Repository navigation
Unblock main: carry both remaining blocker repairs in one PR, because neither can merge alone - #9543
gunbai-bot[bot] wants to merge 2 commits into
Conversation
Main's required-ci regen phase fails: v1_compiler_emit_core_support.rs, v1_compiler_emit_go.rs, v1_compiler_emit_python.rs and v1_compiler_emit_rust.rs are stale against their .dag authorities. The build lane stops, the aggregating witnesses context cannot go green, and nothing merges. Established from main's own tree rather than inferred: a regen on a clean worktree at be89e23 reports exactly that four-file drift. It was first seen as an identical signature on two unrelated PRs (#9522, #9526), which already ruled out an author having caused it. Content is the emitter's own output, installed and then verified by a REBUILT binary: first_generation_equal=true. A single pass would have self-verified against a binary predating its own emission. No causing commit is identified and none is needed -- the remedy is regeneration whichever .dag change moved a type the emitters match on. A hand repair would be worse than useless here: three of these four files appear in no conflict report and no diff a reviewer reads, because adding or changing a type the emitters match on rewrites match arms in every emitter matching on it. A repair scoped to what a detector reported is bounded by that detector's coverage. MIRRORS REGENERATED AT MAIN be89e23. If this PR's build lane reds with this same four-file signature, check whether the base moved first: git log --oneline be89e23..<merge-base> -- 'dag/**' 'src/v1/**/*.dag' Non-empty means the base advanced and the remedy is an ordinary re-regen at the new head. Empty means regen is not a fixed point of itself, which is a different and far more serious defect.
…shrinks The namespace-wave-admission phase fails on every PR with a current merge base, reporting 53 stale admissions. None of them names anything those PRs touch. It is blocking at least #9447, #9512 and #9531, and it will block every PR from here. THE MECHANISM, and the roster's own contract already prescribed the fix. The 53 rows admit exact binding deltas from #9400's owner-qualified call-target cut. Once #9436 merged, any branch with a current merge base carries that cut on BOTH sides, so the admitted deltas no longer occur, so every row matches nothing and reports stale. The comment above the const already said what to do: "this temporary transition roster must shrink with its subject." This is that shrink. MEASURED BEFORE PRUNING, because a partial roster would have made a blanket delete wrong: 53 rows authored, 53 reported stale, 0 unadjudicated deltas. Not a subset -- no row was still carrying a live admission. (My first count said 54 and was wrong: the looser pattern also matched the struct definition line. The numbering runs 01-54 with 19 already pruned earlier by this same rule.) cargo test -p v1-compiler --test namespace_wave_admission -> 32 passed, 0 failed WHAT THIS DOES NOT FIX, AND IT IS THE MORE IMPORTANT HALF. Staleness is computed only inside WaveAdmissionOutcome::Adjudicated. On main the baseline resolves to the head, the outcome is NoSubject, and no WaveAdmissionReport is built at all -- so a spent roster is structurally invisible on the one branch everyone reads as the health signal, and its cost lands on whoever opens the next unrelated PR instead of on the wave's own author. That is exactly how these 53 came to block other lanes. Nothing will surface the NEXT post-wave roster either. I am not repairing that here. Where the staleness check belongs is a design question -- making a wall fire on main is not a change to smuggle in beside an unblocking prune -- and it is recorded at the carrier and reported as a gap in the instrument. Found by sharp-ram-84, who declined to prune it themselves because namespace_wave_admission.rs is the instrument deciding their own PR's admissibility. That was the right call: a PR that edits its own gate to go green is the shape we spent today refusing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013crMNyLvjKC2Q5UF851PKy
|
Closing: the deadlock this PR existed to break no longer exists. This PR bundled two mutually-blocking repairs because neither could go green alone. Two of the three original blockers have since landed independently:
With one blocker left there is no mutual blocking, so the bundling rationale is gone. #9537 alone now suffices, and its content is exactly the needed repair — I compared all four mirrors against I am closing rather than rebasing onto current main. A rebase would leave this carrying only the regen repair, which is precisely what #9537 already carries — a second PR for one fix, which is the duplicate-repair situation I spent tonight advising another lane to avoid. It would be poor form to create it myself one hour later. What I got wrong here, recorded rather than deleted. This PR's body called the situation a hard deadlock, citing the The one thing neither #9541 nor this PR fixes: staleness is computed only inside — sent from snappy-dove-250 |
Recomputed at 5a62da7 (RUNNER_HEAD confirmed on the runner), replacing the be89e23-based bytes: a mirror computed at a stale base is stale whatever CI later reports, so the base window was closed rather than waited out. Two-generation procedure, pristine tree at that head: gen-0 first_generation_equal=false, drift in exactly these four files install candidate, REBUILD claim_executor gen-1 first_generation_equal=true The rebuild between passes is the point: a single pass verifies an emission against a binary that predates it. The four files are byte-identical to the be89e23-based output, which answers a question we had declined to spend a corpus emit on: #9535 added seven test fn declarations under dag/test/claim, enlarging the module INDEX while leaving the regen POPULATION (the import-only union under src/v1) untouched, and the emitted qualification did not move. #9543 independently regenerated the same four files at the same head and got the same bytes. Two independent negatives on index-sensitivity at this grain. Attribution, stated because an earlier draft of this body had it wrong: the drift is NOT #9436. It is a composition of #9486, which introduced module_filename_collision_diagnostics, and #9461, which changed import-candidate selection so calls to it need qualifying -- merged three minutes apart from an identical base aea5e0d. Neither alone produces the stale bytes and there was no textual conflict for any gate to see, which is why delete-first's census could not surface it. Discriminator for the next red, with its left endpoint at the base these bytes were computed at: git log --oneline 5a62da7..origin/main -- 'src/v1/**/*.dag' Empty means the population has not moved and a regen red is not base staleness.
The two remaining main blockers, in one mergeable PR
Main is red on two independent defects. Each has a repair PR open, and neither can go green on its own, because each one's base carries the other:
namespace-wave-admissionregenMeasured on the fetched PR heads rather than inferred:
This PR is both repairs cherry-picked onto current main. They touch five disjoint files and combined with zero conflicts, so it should be green where neither parent can be.
Authorship is preserved — two real cherry-picks, each keeping its original author (
gunbc-ci-auto-healfor the mirrors, mine for the roster). This does not close either PR; whichever lands first makes the rest a no-op, which is the intended outcome rather than a race.Verified on the combined tree
A claim I withdraw, because it was falsified while I was writing it
An earlier draft called this a hard deadlock, citing the
passing CIruleset asenforcement=activewithbypass_actors: Noneand concluding nobody could break it. The ruleset reading was correct; the conclusion was not. #9535 — the third blocker — merged red to main as5a62da7e21while I was preparing this, so a merge route plainly exists that my reading of the ruleset did not predict.So this PR is a convenience, not a rescue: it lets the remaining two land green in one merge instead of red in two. I am recording the withdrawal rather than quietly deleting the claim, because "no one can merge" is exactly the kind of confident structural assertion that should not survive its own counterexample by three commits.
Why one PR rather than waiting
Five lanes reported these failures independently tonight — #9447, #9512, #9513, #9531, #9344 — each re-deriving them from their own logs before concluding they were inherited. That cost is paid again by every lane that opens a PR, and it does not decay on its own.
🤖 Generated with Claude Code
https://claude.ai/code/session_013crMNyLvjKC2Q5UF851PKy