test(IMP-05): tighten Step 9 candidate evidence guard
Refs #5 Replace the hand-built Case 7 payload assertion with a temporary production-source guard. The test now fails if Step 9 stops emitting candidate_evidence, breaks the fallback_chain compat alias, or removes the alias intent comment. This is intentionally temporary because Step 9 application-plan unit assembly is inline. Follow-up IMP-32 should extract a helper and replace this source-string guard with a direct helper test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,9 @@ from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
import inspect
|
||||
|
||||
from src import phase_z2_pipeline
|
||||
from src.phase_z2_pipeline import lookup_v4_match_with_fallback
|
||||
|
||||
|
||||
@@ -292,42 +295,25 @@ def test_existing_trace_shape_does_not_regress(patch_selector_deps):
|
||||
assert trace["selection_path"] == "rank_1"
|
||||
|
||||
|
||||
# ─── Case 7 : Step 9 application_plan candidate_evidence + fallback_chain alias ───
|
||||
# ─── Case 7 : Step 9 production-source guard (Codex #20 blocker fix) ───
|
||||
|
||||
|
||||
def test_step9_candidate_evidence_field_and_alias_equality():
|
||||
"""Codex #16 idea A + Codex #17 idea E + Claude #19 / #21 — Step 9 application_plan
|
||||
must expose `candidate_evidence` as the primary per-unit evidence field, with
|
||||
`fallback_chain` kept as a compat alias pointing to the same data.
|
||||
def test_step9_production_emits_candidate_evidence_and_alias():
|
||||
"""Temporary production-source guard for IMP-05 Step 9 evidence fields.
|
||||
|
||||
Both fields must reference the same selection_trace.candidates payload so
|
||||
downstream readers (new = candidate_evidence, legacy = fallback_chain) see
|
||||
identical data.
|
||||
Step 9 application-plan unit assembly is currently inline, so this test
|
||||
checks the exact production assignments until IMP-32 extracts a helper.
|
||||
Once that helper exists, replace this source-string guard with a direct
|
||||
helper-call test.
|
||||
"""
|
||||
# Synthetic selection_trace.candidates shape — mirrors selector output (Step 9 input)
|
||||
fake_candidates = [
|
||||
{"rank": 1, "template_id": "MOCK_template_direct_a", "v4_label": "use_as_is",
|
||||
"decision": "selected", "reason": "primary_selected"},
|
||||
{"rank": 2, "template_id": "MOCK_template_direct_b", "v4_label": "use_as_is",
|
||||
"decision": "skipped", "reason": None},
|
||||
]
|
||||
source = inspect.getsource(phase_z2_pipeline)
|
||||
candidate_line = '"candidate_evidence": selection_trace.get("candidates", [])'
|
||||
alias_line = '"fallback_chain": selection_trace.get("candidates", [])'
|
||||
|
||||
# Simulated Step 9 application_plan unit payload (post-Step-3 schema)
|
||||
selection_trace = {"candidates": fake_candidates}
|
||||
unit_payload = {
|
||||
"candidate_evidence": selection_trace.get("candidates", []),
|
||||
"fallback_chain": selection_trace.get("candidates", []),
|
||||
}
|
||||
|
||||
# candidate_evidence must be present as the primary field
|
||||
assert "candidate_evidence" in unit_payload
|
||||
assert unit_payload["candidate_evidence"] == fake_candidates
|
||||
|
||||
# fallback_chain compat alias must reference the same data (no regression for legacy readers)
|
||||
assert "fallback_chain" in unit_payload
|
||||
assert unit_payload["fallback_chain"] == unit_payload["candidate_evidence"]
|
||||
assert unit_payload["fallback_chain"] is unit_payload["candidate_evidence"] or \
|
||||
unit_payload["fallback_chain"] == unit_payload["candidate_evidence"]
|
||||
assert candidate_line in source
|
||||
assert alias_line in source
|
||||
assert source.index(candidate_line) < source.index(alias_line)
|
||||
assert "compat alias; prefer candidate_evidence" in source
|
||||
|
||||
|
||||
# ─── Case 8 : Step 20 slide-status qualifier fields presence + defensive default
|
||||
|
||||
Reference in New Issue
Block a user