refactor: remove dead code, improve execute-phase UX, fix requirements flow

- Remove phantom status.md command (background agent model abandoned)
- Remove agent-history.md template (unused)
- Remove _archive/ directory
- Add narration to execute-phase (describe what's being built before/after waves)
- Update new-project to offer define-requirements as fast path
- Make define-requirements work without research (gather through questioning)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson
2026-01-15 01:04:41 -06:00
parent 73083db966
commit bd4bd9db53
8 changed files with 153 additions and 1209 deletions

View File

@@ -340,7 +340,6 @@ You're never locked in. The system adapts.
| `/gsd:plan-phase [N]` | Generate task plans for phase |
| `/gsd:execute-plan` | Run single plan via subagent |
| `/gsd:execute-phase <N>` | Execute all plans in phase N with parallel agents |
| `/gsd:status [--wait]` | Check background agent status from parallel execution |
| `/gsd:progress` | Where am I? What's next? |
| `/gsd:verify-work [N]` | User acceptance test of phase or plan ¹ |
| `/gsd:plan-fix [plan]` | Plan fixes for UAT issues from verify-work |

View File

@@ -10,14 +10,13 @@ allowed-tools:
---
<objective>
Define concrete, checkable requirements from research findings.
Define concrete, checkable requirements for v1.
Research answers "what do products like this have?"
Requirements answers "what are WE building?"
Two modes:
1. **With research** — Transform FEATURES.md into scoped requirements
2. **Without research** — Gather requirements through questioning
Transforms research features into scoped v1/v2 requirements that roadmap phases map to.
Run after `/gsd:research-project`, before `/gsd:create-roadmap`.
Run before `/gsd:create-roadmap`.
Output: `.planning/REQUIREMENTS.md`
</objective>
@@ -30,8 +29,8 @@ Output: `.planning/REQUIREMENTS.md`
<context>
@.planning/PROJECT.md
@.planning/research/FEATURES.md (required)
@.planning/research/SUMMARY.md
@.planning/research/FEATURES.md (if exists)
@.planning/research/SUMMARY.md (if exists)
</context>
<process>
@@ -41,8 +40,8 @@ Output: `.planning/REQUIREMENTS.md`
# Verify project exists
[ -f .planning/PROJECT.md ] || { echo "ERROR: No PROJECT.md found. Run /gsd:new-project first."; exit 1; }
# Verify research exists
[ -f .planning/research/FEATURES.md ] || { echo "ERROR: No research found. Run /gsd:research-project first."; exit 1; }
# Check for research
[ -f .planning/research/FEATURES.md ] && echo "HAS_RESEARCH" || echo "NO_RESEARCH"
# Check if requirements already exist
[ -f .planning/REQUIREMENTS.md ] && echo "REQUIREMENTS_EXISTS" || echo "NO_REQUIREMENTS"
@@ -66,12 +65,24 @@ If "Replace": Continue with workflow
</step>
<step name="execute">
**If HAS_RESEARCH:**
Follow the define-requirements.md workflow:
- Load research features
- Load research features from FEATURES.md
- Present features by category
- Ask user to scope each category (v1 / v2 / out of scope)
- Capture any additions research missed
- Generate REQUIREMENTS.md with checkable list
**If NO_RESEARCH:**
Gather requirements through questioning:
- Read PROJECT.md for core value and context
- Ask: "What are the main things users need to be able to do?"
- For each capability mentioned, probe for specifics
- Group into categories (Authentication, Content, etc.)
- For each category, ask what's v1 vs v2 vs out of scope
- Generate REQUIREMENTS.md with checkable list
Same output format either way — the difference is source (research vs conversation).
</step>
<step name="done">
@@ -101,8 +112,7 @@ Requirements defined:
<success_criteria>
- [ ] PROJECT.md validated
- [ ] Research FEATURES.md loaded
- [ ] Features presented by category
- [ ] Features gathered (from research OR questioning)
- [ ] User scoped each category (v1/v2/out of scope)
- [ ] User had opportunity to add missing requirements
- [ ] REQUIREMENTS.md created with checkable list

View File

@@ -144,15 +144,6 @@ Options (via `.planning/config.json` parallelization section):
- `skip_checkpoints`: Skip human checkpoints in background (default: true)
- `min_plans_for_parallel`: Minimum plans to trigger parallelization (default: 2)
**`/gsd:status [--wait]`**
Check status of background agents from parallel execution.
- Shows running/completed agents from agent-history.json
- Uses TaskOutput to poll agent status
- With `--wait`: blocks until all agents complete
Usage: `/gsd:status` or `/gsd:status --wait`
### Roadmap Management
**`/gsd:add-phase <description>`**

View File

@@ -300,15 +300,15 @@ Project initialized:
Choose your path:
**Option A: Research first** (recommended for new domains)
Research the ecosystem before creating roadmap. Discovers standard stacks, expected features, architecture patterns, and common pitfalls.
**Option A: Research first** (recommended)
Research ecosystem → define requirements → create roadmap. Discovers standard stacks, expected features, architecture patterns.
`/gsd:research-project`
**Option B: Create roadmap directly** (for familiar domains)
Skip research if you know this domain well or have a clear spec.
**Option B: Define requirements directly** (familiar domains)
Skip research, define requirements from what you know, then create roadmap.
`/gsd:create-roadmap`
`/gsd:define-requirements`
<sub>`/clear` first → fresh context window</sub>

View File

@@ -1,263 +0,0 @@
# Agent History Template
Template for `.planning/agent-history.json` - tracks subagent spawns during plan execution for resume capability.
---
## File Template
```json
{
"version": "1.2",
"max_entries": 50,
"entries": []
}
```
## Entry Schema
Each entry tracks a subagent spawn or status change:
```json
{
"agent_id": "agent_01HXXXX...",
"task_description": "Execute tasks 1-3 from plan 02-01",
"phase": "02",
"plan": "01",
"segment": 1,
"timestamp": "2026-01-15T14:22:10Z",
"status": "spawned",
"completion_timestamp": null,
"execution_mode": "sequential",
"parallel_group": null,
"granularity": "plan",
"depends_on": null,
"files_modified": null,
"checkpoints_skipped": null,
"task_results": null
}
```
### Field Definitions
| Field | Type | Description |
|-------|------|-------------|
| agent_id | string | Unique ID returned by Task tool |
| task_description | string | Brief description of what agent is executing |
| phase | string | Phase number (e.g., "02", "02.1") |
| plan | string | Plan number within phase |
| segment | number/null | Segment number for segmented plans, null for full plan |
| timestamp | string | ISO 8601 timestamp when agent was spawned |
| status | string | spawned, completed, interrupted, resumed, queued, failed |
| completion_timestamp | string/null | ISO timestamp when completed |
| execution_mode | string | "sequential" or "parallel" |
| parallel_group | string/null | Batch ID linking agents in same parallel execution |
| granularity | string | "plan" or "task_group" |
| depends_on | array/null | Agent IDs or plan refs this depends on |
| files_modified | array/null | Files this agent created/modified |
| checkpoints_skipped | number/null | Count of checkpoints skipped in background |
| task_results | object/null | Per-task outcomes for task-level parallelization |
### Status Lifecycle
```
queued ──> spawned ──────────────────> completed
│ ^
│ │
├──> interrupted ──> resumed┘
│
└──> failed
```
- **queued**: Waiting for dependency (parallel execution only)
- **spawned**: Agent created via Task tool, execution in progress
- **completed**: Agent finished successfully, results received
- **interrupted**: Session ended before agent completed (detected on resume)
- **resumed**: Previously interrupted agent resumed via resume parameter
- **failed**: Agent execution failed (error during execution)
## Usage
### When to Create File
Create `.planning/agent-history.json` from this template when:
- First subagent spawn in execute-plan workflow
- File doesn't exist yet
### When to Add Entry
Add new entry immediately after Task tool returns with agent_id:
```
1. Task tool spawns subagent
2. Response includes agent_id
3. Write agent_id to .planning/current-agent-id.txt
4. Append entry to agent-history.json with status "spawned"
```
### When to Update Entry
Update existing entry when:
**On successful completion:**
```json
{
"status": "completed",
"completion_timestamp": "2026-01-15T14:45:33Z"
}
```
**On resume detection (interrupted agent found):**
```json
{
"status": "interrupted"
}
```
Then add new entry with resumed status:
```json
{
"agent_id": "agent_01HXXXX...",
"status": "resumed",
"timestamp": "2026-01-15T15:00:00Z"
}
```
### Entry Retention
- Keep maximum 50 entries (configurable via max_entries)
- On exceeding limit, remove oldest completed entries first
- Never remove entries with status "spawned" (may need resume)
- Prune during init_agent_tracking step
## Example Entries
### Sequential Execution (Default)
```json
{
"agent_id": "agent_01HXY123ABC",
"task_description": "Execute full plan 02-01 (autonomous)",
"phase": "02",
"plan": "01",
"segment": null,
"timestamp": "2026-01-15T14:22:10Z",
"status": "completed",
"completion_timestamp": "2026-01-15T14:45:33Z",
"execution_mode": "sequential",
"parallel_group": null,
"granularity": "plan",
"depends_on": null,
"files_modified": ["src/api/auth.ts", "src/types/user.ts"],
"checkpoints_skipped": null,
"task_results": null
}
```
### Parallel Execution (Plan-Level)
Independent plans in a phase running in parallel:
```json
{
"agent_id": "agent_01HXYZ123",
"task_description": "Execute plan 05-01 (parallel)",
"phase": "05",
"plan": "01",
"segment": null,
"timestamp": "2026-01-12T10:00:00Z",
"status": "completed",
"completion_timestamp": "2026-01-12T10:15:00Z",
"execution_mode": "parallel",
"parallel_group": "phase-05-batch-1736676000",
"granularity": "plan",
"depends_on": null,
"files_modified": ["src/auth/login.ts", "src/auth/types.ts"],
"checkpoints_skipped": 1,
"task_results": null
}
```
### Queued with Dependency
Agent waiting for another to complete:
```json
{
"agent_id": "agent_01HXYZ456",
"task_description": "Execute plan 05-03 (depends on 05-01)",
"phase": "05",
"plan": "03",
"segment": null,
"timestamp": "2026-01-12T10:15:00Z",
"status": "spawned",
"completion_timestamp": null,
"execution_mode": "parallel",
"parallel_group": "phase-05-batch-1736676000",
"granularity": "plan",
"depends_on": ["agent_01HXYZ123"],
"files_modified": null,
"checkpoints_skipped": null,
"task_results": null
}
```
### Parallel Group Format
- **Plan-level parallel:** `phase-{phase}-batch-{timestamp}`
- **Task-level parallel:** `plan-{phase}-{plan}-tasks-batch-{timestamp}`
Example: `phase-05-batch-1736676000` groups all agents executing Phase 5 plans in parallel.
## Parallel Execution Resume
When a session is interrupted during parallel execution:
### Detection
Check for entries with `status: "spawned"` and `parallel_group` set. These are agents that were running when session ended.
```bash
# Find interrupted parallel agents
jq '.entries[] | select(.status == "spawned" and .parallel_group != null)' .planning/agent-history.json
```
### Resume Options
1. **Resume batch:** Resume all interrupted agents in the parallel group
2. **Resume single:** Resume a specific agent by ID
3. **Start fresh:** Abandon interrupted batch, start new execution
### Resume Command
`/gsd:resume-task` accepts:
- No argument: Resume most recent interrupted agent
- Agent ID: Resume specific agent
- `--batch`: Resume entire parallel group
### Conflict Detection
Before resuming, check for file modifications since spawn:
```bash
git diff --name-only ${SPAWN_COMMIT}..HEAD
```
If files modified by another agent conflict with files this agent modifies, warn user before proceeding. This prevents overwriting work done by other parallel agents that completed after the interruption.
## Related Files
- `.planning/current-agent-id.txt`: Single line with currently active agent ID (for quick resume lookup)
- `.planning/STATE.md`: Project state including session continuity info
---
## Template Notes
**When to create:** First subagent spawn during execute-plan workflow.
**Location:** `.planning/agent-history.json`
**Companion file:** `.planning/current-agent-id.txt` (single agent ID, overwritten on each spawn)
**Purpose:** Enable resume capability for interrupted subagent executions via Task tool's resume parameter.

View File

@@ -1,898 +0,0 @@
<purpose>
Execute all plans in a phase with intelligent parallelization.
Analyzes plan dependencies to identify independent plans that can run in parallel.
**Critical constraint:** One subagent per plan, always. This is for context isolation, not parallelization. Even strictly sequential plans spawn separate subagents so each starts with fresh 200k context at 0%. Quality degrades above 50% context - executing multiple plans in one subagent defeats the entire segmentation model.
</purpose>
<when_to_use>
Use /gsd:execute-phase when:
- Phase has multiple unexecuted plans (2+)
- Want "walk away, come back to completed work" execution
- Plans have clear dependency boundaries
Use /gsd:execute-plan when:
- Executing a single specific plan
- Want sequential, interactive execution
- Need checkpoint interactions
</when_to_use>
<required_reading>
Read STATE.md before any operation to load project context.
</required_reading>
<process>
<step name="load_project_state" priority="first">
Before any operation, read project state:
```bash
cat .planning/STATE.md 2>/dev/null
```
**If file exists:** Parse and internalize:
- Current position (phase, plan, status)
- Accumulated decisions (constraints on this execution)
- Blockers/concerns (things to watch for)
**If file missing but .planning/ exists:**
```
STATE.md missing but planning artifacts exist.
Options:
1. Reconstruct from existing artifacts
2. Continue without project state (may lose accumulated context)
```
**If .planning/ doesn't exist:** Error - project not initialized.
</step>
<step name="identify_phase">
**Identify the phase to execute from argument or roadmap.**
**1. Parse phase argument:**
```bash
# From command argument: /gsd:execute-phase 10
# Or: /gsd:execute-phase .planning/phases/10-parallel-execution/
PHASE_ARG="$1"
```
**2. Find phase directory:**
```bash
# If numeric: find matching directory
if [[ "$PHASE_ARG" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
PHASE_DIR=$(ls -d .planning/phases/${PHASE_ARG}-* 2>/dev/null | head -1)
else
PHASE_DIR="$PHASE_ARG"
fi
# Verify exists
if [ ! -d "$PHASE_DIR" ]; then
echo "Error: Phase directory not found: $PHASE_DIR"
exit 1
fi
```
**3. List all PLAN.md files:**
```bash
PLANS=($(ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null | sort))
echo "Found ${#PLANS[@]} plans in phase"
```
**4. Identify unexecuted plans:**
```bash
UNEXECUTED=()
for plan in "${PLANS[@]}"; do
summary="${plan//-PLAN.md/-SUMMARY.md}"
if [ ! -f "$summary" ]; then
UNEXECUTED+=("$plan")
fi
done
echo "Unexecuted: ${#UNEXECUTED[@]} plans"
```
**5. Check if parallelization is appropriate:**
| Condition | Action |
|-----------|--------|
| 0 unexecuted plans | "All plans complete. Nothing to execute." |
| 1 unexecuted plan | "Single plan - use /gsd:execute-plan instead" |
| 2+ unexecuted plans | Proceed to dependency analysis |
</step>
<step name="analyze_plan_dependencies">
**Analyze plan dependencies to determine parallelization.**
**1. Find all unexecuted plans:**
```bash
UNEXECUTED=()
for plan in .planning/phases/${PHASE}-*/*-PLAN.md; do
summary="${plan//-PLAN.md/-SUMMARY.md}"
[ ! -f "$summary" ] && UNEXECUTED+=("$plan")
done
echo "Found ${#UNEXECUTED[@]} unexecuted plans"
```
**2. For each plan, extract dependency info:**
```bash
# Initialize associative arrays for tracking
declare -A PLAN_REQUIRES # plan -> required plans (from depends_on or inferred)
declare -A PLAN_FILES # plan -> files modified
declare -A PLAN_CHECKPOINTS # plan -> has checkpoints
for plan in "${UNEXECUTED[@]}"; do
plan_id=$(basename "$plan" -PLAN.md)
# Check for depends_on frontmatter
DEPENDS_ON=$(awk '/^---$/,/^---$/' "$plan" | grep "^depends_on:" | sed 's/depends_on: \[//' | sed 's/\]//' | tr -d ' "')
# Check for files_modified frontmatter
FILES_MODIFIED=$(awk '/^---$/,/^---$/' "$plan" | grep "^files_modified:" | sed 's/files_modified: \[//' | sed 's/\]//' | tr -d ' "')
# Use frontmatter if present
if [ -n "$DEPENDS_ON" ]; then
PLAN_REQUIRES["$plan_id"]="$DEPENDS_ON"
else
# Fall back to inference from old frontmatter format
REQUIRES=$(awk '/^---$/,/^---$/' "$plan" | grep -E "^\s*-\s*phase:" | grep -oP '\d+' | tr '\n' ',')
PLAN_REQUIRES["$plan_id"]="${REQUIRES%,}"
# Check for SUMMARY references in @context (implies dependency)
SUMMARY_REFS=$(grep -oP '@[^@]*\d+-\d+-SUMMARY\.md' "$plan" | grep -oP '\d+-\d+' | tr '\n' ',')
if [ -n "$SUMMARY_REFS" ]; then
PLAN_REQUIRES["$plan_id"]="${PLAN_REQUIRES[$plan_id]},${SUMMARY_REFS%,}"
fi
fi
# Use files_modified frontmatter if present, else extract from <files> elements
if [ -n "$FILES_MODIFIED" ]; then
PLAN_FILES["$plan_id"]="$FILES_MODIFIED"
else
FILES=$(grep -oP '(?<=<files>)[^<]+(?=</files>)' "$plan" | tr '\n' ',' | tr -d ' ')
PLAN_FILES["$plan_id"]="${FILES%,}"
fi
# Check for checkpoint tasks
if grep -q 'type="checkpoint' "$plan"; then
PLAN_CHECKPOINTS["$plan_id"]="true"
else
PLAN_CHECKPOINTS["$plan_id"]="false"
fi
done
```
**Dependency detection:**
1. **If `depends_on` frontmatter exists:** Use it directly
2. **If no frontmatter:** Fall back to inference:
- Parse `requires` from old frontmatter format
- Check for SUMMARY references in @context
3. **File conflicts:** Detected separately in step 4
**3. Build dependency graph:**
For each plan, determine:
- `requires`: Prior phases/plans this depends on
- `files_modified`: Files from `<files>` elements
- `has_checkpoints`: Contains checkpoint tasks
```
Example dependency graph:
┌─────────┬───────────────────────┬─────────────────────────────┬──────────────┐
│ Plan │ Requires │ Files Modified │ Checkpoints │
├─────────┼───────────────────────┼─────────────────────────────┼──────────────┤
│ 10-01 │ [] │ [workflows/execute-plan.md] │ false │
│ 10-02 │ [10-01] │ [workflows/execute-phase.md]│ false │
│ 10-03 │ [10-02] │ [commands/execute-phase.md] │ false │
│ 10-04 │ [] │ [templates/agent-history.md]│ false │
└─────────┴───────────────────────┴─────────────────────────────┴──────────────┘
```
**4. Detect file conflicts:**
```bash
# Build file-to-plan mapping
declare -A FILE_TO_PLANS
for plan_id in "${!PLAN_FILES[@]}"; do
IFS=',' read -ra files <<< "${PLAN_FILES[$plan_id]}"
for file in "${files[@]}"; do
[ -n "$file" ] && FILE_TO_PLANS["$file"]="${FILE_TO_PLANS[$file]},$plan_id"
done
done
# Detect conflicts (same file modified by multiple plans)
declare -A CONFLICTS
for file in "${!FILE_TO_PLANS[@]}"; do
plans="${FILE_TO_PLANS[$file]}"
plan_count=$(echo "$plans" | tr ',' '\n' | grep -c .)
if [ "$plan_count" -gt 1 ]; then
CONFLICTS["$file"]="${plans#,}"
fi
done
# Add conflict dependencies (later plan depends on earlier)
for file in "${!CONFLICTS[@]}"; do
IFS=',' read -ra conflict_plans <<< "${CONFLICTS[$file]}"
for ((i=1; i<${#conflict_plans[@]}; i++)); do
# Each plan depends on previous one in conflict set
prev="${conflict_plans[$((i-1))]}"
curr="${conflict_plans[$i]}"
PLAN_REQUIRES["$curr"]="${PLAN_REQUIRES[$curr]},${prev}"
done
done
```
**File conflict rules:**
- If Plan A and Plan B both modify same file → B depends on A (ordered by plan number)
- If Plan B reads file created by Plan A → B depends on A
- If Plan B references Plan A's SUMMARY in @context → B depends on A
**5. Categorize plans:**
| Category | Criteria | Action |
|----------|----------|--------|
| independent | Empty `depends_on` AND no file conflicts | Can run in parallel (Wave 1) |
| dependent | Has `depends_on` OR file conflicts with earlier plan | Wait for dependency |
| has_checkpoints | Contains checkpoint tasks | Foreground or skip checkpoints |
**6. Build execution waves (topological sort):**
```bash
# Calculate wave for each plan
declare -A PLAN_WAVE
calculate_wave() {
local plan="$1"
[ -n "${PLAN_WAVE[$plan]}" ] && echo "${PLAN_WAVE[$plan]}" && return
local max_dep_wave=0
# Check depends_on (from frontmatter or inferred)
if [ -n "${PLAN_REQUIRES[$plan]}" ]; then
IFS=',' read -ra dep_array <<< "${PLAN_REQUIRES[$plan]}"
for dep in "${dep_array[@]}"; do
[ -z "$dep" ] && continue
# Only consider deps in current phase (unexecuted)
if [[ " ${!PLAN_FILES[*]} " =~ " $dep " ]]; then
dep_wave=$(calculate_wave "$dep")
[ "$dep_wave" -gt "$max_dep_wave" ] && max_dep_wave="$dep_wave"
fi
done
fi
PLAN_WAVE[$plan]=$((max_dep_wave + 1))
echo "${PLAN_WAVE[$plan]}"
}
# Calculate waves for all plans
for plan_id in "${!PLAN_FILES[@]}"; do
calculate_wave "$plan_id" > /dev/null
done
# Group by wave
declare -A WAVES
for plan_id in "${!PLAN_WAVE[@]}"; do
wave="${PLAN_WAVE[$plan_id]}"
WAVES[$wave]="${WAVES[$wave]} $plan_id"
done
# Output wave structure
echo "Execution waves:"
for wave in $(echo "${!WAVES[@]}" | tr ' ' '\n' | sort -n); do
plans="${WAVES[$wave]}"
checkpoint_note=""
frontmatter_note=""
for p in $plans; do
[ "${PLAN_CHECKPOINTS[$p]}" = "true" ] && checkpoint_note=" (has checkpoints)"
[ "${PLAN_HAS_FRONTMATTER[$p]}" = "true" ] && frontmatter_note=" [frontmatter]"
done
echo " Wave $wave:$plans$checkpoint_note$frontmatter_note"
done
```
**Example output:**
```
Execution waves:
Wave 1: 10-01 10-04
Wave 2: 10-02
Wave 3: 10-03
```
**7. Handle checkpoints in parallel context:**
Plans with checkpoints require special handling:
- `checkpoint_handling: "foreground"` → Run in main context (not parallel)
- `checkpoint_handling: "skip"` → Skip checkpoints during parallel (not recommended)
```bash
# Separate checkpoint plans
PARALLEL_PLANS=()
FOREGROUND_PLANS=()
for plan_id in "${!PLAN_CHECKPOINTS[@]}"; do
if [ "${PLAN_CHECKPOINTS[$plan_id]}" = "true" ]; then
FOREGROUND_PLANS+=("$plan_id")
else
PARALLEL_PLANS+=("$plan_id")
fi
done
if [ ${#FOREGROUND_PLANS[@]} -gt 0 ]; then
echo "Plans requiring foreground execution: ${FOREGROUND_PLANS[*]}"
fi
```
**8. Safety rule:**
If dependency detection is uncertain (e.g., complex file patterns, unclear requires), default to sequential execution within that wave.
</step>
<step name="parallelization_config">
**Read parallelization configuration.**
```bash
cat .planning/config.json 2>/dev/null
```
**Config schema (parallelization section):**
```json
{
"parallelization": {
"enabled": true,
"max_concurrent_agents": 3,
"checkpoint_handling": "foreground",
"commit_strategy": "orchestrator"
}
}
```
**Config options:**
| Option | Values | Default | Description |
|--------|--------|---------|-------------|
| enabled | true/false | true | Enable parallel execution |
| max_concurrent_agents | 1-5 | 3 | Max simultaneous background agents |
| checkpoint_handling | "foreground"/"skip" | "foreground" | How to handle plans with checkpoints |
| commit_strategy | "orchestrator"/"agent" | "orchestrator" | Who commits changes |
**If parallelization.enabled is false:**
- Fall back to sequential execution
- Use /gsd:execute-plan for each plan in order
**Checkpoint handling modes:**
- `foreground`: Plans with checkpoints run in foreground (not parallel)
- `skip`: Skip checkpoints during parallel execution (not recommended)
**Commit strategy:**
- `orchestrator`: Agents don't commit. Orchestrator collects all changes and commits.
- `agent`: Each agent commits its own changes (may cause conflicts)
</step>
<step name="spawn_parallel_agents">
**Spawn independent plans as parallel background agents.**
**1. Record pre-spawn git state:**
```bash
PRE_SPAWN_COMMIT=$(git rev-parse HEAD)
echo "All agents start from commit: $PRE_SPAWN_COMMIT"
```
**2. Generate parallel group ID:**
```bash
PARALLEL_GROUP="pg-$(date +%Y%m%d%H%M%S)-$(openssl rand -hex 4)"
```
**3. Initialize tracking:**
```bash
# Ensure agent-history.json exists
if [ ! -f .planning/agent-history.json ]; then
echo '{"version":"1.2","max_entries":50,"entries":[]}' > .planning/agent-history.json
fi
# Initialize tracking arrays
declare -a RUNNING_AGENTS=()
declare -a QUEUED_PLANS=()
declare -A AGENT_TO_PLAN=()
```
**4. Spawn Wave 1 plans (no dependencies):**
```
For each plan in Wave 1:
# Check concurrent agent limit
if len(RUNNING_AGENTS) >= max_concurrent_agents:
QUEUED_PLANS.append(plan)
continue
# Use Task tool to spawn background agent
Task(
description="Execute {plan_id} (parallel)",
prompt="[Agent prompt below]",
subagent_type="general-purpose",
run_in_background=true
)
# After Task returns, capture agent_id
RUNNING_AGENTS.append(agent_id)
AGENT_TO_PLAN[agent_id] = plan_id
# Record to agent-history.json
add_entry_to_history(...)
```
**Agent spawn prompt (for plans WITHOUT checkpoints):**
```xml
<parallel_agent_instructions>
You are executing plan: {plan_path} as part of a PARALLEL phase execution.
<critical_rules>
1. Execute ALL tasks in the plan following deviation rules from execute-plan.md
2. Commit each task atomically (standard task_commit protocol)
3. Create SUMMARY.md in the phase directory when complete
4. Report files modified and commit hashes when done
</critical_rules>
<plan_context>
@{plan_path}
Read the plan for full context, tasks, and deviation rules.
</plan_context>
<execution_protocol>
1. Read plan file and context files
2. Execute each task in order
3. For each task:
- Implement the action
- Run verification
- Track files modified
- Track any deviations
4. After all tasks: create SUMMARY.md
</execution_protocol>
<report_format>
When complete, output this exact format:
PARALLEL_AGENT_COMPLETE
plan_id: {phase}-{plan}
tasks_completed: [count]/[total]
task_commits:
- task_1: abc123f
- task_2: def456g
files_modified:
- path/to/file1.ts
- path/to/file2.md
deviations:
- [Rule X] description
summary_path: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
issues: [none or list]
END_REPORT
</report_format>
<forbidden_actions>
- git push (orchestrator may push after all complete)
- Modifying files outside plan scope
- Running long-blocking network operations
</forbidden_actions>
</parallel_agent_instructions>
```
**5. Record spawn in agent-history.json:**
```bash
# Read current entries
ENTRIES=$(jq '.entries' .planning/agent-history.json)
# Create new entry
NEW_ENTRY=$(cat <<EOF
{
"agent_id": "$AGENT_ID",
"task_description": "Parallel: Execute ${PHASE}-${PLAN}-PLAN.md",
"phase": "$PHASE",
"plan": "$PLAN",
"parallel_group": "$PARALLEL_GROUP",
"granularity": "plan",
"wave": $WAVE_NUM,
"depends_on": $(echo "${PLAN_REQUIRES[$PLAN]}" | jq -R 'split(",") | map(select(. != ""))'),
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"status": "spawned",
"files_modified": [],
"completion_timestamp": null,
"deviations": []
}
EOF
)
# Append and write back
echo "$ENTRIES" | jq ". += [$NEW_ENTRY]" > /tmp/entries.json
jq --argjson entries "$(cat /tmp/entries.json)" '.entries = $entries' .planning/agent-history.json > /tmp/history.json
mv /tmp/history.json .planning/agent-history.json
```
**6. Queue remaining plans:**
```bash
# Queue Wave 2+ plans
for wave in $(seq 2 $MAX_WAVE); do
for plan in ${WAVES[$wave]}; do
QUEUED_PLANS+=("$plan:$wave")
done
done
echo "Spawned: ${#RUNNING_AGENTS[@]} agents"
echo "Queued: ${#QUEUED_PLANS[@]} plans"
```
</step>
<step name="monitor_parallel_completion">
**Poll for agent completion and spawn dependents.**
**1. Polling loop implementation:**
```
declare -A COMPLETED_AGENTS=()
declare -A FAILED_AGENTS=()
while [ ${#RUNNING_AGENTS[@]} -gt 0 ] || [ ${#QUEUED_PLANS[@]} -gt 0 ]; do
# Check each running agent
for agent_id in "${RUNNING_AGENTS[@]}"; do
# Use TaskOutput to check status (non-blocking)
TaskOutput(
task_id=agent_id,
block=false,
timeout=5000
)
if result.status == "completed":
# Parse agent's completion report
files_modified = parse_report_files(result.output)
deviations = parse_report_deviations(result.output)
plan_id = AGENT_TO_PLAN[agent_id]
# Update agent-history.json
update_history_entry(
agent_id,
status="completed",
files_modified=files_modified,
deviations=deviations,
completion_timestamp=now()
)
# Track completion
COMPLETED_AGENTS[agent_id] = plan_id
RUNNING_AGENTS.remove(agent_id)
echo "✓ Agent $agent_id completed plan $plan_id"
echo " Files: ${#files_modified[@]}"
echo " Deviations: ${#deviations[@]}"
# Check if dependents can now spawn
check_and_spawn_dependents()
elif result.status == "failed":
plan_id = AGENT_TO_PLAN[agent_id]
# Log failure
update_history_entry(
agent_id,
status="failed",
error=result.error,
completion_timestamp=now()
)
FAILED_AGENTS[agent_id] = plan_id
RUNNING_AGENTS.remove(agent_id)
echo "✗ Agent $agent_id FAILED on plan $plan_id"
echo " Error: ${result.error}"
# Continue monitoring - don't abort batch
# else: still running, check next agent
done
# Brief pause between polls
sleep 10
done
```
**2. Parse agent completion report:**
```bash
parse_report_files() {
local output="$1"
# Extract files from PARALLEL_AGENT_COMPLETE block
echo "$output" | \
sed -n '/^files_modified:/,/^[a-z_]*:/p' | \
grep '^\s*-' | \
sed 's/^\s*-\s*//'
}
parse_report_deviations() {
local output="$1"
echo "$output" | \
sed -n '/^deviations:/,/^[a-z_]*:/p' | \
grep '^\s*-' | \
sed 's/^\s*-\s*//'
}
```
**3. Spawn ready dependents:**
```bash
check_and_spawn_dependents() {
# Get completed plan IDs
local completed_plans=$(printf '%s\n' "${COMPLETED_AGENTS[@]}")
for i in "${!QUEUED_PLANS[@]}"; do
local queued="${QUEUED_PLANS[$i]}"
local plan_id="${queued%%:*}"
local wave="${queued##*:}"
# Get this plan's dependencies
local deps="${PLAN_REQUIRES[$plan_id]}"
# Check if all dependencies are in completed list
local all_deps_met=true
IFS=',' read -ra dep_array <<< "$deps"
for dep in "${dep_array[@]}"; do
[ -z "$dep" ] && continue
if ! echo "$completed_plans" | grep -q "^$dep$"; then
all_deps_met=false
break
fi
done
if [ "$all_deps_met" = true ]; then
# Check concurrent limit
if [ ${#RUNNING_AGENTS[@]} -lt $MAX_CONCURRENT ]; then
# Remove from queue
unset 'QUEUED_PLANS[$i]'
# Spawn agent
spawn_plan_agent "$plan_id" "$wave"
echo "→ Spawned dependent: $plan_id (wave $wave)"
fi
fi
done
# Rebuild array to remove gaps
QUEUED_PLANS=("${QUEUED_PLANS[@]}")
}
```
**4. Handle failures:**
| Failure Type | Action |
|--------------|--------|
| Agent crash | Log status="failed", continue batch |
| Plan error | Same as crash - logged, batch continues |
| All dependents | Plans depending on failed agent also fail |
```bash
# When agent fails, mark its dependents as blocked
mark_dependents_blocked() {
local failed_plan="$1"
for i in "${!QUEUED_PLANS[@]}"; do
local queued="${QUEUED_PLANS[$i]}"
local plan_id="${queued%%:*}"
local deps="${PLAN_REQUIRES[$plan_id]}"
if echo "$deps" | grep -q "$failed_plan"; then
echo "⚠ Plan $plan_id blocked (depends on failed $failed_plan)"
# Mark in history as blocked
update_history_entry("queued-$plan_id", status="blocked", blocked_by="$failed_plan")
fi
done
}
```
**5. Completion conditions:**
```
while true:
if RUNNING_AGENTS is empty AND QUEUED_PLANS is empty:
break # All done
if RUNNING_AGENTS is empty AND QUEUED_PLANS is not empty:
# All queued plans are blocked by failed dependencies
echo "All remaining plans blocked by failures"
break
poll_and_check()
```
**6. Progress display:**
```
During execution, show:
═══════════════════════════════════════════════════
Parallel Execution Status
═══════════════════════════════════════════════════
Running: [agent-1: 10-01] [agent-2: 10-04]
Queued: 10-02, 10-03
Complete: 0
Failed: 0
═══════════════════════════════════════════════════
[Update periodically as agents complete]
```
</step>
<step name="orchestrator_commit">
**Commit metadata after all agents complete.**
Agents commit their own task code (per-task atomic commits). The orchestrator only commits metadata.
**1. Verify all agents committed successfully:**
```bash
# Check git log for expected commits from each agent
for agent in $(jq -r ".entries[] | select(.parallel_group==\"$PARALLEL_GROUP\" and .status==\"completed\") | .agent_id" .planning/agent-history.json); do
PLAN=$(jq -r ".entries[] | select(.agent_id==\"$agent\") | .plan" .planning/agent-history.json)
# Verify commits exist for this plan
git log --oneline --grep="(${PHASE}-${PLAN}):" | head -5
done
```
**2. Stage and commit metadata:**
```bash
# Stage all SUMMARY.md files created by agents
git add .planning/phases/${PHASE_DIR}/*-SUMMARY.md
# Stage STATE.md and ROADMAP.md
git add .planning/STATE.md
git add .planning/ROADMAP.md
# Commit metadata
git commit -m "docs(${PHASE}): complete phase via parallel execution
Plans executed: ${#COMPLETED[@]}
Parallel group: $PARALLEL_GROUP
Agents:
$(for a in "${COMPLETED[@]}"; do echo "- $a"; done)"
```
**3. Generate timing stats:**
```bash
START_TIME=$(jq -r ".entries[] | select(.parallel_group==\"$PARALLEL_GROUP\") | .timestamp" .planning/agent-history.json | sort | head -1)
END_TIME=$(jq -r ".entries[] | select(.parallel_group==\"$PARALLEL_GROUP\") | .completion_timestamp" .planning/agent-history.json | sort -r | head -1)
echo "Parallel execution stats:"
echo "- Plans executed: ${#COMPLETED[@]}"
echo "- Wall clock time: $(time_diff $START_TIME $END_TIME)"
echo "- Sequential estimate: $(sum of individual plan durations)"
echo "- Time saved: ~X%"
```
**Note on merge conflicts:**
Since agents commit independently, git will catch conflicts at commit time if they occur.
The dependency analysis step should prevent this, but if an agent fails to commit due to conflict:
- That agent's status will be "failed"
- Other agents continue normally
- User can resolve and retry the failed plan with /gsd:execute-plan
</step>
<step name="create_phase_summary">
**Aggregate results into phase-level summary.**
After all plans complete, create a phase summary that aggregates:
**1. Collect individual SUMMARY.md files:**
```bash
SUMMARIES=($(ls "$PHASE_DIR"/*-SUMMARY.md | sort))
```
**2. Update STATE.md:**
- Update Current Position
- Add any decisions from individual summaries
- Update session continuity
**3. Update ROADMAP.md:**
- Mark phase as complete
- Add completion date
- Update progress table
**4. Report completion:**
```
═══════════════════════════════════════════════════
Phase {X}: {Phase Name} Complete (Parallel Execution)
═══════════════════════════════════════════════════
Plans executed: {N}
- {phase}-01: [name] - {duration}
- {phase}-02: [name] - {duration}
- {phase}-03: [name] - {duration}
Execution mode: Parallel ({max_concurrent} agents)
Wall clock time: {total_duration}
Estimated sequential time: {sum_of_durations}
Time saved: ~{percent}%
Files modified: {total_count}
Commits created: {commit_count}
```
</step>
<step name="offer_next">
**Present next steps after phase completion.**
Read ROADMAP.md to determine milestone status.
**If more phases remain in milestone:**
```
## ✓ Phase {X}: {Phase Name} Complete
All {N} plans finished via parallel execution.
---
## ▶ Next Up
**Phase {X+1}: {Next Phase Name}** — {Goal from ROADMAP.md}
`/gsd:plan-phase {X+1}`
<sub>`/clear` first → fresh context window</sub>
---
**Also available:**
- `/gsd:verify-work {X}` — manual acceptance testing
- `/gsd:discuss-phase {X+1}` — gather context first
```
**If milestone complete:**
```
🎉 MILESTONE COMPLETE!
All {N} phases finished.
`/gsd:complete-milestone`
```
</step>
</process>
<error_handling>
**Agent failure during parallel execution:**
- Log failure but continue with other agents
- Failed plans can be retried individually with /gsd:execute-plan
- Do not automatically retry (may cause cascade failures)
**Merge conflict detected:**
- Stop orchestrator_commit
- Present conflicting files to user
- Options:
1. Manual resolution
2. Re-run sequential with /gsd:execute-plan
**Max concurrent limit reached:**
- Queue excess plans
- Spawn as agents complete
- First-in-first-out ordering within each wave
**Config.json missing:**
- Use defaults: enabled=true, max_concurrent=3, orchestrator commits
</error_handling>
<success_criteria>
- All plans in phase executed
- All agents completed (no failures)
- Commits created for all plans
- STATE.md updated
- ROADMAP.md updated
- No merge conflicts
</success_criteria>

View File

@@ -1,10 +1,11 @@
<purpose>
Transform research findings into scoped, checkable requirements.
Define concrete, checkable requirements for v1.
Research tells you what products in this domain typically have.
Requirements tell you what YOU are building for v1.
Two modes:
1. **With research** — Transform FEATURES.md into scoped requirements
2. **Without research** — Gather requirements through questioning
This is the bridge between "what's possible" and "what we're committing to."
This is the bridge between "what's possible/wanted" and "what we're committing to."
</purpose>
<required_reading>
@@ -12,13 +13,23 @@ This is the bridge between "what's possible" and "what we're committing to."
1. ~/.claude/get-shit-done/templates/requirements.md
2. .planning/PROJECT.md
3. .planning/research/FEATURES.md
4. .planning/research/SUMMARY.md
3. .planning/research/FEATURES.md (if exists)
4. .planning/research/SUMMARY.md (if exists)
</required_reading>
<process>
<step name="load_context">
<step name="detect_mode">
Check for research:
```bash
[ -f .planning/research/FEATURES.md ] && echo "HAS_RESEARCH" || echo "NO_RESEARCH"
```
**If HAS_RESEARCH:** Follow steps load_context → present_features → scope_categories
**If NO_RESEARCH:** Follow steps load_project → gather_requirements → scope_categories
</step>
<step name="load_context" mode="with_research">
Read PROJECT.md and extract:
- Core value (the ONE thing that must work)
- Stated constraints (budget, timeline, tech limitations)
@@ -37,11 +48,52 @@ Read research/SUMMARY.md for:
- Suggested phase structure (informational only)
</step>
<step name="load_project" mode="without_research">
Read PROJECT.md and extract:
- Core value (the ONE thing that must work)
- Stated constraints (budget, timeline, tech limitations)
- Any explicit scope boundaries from project definition
- Any requirements already mentioned in PROJECT.md
</step>
<step name="gather_requirements" mode="without_research">
Since no research exists, gather requirements through conversation.
**Start with core value:**
```
Based on PROJECT.md, the core value is: "[core value]"
What are the main things users need to be able to do?
```
Wait for response. For each capability mentioned:
- Ask clarifying questions to make it specific
- Probe for related capabilities they might need
- Group naturally emerging categories
**Example flow:**
```
User: "Users need to create and share posts"
You: "For posts, what should users be able to include?
- Text only?
- Images?
- Links with previews?
And for sharing — to a feed, or also direct to other users?"
```
Build up a mental feature list organized by category.
**When you have enough:**
Present gathered features in same format as present_features step, then proceed to scope_categories.
</step>
<step name="present_features">
Present researched features grouped by category:
Present features grouped by category (from research or gathered through questioning):
```
Based on research, here are the features for [domain]:
Here are the features for [domain]:
## Authentication
**Table stakes:**
@@ -267,7 +319,7 @@ Requirements defined:
<success_criteria>
- [ ] PROJECT.md core value extracted
- [ ] Research FEATURES.md loaded and parsed
- [ ] Features gathered (from research OR conversation)
- [ ] All categories presented to user
- [ ] User scoped each category (v1/v2/out of scope)
- [ ] User had opportunity to add requirements

View File

@@ -103,15 +103,21 @@ waves = {
**No dependency analysis needed.** Wave numbers are pre-computed during `/gsd:plan-phase`.
Report wave structure to user:
Report wave structure with context:
```
Execution Plan:
Wave 1 (parallel): 03-01, 03-02
Wave 2 (parallel): 03-03 [checkpoint], 03-04
Wave 3: 03-05
## Execution Plan
**Phase {X}: {Name}** — {total_plans} plans across {wave_count} waves
| Wave | Plans | What it builds |
|------|-------|----------------|
| 1 | 01-01, 01-02 | {from plan objectives} |
| 2 | 01-03 | {from plan objectives} |
| 3 | 01-04 [checkpoint] | {from plan objectives} |
Total: 5 plans in 3 waves
```
The "What it builds" column comes from skimming plan names/objectives. Keep it brief (3-8 words).
</step>
<step name="execute_waves">
@@ -119,7 +125,32 @@ Execute each wave in sequence. Autonomous plans within a wave run in parallel.
**For each wave:**
1. **Spawn all autonomous agents in wave simultaneously:**
1. **Describe what's being built (BEFORE spawning):**
Read each plan's `<objective>` section. Extract what's being built and why it matters.
**Output:**
```
---
## Wave {N}
**{Plan ID}: {Plan Name}**
{2-3 sentences: what this builds, key technical approach, why it matters in context}
**{Plan ID}: {Plan Name}** (if parallel)
{same format}
Spawning {count} agent(s)...
---
```
**Examples:**
- Bad: "Executing terrain generation plan"
- Good: "Procedural terrain generator using Perlin noise — creates height maps, biome zones, and collision meshes. Required before vehicle physics can interact with ground."
2. **Spawn all autonomous agents in wave simultaneously:**
Use Task tool with multiple parallel calls. Each agent gets prompt from subagent-task-prompt template:
@@ -155,12 +186,34 @@ Execute each wave in sequence. Autonomous plans within a wave run in parallel.
Task tool blocks until each agent finishes. All parallel agents return together.
3. **Collect results from wave:**
3. **Report completion and what was built:**
For each completed agent:
- Verify SUMMARY.md exists at expected path
- Note any issues reported
- Record completion
- Read SUMMARY.md to extract what was built
- Note any issues or deviations
**Output:**
```
---
## Wave {N} Complete
**{Plan ID}: {Plan Name}**
{What was built — from SUMMARY.md deliverables}
{Notable deviations or discoveries, if any}
**{Plan ID}: {Plan Name}** (if parallel)
{same format}
{If more waves: brief note on what this enables for next wave}
---
```
**Examples:**
- Bad: "Wave 2 complete. Proceeding to Wave 3."
- Good: "Terrain system complete — 3 biome types, height-based texturing, physics collision meshes. Vehicle physics (Wave 3) can now reference ground surfaces."
4. **Handle failures:**