## Summary PR 11B in the Brief 11 sequence. Closes the missing-operator inference gap left by 11A (#343) and ships the per-case audit artifact that Brief 11 §Gate 2 identifies as "the main Brief 11 artifact." ## Why this PR does NOT touch the reader runtime The naive closure fix for `pre_frame_filler_sentence` (drain `statement_terminator` at pre-frame) lifts 2 cases from refused → admitted but creates a `wrong > 0` hazard on `gsm8k-train-sample-v1-0050`: ``` Mark does a gig every other day for 2 weeks. For each gig, he plays 3 songs. ... How many minutes did he play? ``` With the drain enabled, the reader admits `Operation(mark, add, 3, songs)` with unknown unit `minute` and would project to a wrong answer. The stricter variant (`pending_entity_ref is None` + no quantities) fires on 0 of the 11 candidate cases. Per Brief 11 §"Failure modes to avoid §1 — Correct-count greed," this PR rejects both variants and routes the closure fix to a follow-up that adds the required verb vocabulary or sentence-intent classifier. ## Deliverables - `generate/comprehension/audit.py` — three new missing-operator labels: - `pre_frame_filler_sentence` (8 cases) - `descriptive_frame_question` (2 cases) - `question_frame_slot` (1 case) Closes the 11-case `None`-operator gap left by 11A. - `evals/gsm8k_math/train_sample/v1/audit_brief_11.json` — per-case audit artifact pinned by tests. - `evals/gsm8k_math/train_sample/v1/audit_brief_11.md` — narrative summary including the rejected-fix design tension and ranked Brief 11B-step-2 backlog. - `tests/test_brief_11b_audit_artifact.py` — 12 tests pinning the new labels, the per-case artifact, the wrong=0 invariant, and the refusal taxonomy. ## Bottleneck taxonomy (after Brief 11B labelling) | missing_operator | count | category | |-------------------------------|------:|------------------------| | quantity_extraction | 9 | incomplete_operation | | lexicon_entry | 9 | unknown_word | | multi_quantity_composition | 8 | incomplete_operation | | pre_frame_filler_sentence | 8 | unexpected_category | | pronoun_resolution | 3 | unresolved_pronoun | | fraction_percentage_literal | 3 | unexpected_category | | unit_binding | 3 | unattached_quantity | | descriptive_frame_question | 2 | unexpected_category | | (others, 1 each) | 5 | various | ## Test plan - 12 new tests in `tests/test_brief_11b_audit_artifact.py` pass - 23 existing 11A tests in `tests/test_brief_11_audit.py` pass - No runtime changes; reader byte-identical to main ## Hard invariants preserved - `wrong == 0` — no runtime change, no new admissions - ADR-0166 — no new canonical eval lanes added; existing `evals/gsm8k_math/train_sample/v1/` artifact set extended - No teaching store / pack mutation ## Follow-up - **11B-step-2** — verb-vocabulary expansion or sentence-intent classifier for `pre_frame_filler_sentence` (8 cases). See audit_brief_11.md §"design tension" for the rejected one-line variants and why they fail wrong=0. - **11C** — existing-lane capability snapshot (still gated on 11B-step-2 or another closure pass). |
||
|---|---|---|
| .. | ||
| adversarial | ||
| baselines | ||
| dev | ||
| holdouts/v1 | ||
| public/v1 | ||
| scoring | ||
| train_sample | ||
| contract.md | ||
| README.md | ||
| runner.py | ||
| verify.py | ||
gsm8k_math — Curated Eval Split for the GSM8K Evaluation Lane
Status: ADR-0119.2. 200 cases authored.
Schema source of truth: generate/math_problem_graph.py (typed dataclasses).
Format: JSONL — one case per line.
Why this set is not drawn from GSM8K
The GSM8K eval lane (ADR-0119) treats the actual GSM8K corpus as a sealed holdout test set. To preserve that integrity, we author this dataset independently in the same style as GSM8K (grade-school word problems with integer answers and 1-8 reasoning steps) but using our own vocabulary and grammar, ensuring zero overlap with the sealed holdout.
The dataset measures the solver pipeline (parser → solver → verifier → realizer). A correctly-parsed and solved problem is one whose parser output matches the ground-truth graph byte-for-byte and solves to the expected answer and unit.
Case schema
Each line is one JSON object:
{
"id": "gma-NNN",
"problem": "<the natural-language word problem>",
"expected_answer": <integer>,
"expected_unit": "<unit string>",
"ground_truth_graph": {
"entities": ["<entity_1>", "<entity_2>", ...],
"initial_state": [
{"entity": "<entity>", "quantity": {"unit": "<unit>", "value": <number>}},
...
],
"operations": [
{"actor": "<entity>", "kind": "<add|subtract|transfer|multiply|divide>",
"operand": {"unit": "<unit>", "value": <number>},
"target": "<entity>" /* required when kind=transfer; omitted otherwise */},
...
],
"unknown": {"entity": "<entity>" | null, "unit": "<unit>"}
},
"patterns": ["<pattern_tag_1>", "<pattern_tag_2>", ...],
"notes": "<authoring rationale>"
}
Field rules
id—gma-NNNwhere:gma-001...gma-050are for thedevsplit.gma-101...gma-250are for thepublicsplit.
problem— one or more complete English sentences ending in a question. Use Title-Cased proper names for entities ("Sam", "Anna's Toy Box"). Be consistent: the same entity always spelled the same way inproblemandground_truth_graph.entities.expected_answer— the integer answer to the question.expected_unit— the unit string the answer is in. Must matchground_truth_graph.unknown.unitbyte-for-byte.ground_truth_graph.entities— tuple in order of first introduction in the problem text. Not alphabetical. No duplicates.ground_truth_graph.initial_state— every entity that starts the problem with a known quantity. Empty list is legal if no initial possessions are asserted (rare).ground_truth_graph.operations— in source-text order. Empty list is legal (e.g. multi-entity sum questions with no mutations).ground_truth_graph.unknown.entity— set to the entity the question asks about, ornullif the question asks for a total across all entities ("How many ... in total?"; "How many do they have altogether?").patterns— tag list naming the constructions used. See Pattern registry below.notes— author-supplied one-sentence rationale. Read by future reviewers when the parser fails this case.
Canonicalization rules
- Units — lowercase, plural form ("apples", "candies", "dollars", "hours"). Use "dollars" for "$" quantities; the parser is expected to rewrite the "$" surface to the canonical unit.
- Entities — preserve capitalization as written. Do not lowercase.
- Numbers — integers when the text shows integers.
- Operation kinds — exactly one of
add,subtract,transfer,multiply,divide. Choose the one closest to the verb in the text:- "buys / gets / receives / earns / finds / adds" →
add - "eats / loses / sells / spends / drops / uses / removes" →
subtract - "gives / sends / hands / passes / mails / transfers" →
transfer(and settarget) - "doubles / triples / Nx as many" →
multiply - "splits evenly into N / N% of / shares equally with N people" →
divide
- "buys / gets / receives / earns / finds / adds" →
Scope limits (ADR-0119.2)
The parser and solver handle the following patterns and no others. Cases violating these constraints are out of scope:
- NO Time-modal / conditional phrasing ("If Sam had 5 apples, ...") — out of scope. Use direct declarative phrasing only.
- NO Rate/per-unit pricing requiring inference ("Each apple costs $2. Sam buys 4. How much does he spend?") — out of scope. A simpler variant ("Sam spends $8 on apples. How much does he have left?") IS in scope.
- NO Multi-clause / compound-question problems ("How many does Sam have, and how many does Tom have?") — out of scope. One unknown per case.
- NO Implicit-entity / generic plural ("There are 5 boys. Each has 2 apples.") — out of scope. Use named entities.
- NO Comparative phrasing without explicit numbers ("Sam has twice as many as Tom") — out of scope. Use numeric multipliers only ("Sam has 2 times 3 apples").
- NO metaphor or mixed units within one entity — out of scope. Keep units consistent.
- NO numeric magnitude beyond integer scope — out of scope. Only use integers.
Pattern registry
When tagging a case under patterns, draw from this list.
| Pattern tag | Construction | Example |
|---|---|---|
initial_has |
" has ." | "Sam has 5 apples." |
initial_there_are |
"There are ." (no entity; rare) | "There are 12 candies on the table." |
operation_buy_more |
" buys more." | "He buys 3 more." |
operation_get_more |
" gets more ." | "She gets 4 more pencils." |
operation_find_adds |
" finds ." | "Sam finds 2 apples on the path." |
operation_eat_loses |
" eats ." | "Tom eats 4 candies." |
operation_lose_loses |
" loses ." | "Anna loses 3 marbles." |
operation_sell_loses |
" sells ." | "Lisa sells 2 books." |
operation_donate_loses |
" donates ." | "Lisa donates 3 books." |
operation_use_loses |
" uses ." | "He uses 2 sheets of paper." |
operation_give_transfer |
" gives to ." | "Anna gives 3 marbles to Ben." |
operation_send_transfer |
" sends to ." | "Tom sends 4 letters to Sara." |
operation_double |
" doubles ..." | "Sam doubles his savings." |
operation_triple |
" triples ..." | "Sam triples his stickers." |
operation_split_divide |
"splits/shares evenly" | "They split 12 candies evenly." |
question_how_many_entity |
"How many does have?" | "How many apples does Sam have?" |
question_how_many_left |
"How many ... left?" | "How many candies does Tom have left?" |
question_how_many_total |
"How many ... in total?" / "altogether" | "How many stickers do they have in total?" |
question_how_many_now |
"How many ... now?" | "How many marbles does Anna have now?" |