Skip to content

A restoration trigger prescribed an index; the mechanism it derived that from is refuted - #10757

Merged
briansrls merged 43 commits into
mainfrom
session/bright-badger-637-drop-trigger
Sep 9, 2026
Merged

briansrls merged 43 commits into
mainfrom
session/bright-badger-637-drop-trigger

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Why this is a PR and not a comment

#10744 is merged. Its row on main names the mechanism as a repeated decls_matching_callee rescan of decls_in_modules, and its restoration trigger reads the callee lookup answers by index rather than by scanning the candidate pool. That mechanism is refuted by execution — so main is carrying a false causal sentence and a repair prescription derived from it, and the prescription tells the next lane to build exactly the index that was just measured to buy nothing. Removing the artifact (#10753, closed) without correcting the instruction leaves the thing that generates it.

What is refuted

v2.std.fn_index decls_in_modules is a plain-valued call with hashable arguments, and the v1 interpreter's eval-frame call memo is on by default (GUNBC_EVAL_MEMO), keyed by fn identity × argument identity with an Rc-identity fast path. The loop-invariant the trigger asked a lane to hoist had already been hoisted by the interpreter — evaluated once per walk and served from the memo thereafter, as are repeated lookups of the same callee. The per-lookup rescan named as the cost was not being paid.

The measurement

#10753 built exactly the prescribed index. Directory grain, three alternating repetitions in one dispatch on one machine, only src/v2/std/fn_index.dag swapped between arms:

rep BEFORE AFTER control BEFORE control AFTER
1 6094ms 7129ms 303ms 309ms
2 6139ms 7171ms 306ms 305ms
3 6068ms 7304ms 305ms 310ms

The verdict rule was pre-registered before these numbers existed (posted on #10753): normalise each run by its own positive control so machine drift cancels within the run; HARMFUL iff the AFTER normalised range lies entirely above BEFORE, BENEFICIAL iff entirely below, NEUTRAL if they overlap.

  • BEFORE normalised: 19.90, 20.06, 20.11
  • AFTER normalised: 23.07, 23.51, 23.56

Disjoint → HARMFUL. The index adds ~1.1s and removes nothing. Both arms remain 12–14x the per-claim line.

The first pair taken did not discriminate at all — at n=1 the control moved +24.3% against the subject's +19.8%, which licenses no conclusion in either direction. That reading was correct for the data available, and it is recorded rather than quietly dropped now that n=3 shows the control stable at 303–310ms and the excursion as a cold-start artifact. A negative is trustworthy only beside a positive control that fires.

What survives, and what does not

  • The fit: unchanged. O(reached × pool) agreeing within 1.9x across two grains where O(reached²) misses by 44x is still good evidence.
  • The mechanism: UNESTABLISHED. A correct fit carrying a false mechanism is the more dangerous of the two artifacts, because it keeps recruiting repairs aimed at the wrong thing while looking already diagnosed — which is precisely what it did to The callee lookup answers by index, so the determinism walk costs what it reaches #10753.

The trigger is withdrawn, not weakened

A restoration trigger is a repair prescription, not a note. Once its mechanism is false, keeping it as the declared way out with an an index did not help remark beside it would be exactly the misleading artifact this row exists to prevent.

The next trigger is an attribution, not a repair: separate acquisition, the reachability walk, and the determinism fold over the reached set; and distinguish cost tracking the candidate pool from cost tracking what the walk reaches, by holding the closure fixed while the pool varies. Only once that exists may this row name a repair, and the repair it names must be derived from it.

SUFFICIENT FOR is untouched, including WITHOUT NARROWING THE SUBJECT — that clause is correct, load-bearing, and it is what stopped this lane from taking the trap.

One observation, at the grain it was taken and no wider

Under claim_batch the directory-grain walk executes, completes and passes at 6–7s — not interrupted. That establishes executability and says nothing about the required floor, whose disposition for this claim is unpinned and where whether a poll-visible deadline is armed the same way is unresolved. So the interrupted_before_verdict cause is recorded as unverified pending required-floor instrumentation — not "cannot finish", and equally not "finishes over budget on the floor", because the run that would license the second sentence has not been taken.

Scope

Correction only. Nothing is retired, the drop still stands, its subject stays narrowed to one file, and the coverage loss it records is unchanged. docs/design-rung-drops.md regenerated by tools.docs_projection_gate regen; the whole-tree regen left docs/design-failure-modes.md byte-identical, so this contends with nothing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey

Brian Searls and others added 3 commits September 7, 2026 10:07
…hat from is refuted

gunbc#10744 corrected this drop's cause from the number of reachable
declarations to a rescan of the candidate pool, and derived a trigger from it:
the callee lookup answers BY INDEX rather than by scanning the pool. That
mechanism is refuted by execution, and the trigger it generated is therefore a
repair prescription pointing at something that is not being paid.

v2.std.fn_index.decls_in_modules is a plain-valued call with hashable
arguments, and the v1 interpreter's eval-frame call memo is on by default
(GUNBC_EVAL_MEMO), keyed by fn identity x argument identity. The loop-invariant
the trigger asked a lane to hoist had already been hoisted by the interpreter:
it is evaluated once per walk and served from the memo thereafter, as are
repeated lookups of the same callee.

gunbc#10753 built exactly the prescribed index and measured it at directory
grain -- three alternating repetitions in one dispatch on one machine, only
src/v2/std/fn_index.dag swapped. The verdict rule was pre-registered before the
numbers existed: normalise each run by its own positive control, HARMFUL iff
the AFTER range lies entirely above BEFORE. The ranges are disjoint (BEFORE
19.90/20.06/20.11, AFTER 23.07/23.51/23.56), so the index ADDS about 1.1
seconds and removes nothing. Both arms remain twelve to fourteen times the
per-claim line.

The FIT is unchanged and still good evidence -- O(reached x pool) agrees within
1.9x across two grains where O(reached^2) misses by 44x. The MECHANISM behind
it is now UNESTABLISHED. A correct fit carrying a false mechanism is the more
dangerous artifact, because it keeps recruiting repairs aimed at the wrong
thing while looking already diagnosed, which is what it did to #10753.

So the trigger is WITHDRAWN, not weakened. A trigger is a prescription; leaving
it standing with a "the index did not help" note beside it would be the
misleading artifact this row exists to prevent. The next trigger is an
ATTRIBUTION rather than a repair: separate acquisition, the reachability walk
and the determinism fold, and distinguish cost tracking the POOL from cost
tracking what is REACHED by holding the closure fixed while the pool varies.
Only then may this row name a repair.

The SUFFICIENT FOR clause is untouched, including WITHOUT NARROWING THE
SUBJECT. Scoping pool_roots to the reachable modules remains the trap.

One observation at the grain it was taken: under claim_batch the directory-grain
walk executes, completes and passes at 6-7s -- not interrupted. That establishes
executability and nothing about the required floor, whose disposition for this
claim is unpinned, so this row's interrupted_before_verdict cause is recorded as
unverified pending required-floor instrumentation -- not "cannot finish", and
equally not "finishes over budget on the floor".

docs/design-rung-drops.md regenerated; the whole-tree regen left
docs/design-failure-modes.md byte-identical, so this contends with nothing.

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

Six arms, two repetitions, one dispatch, agreeing within 1%. Acquisition over
the lens pool 592-597ms; the closure list 9ms; the reachability walk
4399-4412ms; the walk PLUS the determinism fold over every reached
declaration's whole subtree 4341-4351ms.

THE FOLD IS FREE, which refutes the other obvious hypothesis -- including the
one this branch's own PR body advanced. Adding determinism_findings measured
BELOW the walk alone in both repetitions. So its concat accumulator is not the
cost either, and a lane that optimises it will move nothing.

THE WALK IS POOL-SENSITIVE AT A FIXED REACHED SET. Holding the entry and the
closure fixed -- lens modules only, so the reachable set is identical -- while
enlarging only the candidate pool from src/v2/lens to src/v2/lens plus
src/v2/std: acquisition 592-597ms -> 1905-1950ms, walk 4399-4412ms ->
8474-8637ms. This is the arm neither #10744 nor #10753 ran, and it is the one
that separates the fit from the mechanism: #10744's pool term is corroborated,
and it lives inside the reachability walk.

WHICH construct inside the walk is pool-proportional remains unattributed. The
per-lookup rescan is refuted, so it is something else; one candidate a reader
should not skip is the eval-frame memo's own keying, which must derive a key
from the pool-sized argument on every call -- a provider that removes a
pool-sized scan can reintroduce a pool-sized cost in its key. Written as the
hypothesis it is.

Two honesty items. Whether each arm re-pays acquisition or is served from a
cross-witness share is not pinned by this run, so the ratios are directional
and not quotable as exact. And interrupted_before_verdict is a disposition
shared across unrelated subjects -- it appears on main-tip receipts for
outside_modeled_guarantee_witness_test and carrier_reference_integrity too --
so the row no longer lets a reader infer it names this population.

Recorded and NOT recorded as a cost result: on main tip 9b341e1 this witness
appears only in a roster membership list, not on a BLOCKING line. Those are
consecutive main tips rather than a controlled comparison, so absence of a
blocking line settles urgency, not cost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
Two findings, both correct, both against DESIGN authorities this row itself
invokes.

FIRST: the rewrite deleted the instrument-naming sentence and expanded the
transcription. The old trigger carried a re-derivation recipe; the replacement
dropped it and copied in a full result table instead. That reproduces, one
layer up, exactly the failure this row records -- figures unreachable from the
thing that owns them, rotting untouched, with the recipe to re-derive them
deleted to make room. DESIGN section 6: name the instrument, never transcribe
its output.

The fix is a real entry point rather than fewer digits.
scratch-probe/test/claim/fn_index_attribution_probe.dag lands as the named
instrument, with the claim_batch invocation that runs it, an account of what
each arm isolates, and why arm f -- entry and closure fixed, pool enlarged, so
the reached set is unchanged -- is what separates the fit from the mechanism.
It lives in scratch-probe because it is an instrument and not a floor witness,
and its rows assert only non-emptiness; that is stated so nobody reads them as
coverage. The trigger now names it and states findings qualitatively. For the
index comparison it cites gunbc#10753, which carries its own method and
pre-registration, rather than copying that PR's figures here. Every transcribed
measurement is gone from the row.

SECOND: the annotation block and the trigger string had become two carriers of
the same content -- the memo mechanism, the verdict rule, the ranges, the
n=1 story, the fit/mechanism split, the withdrawn ruling, all in both. In a row
whose subject is a duplicated authority that is the fork it exists to prevent.
The typed field is the authority for how this drop ends, so it carries the
prescription, the evidence and the instrument. The annotation keeps only what
the field cannot: why a trigger is withdrawn rather than weakened, why a correct
fit carrying a false mechanism is the dangerous artifact, and why the numbers
are not written down.

docs/design-rung-drops.md regenerated; design-failure-modes.md byte-identical.

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

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Both findings in review 61856 are correct and both are now fixed in code, not argued away.

Finding 1 — deleted the instrument-naming sentence and expanded the transcription. This is the sharper of the two, because it is the same failure this row exists to record, committed one layer up: I removed a re-derivation recipe and replaced it with a larger pile of figures unreachable from the thing that owns them. That the row's own thesis is "a stale attributed number recruited a lane to the wrong repair" makes it worse, not better.

The fix is a real entry point rather than fewer digits. scratch-probe/test/claim/fn_index_attribution_probe.dag lands as the named instrument, carrying the claim_batch invocation that runs it, what each arm isolates, and why arm f — entry and closure held fixed while only the pool grows, so the reached set is unchanged — is the arm that separates the fit from the mechanism. It sits in scratch-probe because it is an instrument and not a floor witness, and its rows assert only non-emptiness; that is said explicitly so nobody reads them as coverage.

The trigger now names that instrument and states its findings qualitatively (the fold is not the cost; the walk is pool-sensitive at a fixed reached set; the construct inside the walk is unattributed). For the index comparison it cites #10753, which carries its own method and pre-registered verdict rule, instead of copying that PR's numbers across. Every transcribed measurement is gone from the row — no ms figures, no normalised ratios, no percentages.

Finding 2 — two carriers of the same content. Also correct, and in a row whose subject is a duplicated authority it is the fork the row exists to prevent. The typed field is the authority for how this drop ends, so restoration_trigger now carries the prescription, the evidence and the instrument. The // block keeps only what the field cannot: why a trigger is withdrawn rather than weakened, why a correct fit carrying a false mechanism is the dangerous artifact, and why the numbers are not written down here. The memo mechanism, the verdict rule, the ranges and the n=1 story appear once each.

One thing I did not change, so it is visible rather than silent: SUFFICIENT FOR and its WITHOUT NARROWING THE SUBJECT clause are untouched. That clause is correct and load-bearing — it is what kept this lane out of the trap — and the correction is to the mechanism and the prescription, not to what is being restored.

docs/design-rung-drops.md regenerated; docs/design-failure-modes.md came back byte-identical.

…review 61869)

attribution.probe.sh was a throwaway dispatch wrapper used to run the probe on
a remote runner. It was never meant to land; a git add -A swept it into the
commit, at repo root, with no header, no marker and no dissolution trigger.

The reviewer is right on both counts and either alone is disqualifying.

DESIGN section 6 names this shape exactly -- a hand-authored script performing
out-of-band actuation -- and section 5 admits a scaffold only with a documented,
bounded dissolution trigger, which this had none of. A root-level filename that
reads as permanent is the worst version of it.

And it forked an invocation the corpus already owns. The entry path, the three
source roots and the six function names were restated in the shell script and
again in the rung drop's restoration_trigger, so the two could drift apart
independently: rename an arm and the script silently runs a stale --functions
list while the row still reads correctly. In a PR whose whole subject is naming
the instrument rather than transcribing it, this file transcribed the
instrument's INVOCATION into a second, unmodeled medium.

Deleted rather than modelled and marked. The row's prose already carries the
recipe, so the second carrier buys nothing that would justify keeping it under
a trigger.

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

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Correct on both counts in review 61869, and it is a clean catch — attribution.probe.sh is deleted.

It was a throwaway wrapper for dispatching the probe to a remote runner and was never meant to land. A git add -A swept it in, at repo root, with no header, no marker and no dissolution trigger. Neither the accident nor its convenience is a defence: §6 names the shape (a hand-authored script doing out-of-band actuation), §5 admits a scaffold only with a documented bounded trigger, and this had none.

The second half of the finding is the sharper one and is the reason it is deleted rather than modelled and marked. It forked an invocation the corpus already owns — entry path, three source roots, six function names, restated in the script and again in the row's restoration_trigger. Rename an arm and the shell script silently runs a stale --functions list while the row still reads correctly. In a PR whose entire subject is naming the instrument rather than transcribing it, that file transcribed the instrument's invocation into a second, unmodeled medium. Keeping it under a trigger would buy nothing the row's prose does not already carry, so the honest disposition is removal.

Nothing else in the change moves; the row and the probe are unchanged.

Brian Searls and others added 3 commits September 7, 2026 11:25
…o wrong ones

Two single-tip readings were made in one night, in opposite directions, and
both were wrong for the same reason: a roster appearance and a blocking
appearance are the same population sampled twice. 9b341e1 showed the
witness reaching a verdict; #10764 -- eight lines of Rust comment, no .dag --
showed it interrupted before one. Since #10764 changes nothing this row
reads, the intermittency is a property of main, not of any branch.

The row now says INTERMITTENT, which is what the original brief said before
either observation. It also records why an intermittent blocker is worse
than a steady one: the principal paying the cost is not the one who caused
it (DESIGN.md 1).

Also declares the scratch-probe exposure: fn_index_attribution_probe.dag is
cited by this row but reached by no compiled closure, so it can rot silently.
The alternative -- homing it under a source root -- would put six multi-second
claims on the floor, which is the worse trade. The exposure is stated rather
than left silent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
…estion (review 61911)

The row justified leaving the attribution probe outside every compiled
closure by saying enrolment would put six multi-second claims on the
required floor. That priced RUNNING the arms, but the exposure is about
COMPILING them, and a compile-only enrolment buys the typecheck without
running anything. The argument was wrong, not merely weak.

The real reason is a boundary, not a trade: the compile-only surface is
gunbc.ci_layer_roots.compile_clean_source_roots, and a root added there
must also be added to the partition that
dag_compile_clean_shard_a_witness_test.compile_clean_partition_boundary_matches_compile_clean_source_roots
checks against it. That widens what four serial full-corpus compiles cover
on every push and pull request -- a roster this repository holds closed to
growth without operator sign-off, and one this lane's brief forbids
outright. The discharge stays available to whoever may perform it, and the
row now names it precisely enough to be taken in one edit.

The probe also gets the dissolution it lacked: it exists only to attribute
the cost this row leaves unattributed, so the lane that either retires the
row or names the pool-proportional construct deletes the module in the same
change. An instrument that outlives its investigation is residue and this
one is not exempt for being cited.

And arm g lands beside f, because f's whole discrimination rests on the two
walks reaching the same set -- which was an argument from "the closure
bounds the walk", a true fact about a different subject than what a given
run enumerated. g measures the two reached-set sizes and is red if they
differ; reached_sizes reports the numbers rather than only the verdict.

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

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Taken, review 61911 — and the central point is right in a way worth stating plainly rather than just patching.

The argument I had written was wrong, not merely weak. It priced the cost of running the six arms and offered that as the reason they are not enrolled — but the exposure the review names is about compiling them, and a compile-only enrolment buys the typecheck without running anything. I never addressed it. That is the same shape as the errors this row exists to record: a true sentence doing duty for a different subject.

What replaced it is a boundary rather than a trade. The compile-only surface is gunbc.ci_layer_roots.compile_clean_source_roots, and a root added there must also be added to the partition that dag_compile_clean_shard_a_witness_test.compile_clean_partition_boundary_matches_compile_clean_source_roots checks against it. That widens what four serial full-corpus compiles cover on every push and every pull request — a standing claim on paid runners, which this repository holds closed to growth without operator sign-off, and which this lane's brief forbids outright ("do not touch ... any budget or roster"). So the exposure is not accepted as a good trade; it is the residue of a discharge this lane may not perform, and the row now names the discharge precisely enough that whoever may take it can do so in one edit: add scratch-probe to those two places and the whole paragraph dissolves. If you would rather I take (a) than (b), say so and I will — it is one line plus the partition, and I stopped only because of the brief.

And I took (b) as well, since the review is right that it was missing entirely. The probe now carries its dissolution on the row that owns it: it exists only to attribute the cost this drop leaves unattributed, so the lane that either retires the row or names the pool-proportional construct deletes the module in the same change. An instrument that outlives its investigation is residue and this one is not exempt for being cited. I agree that a missing dissolution condition makes the finding more severe, and that peano_probe.dag is prevalence and not precedent — I have not cited it.

One thing the same commit fixes that no review caught, because it is my own error of the identical shape: the arm that separates the fit from the mechanism (f) rests entirely on the premise that the two walks reach the same set, and I had that as an argument from "the closure bounds the walk" rather than a measurement of what a given run enumerated. Arm g now measures the two reached-set sizes and goes red if they differ, and reached_sizes reports the numbers instead of only the verdict. I will not quote the f-vs-c discrimination until g is green.

Separately, so a reviewer does not have to rediscover it: the required-witnesses-floor red on the earlier heads was cause=stale_cost_debt on main, not this diff — an identity enrolled in v2.workflow.floor_cost_debt that the tree declares nowhere. gunbc#10763 fixed it and I merged origin/main in rather than edit the roster.

— sent from bright-badger-637

Brian Searls and others added 3 commits September 7, 2026 11:57
…cond one

The two answered the same question -- does enlarging the pool change what
the walk reaches -- so keeping both was two carriers of one fact, which is
the failure review 61856 already caught in this same file. g survives
because it is the enrollable form and it goes red rather than reporting.

The premise it exists to test is measured and holds: both pools reach 89.
So none of the f-minus-c difference is reach and all of it is pool.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
GUNBC_EVAL_MEMO=0 removes the key comparisons AND the retained entries in
one move. So if the 211s frame collapses with the memo off, the keying
hypothesis and the allocation-pressure hypothesis are confirmed equally and
nothing is learned about which. An arm that cannot come out against the
thing it tests establishes nothing, which is this repository's own rule
about discriminating REDs applied to a measurement.

h does the same amount of walking as g -- two full reachability walks in one
eval frame -- while holding the pool at one pool rather than two, so frame
retention and key diversity halve while the walking does not. Against c:
~2x means the blowup needs pool diversity in the frame, so keying survives
and pressure dies; ~13x means two walks in a frame suffice regardless of
pool, which points at retention or at something per-frame that is not
keying at all.

The two walks use different entry modules deliberately. Repeating one entry
hands the second walk an argument-identical call the memo serves outright,
which would measure the memo working rather than the frame cost under test.

The header also now records that claim_batch reports VmHWM per PROCESS and
not per witness, so peak RSS is attributable to an arm only when that arm is
alone in the process -- and that frame structure is itself a variable, since
c and f are separate frames while g and h are one frame each. A 211-versus-16
ratio invites a reader to assume different machines or different load; the
frame is the variable and the file now says so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
determinism_live_intra_holds runs at FILE grain over affected_set.dag with
pool_roots EMPTY, and builds its closure from those same empty roots. Arm c
runs at directory grain over a real root list. Those are not the same fold at
two values of n -- the closure term differs structurally, and an empty root
list is a term no arm above exercises.

So arms i, k and l reproduce the floor's subject term by term. l minus i is
what the walk and fold cost at the grain that actually blocks lanes, which is
the quantity a repair aimed at the floor has to move; the directory arms
answer a question about cost SHAPE and are only a magnifier if these agree.

k is not a timing arm. The rung-drop row records that the floor's closure fold
runs over an empty list, and that is why the witness is named intra rather
than transitive. If k goes red that recorded fact is stale and the readings
built on it need revisiting. It is the one arm here that can falsify a
written row.

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

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Pre-registration: how arms i, k and l will be read, written before they return

These are dispatched and not yet back. Recording the readings now so a result cannot be fitted to whichever hypothesis happens to be in hand when it arrives — the same discipline this PR already applies to the index verdict in gunbc#10753.

Why these arms exist. The floor claim that intermittently blocks unrelated lanes — determinism_live_intra_holds — is not the directory-grain arm at smaller n. From the call site:

determinism_live_subject_roots = []                        <-- EMPTY
determinism_live_subject_files = ["src/v2/lens/affected_set.dag"]
closure_modules = fold over module_declaration_facts_live(pool_roots: <that empty list>)

Same fold, structurally different terms: an empty root list for both the pool and the closure, with the pool narrowed by file. No arm measured so far exercises an empty root list. So i (the floor's acquisition alone), l (its body exactly) and k (does its closure contain nothing) reconstruct the blocker term by term.

The shape being tested for, named

If module_declaration_facts_live([]) walks the whole of ctx.modules, that is the absorbing fallback — DESIGN §5: "can't compute the affected set → rerun everything", ⊤-as-answer conflated with ⊤-as-ignorance. §5 says it fails open twice: it destroys the signal that the precise mechanism has a deficit, and its cost is denominated in the corpus rather than the change. 78 declarations costing 503ms would be that second half, measured. The withdrawal note in the witness file records the zero-arity ancestor "always walked the whole of ctx.modules" — the same arm one generation back.

If i and l show that, the finding is not a cost defect at all. It is a fail-open degradation with a cost symptom, and it outranks the memo-keying hypothesis this PR's row currently carries as its named candidate.

The two readings of k, and the green is the confusing one

k_floor_closure_is_empty asserts the floor's closure list contains nothing. It is a claim, not a timing arm, and it is the only arm here that can falsify a row already written.

  • k RED — the closure is not empty. The empty-closure fact recorded in gunbc.rung_drop.determinism_transitive_reachability is stale, and the rename from determinism_transitive_live_closure_holds to determinism_live_intra_holds rests on it. A claim named intra whose behaviour is corpus-wide is a §3 meaning fork, not a naming detail. Every reading built on that fact gets revisited and the rename is treated as suspect rather than as context.
  • k GREEN — the closure is empty, the row is correct, and 78 declarations with an empty closure cost 503ms. This vindicates nothing. It eliminates the closure walk as the payer and leaves the cost unexplained. A green k beside a slow l is a sharper mystery than a red k, and it must not be read as "the row is fine" and set down.

What is deliberately not claimed yet

The 13× frame-sharing blowup in arm g (211s for two walks in one frame, against ~16s for the same two walks in separate frames) is a real finding about the walk's cost shape, but its relevance to the blocker is undetermined until l says the directory arms magnify the floor claim rather than measuring a neighbouring execution. It is not quoted as bearing on the 503ms.

Likewise the mechanism sentence: what survives from gunbc#10744 is the fit — cost is pool-proportional, now confirmed with reached-set size held at 89 across both pools. The causal sentence behind it ("the callee lookup rescans the candidate pool") is refuted by execution and is not restated anywhere in this diff. The honest phrasing is pool-proportional by an unattributed mechanism.

— sent from bright-badger-637

h ran two walks in one frame over one pool and came in near c rather than
near 2c. So two walks in a frame is not enough to produce the blowup, and
neither is anything per-frame that does not depend on the pool. What
survives is pool diversity -- and h cannot say which kind, because one pool
means one key universe AND one retained pool at the same time.

m takes those apart. It acquires both pools in one frame, so retention
matches g, while walking only the small one, so the repeated pool-sized
probes match c. Near c+e means two-pool retention is free and the cost needs
two pools flowing into repeated probes, which is the keying signature. Near
g means retention is the payer and the memo-keying hypothesis is dead.

Run under GUNBC_INTERP_STATS=1, which prints retained-value accounting and
VmHWM, so the memory half is measured rather than inferred from time.

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

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Pre-registration II: arm m, including the middle — written before it returns

Both ends were registered when m was built. Registering the middle now, because that is where a result gets fitted to whichever hypothesis is in hand.

What is being asked, in its strongest form

This is not a new hypothesis. claim_batch carries, at the frame-exit call, the comment that this is "the exact path the 6-witness 20GiB-kill recipe runs (the memo must not retain values across witnesses sharing this ctx)". So this memo has already killed the binary once at 20 GiB, and eval_call_memo_frame_exit is the repair that landed for it. The question is whether that landed repair is sufficient — not whether some speculative defect might exist.

What h established, and what it did not

h (two walks, one frame, one pool) came in at 1.10× c, not 2×, not 13×. That kills frame-sharing per se as the payer, and anything per-frame that does not depend on the pool. It does not exonerate memory pressure: with one pool, h holds one key universe and one retained pool, so retention was never varied. A design that cannot vary a factor cannot clear it.

m is the only shape that moves retention while holding the probe universe fixed: acquire both pools, walk one.

The three readings

m lands at reading
~c+e (~8s) two-pool retention is free. The cost needs two pools flowing into repeated probes — the keying signature, not the pressure one.
~g (~200s) retention is the payer. The memo-keying hypothesis is dead, the repair is about footprint rather than key derivation, and the observation below needs re-explaining rather than keeping.
anywhere between (say 40–80s) neither factor is "the payer." The single-payer framing is retired: the question stops being which of two and becomes how they compose, plausibly multiplicatively. The next arm then varies pool size at fixed diversity, to see which term carries the growth.

The middle is registered because it is the outcome to expect if both factors are real, and it is the one most easily narrated away as "mostly keying" or "mostly pressure" after the fact.

The observation m will confirm or destroy

Flagged as observation, not result: in h the second walk cost ~0.6s against the first's ~6s, over an identical pool. So the memo is excellent on identity and catastrophic on diversity. That is a mechanism-shaped statement — it says the memo has a probe whose cost is a function of how different the keys are, which is what a structural comparison over a pool-sized value looks like and is not what allocation pressure looks like. If m shows retention is the payer, this observation needs re-explaining rather than keeping.

Why the memory half is no longer inferred

Every arm so far shares one weakness: footprint inferred from wall time. GUNBC_INTERP_STATS=1 makes claim_batch print retained-value accounting for the data cache and pure-call memo, plus VmHWM. m, c and g are dispatched under it.

And the finding that reframes the blocker, from i/k/l

  • i floor acquisition alone — 27ms
  • k floor closure is empty — GREEN, 0ms
  • l the floor claim's body, exactly — 228ms, against a 500ms line

k green refutes the absorbing-fallback suspicion I raised in the previous comment: module_declaration_facts_live([]) returns nothing rather than walking ctx.modules. Empty roots means empty. §5 does not apply to this call, and the zero-arity ancestor's behaviour did not survive into the current builtin. Green k also confirms the rung-drop row's empty-closure fact is current and the intra rename is sound rather than a §3 meaning fork.

And l at 228ms means the floor claim run alone is at less than half its budget, while the same claim measures 503ms in CI. The claim is not slow — it is slow in company. That gap alone proves nothing (different machines, different load), so the discriminating arm is l alone versus l beside deliberately pool-diverse company in the same dispatch on the same machine; it is running now. If l inflates there, the subject is cross-claim interpreter state rather than fn_index or the lens, and every repair aimed at the walk since gunbc#10744 — including the index in gunbc#10753 — was aimed at the wrong thing.

— sent from bright-badger-637

@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

A green run is not an acceptance test for any repair to this subject

Stated now, while nobody has a repair to defend. This is the discipline that has to hold when the arms come back, so it goes on record before they do.

There are at least two independent contributors to this blocker.

  1. A cost tier the budget subtraction cannot see. budgeted_cpu_nanos() is thread_cpu_nanos() minus shared_artifact_fill_cpu_nanos(), and that fill total accrues only inside CrossClaimFillGuard::enter(func_name) — the RAII scope for "one admitted call that missed the cross-claim memo". The eval-frame call memo is a different tier: keyed by fn-node identity × argument identity, evicted per witness frame, no producer name, no guard, no ledger row. Its cost accrues inside the claim's ordinary eval, so thread CPU rises and fill does not.

  2. A recorded, unexplained environment variance. v1_interpreter carries, as a declared transcription exception, byte-identical evaluator steps measured against 1.31×–1.80× CPU, and a thirty percent swing in a whole run's total claim CPU across two runs of the same tree. Explicitly not pursued at the time.

The methodological consequence

A claim sitting 3ms over a 500ms line in a process with 1.31×–1.80× step variance will go green sometimes with nothing fixed at all. So the first green after any change to this subject carries almost no information — and it is exactly the observation that will be offered as proof that the change worked.

Acceptance evidence here must be a distribution over repeated runs, on the same machine, before and after. A single green run establishes nothing. A single red run establishes nothing either. This is the same rule this PR already applied to the index verdict in gunbc#10753 — pre-registered rule, n=3, disjoint ranges — and it applies with more force here, not less, because the margin is 0.6% rather than a factor.

It also means a repair to either contributor alone will look partially effective while leaving the intermittency in place. Partial improvement must not be read as a fix.

What is already established, independent of the arms

Whether or not the eval-frame memo turns out to be the payer, this much is true from the code and does not wait on a measurement: a cost tier exists that the fill subtraction cannot see, and a merge-blocking per-claim budget is enforced on the difference. The measurement decides how much that matters; it does not decide whether it is true.

The precise defect is not "fill is broken" — fill works, and is scoped to one tier deliberately. It is that budgeted_cpu_nanos is named for the wider question and computes the narrower one: the name promises "what this claim owes", the body computes "thread CPU minus admitted cross-claim producer fill". One name carrying two materially different meanings, where every consumer — including a merge-blocking budget — reads the wider. That is §3, not only accounting.

Both of those belong in gunbc.recurring_failure_mode rows and will land as a follow-up rather than here, since this PR's subject is the rung-drop correction and it is already at the approval floor. The second row has a §6 defect of its own worth naming: the variance figures were transcribed into a comment because their only other home was logs that age out — which is backwards. A measurement worth keeping is worth an entry point that re-derives it; transcribing it froze a number nothing can refresh, and nobody can now say whether it is still 1.31×.

— sent from bright-badger-637

…utlived all of them

The row had been holding its position open for a cause. That was backwards.
What is established is not a mechanism but a shape -- the walk's cost is
proportional to the pool it is HANDED rather than to what it REACHES -- and
it is established three independent ways: the reached set is pinned equal
across a small pool and a much larger one, so reach is constant while cost
moves; and the cost ratio between those pools is the same with the
eval-frame memo on as with it off.

That third measurement is what makes it a shape rather than an
implementation detail. A cost that tracks the pool identically with a
caching tier present and absent is not a property of that tier, of any key,
or of any index. It is invariant under every mechanism proposed here and
refuted here, which is a stronger result than a mechanism, not a weaker one.
DESIGN section 2 prices a proven cost-shape defect as always worth fixing
regardless of realized n, and does not make that conditional on naming the
cause. A measured defect with no carrier is how a defect becomes ownerless.

The refuted candidate is removed rather than left standing. Its death
condition was written before the arm ran -- if pool sensitivity survives
with the memo off, keying is not the cost -- and it survives. Recording the
death keeps the next lane from spending a dispatch re-killing it.

The same arm carries a constraint the next lane will not expect: with the
memo off these arms run about two orders of magnitude slower. The memo is
not a cost on this path, it is very nearly the whole performance of it, and
it is invisible in the .dag source -- so a later simplification that
bypasses it will look clean and will make this walk a hundred times slower.

And the row now says what it does not claim. Reproduced term by term at the
floor's own grain, the claim runs at well under half the per-claim line, and
running it beside deliberately pool-diverse company on one machine does not
move it. The shape defect is real AND is not the blocker's excess. A lane
that fixes the shape should expect the intermittency to survive it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
Brian Searls and others added 3 commits September 7, 2026 12:35
… every arm

Learning that the claim's own cost is well under half the line makes a
bigger line look reasonable. It is not. A budget cannot distinguish a claim
whose true cost is half the line from one measured at the line when the
environment is separately recorded as swinging by more than a factor of two
on byte-identical evaluator steps. That is a measurement trustworthiness
defect, not a threshold defect, and the repair is never a bigger number --
which is the escape hatch DESIGN section 5 forbids, stopping the refusal
without stopping the wrongness.

The row also carries a reading, labelled as one because it explains every
arm at once and that is exactly when to be careful: the eval-frame memo is
evicted per witness frame, so diversity between claims is cleaned up while
diversity within one frame is not. That predicts all three observations
without residue, and it carries the consequence a later lane must not miss
-- the within-frame blowup does not bear on this blocker, so whoever
re-derives it will have found something real and will be wrong to call it
the cause. Its payer is not retention, refuted by two independent
instruments; before those two, every arm inferred memory from time, so a
timing result and a memory story could not disagree.

And the machine-population boundary is now explicit. Every measurement
behind this row was taken on remote build executors; the line is enforced
on the required-lane CI runner. A distribution measured on the first says
nothing about the second.

The instrument gap is declared with its trigger named as a capability
rather than an artifact. The analysis already exists and must not be
re-minted -- gunbc.floor_cost_distribution models the cost as a coproduct
so a censored bound cannot be divided as a cost, and
identity_inflation_permille_at_equal_work already pairs rows by identity
and equal evaluator steps. What is missing is an actuator that can run it
on demand, and the one that exists runs only inside CI. An actuator that
reaches only a build executor does not retire the trigger, because it
cannot observe the population the refusal fires on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
Harvest the retained required-floor claim-cost artifacts from successful
main runs, take this claim's rows, and group by eval_steps so work is held
constant -- which is what the existing pairing authority exists to do.
Eighteen of twenty recent runs share one step count. Across those eighteen,
at byte-identical evaluator work, with no change to the claim and none to
the tree, observed CPU spans nearly 1.4x and its top reaches 99% of the
per-claim ceiling.

A claim whose cost distribution at fixed work already touches its own line
needs no cost defect, no drift, no accounting hole and no mechanism to
refuse intermittently. It needs only to be sampled again. That is the
intermittency, and it is why this refuses on changes touching nothing near
it.

Two readings were proposed and withdrawn on the way there, both recorded
because both are tempting: a drift across a level change, which dissolved
once the smaller group was compared against the larger group's actual range
rather than its mean; and a small-sample variance figure that understated
the spread, which is what made the groups look separated at all. One error
twice -- a sample too small to see its own width.

The refusal is correct as a MEASUREMENT and wrong as an ATTRIBUTION, and
that distinction decides the repair. The CPU was really consumed, so the
gate is not lying; but the cost is not a property of this claim's code. A
per-claim threshold enforced on one draw from a distribution this wide is
estimating a statistic it cannot see from a single sample. Raising the
ceiling silences the wrong half and destroys the evidence, so no number
moves.

The repair is margin, and it is the pool-proportional shape already
established -- never the blocker, still the fix, and needing no separate
justification under section 2. The acceptance target is derived rather than
guessed: holding the line against that spread requires the median below the
ceiling divided by the spread, about a 10-15% reduction. And acceptance
evidence is a distribution at equal work before and after, never a green
run: a claim this near its ceiling goes green sometimes with nothing
repaired.

The trigger narrows again. CI already emits and retains the artifact on the
enforcing population, so what is missing is a HARVESTER, not an actuator --
no runner capacity, no new job. It is denominated in displaced cost: this
account was produced by hand from artifacts already on disk, and nothing in
the tree can produce it again tomorrow. But it must not land before the
provenance it needs, because the fold holds work constant so only
environment can differ and cannot say which environment either side ran in.

And a receipt for the cost coproduct, because it is a rung claim with an
execution behind it: the observation that opened this investigation was a
budget-refused reading -- a bound, not a cost. It was the most persuasive
number available and it is inadmissible in any ratio, and the model refused
it structurally rather than a reviewer having to catch it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
…rupt (review 61935)

The restoration_trigger had become a withdrawal sentence followed by two
rival triggers at two different subjects -- cost attribution and measurement
trustworthiness. DESIGN section 4b(3) is explicit that a drop is retired by
its trigger and by nothing else, so the trigger is the whole check, and a
field carrying two of them at different subjects is not checkable by any
later lane. That is the untracked-stall shape, not an honest withdrawal.

The field now opens with one trigger at capability grain: the walk's cost
becomes proportional to what it REACHES rather than to the pool it is
HANDED, sufficient for determinism_transitive_holds to reach a verdict
within the line at directory grain without narrowing the subject. Everything
after that sentence is marked as evidence, not a second trigger.

Writing it that way exposed that "no repair until the cost is attributed"
was itself wrong. The trigger does not need the construct named -- it names
the cost SHAPE the capability requires, which is what was measured, and a
lane that reaches it has restored the capability whether or not it can say
which construct was responsible. So the unattributed construct is an open
question under the trigger, not a rival to it. And the trigger was REPLACED
rather than weakened: the old one prescribed an implementation that is
refuted, and a trigger naming a repair that does not work is worse than one
naming none, because it stays satisfiable while the capability stays dead.

The harvester obligation is now explicitly not a trigger of this drop --
different subject, different invalid state, its own carrier.

Separately, the blocking arm is identified and it is not an overrun. On the
runs where this claim blocks, the row is verdict_reached=FALSE with a
right-censored cost and FEWER evaluator steps than any completed run,
because it never finished; on red runs where it did finish it came in under
budget. So the arm is interrupted-before-verdict, and that is a stronger
reason to exclude such a row from the distribution than "a bound is not a
cost": it is not a sample from that distribution at all, being the cost of a
computation that did not happen. It also makes margin worth more than it
looks -- an overrun is a cost debt on a claim that passed, an interrupt
leaves the subject undecided and is the arm that refuses.

The refusal behaviour of that arm is cited rather than absorbed:
gunbc.recurring_failure_mode.non_verdict_disposition_surfaces_as_refusal
already records that the floor computes the difference between a wrong
subject and an unfinished one and then discards it at the aggregate
boundary. That is a different defect and it is that row's to repair.

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

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Taken, review 61935 — and the finding is right in a way that changed the substance, not just the wording.

The defect was real and it was in the one field where it matters most. §4b(3): a drop is retired by its trigger and by nothing else, so the trigger is the whole check. Mine had become a withdrawal sentence followed by two rival triggers at two different subjects — cost attribution and measurement trustworthiness. A later lane could not have checked it, which is the untracked-stall shape rather than an honest withdrawal.

The field now opens with one trigger, at capability grain:

the reachability walk's cost becomes proportional to what it reaches rather than to the pool it is handed, sufficient for determinism_transitive_holds to reach a verdict within the per-claim line at directory grain without narrowing the subject.

Everything after that sentence is explicitly marked as evidence rather than a second trigger.

Three things fell out of writing it that way, and the first is a correction to my own previous commit:

  • "This row prescribes no repair until the cost is attributed" was itself wrong. The trigger does not need the construct named. It names the cost shape the capability requires — which is what was actually measured — and a lane that reaches reach-proportional cost has restored the capability whether or not it can say which construct was responsible. The unattributed construct is now an open question under the trigger, not a rival to it.
  • The trigger was replaced, not weakened, and the row says so with the reason: the previous one prescribed an implementation (answer by index) that is refuted by execution. A trigger naming a repair that does not work is worse than one naming none, because it stays satisfiable while the capability stays dead. §4b(3)'s own rule — the trigger must name the capability, not an artifact that would contribute to one — is what the old one violated.
  • The harvester/provenance obligation is now explicitly not a trigger of this drop. Different subject, different invalid state, carried by its own row.

Separately: the blocking arm is an interrupt, not an overrun

Harvesting the red main runs as well as the green ones: on the runs where this claim blocks, its row is verdict_reached=FALSE, right-censored, with fewer evaluator steps than any completed run — fewer precisely because it never finished. On red runs where it did finish it came in at 451/459/475, under budget, red for other reasons.

That is a stronger reason to keep such a row out of the cost distribution than the one I gave earlier. I said a bound cannot be divided as a cost. The accurate statement is that it is not a sample from that distribution at all — it is the cost of a computation that did not happen. Same underlying fact, different arm: a claim whose completed-cost distribution touches its ceiling will, on a bad draw, hit the deadline before finishing, and then it does not report a larger number, it reports no verdict.

It also changes what margin buys. An overrun is a cost debt on a claim that passed; an interrupt leaves the subject undecided and is the arm that refuses.

The refusal behaviour of that arm is cited rather than absorbed — gunbc.recurring_failure_mode.non_verdict_disposition_surfaces_as_refusal already records that the floor computes the difference between "this subject is wrong" and "I did not finish looking at this subject" and then discards it at the aggregate boundary. That is a different defect, it is what makes an interrupt here block an unrelated change, and it is that row's to repair. Pointing at it also keeps this row from growing a second subject — which is precisely what this review blocked.

— sent from bright-badger-637

…w 61947)

The rung-drop row said the harvester and provenance obligation belonged in
its own carrier and then kept it, which is the fork section 3 forbids --
each fact in exactly one place -- and section 4b names the destination for a
newly discovered error class. Saying where a fact belongs is not the same as
putting it there.

So it is filed:
gunbc.recurring_failure_mode.inflation_fold_cannot_name_the_environment_it_measures.
An analysis that holds WORK constant so that only ENVIRONMENT can differ,
and carries no field naming which environment either side ran in. The
pairing fold refuses censored readings, refuses unequal step counts and
refuses below a minimum base cost, so it reads as defensive -- it is
defensive about everything except its own subject.

Writing it as a row sharpened it twice over the paragraph it replaces. The
rung is mitigatable and protected only by UNREACHABILITY, not by a wall:
every reading comes from CI today so every pair is same-population by
accident, and the first producer elsewhere removes that protection. And the
ceiling is structural impossibility, because a machine population is a
modeled fact and equality of two declared values is decidable -- so the
trigger is that a cross-population figure cannot be CONSTRUCTED, not that it
does not currently occur.

The repair is also not a column: provenance is a fact about the run, so a
constant-across-rows column would be a per-row representation of a per-run
fact. It belongs on RunCost, read once from the header, with the parser
refusing a header that names no population rather than defaulting it -- and
the fold must join on it, because a field a consumer must remember to
consult would be this module's own filed class committed a second time.

The rung-drop row now cites that class in one sentence and states that it
is not a trigger and cannot retire the drop.

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

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Review 61947 — first finding fixed, second escalated rather than answered a fourth way.

The trigger no longer stores a second subject

The reviewer is right, and the phrasing that gave it away was mine: saying a fact "belongs in its own carrier" and then keeping it here is exactly the fork §3 forbids, and §4b names the destination for a newly discovered error class. Saying where a fact belongs is not the same as putting it there.

So it is filed: gunbc.recurring_failure_mode.inflation_fold_cannot_name_the_environment_it_measures, rostered, with evidence pointing at identity_inflation_permille_at_equal_work, RunCost and claim_cost_required_columns. The rung-drop row now cites it in one sentence and states plainly that it is not a trigger of this drop and cannot retire it.

Writing it as a row sharpened it beyond the paragraph it replaces, which is the argument for the reviewer's rule rather than just compliance with it:

  • The rung is protected by unreachability, not by a wall. Every reading comes from CI today, so every pair is same-population by accident. The invalid state is fully writable; the first producer elsewhere removes the protection. That is a §4b distinction the paragraph never made.
  • The ceiling is structural impossibility, because a machine population is a modeled fact and equality of two declared values is decidable — so the trigger is that a cross-population figure cannot be constructed, not that it does not currently occur.
  • The repair is not a column. Provenance is a fact about the run, so a constant-across-rows column would be a per-row representation of a per-run fact (§2). It belongs on RunCost, read once from the header, with the parser refusing a header naming no population rather than defaulting it — and the fold must join on it, because a field a consumer must remember to consult would be this module's own filed class committed a second time.

The probe: escalated, not argued

The second finding is correct and it invalidates the discharge I gave review 61911. I answered that one with a dissolution condition, and §5 says a dissolution condition describes how admitted debt ends and does not authorize creating it. That is a direct answer to what I did, and I accept it.

I am not fixing it unilaterally, because the fix collides with a standing constraint on this lane rather than with my judgement.

The probe is now load-bearing: this drop's trigger is "the walk's cost becomes proportional to what it reaches rather than to the pool it is handed," and the probe's arms are the only instrument that measures that shape. §6 requires the trigger to name an instrument rather than transcribe its output, so deleting the probe would leave the trigger with no re-deriver — trading one §6 defect for another.

The correct fix is a compile-only enrolment, which the earlier exposure paragraph wrongly priced as a floor cost: adding scratch-probe to gunbc.ci_layer_roots.compile_clean_source_roots and to the partition that dag_compile_clean_shard_a_witness_test.compile_clean_partition_boundary_matches_compile_clean_source_roots checks against it. No arm joins the required floor and no runner time is added; what widens is what four serial per-PR compiles cover. That is a roster edit, and this lane's brief says: "Do not touch #10741, #10748, or any budget or roster."

I have declined it twice on that ground and two reviewers have now called it a defect, so continuing to invent positions would be improvising past a real constraint. It is escalated to the owning manager with option A (make the roster edit) recommended, on the reasoning that an instrument a rung-drop trigger depends on, which nothing typechecks, will rot silently and take the trigger's evidence with it. I will act on the ruling.

— sent from bright-badger-637

Brian Searls and others added 5 commits September 7, 2026 13:54
l runs the floor claim's whole body -- walk plus the determinism fold over
every reached declaration's subtree -- so it cannot say which to make
cheaper. n runs the walk at the floor's own terms and nothing else, so l
minus n is the fold at the grain that blocks.

And the directory-grain answer does not transfer. The floor's closure is
empty, so decls_in_modules returns nothing for every callee and the walk
follows no edges: it drains its seeds and stops. A walk following no edges
cannot be pool-proportional, so the term this drop's trigger names is not
exercised at floor grain at all, and whatever costs 200ms there is a
different construct from the one the directory arms measure. Aiming the
repair from those arms would fix a real defect this claim does not pay.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
…-637-drop-trigger

# Conflicts:
#	docs/design-failure-modes.md
… figure

One sentence to save the next harvester an afternoon. An interrupted claim
stopped wherever it had got to when the deadline fired, so its step count
records how far it got and nothing else: two observed interrupts on this
claim truncate at different step counts, both far below every completed run,
and neither denotes a workload.

The harvest this row describes groups by eval_steps to hold work constant,
which is correct only over completed rows. Group the censored ones the same
way and they form a third apparent level out of nothing but where the
deadline landed -- a bogus population that would look exactly like the drift
finding this row already withdrew once.

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

The floor-grain walk costs ~134ms over 78 seeds while following no edges.
Costing the three list shapes at their worst -- decl_in_list scanning
reached, list_snoc_item copying it, list_append copying the remaining seeds
-- gives roughly nine thousand element operations, so 134ms implies about
fifteen microseconds per element touch. That is at the top of defensible for
an interpreted list operation rather than comfortably inside it, which is the
signal that a term has not been named.

The unnamed term is not a list shape. call_reachable_decls_go calls
callees_from_node on every newly reached seed, and that materializes the
WHOLE SUBTREE of the declaration's output node via node_subtree_nodes before
folding over it. That cost is proportional to AST size rather than seed
count, so it is invisible to every list-shape argument and no list fix
removes it.

Arm o folds callees_from_node over exactly the seeds the floor claim walks
and does nothing else, so o minus i is the AST traversal alone. If it is
most of the walk, the list shapes are a rounding error here and a repair
aimed at them moves nothing.

Measuring before repairing is the point: landing three list fixes and
finding the walk still expensive would read as a partial win, and the
remaining payer would never rank.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
callees_from_node does two separable things per seed: node_subtree_nodes
materializes the declaration's whole subtree, cost linear in AST size; and
the fold scans the accumulator on every callee hit, cost quadratic in callee
count. They want opposite repairs. The scan is the cheap one and belongs to
the copied-accumulator family already named here, fixed without touching
traversal. The materialization is the expensive one and is partly
irreducible, since something must visit the nodes.

So going straight from a large o to 'stop materializing' attacks the hard
half first and possibly the wrong one. p materializes exactly what o
materializes and then only counts, so it pays the first and none of the
second; p against o, both netted against the same acquisition, separates
them in one dispatch.

Written now so the split is not designed around whatever number o produces.

And p is only worth running if o comes back large. If o is small the
traversal is not the payer, the list shapes in the walk are, and this arm
and the structural story behind it are both dead -- a tidy account must not
outlive the measurement that contradicts it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
…aths, fold the two trigger histories

#10822 deleted docs/design-failure-modes.md and dag/gunbc/recurring_failure_mode/roster.dag
(both now gitignored and generated before compile; membership is the directory). Both
deletions accepted -- restoring either would re-create the attractor DESIGN §3 names.
inflation_fold_cannot_name_the_environment_it_measures.dag is kept: that per-class file
IS the registration now.

docs/design-rung-drops.md is taken from the base side verbatim, unregenerated, per the
generated-artifact driver's declared repair route; set difference over both row-identity
shapes reports no row gone dark.

determinism_transitive_reachability.dag's restoration_trigger was edited on both sides and
neither subsumed the other. Merged rather than chosen: this branch's capability-grain
trigger (the index prescription is refuted by execution, so the trigger names the COST
SHAPE) is the head, and main's later paragraphs are folded in -- the artifact-not-a-clock
instrument correction, the partition-by-eval_steps rule, the worsening pre-repair
distribution, the three repaired shapes in the past tense, and the map-dedup obligation.
One sentence of main's was rewritten where it cited the CAPABILITY clause that no longer
says what it said.

Compiles: 0 blocking errors on the row's own entry.

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

gunbai-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Status, recorded here because my manager session is no longer reachable on the dashboard channel.

Merged main locally; HELD UNPUSHED at 64e111897e, git merge-tree --write-tree origin/main HEAD rc=0.

  • Stop merging the failure-mode ledger on every append #10822 deleted docs/design-failure-modes.md and dag/gunbc/recurring_failure_mode/roster.dag (both now gitignored and generated before compile — membership is the directory). Both deletions accepted. Restoring either would re-create the attractor DESIGN §3 names in the replacement-migration rule.
  • inflation_fold_cannot_name_the_environment_it_measures.dag kept: that per-class file is the registration now.
  • docs/design-rung-drops.md taken from the base side verbatim, unregenerated, per the generated-artifact driver's declared repair route. Set difference over both row-identity shapes (- `slug` bullets and ### Title — … headings) is empty — no row went dark. This path is held pending Join four cadence rung drops on one executable shared capability #10837.

The one resolution that was judgement, not mechanics

determinism_transitive_reachability.dag's restoration_trigger was edited on both sides and neither side subsumed the other:

Taking either side would have deleted the other's rows, so they are folded: this branch's head, main's later paragraphs appended, and main's single sentence citing "this trigger's CAPABILITY clause" rewritten, because that clause no longer says what it said. Compiles at 0 blocking errors on the row's own entry.

Worth stating plainly: main's landed row still names the refuted index repair as its CAPABILITY. That is the defect this PR exists to fix, and it is live on main right now.

The scratch-probe/ consumer question, answered honestly rather than favourably

It has a named consumer and no executing route. The consumer is the drop row itself, which cites the probe as the instrument that re-derives the attribution and binds the probe's deletion to the row's retirement. The route is the problem: scratch-probe/ is reached by no source root and no scan dir, so it is outside every compiled closure — a rename would rot it with no red anywhere. The row states that exposure in its own text and names the discharge (add scratch-probe to gunbc.ci_layer_roots.compile_clean_source_roots and to the partition dag_compile_clean_shard_a_witness_test.compile_clean_partition_boundary_matches_compile_clean_source_roots checks against it), which is a roster edit this lane's brief forbids and which needs operator sign-off regardless.

By §3c that is a declared frontier at best, not a consumed declaration, and I will not argue it past that. Either disposition is one commit: leave it with the exposure declared, or delete the module and strip its citation from the row. Say which before merge.

— sent from bright-badger-637

gunbc-ci-auto-heal and others added 5 commits September 9, 2026 02:04
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
The drop row's own new comment block says why the numbers are not written down, and the
same diff deposited them in a file that is outside every compiled closure and run by no
lane -- so they rot with LESS chance of anyone noticing than where they came from. That is
the finding and it is correct.

Removed from the probe: the absolute walk cost and seed count, the derived element-touch
arithmetic, the run-to-run spread factor, the machine-population ratio, and the floor-grain
millisecond figure. Each is replaced by the arm that re-derives it. The pre-registered
arm-vs-arm ladders stay -- h ~ 2x c, h ~ 13x c, m ~ c + e, p ~ o -- because a stated
expectation written before the measurement is not a transcription of one.

Removed from the restoration_trigger: the run counts, the spread factor and the
percent-of-ceiling figure, replaced by the harvest that re-derives them. That field
instructed the reader to re-derive both figures from the artifacts two paragraphs after
printing them.

Both files compile at 0 blocking errors on their own entries.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
…al re-derive it

The remote branch carried a gunbc-ci-auto-heal commit on top of my merge, which had
already regenerated docs/design-rung-drops.md from the merged authorities. Merging it back
conflicted on that same generated path, and the driver's declared route applies unchanged:
take the base side verbatim, do not hand-edit, do not regenerate locally, let
heal-generated-artifacts derive it from the merged authorities.

Verified by set difference over both row-identity shapes rather than by count: no row goes
dark against main, and none against the heal head either.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
Two findings, both real.

(1) The leading annotation said the index prescription is "removed and nothing replaces it
until the cost is attributed to a construct that executes", while restoration_trigger opens
with an active capability-grain trigger and says explicitly that naming the construct is
NOT required to retire the row. That is a meaning fork between quarantine prose and the
typed carrier -- and by this row's own argument, the reader follows the prescription rather
than the remark, so the remark being the stale half is exactly the harm. The annotation now
says what replaced the prescription (the cost-shape trigger), names construct attribution
as an open question UNDER it rather than a precondition, and confines itself to why the
withdrawal was a deletion and not a weakening. The field stays the authority for both.

(2) The same field that says THE FIGURES ARE NOT WRITTEN HERE ON PURPOSE still embedded
"roughly ten to fifteen percent of the current median" as the acceptance target and then
told the reader to re-derive it. The formula and the harvest stay; the percentage is gone.
That is the third transcription removed from this row, which is itself the signal: figures
survive in prose because nothing executes over them.

Compiles at 0 blocking errors.

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

gunbai-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

review 62837 — both findings are real and both are fixed in e53933f0.

  1. The annotation contradicted the field it annotates. It said the index prescription is "removed and nothing replaces it until the cost is attributed to a construct that executes", while restoration_trigger opens with an active capability-grain trigger and states explicitly that naming the construct is not required to retire the row. The sharp part of your finding is that this row's own argument condemns it: the reason a false prescription must be deleted rather than annotated is that the reader follows the prescription and not the remark — so the remark being the stale half is precisely the harm the paragraph describes. The annotation now says what replaced the prescription (the cost-shape trigger), names construct attribution as an open question under it rather than a precondition, and confines itself to why the withdrawal was a deletion and not a weakening. The field remains the single authority for both.

  2. "roughly ten to fifteen percent of the current median" was transcribed instrument output, inside the field that says the figures are not written down on purpose, two sentences before telling the reader to re-derive them. The formula and the harvest recipe stay; the percentage is gone.

Worth naming rather than fixing quietly: that is the third transcription removed from this row across two reviews — the census denominator, the run counts and spread, and now the acceptance percentage. They keep surviving in prose for the same reason each time, which is that nothing executes over them. §4c is the structural reason: no Accepted program can read an annotation, so a wrong number there has no red to hit and only a reader ever catches it. The reviewers have been that reader three times on this row.

Compiles at 0 blocking errors. CI re-running on the new head.

gunbc-ci-auto-heal and others added 2 commits September 9, 2026 03:21
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
…or: review 62859

Same fork class as e53933f, one paragraph further down, which is the finding worth more
than either fix: this row keeps producing stale annotations because nothing executes over
them.

(1) The annotation recorded this row's interrupted_before_verdict cause as UNVERIFIED
PENDING REQUIRED-FLOOR INSTRUMENTATION while restoration_trigger says the blocker is
accounted for POSITIVELY on the population that enforces the line, via the
required-floor-claim-cost harvest. The instrumentation never had to be built: every
completed witnesses run already publishes that artifact, so the run had been taken and its
receipt was sitting unread. The paragraph now records only how the uncertainty was
resolved and leaves the field as the authority for what the harvest establishes.

(2) The same module cites section 6 and then embedded "6-7 seconds" with no re-derivation
recipe. The figure is replaced by the claim_batch run that re-derives it. The observation
it supports -- that the walk executes and completes at directory grain, and that this says
nothing about the floor -- is unchanged and did not need the number.

That is the fourth transcription removed from this row.

Compiles at 0 blocking errors.

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

gunbai-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

review 62859 — both findings are real and fixed in 5edfdbff. You also identified the pattern correctly, and that is worth more than either fix: this is the same fork class as e53933f0, one paragraph further down.

  1. Annotation said UNVERIFIED PENDING REQUIRED-FLOOR INSTRUMENTATION while the field says the blocker is accounted for positively on the enforcing population. The paragraph now records only how that uncertainty was resolved, and leaves restoration_trigger as the authority for what the harvest establishes. The substance of the resolution is worth keeping visible: the instrumentation never had to be built. Every completed witnesses run already publishes required-floor-claim-cost, so the run had been taken and its receipt was sitting unread — reasoning about a subject an artifact answers directly, which is the recurring shape this row keeps producing.

  2. 6-7 seconds with no re-derivation recipe, in a module that cites §6 eleven lines earlier. Replaced by the claim_batch run that re-derives it. The observation it supported — the walk executes and completes at directory grain, and that says nothing about the floor — is unchanged and never needed the figure.

That is the fourth transcription removed from this row, and the third stale annotation contradicting its own typed field. Both counts have one cause: §4c means no Accepted program can read an annotation, so a wrong number or a superseded disposition there has no red to hit. Every one of these has been caught by a reader, never by a gate — which is the honest rung for annotation prose on this row, and is why the field rather than the prose is repeatedly named as the authority.

Compiles at 0 blocking errors. CI re-running.

…eview 62869

The floor already answered this before the review did. On the previous head every arm of
the probe appears in the required-ci receipt as a BLOCKER --
declined_changed_witness_outside_discovery -- because the change touches the file, so the
floor plans it as a changed witness, and the module is outside the discovery closure, so
the floor refuses rather than skipping. The exposure this row admitted was not theoretical:
it made the PR unlandable.

The row's argument for accepting it is withdrawn as refuted by the tree. It claimed the
only discharge was adding a root to compile_clean_source_roots and to its partition -- a
closed roster this brief forbids. The repository already held the answer:
src/v2/test/claim/long/ is inside a compiled source root, so rot reds like any other
module, AND v2.workflow.required_floor declines the module by AUTHORED NAME through
long_home_prefixes, so eight multi-second arms do not run on every push. Both halves, no
roster edit.

So the module is now v2.test.claim.long.fn_index_attribution_probe at
src/v2/test/claim/long/fn_index_attribution_probe.dag, the scratch-probe/ copy is gone, and
the row's exposure paragraph is replaced by what actually holds. The probe's own dissolution
condition is unchanged: the lane that retires this drop or names the pool-proportional
construct deletes it in the same change.

The floor reads the authored name and not the path, so the name is the admission fact;
long_home_storage_agreement refuses the two states where name and directory disagree.

The row's entry point and citation now name the new module and drop the third source root.

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

gunbai-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

review 62869 — you are right, and the floor had already said so in a receipt I had not yet read when I argued the other way. Fixed in 8c21ae32.

The exposure was not theoretical; it made the PR unlandable. On the previous head, every arm of the probe appears in required-ci-measurement-receipt as a blocker: phase=floor identity=test.claim.fn_index_attribution_probe.<arm> cause=declined_changed_witness_outside_discovery, eight of them. The change touches the file, so the floor plans it as a changed witness; the module is outside the discovery closure, so the floor refuses rather than skips. That is the fail-closed wall working, and my "declared frontier, tolerable" reading was the defect.

And the row's justification for accepting it is refuted by the tree, as you say. It claimed the only discharge was adding a root to compile_clean_source_roots plus its partition — a closed roster this brief forbids — so the exposure was "the residue of a discharge this lane may not perform". The repository already held the answer: src/v2/test/claim/long/ is inside a compiled source root, so rot reds like any other module, and v2.workflow.required_floor declines the module by authored name through long_home_prefixes, so eight multi-second arms do not run on every push. Both halves, no roster edit.

The module is now test.claim.long.fn_index_attribution_probe at src/v2/test/claim/long/fn_index_attribution_probe.dag; scratch-probe/'s copy is gone. The row's exposure paragraph is replaced by what actually holds, its entry point and citation name the new module and drop the third source root, and the probe's dissolution condition is unchanged — the lane that retires this drop or names the pool-proportional construct deletes it in the same change.

One detail worth carrying, since it is the fact that makes the home work: the floor tests the authored module name, not the path, and long_home_storage_agreement refuses the two states where the name and the directory disagree. So the name is the admission and the directory is only storage.

I had recommended keeping the probe where it was, citing peano_probe.dag as precedent. That was wrong for a reason worth stating: peano_probe.dag never blocks because no change touches it, so the precedent only holds while the file is never edited. A location that refuses any change touching it is not viable for a file a PR adds.

gunbc-ci-auto-heal and others added 3 commits September 9, 2026 04:38
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
(1) Lines 68-69 said the floor's disposition for this claim is unpinned and the deadline
question unresolved, while the paragraph below says the uncertainty is resolved and the
typed field says the blocker is accounted for. Same class as reviews 62837 and 62859,
incompletely fixed twice: I corrected the paragraph that stated the conclusion and left the
sentence upstream of it. Now corrected at the point where the claim is made, with only the
part that survives kept -- that a BuildBuddy observation is a different machine population
from the one that enforces.

(2) One sentence called the probe v2.test.claim.long.fn_index_attribution_probe while the
authored module name, and the one the floor's long_home_prefixes test reads, is
test.claim.long.fn_index_attribution_probe. A second name for one module is the nickname
DESIGN 3 forbids, and here the wrong half is the one the admission mechanism does not
match. Corrected, and the sentence now says the authored name is the fact the floor reads.

(3) docs/design-rung-drops.md is stale against this authority. That is the generated
projection under the merge=generated-artifact driver, whose declared route is that
heal-generated-artifacts derives it -- not a hand edit and not a local regen. It is stale
because regen last ran before the probe moved; the run on this head derives it again.

Compiles at 0 blocking errors.

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

gunbai-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

review 62883 — all three verified; two fixed in af233aba, the third is the driver's route rather than an edit.

  1. The stale annotation at :68-69. Correct, and the part worth recording is that this is the third incomplete fix of the same class on this row (after reviews 62837 and 62859): each time I corrected the paragraph that stated the conclusion and left a sentence upstream of it still asserting the opposite. It now says the floor's disposition is no longer unpinned, names the two artifacts that answer it, and keeps only the part that survives — a BuildBuddy observation is a different machine population from the one that enforces, so it cannot be carried across.

  2. The nicknamed module. One sentence said v2.test.claim.long.fn_index_attribution_probe; the authored name — the one long_home_prefixes actually tests — is test.claim.long.fn_index_attribution_probe. A second name for one module is the §3 nickname, and here the wrong half is precisely the one the admission mechanism would not match, so it would have read as a correct citation while naming a module the floor does not know. Corrected, and the sentence now says the authored name is the fact the floor reads.

  3. docs/design-rung-drops.md stale against the authority. Confirmed, and it is the generated projection under the merge=generated-artifact driver, whose declared route is that heal-generated-artifacts derives it — not a hand edit and not a local regen. It was stale because regen last ran before the probe moved; heal has since pushed 10e534c5e5 on this branch, and this head's run derives it again over the new authority. The one remaining scratch-probe occurrence in that file is deliberate: it is the historical sentence recording that the earlier home made the floor refuse every arm, not a live instruction.

I will verify the healed projection names the long home rather than assuming it, and I'll read the floor's disposition artifact to confirm the probe's arms now decline as declined_long_module rather than merely ceasing to block — those are different claims and only the second one shows the move worked for the right reason.

Brian Searls and others added 3 commits September 9, 2026 04:47
…rename the probe

The move into the long home was right and incomplete: the floor refused the whole lane
with FloorDiscoveryRefused -- "`test`-marked decls must live in `*_test.dag` files; found
in: src/v2/test/claim/long/fn_index_attribution_probe.dag". Every sibling in that directory
already carries the suffix; I read the module-name admission rule and not the discovery
rule, and the two are separate walls.

The module is now test.claim.long.fn_index_attribution_probe_test at
src/v2/test/claim/long/fn_index_attribution_probe_test.dag. The row records that the suffix
is required rather than stylistic, and how it was caught, so the next lane moving an
instrument into that home does not repeat the same half-move.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
… touches: the probe does not land

Three placements were tried and all three were refused, and the third refusal is the one
that generalizes.

  scratch-probe/            declined_changed_witness_outside_discovery, eight arms -- a
                            planned witness the floor cannot reach is a typed refusal
  long home, wrong suffix   FloorDiscoveryRefused: a test-marked decl must live in a
                            *_test.dag file
  long home, right suffix   sixteen blockers: six interrupted_before_verdict, two
                            completed_over_cost_requirement, eight
                            changed_witness_planned_without_terminal_verdict

The rule behind the third is in required_floor itself:
required_floor_disposition_with_changed_selection REPLACES the ordinary disposition, so a
long-home decline, a fixture decline and a declared cost-debt withhold are ALL overridden
for a claim whose file the change touches. So there is no directory, prefix or roster that
lets a multi-second claim be added -- or later edited -- without running on the floor of
the change that touches it. An instrument of this cost cannot be a claim here.

So the probe is not landed, and the row says so first, before any finding that depended on
it. It also says what to rebuild and how to run it, and states plainly that this is a
weaker citation than a landed instrument: nothing in the tree re-derives these findings.

That is the honest arm. The alternative was to keep asserting a home that three walls had
already refused.

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

gunbai-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Status: the probe does not land, and the reason generalizes beyond this PR. 210fa277.

Three placements were tried; all three were refused, each by a different wall, and I read each refusal from the run's own required-ci-measurement-receipt rather than inferring it:

placement refusal
scratch-probe/ (no source root) declined_changed_witness_outside_discovery ×8 — a planned witness the floor cannot reach is a typed refusal, not a skip
long home, …_probe.dag FloorDiscoveryRefused — a test-marked decl must live in a *_test.dag file
long home, …_probe_test.dag 16 blockers: 6 interrupted_before_verdict, 2 completed_over_cost_requirement, 8 changed_witness_planned_without_terminal_verdict

The third is the one that matters, and the rule is in required_floor itself: required_floor_disposition_with_changed_selection replaces the ordinary disposition, so a long-home decline, a fixture decline, and even a declared cost-debt withhold are all overridden for any claim whose file the change touches. There is therefore no directory, prefix or roster in this repository where a multi-second claim can be added — or later edited — without running on the floor of the change that touches it. An instrument of this cost cannot be a claim here at all.

So the row now says, first and before any finding that depended on it, that the instrument is not in the tree; it records the three refusals so the next lane does not re-walk them; it says what to rebuild and how to run it; and it states plainly that this is a weaker citation than a landed instrument, because nothing in the tree re-derives these findings.

I want to be explicit that this reverses my own reasoning twice. I argued to keep the probe under scratch-probe/ on a precedent that only held while nobody edited the file, then argued the long home discharged the exposure. The long home was the right idea — compiled, so rot reds — and it still cannot hold this module, because the changed-witness selector outranks every decline. The wall was right each time and my reasoning was what needed replacing.

#10757's diff is now three files: the new failure-mode class, the drop-row rewrite, and heal's regeneration of the projection.

@gunbai-bot

gunbai-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

review 62912 — both findings are the same staleness and I verified it rather than assumed: at the current tip 210fa277, docs/design-rung-drops.md still carries fn_index_attribution_probe_test ×4 and THE INSTRUMENT IS HOMED WHERE A COMPILE CATCHES ITS ROT ×1, with THE INSTRUMENT IS NOT IN THE TREE ×0. So the projection is the pre-deletion text and the authority is the post-deletion text — a genuine meaning fork on one fact, and you are right that the divergence must not ship.

The remedy is the driver's declared route rather than an edit from me: docs/design-rung-drops.md is a generated artifact under merge=generated-artifact, whose repair route is explicitly do not hand-edit, do not regenerate locally — heal-generated-artifacts derives it from the authority and pushes the healed head. That job is running on this head now. Hand-regenerating it in the diff is what the route forbids and what the drift gate would then adjudicate against.

I will confirm on the healed head that the projection carries the deletion text and names no instrument, rather than reporting the route as if it were the result. If heal does not land it, that is a different problem and I will say so.

Worth stating for the record, since it is the third heal cycle on this PR: every substantive correction to this row costs a full CI cycle, because the projection can only be regenerated by CI and the row is heavily cited. That is a real cost of the route, not a complaint about the finding — the finding is correct.

gunbc-ci-auto-heal and others added 2 commits September 9, 2026 06:05
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
…eview 62919

declared_trigger_names_a_term_that_is_not_the_cause names, as a LIVE unremediated
instance, the very trigger this PR withdraws. Merging without touching it would leave the
ledger asserting present-tense corpus state that the same merge makes false -- fabricated
plausible output, from the row whose subject is triggers that name the wrong term.

Three receipts updated, none deleted:

  the live-instance claim becomes the DISCHARGE, dated and attributed, keeping what the
  instance was so the class still carries its specimen;

  "this row does not discharge it" becomes why it could not, kept because the ORDERING is
  the rule -- a replacement capability may only be named by the lane holding the falsifier,
  and the discharge arrived exactly that way, which is evidence the ordering works;

  the instrument receipt said the figures re-derive from the producer the drop row names.
  That row now says the probe was deliberately not landed, so the receipt said the opposite
  of its own authority. It now says the instrument is NOT in the tree, that these figures
  are re-derived by REBUILDING the arms, and why no location can hold them.

Compiles at 0 blocking errors.

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

gunbai-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

review 62919 — correct, and it is the sharpest kind of finding: the ledger row that tracks this defect names, as a live unremediated instance, the exact trigger this PR withdraws. Merging without touching it would have left the ledger asserting present-tense corpus state that the same merge makes false — fabricated output, from the row whose whole subject is triggers that name the wrong term. Fixed in f3f1f50b.

Three receipts updated, none deleted:

  • The live-instance claim becomes the discharge, dated and attributed, keeping what the instance was so the class still carries its specimen. The prescription is recorded as withdrawn rather than weakened, and the replacement is named at cost-shape grain with its SUFFICIENT FOR clause.
  • "This row does not discharge it" becomes why it could not — kept, because the ordering is the rule and not the anecdote: a replacement capability may only be named by the lane holding the falsifier, never by the lane filing the class. The discharge arrived exactly that way, which is evidence the ordering works rather than a reason to relax it.
  • The instrument receipt said every figure re-derives from "the producer that determinism_transitive_reachability names". That row now says the probe was deliberately not landed, so the receipt asserted the opposite of its own authority — your second finding, and it was the more dangerous of the two, because it reads as a re-derivation guarantee. It now says the instrument is not in the tree, that these figures are re-derived by rebuilding the arms, and why no location in the repository can hold them.

That last point is the one I'd flag beyond this PR: the changed-witness selector overrides long-home, fixture and cost-debt declines for any claim whose file a change touches, so a multi-second instrument cannot be added or later edited anywhere here. Three placements were tried and refused before I accepted that. It is recorded in the drop row so the next lane inherits the constraint instead of rediscovering it.

Compiles at 0 blocking errors.

Brian Searls and others added 3 commits September 9, 2026 07:07
…e it

The generated-artifact driver refused docs/design-rung-drops.md, which is what it does when
both sides changed a generated path since the merge base: neither side's bytes are the
projection of the MERGED authorities. Its declared route applies unchanged -- take the base
side verbatim, no hand edit, no local regen, and heal derives it from the merged
authorities on CI.

Verified by set difference over both row-identity shapes rather than by count: no row goes
dark against main, and none against this branch's pre-merge head either.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
…nblock this PR by having something to heal

MEASURED, TWO HEADS ON THIS BRANCH DIFFERING ONLY IN WHO AUTHORED THEM. On f3f1f50, mine,
heal-generated-artifacts RAN, concluded success, and the PR read CLEAN. On 2bc7918,
heal's own auto-heal commit on top of it, heal SKIPPED, the other three jobs concluded
success, the aggregating witnesses job concluded success, and the PR read BLOCKED with
mergeable=MERGEABLE. The combined-status endpoint on that head reports state=pending with
zero statuses.

Nothing regressed between them: the second head is strictly the projection the first was
missing. heal is not wrong to skip on its own commit -- re-healing its own output is how a
loop starts -- but a skipped REQUIRED check is not a satisfied one, so the head that
finally matches its authority is the one head that cannot merge.

The harm is that it is indistinguishable from author error. Four green jobs and MERGEABLE
read as ready, and the lane waits on a merge that cannot happen; the condition that clears
it is another commit, which the lane has no reason to author.

Ceiling 3 with a capability trigger: the healed head's revalidation satisfies every
required context it does not re-run, so readiness is decidable from the head alone.

This commit is also the other commit. It is a real class with an executed receipt rather
than a no-op to move the ref, and it gives heal a drifted projection to regenerate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
@briansrls
briansrls merged commit 8ced37b into main Sep 9, 2026
4 checks passed
@briansrls
briansrls deleted the session/bright-badger-637-drop-trigger branch September 9, 2026 13:55
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