Commit graph

2 commits

Author SHA1 Message Date
Shay
6582df3bae feat(parser): ADR-0122 rate/per-unit grammar (substrate-only; lift deferred)
First parser-expansion ADR after ADR-0121's deferral. Adds the rate
algebra substrate (Rate dataclass + apply_rate operation kind + parser
pattern + solver/verifier/realizer + en_arithmetic_v1 pack lemma)
mirroring the deferral pattern that ADR-0121 demonstrated for
capability promotion: substrate complete, gate refuses honestly.

Substrate
- Rate(value, numerator_unit, denominator_unit) frozen dataclass with
  strict positive-value + non-empty-distinct-unit refusal at construction
- apply_rate operation kind admitted in VALID_OPERATION_KINDS;
  Operation.operand widened to Quantity | Rate with kind-discriminated
  type enforcement
- Parser: _RATE_COST_EACH_RE + _RATE_COST_EACH_TRAILING_RE +
  _Q_RATE_AGGREGATE_RE patterns; actor_units state tracking;
  first-declaration-wins on redeclaration (ParseError); orphan-rate
  refusal at end of parse; three refusal paths in rate-aggregate question
- Solver: _apply_rate() reads denominator-unit state, multiplies by
  rate.value, writes numerator-unit state (denom preserved)
- Verifier: _verify_apply_rate_step() byte-equal replay
- Realizer: 'At {N} {numer} per {denom_singular}, {actor} spends ...'
  template containing required tokens
- Pack: en-arith-006 apply_rate lemma + gloss; SHA-256 checksums
  refreshed; manifest version 1.0.0 -> 1.1.0; provenance tagged
  adr-0122:rate_extension:2026-05-22

Measurement (honest)
- Sealed GSM8K correct_rate: 0/1319 (substrate matches zero real cases
  alone). Multi-construction barrier documented in the ADR: all 14 sealed
  cases matching 'each \w+ costs?' combine rate with at least one other
  class (aggregation 6, comparison 3, unit conversion 2, multi-actor 2,
  conditional 1)
- Sealed GSM8K wrong: 0 (load-bearing positive claim; grammar adds zero
  misparses across 1,319 real test problems)
- Anti-overfit lanes unchanged: OOD ratio, perturbation invariance
  preserving/breaking 1.0, adversarial wrong 0
- ADR-0121 invariants byte-equal preserved (6/6)
- 41 new ADR-0122 invariants pinned in tests/test_adr_0122_rate_per_unit.py
- 670 existing math + pack regression tests pass

Roadmap update
- Per-ADR lift expectation corrected: no single parser-expansion ADR
  will move sealed correct_rate alone. First lift signal will come
  from cumulative composition after 3rd or 4th class lands (rate +
  comparison + aggregation foundational set)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:24:28 -07:00
Shay
d2f5607167 feat: ADR-0116 — deterministic solver + en_arithmetic_v1 operator pack
Phase 2 of the ADR-0114 expert-capability roadmap. Consumes the
MathProblemGraph from Phase 1 and emits a SolutionTrace — ordered
operation applications ending at a numeric answer, byte-deterministic
across runs, with each step's operation bound to a pack-resolved
lemma identifier.

What landed

generate/math_solver.py
  - solve(graph) -> SolutionTrace; pure function, no I/O, no globals
  - SolutionStep dataclass with before/after values per step (for
    verifier replay; ADR-0117 hardens)
  - SolutionTrace with canonical_bytes() byte-deterministic JSON
  - SolveError typed refusal: missing pack, division by zero,
    unknown-references-nothing

language_packs/data/en_arithmetic_v1/
  - 5 operator lemmas: add / subtract / multiply / divide / transfer
  - role=operational_base (vocabulary-only; no domain claim)
  - SHA-256-anchored lexicon + glosses; manifest carries
    provenance=adr-0116:operator_seed:2026-05-22

tests/test_math_solver.py — 109 cases pinning five invariants:
  1. Phase 2 exit criterion: ≥ 0.80 on parser-correct dev set
     (current: 50/50 = 1.00)
  2. Determinism: two solves produce byte-equal trace
  3. Trace replay reproduces answer_value (verifier rehearsal)
  4. Typed refusal on under-determined inputs
  5. Every step.pack_lemma_id resolves to a real lexicon entry
     in en_arithmetic_v1

ADR-0114a obligation discharge

Four of ten anti-overfitting obligations now have load-bearing
implementations in code:

  #3  replay-equal trace                 — discharged (solver-layer)
  #4  typed refusal                      — discharged (solver-layer)
  #9  determinism                        — discharged (solver-layer)
  #10 operation provenance via pack      — DISCHARGED IN FULL

Removing the en_arithmetic_v1 pack now breaks every solve loudly.
The "operations bind to concepts, not hardcoded strings" claim is
architecturally true, not rhetorical.

Tests: 109/109 green on solver suite; 67/67 smoke suite green;
parser + schema suites still green from prior phases.

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