Skip to content

Commit 00ff8d2

Browse files
author
OpenCode
committed
feat: Phase N N5 experiment priority justification schema -- auditable batch selection over alternatives (completes Phase N)
1 parent 955e01f commit 00ff8d2

10 files changed

Lines changed: 598 additions & 5 deletions

File tree

‎Makefile‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.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
1+
.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 experiment-priority-check reviewer-briefing-check audit-chain-check pre-registration-check hypothesis-outcome-check baseline-comparison-check negative-result-check dataset-release-check
22

33
PYTHON := $(shell [ -f .venv/bin/python ] && echo .venv/bin/python || echo python3)
44
PYTEST := $(shell [ -f .venv/bin/pytest ] && echo .venv/bin/pytest || echo pytest)
@@ -960,6 +960,9 @@ baseline-comparison-check:
960960
negative-result-check:
961961
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
962962

963+
experiment-priority-check:
964+
openamp-foundry experiment-priority-check --entry-json '{"justification_id":"EPJ-001","batch_id":"BATCH-002","pipeline_version":"0.9.8","decision_date":"2026-07-10","selection_criteria":["Highest predicted hit rate","All candidates passed safety filters"],"rejected_alternatives":["BATCH-001"],"rejection_rationale":"BATCH-001 showed lower predicted hit rate and higher predicted toxicity scores.","resource_constraint":"Synthesis limited to 10 candidates per wave.","safety_reviewed":true,"pre_specified":true,"decided_by":"pipeline@example.com","dry_lab_only":true}' --format text
965+
963966
dataset-release-check:
964967
.venv/bin/openamp-foundry dataset-release-check \
965968
--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}' \
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Experiment Priority Justification Guide
2+
3+
## Purpose
4+
5+
The experiment priority justification records why a specific batch of candidates
6+
was selected for the next experimental wave over alternatives. This prevents
7+
the most common form of selection bias in pipeline-driven research: choosing
8+
experiments based on convenience, intuition, or results-seeking rather than
9+
pre-specified scientific reasoning.
10+
11+
## Schema Fields
12+
13+
| Field | Type | Description |
14+
|---|---|---|
15+
| justification_id | str | Unique identifier (prefix "EPJ-") |
16+
| batch_id | str | Batch selected for the next experiment |
17+
| pipeline_version | str | Pipeline version at decision time |
18+
| decision_date | str | ISO 8601 date of this decision |
19+
| selection_criteria | list[str] | Criteria used to prioritize this batch (at least 2) |
20+
| rejected_alternatives | list[str] | Batch or candidate IDs that were considered but not selected (at least 1) |
21+
| rejection_rationale | str | Why alternatives were not chosen (max 500 chars) |
22+
| resource_constraint | str | Resource/capacity constraint driving prioritization (max 200 chars) |
23+
| safety_reviewed | bool | Whether safety criteria were checked before selection |
24+
| pre_specified | bool | Whether selection criteria were pre-specified before seeing candidates |
25+
| decided_by | str | Person or system making this decision |
26+
| dry_lab_only | bool | Always True (computational prioritization) |
27+
28+
## Validation Rules
29+
30+
1. justification_id must start with "EPJ-"
31+
2. selection_criteria must contain at least 2 criteria
32+
3. rejected_alternatives must contain at least 1 alternative
33+
4. rejection_rationale must not be empty and must not exceed 500 characters
34+
5. resource_constraint must not exceed 200 characters (may be empty)
35+
6. safety_reviewed must be True
36+
7. decided_by must not be empty
37+
8. dry_lab_only must be True
38+
39+
## Warning Conditions
40+
41+
- Post-hoc selection: pre_specified=False → warn that selection criteria were not pre-specified
42+
- Few criteria: len(selection_criteria) == 2 → warn that only minimum criteria used; more criteria strengthens defensibility
43+
- No resource constraint documented: resource_constraint is empty → warn that documenting constraints improves transparency
44+
- Many criteria: len(selection_criteria) > 6 → warn that many criteria may introduce over-fitting to batch characteristics
45+
46+
## Honest Use Boundary
47+
48+
An experiment priority justification is a dry-lab decision record. It documents
49+
the computational reasoning for prioritization. The ultimate decision to run
50+
experiments must involve qualified scientists. Safety_reviewed=True means the
51+
pipeline's safety checks were run — it does not mean a domain expert has
52+
signed off on the biological safety of the candidates.

‎docs/evidence/METRICS_CURRENT.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ Machine-readable snapshot: `outputs/metrics_snapshot.json` regenerated with `mak
55
> **Purpose:** One authoritative table of current pipeline metrics. If any doc disagrees
66
> with this file, this file wins. Updated whenever benchmark/benchmark config changes.
77
>
8-
> **Last updated:** 2026-07-10 (Phase N N4 — negative result record — v0.9.7)
8+
> **Last updated:** 2026-07-10 (Phase N N5 — experiment priority justification — v0.9.8)
9+
> **New in v0.9.8:** Experiment priority justification schema (N5 — Loop 137) — docs/evidence/EXPERIMENT_PRIORITY_GUIDE.md with purpose, schema fields table (12 fields: justification_id, batch_id, pipeline_version, decision_date, selection_criteria, rejected_alternatives, rejection_rationale, resource_constraint, safety_reviewed, pre_specified, decided_by, dry_lab_only), 8 validation rules (EPJ- prefix, >=2 selection criteria, >=1 rejected alternative, non-empty rejection_rationale<=500 chars, resource_constraint<=200 chars, safety_reviewed must be True, non-empty decided_by, dry_lab_only must be True), 4 warning conditions (post-hoc, minimum criteria, no resource constraint, many criteria), honest-use boundary. ExperimentPriorityEntry dataclass (12 fields, dry_lab_only=True), ExperimentPriorityResult dataclass (8 fields: justification_id, batch_id, criteria_count, rejected_alternative_count, safety_reviewed, passed, errors, warnings, dry_lab_only=True), MINIMUM_SELECTION_CRITERIA=2, MAXIMUM_SELECTION_CRITERIA_WARNING=6, MAX_REJECTION_RATIONALE_LENGTH=500, MAX_RESOURCE_CONSTRAINT_LENGTH=200. validate_experiment_priority() (8+ error checks: EPJ- prefix, >=2 criteria, >=1 alternative, non-empty rationale<=500 chars, constraint<=200 chars, safety_reviewed must be True, non-empty decided_by, dry_lab_only must be True; 4 warnings: post-hoc, minimum criteria, no constraint, many criteria). validate_experiment_priority_dict() (11 required fields guard). CLI (openamp-foundry experiment-priority-check) with --entry-json, --format text|json. make experiment-priority-check target. 62 tests. Phase N N5: batch selection decisions are now documented with full audit trail over alternatives. Phase N (Pre-registration & Baseline Honesty) is fully complete with N1-N5.
910
> **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.
1011
> **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.
1112
> **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.

‎docs/research/NEXT_100_PR_MAP.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ Make experiment predictions falsifiable before results are observed. Guard again
235235
| N2 | Add hypothesis outcome record schema (complete — Loop 134). | Documents whether pre-registered hypotheses were confirmed or refuted. | B/D |
236236
| N3 | Add baseline comparison manifest schema (complete — Loop 135). | Machine-verifiable proof the model beats cheap baselines. | B |
237237
| 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 |
238-
| N5 | Add experiment priority justification schema. | Documents why this batch was selected over alternatives. | B |
238+
| N5 | Add experiment priority justification schema (complete — Loop 137). | Documents why this batch was selected over alternatives. Completes Phase N. | B |
239239

240240
## Prioritization rule
241241

‎docs/research/ROADMAP.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Roadmap
22

3+
### v0.9.8 — Phase N N5: Experiment Priority Justification (Completes Phase N)
4+
- Added `ExperimentPriorityEntry` schema documenting why a batch was selected over alternatives
5+
- Safety review enforcement; post-hoc selection warning; resource constraint transparency
6+
- Requires at least 2 criteria and 1 rejected alternative — selection without alternatives is not a decision
7+
- CLI: `openamp-foundry experiment-priority-check`
8+
- 62 tests; all passing
9+
- Phase N (Pre-registration & Baseline Honesty) complete
10+
311
### v0.9.7 — Phase N N4: Negative Result Record
412
- Added `NegativeResultEntry` schema ensuring failed experiments are documented, not discarded
513
- 6 failure categories, 5 assay types; warns on suppressed reporting, systematic failures, uncalibrated overprediction

‎src/openamp_foundry/cli/commands/reports.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3388,3 +3388,22 @@ def _run_negative_result_check(args: argparse.Namespace) -> None:
33883388
print(f" ERROR: {e}")
33893389
for w in result.warnings:
33903390
print(f" WARN: {w}")
3391+
3392+
3393+
def _run_experiment_priority_check(args: argparse.Namespace) -> None:
3394+
import json
3395+
from openamp_foundry.evidence.experiment_priority_justification import validate_experiment_priority_dict
3396+
3397+
entry_dict = json.loads(args.entry_json)
3398+
result = validate_experiment_priority_dict(entry_dict)
3399+
3400+
if args.format == "json":
3401+
import dataclasses
3402+
print(json.dumps(dataclasses.asdict(result), indent=2))
3403+
else:
3404+
status = "PASS" if result.passed else "FAIL"
3405+
print(f"[{status}] Experiment Priority: {result.justification_id} ({result.criteria_count} criteria, {result.rejected_alternative_count} alternatives rejected)")
3406+
for e in result.errors:
3407+
print(f" ERROR: {e}")
3408+
for w in result.warnings:
3409+
print(f" WARN: {w}")

0 commit comments

Comments
 (0)