Skip to content

Commit 26bdf33

Browse files
cschanhniemOpenCode
andauthored
feat: Phase W W5 Phase W benchmark gate schema (WBG-) -- top-level gate asserting NCH+CMC+SCH+BCR all present; VALID_WBG_VERDICTS (3: hardened/partially_hardened/not_hardened), HARDENED_REQUIRED_PRESENT=4; closes Phase W; 61 tests (#1007)
Co-authored-by: OpenCode <opencode@example.com>
1 parent 278f805 commit 26bdf33

3 files changed

Lines changed: 507 additions & 1 deletion

File tree

‎docs/research/NEXT_100_PR_MAP.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,4 +280,4 @@ Make it machine-verifiable that the pipeline produces novel candidates that beat
280280
| W2 | Add charge-matched challenge schema (CMC-) (complete). — src/openamp_foundry/evidence/charge_matched_challenge.py: VALID_CMC_VERDICTS (4: gap_meaningful/gap_marginal/gap_absent/challenge_not_run), VALID_CHARGE_BASELINE_METHODS (4), MEANINGFUL_GAP_THRESHOLD=0.05, MARGINAL_GAP_LOWER=0.02; auroc_gap auto-computed; verdict auto-derived; dry_lab_only=True enforced; 60 tests in tests/evidence/test_charge_matched_challenge.py. | Formally documents the charge-matched challenge: compares pipeline AUROC vs a charge-only baseline on the same candidate set; verdict controlled vocabulary (gap_meaningful/gap_marginal/gap_absent/not_run); blocks performance claims when the charge-only baseline explains the gap. | C |
281281
| W3 | Add similarity challenge harness schema (SCH-) (complete). — src/openamp_foundry/evidence/similarity_challenge_harness.py: VALID_SCH_VERDICTS (4: selection_adds_value/marginal_improvement/proximity_driven/challenge_not_run), VALID_SIMILARITY_METRICS (4), SELECTION_VALUE_GAP_THRESHOLD=0.10, MARGINAL_IMPROVEMENT_LOWER=0.03; SimilarityGroupStats helper; similarity_gap auto-computed; dry_lab_only=True enforced; 60 tests in tests/evidence/test_similarity_challenge_harness.py. | Documents whether pipeline-selected candidates are systematically more similar to known AMPs than random selection from the sequence space; flags selection bias from similarity clustering; prevents "novel panel" claim when selection is proximity-driven. | C |
282282
| W4 | Add benchmark challenge registry schema (BCR-) (complete). — src/openamp_foundry/evidence/benchmark_challenge_registry.py: REQUIRED_CHALLENGE_TYPES (3: NCH/CMC/SCH), VALID_CHALLENGE_VERDICTS (4: pass/marginal/fail/not_run), VALID_BCR_HARDNESS_GRADES (A-D); ChallengeEntry helper; verdict mapping (novel_batch→pass, mixed_novelty→marginal, gap_meaningful→pass, etc.); grade A=all pass, B=all pass+marginal, C=some pass/marginal, D=all fail/not_run; dry_lab_only=True; 64 tests in tests/evidence/test_benchmark_challenge_registry.py. | Machine-readable registry of which benchmark challenges (NCH/CMC/SCH) have been run and passed for a given pipeline version; aggregates challenge verdicts; overall hardness grade (A: all passed, B: most passed, C: some passed, D: none passed). | C |
283-
| W5 | Add Phase W benchmark gate (WBG-). | Top-level gate asserting NCH + CMC + SCH + BCR all present; overall verdict: hardened/partially_hardened/not_hardened; closes Phase W; no batch-level performance claim is credible without passing this gate. | C |
283+
| W5 | Add Phase W benchmark gate (WBG-) (complete). — src/openamp_foundry/evidence/phase_w_benchmark_gate.py: REQUIRED_W_COMPONENTS (4: NCH/CMC/SCH/BCR), VALID_WBG_VERDICTS (3: hardened/partially_hardened/not_hardened), HARDENED_REQUIRED_PRESENT=4, PARTIALLY_HARDENED_MIN_PRESENT=2; WComponentCheck helper; prefix validation for all artifact IDs; verdict: hardened=all 4 present, partially_hardened=2-3, not_hardened=0-1; dry_lab_only=True; 61 tests. Closes Phase W. | Top-level gate asserting NCH + CMC + SCH + BCR all present; overall verdict: hardened/partially_hardened/not_hardened; closes Phase W; no batch-level performance claim is credible without passing this gate. | C |
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"""WBG- Phase W benchmark gate schema.
2+
3+
Top-level gate asserting all four Phase W benchmark challenge artifacts
4+
(NCH, CMC, SCH, BCR) are present for a batch. Produces an overall
5+
verdict: hardened/partially_hardened/not_hardened. No batch-level
6+
performance claim is credible without a passing WBG-.
7+
"""
8+
9+
from __future__ import annotations
10+
11+
from dataclasses import dataclass
12+
13+
REQUIRED_W_COMPONENTS: tuple[str, ...] = ("NCH", "CMC", "SCH", "BCR")
14+
15+
VALID_WBG_VERDICTS: frozenset[str] = frozenset({
16+
"hardened",
17+
"partially_hardened",
18+
"not_hardened",
19+
})
20+
21+
_COMPONENT_ID_PREFIXES: dict[str, str] = {
22+
"NCH": "NCH-",
23+
"CMC": "CMC-",
24+
"SCH": "SCH-",
25+
"BCR": "BCR-",
26+
}
27+
28+
HARDENED_REQUIRED_PRESENT: int = 4
29+
PARTIALLY_HARDENED_MIN_PRESENT: int = 2
30+
31+
32+
@dataclass
33+
class WComponentCheck:
34+
component_type: str
35+
artifact_id: str
36+
present: bool
37+
38+
39+
@dataclass
40+
class PhaseWBenchmarkGate:
41+
wbg_id: str
42+
batch_id: str
43+
pipeline_version: str
44+
component_checks: list[WComponentCheck]
45+
n_components_required: int
46+
n_components_present: int
47+
missing_component_types: list[str]
48+
gate_verdict: str
49+
dry_lab_only: bool
50+
limitations: list[str]
51+
created_at: str
52+
53+
54+
def validate_phase_w_benchmark_gate(gate: PhaseWBenchmarkGate) -> None:
55+
if not gate.wbg_id.startswith("WBG-"):
56+
raise ValueError(f"wbg_id must start with 'WBG-': {gate.wbg_id!r}")
57+
if not gate.batch_id:
58+
raise ValueError("batch_id must be non-empty")
59+
if not gate.pipeline_version:
60+
raise ValueError("pipeline_version must be non-empty")
61+
seen: set[str] = set()
62+
for check in gate.component_checks:
63+
if check.component_type not in REQUIRED_W_COMPONENTS:
64+
raise ValueError(
65+
f"component_type {check.component_type!r} not in REQUIRED_W_COMPONENTS"
66+
)
67+
if check.component_type in seen:
68+
raise ValueError(f"duplicate component_type: {check.component_type!r}")
69+
seen.add(check.component_type)
70+
expected_prefix = _COMPONENT_ID_PREFIXES[check.component_type]
71+
if check.present and not check.artifact_id.startswith(expected_prefix):
72+
raise ValueError(
73+
f"artifact_id for {check.component_type} must start with "
74+
f"'{expected_prefix}': {check.artifact_id!r}"
75+
)
76+
if gate.n_components_required != len(REQUIRED_W_COMPONENTS):
77+
raise ValueError(
78+
f"n_components_required must be {len(REQUIRED_W_COMPONENTS)}"
79+
)
80+
present_count = sum(1 for c in gate.component_checks if c.present)
81+
if gate.n_components_present != present_count:
82+
raise ValueError("n_components_present mismatch")
83+
expected_missing = sorted(
84+
c.component_type for c in gate.component_checks if not c.present
85+
)
86+
if gate.missing_component_types != expected_missing:
87+
raise ValueError("missing_component_types mismatch")
88+
if gate.gate_verdict not in VALID_WBG_VERDICTS:
89+
raise ValueError(
90+
f"gate_verdict {gate.gate_verdict!r} not in VALID_WBG_VERDICTS"
91+
)
92+
if not gate.dry_lab_only:
93+
raise ValueError("dry_lab_only must be True")
94+
if not gate.limitations:
95+
raise ValueError("limitations must be non-empty")
96+
if not gate.created_at:
97+
raise ValueError("created_at must be non-empty")
98+
99+
100+
def _compute_verdict(n_present: int) -> str:
101+
if n_present == HARDENED_REQUIRED_PRESENT:
102+
return "hardened"
103+
if n_present >= PARTIALLY_HARDENED_MIN_PRESENT:
104+
return "partially_hardened"
105+
return "not_hardened"
106+
107+
108+
def build_phase_w_benchmark_gate(
109+
*,
110+
wbg_id: str,
111+
batch_id: str,
112+
pipeline_version: str,
113+
nch_artifact_id: str = "",
114+
cmc_artifact_id: str = "",
115+
sch_artifact_id: str = "",
116+
bcr_artifact_id: str = "",
117+
limitations: list[str],
118+
created_at: str,
119+
) -> PhaseWBenchmarkGate:
120+
artifact_map = {
121+
"NCH": nch_artifact_id,
122+
"CMC": cmc_artifact_id,
123+
"SCH": sch_artifact_id,
124+
"BCR": bcr_artifact_id,
125+
}
126+
checks = [
127+
WComponentCheck(
128+
component_type=ctype,
129+
artifact_id=artifact_map[ctype],
130+
present=bool(artifact_map[ctype]),
131+
)
132+
for ctype in REQUIRED_W_COMPONENTS
133+
]
134+
n_present = sum(1 for c in checks if c.present)
135+
missing = sorted(c.component_type for c in checks if not c.present)
136+
verdict = _compute_verdict(n_present)
137+
gate = PhaseWBenchmarkGate(
138+
wbg_id=wbg_id,
139+
batch_id=batch_id,
140+
pipeline_version=pipeline_version,
141+
component_checks=checks,
142+
n_components_required=len(REQUIRED_W_COMPONENTS),
143+
n_components_present=n_present,
144+
missing_component_types=missing,
145+
gate_verdict=verdict,
146+
dry_lab_only=True,
147+
limitations=limitations,
148+
created_at=created_at,
149+
)
150+
validate_phase_w_benchmark_gate(gate)
151+
return gate
152+
153+
154+
def format_phase_w_benchmark_gate(gate: PhaseWBenchmarkGate) -> str:
155+
lines = [
156+
f"Phase W Benchmark Gate — {gate.wbg_id}",
157+
f"Batch: {gate.batch_id} | Pipeline: {gate.pipeline_version}",
158+
f"Verdict: {gate.gate_verdict} | Present: {gate.n_components_present}/{gate.n_components_required}",
159+
"Components:",
160+
]
161+
for check in gate.component_checks:
162+
status = "PRESENT" if check.present else "MISSING"
163+
aid = check.artifact_id if check.artifact_id else "(none)"
164+
lines.append(f" {check.component_type}: {status} {aid}")
165+
if gate.missing_component_types:
166+
lines.append(f"Missing: {', '.join(gate.missing_component_types)}")
167+
lines.append(f"Created: {gate.created_at}")
168+
lines.append(f"Limitations: {'; '.join(gate.limitations)}")
169+
lines.append(f"dry_lab_only: {gate.dry_lab_only}")
170+
return "\n".join(lines)

0 commit comments

Comments
 (0)