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:
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>`**
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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:**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user