Skip to content

Commit 78eeea7

Browse files
committed
test(governance): add QUALITY_GATES_SUMMARY anti-drift checks
Prevent collapsed ROUTE-003 / fixture-gate sections and stale ROUTE metrics from regressing without CI failure.
1 parent 9a0a5fb commit 78eeea7

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Structural anti-drift tests for QUALITY_GATES_SUMMARY.md."""
2+
3+
import re
4+
import sys
5+
from pathlib import Path
6+
7+
import pytest
8+
9+
sys.path.insert(0, str(Path(__file__).parent.parent))
10+
11+
from validate_route_fixture import ( # noqa: E402
12+
ROUTE_001_MIN_PHRASES,
13+
ROUTE_002_MIN_HOLDOUT_GROUPS,
14+
ROUTE_002_MIN_PHRASES,
15+
ROUTE_003_MIN_ADVERSARIAL_GROUPS,
16+
ROUTE_003_MIN_PHRASES,
17+
)
18+
19+
SUMMARY_PATH = Path(__file__).parent.parent / "QUALITY_GATES_SUMMARY.md"
20+
21+
22+
@pytest.fixture(scope="module")
23+
def summary_text() -> str:
24+
assert SUMMARY_PATH.is_file(), f"missing {SUMMARY_PATH}"
25+
return SUMMARY_PATH.read_text(encoding="utf-8")
26+
27+
28+
def _section_between(text: str, start_heading: str, end_heading: str) -> str:
29+
start = text.index(start_heading)
30+
end = text.index(end_heading, start + len(start_heading))
31+
return text[start:end]
32+
33+
34+
def test_route_eval_sections_are_not_collapsed(summary_text: str):
35+
"""Round-22 regression: 7.3 and 7.4 must not share one heading line."""
36+
for line in summary_text.splitlines():
37+
if "### 7.3" in line:
38+
assert "### 7.4" not in line, "collapsed ROUTE-003 and fixture-gate headings"
39+
40+
41+
def test_route_003_section_structure(summary_text: str):
42+
section = _section_between(
43+
summary_text,
44+
"### 7.3 ROUTE-003 Adversarial Eval ✅",
45+
"### 7.4 Route Fixture Gate ✅",
46+
)
47+
assert "route-003-adversarial-eval.yaml" in section
48+
assert "**Results:**" in section
49+
assert "**Usage:**" in section
50+
assert f"{ROUTE_003_MIN_ADVERSARIAL_GROUPS} adversarial groups" in section
51+
assert f"{ROUTE_003_MIN_PHRASES} paraphrases" in section
52+
assert "implement_not_plan_trap" in section or "R11" in section
53+
54+
55+
def test_route_fixture_gate_section_structure(summary_text: str):
56+
section = _section_between(
57+
summary_text,
58+
"### 7.4 Route Fixture Gate ✅",
59+
"### 7. Small Benchmark Set ✅",
60+
)
61+
assert "validate_route_fixture.py" in section
62+
assert "**What it does:**" in section
63+
assert "**Usage:**" in section
64+
assert str(ROUTE_002_MIN_HOLDOUT_GROUPS) in section
65+
assert str(ROUTE_002_MIN_PHRASES) in section
66+
assert str(ROUTE_003_MIN_ADVERSARIAL_GROUPS) in section
67+
assert str(ROUTE_003_MIN_PHRASES) in section
68+
69+
70+
def test_key_metrics_table_matches_fixture_minimums(summary_text: str):
71+
metrics = _section_between(summary_text, "## Key Metrics", "### Routing Consistency Tracking")
72+
assert re.search(
73+
rf"ROUTE-002 \({ROUTE_002_MIN_HOLDOUT_GROUPS} groups, {ROUTE_002_MIN_PHRASES} paraphrases\)",
74+
metrics,
75+
)
76+
assert re.search(
77+
rf"ROUTE-003 \({ROUTE_003_MIN_ADVERSARIAL_GROUPS} groups, {ROUTE_003_MIN_PHRASES} paraphrases\)",
78+
metrics,
79+
)
80+
81+
82+
def test_ci_paraphrase_totals_match_route_minimums(summary_text: str):
83+
expected_total = (
84+
f"{ROUTE_001_MIN_PHRASES} + {ROUTE_002_MIN_PHRASES} + {ROUTE_003_MIN_PHRASES}"
85+
)
86+
assert expected_total in summary_text

0 commit comments

Comments
 (0)