Source: engagement-retro (eng-4b71)
Title: git branch -d can approve a deletion on the word of a stale remote-tracking ref, so it contributes no safety at all — and the documented cleanup order is what lets it pass
Measured. Cleaning up two squash-merged branches, the session predicted git branch -d would
refuse (after a squash the branch is not an ancestor of its base) and planned to fall back to
-D once content was verified. It did not refuse. It printed:
deleting branch '22-revendor-cadence' that has been merged to
refs/remotes/origin/22-revendor-cadence, but not yet merged to HEAD
and deleted — consulting a stale remote-tracking ref for a branch the forge had already
auto-deleted at merge. Not the remote, and not local main.
The ordering consequence is the sharp part. The documented cleanup order is sync → verify →
delete → prune. Pruning first would have removed the stale ref, made -d refuse, and forced
the explicit -D — so the documented order is precisely what lets the weak flag pass. What kept
this safe was that the content verification was done independently of the flag that was supposed to
enforce it: git diff --stat <branch> <merge-commit> returning empty. That comparison must be made
against the merge commit, not today's main, which is ahead and yields a non-empty diff that
reads like unmerged work — a fifth-hand instance of the same session's own pattern.
Proposed mechanism.
- (a) State that the upstream
-d consults may no longer exist, so -d succeeding is not
evidence of anything. The existing guidance frames the risk as local main behind; that is the
weaker half.
- (b) The check that licenses a branch deletion is the content comparison against the commit
that merged it, run independently of the deletion flag.
- (c) Note that pruning before deleting changes
-d's answer, so the cleanup order is
load-bearing and should be stated as such rather than as tidiness.
Companion, worth stating beside it: a local cache of a remote's state answers a different
question than the remote does, and the two are indistinguishable on screen. Two instances in this
window alone — git branch -r (stale remote-tracking refs) read as a listing of remote branches, and
a branch diff taken against today's main rather than the merge commit. git ls-remote --heads origin is the question that was meant.
Gate-2 recommendation: the companion clause may belong as a comment on #76 (four measured
shell traps the harness-trap list does not carry) rather than in this issue's body. Recorded here,
not acted on.
Source: orchestrator/findings/2026-09-01-025-slice-22-revendor-cadence.md;
orchestrator/lessons.md 2026-09-01 (git branch -d consulted a stale tracking ref and deleted
anyway).
Title:
git branch -dcan approve a deletion on the word of a stale remote-tracking ref, so it contributes no safety at all — and the documented cleanup order is what lets it passMeasured. Cleaning up two squash-merged branches, the session predicted
git branch -dwouldrefuse (after a squash the branch is not an ancestor of its base) and planned to fall back to
-Donce content was verified. It did not refuse. It printed:and deleted — consulting a stale remote-tracking ref for a branch the forge had already
auto-deleted at merge. Not the remote, and not local
main.The ordering consequence is the sharp part. The documented cleanup order is sync → verify →
delete → prune. Pruning first would have removed the stale ref, made
-drefuse, and forcedthe explicit
-D— so the documented order is precisely what lets the weak flag pass. What keptthis safe was that the content verification was done independently of the flag that was supposed to
enforce it:
git diff --stat <branch> <merge-commit>returning empty. That comparison must be madeagainst the merge commit, not today's
main, which is ahead and yields a non-empty diff thatreads like unmerged work — a fifth-hand instance of the same session's own pattern.
Proposed mechanism.
-dconsults may no longer exist, so-dsucceeding is notevidence of anything. The existing guidance frames the risk as local
mainbehind; that is theweaker half.
that merged it, run independently of the deletion flag.
-d's answer, so the cleanup order isload-bearing and should be stated as such rather than as tidiness.
Companion, worth stating beside it: a local cache of a remote's state answers a different
question than the remote does, and the two are indistinguishable on screen. Two instances in this
window alone —
git branch -r(stale remote-tracking refs) read as a listing of remote branches, anda branch diff taken against today's
mainrather than the merge commit.git ls-remote --heads originis the question that was meant.Gate-2 recommendation: the companion clause may belong as a comment on
#76(four measuredshell traps the harness-trap list does not carry) rather than in this issue's body. Recorded here,
not acted on.
Source:
orchestrator/findings/2026-09-01-025-slice-22-revendor-cadence.md;orchestrator/lessons.md2026-09-01 (git branch -dconsulted a stale tracking ref and deletedanyway).