| name | finishing-a-development-branch |
| description | Use when implementation is complete, branch verification passes, and you need to decide how to integrate the work |
Finishing a Development Branch
Overview
Guide completion of development work by selecting a mode, then executing the appropriate flow (autonomous push+PR or interactive menu).
Core principle: Verify the project-defined branch gate -> choose mode (autonomous default) -> execute -> clean up.
Announce at start: "I'm using the finishing-a-development-branch skill to complete this work."
Mode Selection
If the agent was just finishing an autonomous execution run (i.e. this skill is being invoked as the final step of razorback:executing-plans or razorback:subagent-driven-development), use Autonomous Mode. If the user invoked the skill directly (e.g. "finish this branch"), use Interactive Mode. In ambiguous cases, default to Autonomous - run-to-completion is the bias.
Autonomous Mode
No menu, no prompts. Push the branch, open a PR with the morning-report summary, write the full report to .memories/, emit a one-line terminal pointer, exit. Merge is never auto-performed.
Step 1: Verify branch gate
Use the plan's Verification Strategy and verification ledger.
Run the project-defined branch-gate scope before push or PR. If the verification ledger already has a passing branch-gate entry for the current HEAD, reuse that evidence instead of rerunning the same command. Add any required expensive-specialist scopes when touched areas demand them.
If required verification fails, this is a blocker taxonomy #5 (unresolvable test failures). Do not create a PR. Instead:
- Render a partial morning report with
Status: Blocked, the failure summary in the Tests section, and the blocker description in Blockers hit.
- Write it to
.memories/autonomous-run-YYYY-MM-DD-<slug>.md.
- Emit terminal one-liner:
Blocked. Report: .memories/autonomous-run-YYYY-MM-DD-<slug>.md and exit.
If required verification passes, continue.
Step 2: Determine base branch and merge-base commit
git merge-base returns a commit SHA, not a branch name. Autonomous Mode needs both: the branch name for gh pr create --base, and the SHA for diff-range computation. Resolve them as two separate values:
if [ -n "$PLAN_BASE" ]; then
BASE_BRANCH="$PLAN_BASE"
elif DEFAULT_REF=$(git symbolic-ref --quiet refs/remotes/origin/HEAD 2>/dev/null); then
BASE_BRANCH="${DEFAULT_REF#refs/remotes/origin/}"
elif git show-ref --verify --quiet refs/heads/main; then
BASE_BRANCH=main
elif git show-ref --verify --quiet refs/heads/master; then
BASE_BRANCH=master
fi
if [ -z "$BASE_BRANCH" ] || ! BASE_SHA=$(git merge-base HEAD "$BASE_BRANCH" 2>/dev/null); then
echo "Cannot determine PR base branch/merge-base." >&2
fi
Use $BASE_SHA for any base..HEAD range computation (e.g. git diff --stat $BASE_SHA..HEAD in Step 3). Use $BASE_BRANCH for gh pr create --base "$BASE_BRANCH" in Step 6.
If both lookups fail (no main, no master ancestor), that's a blocker per taxonomy #3. Render a partial morning report with Status: Blocked, describe the missing base in Blockers hit, write it to .memories/autonomous-run-YYYY-MM-DD-<slug>.md, emit the terminal one-liner, and exit. Do not push.
Step 3: Render morning report
Fill the placeholders in ./morning-report-template.md using the fields the caller accumulated during execution (plan name + path, branch name, phases complete/total, tasks complete/total, duration, judgment calls log, external review outcome, tests summary, blockers, files changed from git diff --stat $BASE_SHA..HEAD, next steps).
Produce two renderings:
- Full report — every section filled in, for
.memories/ and for review.
- PR summary — status, What shipped, External review, Blockers, Next steps only. The Judgment calls section is not inlined in the PR description; the PR body points at the
.memories/ file instead (committed in Step 4, so the link is live the moment the PR opens).
Step 4: Write full report + commit
Write the full rendered report to .memories/autonomous-run-YYYY-MM-DD-<slug>.md, where <slug> is a short kebab-case identifier for the plan (e.g. autonomous-execution). Committing it before the push means the PR includes the report from its first revision — no dead link in the PR body. The PR does not exist yet, so render {{pr_url}} as pending — filled in after PR creation; Step 7 writes the real URL back.
git add .memories/autonomous-run-YYYY-MM-DD-<slug>.md
git commit -m "docs: autonomous run report for <plan name>"
This commit (and the Step 7 URL write-back) are metadata-only: they touch nothing outside .memories/, so the Step 1 branch-gate evidence carries over to the new HEAD. If anything outside .memories/ changes after Step 1, the evidence is invalidated — re-run the branch gate before pushing.
Step 5: Push branch
git push -u origin <branch>
If the push is rejected (branch already tracks a different remote, non-fast-forward, network failure), log the exact error in the report's Blockers hit section, set Status: Blocked, commit the updated report, emit the terminal pointer, and exit. Do not retry with --force.
Step 6: Create PR
gh pr create \
--base "$BASE_BRANCH" \
--title "<plan name or feature name>" \
--body "$(rendered_pr_summary)"
If gh is not installed or the command fails (auth, network, repo not on origin), update the report with the failure in Blockers hit and Status: Partial (the branch was pushed but the PR was not created), commit and push the update, emit the terminal pointer, and exit.
Capture the PR URL from gh's output.
Step 7: Write the PR URL back into the report
Replace the pending — filled in after PR creation value in the committed report with the captured URL, then commit and push the update. This is a metadata-only commit; the branch-gate evidence still holds (see Step 4).
git add .memories/autonomous-run-YYYY-MM-DD-<slug>.md
git commit -m "docs: record PR URL in run report"
git push
Step 8: Emit terminal pointer
One line, then exit:
Done. PR: <url>. Report: .memories/autonomous-run-YYYY-MM-DD-<slug>.md
Autonomous Mode rules
- Never merge. Stopping at PR creation is the point; merge is a separate human (or agent) action after PR review.
- Never show a menu, never ask "which option". Autonomous means no prompts.
- Never fall back to Interactive Mode mid-run. If a step fails (push rejected,
gh missing, remote mismatch), emit a partial report with Status: Blocked or Status: Partial as appropriate and let the user resolve from there.
- Always write the report to
.memories/, even on blocked/partial outcomes — the report is the user's morning read regardless of outcome.
Interactive Mode
Used when the user invokes this skill directly ("finish this branch"). Presents the classic 4-option menu.
Step 1: Verify Branch Gate
Before presenting options, verify the project-defined branch gate passes or reuse a passing ledger entry for current HEAD:
<branch-gate command>
If verification fails:
Branch verification failing (<N> failures). Must fix before completing:
[Show failures]
Cannot proceed with merge/PR until branch verification passes.
Stop. Don't proceed to Step 2.
If verification passes: Continue to Step 2.
Step 2: Determine Base Branch
git merge-base returns a commit SHA, not a branch name. Downstream steps need the branch name (git checkout <base-branch>, gh pr create --base), so resolve both values the same way Autonomous Step 2 does:
if [ -n "$PLAN_BASE" ]; then
BASE_BRANCH="$PLAN_BASE"
elif DEFAULT_REF=$(git symbolic-ref --quiet refs/remotes/origin/HEAD 2>/dev/null); then
BASE_BRANCH="${DEFAULT_REF#refs/remotes/origin/}"
elif git show-ref --verify --quiet refs/heads/main; then
BASE_BRANCH=main
elif git show-ref --verify --quiet refs/heads/master; then
BASE_BRANCH=master
fi
if [ -z "$BASE_BRANCH" ] || ! BASE_SHA=$(git merge-base HEAD "$BASE_BRANCH" 2>/dev/null); then
echo "Cannot determine base branch/merge-base." >&2
fi
If nothing resolves, ask: "This branch split from main - is that correct?"
Step 3: Present Options
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?
Don't add explanation - keep options concise.
Step 4: Execute Choice
Option 1: Merge Locally
git checkout <base-branch>
git pull
git merge <feature-branch>
<branch-gate command>
git branch -d <feature-branch>
Then: Cleanup worktree (Step 5)
Option 2: Push and Create PR
git push -u origin <feature-branch>
gh pr create --title "<title>" --body "$(cat <<'EOF'
## Summary
<2-3 bullets of what changed>
## Test Plan
- [ ] <verification steps>
EOF
)"
Then: Cleanup worktree (Step 5)
Option 3: Keep As-Is
Report: "Keeping branch . Worktree preserved at ."
Don't cleanup worktree.
Option 4: Discard
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:
git checkout <base-branch>
git branch -D <feature-branch>
Then: Cleanup worktree (Step 5)
Step 5: Cleanup Worktree
For Options 1, 2, 4:
Check if in worktree:
git worktree list | grep $(git branch --show-current)
If yes:
git worktree remove <worktree-path>
For Option 3: Keep worktree.
Quick Reference
| 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) |
Common Mistakes
Skipping test verification
- Problem: Merge broken code, create failing PR
- Fix: Always verify tests before offering options
Open-ended questions
- Problem: "What should I do next?" -> ambiguous
- Fix: Present exactly 4 structured options
Automatic worktree cleanup
- Problem: Remove worktree when might need it (Option 2, 3)
- Fix: Only cleanup for Options 1 and 4
No confirmation for discard
- Problem: Accidentally delete work
- Fix: Require typed "discard" confirmation
Red Flags
Never:
- Proceed with failing tests
- Merge without verifying tests on result
- Delete work without confirmation
- Force-push without explicit request
- Merge in autonomous mode — merge is always a separate human (or agent) action after PR review
- Fall back to Interactive Mode mid-autonomous-run — if autonomous mode can't complete (e.g.
gh not installed), emit a partial report with status Blocked and let the user resolve; don't prompt for an option
Always:
- Verify tests before offering options (Interactive) or before pushing (Autonomous)
- In Interactive Mode, present exactly 4 options
- Get typed confirmation for Option 4
- Clean up worktree for Options 1 & 4 only
- In Autonomous Mode, emit the morning report to all three destinations (PR summary,
.memories/ file, terminal one-liner) regardless of outcome
Integration
Called by:
razorback:executing-plans (Step 5) — Autonomous mode when the execution skill finishes cleanly
razorback:subagent-driven-development (Step 5 or 4a+finish) — Autonomous mode
- Direct user invocation ("finish this branch") — Interactive mode
Pairs with:
- using-git-worktrees - Cleans up worktree created by that skill (Interactive Mode, Options 1 & 4)
- morning-report-template.md (this directory) — template rendered by Autonomous Mode Step 3