|
| 1 | +#!/usr/bin/env python3 |
| 2 | +from __future__ import annotations |
| 3 | + |
| 4 | +from pathlib import Path |
| 5 | + |
| 6 | + |
| 7 | +def replace_once(path: Path, old: str, new: str, label: str) -> None: |
| 8 | + text = path.read_text() |
| 9 | + count = text.count(old) |
| 10 | + if count != 1: |
| 11 | + raise RuntimeError(f"{label}: expected one target, found {count}") |
| 12 | + path.write_text(text.replace(old, new, 1)) |
| 13 | + |
| 14 | + |
| 15 | +def harden_parser() -> None: |
| 16 | + path = Path("dev/benchmarks/frontend_data/parsers/panel_stage_c_identifiability.py") |
| 17 | + replace_once( |
| 18 | + path, |
| 19 | + "historical v1/v2 sources without overwriting or colliding with them.", |
| 20 | + "historical v1/v2/v3 sources without overwriting or colliding with them.", |
| 21 | + "parser history docstring", |
| 22 | + ) |
| 23 | + replace_once( |
| 24 | + path, |
| 25 | + ''' repeats = int(row.get("repeats", 0)) |
| 26 | + samples = row.get("samples_seconds") |
| 27 | + if repeats <= 0 or not isinstance(samples, list) or len(samples) != repeats: |
| 28 | + raise ValueError("PR126 identifiability Stage-C timing samples/repeats contract failed")''', |
| 29 | + ''' repeats = int(row.get("repeats", 0)) |
| 30 | + samples = row.get("samples_seconds") |
| 31 | + if repeats != 3 or not isinstance(samples, list) or len(samples) != 3: |
| 32 | + raise ValueError( |
| 33 | + "PR126 identifiability Stage-C timing requires exactly three raw samples" |
| 34 | + )''', |
| 35 | + "exact three-sample contract", |
| 36 | + ) |
| 37 | + replace_once( |
| 38 | + path, |
| 39 | + ''' expected_median = float(statistics.median(numeric_samples)) |
| 40 | + if not math.isclose(median, expected_median, rel_tol=1e-12, abs_tol=1e-15): |
| 41 | + raise ValueError("PR126 identifiability Stage-C reported median does not match raw samples")''', |
| 42 | + ''' expected_median = float(statistics.median(numeric_samples)) |
| 43 | + if median != expected_median: |
| 44 | + raise ValueError( |
| 45 | + "PR126 identifiability Stage-C reported median must exactly match raw samples" |
| 46 | + )''', |
| 47 | + "exact median contract", |
| 48 | + ) |
| 49 | + replace_once( |
| 50 | + path, |
| 51 | + ''' {"metric": "synchronized_timing", "status": "pass"}, |
| 52 | + {"metric": "raw_samples_finite_positive", "status": "pass"}, |
| 53 | + {"metric": "median_matches_raw_samples", "status": "pass"},''', |
| 54 | + ''' {"metric": "synchronized_timing", "status": "pass"}, |
| 55 | + {"metric": "exactly_three_raw_samples", "status": "pass"}, |
| 56 | + {"metric": "raw_samples_finite_positive", "status": "pass"}, |
| 57 | + {"metric": "median_exactly_matches_raw_samples", "status": "pass"},''', |
| 58 | + "performance validation checks", |
| 59 | + ) |
| 60 | + |
| 61 | + |
| 62 | +def harden_tests() -> None: |
| 63 | + path = Path("dev/tests/test_panel_stage_c_identifiability_frontend_source.py") |
| 64 | + text = path.read_text() |
| 65 | + if "import math\n" not in text: |
| 66 | + text = text.replace("import json\n", "import json\nimport math\n", 1) |
| 67 | + old = '''def test_v4_performance_parser_rejects_matrix_or_median_drift(tmp_path): |
| 68 | + payload = json.loads(PERFORMANCE.read_text()) |
| 69 | + broken = copy.deepcopy(payload) |
| 70 | + broken["rows"] = broken["rows"][:-1] |
| 71 | + with pytest.raises(ValueError, match="60 rows"): |
| 72 | + parse_panel_stage_c_identifiability_performance( |
| 73 | + _write(tmp_path, "bad-matrix.json", broken), ENV |
| 74 | + ) |
| 75 | +
|
| 76 | + broken = copy.deepcopy(payload) |
| 77 | + broken["rows"][0]["median_seconds"] *= 2.0 |
| 78 | + with pytest.raises(ValueError, match="median"): |
| 79 | + parse_panel_stage_c_identifiability_performance( |
| 80 | + _write(tmp_path, "bad-median.json", broken), ENV |
| 81 | + ) |
| 82 | +''' |
| 83 | + new = '''def test_v4_performance_parser_rejects_matrix_repeat_or_median_drift(tmp_path): |
| 84 | + payload = json.loads(PERFORMANCE.read_text()) |
| 85 | + broken = copy.deepcopy(payload) |
| 86 | + broken["rows"] = broken["rows"][:-1] |
| 87 | + with pytest.raises(ValueError, match="60 rows"): |
| 88 | + parse_panel_stage_c_identifiability_performance( |
| 89 | + _write(tmp_path, "bad-matrix.json", broken), ENV |
| 90 | + ) |
| 91 | +
|
| 92 | + broken = copy.deepcopy(payload) |
| 93 | + broken["rows"][0]["repeats"] = 2 |
| 94 | + broken["rows"][0]["samples_seconds"] = broken["rows"][0]["samples_seconds"][:2] |
| 95 | + broken["rows"][0]["median_seconds"] = sum(broken["rows"][0]["samples_seconds"]) / 2.0 |
| 96 | + with pytest.raises(ValueError, match="exactly three raw samples"): |
| 97 | + parse_panel_stage_c_identifiability_performance( |
| 98 | + _write(tmp_path, "bad-repeats.json", broken), ENV |
| 99 | + ) |
| 100 | +
|
| 101 | + broken = copy.deepcopy(payload) |
| 102 | + current = float(broken["rows"][0]["median_seconds"]) |
| 103 | + broken["rows"][0]["median_seconds"] = math.nextafter(current, math.inf) |
| 104 | + with pytest.raises(ValueError, match="exactly match"): |
| 105 | + parse_panel_stage_c_identifiability_performance( |
| 106 | + _write(tmp_path, "bad-median.json", broken), ENV |
| 107 | + ) |
| 108 | +''' |
| 109 | + if text.count(old) != 1: |
| 110 | + raise RuntimeError(f"v4 performance test anchor drifted: {text.count(old)}") |
| 111 | + path.write_text(text.replace(old, new, 1)) |
| 112 | + |
| 113 | + |
| 114 | +def update_review_record() -> None: |
| 115 | + path = Path("dev/reviews/pr126_round4_autofix_review_2026-08-12.md") |
| 116 | + text = path.read_text() |
| 117 | + text = text.replace( |
| 118 | + "`PHYSICAL_GPU_ACCEPTED / CANONICAL_PROMOTION_PENDING / NOT MERGE-READY`", |
| 119 | + "`PHYSICAL_GPU_ACCEPTED / CANONICAL_PROMOTED / HOSTED_FINAL_PENDING / NOT MERGE-READY`", |
| 120 | + 1, |
| 121 | + ) |
| 122 | + if "[MEDIUM][PARSER][fixed]" not in text: |
| 123 | + text += '''\n\n## Post-promotion independent parser review\n\n[MEDIUM][PARSER][fixed] The first v4 performance parser accepted any positive `repeats` count and used a tolerance-based median comparison, while the immutable source contract requires exactly three raw timing samples and an exactly persisted median. The parser now requires `repeats == 3`, exactly three samples, and exact equality with `statistics.median(samples)`. Corruption tests cover a two-sample row and a one-ULP median drift.\n\n[MEDIUM][ARTIFACT][fixed] The checkpoint header still said `CANONICAL_PROMOTION_PENDING` after canonical promotion commit `72bc21d3d0a1afd23467ecb1ff176d42df709cb4` had passed the dedicated v4 promotion gate. The record now reflects `CANONICAL_PROMOTED / HOSTED_FINAL_PENDING`.\n\nThe post-promotion parser hardening changes only parser/test/review artifacts. It does not touch `statgpu/panel/**`, the correctness runner, the performance runner, or either immutable raw JSON file, so the exact-clean `a99726e1...` P100 evidence remains applicable.\n''' |
| 124 | + path.write_text(text) |
| 125 | + |
| 126 | + |
| 127 | +def main() -> None: |
| 128 | + harden_parser() |
| 129 | + harden_tests() |
| 130 | + update_review_record() |
| 131 | + print("PR126 v4 final parser hardening applied") |
| 132 | + |
| 133 | + |
| 134 | +if __name__ == "__main__": |
| 135 | + main() |
0 commit comments