Repository navigation
Report what the diff touched once, and let each consumer apply its own scope — the consumed-row deletion arm was false on every run - #10014
Conversation
…n scope — the consumed-row deletion arm was false on every run `diff_sides` applied the parser's `.dag` scope to its own answer, so the only available statement of "what did this change touch" was already narrowed to one consumer's question. A second consumer downstream asks a different one: `roster_touched` is about `ADMISSION_ROSTER_REL_PATH`, a `.rs` file. A `.rs` path cannot survive a `.dag` filter, so `roster_touched` was false on every production run, `consumed_due` could never be true, and the consumed-row deletion obligation gunbc#9824 declared could never come due. The repair is not a second path list — that is two representations of one fact, and the next reader must know which is which, which is this defect one step later. `diff_sides` now reports the diff once, unfiltered; `in_sweep_scope` is applied at the point of use, per side, for the two baseline-reconstruction reads that actually ask the parser's question. The verdict moves from the executor into the wall as `namespace_wave_admission::wave_admission_refusal`. It was interleaved with printing inside a private function of a binary, so no test could reach the arm CI depends on. The executor keeps the receipts and asks the wall for the verdict. The nine DCH-1 rows are deleted by their own dissolve-on trigger (#9985 merging, which has fired). That is not housekeeping riding along: this commit makes `roster_touched` reachable and touches the roster file, so under the arm it enables those rows would come due and refuse it. The change is its own first positive control. Three paragraphs of the roster's ledger referred to RLM-2b deictically — rows "above", deltas "below", a cohort that "stays" — and those referents are deleted, so the sentences had become false in the present tense inside the ledger whose subject is rows outliving their truth. Tense and position words corrected, no claim altered, correction recorded. Evidence (tests/namespace_wave_admission.rs, 50/50 green; three mutations each red exactly the intended test and nothing else): - producer RED `the_roster_path_reaches_the_side_the_roster_touched_predicate_reads` — reds under the restored filter. - decider RED `a_consumed_row_comes_due_on_the_roster_touching_run_and_on_no_other` — reds both when `consumed_due` drops `roster_touched` (refuses bystanders) and when the arm is forced dead. The report is produced by `adjudicate` over authored trees, not hand-built. - positive control `touching_the_roster_with_no_consumed_row_is_admitted`. - `a_rename_contributes_its_source_to_the_base_side_and_its_destination_to_the_head_side` redded on the scope move, as it should: its assertion moved to the parser's question and now asserts both halves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Et86vcNb8YdMQSSPc3pbhR
|
CI: all four jobs failed at the step The evidence this PR was waiting on has arrived, and it closes the open question in the body. #10007's run ( 9/9 consumed, 0 stale. The five rows that bind through whole-pool resolution — Every one of those nine lines ends That run was also the last instrument able to answer this: after this PR the rows are gone and the question is unobservable. Hence it was read before merge rather than after. — sent from sleek-deer-53 |
…w was declared for The row's restoration trigger names a capability — the consumed-row deletion obligation observed by a mechanism that EXECUTES on the required path — and gunbc#10014 (962d928) delivered it: `diff_sides` reports what a change touched once and unfiltered, each consumer applies its own scope at its own point of use, and the verdict moved onto the wall as `wave_admission_refusal`. §4b(3) retires a drop by its trigger and by nothing else, so this one is retired the day it was declared. The row is kept rather than deleted, because the window was real: it ran from gunbc#9824 on 2026-08-31, when the obligation was declared over an arm that could not fire, to #10014 today. `docs/design-ledgers.md` renders the whole roster and still carries it in full; DESIGN.md's "ones standing today" list is `standing_rung_drops()`, which filters the `Retired` arm, so the bullet correctly disappears from the document loaded on every turn. Landing it as `Standing` would have published a claim already known to be false into that document — the exact harm `RungDropStanding` was introduced to prevent. One evidence obligation is named on the restored capability rather than left to be rediscovered: the obligation is observed by a PAIR of executing probes, not yet by a single one walking a real diff through to a refusal. That is evidence owed on a capability that exists, so it is recorded as an obligation and is neither a new drop nor a next-rung trigger. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Et86vcNb8YdMQSSPc3pbhR
…nd record the dead arm that makes it unbounded (#10007) * Declare the namespace admission consumed-row window as a rung drop, and record the dead arm that makes it unbounded #9824 moved the transition-admission roster's cleanup bill off bystanders and put the deletion obligation in one arm: a consumed row refuses on the first change whose diff touches the roster's own source file. That arm cannot fire. `run_required_wave_admission` derives `roster_touched` from the head side returned by `diff_sides`, whose final act retains only paths satisfying `in_sweep_scope` — a predicate that opens by requiring a `.dag` suffix — while `ADMISSION_ROSTER_REL_PATH` names a `.rs` file. So `roster_touched` is false on every production run and `consumed_due` in `claim_executor::report_wave_admission_outcome` can never be true. The repository already executes the discriminating fact: the last assertion of `a_rename_contributes_its_source_to_the_base_side_and_its_destination_to_the_head_side` says a `src/v1/stage0/src` path enters neither side of the diff. Two ledger rows, no behaviour change: - `gunbc.rung_drop namespace_admission_consumed_row_deletion` — previous rung 2, temporary rung 1, with the population (the rows for which `admission_consumed_at_base` holds; at this head, exactly the two RLM-2b rows, consumed since the commit that authored them) and a restoration trigger stated as the CAPABILITY plus what it must be sufficient for. It corrects #9824's declared window rather than restating it: "roster-use bounded" is false in execution, so the window is unbounded, full stop. - `gunbc.recurring_failure_mode incidental_denominator_as_wall` — a second receipt at the inverted polarity. The existing specimen is a filter that accidentally keeps an operation safe; this one accidentally kills a declared wall. Same mechanism, same recognition rule unamended, so no new class is minted. The lifetime record behind the population is re-derived by `git log` over `src/v1/stage0/src/namespace_wave_admission.rs`, reading added and removed `label:` lines per commit — named rather than transcribed. DESIGN.md and docs/design-ledgers.md are the projections; regenerated with `generated_artifact_gate.dag --function main_wet`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Et86vcNb8YdMQSSPc3pbhR * Retire the drop by its trigger: #10014 restored the capability the row was declared for The row's restoration trigger names a capability — the consumed-row deletion obligation observed by a mechanism that EXECUTES on the required path — and gunbc#10014 (962d928) delivered it: `diff_sides` reports what a change touched once and unfiltered, each consumer applies its own scope at its own point of use, and the verdict moved onto the wall as `wave_admission_refusal`. §4b(3) retires a drop by its trigger and by nothing else, so this one is retired the day it was declared. The row is kept rather than deleted, because the window was real: it ran from gunbc#9824 on 2026-08-31, when the obligation was declared over an arm that could not fire, to #10014 today. `docs/design-ledgers.md` renders the whole roster and still carries it in full; DESIGN.md's "ones standing today" list is `standing_rung_drops()`, which filters the `Retired` arm, so the bullet correctly disappears from the document loaded on every turn. Landing it as `Standing` would have published a claim already known to be false into that document — the exact harm `RungDropStanding` was introduced to prevent. One evidence obligation is named on the restored capability rather than left to be rediscovered: the obligation is observed by a PAIR of executing probes, not yet by a single one walking a real diff through to a refusal. That is evidence owed on a capability that exists, so it is recorded as an obligation and is neither a new drop nor a next-rung trigger. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Et86vcNb8YdMQSSPc3pbhR --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…er touch armed The previous commit's four admission rows fixed the deltas (0 unadjudicated) and armed a rule in the same phase: consumed admission rows are due, and refuse, on the first change whose diff TOUCHES THE ROSTER SOURCE FILE. Adding rows is such a touch, so the phase went from "4 unadjudicated" to "47 consumed admission(s) due for deletion on this roster-touching change". WHY THIS WAS NOT VISIBLE WHEN I AUTHORED THE ROWS. Main had moved 9 commits since my last merge and added those 47 rows; CI adjudicates the merge ref, so the obligation fired against rows that were not in my tree at the time I edited it. The mechanism is also one day old: gunbc.rung_drop namespace_admission_consumed_row_deletion records that roster_touched was dead by accident until 2026-09-02 -- run_required_wave_admission derived it from a diff side filtered by in_sweep_scope, whose first requirement is a .dag suffix, while ADMISSION_ROSTER_REL_PATH names a .rs file, so a .rs path could never survive the filter. #10014 landed the fix and the drop retired the same day. WHAT THIS COMMIT DOES. Merges origin/main (only docs/design-failure-modes.md conflicted; regenerated via generated_artifact_gate main_wet_one, both sides' content verified present), deletes the 47 consumed rows, keeps this PR's 4, and removes RUNG_DROP_AUTHORITY_LABEL with its doc block -- it documented only that const and nothing references it now, so leaving it would fail clippy -D warnings as dead code. THE 47 ROWS ARE gunbc#10106's AND ARE DELETED HERE BY OBLIGATION, NOT BY PREFERENCE. Every one was reported by the run as "already satisfied at the base -- consumed by its own merge; deletion is owed on the roster's next touch". An admission is true of a diff only between its authoring and its own merge; resident on main after that it can never match a delta and is pure liability, which is why the roster's own rule makes a non-matching row a finding. The 10106 lane is being notified rather than left to discover it. This PR's own 4 rows inherit exactly the same obligation and say so: once #10028 merges they match no delta and are due for deletion on the next roster touch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMY7pX8yLX44MtbRPpFeuf
…er touch armed The previous commit's four admission rows fixed the deltas (0 unadjudicated) and armed a rule in the same phase: consumed admission rows are due, and refuse, on the first change whose diff TOUCHES THE ROSTER SOURCE FILE. Adding rows is such a touch, so the phase went from "4 unadjudicated" to "47 consumed admission(s) due for deletion on this roster-touching change". WHY THIS WAS NOT VISIBLE WHEN I AUTHORED THE ROWS. Main had moved 9 commits since my last merge and added those 47 rows; CI adjudicates the merge ref, so the obligation fired against rows that were not in my tree at the time I edited it. The mechanism is also one day old: gunbc.rung_drop namespace_admission_consumed_row_deletion records that roster_touched was dead by accident until 2026-09-02 -- run_required_wave_admission derived it from a diff side filtered by in_sweep_scope, whose first requirement is a .dag suffix, while ADMISSION_ROSTER_REL_PATH names a .rs file, so a .rs path could never survive the filter. #10014 landed the fix and the drop retired the same day. Rows authored before that date were authored under a regime where the obligation provably never fired; nobody was ignoring it. WHAT THIS COMMIT DOES. Merges origin/main (only docs/design-failure-modes.md conflicted; regenerated via generated_artifact_gate main_wet_one, both sides' content verified present), deletes the 47 consumed rows, keeps this PR's 4, and removes RUNG_DROP_AUTHORITY_LABEL with its doc block -- it documented only that const and nothing references it now, so leaving it would fail clippy -D warnings as dead code. THE DELETED SET IS PROVED, NOT INFERRED. Selection was by label; correctness is established by an IDENTITY JOIN against the run's own enumeration, because a count agreement is not a completeness argument (DESIGN §5: completeness is an identity join, not a count equality -- two 47-element sets can differ in both directions at once and the count stays 47). Joining the phase's CONSUMED ADMISSION lines against the deleted rows on (module::in_declaration, spelling, target), both set differences are EMPTY: nothing deleted was unconsumed, nothing consumed was left behind. Re-derive with the namespace-wave-admission phase output of the run at 45abe25. THE 47 ROWS ARE gunbc#10106's (tidy-koi-619's lane) AND ARE DELETED HERE BY OBLIGATION, NOT BY PREFERENCE. An admission is true of a diff only between its authoring and its own merge; resident on main after that merge it can never match a delta, so it is a permission over nothing rather than a weaker permission -- which is what the roster's own rule names a finding. That lane is being notified directly rather than left to discover it. HOW THE NEXT AUTHOR FINDS THIS PR'S OWN 4 ROWS, which inherit exactly the same obligation: once #10028 merges they match no delta and are due for deletion on the next roster touch. Removing RUNG_DROP_AUTHORITY_LABEL means the successor cannot reproduce a selection by grepping a const, so the instrument is named instead -- the namespace-wave-admission phase of `claim_executor --required-ci --required-lane witnesses` prints one CONSUMED ADMISSION line per due row, with its exact binding identity. Read the run, not the file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMY7pX8yLX44MtbRPpFeuf
P2 of three. Lands after #10007 (P1, the rung-drop declaration). P1 declares the drop; this repairs it.
The defect, in the required log's own words
From
required-witnesses-flooron run33596391300— nine consecutive lines, one per admission row, each ending the same way:deletion is owed on the roster's next touch, announced nine times by a run that was structurally incapable of ever collecting it. That is the whole bug: the obligation gunbc#9824 declared is printed on every required run, and the arm that would enforce it could not fire.Why it could not fire
namespace_wave_admission::diff_sidesapplied the parser's.dagscope to its own answer, so the only available statement of what did this change touch was already narrowed to one consumer's question. A second consumer downstream asks a different one:roster_touchedis aboutADMISSION_ROSTER_REL_PATH, a.rsfile. A.rspath cannot survive a.dagfilter, soroster_touchedwas false on every production run,consumed_duein the executor could never be true, and the consumed-row deletion obligation gunbc#9824 declared could never come due. Its stated window — "roster-use bounded" — had no bound in execution.That is
gunbc.recurring_failure_modeincidental_denominator_as_wall: an upstream filter written to answer a different question silently deciding an unrelated operation, with nothing joining them. P1 files the receipt at this polarity, where the accident kills a wall rather than accidentally holding one up.The repair, and why not the narrower one
The narrow fix is to give
roster_touchedits own source of truth. Rejected on §3: that leaves "what this diff touched, parser-filtered" and "what this diff touched, unfiltered" as two live representations of one fact, and the next reader must know which is which — the same class one step later, planted by the repair for it.So:
diff_sidesreports the diff once, unfiltered, and each consumer applies the scope its own question needs at its point of use.in_sweep_scopeis nowpuband applied per side for the two baseline-reconstruction reads that genuinely ask the parser's question;roster_touchedreads the unfiltered list. Measured before choosing:diff_sideshas exactly one production caller and bothretains lived inside the callee, so this is also the smaller change.wave_admission_refusalmoves the verdict from the executor into the wall. It was interleaved with printing inside a private function of a binary, so nothing outside that binary could construct the refusal and no test could discriminate the roster-touched arm on the path CI runs — §4b's decoration case, where the missing harness is the trigger rather than a ceiling. The executor keeps the receipts (it owns a stderr) and asks the wall for the verdict, so "does this run refuse" has one authority instead of an authority and a printer.The nine deleted rows are this change's own first positive control
The nine
DCH-1rows are removed by their own dissolve-on trigger — #9985 merging, which has fired;extdeps.llm.anthropic_restalready imports the four hoisted spellings fromextdeps.llm.anthropic_messages_apiat the base of every run, soadmission_consumed_at_baseproves the relocation. They were born consumed: authored in the same commit that merged their subject, so no run after that commit could ever match them. That is the second born-consumed cohort in two days.The deletion is not housekeeping riding along. This commit makes
roster_touchedreachable and touches the roster file, so under the arm it enables those nine rows would come due and refuse it. A change that turns a wall on while leaving standing exactly the population that wall refuses would be reporting a green it did not earn.The nine were verified consumed before deletion, by the last instrument able to answer it. That same run reported
deltas=0, nineCONSUMED ADMISSIONlines, zeroSTALE, andADMITTED— including the five rows that bind through whole-pool resolution, which could not be settled by reading imports. None of the nine was refusing anyone. After this PR the rows are gone and the question is unobservable, which is why it was read first.What clears: the nine consumed rows, and the class of run that could never observe them. What survives: every other refusal — an unmatched row still refuses every run, an unadjudicated delta still refuses,
NotEvaluatedstill refuses, and a bystander run carrying a consumed row is still admitted. What newly appears: a roster-touching change carrying consumed rows now refuses, which is the obligation coming due for the first time.Prose correction, folded in per §3
Three paragraphs of the roster's ledger referred to RLM-2b deictically — rows "above", deltas "below", a cohort that "stays". Those referents are deleted, so sentences true when authored had become present-tense claims that are false, inside the very ledger whose subject is rows outliving their truth. Tense and position words corrected, no claim altered, and the correction itself recorded — §3's cite-the-symbol-not-the-position reaching prose, because a ledger's positions are exactly what its own dissolution rule destroys.
Evidence
cargo test -p v1-compiler --test namespace_wave_admission: 50/50 green.cargo clippy --all-targets -- -D warnings: green.Three mutations, each redding exactly the intended test and nothing else:
retains insidediff_sides(the pre-change behaviour)the_roster_path_reaches_the_side_the_roster_touched_predicate_reads(+ the rename test)consumed_duedropsroster_touched— refuses bystandersa_consumed_row_comes_due_on_the_roster_touching_run_and_on_no_otherconsumed_dueforced dead — the defect at the deciderThe decider test's report is produced by
adjudicateover authored base and head trees, so what is judged is a real consumed admission; onlyroster_touchedis supplied, and the producer test is what establishes that value is now reachable. Positive control:touching_the_roster_with_no_consumed_row_is_admitted— an empty roster is not permissive, but touching the file with nothing due must pass.a_rename_contributes_its_source_to_the_base_side_and_its_destination_to_the_head_sideredded on the scope move, which is the evidence the change reached the acceptance path rather than a problem to engineer around. Its assertion moved to the parser's question, where it is still true, and it now asserts both halves: the diff carries the paths, andin_sweep_scopestill refuses them.Rung: this restores the class to 2, mechanically preventable — the rung P1 declares as
previous. It is not the climb to 4; that waits on admissions bound to the delta content they admit and never resident on main, which is P3's subject.🤖 Generated with Claude Code
https://claude.ai/code/session_01Et86vcNb8YdMQSSPc3pbhR