Skip to content

The floor's non-verdict census reported 65 causes for a population with four: the cause was typed at the seam and thrown away - #9137

Merged
briansrls merged 5 commits into
mainfrom
session/valiant-lynx-227
Aug 25, 2026
Merged

briansrls merged 5 commits into
mainfrom
session/valiant-lynx-227

Conversation

@briansrls

@briansrls briansrls commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

The instrument reported the opposite of the fact

The required floor's non-verdict census, on main f9963a762 (run 32743601436):

[floor-known-red-causes] 65 distinct signature(s) across 142 non-verdict enrolled identity(ies)
[floor-known-red-causes] 18 × no declaration named 'srv3_install_hang_no_router_lease_ms' in this execution's loaded index (searched the modules
[floor-known-red-causes] 13 × no declaration named 'extdeps_cargo_build_module' in this execution's loaded index (searched the modules
[floor-known-red-causes] 11 × type error: atom_identity_hash requires exactly one string argument
[floor-known-red-causes]  5 × undefined variable: LocalInProcess
… 16 more rows, then nothing

Three defects, ordered by how hard each is to notice.

1. Silent truncation. causes.iter().take(20) with no note of what was dropped. The twenty printed rows sum to 93 of 142 identities; 45 further causes covering 49 identities simply vanish. This is ranked first on crisp-boar-716's argument, which is better than mine: a prose-keyed census is wrong in a way that shows — 65 causes for 142 rows invites the question. A silent truncation summing to 93 of 142 is wrong in a way that looks complete, and I read that line without noticing the rows did not sum. An experienced reader looked straight at it and did not see the shortfall.

2. The key is prose, and the prose embeds the missing NAME. known_red_runtime_error_causes keyed on the first twelve whitespace-separated words of the message, so no declaration named X and no declaration named Y counted as two causes. That is where 65 comes from. The population has about four. The number is an artifact of the key: it told every reader many roots where the truth is one root, many names, pointing them away from the single repair that closes most of the population.

3. No per-row cause at all. A row read ERROR in 33720ns. You could learn that 18 identities failed on one name and never learn which 18.

The root: a typed value destroyed at a seam, guessed back 26k lines downstream

v1_interpreter::InterpError is a closed 24-arm coproduct. At the witness boundary, run_claim mapped four variants to their own ClaimOutcome arms and flattened every other one:

other => ClaimOutcome::RuntimeError { message: format!("{other}") },

So the cause was known at the moment of routing, destroyed there, and partially reconstituted by word-slicing at the reporting site. cli_run.rs already condemns this exact pattern twice in its own comments — for TimedOut and for HostToolUnresolved, both repaired the same way, both explaining that a consumer partitioning on the outcome cannot see a difference the producer had in hand. This is the third instance, which makes it a producer rather than three defects.

The repair

gunbc.observation_ci_render gains CiWitnessRuntimeCause, twenty arms mirroring InterpError one-for-one and minting no vocabulary of its own. WitnessRuntimeCause in the seed is its mirror, under the byte-equality parity test CiWitnessVerdict already had.

The cause rides as the PAYLOAD of the error arm, not beside it. A separate cause parameter would make two invalid states writable — a PASSED row carrying a cause, an ERROR row carrying none — and both would then need a check. As the arm's payload, neither has a spelling: WitnessRuntimeError cannot be constructed without a cause, and no other arm has a field to hold one. That is §4b's structurally impossible rung instead of mechanically preventable, for the price of a field. (The brief asked for a printed field; this is stronger and was ruled the right move before it was built.)

The five variants that cannot reach the classifier are not folded into a neighbour. HostToolUnresolved, HermeticHostEffectRefused, EvalBudgetExceeded, WitnessWallBudgetExceeded and the pre-mapped EvaluationBudgetExceeded are consumed by earlier arms. All five map to MappedOutcomeEscaped — one arm, because all five share one remedy (repair the mapper) — a typed, countable diagnostic rather than silence.

The cap is printed, not raised, and printed whether or not it bit:

[floor-known-red-causes] listed=N listing_cap=20 not_listed=M not_listed_identities=K listed_identities=L

not_listed=0 is the load-bearing case: a drop notice that appears only when something drops requires the reader to know the field exists in order to miss it. Raising the cap to 65 would have fixed one run and left the same silence for the next.

The row now reads ERROR in 33720ns cause=no-such-variable — trailing and key-tagged, so a reader pairs identity with cause by key and never by column offset. That property is not decorative: my own first extraction over this log used grep -oE '//[^ ]*ERROR in', which cannot cross the floor's column padding, silently selected only long identities, and produced an inverted claim (9 rows reported as duplicated when the pattern had missed them) that reached a merge-ready PR as a high-priority alarm before I refuted it.

Evidence

Executed, .dag oracle — four new witnesses in observation_ci_render_witness_test.dag, all true.

Mutation-controlled, because four green witnesses establish nothing alone. Each mutant is caught by a different witness:

mutant result
cause field dropped from the error arm w_witness_claim_line_carries_the_runtime_cause and w_RED_two_causes… fail (2 of 4)
constant cause field (decoration) only w_RED_two_causes_do_not_render_the_same_row fails (1 of 3)
cause leaks onto PASSED rows only w_RED_non_error_rows_carry_no_cause_field fails (1 of 3)
restored all pass

The second is load-bearing: a renderer appending a constant cause= satisfies every other assertion. Without that one witness the decoration mutant ships green.

Executed, seed↔.dag parity — render_witness_claim_result_text_mirror_matches_seed_oracle passes: the seed mirror is byte-equal to the .dag oracle on all eight verdict arms, cause included.

Executed, end-to-end from a real interpreter throw — a fixture witness calling atom_identity_hash() with wrong arity, through claim_batch:

FAIL w_type_error_throws (runtime error [type-error]: type error: atom_identity_hash requires exactly one string argument)
PASS w_plain_pass

That is one of the four causes the measured population carries, classified from the live InterpError rather than from its prose.

Also run: cargo check -p v1-compiler --bins clean · cargo fmt --all --check clean · v1_src_dag_parse 3939 files parse-clean · gunbc compile on both changed .dag entries, 0 blocking errors · the six claim_executor expected-red/render tests pass.

What is NOT proven

THE FLOOR'S OWN CONSOLE LINE AND THE RE-KEYED CENSUS HAVE STILL NOT EXECUTED — INCLUDING ON THIS PR'S CI RUN. This is stated as an outstanding measurement rather than a caveat, because it is the one number the change predicts and three approvals are not a substitute for it.

The prediction, so it stays falsifiable: [floor-known-red-causes] N distinct cause(s) should fall from 65 to roughly four, and not_listed should read 0 — not because the cap moved (it is unchanged at 20) but because the distinct count now fits under it once the key stops embedding the missing name. If N comes back large, the key is still carrying something identity-shaped and the repair is incomplete.

Why it has not run, at either boundary:

  • Locally — --required-floor is OOM-killed in a session container (exit 137 at ~240s in strict-preparation, rss ~6.8GB, the documented ancestor-cgroup kill).
  • In CI — this PR's run (32786338570) refused in strict-preparation, so no witness executed at all. That refusal is main's, not this branch's: #9057 deleted four helpers in dag/gunbc/systemctl_show_read.dag's transport vocabulary and #9062 added 75 lines calling them, each green on a merge subject computed before the other landed. Verified by comparing this run against main's own run 32780728859 — four byte-identical diagnostics — and by confirming the last green main run d3bebd007 is an ancestor of the first red bc992dbe6f. Repair is ruled to MAIN RED: four symbols in dag/gunbc/systemctl_show_read.dag are referenced and defined nowhere (#9062); the whole fleet inherits it #9147; nothing here is a fix for it, and no file in this diff is involved.

What is proven is every layer either side of the floor: the .dag renderer produces the field, the seed mirror is byte-equal to it on all eight arms, and the classification runs end-to-end from a real interpreter throw. The floor's own rendering of it is measured by nothing yet, and this section stays as written until a run produces the counts.

Three of five throw-consumers still carry prose only and deliberately so: the witness-cost event payload (witness_cost_seed_failed_event, whose error: string crosses into .dag) and the discovery-path failure summary already carried the full message and lose nothing. The two changed are the ones that had no cause at all. Widening the other two is a follow-up with its own consumer check, not a free rename — scoped_run_observation.rs asserts on "runtime error:" prose, which is what makes that class of edit worth checking rather than assuming.

Two pre-existing defects found on the way, neither introduced here

cargo check -p v1-compiler --tests FAILS ON MAIN. Verified by execution on a clean origin/main worktree (6a264c3282) with an isolated CARGO_TARGET_DIR, so it is not a cache artifact:

error[E0063]: missing field `type_head_exposures` in initializer of `SymbolIndex`
  --> src/v1/stage0/src/cli_run.rs:40395:49

The site is under #[cfg(test)], so production bins build fine and the required run (parse · regen · floor) never reaches it. The Rust suite has not run in CI since 2026-07-11. Not fixed here — it is unrelated to this change and belongs to whoever added the field; naming it is the point.

A parity assertion was already red on main for the same reason. render_witness_claim_result_text_mirror_matches_seed_oracle asserted distinct.len() == 7 against an eight-arm table. Executed receipt: left: 8 right: 7, and the eight lines are pairwise distinct with or without the cause field. It is repaired here because this PR touches that table, and pinned to arm_count rather than to a new literal 8 — a count copied out of the fixture by hand is the second representation that went stale in the first place.

Scope

Output fidelity and the census key. required_floor_outcome_is_clean and every gating conjunct are untouched, and nothing changes which rows are emitted or counted — only the census map's key, two detail strings, and the row's trailing field. The .take(10) bounded sample in the partition-refusal path is the same truncation class and is left alone, named here rather than quietly changed: its comment shows a deliberate reasoned bound, and editing a refusal message is not this PR's subject.

gunbc.witness_runtime_cause_seed_growth carries the forward-freeze receipt for the three hand items added to v1_compiler.cli_run (+205/−28 there, +48/−5 and +7/−2 in the two bins), authored with the change rather than after a review found it missing. The seed_growth_admission roster prose is repaired in both directions — it was already missing anonymous_record_resolution_seed_growth_justification from #9089, which surfaced only as a conflict against this branch.

🤖 Generated with Claude Code

Brian Searls and others added 2 commits August 24, 2026 20:53
…flattening it to prose

InterpError is a closed 24-arm coproduct. At the witness boundary run_claim
flattened every arm without its own ClaimOutcome variant into
RuntimeError { message: String } via format!("{other}"), the console printed
identity and duration and dropped the message, and the floor's aggregate census
then reconstituted a guess by slicing the first twelve words off that prose --
a key that embeds the missing NAME, so `no declaration named X` and
`no declaration named Y` counted as different causes.

Measured on main f9963a7: 65 distinct "signatures" over 142 non-verdict
identities, for a population with about four actual causes, and the listing was
truncated at 20 rows with nothing saying so (93 of 142 identities printed).

The cause now rides as the PAYLOAD of the error arm on both sides, so a PASSED
row carrying a cause and an ERROR row carrying none have no spelling; the row
renders a key-tagged `cause=<token>` field; and the census keys on the token and
prints its own cap and drop counts on every run, including when nothing dropped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NKppTPqiuLDoivSYLBR6vj
# Conflicts:
#	dag/gunbc/seed_growth_admission.dag
#	src/v1/stage0/src/cli_run.rs
@gunbai-bot gunbai-bot Bot changed the title 119 witnesses reference existing declarations while declaring no import: the mechanical repair backlog blocking the non-verdict gate The floor's non-verdict census reported 65 causes for a population with four: the cause was typed at the seam and thrown away Aug 24, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 24, 2026 21:35
Brian Searls and others added 3 commits August 24, 2026 21:45
… actually lives

The 27 came from a grep that counted three HermeticEffectGround arms --
UnpublishedMockCase, NoMockResponse, FilesystemRemoval -- as peers of the
variant that nests them. The seed's exhaustiveness check refused those three
when they were briefly given cause arms, which is how the real number surfaced;
the prose in two of three places had already been written against the miscount.

The renderer's comment now also says the figure is illustrative: totality is
held by of_interp_error's exhaustiveness check, so a new interpreter arm fails
to compile rather than silently aging a sentence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NKppTPqiuLDoivSYLBR6vj
# Conflicts:
#	dag/gunbc/seed_growth_admission.dag
@briansrls
briansrls merged commit 881a5c6 into main Aug 25, 2026
1 check passed
@briansrls
briansrls deleted the session/valiant-lynx-227 branch August 25, 2026 00:23
gunbai-bot Bot pushed a commit that referenced this pull request Aug 25, 2026
Main gained witness_runtime_cause (#9137) while this branch carries
reference_closure_binder. Union is seven; both sides kept, per the rule
main's own note now states.

This file has conflicted on a roster union three times this evening, each
time because the prose listing is a second representation of
seed_growth_justification_roster(). Recorded that count in the note, since
the argument for deriving the listing is now a measurement rather than a
prediction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant