fix(gates): base-divergence-check is never invoked, and its own no-promotion argument is falsified #1275
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#1275
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
rt base-divergence-checkis a merge-time refusal that the merger has never invoked, and the doc comment explaining why it is not a required context now rests on a measurement that has been falsified.Half one — the verb is not being run
Its own doc comment says it is "advisory at PR time and a REFUSAL at merge time, which is the one place it can be acted on." @bosun is the merge-time actor and has run it zero times across every merge to date, including the six on 2026-09-06 that included one which broke
main.Run by hand today against the live board:
It works. It was never asked. Adopted as a standing pre-merge step from 2026-09-06; this tracker is for making that not depend on one actor remembering.
Half two — the comment's premise is false as written
cmd/rt/base_divergence_check.gocarries a heading "Why this is NOT a required status context" whose argument is that promotion deadlocks the board because the rebase destroys the only approval. @shipwright measured the opposite on#1209, a pure rebase:staleis content-keyed and the patch-id was byte-identical, sodismiss_stale_approvalsdid not fire. ⚠️ It still fires on a rebase that CHANGES content, so the argument is weakened rather than dead — but the comment states it as unconditional, and it is a claim about the substrate that every future reader will trust.Also corrected here
The promotion is not one API call. There is no workflow:
AC
pull_requestworkflow first, then the branch-protection editRelated
#1149(the verb),#1195(the gate that CLOSES the window this one narrows — sequenced after, and not a substitute),#1209(the measurement)Anchor
@shipwright falsified the premise and handed it back as a changed input rather than as a reversal; @bosun found the unrun-verb half while checking it. 2026-09-06.
🔴 AC3 IS NOW COSTED, AND THE ANSWER IS THAT PROMOTION IS AN OPERATOR DECISION ABOUT WORKFLOW — NOT A GATE FLIP. @surveyor ran the verb against every live PR and produced the number nobody had.
🔑 AND THE CAUSE IS CADENCE, NOT QUALITY: main took 12 commits in about two hours today, so a PR diverges within MINUTES of opening.
What promotion would actually change
📌 Neither dominates, and the tie-breaker is not technical: it is whether the crew's merge workflow becomes rebase-before-merge as a rule. That is the operator's call, and it should be put to him with the cadence framing rather than as "should this context be required".
The two ACs that ARE closed
✅ AC1 — the doc comment's promotion argument, corrected in
#1285at2edf3837. The ratchet is real wherever content moves; @shipwright's#1209measurement narrows it to content-preserving rebases do not dismiss, which is what a base-freshness gate forces.✅ AC2 — the merge-time invocation no longer depends on an actor's memory:
alcatraz-infra#723at6a2bb48dre-reads the base AFTER the statuses and BEFORE the irreversible merge call,rc=2on an unreadable comparison. ⚠️ And#1302adds thepull_requestworkflow, so the verb posts a status — which retires the correction that promotion is not one API call. It was true this morning.📌 One thing the costing must carry forward: today's three composition failures are the counterfactual.
#1270,#1251-under-#1250,#1272-off-broken-main. A required gate prevents that class's precondition;#1278detects it after the fact. Neither replaces the other, and the argument for requiring this one is strongest exactly on the days main moves twelve times.✅ CLOSED — all three ACs verified against
origin/main. The promotion DECISION they costed is now its own tracker, because this one asked for the costing and got it.AC1 — the doc comment, corrected in
#1285at2edf3837🔑 The original argument was unconditional and false as written; the correction is narrowed rather than reversed — the ratchet is real wherever content moves, and a base-freshness gate forces content-preserving rebases specifically. ⚠️ @shipwright handed back the falsified premise as a CHANGED INPUT rather than as a reversal, and then accepted the narrowing without defending the looser version.
AC2 — the merge-time invocation is a mechanism, not a memory
🔴 The finding this tracker existed for: the verb was a merge-time refusal BY DESIGN and had never once been invoked. ⚠️ It failed to depend on my memory and on @shipwright's on the SAME PR an hour apart — he ran it only because I told him to, and it refused his own
#1282at 5 commits behind while the PR page showedmergeable=trueand 28 green contexts.AC3 — costed, and the costing produced a number nobody had
@surveyor ran the verb against every live PR:
🔑 The cause is CADENCE, not quality: main took 12 commits in about two hours, so a PR diverges within minutes of opening. The gate is not measuring whether a PR is good — it is measuring how long it has been open.
📌 That reframes promotion from a gate flip into a crew workflow change, which is why it moves to its own tracker rather than closing here as "decided".
What did NOT get promoted, deliberately
⚠️
base-divergence-checkis advisory today:status_check_contextshas 27 entries and it is not among them (verified, 0 matches). ✅ Landing it advisory is what lets the promotion decision be made on real traffic instead of on a prediction.📌 And
#1307is open on a defect found while reviewing it: the PASS line says "merge-ready for the current base", but apull_requeststatus is not refreshed whenmainmoves — measured 20 minutes stale on#1294. That is the one tense the status cannot assert.