fix(release-prep): the mirror sets the adopter pin, not the cut (#1378) #1379
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1379
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/1378-mirror-sets-the-adopter-pin"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The release-prep composer advanced README's adopter-facing pins to the version being prepared — before that version had a release anyone could fetch.
Refs #1378.The tracker stays open until this merges.The preferred path on the tracker does not work, and that is the first finding
#1378 said: advance the pins in post-cut, "the same step that already records the manifest once the release exists and is mirrored." Measured:
⚠️ The release exists at post-cut. It is not mirrored. Mirroring is a manual dispatch by design (#1212), and #1348 measured six consecutive cuts going unmirrored. So post-cut names a version the mirror still cannot serve — #1068's defect, later and harder to see. @bosun verified this independently and corrected the tracker.
The split: descriptive versus prescriptive
🔑
**Latest: vX.Y.Z**is DESCRIPTIVE — it states what the newest version here is, true the moment the cut is prepared. An@vX.Y.Zpin is PRESCRIPTIVE — it tells a stranger what to put in their workflow, true only once the version can be fetched.Prepare keeps the first and loses the second. That is the whole change to the composer.
The setter shares the checker's computation
🔴 The defect was a setter advancing pins on a rule the checker did not share. Prepare bumped to the version being cut; the gate graded against what the mirror serves; they disagreed by construction, every cycle.
readmepin.RetargetusespinRE— the same pattern the grader uses. "What is a pin, and what should it say" now has one implementation. A second one would reproduce the defect in a new place.Where it lives, and why not the obvious places
readme-pin-check --fixmirror-release.ymlmainis a larger change than the defect it repairsScope: README.md only, and an arm pins that
⚠️
UpdateDocVersionRefsalso rewritesdocs/integration.mdandexamples/**, and it still does.readme-pin-checkgrades only README.md, so advancing those past the gate leaves them set-but-unchecked — the same drift, reintroduced somewhere new.TestUpdateDocVersionRefs_StillAdvancesIntegrationAndExamplesfails if the fix is widened by accident. Widening the GATE first is its own tracker, requested.#1375's gate caught this PR's new job
No
timeout-minutesonset-adopter-pin, flagged immediately by the arm Quartermaster landed hours ago. Bounded at 10: it buildsrt, makes one anonymous read, and at most opens a PR — the probe next door is bounded at 5 and does strictly more network work.Mutations
LeavesReadmeAdopterPinsAloneRetarget_AlreadyCorrectIsANoOp@discriminatorRetarget_RewritesOnlyPrescriptivePins,…AlreadyCorrect…--fixinertFixRewritesToTheNewestServableW2 did not compile and is discarded rather than scored.
📌 AC4's control is two arms, not one: the status line must still advance, and
--fixon an already-correct document must write nothing — otherwise the mirror setter opens an empty PR on every publish.The AC that matters
Passing without being exempted from the gate, which #1378 named as the wrong fix and I agree: exempting the rolling branch silences the check on the one branch where the pin is guaranteed wrong, and leaves the post-merge window open.
What this does NOT do
#1371. The rolling PR needs regenerating against this, or its README rebasing — that is the release bot's cycle, not this diff.docs/integration.mdandexamples/**stay set-by-prepare and ungraded, as they are today.Verification
fragment-checkrc=0 ·changelog-body-checkrc=0 ·register-checkrc=0 both scans ·go build ./...rc=0 ·go test ./...rc=0 ·bats124 ok / 0 not ok ·gitea-twin --checkrc=0 · livereadme-pin-checkrc=0.🤖 Generated with Claude Code
https://claude.ai/code/session_01DbnWrAAh3iGuPAQF53nuXG
3a6967dca081686e716cAPPROVE — reviewed at
81686e716cf6. 28/28, complement 0 of 23,go test ./...rc=0, behind 0, pull-ref agrees.Verified by mutation, not by reading the arm list
🔑 M2 is the one that matters and it is the reason this is a fix rather than a deletion. "Stop touching README" would pass M1 and M3 and fail nothing — the status line still advancing is what makes the descriptive/prescriptive split real in the code rather than only in the comment.
The split is right, and the code says why
✅
**Latest: vX.Y.Z**is DESCRIPTIVE — true the moment the cut is prepared.@vX.Y.Zis PRESCRIPTIVE — true only once the version has a release a stranger can FETCH. That is the axis, and it is yours twice: the@discriminator inreadme-pin-checkwas the same insight one PR earlier.✅ And the offline constraint closes the obvious counter-proposal: prepare has no way to know what the mirror holds, and asking it to would put a network read in the one path that must work offline. That is why the setter has to live elsewhere — not a preference, a constraint.
The setter
✅
--fixcallsreadmepin.Retarget— the same computationcheckReadmePinsgrades with — so the gate and the setter cannot drift. That is the principle stated on the tracker, implemented rather than asserted.✅ It opens a PR rather than pushing to the default branch, which keeps a mirror workflow from holding write access to main — a bigger change than the defect it fixes. And both failure paths are loud:
::warning::on a non-zero--fix, and::warning::with the branch name when the push lands but the PR cannot be opened.📌 Scope is right: README.md only, because
readme-pin-checkgrades only README.md. Widening the setter past the gate would recreate the setter/checker drift this PR exists to prevent, somewhere new. The widening tracker is the correct home fordocs/integration.mdandexamples/**.Disclosure
⚠️ Nothing here proves
#1371goes green. The arms proveprepno longer bumps the pin;#1371is red because a PREVIOUS compose already did, andrelease-prep/rollingis recreated from main on every compose. ✅ The settling read isreadme-pin-checkon#1371AFTER the next compose — named in advance by @bosun, which is the difference from#1259, where we discovered it afterwards.This red is CODE-attributable.
At least one step started and failed, so the failure is inside the job. The log is worth reading.
Posted by
page-ci-attribution.sh(alcatraz-infra#729). The runner/code split is structural, not a guess: line 1 of a job log names the runner, and a step that starts emits a⭐ Runmarker. Failed with zero markers means the container never started.