Skip to content

docs(branching): fix the promotion ancestry precondition - #574

Merged
ss-o merged 1 commit into
mainfrom
code/promotion-precondition-ancestry
Aug 30, 2026
Merged

docs(branching): fix the promotion ancestry precondition#574
ss-o merged 1 commit into
mainfrom
code/promotion-precondition-ancestry

Conversation

@ss-o

@ss-o ss-o commented Aug 30, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the promotion precondition in runbooks/branch-protection.md, which
required a check that cannot pass after any successful promotion.

Closes #573

Problem

Step 1 of the promotion procedure required:

git merge-base --is-ancestor origin/main origin/next

Promotion creates a merge commit on main that never exists on next, so
main stops being an ancestor of next the moment a promotion lands. ADR-0019
states the opposite property, that promotion needs no back-merge because the
promoted next commit becomes an ancestor of main. Both cannot hold.

Reading the guaranteed failure as drift has produced three no-content
reconciliation merges in z-shell/zi (9a4fa51, b0ebcc3, 73df7bf), each
contributing zero files to next. That is the routine back-merge ADR-0019 set
out to remove.

Change

Replaces the precondition with an empty three-dot content diff, which asserts
what the step was actually trying to establish: the stable branch carries no
content the candidate lacks.

git fetch origin main next
test -z "$(git diff --name-only origin/next...origin/main)"

Also documents why the ancestor test is correct in the hotfix-synchronization
step, where the merge runs in the opposite direction. That asymmetry is the
likely origin of the defect.

Verification

Both checks exercised across the four states a persistent integration branch can
occupy, in a scratch repository:

Scenario old check new check Correct
Just promoted, healthy fail pass pass
Work continued on next, healthy fail pass pass
Unmerged hotfix on main fail fail fail
Hotfix synchronized forward pass pass pass

The third row confirms this is not a check that passes unconditionally: a
genuine stable-only commit is still caught.

Applied to the live pending z-shell/zi candidate, the new check passes where
the old one falsely failed, and git diff --name-only origin/next...origin/main
is empty.

trunk check reports no issues on the changed file.

Follow-up

z-shell/zi carries the same defect in
.github/PULL_REQUEST_TEMPLATE/promotion.md, which would reimpose the
impossible check on the promotion pull request itself. Tracked separately and
should land before the pending promotion.

The promotion procedure required
`git merge-base --is-ancestor origin/main origin/next`. That check cannot pass
after a successful promotion: promotion creates a merge commit on `main` that
never exists on `next`, so `main` stops being an ancestor of `next` as soon as
a promotion lands. ADR-0019 states the opposite property, that promotion needs
no back-merge because the promoted `next` commit becomes an ancestor of `main`.

Reading the failure as drift produced a no-content reconciliation merge before
each promotion, the routine back-merge ADR-0019 set out to remove.

Replace the precondition with an empty three-dot content diff, which holds
right after a promotion and while work continues on `next`, and still fails
when a genuine stable-only commit such as an unmerged hotfix exists on `main`.

Note that the hotfix-synchronization step keeps the ancestor test, where it is
correct, because that direction merges `main` into `next`.
@ss-o
ss-o requested a review from a team as a code owner August 30, 2026 04:22
@ss-o
ss-o merged commit 92cf4f3 into main Aug 30, 2026
7 checks passed
@ss-o
ss-o deleted the code/promotion-precondition-ancestry branch August 30, 2026 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(branching): promotion precondition cannot be satisfied

1 participant