Problem
pdd checkup (PR/fix mode) aborts during worktree setup when a stale checkup/issue-N branch is already present. _setup_worktree in pdd/agentic_checkup_orchestrator.py deletes the existing branch but ignores the result of _delete_branch and unconditionally sets has_branch = False. When the delete fails — which happens when the branch is still registered to a worktree directory that no longer exists (a crashed or out-of-band-cleaned-up prior run) — the subsequent git worktree add -b fails and the whole checkup dies.
Reproduction
from pathlib import Path
import subprocess, shutil, tempfile
from pdd.agentic_checkup_orchestrator import _setup_worktree
d = Path(tempfile.mkdtemp())
def git(*a): return subprocess.run(["git", *a], cwd=d, capture_output=True, text=True)
git("init", "-q"); git("config","user.email","t@x"); git("config","user.name","t")
(d/"f.txt").write_text("x\n"); git("add","."); git("commit","-q","-m","init")
# Stale branch: registered to a worktree dir that is then removed out of band.
stale = d/"old-wt"
git("worktree","add","-q","-b","checkup/issue-7", str(stale), "HEAD")
shutil.rmtree(stale)
print(_setup_worktree(d, issue_number=7, quiet=True, resume_existing=False))
Actual:
(None, "Failed to create worktree: Preparing worktree (new branch 'checkup/issue-7')\nfatal: a branch named 'checkup/issue-7' already exists")
(git branch -D checkup/issue-7 first fails with Cannot delete branch 'checkup/issue-7' checked out at '<gone path>', but that failure is swallowed.)
Expected: the stale branch is reset and a fresh worktree is created; the checkup proceeds.
Root cause
pdd/agentic_checkup_orchestrator.py _setup_worktree, step "Handle existing branch":
_delete_branch(git_root, branch_name) # return value ignored
has_branch = False # assumes success unconditionally
There is also no git worktree prune to clear the stale worktree registration that blocks the delete.
Proposed fix
git worktree prune before handling the branch, so a branch left registered to a removed worktree directory can be deleted/recreated.
- Check
_delete_branch's return value; only set has_branch = False on success.
- If the branch is still undeletable after pruning (genuinely checked out in a live worktree), return a clear, actionable error instead of the cryptic
Failed to create worktree.
Acceptance criteria
- A stale
checkup/issue-N branch from a removed worktree dir no longer fails checkup — the branch is reset and a fresh worktree is created.
- A plain leftover branch (not checked out) still works.
- A branch genuinely checked out in another live worktree yields a clear, actionable error (which worktree to remove), not
Failed to create worktree: a branch named ... already exists.
- Regression test covering all three cases against a real git repo.
🤖 Filed from Claude Code.
Problem
pdd checkup(PR/fix mode) aborts during worktree setup when a stalecheckup/issue-Nbranch is already present._setup_worktreeinpdd/agentic_checkup_orchestrator.pydeletes the existing branch but ignores the result of_delete_branchand unconditionally setshas_branch = False. When the delete fails — which happens when the branch is still registered to a worktree directory that no longer exists (a crashed or out-of-band-cleaned-up prior run) — the subsequentgit worktree add -bfails and the whole checkup dies.Reproduction
Actual:
(
git branch -D checkup/issue-7first fails withCannot delete branch 'checkup/issue-7' checked out at '<gone path>', but that failure is swallowed.)Expected: the stale branch is reset and a fresh worktree is created; the checkup proceeds.
Root cause
pdd/agentic_checkup_orchestrator.py_setup_worktree, step "Handle existing branch":There is also no
git worktree pruneto clear the stale worktree registration that blocks the delete.Proposed fix
git worktree prunebefore handling the branch, so a branch left registered to a removed worktree directory can be deleted/recreated._delete_branch's return value; only sethas_branch = Falseon success.Failed to create worktree.Acceptance criteria
checkup/issue-Nbranch from a removed worktree dir no longer fails checkup — the branch is reset and a fresh worktree is created.Failed to create worktree: a branch named ... already exists.🤖 Filed from Claude Code.