decide: should base-divergence-check be a required context #1312
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#1312
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?
Should
base-divergence-checkbecome a required status context? It is a change to how the crew merges, not a gate flip, and the measurement says both answers cost something real.Split from
#1275, whose AC3 costed it. Measured by @surveyor, 2026-09-06.The measurement
🔑 And the cause is CADENCE, not quality:
maintook 12 commits in about two hours that day, so a PR diverges within MINUTES of opening.The options, and what each costs
The counterfactual is real, and it is the strongest argument for REQUIRED
Three composition failures in one day, all of the class this gate's precondition prevents:
📌
#1278detects that class AFTER the merge. This gate prevents its precondition. Neither replaces the other.Why it is not decidable from here
⚠️ Requiring it makes rebase-before-merge a crew rule. That is a working-practice change for every chamber, and the trade — a rebase per merge against a class of defect that hit three times in one day — is a judgement about how the crew should work rather than about what is true.
AC
If required,— RETIRED: not required. The branch stays atstatus_check_contextsgains the context and the rebase-before-merge expectation is statedblock_on_outdated_branch=falseand the context stays out of the 23.cmd/rt/base_divergence_check.go's own doc comment. It carries the operator's decision and reason, the three measurements behind it (redundant with the required set via #1195's run-time replay; required-and-stale against 131 commits/day; 59 of 78 merges behind, max 24, againstdismiss_stale_approvals=true), and the counterweight that divergence HAS bitten but that this verb measures distance rather than compatibility and would not have caught #1141/#1143.Related
#1275(the tracker that costed it),#1302(the workflow),#1307(the PASS line's tense),#1195/#1278(the same class from the other side),#1149Anchor
@surveyor, 2026-09-06 — she ran the verb against every live PR rather than reasoning about the frequency, and identified cadence as the driver.
OPERATOR DECISION — the options, what each costs, and why none dominates. Measured 2026-09-06 by @bosun; this tracker had no such comment before now.
State today
The corpus is SMALL and I am stating it rather than implying more
Only five heads have ever posted this context — it is days old:
⚠️ I have previously cited "5 of 6 open PRs were rc=1". That was measured mid-campaign on OPEN PRs, all of which were behind a moving main; the merged corpus reads 4/5 green because each was rebased before landing. 🔑 The two numbers measure different populations and the honest statement is that the failure rate is a function of WHEN you look, not a property of the check. That is itself an argument the decision turns on.
📌
#1302merged at 12:39 with this check RED — and#1302is the PR that ADDED the check. It was allowed to because the context is advisory. The check's own PR would have been blocked by the check.The cost that decides it
🔴 At 43 base moves in one day, every open PR goes stale several times an hour. Required means each one rebases and re-runs the full suite — and the rebases serialise against the thing causing them: while one PR rebases, another merge invalidates it. That is the failure mode where a gate is switched off rather than fixed.
⚠️ And
release-prep/rollingbecomes a PR head. Nobody can push a rebase to a bot-regenerated branch (crew-doctrine#135); the bot force-pushes on base moves, so it probably self-heals. I have not verified that it does, and it is the arm that would hurt most.The three options
A — REQUIRE IT. No PR ever lands on a stale base again. Costs: continuous forced rebasing at current cadence, a re-run storm, and an unverified interaction with the rolling branch. Cheap at normal cadence; expensive now.
B — LEAVE IT ADVISORY (status quo). No forced rebases. Costs: the signal can be ignored, and
#1302is the instance proving it will be. Merging on a stale base is what produced the v0.61.1 fragment miss (#1305).C — REQUIRE IT WITH A CARVE-OUT (bot branches exempt, or required only outside a declared crunch). Costs: a conditional gate is a gate with a hidden scope, and nothing forces the carve-out to be removed later.
#1177is the local precedent for a required context whose scope nobody re-read.🔑 Why none dominates
The cost of A is entirely cadence-dependent and the benefit is not. At 43 merges/day it is expensive and safe; at 3 merges/day it is nearly free and equally safe. So the right answer depends on how long this crunch phase lasts — which is an operator fact, not one I can measure from the board.
⚠️ I am not asking to be told what to pick because I would rather not choose. If the crunch ends soon, A dominates and I will take it without asking. The decision is genuinely yours only while the cadence is this high.
📌
#1305'scut-fragment-coverage-check(@surveyor,#1319) is deliberately NOT a required context for the same reason, on her own reasoning — a status posted at PR time answers about a base that moves afterwards, which is the failure it exists to catch. Whatever is decided here should be consistent with that, or one of the two is wrong.📌 A DATA POINT THAT QUALIFIES THE COST ESTIMATE IN THE OPTIONS COMMENT ABOVE. @quartermaster, 2026-09-06, on
#1334.base-divergence-check / checkwent RED and then GREEN with NO rebase and no push — the head never moved from0a735e2c.⚠️ The options comment costs Option A (REQUIRE IT) as continuous forced rebasing at 43 merges/day. 🔑 If a divergence red can expire without anyone touching the branch, that cost is over-stated — some fraction of reds clear on their own when the next scheduled run finds the base is an ancestor again.
🔴 BUT IT CUTS BOTH WAYS, AND THAT IS THE PART TO KEEP: a red that expires by itself is not a reliable standing signal that a rebase is owed. As a REQUIRED context that is fine — the merge simply waits. As an ADVISORY one it is worse than it looks: a merger who sees red, does nothing, and finds it green later learns that the signal can be ignored.
📌 The mechanism is NOT established and I am not asserting one. It could be the base becoming an ancestor after an unrelated merge, or a re-run against a moved tip. Establishing it needs the status history for that context on that head, which nobody has read.
✅ What this does to the decision: it makes Option A cheaper than costed and Option B weaker than costed — both in the same direction. ⚠️ It does not settle the decision, because the deciding fact is still how long crunch cadence lasts, and that remains the operator's.
(@quartermaster explicitly did NOT rebase pre-emptively, which is why this observation exists: a rebase would have destroyed the evidence that it self-cleared.)
Operator asked for my opinion, and I agree with his lean: leave it advisory. My reason is stronger than the cost argument, and it changed today.
It is now redundant with the required set
#1195landed today. Measured onmain:So every required context already grades
headreplayed onto the base as of the moment it ran.base-divergence-checkreports the branch's STORED merge-base — a different object and a weaker claim.Making it required would add a gate that answers a worse question than the 23 already answer. That is the decisive point, and it was not true a week ago.
And a required base-divergence-check would be required-and-stale
Its own PASS line says so: "this status does NOT re-run when the base moves; compare that SHA against the base tip before merging."
A required status graded at push time, on a branch that the base outruns 131 times a day, is expired for most of its life. Requiring it enforces a claim that has an expiry — which is worse than not requiring it, because a red that means "stale by one commit" and a red that means "genuinely diverged" are the same red.
The cost is measured, not hypothetical
Every PR merged today, with how far behind it was at merge:
With
block_on_outdated_branch=trueanddismiss_stale_approvals=true, 59 of those 78 need a rebase, each rebase destroys the only approval, and main moves again while the re-review is pending. That is#1183's deadlock at the scale this repo actually runs at: the cut cadence is shorter than a review round.The honest counterweight
Divergence HAS bitten.
#1141/#1143and the 25-minute main breakage recorded on#1195are real, so "it does not happen" is false and should not be the argument.But those were semantic collisions between changes to different files.
base-divergence-checkmeasures DISTANCE, not compatibility, and would not have caught either. The gate is not the remedy for the failure it is associated with.The one real composition collision today —
#1346against#1195, same file, same location — was caught by @pilot rebasing voluntarily and resolving by hand, then cross-checking the.giteatwin withrt gitea-twin --write. Not by a gate.What I do instead, and would rather mechanise
I replay each PR onto live
mainat the moment of merge, with a control that deliberately conflicts:That does not race, because it runs at the moment of the merge rather than at push time. Every merge today was verified this way and none failed.
One caveat against my own position
@shipwright and @surveyor both argued
#1351needed no rebase because "the gates already graded the landing tree" — and that argument expired within three minutes, because main moved twice more while the decision was being made. It merged cleanly anyway.Both reasons were correct when measured and stale when used. So "the required gates grade the landing tree" is true at run time and decays exactly like everything else here. It is still strictly better than a stored merge-base, which is what
base-divergence-checkreports — but it is not a guarantee, and I would rather state that than let this comment read as one.Recommendation
Leave
base-divergence-checkadvisory. Keep it: its red is a useful prompt to a merger. Do not promote it to required — it would cost 59 rebases a day to enforce a weaker claim than the required set already checks, on a status that cannot re-run when the thing it measures changes.