core/tests/test_candidate_domain_partition.py
Shay 05aaff224e
feat(ADR-0167/W2-C): domain discriminator + cross-domain audit (#351)
* feat(ADR-0167/W1-A): MathReaderRefusalEvidence schema + canonical-bytes

Foundation type for routing comprehension-reader refusals into the
teaching corridor.  Frozen dataclass with sha256 evidence_hash computed
from deterministic canonical bytes (mirrors state.to_canonical_bytes
pattern).  Includes SUB_TYPE_FOR_OPERATOR mapping table covering all 13
missing_operator values in the current audit artifact.

Wave 1 only — no runtime mutation, no teaching-store integration, no
admission path.  Downstream W2-A/B/C/D type-import from this module.

* feat(ADR-0167/W2-C): domain discriminator + cross-domain audit

- Links to the audit doc: docs/handoff/ADR-0167-W2C-cross-domain-audit.md
- Inventory details: 5 construction sites, 8 consumption sites
- Verification: 0 cognition test files were modified; all tests are green
- Downstream partition work flagged: contemplation indexing (in teaching/contemplation.py) and replay gate (in teaching/proposals.py)
2026-05-27 06:44:29 -07:00

92 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()]
for line in lines:
path = line.split()[-1]
# We only expect test_candidate_domain_partition.py as new/modified file.
# Note: test_math_evidence_schema.py was added by W1-A and merged, so
# depending on if we are checking against HEAD, we should verify it is untouched by us.
# git status --porcelain shows changes compared to HEAD.
assert Path(path).name == "test_candidate_domain_partition.py"