feat(evals): the reader/writer construction overlap is 6 — and the reader fabricates on 22 more #138
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/construction-inventory"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 5 item 1 of
docs/plans/grammar-unification-2026-07-26.md. §6's RESULT asked for the overlap to be sized "by measuring the reader's construction set against the writer's rather than by growing corpora blindly." This does that.What it measures
New lane
evals/construction_inventory. It sweeps the writer's whole parameter space — everyRhetoricalMove×IntentTag× predicate × quantifier × tense × aspect, both public entry points, 32292 cells — quotients it by the reader's own function-word skeleton, and comprehends each construction under three vocabularies.The quotient is read off
reader._RESERVED, so it cannot be gerrymandered to flatter a number and it widens automatically when the reader learns a word.The overlap is the same six from both directions and is entirely set-theoretic:
X is a Y,the X is a Y, and the four categoricals. The writer cannot express one ordering, propositional or interrogative construction; the reader has no template for the bare transitive clause that is the writer's whole default output. Two reader constructions need a?, which no writer template contains — unreachable by shape, so corpus work cannot close that gap.This corrects §6, using a metric that was already on the page
Faithfulness, not acceptance, is the criterion — and that reverses two claims I wrote into §6's RESULT:
g_read_rateis1/293butg_args_rateis0.0. The one surface that "reads" —all molecules are defined as compounds— is comprehended assubset(molecule, defined_as_compound). The reader chunked the writer's verb phrase into a class name. It accepted; it did not comprehend.The lane's contract had separated
readfromargsfor exactly this reason; the RESULT put its weight on the wrong one. Kept in the doc as a correction rather than edited away, per that block's own convention.evals/grammar_roundtrip/contract.mdnow carries a standing warning never to quoteg_read_ratewithoutg_args_rate.Three findings that re-order Phase 5 item 1
1. Growing the inventory is not the first move — the reader fabricates. On 22 constructions it neither reads nor refuses; it invents.
every dog is a mammalmember(every_dog, mammal)all dogs are defined as mammalssubset(dog, defined_as_mammal)furthermore, all dogs are mammalsasserted(furthermore)The first and third are ordinary user English, not writer artefacts. One root cause:
_RESERVEDlacks the function words the writer emits, and_parse_propositionalaccepts any single token as a fact. This breaks the reader's own stated contract — "a fabricated reading is the only failure."2. It reaches served output.
CORE recites a premise the user never stated.
chat/runtime.pyadditionally realizes declarative turns into the held self, so a fabricated atom is vault-writable. Widening the inventory before closing this would widen the fabrication surface with it.3. ADR-0265's defect class survives inside ADR-0265's own designated owner of clause grammar. The four aspect arms of
_inflect_predicatebindnegatedto a wildcard and never read it:10530 of 16146 parameter points. Not reachable today — no producer sets
aspecton the serving path — so a loaded gun, not a casualty; the distinction ADR-0265 got wrong once already, so it is stated rather than assumed. It survived because ADR-0265's invariant is structural (isnegatedthreaded to the call?) and cannot see an arm that receives the flag and ignores it. A behavioural sweep catches what a threading invariant cannot.Deliberately not applied here
The two fabrication fixes are written already — as the mutations that turn the defect pins red (
every/eachinto_RESERVED; discourse connectives stripped in_split_clauses). They are not in this PR: they change what CORE comprehends from user input, which is a serving change on the truth path. Authorization-gated, ADR first, on the ADR-0261 §5.1 refuse-don't-drop precedent.This PR changes zero served bytes. It is measurement plus pins.
Guards, so the tables cannot rot
_inflect_predicate's match arms-f/-ves, suppletive) so a morphology gap cannot masquerade as a construction gap — currently 0 filler-dependence[Verification]
In-worktree, canonical CPython 3.12.13,
uv sync --locked:The suite count was checked deliberately: the first registration attempt silently landed in a different tuple than intended, and only the count delta caught it.
🤖 Generated with Claude Code