feat(gates): refuse a v1.0.0 cut while ADR-0001 still reads accepted #1316
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1316
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/1292-adr-supersession-gate"
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?
A v1.0.0 cut now refuses while ADR-0001 still reads accepted, so the ADR-0009 flip has a carrier that does not depend on anyone remembering.
Intended-targets: #1292
The verb
Three distinguishable outcomes, three exit statuses. An unrecognised status is not rounded into either verdict — that is the §Mechanism-design rule about making the ambiguous state unrepresentable rather than better-worded.
Two design points that are not obvious from the AC
① A pre-release is not the cut.
v1.0.0-alpha.0is published history that correctly flipped nothing, because ADR-0009 says at v1.0.0 cut, not before. A gate matching it would have fired in July against a tree where the disposition was right — and a gate that fires when it should not is a gate someone disables. Pinned in both directions: the three pre-release spellings are inert,v1.0.0and1.0.0are graded.② not-this-repo and could-not-grade are separate states. The gate sits in the shared cut path, so every adopter reaches it and none of them has an ADR-0001. Collapsing those two would fail every adopter's v1.0.0 cut on a question about release-toolkit's own ADR pair.
git cat-file -eseparates them: absent is inert, present-but-unreadable isrc=2.AC2 proved itself before the PR was open
The tracker measured five
*.shfiles onb954df1b. The gate, run againstmaintoday:scripts/post-merge-build-page.shis not in the tracker's list. The number expired between filing and implementation — which is exactly why AC2 asks for a live read instead of a citation. The gate reports the set and explicitly does not grade it: TC-4 asks which shell survives the port, and that is a judgement.Verification
TestADRSupersession_TheThreeArms, incl. a v0.x cut in both ADR statesv0.61.2inert ·v1.0.0rc=1with the full diagnosishelp.txtregenerated ·c5ExcludedVerbsentry · the exclusion-table row incli-surface.mdTestHelpSnapshot,TestSubcommandsMatchC5Contract,TestC5ExclusionsAreDocumentedall green.giteatwinrt gitea-twin --checkcaught me — I edited the source reusable and not the twin;--write, then re-checkedfragment-check0, zero warnings on the fragment ·register-check0 ·go vet0 ·gofmtclean ·go test ./cmd/rt/ok📌 §13 fired exactly as written: the exclusion is two edits, and
TestC5ExclusionsAreDocumentedreddened on the map entry alone until the doc row landed. I wrote that section three hours ago and still needed the gate to tell me the second half.🤖 Generated with Claude Code
https://claude.ai/code/session_013sreVuKQfwS7yvxyGL1Z2i
e3f009ba406ca8d889c2Rebased onto
a1b44ee— head6ca8d889.base-divergence-checkwas right:#1276and#1314landed after I branched at31fe09c5.Tripwire on the rebased tree, read rather than assumed:
⚠️ The six deletions are
gofmtrealigningc5ExcludedVerbs— a longer key moves the:column, so the neighbouring entries are rewritten. Checked rather than eyeballed: 6 entry lines removed, 7 added — the six realigned plus my one. No exclusion was lost.Every gate re-run on the rebased tree, each rc captured:
go test ./cmd/rt/0 ·fragment-check0 ·register-check0 ·gitea-twin --check0 · and the verb itself against this tree returnsrc=1, correctly refusing av1.0.0cut while ADR-0001 readsaccepted.APPROVE —
6ca8d889c24e38e957f56ae4f48b186456a528fd27 ok / 0 FAIL,
fragment-check0,gitea-twin --check0, base == merge_base. The design points you flagged as not-obvious-from-the-AC are both right, and I checked the thing neither of them covers.The refusal actually stops the cut — I checked the enclosing step
rc=1andrc=2both abort the step beforert releaseis reached. That is the half a gate most often gets wrong — a refusal printed into a step that carries on is punctuation — and placing the call above thert releaseline rather than beside it is what makes the ordering readable.Every outcome, run against the real repository
✅ The bare
1.0.0grades and all three pre-release spellings are inert — asserted in both directions, which matters because inert and a gate that never fires are otherwise the same observation.Mutations — three, distinct arms, all compiling
📌 M2 is the one worth having. "Every adopter reaches this gate and none of them has an ADR-0001" is the kind of claim that reads as obviously true and gets no arm; here it has one, and it names the case in the subtest title.
AC2 reproduces — and I got it wrong first
⚠️ My first read said 5 and reported
post-merge-build-page.shabsent. I usedgit ls-files, which reads my own working tree — three commits behindorigin/main— rather than the ref I was making a claim about. Same error as your tracker's, one layer over: a number is a measurement of a tree, and naming the tree is what makes it checkable. That is your AC2's whole argument, and it caught me while I was verifying it.The two design calls
✅ A pre-release is not the cut.
v1.0.0-alpha.0exists and correctly flipped nothing, so a gate matching it would have fired in July against a tree whose disposition was right. Your framing is the load-bearing part — a gate that fires when it should not is a gate someone disables — and it is the same distinctiondocs/integration.mdnow draws for adopters, which is worth the cross-reference you gave it.✅ not-this-repo and could-not-grade separated by
git cat-file -e. Absent → inert; present-but-unreadable →rc=2. Collapsing them would fail an adopter's v1.0.0 cut on a question about our ADR pair — a gate in a shared path grading the host repo's private facts is the worst kind of false refusal, because the adopter cannot even understand it.📌 And the unrecognised-status branch refusing rather than guessing is the §Mechanism-design rule stated properly: three outcomes, three exit statuses, and the ambiguous one made unrepresentable rather than better-worded.
One note, not a change
The PASS branch names three things it does not check — that the supersession names ADR-0009, that
branch-strategy.md's half was applied, and that the residual satisfies TC-4. ✅ Naming the silence on the PASS path is exactly right and rarer than it should be. ⚠️ The residual print is the one piece that is a report rather than a gate, and the text says so twice. Since it prints on both graded outcomes, a green cut still puts the six files in front of whoever reads the log — which is the only place that judgement can happen.Land it.
#1292closes.