feat: add parallel issue implementation capability with worktrees

Add complete capability set for orchestrating parallel issue implementation
with automated review cycles using git worktrees.

Components:
- worktrees skill: Git worktree patterns + bundled scripts for reliable operations
- spawn-issues skill: Event-driven orchestrator (Haiku) for parallel workflow
- issue-worker agent: Implements issues autonomously (Sonnet)
- code-reviewer agent: Reviews PRs with quality checks (Haiku, read-only)
- pr-fixer agent: Addresses review feedback automatically (Haiku)

Workflow: /spawn-issues creates worktrees → spawns workers → reviews PRs →
fixes feedback → iterates until approved → cleans up worktrees

Scripts handle error-prone worktree operations. Orchestrator uses event-driven
approach with task notifications for efficient parallel execution.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-01-12 15:51:10 +01:00
parent 6e4ff3af86
commit 03a665503c
8 changed files with 1337 additions and 0 deletions

View File

@@ -0,0 +1,290 @@
---
name: spawn-issues
description: >
Orchestrate parallel issue implementation with automated review cycles. Use when
implementing multiple issues concurrently, or when user says /spawn-issues.
model: haiku
argument-hint: <issue-number> [<issue-number>...]
user-invocable: true
---
# Spawn Issues
@~/.claude/skills/worktrees/SKILL.md
@~/.claude/skills/gitea/SKILL.md
Orchestrate parallel implementation of multiple issues with automated PR review and fixes.
## Arguments
One or more issue numbers: `$ARGUMENTS`
Example: `/spawn-issues 42 43 44`
## Workflow
```
Concurrent Pipeline - each issue flows independently:
Issue #42 ──► worker ──► PR #55 ──► review ──► fix? ──► ✓
Issue #43 ──► worker ──► PR #56 ──► review ──► ✓
Issue #44 ──► worker ──► PR #57 ──► review ──► fix ──► ✓
Event-driven: As each task completes, immediately start next step.
```
## Process
### 1. Parse and Validate
Parse `$ARGUMENTS` into issue numbers. If empty:
```
Usage: /spawn-issues <issue-number> [<issue-number>...]
Example: /spawn-issues 42 43 44
```
### 2. Setup Repository Context
```bash
REPO_PATH=$(pwd)
REPO_NAME=$(basename "$REPO_PATH")
WORKTREES_DIR="${REPO_PATH}/../worktrees"
```
Verify in git repository:
```bash
git rev-parse --git-dir >/dev/null 2>&1 || exit 1
```
### 3. Create All Worktrees Upfront
For each issue, create worktree using script:
```bash
cd "$REPO_PATH"
worktree_path=$(./scripts/create-worktree.sh issue <ISSUE_NUMBER>)
```
Track worktree paths:
```javascript
issues = {
42: {
worktree: "/path/to/worktrees/repo-issue-42",
stage: "ready",
task_id: null,
pr: null,
branch: null,
review_iterations: 0
},
...
}
```
Print initial status:
```
Created worktrees for 3 issues:
[#42] ready
[#43] ready
[#44] ready
```
### 4. Spawn All Issue Workers
For each issue, spawn issue-worker agent in background:
```
Task tool with:
- subagent_type: "issue-worker"
- run_in_background: true
- prompt: "Implement issue #<NUMBER>
Repository: <REPO_PATH>
Repository name: <REPO_NAME>
Issue number: <NUMBER>
Worktree: <WORKTREE_PATH>
Follow the issue-worker agent instructions to implement, commit, push, and create PR.
Output the result in ISSUE_WORKER_RESULT format."
```
Track task_id for each issue and update stage to "implementing".
Print status:
```
[#42] implementing...
[#43] implementing...
[#44] implementing...
```
### 5. Event-Driven Pipeline
**Wait for `<task-notification>` messages** that arrive automatically when background tasks complete.
When notification arrives:
1. **Identify which issue/task completed:**
- Extract task_id from notification
- Look up which issue this belongs to
2. **Read task output:**
```
TaskOutput tool with task_id
```
3. **Parse result and update state:**
- If issue-worker: extract PR number, branch, status
- If code-reviewer: extract verdict (approved/needs-work)
- If pr-fixer: extract status
4. **Print status update:**
```
[#42] Worker completed → PR #55 created, starting review
[#43] Review: approved ✓
[#42] Review: needs work → spawning fixer
```
5. **Spawn next agent if needed:**
- Worker done → spawn code-reviewer
- Reviewer says "needs-work" → spawn pr-fixer
- Fixer done → spawn code-reviewer again
- Reviewer says "approved" → mark complete
6. **Check if all done:**
- If all issues in terminal state → proceed to cleanup
### 6. State Transitions
```
ready → implementing → reviewing → done
→ needs-work → fixing → reviewing...
→ (3 iterations) → needs-manual-review
→ failed → done
```
**Terminal states:** done, failed, needs-manual-review
### 7. Spawning Code Reviewer
When worker completes successfully:
**Get PR branch name from worker result:**
```javascript
branch_name = worker_result.branch
```
**Create review worktree:**
```bash
cd "$REPO_PATH"
review_worktree=$(./scripts/create-worktree.sh review <PR_NUMBER> <BRANCH_NAME>)
```
**Spawn code-reviewer agent:**
```
Task tool with:
- subagent_type: "code-reviewer"
- run_in_background: true
- prompt: "Review PR #<PR_NUMBER>
Repository: <REPO_PATH>
PR number: <PR_NUMBER>
Worktree: <REVIEW_WORKTREE>
Follow the code-reviewer agent instructions to review the PR.
Output the result in REVIEW_RESULT format."
```
Update state: stage = "reviewing"
### 8. Spawning PR Fixer
When reviewer says "needs-work":
**Check iteration count:**
- If review_iterations >= 3: mark as "needs-manual-review", skip fixer
- Otherwise: increment review_iterations and spawn fixer
**Use existing issue worktree** (don't create new one):
```javascript
worktree_path = issues[issue_number].worktree
```
**Spawn pr-fixer agent:**
```
Task tool with:
- subagent_type: "pr-fixer"
- run_in_background: true
- prompt: "Fix review feedback for PR #<PR_NUMBER>
Repository: <REPO_PATH>
PR number: <PR_NUMBER>
Worktree: <WORKTREE_PATH>
Follow the pr-fixer agent instructions to address feedback.
Output the result in PR_FIXER_RESULT format."
```
Update state: stage = "fixing"
### 9. Cleanup Worktrees
After all issues reach terminal state:
```bash
cd "$REPO_PATH"
./scripts/cleanup-worktrees.sh "$WORKTREES_DIR"
```
This removes all issue and review worktrees created during this run.
### 10. Final Report
Print summary table:
```
All done!
| Issue | PR | Status |
|-------|-----|---------------------|
| #42 | #55 | approved |
| #43 | #56 | approved |
| #44 | #57 | needs-manual-review |
2 approved, 1 needs manual review
```
## Guidelines
**Event-driven execution:**
- Wait for task-notification messages
- Don't poll or check task status manually
- Process notifications as they arrive
- Pipeline each issue independently
**Worktree management:**
- Create all issue worktrees at start
- Create review worktrees on demand
- Reuse issue worktrees for pr-fixer
- Clean up all worktrees at end
**State tracking:**
- Track stage, task_id, PR, branch for each issue
- Update state when notifications arrive
- Print status after each transition
**Error handling:**
- If worker fails: mark as "failed", continue with others
- If reviewer fails: mark as "review-failed", continue
- If 3 review iterations: mark as "needs-manual-review"
- Always cleanup worktrees, even on error
**Review iteration limit:**
- Maximum 3 review/fix cycles per issue
- After 3 iterations: requires manual intervention
- Prevents infinite review loops
## Tips
- Use `cd "$REPO_PATH"` before git/worktree operations
- Scripts are in `~/.claude/skills/worktrees/scripts/`
- Agents output structured results for parsing
- Event notifications include task_id
- Print status frequently to show progress

229
skills/worktrees/SKILL.md Normal file
View File

@@ -0,0 +1,229 @@
---
name: worktrees
description: >
Git worktree patterns for parallel development workflows. Use when managing
multiple concurrent branches, implementing issues in parallel, or isolating
work contexts.
user-invocable: false
---
# Git Worktrees
Patterns and scripts for managing git worktrees in parallel development workflows.
## What are Worktrees?
Git worktrees allow multiple working directories from a single repository. Each worktree can have a different branch checked out, enabling true parallel development.
**Use cases:**
- Implementing multiple issues simultaneously
- Isolated review environments for PRs
- Switching contexts without stashing
## Naming Conventions
**Directory structure:**
```
project/
├── .git/ # Main repo
├── src/ # Main working tree
└── ../worktrees/ # Sibling worktrees directory
├── project-issue-42/ # Issue implementation
├── project-issue-43/ # Another issue
└── project-review-55/ # PR review
```
**Naming patterns:**
- Issue work: `${REPO_NAME}-issue-${ISSUE_NUMBER}`
- PR review: `${REPO_NAME}-review-${PR_NUMBER}`
- Feature work: `${REPO_NAME}-feature-${FEATURE_NAME}`
**Why sibling directory:**
- Keeps main repo clean
- Easy to identify worktrees
- Simple bulk operations
- Works with tooling that scans parent directories
## Creating Worktrees
### For Issue Implementation
```bash
REPO_PATH=$(pwd)
REPO_NAME=$(basename "$REPO_PATH")
WORKTREES_DIR="${REPO_PATH}/../worktrees"
ISSUE_NUMBER=42
# Create worktrees directory
mkdir -p "$WORKTREES_DIR"
# Fetch latest
git fetch origin
# Get issue title for branch name
ISSUE_TITLE=$(tea issues $ISSUE_NUMBER | grep -i "title" | head -1 | cut -d: -f2- | xargs)
BRANCH_NAME="issue-${ISSUE_NUMBER}-$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd '[:alnum:]-' | cut -c1-50)"
# Create worktree with new branch from main
git worktree add "${WORKTREES_DIR}/${REPO_NAME}-issue-${ISSUE_NUMBER}" \
-b "$BRANCH_NAME" origin/main
```
### For PR Review
```bash
# For reviewing existing PR branch
PR_NUMBER=55
BRANCH_NAME="issue-42-feature-name" # Get from PR details
git fetch origin
git worktree add "${WORKTREES_DIR}/${REPO_NAME}-review-${PR_NUMBER}" \
"origin/${BRANCH_NAME}"
```
## Bundled Scripts
Use bundled scripts for error-prone operations:
### Create Worktree
```bash
# Usage: ./scripts/create-worktree.sh issue <issue-number>
# Usage: ./scripts/create-worktree.sh review <pr-number> <branch-name>
./scripts/create-worktree.sh issue 42
./scripts/create-worktree.sh review 55 issue-42-feature-name
```
Returns worktree path on success.
### List Worktrees
```bash
./scripts/list-worktrees.sh
```
Shows all active worktrees with their branches.
### Cleanup Worktrees
```bash
# Remove specific worktree
./scripts/cleanup-worktrees.sh "${WORKTREES_DIR}/${REPO_NAME}-issue-42"
# Remove all worktrees in directory
./scripts/cleanup-worktrees.sh "${WORKTREES_DIR}"
# Force remove even if dirty
./scripts/cleanup-worktrees.sh --force "${WORKTREES_DIR}"
```
## Patterns
### Pattern: Parallel Issue Implementation
**Orchestrator creates all worktrees upfront:**
```bash
for issue in 42 43 44; do
worktree_path=$(./scripts/create-worktree.sh issue $issue)
# Spawn worker with worktree_path
done
```
**Worker uses provided worktree:**
```bash
cd "$WORKTREE_PATH" # Provided by orchestrator
# Do work
git add -A && git commit -m "..."
git push -u origin $(git branch --show-current)
```
**Orchestrator cleans up after all complete:**
```bash
./scripts/cleanup-worktrees.sh "${WORKTREES_DIR}"
```
### Pattern: Review in Isolation
**Create review worktree:**
```bash
worktree_path=$(./scripts/create-worktree.sh review $PR_NUMBER $BRANCH_NAME)
cd "$worktree_path"
git diff origin/main...HEAD # Review changes
```
### Pattern: Error Recovery
**List stale worktrees:**
```bash
./scripts/list-worktrees.sh
```
**Force cleanup:**
```bash
./scripts/cleanup-worktrees.sh --force "${WORKTREES_DIR}"
```
## Best Practices
**Always provide worktree paths to agents:**
- Orchestrator creates worktrees
- Agents receive path as parameter
- Agents work in provided path
- Orchestrator handles cleanup
**Never nest cleanup:**
- Only orchestrator cleans up
- Agents never remove their own worktree
- Cleanup happens after all work complete
**Track worktree paths:**
```bash
# In orchestrator
declare -A worktrees
worktrees[42]=$(./scripts/create-worktree.sh issue 42)
worktrees[43]=$(./scripts/create-worktree.sh issue 43)
# Pass to agents
spawn_agent --worktree="${worktrees[42]}"
```
**Handle errors gracefully:**
- Use scripts (they handle errors)
- Always cleanup, even on failure
- Force-remove if necessary
## Common Issues
**Worktree already exists:**
```bash
# Remove old worktree first
./scripts/cleanup-worktrees.sh "${WORKTREES_DIR}/${REPO_NAME}-issue-42"
# Then create new one
./scripts/create-worktree.sh issue 42
```
**Branch already exists:**
```bash
# Delete branch if safe
git branch -d issue-42-old-name
# Or force delete
git branch -D issue-42-old-name
```
**Stale worktrees after crash:**
```bash
# List and force remove
./scripts/list-worktrees.sh
./scripts/cleanup-worktrees.sh --force "${WORKTREES_DIR}"
```
## Tips
- Keep worktrees short-lived (hours, not days)
- Clean up regularly to avoid clutter
- Use scripts for reliability
- Let orchestrator manage lifecycle
- Check `git worktree list` if unsure about state

View File

@@ -0,0 +1,56 @@
#!/bin/bash
set -euo pipefail
# Clean up git worktrees
#
# Usage:
# ./cleanup-worktrees.sh <path> # Remove specific worktree
# ./cleanup-worktrees.sh <directory> # Remove all worktrees in directory
# ./cleanup-worktrees.sh --force <path> # Force remove even if dirty
FORCE=false
if [ "$1" = "--force" ]; then
FORCE=true
shift
fi
TARGET="$1"
REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
cd "$REPO_PATH"
remove_worktree() {
local worktree_path="$1"
if [ ! -d "$worktree_path" ]; then
return 0
fi
if [ "$FORCE" = true ]; then
git worktree remove "$worktree_path" --force 2>/dev/null || true
else
git worktree remove "$worktree_path" 2>/dev/null || true
fi
}
# Check if target is a directory containing multiple worktrees
if [ -d "$TARGET" ]; then
# Check if it's a worktree itself or a directory of worktrees
if git worktree list | grep -q "$TARGET\$"; then
# It's a single worktree
remove_worktree "$TARGET"
else
# It's a directory, remove all worktrees inside
for worktree in "$TARGET"/*; do
if [ -d "$worktree" ]; then
remove_worktree "$worktree"
fi
done
# Try to remove the directory if empty
rmdir "$TARGET" 2>/dev/null || true
fi
else
echo "Error: Path does not exist: $TARGET" >&2
exit 1
fi

View File

@@ -0,0 +1,74 @@
#!/bin/bash
set -euo pipefail
# Create a git worktree for issue work or PR review
#
# Usage:
# ./create-worktree.sh issue <issue-number>
# ./create-worktree.sh review <pr-number> <branch-name>
#
# Returns: Absolute path to created worktree (stdout)
MODE="$1"
REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
REPO_NAME=$(basename "$REPO_PATH")
WORKTREES_DIR="${REPO_PATH}/../worktrees"
# Ensure worktrees directory exists
mkdir -p "$WORKTREES_DIR"
# Fetch latest from origin
cd "$REPO_PATH"
git fetch origin >/dev/null 2>&1
case "$MODE" in
issue)
ISSUE_NUMBER="$2"
WORKTREE_NAME="${REPO_NAME}-issue-${ISSUE_NUMBER}"
WORKTREE_PATH="${WORKTREES_DIR}/${WORKTREE_NAME}"
# Get issue title for branch name
ISSUE_TITLE=$(tea issues "$ISSUE_NUMBER" 2>/dev/null | grep -i "title" | head -1 | cut -d: -f2- | xargs || echo "untitled")
# Create safe branch name
BRANCH_NAME="issue-${ISSUE_NUMBER}-$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd '[:alnum:]-' | cut -c1-50)"
# Remove worktree if it already exists
if [ -d "$WORKTREE_PATH" ]; then
git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || true
fi
# Delete branch if it exists
git branch -D "$BRANCH_NAME" 2>/dev/null || true
# Create worktree with new branch from main
git worktree add "$WORKTREE_PATH" -b "$BRANCH_NAME" origin/main >/dev/null 2>&1
echo "$WORKTREE_PATH"
;;
review)
PR_NUMBER="$2"
BRANCH_NAME="$3"
WORKTREE_NAME="${REPO_NAME}-review-${PR_NUMBER}"
WORKTREE_PATH="${WORKTREES_DIR}/${WORKTREE_NAME}"
# Remove worktree if it already exists
if [ -d "$WORKTREE_PATH" ]; then
git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || true
fi
# Create worktree from existing branch
git worktree add "$WORKTREE_PATH" "origin/${BRANCH_NAME}" >/dev/null 2>&1
echo "$WORKTREE_PATH"
;;
*)
echo "Error: Invalid mode '$MODE'. Use 'issue' or 'review'" >&2
echo "Usage:" >&2
echo " $0 issue <issue-number>" >&2
echo " $0 review <pr-number> <branch-name>" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,13 @@
#!/bin/bash
set -euo pipefail
# List all active git worktrees
#
# Usage:
# ./list-worktrees.sh
REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
cd "$REPO_PATH"
echo "Active worktrees:"
git worktree list