# ADR-0163-F2 — Confuser Corpus: a discrimination probe, not a coverage target **Status:** Proposed (spec only — no code). Follow-on to ADR-0163 §F (the Track-B additive practice scale). Corrects the *metric*, not just the data. > **One line.** A small, curated set of **hard negatives and near-miss confusers** > whose purpose is to measure whether the reader **refuses what it cannot yet read** > — success is `wrong = 0` on the confusers, *not* a higher solved count. --- ## 1. Why this exists (the failure it fixes) ADR-0163 §F added 150 templated additive practice cases. GB-3b flipped 55–96 of them — but on **real GSM8K (`train_sample`) accumulation fired on only 2/50, 1 correct / 1 wrong**. The synthetic flips did not generalise. The canonical misfire: > `train_sample-0002`: *"Jan buys 1000 feet of cable. She splits it into 25-foot > sections. She gives 1/4 to a friend. She puts half in storage. How much does she > keep?"* (gold 15) — read as `buys 1000 … gives … to` → **996**. The templated corpus has two defects that *cause* overfitting (memory: `feedback-synthetic-corpus-overfitting-trap`): 1. **Redundancy** — the 46 gain cases are one template × 46 noun/number swaps, so a surface-cue matcher "passes" without comprehension and the CP ledger fills with tautological confirmations. 2. **No hard negatives** — there is no problem that *looks* like accumulation but isn't (a fraction problem, a disguised-polarity verb, a second actor). The confusers are exactly what teach a reader **where to refuse**, and a corpus of clean templates contains none. This spec builds the missing half: the cases that make being wrong *informative*. ## 2. The reframe — what "success" means here This corpus is a **discrimination probe**, scored the opposite way from a coverage lane: | metric | meaning | bar | |---|---|---| | **`wrong` on confusers** | the reader committed an answer a confuser was built to trip | **must be 0** | | **`refused` on confusers** | the reader declined (the correct response to a not-yet-readable shape) | expected-high, honest frontier | | **`spurious` on confusers** | committed the *correct* value on a `refuse` case (right answer, but the bar was "don't commit yet") | see §2.1 — a *graduation signal*, not automatically a defect | | **`solved` on the paired positives** | the reader genuinely read the near-identical solvable case | real-capability signal | The headline number is **wrong=0**, never "how many solved." A change that solves more confusers is only progress if it does so by a **general mechanism** that also keeps `wrong=0` — and is validated on the held-out real lane, not by passing these specific rows. ## 2.1 `refuse` is maturity-relative — every confuser is a solvable coverage target **Amendment (2026-05-29).** A confuser's `expected: refuse` does **not** mean the problem is unanswerable or missing information. Every confuser carries its **true gold** in `answer_numeric` and is, ultimately, a **solvable coverage target**. The `refuse` label is **relative to what the reader can currently comprehend**: it means *"the engine cannot yet read this category, so refusing is the honest outcome — committing a **wrong** value is the defect."* The clearest example is `confuser-v1-0001`: > "Dan has 50 coins. He buys a toy **for** 30 coins. How many coins does Dan have > **left**?" — gold **20**. This is a plain subtraction (`50 − 30 = 20`; "left" even names the operation). It is labelled `refuse` only because today's reader has `buys` in its *gain* lexeme set and would commit `50 + 30 = 80`. A mature reader **should solve it to 20** — at which point its honest label is `solve`, not `refuse`. **Graduation protocol.** When a *general* mechanism teaches the reader to read a category correctly — validated on `train_sample` + the category, with `wrong=0` preserved (the §3/§8 guardrails) — those cases **graduate** `refuse → solve`, and committing their gold becomes a *win*. Graduation is the intended success path; it does **not** contradict "never optimise `refused` down by patches" (§2), because the bar is comprehension proven generally, not a row passed by vocab fitting. **`spurious` reframed.** A correct-valued commit on a `refuse` case is scored `spurious` (right value, but the case said "don't commit yet"). That is **"solved-before-graduation" — a signal to re-examine the case for graduation, not automatically a defect.** The **pair-consistency** check is the discriminator: a reader that solves the twin *and* commits the confuser by the same surface cue is surface-matching (a real tell); a reader that commits the correct gold *while still discriminating the pair* has genuinely read it, and the case should graduate. Until a category graduates, `spurious` stays flagged (conservative — wrong=0 first). **No category in v1 is degenerate.** Every current confuser is a solvable coverage target (disguised-polarity, pseudo-accumulation/fractions, multi-referent, multi-actor-pronoun, distractor, temporal-scope, comparative-referent, unit-confuser all have a definite gold reading). A genuinely *unanswerable* case (truly insufficient/contradictory information) — if ever added — would be labelled `expected: refuse` with `answer_numeric: null` and a `degenerate: true` flag, so the two senses of "refuse" (not-yet-readable vs unanswerable) stay distinguishable. ## 3. Anti-overfitting design rules (the load-bearing part) 1. **Minimal pairs.** Every confuser ships with a near-identical *solvable* twin that shares its surface cues but has a different correct reading. A reader that passes by surface cue alone gets the pair wrong; only a reader that reads the *structure* separates them. Example pair: - solvable: *"Anna has 25 stickers. She gives 10 **more** to her collection…"* → +10 - confuser: *"Anna has 25 stickers. She gives 10 **to a friend**…"* → −10 2. **Real-sourced, not invented templates.** Each case is a paraphrase of (or structurally drawn from) a real GSM8K problem; record the source id. No new generative template that a matcher could learn. 3. **Held-out by contract.** The corpus is a **probe, never a training-to-fit target.** If the reader is changed so a confuser stops misfiring, that change MUST be a general mechanism (e.g. completeness counting the fractions it currently misses), proven not to regress `train_sample`, and the confuser MUST be one of *many* of its category so the fix can't be memorisation. 4. **Diversity quota per category.** ≥ ~8 distinct cases per confuser category (below), with varied surface forms, so "passing the category" can't be one rule. 5. **Expected-behavior labelling.** Each case is labelled `expected: refuse | solve`. Most confusers are `refuse` (the reader can't yet read them and must not guess) — so the corpus is primarily a *refusal-correctness* test. The `refuse` label is **maturity-relative**, not a claim of unanswerability: every confuser carries its true gold and graduates `refuse → solve` once a general mechanism reads its category (see §2.1). ## 4. Confuser categories (grounded in observed real misfires) | category | what it trips | example (confuser) | correct | expected | |---|---|---|---|---| | **disguised-polarity verb** | gain verb that is actually a spend | "He buys a gift **for** 60" (coins) | −60 | refuse | | **pseudo-accumulation / fractions** | has/gives surface over a fraction-division problem | the 0002 cable problem | (multi-step) | refuse | | **multi-referent (H1)** | two actors, same unit | "Alice has 6. **Tom** has 2. How many does Alice have?" | 6 | refuse | | **multi-actor pronoun (ADR-0174)** | ambiguous "he/she" antecedent | "Sam and Tom shopped. **He** bought 5 more." | (ambiguous) | refuse | | **distractor quantity** | a number not in the computation | "for **3** days", "**25**-foot sections" | (varies) | refuse-unless-consumed | | **temporal/question-scope (H3)** | question asks *before* a stated change | "…gave 3 away. How many **before** giving any?" | pre-change | refuse | | **comparative-referent (H2)** | comparative binds to the non-asked actor | "**Tom** picked twice as many. How many did **Alice** pick?" | Alice's | refuse | | **unit confuser** | different-unit quantities that look summable | "6 **boxes** and 50 **apples**" | (not a sum) | refuse | | **genuine positive (paired twin)** | the solvable near-identical case | "She gives 10 **more**…" | +10 | solve | Categories are derived from the actual hazards already proven live (GB-3a H1/H2/H3, the 0002 misfire, the `buys-a-gift-for` polarity flip) — not invented. ## 5. Schema (`evals/gsm8k_math/confusers/v1/cases.jsonl`) ```json { "case_id": "confuser-v1-0001", "question": "…", "answer_numeric": 15, "category": "pseudo-accumulation", "surface_trap": "buys/gives-to over a fraction-division problem", "expected": "refuse", "pair_id": "confuser-v1-0002", "source": "gsm8k-train-sample-v1-0002 (paraphrase)", "notes": "fractions 1/4, half and 25-foot sections are unconsumed -> must refuse" } ``` Deterministic ordering; `pair_id` links minimal pairs; `source` records provenance. ## 6. The runner / how it scores (`confusers/v1/runner.py`) For each composer under test (accumulation, multiplicative, chain), report **per category**: `solved-correct / refused / wrong`, plus the **pair-consistency** check (did the reader separate each minimal pair, or pass both by surface cue?). The gate: - **`wrong == 0` across all confusers** — the hard bar (a confuser answered is a defect, regardless of value). - **pair-consistency** — a pair where the reader solves the twin but *also* answers the confuser (same surface, wrong) is a surface-matching tell → fail. - `refused` count is reported as the honest frontier, never optimised down by patches. ## 7. How the CP ledger uses it (the real learning value) Run the general composers over the confusers and `record_case` by gold. The **wrong attempts on confusers become the negative samples** the templated corpus lacked — they push the offending `(cue, op, unit_shape)` reliabilities *down*, which is exactly the discrimination signal CP-2b needs. Positive twins push the genuine cues up. This is "compare and contrast" with hard negatives, not redundant template confirmations. ## 8. Construction process (and its guardrails) 1. Start from the proven hazards + real `train_sample` misfires; paraphrase real problems into confuser/twin pairs. 2. Curate by hand (small, ≤ ~80 cases); no generative template. 3. Each row carries category + surface_trap + expected + source + pair_id. 4. **Guardrail:** building this corpus is *not* an invitation to grow reader vocab to pass it. The corpus is frozen as a probe; reader changes are judged on `train_sample` + pair-consistency, never on raw confuser solved-count. ## 9. Acceptance (Proposed → Accepted) 1. The corpus lands (~8/ category, all paired where applicable) with the schema + a runner reporting per-category `solved/refused/wrong` + pair-consistency. 2. The current composers score **`wrong = 0`** on it (they should *refuse* nearly all — that is the correct, honest result today). 3. A documented baseline (mostly-refuse) is recorded; future reader work is measured against it as a **regression gate** (`wrong` may never rise) and a generalisation signal (`solved` may rise only via general mechanisms that hold on `train_sample`). ## 10. Non-goals / explicit guardrails - **Not** a coverage lane; **not** scored by solved-count. - **Not** to be expanded with templates or used to tune cue vocab reactively. - **Not** a replacement for `train_sample` as the real-capability measure — it is the *refusal-correctness* complement to it. See [[thesis-decoding-not-generating]], `feedback-synthetic-corpus-overfitting-trap`, ADR-0178 (GB-3a hazards), ADR-0177 (CP ledger consumes the hard negatives).