Skip to content

Commit af5ee51

Browse files
cschanhniemOpenCode
andauthored
feat: Phase Y Y1 cheap baseline comparison record schema (CBR-) -- machine-verifiable verdict comparing pipeline vs cheap baseline; prevents performance claims without named baseline (#854) (#1013)
VALID_CBR_VERDICTS (4: pipeline_superior/tied/baseline_superior/insufficient_data), VALID_BASELINE_METHODS (5: charge_only_rank/length_only_rank/random_selection/charge_length_combined/hydrophobicity_only_rank), VALID_CBR_METRICS (4: auroc/hit_rate/top_k_precision/ndcg). SUPERIORITY_THRESHOLD=0.05, MIN_SAMPLE_SIZE=5; metric_delta auto-computed. Adds Phase Y baseline-vs-pipeline accountability section to NEXT_100_PR_MAP.md. 62 tests; BASELINE updated 10498->10560. Co-authored-by: OpenCode <opencode@example.com>
1 parent b435dc1 commit af5ee51

4 files changed

Lines changed: 528 additions & 1 deletion

File tree

‎docs/research/NEXT_100_PR_MAP.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,3 +293,15 @@ Track whether the pipeline actually improves across batches by capturing per-bat
293293
| X3 | Add learning progress report schema (LPR-) (complete). — src/openamp_foundry/evidence/learning_progress_report.py: VALID_LPR_VERDICTS (4: learning_confirmed/learning_inconclusive/no_learning_signal/insufficient_data), VALID_FEATURE_PREDICTIVITY (3: predictive/not_predictive/uncertain), VALID_FEATURE_CATEGORIES (8); FeatureLearningEntry helper; verdict auto-computed: learning_confirmed (n_pred>n_non), learning_inconclusive (equal+>0), no_learning_signal (n_pred<n_non), insufficient_data (no batches or no definitive features); dry_lab_only=True; 58 tests in tests/evidence/test_learning_progress_report.py. | Human-readable summary of what the pipeline has learned from all batches to date; references CIT- for trend data; includes which candidate features proved predictive vs not; links to calibration decision logs. | C |
294294
| X4 | Add recalibration confidence certificate schema (RCC-) (complete). — src/openamp_foundry/evidence/recalibration_confidence_certificate.py: VALID_RCC_GRADES (A-D), VALID_RCC_VERDICTS (4: high_confidence/moderate_confidence/low_confidence/insufficient_data), VALID_CONSISTENCY_RATINGS (4); BatchCohortEntry helper; grade A (≥4 batches+consistent), B (≥2 batches+consistent/moderately_consistent), D (insufficient_data); cross_batch_consistency auto-computed; total_cohort_size auto-summed; dry_lab_only=True; cit_id/lpr_id prefix-validated; 76 tests. | Asserts with what confidence the current calibration weights are reliable based on cohort size, quality, and consistency across batches; A/B/C/D grade; prevents overconfident calibration claims. | C |
295295
| X5 | Add Phase X learning gate (XLG-) (complete). — src/openamp_foundry/evidence/phase_x_learning_gate.py: REQUIRED_X_COMPONENTS=(MBL,CIT,LPR,RCC), VALID_XLG_VERDICTS (3: learning_verified/learning_in_progress/learning_not_started); XComponentCheck helper; verdict auto-computed: learning_verified (all 4 present), learning_in_progress (2-3), learning_not_started (0-1); artifact_id prefix-validated per component; dry_lab_only=True; 55 tests. | Top-level gate asserting MBL + CIT + LPR + RCC all present; overall verdict: learning_verified/learning_in_progress/learning_not_started; closes Phase X; no calibration improvement claim is credible without passing this gate. | C |
296+
297+
## Phase Y — Baseline-vs-pipeline accountability
298+
299+
Track and publish structured comparisons between pipeline selections and cheap baselines. Every pilot claim must reference a pre-registered baseline comparison record. Makes it impossible to claim "the pipeline works" without a machine-verifiable comparison against the cheapest plausible alternative. Directly addresses the bottleneck: can the pipeline choose real experiments better than charge/length heuristics?
300+
301+
| ID | Task | Why it matters | Priority |
302+
|----|------|----------------|----------|
303+
| Y1 | Add cheap baseline comparison record schema (CBR-) (complete). — src/openamp_foundry/evidence/cheap_baseline_comparison_record.py: VALID_CBR_VERDICTS (4: pipeline_superior/tied/baseline_superior/insufficient_data), VALID_BASELINE_METHODS (5: charge_only_rank/length_only_rank/random_selection/charge_length_combined/hydrophobicity_only_rank), VALID_CBR_METRICS (4: auroc/hit_rate/top_k_precision/ndcg), SUPERIORITY_THRESHOLD=0.05, MIN_SAMPLE_SIZE=5; metric_delta auto-computed; verdict auto-derived; dry_lab_only=True; 62 tests. | Structured record: pipeline metric vs charge-only/random/length-only baseline; pre-registered threshold; verdict (pipeline_superior/tied/baseline_superior/insufficient_data). Forces every performance claim to cite the baseline it beat. | C |
304+
| Y2 | Add feature importance audit schema (FIA-). | Documents which features drove selections and whether charge/length alone explains the result; anti-cheap-explanation gate; rejects candidate panels where charge-only ordering recovers the same top-k. | C |
305+
| Y3 | Add selection diversity audit schema (SDA-). | Tracks sequence diversity of selected panel vs random draw; detects proximity-driven selection masquerading as discovery; required before any novelty claim. | C |
306+
| Y4 | Add pipeline maturity certificate schema (PMC-). | Aggregates CBR/FIA/SDA results into A/B/C/D maturity grade; anchors pre-registration; prevents retroactive interpretation of results. | C |
307+
| Y5 | Add Phase Y accountability gate (YAG-). | Top-level gate asserting CBR+FIA+SDA+PMC all present; verdict: accountability_verified/accountability_partial/accountability_not_established; closes Phase Y; no external pilot claim is credible without passing this gate. | C |
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""CBR- cheap baseline comparison record schema.
2+
3+
Structured record comparing the pipeline's performance metric against a
4+
cheap baseline (charge-only, length-only, random) on the same candidate set.
5+
Forces every performance claim to name the specific baseline it beat and
6+
provide a machine-readable verdict. No performance claim is credible without
7+
this record.
8+
"""
9+
10+
from __future__ import annotations
11+
12+
from dataclasses import dataclass
13+
14+
VALID_CBR_VERDICTS: frozenset[str] = frozenset({
15+
"pipeline_superior",
16+
"tied",
17+
"baseline_superior",
18+
"insufficient_data",
19+
})
20+
21+
VALID_BASELINE_METHODS: frozenset[str] = frozenset({
22+
"charge_only_rank",
23+
"length_only_rank",
24+
"random_selection",
25+
"charge_length_combined",
26+
"hydrophobicity_only_rank",
27+
})
28+
29+
VALID_CBR_METRICS: frozenset[str] = frozenset({
30+
"auroc",
31+
"hit_rate",
32+
"top_k_precision",
33+
"ndcg",
34+
})
35+
36+
SUPERIORITY_THRESHOLD: float = 0.05
37+
INFERIORITY_THRESHOLD: float = -0.05
38+
MIN_SAMPLE_SIZE: int = 5
39+
40+
41+
@dataclass
42+
class CheapBaselineComparisonRecord:
43+
cbr_id: str
44+
pipeline_version: str
45+
baseline_method: str
46+
metric_name: str
47+
pipeline_metric_value: float
48+
baseline_metric_value: float
49+
metric_delta: float
50+
n_candidates_evaluated: int
51+
pre_registered_threshold: float
52+
cbr_verdict: str
53+
comparison_notes: str
54+
dry_lab_only: bool
55+
limitations: list[str]
56+
created_at: str
57+
58+
59+
def validate_cheap_baseline_comparison_record(
60+
cbr: CheapBaselineComparisonRecord,
61+
) -> None:
62+
if not cbr.cbr_id.startswith("CBR-"):
63+
raise ValueError(f"cbr_id must start with 'CBR-': {cbr.cbr_id!r}")
64+
if not cbr.pipeline_version:
65+
raise ValueError("pipeline_version must be non-empty")
66+
if cbr.baseline_method not in VALID_BASELINE_METHODS:
67+
raise ValueError(
68+
f"baseline_method {cbr.baseline_method!r} not in VALID_BASELINE_METHODS"
69+
)
70+
if cbr.metric_name not in VALID_CBR_METRICS:
71+
raise ValueError(
72+
f"metric_name {cbr.metric_name!r} not in VALID_CBR_METRICS"
73+
)
74+
if not (0.0 <= cbr.pipeline_metric_value <= 1.0):
75+
raise ValueError(
76+
f"pipeline_metric_value must be in [0, 1]: {cbr.pipeline_metric_value}"
77+
)
78+
if not (0.0 <= cbr.baseline_metric_value <= 1.0):
79+
raise ValueError(
80+
f"baseline_metric_value must be in [0, 1]: {cbr.baseline_metric_value}"
81+
)
82+
expected_delta = round(cbr.pipeline_metric_value - cbr.baseline_metric_value, 6)
83+
if abs(cbr.metric_delta - expected_delta) > 1e-5:
84+
raise ValueError(
85+
f"metric_delta mismatch: expected {expected_delta}, got {cbr.metric_delta}"
86+
)
87+
if cbr.n_candidates_evaluated < 0:
88+
raise ValueError("n_candidates_evaluated must be non-negative")
89+
if cbr.cbr_verdict not in VALID_CBR_VERDICTS:
90+
raise ValueError(
91+
f"cbr_verdict {cbr.cbr_verdict!r} not in VALID_CBR_VERDICTS"
92+
)
93+
if not cbr.dry_lab_only:
94+
raise ValueError("dry_lab_only must be True")
95+
if not cbr.limitations:
96+
raise ValueError("limitations must be non-empty")
97+
if not cbr.created_at:
98+
raise ValueError("created_at must be non-empty")
99+
100+
101+
def _compute_verdict(
102+
delta: float,
103+
n_candidates: int,
104+
superiority_threshold: float,
105+
) -> str:
106+
if n_candidates < MIN_SAMPLE_SIZE:
107+
return "insufficient_data"
108+
if delta >= superiority_threshold:
109+
return "pipeline_superior"
110+
if delta <= INFERIORITY_THRESHOLD:
111+
return "baseline_superior"
112+
return "tied"
113+
114+
115+
def build_cheap_baseline_comparison_record(
116+
*,
117+
cbr_id: str,
118+
pipeline_version: str,
119+
baseline_method: str,
120+
metric_name: str,
121+
pipeline_metric_value: float,
122+
baseline_metric_value: float,
123+
n_candidates_evaluated: int,
124+
pre_registered_threshold: float = SUPERIORITY_THRESHOLD,
125+
comparison_notes: str = "",
126+
limitations: list[str],
127+
created_at: str,
128+
) -> CheapBaselineComparisonRecord:
129+
"""Build a CheapBaselineComparisonRecord.
130+
131+
metric_delta = pipeline_metric_value - baseline_metric_value (auto-computed).
132+
cbr_verdict is auto-derived from delta vs pre_registered_threshold and n_candidates.
133+
"""
134+
delta = round(pipeline_metric_value - baseline_metric_value, 6)
135+
verdict = _compute_verdict(delta, n_candidates_evaluated, pre_registered_threshold)
136+
cbr = CheapBaselineComparisonRecord(
137+
cbr_id=cbr_id,
138+
pipeline_version=pipeline_version,
139+
baseline_method=baseline_method,
140+
metric_name=metric_name,
141+
pipeline_metric_value=float(pipeline_metric_value),
142+
baseline_metric_value=float(baseline_metric_value),
143+
metric_delta=delta,
144+
n_candidates_evaluated=n_candidates_evaluated,
145+
pre_registered_threshold=float(pre_registered_threshold),
146+
cbr_verdict=verdict,
147+
comparison_notes=comparison_notes,
148+
dry_lab_only=True,
149+
limitations=limitations,
150+
created_at=created_at,
151+
)
152+
validate_cheap_baseline_comparison_record(cbr)
153+
return cbr
154+
155+
156+
def format_cheap_baseline_comparison_record(
157+
cbr: CheapBaselineComparisonRecord,
158+
) -> str:
159+
lines = [
160+
f"Cheap Baseline Comparison Record — {cbr.cbr_id}",
161+
f"Pipeline: {cbr.pipeline_version}",
162+
f"Baseline: {cbr.baseline_method} | Metric: {cbr.metric_name}",
163+
f"Verdict: {cbr.cbr_verdict}",
164+
f"Pipeline {cbr.metric_name}: {cbr.pipeline_metric_value:.4f}",
165+
f"Baseline {cbr.metric_name}: {cbr.baseline_metric_value:.4f}",
166+
f"Delta: {cbr.metric_delta:+.4f} "
167+
f"(threshold: {cbr.pre_registered_threshold:+.4f})",
168+
f"Candidates evaluated: {cbr.n_candidates_evaluated}",
169+
]
170+
if cbr.comparison_notes:
171+
lines.append(f"Notes: {cbr.comparison_notes}")
172+
lines.append(f"Created: {cbr.created_at}")
173+
lines.append(f"Limitations: {'; '.join(cbr.limitations)}")
174+
lines.append(f"dry_lab_only: {cbr.dry_lab_only}")
175+
return "\n".join(lines)

0 commit comments

Comments
 (0)