skills/finishing-a-development-branch/SKILL.md
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
npx skillsauth add sartoris-digital/pi-superpowers finishing-a-development-branchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Guide completion of development work by presenting clear options and handling the chosen workflow.
Core principle: Verify tests → Detect environment → Present options → Execute choice → Clean up.
Announce at start: "I'm using the finishing-a-development-branch skill to complete this work."
Before presenting options, verify tests pass:
# Run project's test suite
npm test / cargo test / pytest / go test ./...
If tests fail:
Tests failing (<N> failures). Must fix before completing:
[Show failures]
Cannot proceed with merge/PR until tests pass.
Stop. Don't proceed to Step 2.
If tests pass: Continue to Step 2.
Determine workspace state before presenting options:
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
Submodule guard: GIT_DIR != GIT_COMMON is also true inside git submodules. Before concluding "in a linked worktree," verify the agent is not in a submodule:
# If this returns a path, the agent is in a submodule — treat as a normal repo
git rev-parse --show-superproject-working-tree 2>/dev/null
This determines which menu to show and how cleanup works:
| State | Menu | Cleanup |
|-------|------|---------|
| GIT_DIR == GIT_COMMON (normal repo or submodule) | Standard 4 options | No worktree to clean up |
| GIT_DIR != GIT_COMMON, named branch | Standard 4 options | Provenance-based (see Step 6) |
| GIT_DIR != GIT_COMMON, detached HEAD | Reduced 2 options (no merge, no separate keep) | No cleanup (externally managed) |
# Try common base branches
git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null
Or ask: "This branch split from main — is that correct?"
Normal repo and named-branch worktree — present exactly these 4 options:
Implementation complete. What would you like to do?
1. Merge back to <base-branch> locally
2. Push and create a Pull Request
3. Keep the branch as-is (I'll handle it later)
4. Discard this work
Which option?
Detached HEAD — present exactly these 2 options:
The workspace is externally managed and there is no branch to merge from, so the menu collapses:
Implementation complete. You're on a detached HEAD (externally managed workspace).
1. Push as new branch and create a Pull Request
2. Discard this work
Which option?
Don't add explanation — keep options concise.
# Get main repo root for CWD safety
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"
# Merge first — verify success before removing anything
git checkout <base-branch>
git pull
git merge <feature-branch>
# Verify tests on merged result
<test command>
Then: Cleanup worktree (Step 6), then delete branch:
git branch -d <feature-branch>
# Push branch
git push -u origin <feature-branch>
# Create PR
gh pr create --title "<title>" --body "$(cat <<'EOF'
## Summary
<2-3 bullets of what changed>
## Test Plan
- [ ] <verification steps>
EOF
)"
Do NOT clean up worktree — user needs it alive to iterate on PR feedback.
Report: "Keeping branch <name>. Worktree preserved at <path>."
Don't cleanup worktree.
Confirm first:
This will permanently delete:
- Branch <name>
- All commits: <commit-list>
- Worktree at <path>
Type 'discard' to confirm.
Wait for exact confirmation.
If confirmed:
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"
Then: Cleanup worktree (Step 6), then force-delete branch:
git branch -D <feature-branch>
Only runs for Options 1 and 4. Options 2 and 3 always preserve the worktree.
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
WORKTREE_PATH=$(git rev-parse --show-toplevel)
If GIT_DIR == GIT_COMMON: Normal repo, no worktree to clean up. Done.
Otherwise — provenance check: The skill only removes worktrees it (or using-git-worktrees) created. Everything else is left alone.
Authoritative source for cleanup decisions is git worktree list --porcelain — nothing else. Do not infer ownership from filesystem walks, environment variables, or other heuristics. The provenance rules below are strict and non-negotiable.
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
WORKTREES_DIR="$MAIN_ROOT/.worktrees"
# Enumerate registered worktrees from git's authoritative source
git -C "$MAIN_ROOT" worktree list --porcelain
Apply all of these checks against the candidate worktree path before removing:
git worktree list --porcelain output. If git does not know about it, do not touch it.realpath resolution: Resolve the candidate with realpath (or readlink -f / pwd -P). Compare the resolved path, not the raw string.<repo>/.worktrees/: The resolved path must be exactly one directory below <MAIN_ROOT>/.worktrees/. Nested deeper, no... traversal: Reject any candidate whose original (pre-realpath) path contains ...If all five checks pass: the skill owns this worktree.
git -C "$MAIN_ROOT" worktree remove "$WORKTREE_PATH"
git worktree remove. No rm -rf fallback ever. If git worktree remove fails, surface the error to the user and stop — do not try to clean up with shell file removal.git worktree prune to clear any stale registrations git noticed. Stale metadata (unreferenced entries that git worktree prune would remove) is logged but not auto-removed without consent — print the prune dry-run output, ask the user before applying, and only apply on explicit approval.git -C "$MAIN_ROOT" worktree prune --dry-run --verbose
# If stale entries exist, ask the user before running:
# git -C "$MAIN_ROOT" worktree prune --verbose
Otherwise (any check fails): The host environment (harness, the user, another tool) owns this workspace. Do NOT remove it. If the harness provides a workspace-exit tool, use it. Otherwise, leave the workspace in place and report.
| Option | Merge | Push | Keep Worktree | Cleanup Branch | |--------|-------|------|---------------|----------------| | 1. Merge locally | yes | - | - | yes | | 2. Create PR | - | yes | yes | - | | 3. Keep as-is | - | - | yes | - | | 4. Discard | - | - | - | yes (force) |
Skipping test verification
Open-ended questions
Cleaning up worktree for Option 2
Deleting branch before removing worktree
git branch -d fails because worktree still references the branchRunning git worktree remove from inside the worktree
cd to main repo root before git worktree removeCleaning up worktrees the skill did not create
git worktree list --porcelain is the only authority; require realpath-resolved direct child of <repo>/.worktrees/, no symlinks, no ..Using rm -rf to force-clean a worktree
git worktree remove. No rm -rf fallback ever. If git worktree remove fails, stop and surface the error.Auto-pruning stale metadata
git worktree prune removes registrations the user might still expect--dry-run, do not apply without consentNo confirmation for discard
Never:
git worktree list --porcelain as authoritative for ownershipgit worktree remove from inside the worktreerm -rf when git worktree remove failsgit worktree prune without user consentAlways:
cd to main repo root before worktree removalrealpath candidate paths, reject symlinks and .., require direct child of <repo>/.worktrees/git worktree remove (no rm -rf)Pi has no native worktree tool. The bundled @mariozechner/pi-coding-agent tool registry and the pi-superpowers extension surface (bootstrap, subagent, state-manager, persistence-engine, orchestrator) do not expose any worktree, EnterWorktree, or ExitWorktree primitive. All cleanup runs through git worktree remove invoked via bash.
The provenance rules (Step 6) are enforced through bash invocations of git worktree list --porcelain, realpath, and git worktree remove. If a future Pi extension registers a workspace-exit tool, this skill should defer to it after the provenance check passes; for now, the bash path is the only path.
testing
Use when creating new skills, editing existing skills, or verifying skills work before deployment
development
Use when you have a spec or requirements for a multi-step task, before touching code
data-ai
Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
tools
Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions