core/tests/test_percent_partition_proposal.py
Shay 0dbcd63d63 feat: 3lang depth PropGraph unification - phase refinements, wiring, tests + session pickup cleanups/governance
- Complete depth canonical, pack resolver DEPTH_PACKS, pipeline attrs+node_depths+graph_anti, contemplate/pass_manager/contracts propagation (immutable).
- Polish anti_unifier, tests (oov, construction, percent), runtime/chat integration.
- Governance: AGENTS.md updates, docs/README/handoff_template, skills bootstrap, retire handoff.
- Leaves pickup seeds (NEW_SESSION_PROMPT, plan.md, compact) for continuity.
- Spine tests green, 3lang depth visible in ctx for he.

Refs: plan.md, 2026-07-06-compact.md
2026-07-08 07:07:11 -07:00

119 lines
4.2 KiB
Python

"""Percent-partition proposal-first construction seam tests."""
from __future__ import annotations
import dataclasses
import generate.construction_affordances as construction_affordances
import generate.problem_frame_builder as problem_frame_builder
import generate.problem_frame_contracts as problem_frame_contracts
from generate.problem_frame_builder import build_problem_frame
from generate.problem_frame_contracts import assess_contracts
PERCENT_PARTITION_CASE = (
"A school has 100 students. Half of the students are girls, the other half are boys. "
"20% of the girls have dogs at home and 10% of the boys have dogs at home. "
"How many students own dogs?"
)
ONE_SUBGROUP_CONFUSER = (
"There are 100 students. Half are girls. 30% of the girls own pets. "
"How many students own pets?"
)
PERCENT_CHANGE_CONFUSER = "A store spent 20% of its budget. How many dollars remain?"
def _percent_partition_proposal(frame):
return next(
proposal
for proposal in frame.proposals
if proposal.family_id == "partition.percent_partition"
)
def _percent_partition_assessment(frame):
return next(
assessment
for assessment in assess_contracts(frame, depth={"n": {"root": "test"}})
if assessment.candidate_organ == "percent_partition"
)
def test_supported_case_has_diagnostic_catalog_proposal() -> None:
proposal = _percent_partition_proposal(build_problem_frame(PERCENT_PARTITION_CASE))
assert proposal.status == "proposed"
assert proposal.diagnostic_only is True
assert proposal.serving_allowed is False
# AC3: depth used, explanation has root note
assessment = _percent_partition_assessment(build_problem_frame(PERCENT_PARTITION_CASE))
assert "[root:test]" in (getattr(assessment, "explanation", "") or "")
assert {role.role for role in proposal.role_obligations if role.required} == {
"whole",
"part",
"scale",
}
assert tuple(span.text for span in proposal.evidence_spans) == (
"20% of",
"10% of",
)
assert all(
PERCENT_PARTITION_CASE[span.start : span.end] == span.text
for span in proposal.evidence_spans
)
def test_migrated_family_produces_proposal() -> None:
"""Migrated family produces proposal via current path."""
proposal = _percent_partition_proposal(build_problem_frame(PERCENT_PARTITION_CASE))
assert proposal.status == "proposed"
assert proposal.family_id == "partition.percent_partition"
def test_contract_assessment_remains_runnable_authority() -> None:
frame = build_problem_frame(PERCENT_PARTITION_CASE)
assert _percent_partition_proposal(frame).status == "proposed"
assert _percent_partition_assessment(frame).runnable is True
def test_positive_proposal_does_not_close_missing_subgroup_bindings() -> None:
frame = build_problem_frame(ONE_SUBGROUP_CONFUSER)
assessment = _percent_partition_assessment(frame)
assert _percent_partition_proposal(frame).status == "proposed"
assert assessment.runnable is False
assert "partition_subgroups_not_distinct" in assessment.missing_bindings
assert "percent_subgroup_links_incomplete" in assessment.missing_bindings
def test_percent_partition_dispatch_requires_proposal_first_trace() -> None:
frame = build_problem_frame(PERCENT_PARTITION_CASE)
relation_only_frame = dataclasses.replace(frame, proposals=())
assert {candidate.name for candidate in relation_only_frame.process_frames} & {
"partition",
"consumption",
}
assert any(
relation.relation_type in {"subgroup_partition", "percent_of"}
for relation in relation_only_frame.bound_relations
)
assert not any(
assessment.candidate_organ == "percent_partition"
for assessment in assess_contracts(relation_only_frame)
)
def test_percent_change_confuser_is_proposed_but_not_runnable() -> None:
frame = build_problem_frame(PERCENT_CHANGE_CONFUSER)
assessment = _percent_partition_assessment(frame)
assert _percent_partition_proposal(frame).status == "proposed"
assert assessment.runnable is False
assert "grounded_partition_subgroup" in assessment.missing_bindings
assert "percent_change_vs_percent_of" in assessment.unresolved_hazards