core/docs/decisions/ADR-0163-F2-confuser-corpus-spec.md
Shay 47a406b590
docs(adr-0163-f2): clarify refuse is maturity-relative — confusers are solvable coverage targets that graduate (#478)
A confuser's `expected: refuse` does not mean unanswerable. Every confuser carries
its true gold (`answer_numeric`) and is a solvable coverage target; `refuse` means
"the reader can't yet comprehend this category, so refusing is the honest outcome —
committing a WRONG value is the defect." Example: 0001 "buys a toy for 30 coins …
how many left?" is plain 50-30=20; it is refuse only because today's reader takes
`buys` as a gain.

Adds §2.1 (graduation protocol): when a general mechanism reads a category correctly
(validated on train_sample + the category, wrong=0 preserved), those cases graduate
refuse -> solve and committing their gold becomes a win. Reframes the `spurious`
verdict as "solved-before-graduation" (a graduation signal, with pair-consistency as
the genuine-reading-vs-surface-match discriminator), not automatically a defect.
Notes that no v1 category is degenerate, and how a truly-unanswerable case would be
labelled (answer_numeric: null + degenerate: true) so the two senses of "refuse"
stay distinguishable.

Spec only; no corpus/runner change (today's commits are wrong-reading, so spurious
stays flagged until a category genuinely graduates).
2026-05-29 13:23:02 -07:00

12 KiB
Raw Permalink Blame History

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 5596 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 … to996.

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)

{
  "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).