Repository navigation
orchestrate: gh pr merge --delete-branch leaks the remote slice branch on every slice (recurrence of closed #284, prose still false) #384
Description
Found during orchestrate run prd352-20260803-015333 (PRD #352, 12 slices, all passed).
Symptom
On slice #353, gh pr merge 366 --squash --delete-branch exited 1 with:
failed to delete local branch orchestrate/slice-353: failed to run git: error: cannot delete
branch 'orchestrate/slice-353' used by worktree at '.../slice-353'
The squash-merge itself landed correctly (PR MERGED, umbrella tip moved to the squash commit). But git ls-remote --heads origin orchestrate/slice-353 still returned the branch after the merge.
The real defect
references/slice-pipeline.md step 8 says the local-branch failure is "tolerated, not a slice failure", and step 9 says "the remote half was done by --delete-branch at step 8, the local half here." That second claim is false in the worktree case: gh aborts on the local-delete error before deleting the remote ref.
Since the plugin creates a worktree for every slice and holds it until step 9, this leaks one remote branch per slice, on every run — the exact condition the "incremental reclamation" design says it prevents. It also silently breaks any non-zero-exit-code check on the merge step: a successful merge returns exit 1.
Current-code verification (this run, not inherited)
plugins/orchestrate/skills/orchestrate/references/slice-pipeline.md:330-335— still asserts "The--delete-branchflag reclaims the remote slice branch as part of the merge; it may additionally warn or no-op on the local branch … that warning is tolerated, not a slice failure."plugins/orchestrate/skills/orchestrate/references/slice-pipeline.md:420— still asserts "This completes incremental reclamation: the remote half was done by--delete-branchat step 8, the local half here."plugins/orchestrate/orchestrate-mcp/src/tools/finalize-slice.ts—finalizePostMergeperforms no remote operation: it checkpointssubState: merged, removes the worktree, then callsdeleteLocalBranch(branch, repoPath)and returns. There is nogit push --deleteanywhere in the phase. Sogh pr merge --delete-branchremains the only remote-reclaim attempt.
Workaround used
Explicit git push origin --delete orchestrate/slice-<N> after finalize_slice post-merge returned ok.
Suggested fix
Either:
- Drop
--delete-branchfrom step 8 entirely and havefinalize_slice'spost-mergephase reclaim both halves — it already removes the worktree first, which is precisely the ordering that makes the local delete succeed. Dropping the flag also restores the meaning of the merge step's exit code. - Or keep the flag but make step 8 verify the remote ref is gone with
git ls-remoteand delete it explicitly when it is not.
Either way, correct the step-9 prose, which currently asserts a remote reclamation that did not happen.
Relationship to existing issues (read before deduping)
- This is a recurrence of closed orchestrate: remote slice branch survives merge when local delete fails (worktree checked out) — remote cruft accumulates every run #284, which diagnosed exactly this leak (across two repos and two PRDs) and proposed the same fixes. orchestrate: remote slice branch survives merge when local delete fails (worktree checked out) — remote cruft accumulates every run #284 was closed on 2026-06-05 with no linked fix commit, and the two prose claims it flagged are byte-unchanged today (see the line citations above), as is
finalizePostMerge's local-only behavior. Filed as a fresh issue rather than a comment because a closed issue cannot track the work — the same precedent orchestrate: remote slice branch survives merge when local delete fails (worktree checked out) — remote cruft accumulates every run #284 itself used when it was filed as the field regression of closed orchestrate: cleanup enforcement — incremental slice-branch reclamation + failed-worktree retention/reclaim #232. A pointer comment has been left on orchestrate: remote slice branch survives merge when local delete fails (worktree checked out) — remote cruft accumulates every run #284. - Not orchestrate: slice→umbrella
gh pr mergeblocked by Claude Code auto-mode self-approval classifier, halting an autonomous run mid-wave #350 (auto-mode self-approval classifier blockinggh pr merge): a permission-layer block, unrelated to branch reclamation. - Not finalize_slice reports false "committed-pushed" when slice worktree is checked out on the base/umbrella branch #349 (
finalize_slicefalsecommitted-pushedon a wrong-branch checkout): a different phase (commit-push) and a different failure.
Acceptance criteria — documentation in-sync (P0)
The false invariant is at least half the payload here. Any code fix must land with the corrected prose in references/slice-pipeline.md (steps 8 and 9) in the same unit of work; a code-only fix leaves the contract still wrong.
Environment
orchestrate 1.6.0 (plugins/orchestrate/.claude-plugin/plugin.json:3 on development) plus the PRD #352 umbrella branch (slice-executor delegation layer). Run prd352-20260803-015333.
Activity