Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help demo test lint ci clean bench-leakage bench-multi-negatives bench-baseline bench-hidden-active bench-cluster-split bench-expert-ablation bench-expert-ablation-500 bench-selectivity bench-feature-decomp bench-gate bench-easy-baseline bench-charge-matched bench-order-dependent bench-precision-at-k bench-per-family bench-simulation-ablation bench-simulation-ablation-within-amp simulation-gate bench-strategy-compare regenerate-all generate phase3 pilot validate-scoring validate-scoring-phase3 validate-scoring-strict external-pilot pilot-confident presynth-qc gold-standard diversity synthesis-order novelty-broad external-consensus questionnaire gate-check ip-report benchmark-card wave0-5-gate-check wave0-5-novelty-audit wave0-5-novelty-audit-v2 wave0-5-panel wave0-5-evidence wave0-5-fill-external wave0-5b-generate wave0-5b-filter recalibration-engine recalibration-engine-dry-run validate-policy-version generate-synthetic-lab-results bump-policy-version generate-review-packet failed-candidate-report safe-publication-filter classify-negative-informativeness validate-rejection-events negative-result-dashboard calibration-audit calibration-audit-example calibration-overfit-check result-quality-filter synthetic-result-policy-check calibration-decision-checklist calibration-rollback-plan simulation-registry validate-simulation-result-schema simulation-baseline-check adapter-gate-check simulation-provenance simulation-ensemble-check simulation-ci-report simulation-deprecation-check simulation-scope-check simulation-evidence-packet artifact-version candidate-manifest artifact-changelog integration-check adapter-author-check license-check artifact-compat-check contribution-check adoption-scorecard release-gate-check decision-log release-request-check coi-check rotation-plan-check security-report-check citation-check roadmap-sync-check advisory-review-check annual-review-check selection-rationale-check batch-priority-check pilot-package-check calibration-intake-check uncertainty-report-check preprint-bundle-check reproducibility-manifest-check candidate-summary-card-check multi-candidate-comparison-check pipeline-decision-audit-check claim-to-evidence-check score-decomposition-check reviewer-briefing-check audit-chain-check pre-registration-check hypothesis-outcome-check baseline-comparison-check dataset-release-check
.PHONY: help demo test lint ci clean bench-leakage bench-multi-negatives bench-baseline bench-hidden-active bench-cluster-split bench-expert-ablation bench-expert-ablation-500 bench-selectivity bench-feature-decomp bench-gate bench-easy-baseline bench-charge-matched bench-order-dependent bench-precision-at-k bench-per-family bench-simulation-ablation bench-simulation-ablation-within-amp simulation-gate bench-strategy-compare regenerate-all generate phase3 pilot validate-scoring validate-scoring-phase3 validate-scoring-strict external-pilot pilot-confident presynth-qc gold-standard diversity synthesis-order novelty-broad external-consensus questionnaire gate-check ip-report benchmark-card wave0-5-gate-check wave0-5-novelty-audit wave0-5-novelty-audit-v2 wave0-5-panel wave0-5-evidence wave0-5-fill-external wave0-5b-generate wave0-5b-filter recalibration-engine recalibration-engine-dry-run validate-policy-version generate-synthetic-lab-results bump-policy-version generate-review-packet failed-candidate-report safe-publication-filter classify-negative-informativeness validate-rejection-events negative-result-dashboard calibration-audit calibration-audit-example calibration-overfit-check result-quality-filter synthetic-result-policy-check calibration-decision-checklist calibration-rollback-plan simulation-registry validate-simulation-result-schema simulation-baseline-check adapter-gate-check simulation-provenance simulation-ensemble-check simulation-ci-report simulation-deprecation-check simulation-scope-check simulation-evidence-packet artifact-version candidate-manifest artifact-changelog integration-check adapter-author-check license-check artifact-compat-check contribution-check adoption-scorecard release-gate-check decision-log release-request-check coi-check rotation-plan-check security-report-check citation-check roadmap-sync-check advisory-review-check annual-review-check selection-rationale-check batch-priority-check pilot-package-check calibration-intake-check uncertainty-report-check preprint-bundle-check reproducibility-manifest-check candidate-summary-card-check multi-candidate-comparison-check pipeline-decision-audit-check claim-to-evidence-check score-decomposition-check reviewer-briefing-check audit-chain-check pre-registration-check hypothesis-outcome-check baseline-comparison-check negative-result-check dataset-release-check

PYTHON := $(shell [ -f .venv/bin/python ] && echo .venv/bin/python || echo python3)
PYTEST := $(shell [ -f .venv/bin/pytest ] && echo .venv/bin/pytest || echo pytest)
Expand Down Expand Up @@ -957,6 +957,9 @@ hypothesis-outcome-check:
baseline-comparison-check:
openamp-foundry baseline-comparison-check --entry-json '{"manifest_id":"BCM-001","batch_id":"BATCH-001","pipeline_version":"0.9.6","comparison_date":"2026-07-10","metric_name":"hit_rate","pipeline_score":0.7,"baseline_scores":{"random_selection":0.1,"charge_matched":0.15},"pipeline_beats_all_baselines":true,"effect_size":0.55,"p_value":0.02,"comparison_direction":"higher_is_better","notes":"Pipeline beats random and charge-matched baselines.","reviewer":"test@example.com","dry_lab_only":true}' --format text

negative-result-check:
openamp-foundry negative-result-check --entry-json '{"record_id":"NRR-001","batch_id":"BATCH-001","pipeline_version":"0.9.7","record_date":"2026-07-10","failure_category":"below_activity_threshold","failure_description":"Candidates did not meet MIC threshold in broth microdilution assay.","candidate_ids":["AMP-042"],"assay_type":"mic_assay","expected_outcome":"MIC <= 4 ug/mL","observed_outcome":"MIC = 128 ug/mL","hypothesis_impact":"Activity hypothesis refuted for these candidates. Pipeline review needed.","will_be_reported":true,"recorded_by":"test@example.com","dry_lab_only":true}' --format text

dataset-release-check:
.venv/bin/openamp-foundry dataset-release-check \
--entry-json '{"release_id":"DSR-001","dataset_name":"OpenAMP Wave 0.5 Candidates","dataset_version":"1.0.0","release_date":"2026-07-09","license_identifier":"CC-BY-4.0","data_sources":["UniProt AMP database","APD3","in-house pipeline"],"contains_sequences":true,"contains_activity_data":false,"dual_use_assessed":true,"usage_policy_url":"https://openamp.example.org/data-policy","contact_email":"data@openamp.example.org","release_approved":true,"dry_lab_only":true}' \
Expand Down
3 changes: 2 additions & 1 deletion docs/evidence/METRICS_CURRENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ Machine-readable snapshot: `outputs/metrics_snapshot.json` regenerated with `mak
> **Purpose:** One authoritative table of current pipeline metrics. If any doc disagrees
> with this file, this file wins. Updated whenever benchmark/benchmark config changes.
>
> **Last updated:** 2026-07-10 (Phase N N3 — baseline comparison manifest — v0.9.6)
> **Last updated:** 2026-07-10 (Phase N N4 — negative result record — v0.9.7)
> **New in v0.9.7:** Negative result record schema (N4 — Loop 136) — docs/evidence/NEGATIVE_RESULT_GUIDE.md with purpose, schema fields table (14 fields: record_id, batch_id, pipeline_version, record_date, failure_category, failure_description, candidate_ids, assay_type, expected_outcome, observed_outcome, hypothesis_impact, will_be_reported, recorded_by, dry_lab_only), 6 valid failure categories (assay_quality_failure, below_activity_threshold, excessive_toxicity, model_overprediction, pipeline_error, stability_failure), 5 valid assay types (cytotoxicity_assay, hemolysis_assay, membrane_disruption_assay, mic_assay, stability_assay), 9 validation rules, 3 warning conditions (not reported, large failure set, model overprediction without recalibration), honest-use boundary. NegativeResultEntry dataclass (14 fields), NegativeResultResult dataclass (7 fields), validate_negative_result() (9+ error checks: NRR- prefix, valid failure_category, non-empty failure_description<=500 chars, >=1 candidate_ids, valid assay_type, non-empty expected_outcome/observed_outcome, non-empty hypothesis_impact<=300 chars, non-empty recorded_by; 3 warnings: not reported contributes to publication bias, >10 candidates suggests systematic issue, model_overprediction without calibration mention triggers calibration review), validate_negative_result_dict() (13 required fields guard). CLI (openamp-foundry negative-result-check) with --entry-json, --format text|json. make negative-result-check target. 68 tests. Phase N N4: failed experiments are now documented, not discarded.
> **New in v0.9.6:** Baseline comparison manifest schema (N3 — Loop 135) — docs/evidence/BASELINE_COMPARISON_GUIDE.md with purpose, schema fields table (14 fields: manifest_id, batch_id, pipeline_version, comparison_date, metric_name, pipeline_score, baseline_scores, pipeline_beats_all_baselines, effect_size, p_value, comparison_direction, notes, reviewer, dry_lab_only), 6 valid metric names (fold_change_mic, hemolysis_fraction, hit_rate, mic_value, novelty_score, selectivity_index), 2 valid comparison directions (higher_is_better, lower_is_better), 11 validation rules, 4 warning conditions (pipeline loses, inconsistent verdict, no p-value, large unchecked effect), honest-use boundary. BaselineComparisonEntry dataclass (14 fields), BaselineComparisonResult dataclass (7 fields), validate_baseline_comparison() (11+ error checks: BCM- prefix, valid metric_name, finite pipeline_score, >=1 baseline, finite baseline_scores, finite effect_size, p_value in [0.0,1.0] or -1.0, valid comparison_direction, notes<=300, non-empty reviewer, dry_lab_only must be True; 4 warning conditions: underperforms, inconsistent verdict, no p-value, large+unchecked), validate_baseline_comparison_dict() (13 required fields guard). CLI (openamp-foundry baseline-comparison-check) with --entry-json, --format text|json. make baseline-comparison-check target. 68 tests. Phase N N3: every performance claim against a baseline is now machine-verifiable.
> **New in v0.9.5:** Pre-registration form schema (N1 — Loop 133) — docs/evidence/PRE_REGISTRATION_GUIDE.md with purpose, schema fields table (13 fields: registration_id, batch_id, pipeline_version, registration_date, primary_hypothesis, primary_outcome_metric, success_threshold, baseline_comparators, candidate_ids, assay_type, statistical_test, registered_by, dry_lab_only), 6 valid primary outcome metrics, 5 valid assay types, 10 validation rules, 4 warning conditions, honest-use boundary. PreRegistrationEntry dataclass (13 fields), PreRegistrationResult dataclass (6 fields), validate_pre_registration() (10+ error checks: PRE- prefix, non-empty hypothesis<=500 chars, valid outcome metric, finite success_threshold, >=1 baseline_comparators, >=1 candidate_ids, valid assay_type, non-empty statistical_test<=200 chars, non-empty registered_by, dry_lab_only must be True; 4 warning conditions: no random baseline, large candidate set >20, short hypothesis <50 chars, placeholder statistical test TBD/N/A/NA/none), validate_pre_registration_dict() (12 required fields guard). CLI (openamp-foundry pre-registration-check) with --entry-json, --format text|json. make pre-registration-check target. 62 tests. Phase N (Pre-registration & Baseline Honesty) started with N1.
> > **New in v0.9.3:** Audit chain completeness checker (M5 — Loop 132) — docs/evidence/AUDIT_CHAIN_GUIDE.md with purpose, schema fields table (16 fields: chain_id, batch_id, pipeline_version, audit_date, 9 has_* bools, missing_links, auditor, dry_lab_only), 9 required chain links, validation rules (5), warning conditions (2: single auditor, future date), honest-use boundary. src/openamp_foundry/evidence/audit_chain_completeness.py with AuditChainEntry dataclass (16 fields: chain_id, batch_id, pipeline_version, audit_date, 9 has_* bools, missing_links list[str], auditor, dry_lab_only=True), AuditChainResult dataclass (7 fields: chain_id, batch_id, missing_link_count, passed, errors, warnings, dry_lab_only=True), CHAIN_LINK_FIELDS (9 entries), CHAIN_LINK_COUNT (9), AUDITOR_EMAIL_HINT ("@"), IMPLAUSIBLE_YEAR_THRESHOLD (2030), validate_audit_chain() (5+ error checks: ACH- prefix, non-empty auditor, dry_lab_only must be True, each false chain link errors, missing_links consistency; 2 warnings: no email, future date), validate_audit_chain_dict() (15 required fields guard). CLI (openamp-foundry audit-chain-check) with --entry-json, --format text|json. make audit-chain-check target. 39 tests. Phase M M5: the evidence chain is now machine-checkable end to end. Phase M (Audit Trail Infrastructure) is fully complete with M1-M5.
Expand Down
73 changes: 73 additions & 0 deletions docs/evidence/NEGATIVE_RESULT_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Negative Result Record Guide

## Purpose

A negative result record documents experiments or predictions that failed to
meet expectations. Negative results are not failures of the pipeline — they
are information. Recording them is mandatory for:

1. Honest calibration (you cannot calibrate on cherry-picked successes)
2. Preventing repeated experiments (institutional memory)
3. Publication integrity (selective reporting is a form of bias)
4. Future hypothesis generation (knowing what does NOT work narrows the space)

## Schema Fields

| Field | Type | Description |
|---|---|---|
| record_id | str | Unique identifier (prefix "NRR-") |
| batch_id | str | Batch or experiment set this record covers |
| pipeline_version | str | Pipeline version at time of experiment |
| record_date | str | ISO 8601 date result was recorded |
| failure_category | str | Category of failure (see valid categories) |
| failure_description | str | Plain-language description of what failed (max 500 chars) |
| candidate_ids | list[str] | IDs of candidates that failed (at least 1) |
| assay_type | str | Assay in which failure was observed (see valid types) |
| expected_outcome | str | What was predicted or expected |
| observed_outcome | str | What was actually observed |
| hypothesis_impact | str | How this result affects the working hypothesis (max 300 chars) |
| will_be_reported | bool | Whether this result will be included in any publication or report |
| recorded_by | str | Person or system recording this |
| dry_lab_only | bool | False if real lab data; True if computational only |

## Valid Failure Categories

- `assay_quality_failure` — assay controls failed; results not interpretable
- `below_activity_threshold` — predicted activity not confirmed
- `excessive_toxicity` — candidate was too toxic (hemolysis/cytotoxicity)
- `model_overprediction` — model was significantly more optimistic than results
- `pipeline_error` — computational error or data quality issue
- `stability_failure` — candidate degraded under assay conditions

## Valid Assay Types

- `cytotoxicity_assay`
- `hemolysis_assay`
- `membrane_disruption_assay`
- `mic_assay`
- `stability_assay`

## Validation Rules

1. record_id must start with "NRR-"
2. failure_category must be one of the valid categories
3. failure_description must not be empty and must not exceed 500 characters
4. candidate_ids must contain at least 1 candidate
5. assay_type must be one of the valid assay types
6. expected_outcome must not be empty
7. observed_outcome must not be empty
8. hypothesis_impact must not be empty and must not exceed 300 characters
9. recorded_by must not be empty

## Warning Conditions

- Not reported: will_be_reported=False → warn that suppressing negative results contributes to publication bias
- Large failure set: len(candidate_ids) > 10 → warn about systematic failure; pipeline may need recalibration
- Model overprediction without recalibration note: failure_category="model_overprediction" and "calibrat" not in hypothesis_impact.lower() → warn that recalibration should be considered

## Honest Use Boundary

A negative result record must be filed even when the result is inconvenient.
The commitment to record negative results is not optional. A pipeline that only
documents successes is not a scientific tool — it is a selection bias engine.
Do not set will_be_reported=False without documenting why in hypothesis_impact.
2 changes: 1 addition & 1 deletion docs/research/NEXT_100_PR_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ Make experiment predictions falsifiable before results are observed. Guard again
| N1 | Add pre-registration form schema (complete — Loop 133). | Records what will be tested and how before experiments run. | B |
| N2 | Add hypothesis outcome record schema (complete — Loop 134). | Documents whether pre-registered hypotheses were confirmed or refuted. | B/D |
| N3 | Add baseline comparison manifest schema (complete — Loop 135). | Machine-verifiable proof the model beats cheap baselines. | B |
| N4 | Add negative result record schema. | Ensures failed experiments are documented, not discarded. | B |
| N4 | Add negative result record schema (complete — Loop 136). | Ensures failed experiments are documented, not discarded. | B | | Ensures failed experiments are documented, not discarded. | B |
| N5 | Add experiment priority justification schema. | Documents why this batch was selected over alternatives. | B |

## Prioritization rule
Expand Down
7 changes: 7 additions & 0 deletions docs/research/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Roadmap

### v0.9.7 — Phase N N4: Negative Result Record
- Added `NegativeResultEntry` schema ensuring failed experiments are documented, not discarded
- 6 failure categories, 5 assay types; warns on suppressed reporting, systematic failures, uncalibrated overprediction
- dry_lab_only=False supported for real lab data
- CLI: `openamp-foundry negative-result-check`
- 68 tests; all passing

### v0.9.6 — Phase N N3: Baseline Comparison Manifest
- Added `BaselineComparisonEntry` schema for machine-verifiable proof the pipeline beats cheap baselines
- 6 metric names, 2 comparison directions, p_value sentinel for uncomputed significance
Expand Down
20 changes: 20 additions & 0 deletions src/openamp_foundry/cli/commands/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -3368,3 +3368,23 @@ def _run_baseline_comparison_check(args: argparse.Namespace) -> None:
print(f" ERROR: {e}")
for w in result.warnings:
print(f" WARN: {w}")


def _run_negative_result_check(args: argparse.Namespace) -> None:
import json
from openamp_foundry.evidence.negative_result_record import validate_negative_result_dict

entry_dict = json.loads(args.entry_json)
result = validate_negative_result_dict(entry_dict)

if args.format == "json":
import dataclasses
print(json.dumps(dataclasses.asdict(result), indent=2))
else:
status = "PASS" if result.passed else "FAIL"
reported = "will be reported" if result.will_be_reported else "NOT REPORTED"
print(f"[{status}] Negative Result: {result.record_id} ({result.failure_category}, {result.candidate_count} candidates, {reported})")
for e in result.errors:
print(f" ERROR: {e}")
for w in result.warnings:
print(f" WARN: {w}")
Loading
Loading