Repository navigation
The pool census read every function body to throw it away 82ms later: a heads reading of the same grammar, 2x on the corpus parse - #9131
Conversation
… a heads reading of the same grammar, 2x on the corpus parse `pool_parse` builds full function bodies for all 3875 corpus modules and `census_heads_module_node` replaces every one of them with a shared stand-in 82ms later. The attribution probe measured that as 7.15s of the row's 14.24s and deliberately shipped no repair, naming it this class's next-rung trigger (DESIGN §6, bare minimum cost: a proven cost-shape defect is always fixed). This lands the repair as a READING of the same grammar, not a mode beside it. `ParseContext` carries `heads_only`; `parse_heads_with_table` sets it; a brace-delimited `fn`-shaped body is skipped at token grain, depth-counted over brace SHAPES the tokenizer already decided, and the body slot takes the loud `CensusHeadsBodyStripped` stand-in. All four fn-shaped body sites route through one `parse_item_block_body`, so no call site chooses and the two readings cannot drift apart per site. The census strip is KEPT rather than folded into the parser, and that is the construction move rather than leftover: it normalizes the body slot on BOTH readings, so the stand-in's shape is not a fact any consumer can depend on and the readings can only differ through the HEADS -- which is exactly what the receipt measures. MEASURED (3880 modules, roots dag + src/v2, one process): divergent=0 regressed=0 narrowed=0 both_refused=0 parse wall 12175/5885, 11030/5559, 12882/6382 ms -> 2.07x / 1.98x / 2.02x The ratio is the claim; the absolutes move ~15% on a shared container and are evidence it was measured, not a figure to plan against. It is the PARSE term, not the whole `pool_parse` row -- tokenize and newline indexing are outside both timers and unchanged. RED CONTROL: `depth + 1` -> `depth + 0` in the emitted skip turns 2820 of 3880 modules REGRESSED and exits 1; reverted, rebuilt, re-measured green. SELF-HOST: `--required-regen` first_generation_equal=true over 134 outputs. DECLARED SCOPE NARROWING: the heads reading refuses an unterminated body and every malformed item head, but not a well-braced ungrammatical body. That question is owned by the required run's .dag parse sweep, which full-parses src/v1, dag and src/v2; the census answering it a second time was one fact with two authorities and the expensive one. `narrowed` is a counted column, 0 today, so a future nonzero is visible rather than absorbed. The differential is `claim_executor --heads-reading-differential`, not enrolled in the required run on purpose: reading 3880 modules twice is the cost this removes. Next-rung trigger is a diff-proportional form of the same check. Receipt: docs/probes/heads_reading_of_the_grammar_2026-08-24.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The red is inherited from main, and the fix is already owned by #9133
Not this PR, and the check is mechanical rather than a judgement call. The refusal is an intersection of two declared rosters — Measured on
Which two main commits produced it, by bisecting the carriers between main's last green run (
At Main has not yet rendered its own verdict on this, which is why it looks like a PR-specific failure and is not one: every I am not pushing a fix, deliberately
Pushing the same retirement here would mean two lanes editing one carrier for one fact, and would bundle an unrelated fleet-wide repair into a parser change — which is the thing that makes both harder to review and to revert. This PR waits on #9133 and then wants a re-run; it needs no change of its own. If the operator would rather this PR carry the fix, say so and I will take it — but then #9133 should be closed rather than both landing. — sent from quick-carp-438 |
main changed src/v1/02_parse.dag (#9028) and re-emitted four stage0 mirrors, including this branch's own v1_compiler_parse.rs -- a merge=generated-artifact path where a clean merge can silently take one side wholesale. Controls taken before the merge say nothing about the tree that ships, so both were re-taken: required-regen: first_generation_equal=true planned=134 executed=134, exit 0 heads-reading-differential: compared=3886 divergent=0 narrowed=0 regressed=0 full 10009 ms / heads 4995 ms = 2.00x The .dag merge was checked line-wise too: all 7 lines this branch deletes relative to main are its own rewires (parse_block -> parse_item_block_body, the occurrence_base signature). None of #9028 was dropped. Denominator moved 3880 -> 3886 (main added modules); the ratio did not. Unblocked by #9133, which retired the four stale frozen_path_deferrals rows. That refusal was never this branch's: both rosters are static declarations and this diff touches neither. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Green — closing the loop on the inherited line-stop#9133 merged ( I merged main in rather than re-running the old check, because a rerun replays the previous merge ref and could not have told me whether #9133 fixed anything. Both controls were re-taken on the merged tree, because main changed
The Denominator moved 3880 → 3886 (main added modules); the ratio did not. The probe doc now marks the merged-tree run as the load-bearing measurement, with the three pre-merge runs kept as its history rather than quoted as current. Not merging per the manual-merge policy. Worth stating plainly: the three approvals are all from one provider, so this sits at the one-distinct-provider floor, not at two independent reads. — sent from quick-carp-438 |
The defect
pool_parsetokenizes and parses all 3875 corpus modules to build declaration heads, andcensus_heads_module_nodereplaces every function body with a shared stand-in 82ms later. The attribution probe (#9096's sibling,docs/probes/edge_index_tree_census_attribution_2026-08-24.md) measured that as 7.15s of the row's 14.24s and deliberately shipped no repair, naming it this class's next-rung trigger:This is that PR.
What it is — a reading, not a mode beside the parser
ParseContextcarriesheads_only;parse_heads_with_tableis the entry that sets it. Every item head is parsed by the same productions. A brace-delimitedfn-shaped body is skipped at token grain — depth-counted over brace shapes, which the tokenizer already decided, so a brace inside a string is not a brace — and the body slot takes the loudCensusHeadsBodyStrippedstand-in.Two things make this a reading of one grammar rather than a second, weaker parser:
fn,func,pattern,interface) route through a singleparse_item_block_body. No call site chooses, so the readings cannot drift apart per site.Measured —
claim_executor --heads-reading-differential3880 modules, roots
dag+src/v2, both readings in one process over the same module list, census strip applied to both, compared as an identity:Quote the ratio, not the absolutes. This is a shared container; the walls move ~15% run to run, the ratio does not, because both readings in a run pay the same contention. And it is the parse term only —
tokenizeandbuild_newline_indexare outside both timers and unchanged by this — so it is not a claim about the wholepool_parserow.RED control — the instrument can fail
One token mutated in the emitted mirror (
depth + 1→depth + 0, so a nested{stops deepening the count):2820 of 3880 red, exit 1. Reverted from the regen candidate, rebuilt, re-measured green (exit 0) — the restored tree is the one measured, not assumed restored. The mutation landing in
regressedrather thandivergentis why both columns exist: an early-ending skip leaves the stream mid-body and the next item refuses. Fail-closed, but not something to assume — a future mutation that does produce a silently shorter head list has somewhere to land.Self-host fixed point
The compiler built from this mirror re-emits this mirror. (
main.rsis a pre-existing declared divergence.)The one refusal this reading does not make — declared and counted
It refuses an unterminated body and every malformed item head, exactly as before. It does not refuse a well-braced but ungrammatical body — those tokens never reach the expression grammar.
That is a scope correction, not a hole: the required run's
.dagparse sweep full-parsessrc/v1,dagandsrc/v2and owns is the corpus grammatical. The census answering it a second time, as a side effect of building heads, was one fact with two authorities (§3) — and the expensive one, coupling every pool-derived resolve to the grammaticality of every body in the corpus.What is honestly given up: for roots the sweep does not cover, that refusal is no longer taken anywhere. The sweep's roots are a superset of the required run's pool roots, so the live population is empty today.
narrowedis its own counted column (0) rather than folded into pass or fail, so a future nonzero is visible instead of absorbed (§5).Scope statements
pool_parse's whole row, and no end-to-end floor figure — different machine and architecture from the attribution probe, and the two sets are not subtracted from each other anywhere.Receipt:
docs/probes/heads_reading_of_the_grammar_2026-08-24.md