* docs: consolidate governance anchors and clean up test registries * refactor(cli): decompose cli into dedicated modules * test: fix broken test baselines and formatting * docs: add domain boundary READMEs for governance anchors * test: update baseline for determination lane * test: fix capability_pass expectation * test: fix CORE_SHOWCASE_SKIP_BUDGET enforcement * chore: cleanup CLI extraction and unreachable code
130 lines
4.4 KiB
Python
130 lines
4.4 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)
|
|
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
|
|
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_does_not_use_legacy_assessment_adapter(monkeypatch) -> None:
|
|
original_make_proposal = construction_affordances.make_proposal
|
|
|
|
def reject_migrated_family(*args, **kwargs):
|
|
family_id = kwargs.get("family_id", args[0] if args else None)
|
|
if family_id == "partition.percent_partition":
|
|
raise AssertionError("migrated family reached legacy make_proposal adapter")
|
|
return original_make_proposal(*args, **kwargs)
|
|
|
|
monkeypatch.setattr(
|
|
construction_affordances,
|
|
"make_proposal",
|
|
reject_migrated_family,
|
|
)
|
|
|
|
assert (
|
|
_percent_partition_proposal(build_problem_frame(PERCENT_PARTITION_CASE)).status
|
|
== "proposed"
|
|
)
|
|
|
|
|
|
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
|