- spawn_parallel_agents: Task tool with run_in_background, XML agent prompt, agent-history.json tracking with parallel_group, wave queuing - monitor_parallel_completion: TaskOutput polling loop, completion report parsing, check_and_spawn_dependents, failure handling, progress display - orchestrator_commit: merge conflict detection failsafe, per-plan staging, conflict resolution options - Total: 956 lines (within 800-1200 target)
26 KiB
<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>
Before any operation, read project state:cat .planning/STATE.md 2>/dev/null
If file exists: Parse and internalize:
- Current position (phase, plan, status)
- Accumulated decisions (constraints on this execution)
- Deferred issues (context for deviations)
- 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.
**Identify the phase to execute from argument or roadmap.**1. Parse phase argument:
# From command argument: /gsd:execute-phase 10
# Or: /gsd:execute-phase .planning/phases/10-parallel-execution/
PHASE_ARG="$1"
2. Find phase directory:
# 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:
PLANS=($(ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null | sort))
echo "Found ${#PLANS[@]} plans in phase"
4. Identify unexecuted plans:
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 |
1. Find all unexecuted plans:
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:
# Initialize associative arrays for tracking
declare -A PLAN_REQUIRES # plan -> required plans
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)
# Extract frontmatter requires (handles YAML array syntax)
REQUIRES=$(awk '/^---$/,/^---$/' "$plan" | grep -E "^\s*-\s*phase:" | grep -oP '\d+' | tr '\n' ',')
PLAN_REQUIRES["$plan_id"]="${REQUIRES%,}"
# Extract files from <files> elements (all occurrences)
FILES=$(grep -oP '(?<=<files>)[^<]+(?=</files>)' "$plan" | tr '\n' ',' | tr -d ' ')
PLAN_FILES["$plan_id"]="${FILES%,}"
# Check for SUMMARY references in @context
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
# Check for checkpoint tasks
if grep -q 'type="checkpoint' "$plan"; then
PLAN_CHECKPOINTS["$plan_id"]="true"
else
PLAN_CHECKPOINTS["$plan_id"]="false"
fi
done
3. Build dependency graph:
For each plan, determine:
requires: Prior phases/plans this depends onfiles_modified: Files from<files>elementshas_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:
# 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 | No dependencies, no file conflicts | Can run in parallel |
| dependent | Requires another plan | Wait for dependency |
| has_checkpoints | Contains checkpoint tasks | Foreground or skip checkpoints |
6. Build execution waves (topological sort):
# Calculate wave for each plan
declare -A PLAN_WAVE
calculate_wave() {
local plan="$1"
[ -n "${PLAN_WAVE[$plan]}" ] && echo "${PLAN_WAVE[$plan]}" && return
local deps="${PLAN_REQUIRES[$plan]}"
local max_dep_wave=0
if [ -n "$deps" ]; then
IFS=',' read -ra dep_array <<< "$deps"
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=""
for p in $plans; do
[ "${PLAN_CHECKPOINTS[$p]}" = "true" ] && checkpoint_note=" (has checkpoints)"
done
echo " Wave $wave:$plans$checkpoint_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)
# 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.
**Read parallelization configuration.**cat .planning/config.json 2>/dev/null
Config schema (parallelization section):
{
"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)
1. Record pre-spawn git state:
PRE_SPAWN_COMMIT=$(git rev-parse HEAD)
echo "All agents start from commit: $PRE_SPAWN_COMMIT"
2. Generate parallel group ID:
PARALLEL_GROUP="pg-$(date +%Y%m%d%H%M%S)-$(openssl rand -hex 4)"
3. Initialize tracking:
# 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):
<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
2. DO NOT run git commit - orchestrator handles commits
3. DO NOT run git add - orchestrator stages files
4. Track all files you create or modify
5. Create SUMMARY.md in the phase directory when complete
</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]
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 commit
- git add
- git push
- Modifying files outside plan scope
- Running long-blocking network operations
</forbidden_actions>
</parallel_agent_instructions>
5. Record spawn in agent-history.json:
# 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:
# 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"
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:
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:
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 |
# 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]
1. Collect files from all agents:
# Read agent-history.json
# For each agent in this parallel_group:
# Collect files_modified arrays
# Merge into master list
ALL_FILES=()
for entry in $(jq -r ".entries[] | select(.parallel_group==\"$PARALLEL_GROUP\") | .files_modified[]" .planning/agent-history.json); do
ALL_FILES+=("$entry")
done
2. Check for merge conflicts (failsafe):
# Build file-to-agent mapping
declare -A FILE_AGENTS
for entry in $(jq -c ".entries[] | select(.parallel_group==\"$PARALLEL_GROUP\" and .status==\"completed\")" .planning/agent-history.json); do
agent_id=$(echo "$entry" | jq -r '.agent_id')
for file in $(echo "$entry" | jq -r '.files_modified[]'); do
FILE_AGENTS["$file"]="${FILE_AGENTS[$file]} $agent_id"
done
done
# Detect conflicts (file modified by multiple agents)
CONFLICTS=()
for file in "${!FILE_AGENTS[@]}"; do
agents=(${FILE_AGENTS[$file]})
if [ ${#agents[@]} -gt 1 ]; then
CONFLICTS+=("$file: ${agents[*]}")
fi
done
# Handle conflicts
if [ ${#CONFLICTS[@]} -gt 0 ]; then
echo ""
echo "═══════════════════════════════════════════════════"
echo "⚠ MERGE CONFLICT DETECTED"
echo "═══════════════════════════════════════════════════"
echo ""
echo "Multiple agents modified the same files:"
for conflict in "${CONFLICTS[@]}"; do
echo " - $conflict"
done
echo ""
echo "Options:"
echo "1. Review and merge manually"
echo "2. Re-run sequential with /gsd:execute-plan"
echo "3. Accept last-write-wins (risky)"
echo ""
# Present to user
AskUserQuestion(
header="Merge Conflict",
question="How to resolve file conflicts?",
options=[
"Manual review",
"Abort and retry sequential",
"Accept last-write-wins"
]
)
# Handle based on response
if response == "Abort":
git checkout -- . # Discard changes
exit 1
elif response == "Manual review":
echo "Review files and run: git add <resolved-files> && /gsd:execute-phase --resume"
exit 0
fi
Conflict prevention (dependency analysis should catch this): The analyze_plan_dependencies step should detect file conflicts and add dependencies. This step is a failsafe for edge cases where:
- Agents create new files with same name
- File patterns weren't caught during analysis
- Context files are modified unexpectedly
3. Stage and commit per-plan:
# For each completed agent (in execution order):
for agent in $(jq -r ".entries[] | select(.parallel_group==\"$PARALLEL_GROUP\" and .status==\"completed\") | .agent_id" .planning/agent-history.json | sort); do
PLAN=$(jq -r ".entries[] | select(.agent_id==\"$agent\") | .plan" .planning/agent-history.json)
FILES=$(jq -r ".entries[] | select(.agent_id==\"$agent\") | .files_modified[]" .planning/agent-history.json)
# Stage files for this plan
for f in $FILES; do
git add "$f"
done
# Commit with plan context
git commit -m "feat({phase}-{plan}): [plan name from PLAN.md]
- [task 1]
- [task 2]
- [task 3]
Executed by parallel agent: $agent"
done
4. Stage and commit metadata:
# Stage all SUMMARY.md files created
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)"
5. Generate timing stats:
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%"
After all plans complete, create a phase summary that aggregates:
1. Collect individual SUMMARY.md files:
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}
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`
<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:
- Manual resolution
- 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>