Commit graph

1 commit

Author SHA1 Message Date
Shay
18503f3d6e feat: ADR-0115 Phase 1.3 — deterministic math word-problem parser
Closes Phase 1.3 of the ADR-0114 expert-capability roadmap. Turns a
grade-school word problem into a typed MathProblemGraph deterministically
(no LLM, no sampling). Same input string always produces the same
graph; unsupported constructions raise ParseError rather than guessing.

What the parser handles

  Initial possession:    "<E> has <N> <unit>."
  Add verbs:             buys, gets, finds, receives, earns, adds
                         (+ "<N> more" / unit elision via state.last_unit)
  Subtract verbs:        eats, loses, sells, donates, uses, spends, drops, removes
  Transfer verbs:        gives, sends, hands, passes, mails  (with target)
  Multiply (scalar):     "X doubles <obj>" / "X triples <obj>"
  Divide (split):        "X splits {them|his Y|N Y} evenly into M groups [and keeps one]"

  Compound sentences:    "X buys 5, then donates 3."
  Sentence opener:       "Then X eats 1."  (inherits subject + unit)
  Pronoun anaphora:      he/she/it → last-introduced singular subject
  Object pronoun:        them/these/those → state.last_unit
  Trailing PP:           "finds 7 buttons on the floor" — discarded
  Singular→plural:       "Iris has 1 coin" → canonical unit "coins"

  Questions:
    "How many <unit> does <E> have [left|now|in total|altogether]?"
    "How many <unit> do they have [in total|altogether|left|now]?"

What it explicitly rejects

  - Conditional / time-modal ("If X had ...")
  - Compound questions (two unknowns)
  - Multiple "?" sentences
  - Questions referencing entities never introduced
  - Empty / whitespace-only input

Verification

  - tests/test_math_parser.py: 20 cases (5 byte-equal parametrized
    + 5 determinism parametrized + 1 exit-criterion gate + 6 typed-
    refusal + 2 purity + 1 type check)
  - tests/test_math_problem_graph.py: 26 schema cases still green
  - On the 5 seed cases:  5/5 = 100% byte-equal
  - On Codex's PR #128 50-case dev set (locally tested):
    49/50 = 98% byte-equal. Single failure (gpd-021) is a case-
    quality issue, not a parser limit; feedback filed on #128 to
    rewrite (mixed units + metaphor not in pattern registry).
  - Phase 1.3 exit criterion (≥ 0.90): met.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 16:03:31 -07:00