---
name: build-pr-workflow
description: "Use when feature work needs git lifecycle management — triggered by phrases like 'create a worktree', 'open a PR', 'finish this branch', 'cut a PR', 'set up the feature branch', 'merge this up', 'wrap up the PR'. Covers worktree creation, atomic per-slice commits, PR opening with summary + test plan, and merge handoff. Skip one-off git questions ('what does rebase do', 'why did this conflict resolve that way') where a direct explanation is the right shape, not a workflow."
---

# PR Workflow

## Overview

Manage the full git workflow lifecycle: create isolated workspaces, make atomic commits during development, and finish work with structured options for merge or PR creation.

**Announce at start:** "I'm using the build-pr-workflow skill to manage the git workflow."

## When to Use

- Starting any feature, bugfix, or refactor that needs branch isolation
- Creating pull requests from completed work
- Finishing a development branch (merge, PR, keep, or discard)

## When to load references

- **`references/worktree-setup.md`** — Phase 1 detail: directory selection priority, safety-verification gitignore check, step-by-step worktree creation. Load before starting a new branch.
- **`references/pr-template.md`** — Phase 3 detail: the full PR description template and the `gh pr create` HEREDOC. Load when ready to open the PR.
- **`references/subagent-merge.md`** — Protocol for integrating output from subagents dispatched with `isolation: "worktree"`. Load when a worktree-isolated subagent has returned.

## Phase 1: Worktree Creation

The detailed procedure (directory priority, gitignore safety, project setup, baseline verification) lives in **`references/worktree-setup.md`** — load it before starting a new worktree.

In summary:

1. Pick the worktree directory: `.worktrees/` (preferred) → `worktrees/` → CLAUDE.md preference → ask the user.
2. **Verify it's gitignored.** If not, add to `.gitignore` and commit before creating the worktree.
3. `git worktree add <path> -b <branch-name>` using the conventional branch prefix (`feat/`, `fix/`, `refactor/`, `hotfix/`).
4. Run project setup (npm install, pip install, cargo build, go mod download as appropriate).
5. Verify clean baseline by running the project's test command. If tests fail, report and ask.

## Phase 2: Development

### Commit Discipline

One commit per logical unit of work. Each commit must:

1. **Be atomic** — Contains exactly one logical change
2. **Pass all tests** — Never commit broken code
3. **Use conventional commits** — Format: `type(scope): description`

```
feat(auth): add JWT token validation middleware
fix(api): handle null email in user creation
refactor(db): extract connection pool configuration
test(auth): add integration tests for login flow
docs(api): update endpoint documentation
```

### Commit Workflow

```bash
# 1. Verify tests pass before committing
npm test  # or equivalent

# 2. Stage specific files (never git add .)
git add src/auth/middleware.ts tests/auth/middleware.test.ts

# 3. Commit with conventional message
git commit -m "feat(auth): add JWT token validation middleware"
```

**Rules:**
- Run tests before every commit
- Stage specific files, not everything
- Never commit `.env`, secrets, or large binaries
- One logical change per commit, not "save my progress"

### Atomic Commit Splitting

When a changeset touches 3+ files, split into multiple atomic commits along logical boundaries:

| Files Changed | Minimum Commits |
|---|---|
| 3-4 files | 2+ commits |
| 5-9 files | 3+ commits |
| 10+ files | 5+ commits |

**Split along these boundaries:**
- Separate module/component boundaries
- Separate concern types (types, logic, tests, config)
- Each commit independently revertable without breaking the project

**Before splitting:** Analyze the last 30 commits to detect the project's commit style. If mixed styles, conventional commits take precedence when ≥50% of commits use them. If the repo has fewer than 30 commits or no clear majority, default to conventional commits per git-workflow.md.

### During TDD Cycles

A natural commit rhythm during TDD:

1. RED-GREEN-REFACTOR cycle for behavior A -> commit
2. RED-GREEN-REFACTOR cycle for behavior B -> commit
3. RED-GREEN-REFACTOR cycle for behavior C -> commit

Each commit captures one complete TDD cycle. The commit message describes the behavior added, not the test written.

## Phase 3: PR Creation

### PR-Per-Function Strategy

Each PR should cover one logical function or component. This means:

- **One PR per API endpoint** (e.g., "Add POST /api/users endpoint")
- **One PR per UI component** (e.g., "Add UserProfileCard component")
- **One PR per service** (e.g., "Add email notification service")
- **One PR per migration** (e.g., "Add users table migration")

**Not one giant PR** with everything. Not one PR per file either. One PR per logical unit that can be reviewed, tested, and merged independently.

### PR Requirements

Each PR must be:

1. **Independently mergeable** — Does not break anything if merged alone
2. **Independently testable** — Has its own tests that pass
3. **Properly described** — Links to feature manifest and requirements
4. **Small enough to review** — Under 400 lines of diff is ideal

### Creating the PR

The full template and HEREDOC live in **`references/pr-template.md`** — load it when you're ready to open the PR. The required sections are: Summary, Feature Manifest, Requirements Traceability, Changes, Test Plan, Checklist.

## Phase 4: Finishing

### Step 1: Verify Tests

**Before presenting options, verify tests pass:**

```bash
npm test / pytest / cargo test / go test ./...
```

**If tests fail:**
```
Tests failing (<N> failures). Must fix before completing:

[Show failures]

Cannot proceed with merge/PR until tests pass.
```

Stop. Do not proceed.

**If tests pass:** Continue.

### Step 2: Determine Base Branch

```bash
# 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?"

### 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?
```

Keep options concise. Do not add lengthy explanations.

### Step 4: Execute Choice

#### Option 1: Merge Locally

```bash
# Switch to base branch
git checkout <base-branch>

# Pull latest
git pull

# Merge feature branch
git merge <feature-branch>

# Verify tests on merged result
npm test

# If tests pass, delete feature branch
git branch -d <feature-branch>
```

Then: Clean up worktree (Step 5).

#### Option 2: Push and Create PR

Follow **`references/pr-template.md`** for the structured body. Push, create the PR, report the URL. Then: Clean up worktree (Step 5).

#### Option 3: Keep As-Is

Report: "Keeping branch `<name>`. Worktree preserved at `<path>`."

**Do not clean up worktree.**

#### Option 4: Discard

**Confirm first:**
```
This will permanently delete:
- Branch <name>
- All commits on this branch
- Worktree at <path>

Type 'discard' to confirm.
```

Wait for exact confirmation. If confirmed:

```bash
git checkout <base-branch>
git branch -D <feature-branch>
```

Then: Clean up worktree (Step 5).

### Step 5: Worktree Cleanup

**For Options 1, 2, 4:**

```bash
# Check if working in a worktree
git worktree list | grep <feature-branch>

# If yes, remove it
git worktree remove <worktree-path>
```

**For Option 3:** Keep worktree intact.

## Merging Subagent Worktree Output

When dispatching subagents with `isolation: "worktree"`, follow the protocol in **`references/subagent-merge.md`** — it covers: requiring the subagent to commit, verifying commits before merging, merging via `git merge --no-ff` (never `cp`), and worktree cleanup.

## Quick Reference

### Worktree Selection

| Situation | Action |
|-----------|--------|
| `.worktrees/` exists | Use it (verify ignored) |
| `worktrees/` exists | Use it (verify ignored) |
| Both exist | Use `.worktrees/` |
| Neither exists | Check CLAUDE.md, then ask user |
| Directory not ignored | Add to .gitignore + commit first |
| Tests fail during baseline | Report failures + ask |

### Finishing Options

| Option | Merge | Push | Keep Worktree | Delete Branch |
|--------|-------|------|---------------|---------------|
| 1. Merge locally | Yes | No | No | Yes (safe) |
| 2. Create PR | No | Yes | Cleaned up | No |
| 3. Keep as-is | No | No | Yes | No |
| 4. Discard | No | No | No | Yes (force) |

## Red Flags

**Never:**
- Create a worktree without verifying it is ignored (project-local) — pollutes git status with worktree contents.
- Commit without running tests — breaks bisection and blocks other developers.
- Proceed with failing tests, force-push without request, or skip the typed "discard" confirmation.
- Create a PR without a structured description linking to the feature manifest.

## I/O Contract

| Field | Value |
|---|---|
| **Requires** | Task scope from manifest's `slice_graph` (prototype-driven flow, produced by `harden`) OR `.forge/work/{type}/{name}/tasks.md` (non-prototype fallback, produced by `plan-task-decompose`); work manifest at `.forge/work/{type}/{name}/manifest.yaml` |
| **Produces** | Git worktree, feature branch, atomic commits, pull request(s) on GitHub/GitLab |
| **Feeds into** | `deliver-deploy` (PRs ready to merge and deploy) |
| **Updates manifest** | `branch`, `worktree`, `phase`, PRs created |

## Integration

**Called by:**
- `/feature` command (worktree setup + PR creation)
- `/greenfield` command (worktree setup + PR creation)
- `/bugfix` command (branch + PR)
- `/refactor` command (branch + PR)

**Pairs with:**
- `build-tdd` (commits happen during TDD cycles at Phase 6)
- `quality-code-review` (reviews happen before PR creation)
- `harden` (prototype-driven flow: slice graph determines PR scope)
- `plan-task-decompose` (non-prototype fallback flow: tasks determine PR scope)
- `deliver-deploy` (PRs feed into deployment)
