Repository navigation
The callee lookup answers by index, so the determinism walk costs what it reaches - #10753
gunbai-bot[bot] wants to merge 2 commits into
Conversation
…t it reaches v2.std.fn_index.decls_matching_callee evaluated filter(decls_in_modules(decls, closure_modules), name == callee) once per callee per reached declaration -- a full scan of the candidate pool plus one module-membership pass per closure module, per lookup, of a value that is INVARIANT for the whole walk. gunbc#10744 bracketed both populations and separated the models by measurement: O(reached x pool) agrees within 1.9x across file and directory grain, O(reached^2) is off by 44x. The cost tracks the pool the walk was handed, not what it reaches. callee_index_of now computes the closure-scoped population once and keys it by declaration name; call_reachable_decls_go threads that index instead of (decls, closure_modules), and each callee is one map_lookup. Map here is the host-intercepted primitive, not the closure chain its .dag spelling reads as. The answer is unchanged, including order and multiplicity: decls_in_modules concatenates per module in module order and preserves pool order within a module, and the fold appends each declaration to its bucket in that same traversal, so a bucket is the old filter's output verbatim -- duplicates included, since a declaration legitimately matches twice when a closure names both a module and its parent under the dotted-prefix test. The witness widens back to directory grain, which is what the repair is for. determinism_live_intra_holds becomes determinism_transitive_live_closure_holds again over pool_roots=['src/v2/lens'], following callee edges across the whole lens closure. The subject going in is unchanged -- same decls, same closure_modules -- so this is not the scope-the-pool move #10744 names as the trap. The rung drop's retirement follows in this PR once the required floor has produced the charged directory-grain measurement, which is its trigger. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey
This is not the repair. Measured, and my own result was killed by its control.
Both arms are 12–14x the 500ms line. The index does not reach the trigger, and the indexed arm is the slower of the two. Read the control before reading the delta
Pre-registered verdict rule for the alternating run, written before its numbers existThree alternating BEFORE/AFTER repetitions are running. Each run is normalised by its own control (
Stated in advance so the alternating run cannot become a hunt for the sign I expected. Why the index was probably always going to be neutralI reported early that the interpreter's eval-frame call memo ( The "full scan of the candidate pool per lookup" this PR was built to remove was not being paid. The index removed nothing and added a fold of ~1500–2000 An observation that belongs on the record, with its grain named
DispositionNot merging. A change that buys nothing measurable and adds a fold of 1500–2000 map inserts is redundant work (§2), and "linear by construction" argued without a displaced cost is the purity trap (§6) — priced in elegance rather than in a cost someone pays. If a later attribution finds something genuinely pool-proportional and this index becomes the repair for that, it lands then, with the measurement. Next: attribute where the 6 seconds actually goes, before touching another line. |
|
Closing: this is not the repair, and it should not sit open looking like a candidate. The measurement is in the comment above. Both arms are 12–14x the 500ms line at directory grain, so the index does not reach Keeping the index on shape grounds would be the purity trap (§6): linear-by-construction argued in the absence of a displaced cost, paid for with a fold of 1500–2000 map inserts (§2). If a later attribution finds something genuinely pool-proportional and this index becomes the repair for that, it lands then, with the measurement that makes it one. Nothing here is retired. The drop stands, its subject stays narrowed to one file, and the coverage loss it records is unchanged. Carried forward out of this lane, so it is not lost with the branch:
Next: attribute where the 6 seconds actually goes, before anyone touches another line. |
…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
…hat from is refuted (#10757) * A restoration trigger prescribed an index; the mechanism it derived that 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 * Attribute the walk: the determinism fold is free, and the pool term is 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 * Name the instrument instead of transcribing its output (review 61856) 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 * Delete a hand-authored shell runner that was swept in by git add -A (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 * The witness blocks intermittently, which is the word that survived two 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 * Compiling is not running: the exposure argument answered the wrong question (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 * Arm g is the home for the reached-set premise; reached_sizes was a second 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 * The obvious falsifier cannot come out against the hypothesis; h can 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 * The floor claim is a different subject from every arm measured so far 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 * h eliminates frame sharing; m separates keying from retention 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 * The shape is the finding; three mechanism sentences are dead and it outlived 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 * The disposition is not a bigger number, and the reading that explains 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 * The blocker is accounted for, and it was never this subject 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 * One trigger in the trigger position, and the blocking arm is an interrupt (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 * File the class instead of storing it in someone else's trigger (review 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 * The floor-grain walk-only arm was missing, so no repair could be aimed 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 * eval_steps on a censored row is a truncation artifact, not a workload 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 * The arithmetic did not add up: isolate the fourth payer before repairing 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 * Split what arm o conflates, written before o returns 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 * Pre-register the after-partition before measuring the fn_index repair Commits the expectation ahead of the number: which arms must not move (acquisition, and the determinism fold, both untouched code), which must collapse, and the falsifier -- if the walk comes back only somewhat cheaper that is a fifth payer revealed by removing the first four, not partial credit. The block is attached to data floor_roots rather than appended at the end of the file. Trailing it was a parse error, not a style question: 'source annotation names no subject: no module item follows it' (section 4c admits only standalone LEADING blocks). That error is here because I ran the arms rather than reading the file -- the same execution the compile-clean reading skipped one commit earlier. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-rung-drops.md Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability * Transcribed figures moved rather than removed: review 62806 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 * The annotation contradicted the field it annotates: review 62837 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 * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-rung-drops.md Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability * The annotation still said unverified after the field said accounted for: 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 * The probe moves into the long home: compiled, and declined by name: review 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 * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-rung-drops.md Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability * The fourth stale annotation and a nicknamed module: review 62883 (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 * Floor discovery refuses a test-marked decl outside a _test.dag file: 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 * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-rung-drops.md Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability * No location in this repository can hold a multi-second claim a change 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 * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-rung-drops.md Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability * The ledger row tracking this instance is discharged by this change: review 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 * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-rung-drops.md Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability * A healed head skips the check that requires it: file the class, and unblock 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 --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
The defect
v2.std.fn_indexdecls_matching_calleeevaluatedfilter(decls_in_modules(decls, closure_modules), name == callee)once per callee per reached declaration — a full scan of the candidate pool plus one module-membership pass per closure module, per lookup, of a value that is invariant for the entire walk.gunbc#10744 separated the two candidate cost models by measurement rather than by argument:
O(reached × pool)agrees within 1.9x across file and directory grain;O(reached²)is off by 44x. The cost tracks the pool the walk was handed, not what it reaches — under a hundred reached declarations against a pool of 1500–2000. At file grainpool == n, so the shape reads as quadratic-in-reached and the wrong term gets optimised; only directory grain decouples them.The repair
callee_index_ofcomputes the closure-scoped population once and keys it by declaration name;call_reachable_decls_gothreads that index instead of(decls, closure_modules), and each callee is onemap_lookup.Mapis the host-intercepted primitive (free_call.map_insert/method_call.lookupoverim::HashMap), not the closure chain its.dagspelling reads as — checked rather than assumed, because a secretly-linear map would have given an index-shaped repair with scan-shaped cost.The subject going in is unchanged — same
decls, sameclosure_modules. This is not the scope-pool_rootsmove #10744 names as the trap.The answer is identical, including order and multiplicity
decls_in_modulesconcatenates per module in module order and preserves pool order within a module; the fold appends each declaration to its bucket in that same traversal. So a bucket is the old filter's output verbatim — duplicates included, since a declaration legitimately matches twice when a closure names both a module and its parent under the dotted-prefix membership test. Deduplicating there would have been a semantics change wearing a performance change's clothes, and invisible in every timing number.The witness widens back to directory grain
determinism_live_intra_holdsbecomesdeterminism_transitive_live_closure_holdsagain, overpool_roots=['src/v2/lens']withpool_files=[], following callee edges across the whole lens closure. The name moves with the subject in both directions; a witness whose name outlives what it checks is the §3 meaning fork.The subject was narrowed to one file because the directory walk was
interrupted_before_verdict. Widening it is the point of the repair, not a side effect.Reading the numbers — one fact that is not in #10744
The v1 interpreter carries an eval-frame call memo, on by default (
GUNBC_EVAL_MEMO), keyed by fn identity × argument identity with an Rc-identity fast path.decls_matching_calleeis a plain-valued call, so repeated lookups of the same callee were already served. The 10137ms is therefore paid once per distinct callee, not once per callee occurrence. That does not weaken theO(reached × pool)finding — each distinct callee still scanned the whole pool — but a figure whose denominator is ambiguous is the transcribed-number problem in a different costume, so it is stated here and in the witness annotation.The instrument is named rather than transcribed (§6): this entry under
claim_batch --source-root dag --source-root src/v2, which charges each witness separately. The charged directory-grain measurement in this PR is the required floor's own run of the widened witness.Still to land in this PR
gunbc.rung_drop.determinism_transitive_reachabilityretires on its trigger — a directory-grain verdict within the line without narrowing the subject — and the retirement lands here once the floor has produced that measurement, with the receipt. Retiring it without widening the subject would discharge the receipt while leaving the coverage loss; widening without retiring leaves a drop standing over a defect that is gone.Explicitly not credited with the cost
The three shapes #10744 records —
decl_in_list's linear scan and the copied accumulators incall_reachable_decls_go,determinism_transitive_findings'sconcatfold (free while the corpus is clean, quadratic exactly when findings appear), anddeterminism_live_closure_modules's snoc over a list that is empty today — are real and are not touched here, so a green cannot be read as their repair.🤖 Generated with Claude Code
https://claude.ai/code/session_01CQuBs4mLu9ArojSWFiRcey