core/docs/briefs/parallel-2026-05-23/L9-ADR-0131-G1-verb-classes-initial-state.md
Shay 1a288ad017
docs(ADR-0136): statement-layer corridor, S.0 taxonomy, 2026-05-23 brief archive (#200)
* docs(ADR-0136): statement-layer corridor + S.0 taxonomy + resolve math-file conflicts

- Add ADR-0136-statement-layer-corridor.md: corridor overview, S.0-S.4 phase table,
  taxonomy summary (23 context-filler, 4 rate-class, 5 compound, 17 long-tail),
  standing invariants (admitted_wrong==0, context-filler safety rail, honest delta).
- Restore generate/math_*.py to HEAD (main) — stash-pop conflict markers were
  cosmetic comment rewording; upstream version is authoritative.
- Stage docs/reviewers.yaml math_expert_claims addition (already authored).

* docs(briefs): archive all 2026-05-23 parallel-dispatch briefs (L1–L17 + README)
2026-05-23 20:25:23 -07:00

4.4 KiB

L9 brief — ADR-0131.G.1 — Capability axis: state-introducing verb classes

Worktree setup (do this first, non-negotiable):

git worktree add ../core-adr-0131-g1-verb-classes -b feat/adr-0131-g1-verb-classes origin/main
cd ../core-adr-0131-g1-verb-classes

Scope. First capability-axis iteration on top of ADR-0131.G's coverage probe. Extends the initial-possession candidate emitter to recognize a closed set of state-introducing verbs beyond the current has/have/is/are/was/were. Target verbs (drawn directly from the baseline refused_reasons_top clusters in train_sample_coverage_report.json): bought / buys, sells, collected, saved (up), started (with), had, makes (rate-introducing — only the initial-state reading, not the rate reading; that's L11/G.3's axis).

The architectural claim: each of these verbs introduces a quantity into the same InitialPossession shape <Entity> <verb> <N> <unit> — semantically equivalent to has, syntactically distinct. The candidate emitter widens; the binding graph and solver are untouched.

Reference docs (read these, only these):

  1. docs/decisions/ADR-0131.G-gsm8k-coverage-probe.md — the iteration discipline; every G. must do all 4 items in its "Every subsequent ADR-0131.G. must" section.
  2. generate/math_candidate_parser.py — extend _INITIAL_HAS_RE / CandidateInitial (do not branch into a new module; this is the same shape with a wider anchor alternation).

What to ship:

  • Parser extension in generate/math_candidate_parser.py: widen CandidateInitial.matched_anchor validation set and _INITIAL_HAS_RE anchor alternation to include the listed verbs. Past-tense forms (bought, collected, saved, had, started) are first-class. Round-trip filter stays the firewall — wider grammar, same wrong-rate-zero.
  • Curated coverage cases at evals/math_capability_axes/G1_verb_classes/v1/cases.jsonl (~20 cases, split by verb): each is <Entity> <verb> <N> <unit>. followed by a question the existing pipeline can answer. These exercise the new capability independently of GSM8K.
  • Runner at evals/math_capability_axes/G1_verb_classes/v1/runner.py (pure adapter over evals.gsm8k_math.runner infrastructure or chat/runtime end-to-end; deterministic report.json).
  • Tests at tests/test_adr_0131_G1_verb_classes.py (~10): safety rail (wrong == 0) on the new axis; per-verb at-least-one passing case; closed outcome vocab; replay byte-equality; GSM8K probe re-runs and admission_rate strictly increases vs the baseline 0.0; B3 lane unchanged.
  • ADR docs/decisions/ADR-0131.G.1-verb-classes-initial-state.md. Cite ADR-0131.G parent; document the closed verb set as a scope statement; declare what is not added (no rate verbs, no comparatives, no acquisition-with-cost semantics — those are sibling axes).
  • Refresh evals/gsm8k_math/train_sample/v1/train_sample_coverage_report.json (the diff-able number). PR title must include the new admission_rate.

Hard constraints:

  • Closed verb set. Every added anchor is enumerated in the ADR and in code. No paraphrase tolerance, no synonym expansion.
  • wrong == 0 preserved on both the new axis lane and the GSM8K probe. If round-trip would let a wrong answer through on any new verb, shrink the verb set, do not weaken the filter.
  • Initial-state reading only. makes in "Tina makes $18.00 an hour" is rate-introducing — that case must continue to refuse (or route to L11). Verify with an explicit adversarial probe case.
  • No new modules under algebra/, chat/, core/. No changes to the binding graph, solver, or verifier.
  • Determinism. Report byte-equal across runs.
  • Smell test (ADR-0131.G): if admission moves on GSM8K but the new axis cases don't all pass, the change is a template in disguise — reject.

Out of scope: rate verbs (L11/G.3), comparatives (L10/G.2), conjoined subjects (L12/G.4), commerce-with-price semantics, multi-statement coreference.

Target branch. PR against main. Title: feat(ADR-0131.G.1): state-introducing verb classes — admission N/50 (Δ+N from baseline). Body: new admission_rate, refused_reason delta vs baseline, per-verb case counts, link to ADR.

Exit criterion. CI green; new axis runner exits 0 with wrong == 0; GSM8K probe admission_rate strictly increases; B3 lane unchanged; refreshed coverage report committed.

Do not stack on another agent's branch. Target main directly.