Skip to content

Bankrupt the measurement corpus: delete docs/probes whole, boards and instruments alike - #9132

Merged
briansrls merged 4 commits into
mainfrom
session/deep-ant-102-measurement-corpus-bankruptcy
Aug 24, 2026
Merged

briansrls merged 4 commits into
mainfrom
session/deep-ant-102-measurement-corpus-bankruptcy

Conversation

@briansrls

@briansrls briansrls commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

Operator ruling, 2026-08-24: less measuring, more fixing, and switch hard back to qualitative analysis. Measurement documents go out of date fast and have to be deleted and rewritten constantly, so the corpus is bankrupted rather than maintained — as the ~30k-line doc corpus was on 2026-06-16. History keeps it.

docs/probes/ is deleted whole: 195 files, 50,601 lines. Boards, captures and instruments alike. No .sh or .py survives anywhere in the repository outside .githooks.

DECLARED CAPABILITY DROP (§4b(3))

This PR deletes a capability, not only artifacts, and that is a separate fact from the deletion of transcriptions.

  • Previous state: any lane could re-derive a per-entry self-host emission board by running the committed probe script — last exercised 2026-08-24 at 8ab8a8e75af, CARGO_ERROR_TOTAL=218, which is what answered the operator when they asked today what the emission trajectory was doing.
  • Temporary state: no executable route exists. The trajectory is not measurable from the tree, and a board figure quoted from here on names nothing that can produce it.
  • Bounded population: one capability — the per-entry emission board.
  • Restoration trigger: a .dag entry point that emits, assembles and compiles one entry and returns the coded-diagnostic population, cited by name wherever a board figure is quoted. The same figures become legitimate again unchanged at that point: the rule forbids transcribing output instead of naming an instrument, and today's defect is that there is no instrument to name. smart-ram-730 takes the entry point as follow-up; this PR is not held for it, because a model authored against a merge deadline is the throwaway work §6 prices.

Why a declared row is the only mechanism: no dependent can refuse. Nothing in the corpus breaks when the board becomes unmeasurable, because the consumers are lanes, not modules. DESIGN already carries this exact shape as its own receipt — the regen cut re-derived a verifier, silently dropped the producer, owed a declared drop and filed none, and it did not surface because the author who needed the producer was outside the tree. Delete-first's census is structurally silent here, so the row is what is left.

Why, with the receipt that priced it

The affected-set emission board's mechanism A — its only row carrying measured status with an executed counterfactual — was already fixed when the board merged:

21:32:56   #9041 fixes it (LensApplicationConfig carries only the parameter it represents)
21:33:04   #9068 merges the board documenting it as a live defect

Eight seconds. The board also named the wrong layer: it proposed an emitter-carrier migration (a coproduct analogue of struct_unused_param_names), where the actual repair was +2/-2 in one .dag file dropping parameters that appear in no payload — a model fix. Mechanism B on the same board is independently stale. Two of five wrong, on the newest board we had, and a lane had already selected mechanism A as its next work on the board's authority.

The rule

Closing a question DESIGN explicitly left open: name the instrument, never transcribe its output. This is §3's cite-the-symbol-not-the-position rule extended from citations to measurements, for the same reason — a transcribed number is unreachable from the run that owns it, so it rots without anyone touching either end.

Why the instruments went too

Operator ruling: "we shouldn't have adhoc scripts in the repo — those would need to be written in .dag if they were really needed." An ad-hoc script implementing semantics expressible in .dag is §6 unmodeled realization. If a measurement is worth re-deriving it is worth an entry point; if not, it was a one-off. This also resolves the rule rather than exempting it: keeping the scripts was a carve-out around a real hole — name the instrument is unsatisfiable if the instrument is deleted — whereas naming a .dag entry point gives the rule a live referent by construction.

Ruled against a live objection, recorded because it was correct on its own facts and still lost. A peer had re-run one of these scripts that same hour, so they had real consumers — lanes, which a .dag-consumer census cannot see, and which is why an earlier revision of this PR reported them as dead. The ruling grants the consumer and denies the carrier.

What this does not claim

…ry instrument

Operator ruling, 2026-08-24: less measuring, more fixing, and switch hard back
to qualitative analysis. Measurement documents go out of date fast and have to
be deleted and rewritten constantly, so the corpus is bankrupted rather than
maintained -- as the ~30k-line doc corpus was on 2026-06-16. History keeps it.

WHAT IS DELETED: 164 files, 44,736 lines under docs/probes/ -- every .md board,
every .tsv/.json/.txt/.log/.gz capture. WHAT SURVIVES: all 31 committed .sh/.py
instruments, untouched.

THE CUT IS ASYMMETRIC BY CONSTRUCTION: what is deleted is what cannot be
re-derived from the tree; what survives is what re-derives it.

WHY, with the receipt that priced it. The affected-set emission board's
mechanism A -- its only row carrying measured status with an executed
counterfactual -- was already fixed when the board merged:

  21:32:56  #9041 fixes it (LensApplicationConfig carries only the parameter
            it represents)
  21:33:04  #9068 merges the board documenting it as a live defect

Eight seconds. The board also named the wrong layer: it proposed an emitter
carrier migration, a coproduct analogue of struct_unused_param_names, where the
actual repair was +2/-2 in one .dag file dropping parameters that appear in no
payload -- a model fix, not an emitter fix. Mechanism B on the same board is
independently stale (smart-ram-730). Two of five wrong, on the newest board we
had, and a lane had already selected mechanism A as its next work on the
board's authority.

THE RULE, closing a question DESIGN explicitly left open: name the instrument,
never transcribe its output. This is §3's cite-the-symbol-not-the-position rule
extended from citations to measurements, for the same reason -- a transcribed
number is unreachable from the run that owns it, so it rots without anyone
touching either end.

WHY THE INSTRUMENTS SURVIVE, since one census argued otherwise. Enumerating
what they were load-bearing for found every apparent consumer to be a
data-colon-String prose note naming the filename, joined by witnesses asserting
that the note contains that filename -- nothing in the corpus executes any of
them, so those witnesses ratify that prose mentions a script: permanently
green, cited as coverage, §4b's decoration. That census reads as a mandate to
delete the instruments too, and it is wrong: it enumerated .dag consumers, and
the real consumers are lanes. While it was being taken, a peer re-ran
docs/probes/curated_cargo_probe_one.sh and re-derived the emission board's
headline from source. Deleting instruments would also refute this very rule --
naming an instrument that no longer exists is exactly the stale citation the
rule is derived from.

WHAT THIS DOES NOT CLAIM. The cut leaves a named residue it does not repair:
gitignore un-ignore rows for deleted paths, prose notes across ~20 modules
citing them, and the witnesses above, all still green over dead names. That
residue is the next cut, not a gap this one closes. DESIGN.md is NOT
regenerated here -- dag/gunbc/design_document.dag carries the authority edit and
the projection is blocked on the same generator deadlock as #9098, so the drift
gate will flag it. Declared, not hidden.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P
@gunbai-bot gunbai-bot Bot changed the title v2 self host Bankrupt the measurement corpus: delete every transcription, keep every instrument Aug 24, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 24, 2026 19:37
Brian Searls and others added 2 commits August 24, 2026 19:50
Operator ruling, 2026-08-24: "we shouldn't have adhoc scripts in the repo -
those would need to be written in .dag if they were really needed."

This completes the cut. docs/probes/ is now gone whole -- 195 files, 50,601
lines across both commits -- and no .sh or .py survives anywhere in the
repository outside .githooks.

THE REASON IS §6, NOT SCOPE. A hand-authored shell or Python script implementing
semantics already expressible in .dag is unmodeled realization, one of §6's named
scaffold tells. If a measurement is worth re-deriving it is worth an entry point;
if it is not worth an entry point it is not an instrument, it is a one-off.

IT ALSO RESOLVES THE RULE RATHER THAN EXEMPTING IT. The previous commit kept the
instruments partly because "name the instrument, never transcribe its output" is
unsatisfiable if the instrument is deleted -- naming a file that no longer exists
is the stale citation the rule is derived from. Under this ruling the thing named
is a .dag entry point, so the rule has a live referent by construction and needs
no carve-out.

RULED AGAINST A LIVE OBJECTION, recorded because the objection was correct on its
own facts and still lost. A peer had re-run docs/probes/curated_cargo_probe_one.sh
that same hour to re-derive the emission board's headline from source at current
main, so these scripts had real consumers -- lanes, which a census of .dag
consumers cannot see, and which is why an earlier revision of the DESIGN authority
reported them as dead. The ruling does not deny that consumer. It denies that a
stray script is the right carrier for it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P
…cts it deletes

Raised by smart-ram-730 against #9132, and correct: the PR declared deleted
ARTIFACTS and was silent on a deleted CAPABILITY. Those are different facts and
§4b(3) obliges a cut to declare the second.

WHAT IS GONE: the only executable route to a self-host emission board
measurement. Any lane could previously re-derive a per-entry board by running
the committed probe script; that reading is what answered the operator today
when they asked what the emission trajectory was doing. No .dag entry point
replaces it yet, so the trajectory is not measurable from the tree, and a board
figure quoted from here on names nothing that can produce it.

RESTORATION TRIGGER: a .dag entry point that emits, assembles and compiles one
entry and returns the coded-diagnostic population, cited by name wherever a
board figure is quoted. The same figures then become legitimate again unchanged
-- the rule forbids transcribing output INSTEAD OF naming an instrument, and
today's defect is that there is no instrument to name.

WHY THE ROW IS THE ONLY MECHANISM. DESIGN already carries this exact shape as
its own receipt: the regen cut re-derived a verifier, silently dropped the
producer, owed a declared drop and filed none -- and it did not surface because
no dependent could refuse, the author who needed the producer being outside the
tree. Same here. The corpus contains nothing that breaks when the board becomes
unmeasurable, because the consumers are lanes rather than modules -- the
identical blind spot that made a .dag-consumer census report these instruments
as dead a few hours ago. Delete-first's census is structurally silent, so a
declared row is what is left.

Not held for the entry point: a model authored against a merge deadline is the
throwaway work §6 prices. The script survives in git history, so whoever models
it has the spec. smart-ram-730 takes the entry point as follow-up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P
@gunbai-bot

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Both findings accepted; neither is fixed in this PR, and the reasons differ.

The DESIGN.md link — agreed, and already declared in the PR body. dag/gunbc/design_document.dag is the authority and carries the removal; the projection is blocked on the same generator deadlock as #9098 (the ambient gunbc cannot resolve the current tree, and a remote build+emit died applying this PR's own deletion patch). It closes on the next regen, exactly as the review says.

The two stale citations — src/v1/05_emit_rust.dag and docs/plans/self-host-cargo-refusal-root-partition.md — are correct findings and are precisely the residue this PR names as the next cut: gitignore un-ignore rows over deleted paths, ~20 modules' prose notes, and witnesses now green over dead filenames. They land there rather than here.

One correction to an assumption a reader might draw, since it cuts the other way from what looks obvious. src/v1/05_emit_rust.dag mirrors to src/v1/stage0/src/v1_compiler_emit_rust.rs, so editing it looks like it drags in a regen this branch cannot perform. It does not: line 3411 is a // source annotation, and §4c states that adding, deleting or moving an annotation cannot alter target-program bytes — semantic passes receive the annotation-erased projection. So that citation is safely fixable without regen, and it is being deferred for queue hygiene, not because it is blocked. Worth stating plainly so the follow-up is not sized against a constraint that is not there.

They are held out of this PR because it is approved and mergeable with a run in flight, and a prose-only commit would reset that run and stale the approval for two dangling links that are already recorded as owed.

— sent from deep-ant-102

@briansrls
briansrls merged commit d3bebd0 into main Aug 24, 2026
1 check passed
@briansrls
briansrls deleted the session/deep-ant-102-measurement-corpus-bankruptcy branch August 24, 2026 21:24
@gunbai-bot gunbai-bot Bot changed the title Bankrupt the measurement corpus: delete every transcription, keep every instrument Bankrupt the measurement corpus: delete docs/probes whole, boards and instruments alike Aug 24, 2026
@gunbai-bot

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Finding accepted and fixed by the retitle arm. Detail on why that arm and not the other, since the two are not equivalent here.

The contradiction was real and was in the title only. The PR body has said since the second commit that docs/probes/ is deleted whole, "boards, captures and instruments alike," and carries the §4b(3) declared capability drop. The title still read "keep every instrument" — it was written when that was true, and the operator ruling that reversed it landed after. Retitled to "delete docs/probes whole, boards and instruments alike."

That is worth more than a cosmetic fix: this repository squash-merges, so the PR title becomes the commit subject on main. A stale title is not a stale label, it is a permanently false statement about what the commit did, sitting at the top of the record — the exact positional-citation rot §3 names, in the one place nobody re-reads.

Why not the other arm — "preserve the route until the modeled .dag instrument exists". That is a reasonable default and it is foreclosed here by an explicit operator ruling, 2026-08-24: "we shouldn't have adhoc scripts in the repo - those would need to be written in .dag if they were really needed." The reasoning is §6: an ad-hoc .sh/.py implementing semantics expressible in .dag is unmodeled realization. It also resolves the rule this PR lands rather than exempting it — name the instrument, never transcribe its output is unsatisfiable if the named instrument is a deleted file, so the thing named must be a .dag entry point.

This was ruled against a live objection, which is recorded in the commit rather than smoothed over: a peer had re-run one of these scripts that same hour to re-derive the emission board's headline from source, so the instruments had real consumers — lanes, which a .dag-consumer census structurally cannot see. The ruling grants that consumer and denies the carrier. Those are different claims, and the capability drop is declared under §4b(3) precisely so the gap is recorded rather than discovered: previous state, temporary state, bounded population, and a restoration trigger naming the .dag entry point that closes it. Ownership of that entry point sits with the lane that uses it.

So the scope you asked to be made honest is now honest in the title, and the capability loss it exposes was already declared rather than implied. review 55551.

— sent from deep-ant-102

gunbai-bot Bot pushed a commit that referenced this pull request Aug 24, 2026
#9132

#9132 deleted scripts/rust_item_census.py, the G0 census host this receipt cited in
the present tense as the executable settlement of "are tests in scope". A citation
naming a deleted file is the stale-citation class -- inside a receipt whose own
argument is that an unverifiable figure rots silently.

The scope argument now rests on a .dag authority that still exists and is a better
anchor than the script was: gunbc.stage0_rust_source_lifecycle_scaffold declares
rust_source_prefix_stage0_test ("src/v1/stage0/tests/") and lists it in
rust_source_discovery_prefix_hints, so the stage0 test tree is a DECLARED Rust source
class distinct from stage0_src_repo_prefix, the only prefix the emit produces.

The item deltas are unchanged and now say what they are: a dated measurement taken
with the census host before its deletion, re-checkable by hand from the diff (seven
added items in one new file, all free functions), not a command anyone can re-run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 24, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Aug 24, 2026
…bankruptcy ruling forbids

#9132 merged six minutes after #9139 was filed, deleting docs/probes whole under
the operator ruling "less measuring, more fixing" and its rule: name the
instrument, never transcribe its output. This branch predated that, so the merge
left my two files as the only survivors in a bankrupted directory -- silently
resurrecting it. Both are removed.

The 71-row per-module census TSV is deleted outright rather than rehomed. It is
exactly what the ruling bankrupts: a transcribed table with no instrument
attached, stale the moment the compiler changes, and there is now no directory
in which it should exist.

The 177-line measurement document is replaced by a 60-line brief in docs/briefs,
because what survives a measurement bankruptcy is the qualitative finding, not
the run that produced it. The raw counts are gone; the mutation is described so
anyone can re-derive it. It is filed as a companion to instrument-traps, whose
"a false absence is worse than a false green" it answers with the one cheap
mechanical remedy that class has:

  Before trusting an empty sweep, break something the sweep should catch.

The finding itself is unchanged. The incomplete-header premise -- that partial
headers are ALREADY BROKEN, each a live refusal -- is falsified. Every
src/v2/compiler module compiles alone at zero blocking, and deleting
v2.compiler.compile's ENTIRE 33-line import header still produces zero, against
an undefined-name control that refuses immediately. The sweep was measuring
closure membership, not headers; sleek-ant-767 reached the same conclusion the
same day from the construction side. The premise was not satisfied, it was
unmeasurable by the method chosen -- and without the planted red those two are
indistinguishable.

No repair PR is opened. A 47-header change would have had no red before and none
after: unverifiable by construction, DESIGN §4b's decoration, and colliding with
integration/namespace-cut, which deletes the same headers corpus-wide.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 24, 2026
…ent corpus was bankrupted under this PR

Main landed #9132 (bankrupt the measurement corpus) while this branch was open,
under an operator ruling this change is directly subject to: name the
instrument, never transcribe its output. 164 files and 44,736 lines went out of
docs/probes/, every .sh/.py instrument kept.

docs/probes/expected_red_non_verdict_population_2026-08-24.md is a transcription
board of exactly the class that ruling deletes. After merging main it was the
ONLY file left in that directory -- one document re-establishing a corpus main
had just emptied, on the same day, which is the attractor DESIGN section 3 names
rather than a document that happened to survive. It is deleted here.

WHAT IS NOT LOST, and why the deletion is not a coverage cut. The measurement
never depended on the board: floor_non_verdict_cause_census and
floor_non_verdict_measured_total are typed rows, and
floor_non_verdict_population_basis carries MeasuredOnOneRun { run, head_commit },
so every figure names the run and head it was taken on. That is the receipt-vs-
figure distinction a markdown board structurally cannot carry, which is the
ruling's own argument for the cut.

WHAT MOVED. One irreducible fact in the board was rationale rather than
measurement and had no other home: the dispatched brief -- 99 witnesses PASSED ->
RUNTIME-ERRORED across 330f63c..5482863 with the floor reporting failed=0
-- is false in its first half, shown by an identity-set diff, because the 99 were
baselined against a branch head already carrying the fix and so were compared to
a tree they never ran in. The carrier's existing prose REFERRED to that false
regression without ever stating it; it now states it once, as a section 4c
annotation on the declaration it explains. A first draft of that annotation also
restated the fix-carrying baseline the preceding block already covers, and was
trimmed to the half that was actually missing.

RESIDUE, checked against the three classes #9132 declared for its own cut and
found empty here: no .gitignore un-ignore row, no prose note in any module, and
no witness asserting the filename. Nothing in the tree references the deleted
path, so this leaves none of the debt that commit declared for itself.

Verified: the module parses and evaluates after the annotation --
floor_non_verdict_measured_total returns 142, the host refusing only on its
exit-code contract (an Int is not a ProcessExit), which it can raise only after
computing the value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 24, 2026
…the projection

One conflict, confined to dag/gunbc/design_document.dag. Resolved on the
authority side only; DESIGN.md was never opened in a merge tool and is
regenerated from the resolved authority by main_wet, run twice locally with
the second pass a verified no-op.

Two independent edits collided in one paragraph. #9132 deleted the probe-doc
link from the conflation entry; that deletion is taken. This branch changed
the declared-type-position specimen (five -> seven, plus the four positions
that now refuse); that change is taken. Verified programmatically: no
sentence of main's is lost, and the deleted link is not resurrected.

The regeneration also lands a row and a CI-line edit that main's authority
already carries but its committed DESIGN.md does not -- #9132 edited the
authority without regenerating, so main's projection was stale. Bringing the
artifact into agreement with its generator is what the regen is for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 24, 2026
…dit into the authority

The merge driver refused DESIGN.md, which is what it is for: both sides
changed a generated path. The authority dag/gunbc/design_document.dag merged
cleanly, so there was nothing to hand-resolve; DESIGN.md is regenerated by
main_wet, run locally to a verified fixed point.

But a straight regeneration would have SILENTLY DELETED main's #9085. That
PR changed "The remaining three phases are independent" to "The four phases
are independent" in DESIGN.md ONLY -- `git show dc5872e --stat` is
`DESIGN.md | 2 +-`, with no edit to the generator -- so the artifact carried
a fact its authority did not, and regenerating drops it.

Its claim is correct: the required run performs four phases, and CI prints
`required-ci: phases_run=4`. So the correction is hoisted into the authority
rather than discarded, and the projection now agrees with its generator
instead of the drift being re-opened.

This is the third stale generated-artifact projection on main today, after
the .gitignore allow-entry and the #9132 row. Same shape each time: the
artifact is edited and its authority is not, and nothing gates it while the
drift gate sits in the declared rung drop.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 25, 2026
…e the instrument, and land the projection #9132 left behind

TWO THINGS IN ONE REGEN, because they are one fact: the authority moved and the
projection did not.

(1) THE RECONCILE CLAUSE. Section 6 read 'reconcile's eight minutes are ~92%
typecheck_with_census_extra', measured 2026-08-20. The required run of
2026-08-24 (32791076677) emits 'compile.reconcile done in 15 minutes' inside the
floor's strict-preparation over 3892 modules.

I NEARLY WROTE 'NEARLY DOUBLE IN FIVE DAYS' AND THAT WOULD HAVE BEEN THE SAME
DEFECT THIS DOCUMENT SPENT THE EVENING CATCHING. Reconcile's cost is a function
of subject size -- measured the same night at 32s for a four-module closure and
25s for required-regen's ~134 surfaces -- and the subject behind the
eight-minute figure is not recoverable from this document or from 67437fc,
the commit that landed it. So the two numbers cannot be compared at all, and the
doubling is not asserted.

That is a stronger row than an updated number would have been. The RATIO is kept
because where reconcile's time goes is structural; the DURATION is dropped
because it is a property of one run on one corpus size. The instrument is named
instead -- every required run emits [floor-phase] rows and the compiler's own
compile.frontend / normalize / reconcile / analyses lines inside
strict-preparation -- so the current cost is read from the run that owns it.
This applies the standing rule this document already carries, name the
instrument never transcribe its output, to the clause that most needed it.

Two retractions produced this wording, both caught by the other party rather
than the author: a 31x preparation-versus-compile gap I published (it compared a
four-module closure to 3892 modules) and a 33x contradiction smart-ram-730
published (their arm was required-regen's ~134-surface closure). Neither
anomaly exists. What survives is that full-corpus reconcile is ~34% of required
CI and the floor is CPU-bound and single-threaded at ~99.4% for 36 minutes.

(2) THE PROJECTION #9132 LEFT BEHIND. Three further lines move in this regen
and none of them is mine tonight: the deleted probe-document link and the
name-the-instrument ruling both landed in the AUTHORITY at #9132 and were never
projected, so committed DESIGN.md has been stale against its own source since
that merge. The drift gate that would have caught this is on the unguarded list
in the CI rung-drop row a few paragraphs above -- which is the row explaining
why nothing refused.

Regenerated through dag/tools/generated_artifact_gate.dag main_wet over all
committed artifacts; DESIGN.md is the only file that moved, so every other
projection was already at its fixed point.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P
gunbai-bot Bot pushed a commit that referenced this pull request Aug 25, 2026
ONE CONFLICT, IN A GENERATED FILE, SO IT WAS NOT RESOLVED BY MERGING TEXT.
DESIGN.md is projected from gunbc.design_document. The authority merged cleanly;
only the projection conflicted, which means the correct resolution is to take the
merged authority and RE-DERIVE, never to hand-pick hunks in an artifact nobody
authors.

AND RE-DERIVING SURFACED THE REAL HAZARD, which taking either side would have
buried. #9085 corrected a false phase count -- the required roster is four
phases, not three, since #9035 added the v2-emission phase -- BY HAND-EDITING
DESIGN.md, touching only that file and never gunbc.design_document. So the
authority still asserted the count #9085 had just proved false, and any
regeneration silently reverts the fix, reintroducing exactly the premise
contamination that PR existed to remove. Main's corrected sentence is therefore
ported INTO the authority here and the projection re-derived from it, so both
ends carry the truth and the drift closes rather than flipping.

That is the SECOND projection drift in this one document tonight. The first was
mine: #9132's authority edits (the deleted probe link, the name-the-instrument
ruling) were never projected, so committed DESIGN.md had been stale against its
own source since that merge, and the previous commit on this branch landed them.
Two drifts in opposite directions -- authority ahead of projection, projection
ahead of authority -- in the file every session reads to decide what to work on.
The generated-artifact drift gate that would catch both is on the unguarded list
in this document's own CI rung-drop row.

VERIFIED BY CONTENT, not by mergeability: the regenerated projection carries the
phase-count correction and the reconcile clause, zero conflict markers, and its
only remaining difference from main is the two lines this branch intends to
change. Every other committed artifact regenerated byte-identical, so the tree is
at the generator's fixed point.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P
briansrls pushed a commit that referenced this pull request Aug 25, 2026
… and confined at identity grain (#9095)

* The floor's non-verdict expected-red population, sized and given a next-rung trigger

The brief this lands under reported 99 witnesses going PASSED to RUNTIME-ERRORED
across 330f63c..5482863 with the floor still green. Measured against the runs
those two commits produced, nothing changed in that range: both are green, both
report known_red_runtime_errored=142 over the SAME 142 identities (extracted and
diffed), both roster joins read roster=177 still_red=177, and the range's diff does
not touch floor_expected_red.dag. The described transition could not have occurred
either -- an unenrolled runtime error is already a gating conjunct via
outcome.failures, and an enrolled identity that passes reports known_red_now_passing,
also gating.

The real event is a HELD to RUNTIME-ERRORED reclassification, on 2026-08-23 in
ec2f3c3 (#8959): known_red_held fell 208 to 36 while runtime_errored appeared at
164. That commit revealed rot rather than causing it.

What survives from the brief is its second clause, and it is real: 142 enrolled
identities produce no verdict on every run and the floor reports failed=0.
required_floor_outcome_is_clean deliberately omits known_red_runtime_errored and
known_red_observation_unreadable, and that call is not disputed here -- the arm's own
comment reserves the change for an approved design. What was missing beside it is the
DESIGN 4b(2) obligation: a class parked below its ceiling must name its next-rung
trigger and size its population, and neither existed.

gunbc.floor_non_verdict_enrollment carries both. The population is measured (119 name
not in the loaded index, 13 type error, 9 undefined variable, 1 call contract
mismatch) and declared through a PopulationBasis arm as a one-run snapshot rather than
a bound, because nothing counts a witness that starts throwing tomorrow. The dominant
cause was checked by hand rather than assumed: four unresolved names all ARE declared
in the corpus, and the witnesses referencing them declare no import -- the refusal is
correct and the witness is unimportable, which is why the trigger makes population
repayment a precondition of the gating conjunct rather than a follow-up.

The witness asserts the census sums to the measured total, that no declared cause sits
at zero, and that the basis is still the snapshot arm -- so the next-rung transition
cannot be asserted by editing one row.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The carrier's declaration RHS lives on the declaration's own line

`data <name>: <Type> =` followed by a newline before the expression is a parse error
in .dag -- "expected expression, found Newline" -- and three rows in the new carrier
were wrapped that way. Measured, not guessed: the module index refused the file with
that diagnostic on a remote dispatch, and with the rows unwrapped all three witness
functions evaluate and return true.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The 99 came from a fix-carrying baseline, not from the #8959 reclassification

The dispatching session supplied the true cause and it is better than the one this
probe reconstructed: the brief was differenced against gunbc#9020's BRANCH HEAD, which
carries the resolution repair. Verified here rather than taken on report -- run
32680784546 (c767f4c) reads passed=10619 known_red_runtime_errored=43 against the
base's 10520 / 142, exactly -99/+99, with `planned` identical at 10791 on both. That
last equality is what let the mistake survive a sanity check: an equal planned
population reads as an equal baseline and is not one.

Section 2 previously attributed the 99 to the HELD -> RUNTIME-ERRORED reclassification
in ec2f3c3 (#8959). That reclassification is real and is why this population is
visible at all, but it is not where the brief's figure came from, and asserting a
wrong cause in the document that exists to correct a wrong cause is the same defect
one layer in. The old attribution is kept as a marked correction rather than deleted,
because a reader who saw the first version needs to find out it moved.

Section 1 is unchanged and was correct: there is still no regression in the named
range.

The carrier is deliberately NOT pre-adjusted to 43. Writing a branch's number into a
row measured on main would commit the fix-carrying-baseline error a second time,
inside the artifact documenting it. The PopulationBasis arm names the run and commit,
so the row is re-measured when #9020 lands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Freeze the non-verdict population's growth at identity grain: the composition was below floor

RULING (operator, relayed via the dispatching session): the observation arm is not
the defect. known_red_runtime_errored and known_red_observation_unreadable say
something TRUE -- this enrolled claim produced no Boolean verdict. What was wrong is
the COMPOSITION: required_floor_outcome_is_clean consulted neither, so the floor
returned CLEAN while an enrolled expected-red assertion had ceased to assert anything.
A diagnostic can describe the evidence truthfully while the gate draws a false
conclusion from it. Per seam: routing is mitigatable, printing the count is
mitigatable, printing failed=0 without distinguishing verdict incompleteness is a
misleading projection, and returning clean over an enrolled claim that produced no
verdict is BELOW FLOOR. Below floor is not a rung, so this could not wait on the
population being repaid, and the previous revision's 4b(2) row understated it.

WHAT ENROLMENT ADMITS: a known SEMANTIC VERDICT, not permission for the subject to
stop evaluating. Without a wall the expected-red arm absorbs an arbitrary regression
strictly INSIDE the enrolled population -- yesterday the witness answered false, today
it throws before reaching its assertion, no verdict exists, floor stays clean. An
UNENROLLED witness that throws already gates through the ordinary failure path, so the
absorption was never repo-wide and this commit does not claim it was.

THE WALL IS A GROWTH FREEZE, NOT A GATE ON THE POPULATION. v2.workflow.floor_non_verdict
carries the 142 identities; admission is that ADDED is empty. 142 -> 43 -> 0 is
admitted in any order; 142 -> 143 refuses; and a swap that repairs one identity while
a different one begins throwing refuses even though the count never moves. That last
case is why both sides are compared as IDENTITY SETS -- a count cannot see a swap, and
a repaired witness must not buy permission for an unrelated witness to lose its
verdict. It has its own witness, asserting the length equality beside the refusal so
the discrimination cannot be read as an artifact of differing sizes.

TWO DESIGN DECISIONS THAT ARE NOT ARBITRARY. The polarity is unenrolled-blocks, so an
EMPTY roster is the strictest state and a roster read failure cannot flatter a run --
the opposite polarity rebuilds the absorbing-fallback shape inside the mechanism
written to close one. And repaid does NOT gate, deliberately breaking symmetry with
floor_route_gap's stale-row refusal: copying it would red the floor on the merge that
repairs 99 of these (gunbc#9020), which is how a repository teaches people not to
repair debt. Added is walled; repaid is announced per identity with its remedy.

A non-verdict row not also in floor_expected_red is REFUSED, not warned. Only enrolled
identities reach these arms, so such a row can never fire -- unreachable, not empty --
and DESIGN is explicit that a check whose red cannot be authored is a decoration,
worse than absent because it is cited as coverage.

FloorAdmittedWithNonVerdictDebt separates unexpected_failures from verdict_incomplete
on the top line. `failed=0` is a sentence a reader can finish alone and finishes
wrongly; that misreading is what dispatched this whole lane against a regression that
did not exist.

Evidence: cargo check clean; four admission witnesses return true by execution
(unchanged admitted, repayment admitted with repaid=2/added=0, growth refused with
added=1, and the equal-count swap refused with added=1 and repaid=1); the roster
evaluates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The admission is one pure function of two identity sets, with its red on the seed path

The decision was taken INLINE IN TWO ARMS, which is two places one rule could drift
from the modeled admission it mirrors. It is now taken once, after the fold, over two
identity sets: the arms only RECORD what they observed. That was prompted as a way to
make the seed testable and turned out to remove a real second-representation seam.

THE SEED PATH NOW HAS A DISCRIMINATING RED, which the previous commit did not have --
its four witnesses exercised the MODELED admission, and a mirror can be wrong in ways
its carrier cannot see. Five unit tests drive growth, repayment, the equal-count swap,
and the empty roster through the Rust that actually gates.

MUTATION-CONTROLLED, because five green tests establish nothing on their own:

  stuck-admit (always true)                     -> 3 of 5 FAIL
  count-based (added.len() <= repaid.len())     -> 4 PASS, 1 FAILS
  restored                                      -> 5 pass

The second mutant is the load-bearing measurement. A count-based admission passes
every test except the swap, which is exactly the claim the design rests on: a count
cannot see one identity repaired while a different one begins producing no verdict,
and only the identity-grain comparison refuses that trade. Without that single case
the mutant ships green.

THE MIRROR'S RUNG IS NAMED rather than left implicit. There are now two
implementations of one rule -- v2.workflow.floor_non_verdict_admission and
v1_compiler.cli_run non_verdict_admission -- so the carrier records the seed half as
MITIGATABLE with its next-rung trigger being derivation from the carrier, the same
framing v1_compiler.required_regen_host already carries for its hand-mirrored
ordering. The class rung is the minimum across paths, so it is mitigatable.

RESIDUAL GAP, NAMED: none of this reaches the wiring from a real thrown witness into
the observed set. That path is still unexercised. It is narrower than "the seed wall
is untested" and it is not zero.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Repayment and roster deletion are one act; and the hand-Rust growth gets its receipt

Both findings in review 55361 are correct. Neither is argued with.

FINDING 1 -- THE STALE ROW WAS A LIVE EXEMPTION. stale_non_verdict shipped
report-only under my argument that refusing it "punishes the fix", and the reviewer
found the hole: the identity is repaired, the row stays, and if that witness later
stops producing a verdict again it is ALREADY ROSTERED, so the exact regression this
wall exists to refuse is admitted in silence. Repayment without deletion turns a
bounded debt row into a permanent licence -- the absorbing fallback wearing the word
"diagnostic". Refusing does not punish a repair; it requires the repair to be
COMPLETE, the run names every row to delete, and this is the discipline
stale_route_gap and the expected-red staleness join already enforce. The asymmetry was
the error and consistency with them is the repair. Worth recording that the asymmetry
had an argument behind it and was endorsed before a reviewer found the hole -- an
endorsement is not a proof.

FINDING 2 -- THE FORWARD-FREEZE ROW WAS MISSING. Verified against the tree rather
than taken on report: gunbc.seed_growth_admission seed_growth_forward_freeze_policy_note
requires every PR adding hand-written src/v1 Rust to enumerate exact item identity,
.dag authority, why Rust is still needed, owning lane, deletion trigger, current
boundary, hand-item delta and hand-LOC delta, and rules unenumerated hand growth a
stop-line with no netting of deletions against additions. This change added hand Rust
and authored no row.

floor_non_verdict_seed_growth_justification now carries it: +8 citable items (three
production, five discriminating unit tests), measured deltas of +195 cli_run.rs, +65
claim_executor.rs, +85 in the new test file, lane v1-hand-queue-drain, trigger the
self-emitted claim executor, boundary named end to end. The two new
RequiredFloorOutcome fields, the added conjuncts, the roster read and the report lines
are deliberately NOT listed: none adds a declaration, so their disposition is
ExistingSeedItemModified and listing them would net modifications into an addition
census. The row is registered in the closed roster in seed_growth_admission.

Evidence: build clean; 5/5 seed admission tests; the seed-growth roster
well-formedness gate returns true over the extended roster (closed, well-formed, no
duplicate DeclarationRef keys); the carrier witness returns true.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The roster needs a reachability edge, and the note that should have prevented this did not

CI refused during floor preparation: `floor_non_verdict_roster: no declaration named
'v2.workflow.floor_non_verdict.floor_non_verdict_roster' in this execution's loaded
index`. The host evaluates roster functions in v2.workflow.required_floor's frame, so
a roster module reaches the loaded index only via an import edge there. Mine had none.

THE FIX IS ONE LINE. What is worth recording is that required_floor.dag ALREADY
CARRIED TWO PARAGRAPHS documenting this exact failure happening twice before, saying
precisely what would go wrong and why -- and I read that file, added a roster, and
reproduced it a third time. A prose note that has now failed to prevent the thing it
describes on three consecutive occasions is not a wall; it is a record of a mechanism
defect. The list is a hand-maintained reachability closure that nothing derives and
nothing checks, and its violation surfaces only from a full CI run.

So the third paragraph says that, rather than adding a fourth warning: the structural
repair is for the host's roster evaluations to derive reachability from the qualified
names they call, at which point the import list and all three paragraphs delete
together.

THE POLARITY IS WHY THIS WAS LOUD. The roster read fails closed, so a missing edge
stops the floor instead of yielding an empty roster. Under the opposite polarity this
same omission would have produced a silently permissive wall -- the exact failure mode
this PR exists to close, reintroduced by an oversight nobody would have seen.

AND THE FAILURE IS THE DOCUMENTED CLASS, on its own author: "not in this execution's
loaded index" is the same diagnostic behind 119 of the 142 identities this roster
carries. The witnesses in that population reference declarations that exist while
declaring no import; so did I.

Evidence: required_floor's closure compiles with the edge -- exit 0, 0 blocking
errors, 126 advisory. The host's own roster read is exercised by CI, which is the test
that failed and is the test that has to pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Name the axis the wall does not confine: the roster itself is not compared against the base

The dispatching session, relaying its second reader, asked whether R (subset of) B is
enforced. Checked against the implementation rather than my description of it: it is
not. non_verdict_admission takes observed and roster-at-head, and no base reference
exists anywhere in that path. So a change that makes a NEW identity stop producing a
verdict may add its row IN THE SAME CHANGE, satisfy both executing arms, and be
admitted — the roster legalising the regression it exists to bound. That is review
55361's finding (the row becomes the permission) reached through authorship instead of
through survival.

NO MECHANISM CHANGES HERE. The wall does exactly what it did when CI went green. What
was defective was the CLAIM: the module was named a growth freeze and the title said
"frozen against growth at identity grain", from which a reader concludes growth is
refused. That is rung inflation in DESIGN 4b(1)'s exact sense — worse than sitting
low, because an inflated class never ranks for climbing — and it was false in the
artifact independent of whether the conjunct ever lands. So the header now opens with
what is confined and what is not, BEFORE it describes the admission, and the title
says confines rather than freezes.

TWO AXES, ONE EXECUTES. Observed-vs-roster is walled by execution every run: growth
refuses, stale exemptions refuse, both at identity grain. Roster-vs-base-roster is not
walled at all — mitigatable, confined by review diligence, which is strictly weaker.
The class rung stays the minimum across axes and paths.

NEXT-RUNG TRIGGER, and it is specified at identity grain for the same reason the
executing arm is: the floor reads the roster at the merge base and refuses when the
head roster is not a subset of it, established against a discriminating red. Not
satisfied by counting rows — an addition and a deletion in one change leave every
count unmoved.

WHY THE CONJUNCT IS NOT IN THIS PR: reading the base roster means evaluating a .dag
module out of a git blob in a separate resolve context. That is real machinery
deserving its own discriminating red, not a paragraph bolted onto a change already at
full approval with green CI.

AND THE HONEST ACCOUNT OF WHY THE HOLE EXISTS, which is the reader's framing and
better than mine: the admission was SPECIFIED against a base OBSERVATION, and
substituting the roster for it is what makes the wall runnable in a single pass. The
substitution is sound exactly to the degree the roster cannot be grown freely, so
R (subset of) B is the condition that makes the cheap design safe rather than a nicety
on top of it.

Evidence: required_floor's closure compiles at 0 blocking errors (126 advisory); the
carrier's closure at 0 blocking errors (276 advisory).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The growth trigger names the target-base tip, not the merge base

A precisely-wrong trigger is worse than a vague one, because someone implements
exactly what it says. The previous text named the MERGE BASE as the future authority
for the roster-growth law. It is the wrong baseline, and the failure is an admission
rather than a spelling.

EXEMPTION RESURRECTION. M = {a} at the merge base. Main later repairs `a` and deletes
its row, so the current base tip carries B = {}. A stale branch reintroduces `a` and it
throws: H = {a}, O = {a}. Then O = H passes and H subset-of M PASSES — readmitting an
exemption main has already paid off. H subset-of B fails, which is the law actually
wanted. The mirror is a false red: a row main legitimately adds after the fork sits in
B and in the composed result but not in M, so a subset-of-M rule refuses a branch that
did nothing wrong.

So the law is H subset-of B — the roster in the COMPOSED RESULT is a subset of the
roster at that result's CURRENT TARGET-BASE PARENT — and the trigger now says so, in
both the carrier and the roster header, with the counterexample beside it so the next
author cannot re-derive the weaker rule from the stronger sentence.

CONSEQUENCE FOR THE CUT'S SHAPE, recorded because it changes how the follow-up is
scoped: a BRANCH-HEAD-ONLY RUN CANNOT ESTABLISH THIS LAW. It needs the composed result
AND that result's base parent, which is strictly stronger than "read the roster at
another commit". The trigger also pins the receipt the cut must carry —
target_base_sha, composed_result_sha, base_roster_identity_set,
result_roster_identity_set, added_exemptions = result - base — and requires the same
read-failure polarity the executing arms already have.

NO MECHANISM CHANGES. The two executing axes are untouched and the "confined at
identity grain" claim is unaffected; only the future authority named in the trigger was
wrong. Amended in this PR rather than deferred to the follow-up because the head had
already moved for the main integration, so the approval cycle was already reset and the
marginal cost was zero.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The no-import story does not cover the whole bucket: six of the eight are inside it

An independent census (valiant-lynx-227, run 32743601436) partitions the erroring
modules 53 declaring NO import against 8 that declare imports and error anyway.
Cross-joining that against this carrier's own cause census — which neither lane had
done — puts SIX of those eight inside the `no declaration named` bucket. The bucket is
not homogeneous, and §5's four hand-checked names, all lacking imports, leave the
impression that it is.

ONE OF THE SIX READ IN FULL, so the second shape is evidence and not inference:
v2.lens.vacuity_test fails on `nat_add_left_identity_input` while declaring ten
imports, among them v2.test.nat_semiring.rung_5 — a module that REFERENCES that name
but is not the module that DECLARES it (v2.std.algebra_laws.nat_semiring). Importing a
module does not transitively supply the names its own declarations reach for. So the
second shape is an INCOMPLETE import set, not an absent one.

THE CONCLUSION IS UNCHANGED AND SLIGHTLY STRENGTHENED: both shapes are authored
defects, both repaired by adding the import that declares the referenced name, neither
is a floor scope defect. "Widen the scope" is still the wrong trigger. What moves is
the repairer's expectation, which matters to the lane inheriting the backlog. The
remaining five are established only as "declares imports AND lands in this bucket";
their specific missing imports are unread, and the row says so.

ALSO RECORDED: the census reached me first as "142 rows but 133 distinct, 9 appearing
twice" — which would have meant this roster carried nine stale exemptions. False, and
instructively so: the floor COLUMN-PADS the identity, so short names are followed by
spaces before `ERROR in`, and an extraction using `[^ ]*` cannot cross that padding.
The pattern silently selected for long identifiers and dropped exactly nine rows. The
nine were MISSED, not duplicated — sign inverted, the same shape as the brief this
document exists to correct. Two independent diagnoses converged on the padding cause.
The durable rule: a distinct-vs-total discrepancy is a tell about the READER before it
is a tell about the population, and the control is to count with a different pattern
than the one that extracts.

AND THE CAUSE CENSUS IS DECLARED A CLAIM, NOT A RECEIPT. The floor log carries no cause
text beside the ERROR row, so the 119/13/9/1 partition cannot be checked by anyone
unwilling to re-run a floor that OOMs in a session container — unverifiable by
construction. Printing the cause beside the identity is a smaller change than this
wall and would have made the false alarm impossible; it is a separate subject, and
until it lands the partition is a claim.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The modeled authority still said repaid never gates: one rule, two answers

Review 55515, correct. When stale_non_verdict was flipped to gating after review
55361, the reversal reached the roster header, the seed's field doc and the gate
conjunct — and missed the docstring on v2.workflow.floor_non_verdict_admission
non_verdict_repaid, which went on saying "Reported, never gating: a repaid row must not
red the run that repaid it".

That left two authorities stating OPPOSITE RULES about one admission, inside the module
whose whole subject is single authority, in a PR whose body cites review 55361 for
exactly this class. The mechanism was never wrong — the executing code has refused
stale rows since that fix — which is precisely why the sentence survived: nothing that
runs reads it.

FIXED IN BOTH PLACES, because the reviewer found one instance and there were two. The
docstring now states the rule and records that it was reversed and why. The PR body's
"repaid does not gate" paragraph carried the same stale claim and is corrected as a
struck-through amendment rather than a silent rewrite — a reader of the earlier
revision saw the reversed claim, and quietly replacing it would hide the drift instead
of recording it.

SWEPT FOR OTHERS: grepped every carrier, the seed, the probe document and the PR body
for surviving assertions that repaid or stale does not gate. The only remaining hit is
the verbatim quote of the original brief in the probe document, which is a quotation
and stays.

WHAT THIS IS AN INSTANCE OF, recorded because it is the day's recurring shape: prose
asserting more or other than the mechanism does. Every defect found in this PR has been
that — the failed=0 line, the diagnostic stale row, the growth-freeze title, the
merge-base trigger, and now a docstring left behind by its own reversal. None was a
coding error. All were caught by someone checking a claim against the tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Drop the "65 distinct signatures" figure: it counted names, not causes

valiant-lynx-227 found that the floor's [floor-known-red-causes] census keys on the
FIRST TWELVE WORDS OF THE MESSAGE PROSE, and that prose embeds the missing NAME. So
`no declaration named 'srv3_install_hang_no_router_lease_ms'` and `no declaration named
'extdeps_cargo_build_module'` are two distinct signatures. It reports ~65 for a
population with roughly four actual causes — an artifact of the key, reading as "many
roots" when the truth is "one root, many names". A plan sized off it is sized wrong,
toward heterogeneity, when this population is mostly one repair.

The same line is SILENTLY TRUNCATED AT 20: the printed rows sum to 93 of 142
identities, with 49 identities and 45 signatures dropped and nothing saying so.

WHAT THIS DOES AND DOES NOT REACH, and the boundary is the derivation rather than luck.
The 119/13/9/1 partition was folded over the 142 PER-IDENTITY
KNOWN-RED-RUNTIME-ERRORED lines and sums exactly to 142 — neither prose-keyed nor
truncated — so it stands. The population count and the identity set stand too; the
executed set match settles both. What does not survive is any DISTINCTNESS or
HETEROGENEITY claim, which is precisely the one figure this document took from that
line. It is deleted rather than annotated, because an artifact carried with a caveat is
still cited as a count.

ALSO CORRECTED, IN MY OWN FAVOUR, WHICH IS WHY IT IS WORTH WRITING DOWN: an earlier
revision of this document called the partition "a claim, not a receipt" and
"unverifiable by construction", on the assumption I had hand-derived it. That was too
harsh and is now scoped to what is actually unverifiable — there is no per-identity
cause field, so the partition cannot be JOINED BACK to identities by a reader, which is
a narrower and truer statement than "unverifiable".

The root — ClaimOutcome::RuntimeError carrying message: String built by format! over an
already-closed 27-arm InterpError, so a typed cause is destroyed at the witness
boundary and guessed back by word-slicing at the reporting site — is being repaired
under its own item and is not held by this PR.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Delete the probe board, keep the finding on the carrier: the measurement corpus was bankrupted under this PR

Main landed #9132 (bankrupt the measurement corpus) while this branch was open,
under an operator ruling this change is directly subject to: name the
instrument, never transcribe its output. 164 files and 44,736 lines went out of
docs/probes/, every .sh/.py instrument kept.

docs/probes/expected_red_non_verdict_population_2026-08-24.md is a transcription
board of exactly the class that ruling deletes. After merging main it was the
ONLY file left in that directory -- one document re-establishing a corpus main
had just emptied, on the same day, which is the attractor DESIGN section 3 names
rather than a document that happened to survive. It is deleted here.

WHAT IS NOT LOST, and why the deletion is not a coverage cut. The measurement
never depended on the board: floor_non_verdict_cause_census and
floor_non_verdict_measured_total are typed rows, and
floor_non_verdict_population_basis carries MeasuredOnOneRun { run, head_commit },
so every figure names the run and head it was taken on. That is the receipt-vs-
figure distinction a markdown board structurally cannot carry, which is the
ruling's own argument for the cut.

WHAT MOVED. One irreducible fact in the board was rationale rather than
measurement and had no other home: the dispatched brief -- 99 witnesses PASSED ->
RUNTIME-ERRORED across 330f63c..5482863 with the floor reporting failed=0
-- is false in its first half, shown by an identity-set diff, because the 99 were
baselined against a branch head already carrying the fix and so were compared to
a tree they never ran in. The carrier's existing prose REFERRED to that false
regression without ever stating it; it now states it once, as a section 4c
annotation on the declaration it explains. A first draft of that annotation also
restated the fix-carrying baseline the preceding block already covers, and was
trimmed to the half that was actually missing.

RESIDUE, checked against the three classes #9132 declared for its own cut and
found empty here: no .gitignore un-ignore row, no prose note in any module, and
no witness asserting the filename. Nothing in the tree references the deleted
path, so this leaves none of the debt that commit declared for itself.

Verified: the module parses and evaluates after the annotation --
floor_non_verdict_measured_total returns 142, the host refusing only on its
exit-code contract (an Int is not a ProcessExit), which it can raise only after
computing the value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Make the modeled admission say what its consumer does, and re-measure the hand-Rust receipt (review 55577)

Two findings, both verified against the code before fixing.

ONE: THE MODEL DISAGREED WITH ITS ONLY CONSUMER, AND I CAUSED IT.
`non_verdict_admits` -- modeled in v2.workflow.floor_non_verdict_admission and
mirrored in v1_compiler.cli_run -- answered `added.is_empty()`. The executing
gate `required_floor_outcome_is_clean` has nine conjuncts, two of which are
`non_verdict_unenrolled.is_empty()` (the added arm) AND
`stale_non_verdict.is_empty()` (the repaid arm). So the canonical model said
ADMIT exactly where its consumer said REFUSE.

The provenance matters because it is not an oversight in the original design: it
is the divergence review 55361 opened. That review correctly argued stale rows
must gate, I made the GATE gate, and I did not carry the change into the model or
its tests. DESIGN section 3 is the point -- a modeled authority whose consumer
disagrees is worse than no model, because it is cited as the rule while something
else enforces a different one.

WHAT WAS RIGHT ABOUT THE OLD RULE AND WHAT WAS WRONG. The rationale for admitting
repayment was that refusing it would red the merge that repairs the population
(#9020 repays 99 in one landing). Right about the goal, wrong about the subject:
what refuses is not the repayment, it is the roster row LEFT BEHIND asserting a
debt that no longer exists. Repaying and deleting the row are one act, which is
already how the #9020 merge-order deletion was planned.

So both paths now admit iff added and repaid are BOTH empty, and both suites gain
a control -- repayment WITH the row deleted is admitted. Without that pair the
tests cannot discriminate "stale rows refuse" from "repayment refuses", which are
opposite rules; the pair fails in opposite directions if either is wrong.

TWO: THE HAND-RUST RECEIPT WAS STALE.
It read +195 in cli_run.rs and +65 in claim_executor.rs and omitted
claim_executor's deletions entirely. Measured by git diff --numstat against
origin/main at this head: +203/-0 cli_run.rs, +60/-5 claim_executor.rs, +102/-0
the test file. The forward-freeze policy exists to make hand growth checkable, and
a receipt measured once and not re-measured as the change grew is a figure rather
than a receipt -- the row now says so and says it must be re-measured on every
push touching those files.

Also removed a blank line between one annotation block and the declaration it
attaches to, matching the convention every other annotation in that file follows
(DESIGN section 4c attaches annotations to a declaration). This is NOT claimed as
a fix for anything: a discriminating control through the actual parse sweep, with
and without the blank line, produced identical output, so the form was not what
any gate was refusing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Retire the prose that still states the rule the reversal replaced, and the citation naming a test that no longer exists (review 55591)

The reported finding, plus two of the same class the sweep for it found.

REPORTED: the `observed_repaid` fixture comment still read "Must be admitted --
refusing it would red the merge that repairs the population", directly above the
test that now asserts the opposite. Fixed, and it now says WHY the refusal is not
a penalty on repayment: what refuses is the roster row left standing, not the
repayment, and the deleted-row form is admitted by the fixture below it.

FOUND BY SWEEPING FOR THE CLASS RATHER THAN THE INSTANCE:

(1) The same defect in the Rust mirror. `non_verdict_admits`'s docstring still
described the retired asymmetry -- "so a caller cannot accidentally admit on
`repaid` -- the asymmetry between the two is the content of this wall" -- sitting
directly above a body that now refuses on both arms. Rewritten to state both
refusal reasons, with the correction dated.

(2) A STALE CITATION, and this one would have shipped silently.
`floor_non_verdict_seed_growth_justification` cited
`repayment_is_admitted_and_reported_per_identity`, which the previous commit
RENAMED. That is a DESIGN section 3 fabricated symbol -- and the mechanism that
used to catch it, the cited-symbol census, was removed from CI on 2026-08-23, so
nothing in the repository would have refused it. Verified the whole file by hand
instead: all 12 DeclarationRefs resolve to a definition in the tree. The new
control test is added as a cited row, since a hand-authored seed item that is not
enumerated is exactly what the forward-freeze policy refuses.

Receipt re-measured, as the row itself now requires on every push touching these
files: +210/-1 cli_run.rs, +60/-5 claim_executor.rs, +102/-0 the test file.

THE PATTERN, recorded because it is now four for four in this PR: every defect
found here has been PROSE CLAIMING SOMETHING OTHER THAN WHAT THE MECHANISM DOES
-- the failed=0 headline, the "diagnostic" stale row, the growth-freeze title, the
merge-base trigger, this docstring, this fixture comment, this citation. Not one
was a coding error. That is the cost DESIGN section 4c prices when it calls prose
commentary modeling debt: it cannot be mechanically joined to the code it
describes, so a reversal updates the assertion and leaves every sentence about it
standing.

Verified by execution: both witnesses return true.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Aug 25, 2026
…#9151)

* The forward-freeze policy said "enforceable now"; nothing enforces it

Two corrections to gunbc.seed_growth_admission, both to rows that made a
false claim about their own coverage.

RUNG INFLATION. seed_growth_forward_freeze_policy_note led with "FORWARD-FREEZE
POLICY (enforceable now)". It is contradicted by seed_growth_admission_note two
rows down in the same file: what is enrolled is seed_growth_roster_well_formed_
gate_holds, which checks the roster against ITSELF -- non-empty, well-formed
rows, no duplicate keys -- and never reads a diff. seed_growth_join_declarations,
the join that would refuse an unenumerated addition, is NOT ENROLLED, because no
changed-item population exists to join against. So nothing can refuse hand growth
today, and DESIGN 4b calls a carrier named for a rung it does not occupy worse
than sitting low: the class never ranks for climbing because its own row already
claims the rung.

It is not a scruple. Of the four PRs that added hand src/v1 Rust in the 48 hours
to 2026-08-24, ZERO were caught by an unassisted reviewer; all four were caught
by follow-up investigation after reaching approval. The row now states the rung
(mitigatable, review diligence alone), the measurement, and a 4b(2) next-rung
trigger -- rust_item_host_observation supplying a changed-item population -- with
the two conditions that enrolment must satisfy: the join must be SPLIT (one
candidate set cannot both find unjustified additions and declare rows stale), and
an extractor that cannot attribute a changed region must REFUSE rather than
report an empty delta, which would be the empty-observation narrow DESIGN 5
forbids.

DEAD CITATION. seed_growth_admission_note cited scripts/rust_item_census.py as
its G0 host in the present tense. That file was deleted by gunbc#9132, which left
no .sh or .py outside .githooks. Five sibling modules carry the same dead
citation and are deliberately NOT repaired here -- that is the residue #9132
declared, not a gap this change opens.

Also recorded: hand-item delta and hand-LOC delta are functions of the diff, so
authoring them is a second representation (DESIGN 2). Still required, because
nothing derives them yet, and the cost is already measured -- a receipt on
gunbc#9095 claimed +195/+65 against a measured +203/-0, +60/-5, +102/-0.

EVIDENCE. Prose-only; no behavior changes. The two phrases
seed_growth_admission_witness_test asserts ("exact item identity", "no netting")
both survive. Evaluating that witness locally on this branch and on clean
origin/main produces byte-identical diagnostic sets (496 lines, zero diff), so
this change introduces nothing; the local gunbc shim is a Jun 26 build that
cannot resolve this corpus, so it cannot show the witness passing either way.
CI is the authority for that.

* Repair the two rows this file's own correction left contradicting it

review 55623 is right, and the finding is worse than the one I fixed: I
corrected ONE row to say the G0 census host is gone while leaving TWO rows in
the SAME file asserting scripts/rust_item_census.py is the current host. A
module answering two ways about one fact is the DESIGN 3 violation this PR
exists to remove, so the first pass made the file its own counter-example.

seed_growth_g0_census_host_scaffold_note: rewritten past tense, with its
dissolve-on condition split into the two clauses it always contained --
(a) script deleted, SATISFIED by gunbc#9132, and (b) rust_item_host_observation
producer enrolls, OUTSTANDING. The disposition row is RETAINED, not retired:
(b) is unmet and it has three consumers, so retiring it because half its
trigger fired would delete a live obligation.

seed_growth_admission_g0_population_note: now leads with G0 CENSUS HOST: NONE.
It also carried an instruction to "run the script at HEAD for the live
receipt", which named a deleted file -- an instruction is worse than a stale
citation, because a reader follows it before discovering it is impossible.
The mechanism description is retained, marked as describing what WOULD measure
the population, because the laws survive the producer.

The residue sentence is corrected too: it listed five sibling modules and
omitted the two local ones, which is precisely how the contradiction survived
the first pass. Siblings remain declared residue; the local pair is repaired
here.

EVIDENCE: prose-only. Evaluating seed_growth_admission_witness_test on this
branch and on clean origin/main gives byte-identical diagnostic sets (497
lines, zero diff), so nothing is introduced. The two phrases that witness
asserts are untouched.

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
briansrls pushed a commit that referenced this pull request Aug 25, 2026
…ion refusal (#9072)

* Carry the span the parse phase already computed: locate every annotation refusal

The required-ci parse phase rendered N annotation refusals as N byte-identical
sentences with no position. The span was never missing: AnnotationAttachmentRefusal
carries origin, diagnostic_to_span reads it, and run_dag_parse_sweep then formatted
"{path}: {message}" and discarded it -- a typed, LOCATED diagnostic rendered as
untyped prose (DESIGN section 5).

The printer now builds a NewlineIndex over the same content the parse consumed and
renders "{path}:{line}:{col}: {message}". A diagnostic whose span names no position
in this file renders as the path alone rather than as a fabricated 1:1.

One defect, three instances: all three refusal arms were unlocated for the same
single reason, and the repair is arm-independent because it reads diagnostic_to_span
rather than matching arms. Both consumers inherit it -- the --required-ci parse phase
and the standalone v1_src_dag_parse.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Enumerate this PR's seed growth, and shrink it from 12 hand items to 7

The forward-freeze policy (gunbc.seed_growth_admission seed_growth_forward_freeze_policy_note)
requires every PR that adds hand-written src/v1 Rust to enumerate item identity, authority,
reason, owning lane, deletion trigger, boundary, and both deltas. Tests are not excluded, and
the G0 census host agrees by execution: classify_repo_path returns "hand" for every tracked .rs
outside the stage0 source root, so src/v1/stage0/tests/ is in the measured population.

The scratch directory was an RAII guard -- one struct, two impl blocks, three impl methods --
and every impl method among them is UNCITABLE as a DeclarationRef, so it would have grown the
class seed_growth_uncitable_item_keys reports separately. Collapsed to one free function that
cleans on the way in, which is what makes the run deterministic anyway. Census diff against
origin/main: 12 items -> 7, uncitable 5 -> 0, +123 LOC -> +109.

Files: one justification row homed beside the obligation, one roster entry, one roster note.
cli_run.rs adds zero items (the change is inside an existing fn: ExistingSeedItemModified).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Re-anchor the seed-growth scope argument on the authority that survived #9132

#9132 deleted scripts/rust_item_census.py, the G0 census host this receipt cited in
the present tense as the executable settlement of "are tests in scope". A citation
naming a deleted file is the stale-citation class -- inside a receipt whose own
argument is that an unverifiable figure rots silently.

The scope argument now rests on a .dag authority that still exists and is a better
anchor than the script was: gunbc.stage0_rust_source_lifecycle_scaffold declares
rust_source_prefix_stage0_test ("src/v1/stage0/tests/") and lists it in
rust_source_discovery_prefix_hints, so the stage0 test tree is a DECLARED Rust source
class distinct from stage0_src_repo_prefix, the only prefix the emit produces.

The item deltas are unchanged and now say what they are: a dated measurement taken
with the census host before its deletion, re-checkable by hand from the diff (seven
added items in one new file, all free functions), not a command anyone can re-run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Aug 25, 2026
…ct and verb axis for the emitted-tree consumer (#9154)

* Single build authority + module-grain affected-set selector inverted to one reverse BFS

WIP: repo_self_build.dag is the single cargo-build authority (three workflow
authorities rewired onto it). module_graph.dag gains the reverse-reachability
selector: build adjacency once, BFS outward from touched paths, O(1) membership
per entry -- replacing entry_affected_by_touched_paths' per-entry whole-graph
walk. A touched path resolving to no module on disk refuses
(TouchedPathOutsideModuleGraph); it never widens to the corpus and never
narrows to nothing.

Compiles: 0 blocking errors on src/v2/lens/module_graph.dag.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P

* The build authority gains a subject and a verb, so the emitted-tree build has a home instead of a fork

crisp-crab-430 needs to cargo-check an EMITTED CANDIDATE TREE -- the one
required-regen writes to disk and then compares byte-wise to the committed seed
without ever asking whether either compiles. They raised it before writing
rather than after, which is the only reason this is a design change and not a
second authority.

THE MODULE ARGUED AGAINST ITSELF. repo_self_build_authority_note pins the
package as data because 'a caller free to name the package could build a
different crate and still look like a conforming call'. Their subject IS a
different crate, so the exact property the note relies on is what excluded
them. That is not an under-served case; it is the note being right about the
danger and wrong about the remedy.

A closed subject coproduct keeps the guarantee and admits the second breadth:

  type CargoBuildSubject
    = RepositoryCrate
    | EmittedCandidateTree { manifest_path: String }

No constructor names an arbitrary crate, so the property the note wanted is now
structural rather than rhetorical -- and the one other legitimate subject has a
name. DESIGN section 2 horizontal, one concept at two breadths, rather than a
sibling module sharing an argv vocabulary, which is what a section 3 fork looks
like from the inside.

THE VERB IS THE SECOND AXIS AND THEY DID NOT ASK FOR IT. The base command
hardcoded 'cargo build'. Establishing that an emitted tree COMPILES needs only
check, and the difference is measured, not stylistic: check 59.8s / 2.5GB peak
against build 155s / 4.7GB peak, warm, with the whole stage0 lib recompiled --
the candidate-install case exactly -- and every diagnostic of interest is
check-visible. Left hardcoded, the next consumer writes 'cargo check' beside
this module's 'cargo build' and the fork this module exists to prevent
reappears one field down.

repo_self_build_command keeps its signature, so the three consumers rewired
onto it are untouched: it is now the RepositoryCrate/CargoBuild instance of the
general form rather than the only form.

Compiles: 9 files emitted, 0 diagnostics.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P

* A transcribed duration with no subject was never usable evidence: name the instrument, and land the projection #9132 left behind

TWO THINGS IN ONE REGEN, because they are one fact: the authority moved and the
projection did not.

(1) THE RECONCILE CLAUSE. Section 6 read 'reconcile's eight minutes are ~92%
typecheck_with_census_extra', measured 2026-08-20. The required run of
2026-08-24 (32791076677) emits 'compile.reconcile done in 15 minutes' inside the
floor's strict-preparation over 3892 modules.

I NEARLY WROTE 'NEARLY DOUBLE IN FIVE DAYS' AND THAT WOULD HAVE BEEN THE SAME
DEFECT THIS DOCUMENT SPENT THE EVENING CATCHING. Reconcile's cost is a function
of subject size -- measured the same night at 32s for a four-module closure and
25s for required-regen's ~134 surfaces -- and the subject behind the
eight-minute figure is not recoverable from this document or from 67437fc,
the commit that landed it. So the two numbers cannot be compared at all, and the
doubling is not asserted.

That is a stronger row than an updated number would have been. The RATIO is kept
because where reconcile's time goes is structural; the DURATION is dropped
because it is a property of one run on one corpus size. The instrument is named
instead -- every required run emits [floor-phase] rows and the compiler's own
compile.frontend / normalize / reconcile / analyses lines inside
strict-preparation -- so the current cost is read from the run that owns it.
This applies the standing rule this document already carries, name the
instrument never transcribe its output, to the clause that most needed it.

Two retractions produced this wording, both caught by the other party rather
than the author: a 31x preparation-versus-compile gap I published (it compared a
four-module closure to 3892 modules) and a 33x contradiction smart-ram-730
published (their arm was required-regen's ~134-surface closure). Neither
anomaly exists. What survives is that full-corpus reconcile is ~34% of required
CI and the floor is CPU-bound and single-threaded at ~99.4% for 36 minutes.

(2) THE PROJECTION #9132 LEFT BEHIND. Three further lines move in this regen
and none of them is mine tonight: the deleted probe-document link and the
name-the-instrument ruling both landed in the AUTHORITY at #9132 and were never
projected, so committed DESIGN.md has been stale against its own source since
that merge. The drift gate that would have caught this is on the unguarded list
in the CI rung-drop row a few paragraphs above -- which is the row explaining
why nothing refused.

Regenerated through dag/tools/generated_artifact_gate.dag main_wet over all
committed artifacts; DESIGN.md is the only file that moved, so every other
projection was already at its fixed point.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P

* Move the affected-set selector to its own branch: an unwired lens does not belong in a PR that is otherwise finished

Split at the operator's direction. The selector compiles clean and has no
caller -- required_floor does not reference it -- so merging it here would land
machinery that nothing gates on, which DESIGN section 6 names as coverage by
illusion. It is not abandoned: it moves to
session/deep-ant-102-affected-set-selector with its ceiling measured and stated,
and it merges when it is wired to a consumer and a pruned run is measured.

What remains in this PR is finished and has a waiting consumer: the single build
authority with its subject and verb axes, the three consumers rewired onto it,
and the DESIGN authority/projection corrections.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P

* Back out the subject and verb axes: no consumer in this diff, and I had just applied the opposite standard next door

Review 55633 (approve, non-blocking): CargoVerb and CargoBuildSubject add a
check axis and an emitted-tree subject that nothing in this diff consumes -- the
sole caller pins verb=CargoBuild and subject=RepositoryCrate -- so DESIGN
section 6's new artifact with no final consumer applies and the honest landing
today is bins-only. The reviewer is right on the facts.

WHAT DECIDED IT IS WORSE THAN THE FINDING. Twenty minutes earlier I split the
affected-set selector OUT of this same branch, on the grounds that an unwired
lens does not belong in a PR that is otherwise finished, and then left unwired
axes sitting in it. One principle, two neighbouring artifacts, opposite
treatment. The reviewer also names the correct exception -- non-blocking if the
operator greenlit the pre-plumbed axes -- and there is no such greenlight: I
ruled on the requesting session's design question myself, and an author's own
ruling is not the operator verdict section 6 requires for work landing ahead of
its consumer.

THE DESIGN IS NOT RE-OPENED BY THIS, and the module now says so in a note rather
than losing it: a free package parameter remains the wrong remedy because it
discards the property the authority note relies on, and a sibling authority
sharing this argv vocabulary remains the section 3 fork this module exists to
prevent. The subject belongs here as a CLOSED vocabulary and the verb is a real
axis on a measured 59.8s check against 155s build. What changed is only WHICH
DIFF carries them: the one with the consumer, not the one ahead of it. That is
strictly better for the requesting session too -- axis and consumer in one
reviewable change, justified on its own evidence rather than on mine. They have
been told at high priority, before building against a surface about to change.

116 lines to 55. Compiles: 9 files emitted, 0 diagnostics.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P

* Name why the cargo-argv fork cannot be consumed, so the next author does not discover the transport fusion alone

Review 55636 is right that this module re-mints cargo argv words that
extdeps.rust.cargo_build already owns, and the existing note conceded the
boundary without saying what blocks it. Consuming that module is not
available, and the reason is measurable rather than a matter of taste.

Every cargo argv word there -- cargo, build, -p, --bin -- appears only inside
a transport shell block. Measured on the live file, its entire declaration
surface is one ExternalAuthority anchor, one env map, one note and two
jobs-flag fns; no data or fn exposes the vocabulary at all. So there is no
expression a fn here could read it from: the argv is fused to the shell
transport that spells it.

That is the DESIGN section 3 interface-versus-realization seam exactly. This
consumer needs a workflow YAML string, which is a second realization of the
same operation, so the correct repair is to de-fuse the operation shape from
transport shell and bind both realizations to it -- not to have this module
reach into a transport block, which the language does not admit. The
follow-up is therefore de-fusion in extdeps, strictly larger than this PR and
correctly outside it. Until it lands the fork stands, named rather than silent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRMbwdtHZxTiMNZD5WLS3P

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Aug 28, 2026
…t moved, retire the one whose subject is gone (#9606)

* Two witnesses reading deleted artifacts: repoint the one whose subject moved, retire the one whose subject is gone

Both read files that earlier root cuts deleted, and both were masked until #9592
repaired the route-gap disposition. The dispositions are NOT the same, because
the two deletions were not the same kind of event.

REPOINTED. `regen_stage0_write_and_verify_share_compile_refusal` read
`src/v1/stage0/src/bin/regen_stage0.rs`, deleted by 3b431f3 (#8406) when
`claim_executor --required-regen` took over. The subject MOVED, so the witness
follows it to `src/v1/stage0/src/required_regen_host.rs`, renamed off the dead
binary's name. Both conjuncts survive and the positive one is tighter than at
the old subject: `run_required_regen` (write) and `run_required_regen_fixed_point`
(verify) do not merely share `stage0_self_compile_refusal_message`, they share
the single `compile_stage0` call that consults it. The negative conjunct keeps a
historically authored RED -- at 268919d^ the deleted binary carried its own
forked `let hard_errors: Vec<String>`, and #6293 is the commit that removed it.
A regression control with a real red is worth carrying; one without would not
have been.

RETIRED. The wet parser-drop witness read a receipt under
`docs/probes/claude_paired_entitlement_probe/`, deleted by d3bebd0 (#9132).
That commit's title, and DESIGN.md's account of the bankruptcy, say "delete every
transcription, keep every instrument". FOR THIS PATH THAT IS NOT WHAT HAPPENED:
`git show d3bebd0 --name-status` lists six deletions including
`run-paired-probe.mjs` and `claude-wrapper-tee.mjs`. The instruments were .mjs
while the surviving-instrument clause named .sh/.py, and the 2026-08-24 ruling
then took the .sh/.py corpus too. Nothing in the tree re-derives this receipt,
so the only route to green was authoring the JSON by hand -- fabricating exactly
the measurement receipt the bankruptcy existed to end.

WHAT THE RETIRE COSTS, recorded in the surviving module rather than left to be
inferred from an absence: the predicate and its five discriminating controls are
untouched in `test.claim.claude_sdk_parser_drop_witness`; what dies is
specifically the assertion that the modeled upstream claim is grounded in a
COMMITTED WET OBSERVATION rather than in a fixture transcribed from one.

THE ROUTE-GAP ROWS COME OUT, AND THAT IS REQUIRED RATHER THAN TIDYING. Both
identities were enrolled in `v2.workflow.floor_route_gap` on ground
`NoMockResponse`, which was the wrong ground for both: the route was never
missing, the FILE was. That roster is bidirectionally fail-closed by its own
header -- an enrolled row whose route does not gap reds as stale, and an
enrolled identity that does not execute reds too -- so after the repoint executes
and the retired identity stops existing, leaving either row is a red landed on
purpose.

Also removed, as dead names: `claude_sdk_parser_drop_receipt_path` (a data row
whose only content pointed at a deleted file), and the witness's `bin_wet` entry
and `WitnessExclusionRow` in `gunbc.ci_layer_roots`.

NOT TOUCHED, and it is a real gap. The retired witness's third arm,
`ParserDropNotEstablished`, was built to mean REPAIR THE ARTIFACT.
`eval_filesystem_read_builtin` declares `ExpectSuccess`, so a failed read raises
before any record exists, and the record it returns carries only `content`. That
arm is unreachable from a missing file BY ANY PATH -- the contract the witness
assumed is unrepresentable, not merely unimplemented. Nothing is silently wrong
today, because the TypeError is accidentally louder than the assumed contract.
The fix lives in seed Rust under the v1 freeze and needs its own admission
decision; it is a separate item and deliberately not taken here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Repair the citation my own deletion made stale

Review finding on #9606, and it is the exact class this PR exists to remove: the
hermetic sibling's note still said "The wet receipt filesystem_read witness lives
in claude_sdk_parser_drop_live_witness_test.dag (ReadsLiveTree)" -- a pointer to
a file this PR deletes. Leaving it would have reproduced, one file over, the dead
name I removed from extdeps.llm.claude_agent_sdk_stream.

It is replaced with what a reader actually needs rather than a repointed pointer,
because there is nothing to repoint to: the note now records that the wet half is
RETIRED rather than relocated, why (the receipt AND the instruments that produced
it went with docs/probes/claude_paired_entitlement_probe/), that these controls
are consequently the whole of this evidence, and where the cost of that is
written down.

No gate would have caught this. The citation wall re-derived in
v1_compiler.declaration_index checks typed DeclarationRef literals; a prose
reference inside a String is covered by nothing, before or after -- which is
precisely why it took a reviewer.

Swept for others: the only remaining mention of the deleted module anywhere is
the srv1_residue_rehearsal captured wire blob, which is a historical capture of
paths tracked at a past deploy rehearsal. That one is correctly left alone --
editing a capture to match today's tree would falsify it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 29, 2026
…prepare or build over the live tree carry a live-corpus ignore reason and leave the required run, and the rot the first-ever `cargo test` exposed is repaired at its authorities, not hidden

`cargo test -p v1-compiler --lib` had never run in CI. Its first run (33238828500) was cancelled by its own 60-minute timeout with 204 of 682 tests finished, because ~126 of the "unit" tests each build a fresh multi-entry index over `src/v2`+`dag` (4,260 modules; ~197 single-thread minutes on srv2 under nextest, 97 tests over 60 s, `self_compile_all_modules` alone 505 s), and the runner executes them serially. Those tests now carry `#[ignore = "live-corpus: ..."]` — the crate's existing `manual:` convention, one class, declared on the carrier — and the rung-drop row `required_gate_bankruptcy` names them by their instrument (`cargo test -p v1-compiler --lib -- --ignored --list`). The unit population runs in ~10 s after the compile (srv2: 537 passed / 136 ignored).

Of the 44 failures the full run exposed, the 15 in the unit population are repaired where the fact lives:
- REAL DEFECTS (two): `try_index_source_root_into_module_index` keyed files by their walked path, absolute since #9548 anchored the root, while the strict builder keys through `module_index_path_key` — the primary-precedence index disagreed with the strict one on every path; keyed through the same authority now. `try_build_module_index` carried `if root_idx > 0 { continue; }` before its collision refusal (from #7791), so a module declared in two roots shadowed silently in the builder named strict; the guard is gone and overlay callers have `build_module_index_primary_precedence`.
- v1 TYPECHECK DEFECT: `declared_type_inhabitance` reads `params` as generic type parameters, which is exactly what a callable formal carries, so every higher-order call produced a counted advisory with a false reason (#9194); `direct_call_argument_inhabitance_diags` now excludes callable formals like its sibling `direct_call_arg_type_mismatch`. Mirror regenerated (two passes: the test blob lives inside the emitter).
- STALE AUTHORITY ROWS after the #9637 reorg: 12 entry literals in `gunbc.ci_layer_roots` and 2 in `gunbc.offline_local_recipe` repointed; the two long-lane rows and one freeze row whose subjects 611fd02 and #9206 deleted are gone; the three freeze rows for relocated witnesses are DELETED rather than repointed, because the freeze gate defines relocation as growth and the roster may only shrink. `gunbc.non_fold_residue` receives the 22 sites it lacked and loses the 4 whose subjects moved or greened; its .dag twin therefore leaves floor_expected_red (it passes) and joins cost-debt chunk 12 (629 ms against the 500 ms ceiling, its whole cost the corpus scan it checks).
- DELETED SUBJECTS: `cli_run::floor_witness_a_prove` (its runner, prove test and fixtures went with the FLOOR-Y cutover); the census pin tests and helpers for `docs/probes/census_extra_excludes.txt` (#9132 deleted every transcription).
- EARLY ABORTS: three witness-admission tests and the roadmap jsonl-carrier test were "fast" only because they failed before their expensive step; with their inputs repaired they read the live tree for 2-4 minutes each and join the live-corpus class.
- TEST ROT: the reorg rewrote a revision-addressed literal (`9ce6526c528:dag/gunbc/roadmap/...`) that must name the pre-reorg path; the method-existence witness anchored on a `Primitive()` row the frontier no longer holds.

Not done here, receipts-lane rot for follow-ups: `test.claim.expectation_frontier_witness_test` names the deleted long-lane file; the affected-set kernel (`floor_diff_edits_from_diff_text`, `rerun_frontier_nodes_for_entry`, …) has no production consumer since FLOOR-Y and should go with its remaining fixture-dependent tests; the roadmap jsonl-carrier test takes 453 s and fails after its expensive step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2
briansrls added a commit that referenced this pull request Aug 29, 2026
…e prepares the roster's closure, not the tree; rust unit tests in their own job; the un-required phases declared as a rung drop (#9663)

* Unbreak main: drop the JsSite artifact rows whose authority #9641 deleted, and give the six witness-bin TypeEnv initializers the unit_variant_index #9656 added

Two integration collisions between independently green PRs:
- #9641 deleted dag/examples/js_site but gunbc.generated_artifact and
  gunbc.generated_artifact_emit still imported it, so the whole-tree
  strict resolve refused and every floor on main has been red since.
- #9656 added TypeEnv.unit_variant_index; infer_semantics_witness.rs
  builds six TypeEnvs by hand and none carried it, so --bins failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The lib's own unit tests build one more TypeEnv by hand; give it unit_variant_index too

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* Required CI is the compiler floor: a static gate roster, prepared as its own import closure, with the other four phases and the product witnesses moved off the merge path

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* Drop the six duplicate unit_variant_index initializers the merge with #9648 produced

* Drop the six duplicate unit_variant_index initializers the merge with #9648 produced

* Regenerate .gitattributes: the six js_site rows projected from the deleted artifact registry entries go with them

* Regenerate the four projections of this change: witnesses.yml (probe and all-bins steps gone, rust-unit-tests job added), DESIGN.md and design-ledgers.md (the rung-drop row), .gitattributes (js_site rows gone)

* Restore the lib-test TypeEnv initializer's unit_variant_index (lost when the merge took main's cli_run.rs wholesale)

* The gate closure is the loader's both-closure (imports + reference edges to a fixpoint), not the import headers: stripped modules reach their providers by reference, and the header walk left 1,190 names unresolved

* Shrink the namespace transition roster: the 314 std->extdeps consolidation rows landed with #9641 and now refuse every PR as stale

* Build the entry index once for both gate closures (it is the expensive part: ~75-110s per build on the corpus)

* Gate closure includes containment ancestors to a fixpoint: a module importing only a child of the declaring module still binds the parent's declarations

* The floor's policy module is always a closure seed: its rosters are evaluated in a frame over the prepared subject

* The reference-closure index is keyed by the prepared subject's digest, bounded to the two subjects a floor process prepares by design — the gate's policy-closure preparation and the gate closure are two subjects in one process, and a once-per-process index refused the second (ReferenceIndexSubjectChanged built_for_modules=47 observed_modules=1952, CI and srv2 at 066725c)

The old check keyed on module COUNT: two subjects of equal size would have
shared one index silently. The new one keys on `subject_digest`, so the
index a scope consults was built from the graph that scope is over, by
construction. The population is bounded by
FLOOR_PREPARED_SUBJECTS_PER_PROCESS = 2 (policy closure, gate closure) — a
third distinct subject still refuses with the same cause, because a
subject per claim is the corpus walk per row the index exists to avoid.

Evidence: srv2 rerun of `claim_executor --required-ci --required-lane
witnesses` at this tree builds the 47-module policy index
(subject=09966adcd218af0e) and proceeds into the 1,954-module gate
preparation instead of refusing at claim scope.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The floor's own runtime authorities are explicit closure seeds: the gate-bounded subject refused at output-policy install because resolve_channel_policy had only ever resolved by pool-membership coincidence — the flat bare-name channel found gunbc.output_policy because the whole corpus was loaded, not because the policy closure references it

REQUIRED_FLOOR_RUNTIME_AUTHORITY_MODULES names every module the floor's
Rust evaluates by name outside the gate roster: the policy module (its
rosters), v2.workflow.floor_naming_hygiene (qualified evaluations), and
gunbc.output_policy (bare, from install_output_policy_in). All three are
seeds of the gate closure; a new by-name evaluation adds its module here
or refuses at its own call site.

Measured: the first gate-bounded run (srv2, at 2d5502a) got past both
reference-closure indexes and refused with "no declaration named
'resolve_channel_policy' in this execution's loaded index".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* A by-name evaluation of a module's declaration runs in THAT module's scope: the floor installed the output policy and the naming-hygiene predicates from the policy module's frame, which reached gunbc.output_policy only by the accident of the whole-tree reference closure — under the gate-bounded subject the module was loaded and the name still refused

floor_authority_frame(prepared, module) builds a hermetic frame over one
module's exact claim scope. install_output_policy_in now receives the
frame over gunbc.output_policy; floor_barren_test_sidecars the one over
v2.workflow.floor_naming_hygiene. The policy module's frame keeps only
the policy module's own rosters.

Measured (srv2, lanes 5 and 6): with gunbc.output_policy present in the
1,954-module subject — the seeds changed the seed count 906 -> 908 and
the closure not at all — resolve_channel_policy still refused as "no
declaration named ... in this execution's loaded index". The scope, not
the subject, was the coincidence.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The floor's rosters are joined only over identities inside the required gate — an enrolled identity whose module the gate never loads is withheld with the same accounting as cost-debt withholding, not refused as stale; and two modules that reached rust_target_model_staging by bare reference now import it, because the loader follows bare references only for import-free modules while the claim scope follows all of them

Measured on the first gate-bounded fold (srv2 lane 7, CI at 006b0ef):
ExpectedRedIdentityDidNotExecute count=39, every row in a module outside
the gate roster; and v2.test.lens_vacuity.vacuity_test x5 ERROR
no-such-function `rust_target_model_staging`, reproduced standalone with
`gunbc run --entry src/v2/test/lens_vacuity/vacuity_test.dag`. The
loader's both-closure (build_both_closure_edge_index) skips the bare
scan for any source that declares import lines, so rung_3_4_common
(one import) and leaf_model_verification's bare edge to
v2.extdeps.languages.rust was never followed; under the whole-tree
subject the flat channel found it anyway. The import is the form 10 of
the 12 sibling callers already use; the loader/scope divergence is
recorded in the PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The gate closure follows bare cross-module references from EVERY module, with the loader's own scanner, to a joint fixpoint with containment ancestors — the loader's both-closure bare-scans only import-free sources, while the claim scope the fold builds over the subject follows bare references from all of them; and route-gap expectations located outside the gate are withheld like the roster rows they join

Measured 2026-08-29 on srv2: with the gate subject, `gunbc run` of
v2.test.lens_vacuity.vacuity_test refused no-such-function
`rust_target_model_staging`, then `eval_context` after the first was
imported — one absent module per run, because rung_3_4_common (one
import line) and leaf_model_verification reach them by bare reference
and build_both_closure_edge_index skips the bare scan for any source
that declares an import. The fixpoint reuses
bare_reference_pull_paths_for_source, so the relation is the loader's
and not a second scanner; the count of modules pulled this way is
printed on the gate-closure line.

Lane 8 (srv2) then refused `floor_route_gap_expectations: located
identity is absent from derived roster` for an identity whose module is
outside the gate: the roster had its outside-gate rows withheld and the
expectations had not. Both sides now withhold by the same predicate,
counted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* Cost-debt rows outside the required gate are withheld from the staleness join, route-gap expectations honour cost-debt withholding, and emit_on_demand_classical_not_native_one_build_holds moves to the cost-debt roster — it is budget-refused before it reaches the host effect its route-gap enrollment expects, on both hosts

Measured on the first complete gate-bounded fold (srv2 lane 10 and CI at
e8effe8, identical): verdict=FloorRefused with unexpected_failures=0 —
no claim inside the gate fails — and two bookkeeping refusals: 122
STALE-COST-DEBT rows, every one in a module the gate never loads, and
one STALE-ROUTE-GAP row whose claim ran past its CPU ceiling before
reaching the effect. The first is the same out-of-scope population the
expected-red and route-gap joins already withhold, now counted the same
way. The second is a real cost debt (floor_cost_debt already records
this claim at 502 -> 2374 ms), and cost debt wins over route-gap
enrollment by the roster's own rule; the expectations decode now treats
a cost-debt-withheld identity as dormant rather than absent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* Two lens_module_gate_witness rows leave the expected-red roster: under the gate-bounded subject both PASS on CI and on srv2, and the floor refuses a passing enrollment as STALE-QUARANTINE

Measured at 1f4bda9 (CI) and srv2 lane 12: verdict=FloorRefused with
unexpected_failures=0 and exactly these two STALE-QUARANTINE rows on
CI. Both are "live" claims whose question ranges over the loaded
corpus; under the gate closure that corpus is 2,021 modules rather
than 4,260, and the population they were red on is outside it. That
is a narrowing of what the claim observes, stated here rather than
hidden: the whole-corpus receipts run is where the wider question is
asked again. srv2 additionally passes four emit_host_* rows that stay
red on the required host; those stay enrolled — CI is the oracle for
the required gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* Eleven claims interrupted before verdict on the gate-bounded subject join the cost-debt roster as proven chunk 12 — the same eleven on the GitHub runner and on srv2, run after run

At 92cc92e the floor reports verdict=FloorRefused with
unexpected_failures=0, no stale rows, no now-passing rows, and eleven
INTERRUPTED-BEFORE-VERDICT identities (cost_coverage_witness x3,
loaded_carrier_receipts x3, lens_closure_question_zero_holds_live,
green_control_sanctioned_reader_body_not_flagged,
same_grammar_parse_ingest_bridge_holds, kotlin_grammar_parse_accepted,
nominal_distinct_control_compiles_ok). The set is identical at e8effe8
and 1f4bda9 on CI and in srv2 lane 12, so it is a property of the
subject, not of host load: on the gate closure these claims first-touch
artifacts the whole-tree fold had warmed before reaching them. Declared
here as the roster's own containment for a cost the ceiling cannot
hold; the exit is the warm, as the roster's header states.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* lens_module_gate_holds_live joins cost-debt chunk 12: it was interrupted at 1076ms the run after its sibling was withheld, because the 1.07s pool-root module_path_index fill is billed to whichever consumer runs first

CI 0829ad8: verdict=FloorRefused, unexpected_failures=0, one
INTERRUPTED-BEFORE-VERDICT row. The claim-cost receipt reads
budget_interrupted 1076ms for it and
`[floor-shared-fill] cache=module_path_index key=.../src/v2/lens
fill_ms=1070 paid_by=...lens_module_gate_holds_live consumer_claims=1`;
at 92cc92e the same fill was paid by lens_closure_question_zero_holds_live
(consumer_claims=2) and this claim passed. The index is keyed on a pool
root the decl_facts seam asks for at claim time, so preparation cannot
warm it ahead; with both consumers withheld nothing pays it. The
roster's own header names the warm as the exit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The pool-root module_path_index for src/v2/lens is warmed in preparation by evaluating the declared producer once in its own module's scope — the 1.07s fill was a positional bill that interrupted a different lens_module_gate_witness live claim in each of three consecutive runs — and the two fill-only rows leave cost-debt chunk 12

CI 92cc92e, 0829ad8, 154fb1f: each run's single INTERRUPTED-BEFORE-VERDICT
row was the next `lens_module_gate_witness` live claim in evaluation
order, at 1068–1252ms, with the claim-cost receipt and
`[floor-shared-fill] cache=module_path_index key=.../src/v2/lens`
naming that claim as the payer. The witness-roots warm cannot reach a
per-pool-root key; this warm evaluates
`v2.lens.registry.completeness.lens_registry_completeness_live_facts`
in that module's frame, so the root comes from
`lens_registry_completeness_pool_roots` and the key is the consumers'
by construction. Adjudicated with the other preparation warms as
`ModulePathIndexBuild/lens-pool-roots`; skipped (printed) when the
subject does not carry the producer; a producer that fails to evaluate
refuses. The two rows whose entire cost was this fill leave chunk 12,
as the roster header says they must once the warm exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* lens_closure_question_zero_holds_live leaves the expected-red roster: with the src/v2/lens pool-root index warmed in preparation it passes, as its two siblings did once they stopped paying that fill

srv2 lane 13 at 8ad4091: `[floor-shared-fill] cache=module_path_index
key=.../src/v2/lens paid_by=<outside-fold> consumer_claims=3`, no lens
claim interrupted, and STALE-QUARANTINE for this row — the same row
that was red only while it paid the fill (CI 92cc92e).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The four bootstrap_footprint_anchor claims join cost-debt chunk 12: 474–505ms CPU on three consecutive CI runs with no fill billed to them, so the 500ms ceiling decides them run by run

CI f462bc9: planned=executed=2834, passed=2754, known_red_held=27,
failed=0, no stale rows, interrupted_before_verdict=4 — these four, at
502–505ms. At 154fb1f the same four completed at 487–504ms and at
0829ad8 at 474–485ms; the run-to-run spread is the runner slot, not the
claim. The gate did not change their cost — nothing in the shared-fill
attribution names them — so the disposition is the roster's, not a
ceiling change: withheld as declared debt until the host-load row
lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The rust-unit-tests job runs the unit population: the lib tests that prepare or build over the live tree carry a live-corpus ignore reason and leave the required run, and the rot the first-ever `cargo test` exposed is repaired at its authorities, not hidden

`cargo test -p v1-compiler --lib` had never run in CI. Its first run (33238828500) was cancelled by its own 60-minute timeout with 204 of 682 tests finished, because ~126 of the "unit" tests each build a fresh multi-entry index over `src/v2`+`dag` (4,260 modules; ~197 single-thread minutes on srv2 under nextest, 97 tests over 60 s, `self_compile_all_modules` alone 505 s), and the runner executes them serially. Those tests now carry `#[ignore = "live-corpus: ..."]` — the crate's existing `manual:` convention, one class, declared on the carrier — and the rung-drop row `required_gate_bankruptcy` names them by their instrument (`cargo test -p v1-compiler --lib -- --ignored --list`). The unit population runs in ~10 s after the compile (srv2: 537 passed / 136 ignored).

Of the 44 failures the full run exposed, the 15 in the unit population are repaired where the fact lives:
- REAL DEFECTS (two): `try_index_source_root_into_module_index` keyed files by their walked path, absolute since #9548 anchored the root, while the strict builder keys through `module_index_path_key` — the primary-precedence index disagreed with the strict one on every path; keyed through the same authority now. `try_build_module_index` carried `if root_idx > 0 { continue; }` before its collision refusal (from #7791), so a module declared in two roots shadowed silently in the builder named strict; the guard is gone and overlay callers have `build_module_index_primary_precedence`.
- v1 TYPECHECK DEFECT: `declared_type_inhabitance` reads `params` as generic type parameters, which is exactly what a callable formal carries, so every higher-order call produced a counted advisory with a false reason (#9194); `direct_call_argument_inhabitance_diags` now excludes callable formals like its sibling `direct_call_arg_type_mismatch`. Mirror regenerated (two passes: the test blob lives inside the emitter).
- STALE AUTHORITY ROWS after the #9637 reorg: 12 entry literals in `gunbc.ci_layer_roots` and 2 in `gunbc.offline_local_recipe` repointed; the two long-lane rows and one freeze row whose subjects 611fd02 and #9206 deleted are gone; the three freeze rows for relocated witnesses are DELETED rather than repointed, because the freeze gate defines relocation as growth and the roster may only shrink. `gunbc.non_fold_residue` receives the 22 sites it lacked and loses the 4 whose subjects moved or greened; its .dag twin therefore leaves floor_expected_red (it passes) and joins cost-debt chunk 12 (629 ms against the 500 ms ceiling, its whole cost the corpus scan it checks).
- DELETED SUBJECTS: `cli_run::floor_witness_a_prove` (its runner, prove test and fixtures went with the FLOOR-Y cutover); the census pin tests and helpers for `docs/probes/census_extra_excludes.txt` (#9132 deleted every transcription).
- EARLY ABORTS: three witness-admission tests and the roadmap jsonl-carrier test were "fast" only because they failed before their expensive step; with their inputs repaired they read the live tree for 2-4 minutes each and join the live-corpus class.
- TEST ROT: the reorg rewrote a revision-addressed literal (`9ce6526c528:dag/gunbc/roadmap/...`) that must name the pre-reorg path; the method-existence witness anchored on a `Primitive()` row the frontier no longer holds.

Not done here, receipts-lane rot for follow-ups: `test.claim.expectation_frontier_witness_test` names the deleted long-lane file; the affected-set kernel (`floor_diff_edits_from_diff_text`, `rerun_frontier_nodes_for_entry`, …) has no production consumer since FLOOR-Y and should go with its remaining fixture-dependent tests; the roadmap jsonl-carrier test takes 453 s and fails after its expensive step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

* The host-tool probe root carries the process id: temp_dir() is the host's shared /tmp on a self-hosted runner, and a fixed directory name collided with one another runner slot's uid left behind — PermissionDenied on two tests that had never run in CI before

Found by the first green-by-duration run of the unit population (dc3ca52: 533 passed, 2 failed, 9.59s). The same class as the shared-/tmp emit_on_demand collision on srv2: a test that writes a fixed path into a location the process does not own.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G3t66QwKJFK5w8jXxMXP2

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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