MS-3 composes MS-1 (Target) + MS-2 (comparative chains + completeness) + the gate. generate/derivation/multistep.py: search_chain(problem_text, target=None). Shape-based, NOT blind enumeration: enumerates a small principled candidate set (product-of-all if a multiplicative cue is present; sum-of-all if an aggregation hint is present; each optionally + comparative scalars), each using all quantities, routed through select_self_verified (grounding ∧ cue ∧ unit ∧ completeness ∧ uniqueness). Bounded (MAX_QUANTITIES, refuse-on-overflow) + deterministic. Target supplies the aggregation cue + question quantities; target- UNIT matching is deferred (answer_unit=start.unit is wrong for cross-unit products -> a unit gate would over-refuse; documented). Honest practice measurement (sealed lane): 4 correct / 9 wrong / 37 refused (baseline 3/0/47). +1 flip is the unambiguous whole-problem product (0021); the 9 wrongs are product-of-all eliminations on multi-step problems (caught by gold, the learning signal). Whole-problem shapes add no coverage beyond the unambiguous product WITHOUT cue precision: when product and sum both self-verify they disagree -> uniqueness refuses (safe-but-low-coverage by design). The lever remains cue precision (the ADR-0175 learning loop). Microscope finding: 0003-class flips (48*24*0.75=864=gold) are blocked by a DECIMAL/currency grounding gap -- '$0.75' tokenizes to 0/75 so '0.75' is not grounded by the shared round-trip primitive. Not a search bug; deferred extraction-richness work (won't casually change the serving round-trip primitive). A test documents the current refusal so the fix is detectable. wrong=0: serving untouched (sealed); ambiguity + no-licensed-cue refuse; routes through the proven gate. 8 MS-3 tests; full derivation surface 77/77; ruff clean; smoke 67. |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| comparatives.py | ||
| extract.py | ||
| model.py | ||
| multistep.py | ||
| search.py | ||
| target.py | ||
| verify.py | ||