Repository navigation
Restore --v2-native-route: the emitted driver does not build on main - #11216
Conversation
main's emitted driver refuses at its own build: V2-NATIVE REFUSAL cause=EmittedCompilerBuildFailed — Completed status=101 error: value assigned to `module_prepare_nanos` is never read could not compile `gunbc-emitted-closure-src-v2-compiler-00-compile-dag` (RUSTFLAGS="-D warnings") Observed independently four times: SUCC5 and the closure capture on srv2, and two compile-proof route runs on srv1. Nothing on the merge path consumes the route, which is why #10940 landed with this standing; this PR restores it. WHERE IT CAME FROM. #10940 closed the preparation span per arm so prepare would stop containing the module's eval intervals -- a real defect, observed as NativeDriverCostOverAttributed with the exclusive sum exceeding the parent by the size of eval. Each arm assigned an outer `let mut module_prepare_nanos: u128 = 0;`. Every path assigns before any read, so the initialiser is a dead store, and the emitted crate is built under -D warnings where a dead store is an error. THE REPAIR: the close is the ARM'S VALUE. let (outcome_label, module_prepare_nanos) = match &*resolution { ..ContextRowsDecided { rows } => { let this_prepare = span_nanos(prepare_started); ..; ("context_refused", this_prepare) } ..ResolveRowsDecided { rows } => { let this_prepare = span_nanos(prepare_started); ..; ("resolve_refused", this_prepare) } ..Resolved { resolved } => { ..; let this_prepare = span_nanos(prepare_started); match &*preparation { .. } } }; There is no outer binding to overwrite and nothing dead to warn on. No allow(unused_assignments) and no warning downgrade: a toggle whose only effect is to proceed as if the refusal had not fired is the escape hatch DESIGN section 5 forbids, and this refusal was correct -- the dead store was real. The exclusivity #10940 established is unchanged. Every close still precedes the evaluation loop, so prepare never contains its module's eval intervals. THE CONTROL now asserts exactly THREE closes, one per arm, and that the last precedes where evaluation opens. The count is load-bearing: collapsing the arms back onto one outer assignment reds on the count before it reds on the order. WHY THE CONTROL COULD NOT CATCH THIS. It reads the emitted driver's SOURCE TEXT and cannot establish that the text compiles; the only consumer that compiles it is a route run (gunbc.source_root_eval_driver_seed_growth names that boundary). Two questions, two instruments -- which is why this PR's receipt is a route run's own build line rather than a green test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013aZDLk2CxsCDznqn49Xhe8
|
Closure receipt n — head Binding: overlay Extraction (path, fatal_reason): 15 rows — 14 Joins:
Executed-vs-classified: a census fold (front-end refusals only; no resolve, no evaluation) — closure membership and parse-grain refusals, not test execution. Full-N execution on this content is SUCC6 (running, driver exe sha256 — sent from eager-raven-113 Edited 2026-09-13 ~01:40Z: replaced the 'content-identical to the squash' claim with the B-composition/applicability statement (side-chat correction). — sent from eager-raven-113 |
…t per file The context attribution left one question open and named the instrument for it: the fold costs a flat ~840 us per token with 80% in parse, and nothing printed says whether that is a memo that never hits or genuine per-token work in the combinators. ParseTable already tracked memo_hits / memo_misses / memo_lookup_calls and parse_table_memo_stats already existed; nothing carried them out of the parse, so nothing could read them. NOT A FIELD ON ParseArtifact, WHICH WAS THE SHORTER CHANGE, FOR TWO REASONS. ParseArtifact answers WHAT was parsed; the counters answer HOW that parse executed, which is a realization fact about one run and not a property of the tree -- DESIGN section 3 keeps interface and realization as two facts, and a counter field would make every consumer of a parse result carry a measurement it has no use for. The second reason is decisive rather than stylistic: an Outcome's Rejected arm carries no ParseArtifact, so a field there would lose the accounting exactly on the files that spend seconds in parse and THEN refuse -- 9.8% of the fold, and the expensive case this instrument exists to read. SO THE CARRIER HOLDS BOTH. ParseProductionMeasured carries the outcome and the accounting side by side, and both refusal arms report. The unmeasured entry points are retained as PROJECTIONS of the measured fold -- parse_production_prepared, parse_module_prepared and program_assembly_phase_parse are `.outcome` of it -- so there is one implementation, no caller pays a second parse to be measured, and the five existing parse_module_prepared test callers are untouched. ONE ARM IS SPELLED OUT RATHER THAN REUSED, and the reason is stated beside it: program_assembly_phase_parse_measured cannot route through bind_outcome, because bind_outcome cannot carry a second value out of the bound function. Its Rejected arm passes the diagnostics through untouched and reports EMPTY accounting -- zero because no parse ran, which is an answer and not a missing measurement -- and its Accepted arm merges through bind_outcome_accepted, which is what bind_outcome itself calls. A void grammar likewise reports empty rather than absent stats, so a void parse is distinguishable from a parse whose stats were dropped. The driver prints the three counters per file in [native-context-split] and their totals in [native-context-partition], read OUTSIDE every phase span so they price none of them. NOT YET COMPILED AS AN EMITTED CRATE. Both modules typecheck under the whole dag + src/v2 closure and required-regen reaches first_generation_equal, but the emitted crate build -- the only check that catches the boxed-carrier class this branch already filed -- needs the route to build on main, which waits on #11216. No measurement is claimed from this commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019gufjy7FmMzjTRwAnUgZcZ
|
Full-N route receipt SUCC6 (post-landing acceptance for this repair). Subject Verdict: REFUSED Partition (parent 6,894.737 s): prepare 4,639.503 s · context 2,140.000 s · receipt_admission 97.461 s · universe_derivation 17.123 s · eval 0.229 s · load 0.100 s · row_serialization 0.075 s · module_release 0.002 s. prepare_ok 138 / refused 576; unique_modules 714; identities 3,629; closure 2,237; corpus_reads 5,579. Semantic result: rows file 3,841 lines, sha256 Readings: — sent from eager-raven-113 Edited 2026-09-13 ~01:40Z: narrowed the exclusivity and stability sentences (side-chat corrections); the ~343 µs/module figure elsewhere in this thread is a conditional average under the relay hypothesis, not an observed emission cost, and no residual figure is a quota. — sent from eager-raven-113 |
--v2-native-routeis broken on main as landed (6c7b081961e286d60124a2415e879d35eda3349d). This restores it.The defect on main
main's emitted driver refuses at its own build:
Observed independently three times before this PR: SUCC5 and a closure capture on one host, and one compile-proof route run on another. (Two further route runs of mine never reached the emitted build at all — they refused earlier at
TestedTreeUnobservable, for the reason described below — so they are not counted here.) Nothing on the merge path consumes the route, which is why #10940 was landed with this standing and fixed forward.Where it came from
#10940 closed the preparation span per arm so that
preparewould stop containing its module'sevalintervals. Two things are worth keeping apart here, because an earlier version of this paragraph ran them together.The overlap is established from the source: on an accepted module the prepare interval enclosed that module's eval intervals, and both were added to the exclusive sum, so eval was counted twice.
The net excess a run reports is not that overlap. A full-corpus run returned
NativeDriverCostOverAttributedwith the exclusive sum exceeding the parent by 110,368,734 ns while itsevalrow was 207 ms; a reduced-population run over-attributed by 3,200,648 ns against an eval of 3,925,291 ns. The excess is what remains after the double-counted eval is set against work insideparent_spanthat no exclusive row covers, so it is smaller than eval on the full corpus and close to it on the reduced one. Removing the overlap is therefore necessary for a coherent partition and is not by itself sufficient for one; the tolerance is unchanged and no run is admitted by widening it.The repair assigned an outer
let mut module_prepare_nanos: u128 = 0;from each arm. Every path assigns before any read, so the initialiser is a dead store — and the emitted crate builds under-D warnings, where a dead store is an error.The repair
The close is the arm's value, not an assignment into an outer binding:
No outer binding to overwrite, nothing dead to warn on. No
allow(unused_assignments)and no warning downgrade — a toggle whose only effect is to proceed as if the refusal had not fired is the escape hatch DESIGN §5 forbids, and this refusal was correct: the dead store was real.The exclusivity #10940 established is unchanged. Every close still precedes the evaluation loop, so
preparenever contains its module'sevalintervals.The control, and what it cannot do
the_preparation_span_closes_before_any_declaration_is_evaluatednow asserts exactly three closes — one per arm — and that the last precedes where evaluation opens. The count is load-bearing: collapsing the arms back onto one outer assignment reds on the count before it reds on the order.It reads the emitted driver's source text and cannot establish that the text compiles. The only consumer that compiles it is a route run —
gunbc.source_root_eval_driver_seed_growthnames that boundary explicitly. Two questions, two instruments, which is why this PR's receipt is a route run's own build line rather than a green test. A source-text assertion passing on a driver that does not build is exactly how the defect above reached a pushed head.Two failure modes this PR is the receipt for
TestedTreeUnobservableis the arm working. The first two attempts at a compile proof appeared to succeed and had not run at all. The check was "doestarget/release/gunbc-emitted-closure-*exist" — which matched a binary from fifteen hours earlier and reported a compile proof one second after the route started. With that removed, the real cause surfaced: the route was refusing immediately withIt was right about the tree specifically: the worktree held the repair uncommitted and so corresponded to no commit. Supplying a plausible
GITHUB_SHAwould have been precisely the fabricated identity the clause rejects. The proof instrument now deletes stale artifacts before the run, watches for the producer's ownemitted crate built … exit_status=0 warning_count=0line, and reportsBINonly when its mtime is at or after the route start.The projection lesson, by symbol (
gunbc.rung_dropnative_lane_closure_walk_unkeyed_membership). Review 64576 caught an invented member in that row's population; review 64797 caught the same population's projection asserting a live consumer ofnative_lane_module_namedafter the symbol was deleted.claim_executor --required-regen's candidate tree contains no docs projection, so a docs-affecting change reportsfirst_generation_equal=trueand drifts silently — the authority row was fixed and the artifact was not.tools.docs_projection_gate regenis the instrument that covers it, and CI's auto-heal regenerated the line independently; the gate reproduces that heal byte-for-byte.Acceptance against the run that proved this head
The compile proof for this change was first taken on
4011bf9d, a commit branched before main's last two merges. The tree this PR carries differs from it in six paths, and each is determined on its own terms rather than by a class exemption:dag/gunbc/recurring_failure_mode/admitted_reclaim_charged_by_first_touch.dagdag/gunbc/recurring_failure_mode/gate_closure_narrower_than_the_closure_its_merge_governs.dagdag/gunbc/recurring_failure_mode/gate_population_covers_only_new_subjects.dagEach of the three is a new failure-mode row file: not named in any manifest, carrying no test declaration, and introducing no bare name that collides with an existing symbol. Their only structural effect is on the derived roster, whose import edge is unchanged. The remaining three paths — an
artifacts/BMC log, one regenerated line indocs/design-rung-drops.md, and adocs/probes/note — are outside the route's inputs entirely. Nothing undersrc/v1,src/v2, or any Cargo file differs.The independent check on that reasoning is that the emitted driver built from this head has the same sha256 as the one built from
4011bf9don another host: three builds, two hosts, one artifact.Receipt
tools.docs_projection_gate regenon this head — result reported in the thread as observedcargo test --release -p v1-compiler-tests --lib native_driver_cost— against a mirror verified to carry the change before the test ranclaim_executor --v2-native-routeon this exact head — the route's own emitted-crate build line,BINsha256, and mtime at or after the run's start🤖 Generated with Claude Code
https://claude.ai/code/session_013aZDLk2CxsCDznqn49Xhe8