Add a test-only invariance gate that locks the pre-existing four-test red
baseline so IMP-35 cannot silently grow the red surface while in-flight.
u11 does NOT fix the four reds — Stage 2 follow_up_candidates tracks the
actual repair as a separate issue. u1~u10 production work remains in the
worktree and is explicitly out of this commit per Stage 3 R7 carve-out.
Frozen registry (IMP35_BASELINE_RED_NODE_IDS, set semantics):
1. tests/test_imp47b_step12_ai_wiring.py
::test_mixed_units_classified_by_route_and_provisional_flag
2. tests/test_imp47b_step12_ai_wiring.py
::test_reject_provisional_unit_reaches_router_short_circuit
3. tests/test_imp47b_step12_ai_wiring.py
::test_step12_ai_repair_artifact_writes_json_serialisable_records
4. tests/test_phase_z2_ai_fallback_config.py
::test_ai_fallback_master_flag_default_off
Gate semantics (subprocess pytest, set comparison):
- All 4 node ids resolve to collectible pytest items
(rename / delete is caught up front).
- Broader baseline-area sweep across the two registry files yields
EXACTLY 4 FAILED and 0 ERROR, with FAILED set ≡ registry.
- A new red in the baseline area flips count above 4 OR introduces a
FAILED id outside the registry; either branch fails the gate.
- Cross-lock test ensures registry node ids cannot point outside the
declared area-files inventory.
AI isolation contract (feedback_ai_isolation_contract):
Gate body uses stdlib only (subprocess + re + ast). An AST self-verify
test rejects `anthropic` imports and `route_ai_fallback` references in
this file, structurally preventing AI routing inside the gate.
Stage 4 verification (HEAD c1df656 pre-commit):
pytest -q tests/phase_z2/test_imp35_baseline_red_invariance.py
→ 7 passed in 15.26s.
Baseline area sweep
(tests/test_imp47b_step12_ai_wiring.py +
tests/test_phase_z2_ai_fallback_config.py)
→ 4 failed / 6 passed / 0 errors; FAILED set ≡ registry (identity).
pytest --collect-only on the 4 registered node ids → all 4 resolve.
py_compile clean. Codex R1 = YES (independent verify).
Guardrails honored:
- Scope-locked: test-only file; zero production code in this commit.
- 1 commit = 1 decision unit (u11 only).
- No hardcoding: registry = Stage 2 contract frozen tuple, not
sample-specific literal; gate body has zero magic constants.
- AI isolation: stdlib-only gate, AST self-verify locks isolation.
- baseline-red 4 body repair = separate follow-up issue, not u11 scope.
source_comment_ids: Stage 1 problem-review; Stage 2 plan R2 + Codex R2
YES; Stage 3 Claude #30 + Codex #31 R7 YES; Stage 4 Claude #32 + Codex
#33 R1 YES.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>