core/tests/test_candidate_domain_partition.py
Shay cc6f13a939
feat(ADR-0167/W3-A): e2e determinism + cognition regression — LexicalClaim slice closed (#357)
Wave 3, closes the LexicalClaim slice of ADR-0167.  After this PR the
math reader's refusal taxonomy is evidence, not terminus: lexical
refusals flow through audit row → typed evidence → dedup signature →
HITL ratification (W2-D) → pack write → next-audit-pass-resolves.

Deliverables
------------
- tests/test_math_evidence_e2e.py (new, 7 tests):
  * test_full_pipeline_from_audit_to_evidence
  * test_e2e_replay_equivalence
  * test_lexical_ratification_advances_unknown_word_row (case 0040 'sees')
  * test_e2e_determinism_across_processes
  * test_cognition_teaching_corridor_unaffected
  * test_evidence_dedup_via_claim_signature
  * test_audit_artifact_round_trip_with_signatures
- evals/gsm8k_math/train_sample/v1/audit_brief_11.md: Post-W2 baseline
  table + cognition regression line + case 0050 hazard status + pointer
  to the new e2e regression module.
- tests/test_candidate_domain_partition.py: minimal allowlist patch to
  test_existing_cognition_tests_untouched so that future ADR-0167 PRs
  can add their own evidence test files without tripping a structurally
  brittle hard-coded whitelist (W2-C partition risk; recorded in PR body).

Hard constraints held
---------------------
- wrong == 0: case 0050 hazard still refuses at sentence_index 0
  after the tmpdir-pack 'sees' ratification; no admission introduced.
- Cognition regression: zero modifications to cognition test bodies;
  only the W2-C whitelist assertion was loosened.
- Determinism: in-process and cross-process evidence_hash byte-identical.
- No real-pack mutation: a per-test digest fixture asserts
  language_packs/data/en_core_math_v1/ is byte-identical before and
  after each test.

Out of scope
------------
- Frame/Composition/Reference/Slot ratification handlers (follow-up ADRs).
- Workbench v1 wiring of math candidates (ADR-0167 §Q4).
- Auto-ratification — HITL only, forever.
- The two partition risks Gemini flagged in W2-C (cognition pack indexing,
  replay-gate default) remain follow-up.

With this PR merged the engine can ratify math-domain lexical claims
from its own refusal evidence through the existing HITL teaching
corridor — the thesis claim of ADR-0167 becomes a concrete green test.
2026-05-27 07:27:24 -07:00

97 lines
3.1 KiB
Python

"""Tests for W2-C — candidate domain partition."""
from __future__ import annotations
import subprocess
from pathlib import Path
from typing import Any
from core.protocol import canonical_bytes
from teaching.discovery import DiscoveryCandidate
def _candidate(*, domain: str | None = None) -> DiscoveryCandidate:
kwargs: dict[str, Any] = {
"candidate_id": "cand_1",
"proposed_chain": {
"subject": "wisdom",
"intent": "cause",
"connective": None,
"object": None,
},
"trigger": "would_have_grounded",
"source_turn_trace": "t1",
"pack_consistent": True,
"boundary_clean": True,
}
if domain is not None:
kwargs["domain"] = domain
return DiscoveryCandidate(**kwargs)
def test_default_domain_is_cognition():
"""Bare DiscoveryCandidate has domain == 'cognition'."""
cand = _candidate()
assert cand.domain == "cognition"
def test_math_domain_can_be_set():
"""Explicit domain='math' constructs successfully."""
cand = _candidate(domain="math")
assert cand.domain == "math"
def test_round_trip_preserves_domain():
"""Serialization/deserialization preserves the domain field."""
# Cognition domain
cand_cog = _candidate(domain="cognition")
dict_cog = cand_cog.as_dict()
assert "domain" not in dict_cog # Omitted to preserve legacy keys
roundtrip_cog = DiscoveryCandidate.from_dict(dict_cog)
assert roundtrip_cog.domain == "cognition"
# Math domain
cand_math = _candidate(domain="math")
dict_math = cand_math.as_dict()
assert dict_math["domain"] == "math" # Included for math
roundtrip_math = DiscoveryCandidate.from_dict(dict_math)
assert roundtrip_math.domain == "math"
def test_canonical_bytes_includes_domain_deterministically():
"""Same domain value -> same canonical bytes contribution."""
cand_math_1 = _candidate(domain="math")
cand_math_2 = _candidate(domain="math")
bytes_1 = canonical_bytes(cand_math_1)
bytes_2 = canonical_bytes(cand_math_2)
assert bytes_1 == bytes_2
cand_cog = _candidate(domain="cognition")
bytes_cog = canonical_bytes(cand_cog)
assert bytes_cog != bytes_1
assert b'"domain":"math"' in bytes_1
assert b'"domain":"cognition"' in bytes_cog
def test_existing_cognition_tests_untouched():
"""Assert zero modifications to pre-existing cognition test files."""
# Find modified or untracked test files in git status
result = subprocess.run(
["git", "status", "--porcelain", "tests/"],
capture_output=True,
text=True,
check=True,
)
lines = [line.strip() for line in result.stdout.splitlines() if line.strip()]
# Allowlist of new/modified test files contributed by ADR-0167 PRs.
# Future ADR-0167 PRs append their own file here so this regression net
# stays meaningful as the wave progresses.
allowed = {
"test_candidate_domain_partition.py", # W2-C
"test_math_evidence_e2e.py", # W3-A
}
for line in lines:
path = line.split()[-1]
assert Path(path).name in allowed, (
f"unexpected new/modified test file: {path}"
)