* feat(derivation): Gate A2a unit partition injection Add typed unit_partition primitive with PartitionChunk/result_unit contract, recognizer-injector bridge, DCS yield guard, and pronoun lookback support. Closes unit_partition recognized_no_injection on live train_sample (0002 partition stmt reclassifies); wrong=0 preserved. * test(gsm8k): harden unit partition confusers * test(gsm8k): add unit partition pronoun safety regressions * chore(gsm8k): fix unit partition exemplar file ending * chore(derivation): type unit partition solution step operand
4.4 KiB
4.4 KiB
GSM8K Workstream A Gate A2a — unit partition implementation lookback
Date: 2026-06-17
Gate: A2a — unit_partition recognizer-injector + typed solver primitive
Status: Implementation complete (PR-ready; not merged)
Ratification: docs/analysis/gsm8k-workstream-a-gate-a2a-unit-partition-ratification-2026-06-17.md
1. What shipped
| Surface | Change |
|---|---|
PartitionChunk + unit_partition kind |
generate/math_problem_graph.py |
_apply_unit_partition + pack bind (divide lemma) |
generate/math_solver.py |
_verify_unit_partition_step |
generate/math_verifier.py |
Roundtrip + DIVIDE_VERBS widen (cut, separate) |
generate/math_roundtrip.py |
_match_unit_partition, DCS yield guard |
generate/recognizer_match.py |
inject_unit_partition |
generate/recognizer_anchor_inject.py |
| Exemplars + synthesis + accepted proposal | teaching/admissibility_exemplars/unit_partition_v1.jsonl, teaching/recognizer_synthesis.py, teaching/proposals/proposals.jsonl |
| Tests | tests/test_recognizer_unit_partition_inject.py, tests/test_math_candidate_graph_unit_partition_injection.py, frontier/microscope extensions |
Lead exemplar: case 0002 partition stmt She splits it up into 25-foot sections. now matches ShapeCategory.UNIT_PARTITION and injects CandidateOperation(kind="unit_partition") with result_unit=sections.
DCS yield: _match_discrete_count_statement returns None when _is_unit_partition_v1_surface holds — prevents Initial(25, foot) misread.
2. Solid
- New
unit_partitionkind writes quotient underresult_unit, not dividend unit — baredividereuse avoided. - Closed v1 template: partition verb +
into+ single\d+-(measure)+ optional counted noun. - Pronoun subject (
She) emits withrequires_pronoun_resolution; existing lookback path applies. wrong=0preserved on live train_sample ephemeral runner;unit_partitionrecognized_no_injection= 0.- Pinned
report.jsonunchanged (6/44/0 historical artifact).
3. Gaps (no live risk)
graph_intent: "partition"is new; no separate graph_planner hook (out of v1 scope).- Pack lemma maps
unit_partition→ existingdivideentry (semantically division; kind discriminatesresult_unitcontract). - No dedicated
binding_graphadmissibility hook; partition ops reach solver only via injector + roundtrip.
4. Drift from ratification
| Ratification claim | Implementation |
|---|---|
separate verb |
Included in matcher regex + DIVIDE_VERBS |
| Actor binding “no cross-sentence pronoun beyond session rules” | Uses existing ADR-0174 lookback; no new binding logic |
report.json rebaseline |
Intentionally skipped |
No amendment required.
5. Hazards reviewed
| Hazard | Verdict |
|---|---|
Over-recognition on \d+-(hour|foot) alone |
Mitigated: requires verb + into; 2-hour drive does not match unit_partition |
| DCS wins race on 0002 | Mitigated: DCS yield returns None |
Quotient stored under feet |
Mitigated: PartitionChunk.result_unit |
| Pseudo-accumulation 996 (confuser-v1-0007) | Full 0002 still refuses; no correct lift claimed |
| Non-exact quotient | Solver + verifier refuse (SolveError / VerificationError) |
6. Metric movement (ephemeral live runner)
| Metric | Before | After (expected) |
|---|---|---|
wrong |
0 | 0 |
correct |
6 | ≥ 6 (no lift guaranteed) |
refused |
44 | ≤ 44 |
unit_partition no-injection |
1 (0002 via DCS misroute) | 0 |
discrete_count_statement no-injection |
19 | likely 18 (−1 reclassification) |
Case 0002 partition stmt reclassifies; full solve to 15 remains refused until composition ratification.
7. Validation run
git diff --check origin/main...HEAD
pytest tests/test_recognizer_unit_partition_inject.py -q
pytest tests/test_math_candidate_graph_unit_partition_injection.py -q
pytest tests/test_gsm8k_frontier_report.py -q
pytest tests/test_gsm8k_post_gate_a1_frontier_microscope.py -q
pytest tests/test_candidate_graph_recognizer_wiring.py -q
8. Explicit non-goals (held)
- No full 0002 composition, no
report.jsonrebaseline, no sealed-lane pin movement - No Gate A1b, Inc4, broad DCS,
determine()/FrameVerdict/ CLOSE - No
graph_planner.pychanges