feat(skills): add team-roadmap-dev skill with phased execution pipeline

Roadmap-driven development team skill with coordinator/planner/executor/verifier
roles. Features action-planning-agent integration (IMPL-*.json task format),
convergence criteria verification, pause/resume support, and wave-based execution.
This commit is contained in:
catlog22
2026-02-24 23:32:32 +08:00
parent dadcc1af5e
commit 6c16c121d2
15 changed files with 3740 additions and 0 deletions

View File

@@ -0,0 +1,288 @@
---
name: team-roadmap-dev
description: Unified team skill for roadmap-driven development workflow. Coordinator discusses roadmap with user, then dispatches phased execution pipeline (plan → execute → verify). All roles invoke this skill with --role arg. Triggers on "team roadmap-dev".
allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*)
---
# Team Roadmap Dev
Phased project execution team. Coordinator discusses roadmap with the user and manages phase transitions. Workers handle planning, execution, and verification per phase. Follows filesystem-based state machine pattern with fixed and dynamic artifacts.
## Architecture Overview
```
┌───────────────────────────────────────────────┐
│ Skill(skill="team-roadmap-dev") │
│ args="任务描述" 或 args="--role=xxx" │
└───────────────────┬───────────────────────────┘
│ Role Router
┌──── --role present? ────┐
│ NO │ YES
↓ ↓
Orchestration Mode Role Dispatch
(auto → coordinator) (route to role.md)
┌────┴────┬───────────┬───────────┐
↓ ↓ ↓ ↓
┌──────────┐┌─────────┐┌──────────┐┌──────────┐
│coordinator││ planner ││ executor ││ verifier │
│ (human ││ PLAN-* ││ EXEC-* ││ VERIFY-* │
│ 交互) ││ ││ ││ │
└──────────┘└─────────┘└──────────┘└──────────┘
```
## Command Architecture
```
roles/
├── coordinator/
│ ├── role.md # Orchestrator: roadmap discussion + phase management
│ └── commands/
│ ├── roadmap-discuss.md # Discuss roadmap with user, generate phase plan
│ ├── dispatch.md # Create task chain per phase
│ ├── monitor.md # Stop-Wait phase execution loop
│ ├── pause.md # Save state and exit cleanly
│ └── resume.md # Resume from paused session
├── planner/
│ ├── role.md # Research + task JSON generation per phase
│ └── commands/
│ ├── research.md # Context gathering + codebase exploration
│ └── create-plans.md # action-planning-agent delegation → IMPL-*.json
├── executor/
│ ├── role.md # Task execution with wave parallelism
│ └── commands/
│ └── implement.md # Code implementation via code-developer
└── verifier/
├── role.md # Goal-backward verification
└── commands/
└── verify.md # Convergence criteria checking + gap detection
```
## Role Router
### Input Parsing
```javascript
const args = "$ARGUMENTS"
const roleMatch = args.match(/--role[=\s]+(\w+)/)
const resumeMatch = args.match(/--resume[=\s]+(.+?)(?:\s|$)/)
const teamName = "roadmap-dev"
if (!roleMatch) {
// No --role: Orchestration Mode → auto route to coordinator
// If --resume present: coordinator handles resume via commands/resume.md
}
const role = roleMatch ? roleMatch[1] : "coordinator"
const agentName = args.match(/--agent-name[=\s]+([\w-]+)/)?.[1] || role
```
### Role Dispatch
```javascript
const VALID_ROLES = {
"coordinator": { file: "roles/coordinator/role.md", prefix: null },
"planner": { file: "roles/planner/role.md", prefix: "PLAN" },
"executor": { file: "roles/executor/role.md", prefix: "EXEC" },
"verifier": { file: "roles/verifier/role.md", prefix: "VERIFY" }
}
if (!VALID_ROLES[role]) {
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
}
Read(VALID_ROLES[role].file)
```
### Orchestration Mode
```javascript
if (!roleMatch) {
const role = "coordinator"
Read(VALID_ROLES[role].file)
}
```
### Available Roles
| Role | Task Prefix | Responsibility | Role File |
|------|-------------|----------------|-----------|
| `coordinator` | N/A | Human interaction, roadmap discussion, phase transitions, state management | [roles/coordinator/role.md](roles/coordinator/role.md) |
| `planner` | PLAN-* | Research, context gathering, task JSON generation via action-planning-agent | [roles/planner/role.md](roles/planner/role.md) |
| `executor` | EXEC-* | Code implementation following plans, wave-based parallel execution | [roles/executor/role.md](roles/executor/role.md) |
| `verifier` | VERIFY-* | Convergence criteria verification, gap detection, fix loop trigger | [roles/verifier/role.md](roles/verifier/role.md) |
## Shared Infrastructure
### Artifact System
**Fixed Artifacts** (session-level, persist throughout session):
| Artifact | Path | Created By | Purpose |
|----------|------|------------|---------|
| roadmap.md | `{session}/roadmap.md` | coordinator (roadmap-discuss) | Phase plan with requirements and success criteria |
| state.md | `{session}/state.md` | coordinator | Living memory (<100 lines), updated every significant action |
| config.json | `{session}/config.json` | coordinator | Session settings: mode, depth, gates |
**Dynamic Artifacts** (per-phase, form execution history):
| Artifact | Path | Created By | Purpose |
|----------|------|------------|---------|
| context.md | `{session}/phase-N/context.md` | planner (research) | Phase context and requirements |
| IMPL_PLAN.md | `{session}/phase-N/IMPL_PLAN.md` | planner (create-plans) | Implementation overview with task dependency graph |
| IMPL-*.json | `{session}/phase-N/.task/IMPL-*.json` | planner (create-plans) | Task JSON files (unified flat schema with convergence criteria) |
| TODO_LIST.md | `{session}/phase-N/TODO_LIST.md` | planner (create-plans) | Checklist tracking for all tasks |
| summary-{ID}.md | `{session}/phase-N/summary-{IMPL-ID}.md` | executor (implement) | Execution record with requires/provides/convergence-met |
| verification.md | `{session}/phase-N/verification.md` | verifier (verify) | Convergence criteria check results + gap list |
### Init Prerequisite
Coordinator **must** ensure `.workflow/project-tech.json` exists before starting. If not found, invoke `/workflow:init`.
### Team Configuration
```javascript
const TEAM_CONFIG = {
name: "roadmap-dev",
sessionDir: ".workflow/.team/RD-{slug}-{date}/",
msgDir: ".workflow/.team-msg/roadmap-dev/"
}
```
### Role Isolation Rules
#### Output Tagging
All outputs must carry `[role_name]` prefix.
#### Coordinator Isolation
| Allowed | Forbidden |
|---------|-----------|
| Discuss roadmap with user (AskUserQuestion) | Direct code writing/modification |
| Create task chain (TaskCreate) | Calling implementation subagents |
| Dispatch tasks to workers | Direct analysis/testing/verification |
| Monitor progress (message bus) | Bypassing workers |
| Report results to user | Modifying source code |
#### Worker Isolation
| Allowed | Forbidden |
|---------|-----------|
| Process own-prefix tasks only | Process other roles' tasks |
| SendMessage to coordinator only | Direct worker-to-worker communication |
| Use Toolbox-declared tools | TaskCreate for other roles |
| Delegate to commands/*.md | Modify resources outside scope |
### Message Bus & Task Lifecycle
Each role's role.md contains self-contained Message Bus and Task Lifecycle. See `roles/{role}/role.md`.
## Pipeline
```
Phase N lifecycle:
Coordinator (roadmap-discuss → dispatch phase N)
→ PLAN-N01: Planner (research → action-planning-agent → IMPL-*.json)
→ EXEC-N01: Executor (load IMPL-*.json → wave-based code-developer)
→ VERIFY-N01: Verifier (convergence criteria check)
→ Coordinator (transition: gap closure or next phase)
Cross-phase flow:
Init → Roadmap Discussion → Phase 1 → Phase 2 → ... → Phase N → Complete
↑ |
└── gap closure loop ──────┘
Session lifecycle:
Running → Pause (save coordinates) → Resume (re-enter monitor at coordinates)
```
## Coordinator Spawn Template
```javascript
TeamCreate({ team_name: "roadmap-dev" })
// Planner
Task({
subagent_type: "general-purpose",
team_name: "roadmap-dev",
name: "planner",
prompt: `你是 team "roadmap-dev" 的 PLANNER。
## 首要指令MUST
Skill(skill="team-roadmap-dev", args="--role=planner")
当前需求: ${taskDescription}
Session: ${sessionFolder}
## 角色准则
- 只处理 PLAN-* 前缀任务
- 所有输出带 [planner] 标识
- 仅与 coordinator 通信
## 工作流程
1. Skill(skill="team-roadmap-dev", args="--role=planner")
2. TaskList → PLAN-* 任务 → 执行 → 汇报
3. TaskUpdate completed → 检查下一个任务`
})
// Executor
Task({
subagent_type: "general-purpose",
team_name: "roadmap-dev",
name: "executor",
prompt: `你是 team "roadmap-dev" 的 EXECUTOR。
## 首要指令MUST
Skill(skill="team-roadmap-dev", args="--role=executor")
当前需求: ${taskDescription}
Session: ${sessionFolder}
## 角色准则
- 只处理 EXEC-* 前缀任务
- 所有输出带 [executor] 标识
- 仅与 coordinator 通信
## 工作流程
1. Skill(skill="team-roadmap-dev", args="--role=executor")
2. TaskList → EXEC-* 任务 → 执行 → 汇报
3. TaskUpdate completed → 检查下一个任务`
})
// Verifier
Task({
subagent_type: "general-purpose",
team_name: "roadmap-dev",
name: "verifier",
prompt: `你是 team "roadmap-dev" 的 VERIFIER。
## 首要指令MUST
Skill(skill="team-roadmap-dev", args="--role=verifier")
当前需求: ${taskDescription}
Session: ${sessionFolder}
## 角色准则
- 只处理 VERIFY-* 前缀任务
- 所有输出带 [verifier] 标识
- 仅与 coordinator 通信
## 工作流程
1. Skill(skill="team-roadmap-dev", args="--role=verifier")
2. TaskList → VERIFY-* 任务 → 执行 → 汇报
3. TaskUpdate completed → 检查下一个任务`
})
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Unknown --role value | Error with available role list |
| Missing --role arg | Orchestration Mode → auto route to coordinator |
| Role file not found | Error with expected path |
| project-tech.json missing | Coordinator invokes /workflow:init |
| Phase verification fails with gaps | Coordinator triggers gap closure loop |
| Max gap closure iterations (3) | Report to user, ask for guidance |

View File

@@ -0,0 +1,213 @@
# Command: dispatch
Create task chain for a specific phase. Each phase gets a PLAN -> EXEC -> VERIFY pipeline with dependency ordering.
## Purpose
Read the roadmap and create a linked task chain (PLAN -> EXEC -> VERIFY) for a given phase number. Tasks are assigned to the appropriate worker roles and linked via blockedBy dependencies.
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `phaseNumber` | From coordinator | Phase to dispatch (1-based) |
| `sessionFolder` | From coordinator | Session artifact directory |
## Execution Steps
### Step 1: Read Roadmap and Extract Phase Requirements
```javascript
const roadmap = Read(`${sessionFolder}/roadmap.md`)
const config = JSON.parse(Read(`${sessionFolder}/config.json`))
// Parse phase section from roadmap
// Extract: goal, requirements (REQ-IDs), success criteria
const phaseGoal = extractPhaseGoal(roadmap, phaseNumber)
const phaseRequirements = extractPhaseRequirements(roadmap, phaseNumber)
const phaseSuccessCriteria = extractPhaseSuccessCriteria(roadmap, phaseNumber)
```
### Step 2: Create Phase Directory
```javascript
Bash(`mkdir -p "${sessionFolder}/phase-${phaseNumber}"`)
```
### Step 3: Create PLAN Task (Assigned to Planner)
```javascript
const planTaskId = TaskCreate({
subject: `PLAN-${phaseNumber}01: Plan phase ${phaseNumber} - ${phaseGoal}`,
description: `[coordinator] Plan creation for phase ${phaseNumber}.
## Session
- Folder: ${sessionFolder}
- Phase: ${phaseNumber}
- Depth: ${config.depth}
## Phase Goal
${phaseGoal}
## Requirements
${phaseRequirements.map(r => `- ${r}`).join('\n')}
## Success Criteria
${phaseSuccessCriteria.map(c => `- ${c}`).join('\n')}
## Deliverables
- ${sessionFolder}/phase-${phaseNumber}/context.md (research context)
- ${sessionFolder}/phase-${phaseNumber}/plan-01.md (execution plan with waves and must_haves)
## Instructions
1. Invoke Skill(skill="team-roadmap-dev", args="--role=planner")
2. Follow planner role.md research + create-plans commands
3. Use roadmap requirements as input for plan generation
4. TaskUpdate this task to completed when plan is written`,
activeForm: `Planning phase ${phaseNumber}`
})
```
### Step 4: Create EXEC Task (Assigned to Executor, Blocked by PLAN)
```javascript
const execTaskId = TaskCreate({
subject: `EXEC-${phaseNumber}01: Execute phase ${phaseNumber} - ${phaseGoal}`,
description: `[coordinator] Execute plans for phase ${phaseNumber}.
## Session
- Folder: ${sessionFolder}
- Phase: ${phaseNumber}
## Phase Goal
${phaseGoal}
## Plan Reference
- ${sessionFolder}/phase-${phaseNumber}/plan-01.md (and any additional plans)
## Instructions
1. Invoke Skill(skill="team-roadmap-dev", args="--role=executor")
2. Follow executor role.md implement command
3. Execute all plans in wave order
4. Write summary to ${sessionFolder}/phase-${phaseNumber}/summary-01.md
5. TaskUpdate this task to completed when all plans executed`,
activeForm: `Executing phase ${phaseNumber}`
})
// Set dependency: EXEC blocked by PLAN
TaskUpdate({ taskId: execTaskId, addBlockedBy: [planTaskId] })
```
### Step 5: Create VERIFY Task (Assigned to Verifier, Blocked by EXEC)
```javascript
const verifyTaskId = TaskCreate({
subject: `VERIFY-${phaseNumber}01: Verify phase ${phaseNumber} - ${phaseGoal}`,
description: `[coordinator] Verify phase ${phaseNumber} against success criteria.
## Session
- Folder: ${sessionFolder}
- Phase: ${phaseNumber}
## Phase Goal
${phaseGoal}
## Success Criteria (from roadmap)
${phaseSuccessCriteria.map(c => `- ${c}`).join('\n')}
## References
- Roadmap: ${sessionFolder}/roadmap.md
- Plans: ${sessionFolder}/phase-${phaseNumber}/plan-*.md
- Summaries: ${sessionFolder}/phase-${phaseNumber}/summary-*.md
## Instructions
1. Invoke Skill(skill="team-roadmap-dev", args="--role=verifier")
2. Follow verifier role.md verify command
3. Check each success criterion against actual implementation
4. Write verification to ${sessionFolder}/phase-${phaseNumber}/verification.md
5. If gaps found: list them with gap IDs in verification.md
6. TaskUpdate this task to completed with result (passed/gaps_found)`,
activeForm: `Verifying phase ${phaseNumber}`
})
// Set dependency: VERIFY blocked by EXEC
TaskUpdate({ taskId: verifyTaskId, addBlockedBy: [execTaskId] })
```
### Step 6: Update state.md
```javascript
Edit(`${sessionFolder}/state.md`, {
old_string: `- Phase: ${phaseNumber}\n- Status: ready_to_dispatch`,
new_string: `- Phase: ${phaseNumber}\n- Status: in_progress\n- Tasks: PLAN-${phaseNumber}01 → EXEC-${phaseNumber}01 → VERIFY-${phaseNumber}01`
})
```
### Step 7: Log Dispatch Message
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "coordinator", to: "all",
type: "phase_started",
summary: `[coordinator] Phase ${phaseNumber} dispatched: PLAN-${phaseNumber}01 → EXEC-${phaseNumber}01 → VERIFY-${phaseNumber}01`,
ref: `${sessionFolder}/roadmap.md`
})
```
## Task Description Format
All dispatched tasks follow this structure:
```
[coordinator] {action} for phase {N}.
## Session
- Folder: {sessionFolder}
- Phase: {N}
- Depth: {config.depth} (PLAN only)
## Phase Goal
{goal from roadmap}
## Requirements / Success Criteria
{from roadmap}
## Deliverables
{expected output files}
## Instructions
{step-by-step for the worker role}
```
## Task Naming Convention
| Task | Name Pattern | Example |
|------|-------------|---------|
| Plan | `PLAN-{phase}01` | PLAN-101 |
| Execute | `EXEC-{phase}01` | EXEC-101 |
| Verify | `VERIFY-{phase}01` | VERIFY-101 |
| Gap Plan | `PLAN-{phase}02` | PLAN-102 (gap closure iteration 1) |
| Gap Execute | `EXEC-{phase}02` | EXEC-102 |
| Gap Verify | `VERIFY-{phase}02` | VERIFY-102 |
## Dependency Chain
```
PLAN-{N}01 ←── EXEC-{N}01 ←── VERIFY-{N}01
(planner) (executor) (verifier)
```
Each task is blocked by its predecessor. Workers pick up tasks only when their blockedBy list is empty.
## Output
Returns the three task IDs as a structured result:
```javascript
{
planTaskId: planTaskId,
execTaskId: execTaskId,
verifyTaskId: verifyTaskId
}
```

View File

@@ -0,0 +1,375 @@
# Command: monitor
Stop-Wait phase execution loop. Spawns workers synchronously and manages phase transitions.
## Purpose
Execute all roadmap phases sequentially using the Stop-Wait pattern. The coordinator spawns each worker synchronously (run_in_background: false), waits for completion, then proceeds to the next step. Handles gap closure loops and phase transitions.
## Design Principle
Models have no concept of time. Polling, sleeping, and periodic checking are forbidden. All coordination uses synchronous Task() calls where worker return = step done.
## Strategy
Sequential spawning -- coordinator spawns one worker at a time via synchronous Task() calls. Each worker processes its task and returns. The coordinator inspects the result and decides the next action.
```
Coordinator ──spawn──→ Planner (blocks until done)
←─return──
──spawn──→ Executor (blocks until done)
←─return──
──spawn──→ Verifier (blocks until done)
←─return──
──decide──→ next phase or gap closure
```
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From coordinator | Session artifact directory |
| `roadmap` | From roadmap.md | Parsed phase list |
| `config` | From config.json | Execution mode and gates |
| `resumePhase` | From resume command (optional) | Phase to resume from |
| `resumeStep` | From resume command (optional) | Step within phase to resume from (plan/exec/verify/gap_closure) |
| `resumeGapIteration` | From resume command (optional) | Gap iteration to resume from |
## Execution Steps
### Step 1: Load Session State
```javascript
const roadmap = Read(`${sessionFolder}/roadmap.md`)
const config = JSON.parse(Read(`${sessionFolder}/config.json`))
const state = Read(`${sessionFolder}/state.md`)
const totalPhases = countPhases(roadmap)
// Support resume: use resume coordinates if provided, else parse from state
const currentPhase = resumePhase || parseCurrentPhase(state)
const startStep = resumeStep || 'plan' // plan|exec|verify|gap_closure
const startGapIteration = resumeGapIteration || 0
```
### Step 2: Phase Loop
```javascript
for (let phase = currentPhase; phase <= totalPhases; phase++) {
// --- Phase N execution ---
// 2a. Dispatch task chain (if not already dispatched)
// Read("commands/dispatch.md") → creates PLAN/EXEC/VERIFY tasks
dispatch(phase, sessionFolder)
let phaseComplete = false
let gapIteration = 0
const MAX_GAP_ITERATIONS = 3
while (!phaseComplete && gapIteration <= MAX_GAP_ITERATIONS) {
// 2b. Spawn Planner (Stop-Wait)
const planResult = spawnPlanner(phase, gapIteration, sessionFolder)
// 2c. Gate: plan_check (if configured)
if (config.gates.plan_check && gapIteration === 0) {
const plans = Glob(`${sessionFolder}/phase-${phase}/plan-*.md`)
// Present plan summary to user
AskUserQuestion({
questions: [{
question: `Phase ${phase} plan ready. Proceed with execution?`,
header: "Plan Review",
multiSelect: false,
options: [
{ label: "Proceed", description: "Execute the plan as-is" },
{ label: "Revise", description: "Ask planner to revise" },
{ label: "Skip phase", description: "Skip this phase entirely" }
]
}]
})
// Handle "Revise" → re-spawn planner
// Handle "Skip phase" → break to next phase
}
// 2d. Spawn Executor (Stop-Wait)
const execResult = spawnExecutor(phase, gapIteration, sessionFolder)
// 2e. Spawn Verifier (Stop-Wait)
const verifyResult = spawnVerifier(phase, gapIteration, sessionFolder)
// 2f. Check verification result
const verification = Read(`${sessionFolder}/phase-${phase}/verification.md`)
const gapsFound = parseGapsFound(verification)
if (!gapsFound || gapsFound.length === 0) {
// Phase passed
phaseComplete = true
} else if (gapIteration < MAX_GAP_ITERATIONS) {
// Gap closure: create new task chain for gaps
gapIteration++
triggerGapClosure(phase, gapIteration, gapsFound, sessionFolder)
} else {
// Max iterations reached, report to user
AskUserQuestion({
questions: [{
question: `Phase ${phase} still has ${gapsFound.length} gaps after ${MAX_GAP_ITERATIONS} attempts. How to proceed?`,
header: "Gap Closure Limit",
multiSelect: false,
options: [
{ label: "Continue anyway", description: "Accept current state, move to next phase" },
{ label: "Retry once more", description: "One more gap closure attempt" },
{ label: "Stop", description: "Halt execution for manual intervention" }
]
}]
})
// Handle user choice
phaseComplete = true // or stop based on choice
}
}
// 2g. Phase transition
updateStatePhaseComplete(phase, sessionFolder)
// 2h. Interactive gate at phase boundary
if (config.mode === "interactive" && phase < totalPhases) {
AskUserQuestion({
questions: [{
question: `Phase ${phase} complete. Proceed to phase ${phase + 1}?`,
header: "Phase Transition",
multiSelect: false,
options: [
{ label: "Proceed", description: `Start phase ${phase + 1}` },
{ label: "Review results", description: "Show phase summary before continuing" },
{ label: "Stop", description: "Pause execution here" }
]
}]
})
// Handle "Review results" → display summary, then re-ask
// Handle "Stop" → invoke pause command
if (userChoice === "Stop") {
Read("commands/pause.md")
// Execute pause: save state with currentPhase, currentStep, gapIteration
pauseSession(phase, "transition", gapIteration, sessionFolder)
return // Exit monitor loop
}
}
// If mode === "yolo": auto-advance, no user interaction
}
```
### Step 3: Spawn Functions (Stop-Wait Pattern)
#### Spawn Planner
```javascript
function spawnPlanner(phase, gapIteration, sessionFolder) {
const suffix = gapIteration === 0 ? "01" : `0${gapIteration + 1}`
const gapContext = gapIteration > 0
? `\nGap closure iteration ${gapIteration}. Fix gaps from: ${sessionFolder}/phase-${phase}/verification.md`
: ""
// Synchronous call - blocks until planner returns
Task({
subagent_type: "general-purpose",
team_name: "roadmap-dev",
name: "planner",
prompt: `You are the PLANNER for team "roadmap-dev".
## Primary Directive
Skill(skill="team-roadmap-dev", args="--role=planner")
## Assignment
- Session: ${sessionFolder}
- Phase: ${phase}
- Task: PLAN-${phase}${suffix}${gapContext}
## Workflow
1. Skill(skill="team-roadmap-dev", args="--role=planner")
2. TaskList → find PLAN-${phase}${suffix} → execute
3. TaskUpdate completed when done
All outputs carry [planner] tag.`,
run_in_background: false // CRITICAL: Stop-Wait, blocks until done
})
}
```
#### Spawn Executor
```javascript
function spawnExecutor(phase, gapIteration, sessionFolder) {
const suffix = gapIteration === 0 ? "01" : `0${gapIteration + 1}`
Task({
subagent_type: "general-purpose",
team_name: "roadmap-dev",
name: "executor",
prompt: `You are the EXECUTOR for team "roadmap-dev".
## Primary Directive
Skill(skill="team-roadmap-dev", args="--role=executor")
## Assignment
- Session: ${sessionFolder}
- Phase: ${phase}
- Task: EXEC-${phase}${suffix}
## Workflow
1. Skill(skill="team-roadmap-dev", args="--role=executor")
2. TaskList → find EXEC-${phase}${suffix} → execute plans
3. TaskUpdate completed when done
All outputs carry [executor] tag.`,
run_in_background: false // CRITICAL: Stop-Wait
})
}
```
#### Spawn Verifier
```javascript
function spawnVerifier(phase, gapIteration, sessionFolder) {
const suffix = gapIteration === 0 ? "01" : `0${gapIteration + 1}`
Task({
subagent_type: "general-purpose",
team_name: "roadmap-dev",
name: "verifier",
prompt: `You are the VERIFIER for team "roadmap-dev".
## Primary Directive
Skill(skill="team-roadmap-dev", args="--role=verifier")
## Assignment
- Session: ${sessionFolder}
- Phase: ${phase}
- Task: VERIFY-${phase}${suffix}
## Workflow
1. Skill(skill="team-roadmap-dev", args="--role=verifier")
2. TaskList → find VERIFY-${phase}${suffix} → verify against success criteria
3. TaskUpdate completed when done
All outputs carry [verifier] tag.`,
run_in_background: false // CRITICAL: Stop-Wait
})
}
```
### Step 4: Gap Closure
```javascript
function triggerGapClosure(phase, iteration, gaps, sessionFolder) {
const suffix = `0${iteration + 1}`
// Log gap closure initiation
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "coordinator", to: "planner",
type: "gap_closure",
summary: `[coordinator] Gap closure iteration ${iteration} for phase ${phase}: ${gaps.length} gaps`,
ref: `${sessionFolder}/phase-${phase}/verification.md`
})
// Create new task chain for gap closure
// PLAN-{phase}{suffix}: re-plan focusing on gaps only
TaskCreate({
subject: `PLAN-${phase}${suffix}: Gap closure for phase ${phase} (iteration ${iteration})`,
description: `[coordinator] Gap closure re-planning for phase ${phase}.
## Session
- Folder: ${sessionFolder}
- Phase: ${phase}
- Gap Iteration: ${iteration}
## Gaps to Address
${gaps.map(g => `- ${g}`).join('\n')}
## Reference
- Original verification: ${sessionFolder}/phase-${phase}/verification.md
- Previous plans: ${sessionFolder}/phase-${phase}/plan-*.md
## Instructions
1. Focus ONLY on the listed gaps -- do not re-plan completed work
2. Create ${sessionFolder}/phase-${phase}/plan-${suffix}.md for gap fixes
3. TaskUpdate completed when gap plan is written`,
activeForm: `Re-planning phase ${phase} gaps (iteration ${iteration})`
})
// EXEC and VERIFY tasks follow same pattern with blockedBy
// (same as dispatch.md Step 4 and Step 5, with gap suffix)
}
```
### Step 5: State Updates
```javascript
function updateStatePhaseComplete(phase, sessionFolder) {
const state = Read(`${sessionFolder}/state.md`)
// Update current phase status
Edit(`${sessionFolder}/state.md`, {
old_string: `- Phase: ${phase}\n- Status: in_progress`,
new_string: `- Phase: ${phase}\n- Status: completed\n- Completed: ${new Date().toISOString().slice(0, 19)}`
})
// If more phases remain, set next phase as ready
const nextPhase = phase + 1
if (nextPhase <= totalPhases) {
// Append next phase readiness
Edit(`${sessionFolder}/state.md`, {
old_string: `- Phase: ${phase}\n- Status: completed`,
new_string: `- Phase: ${phase}\n- Status: completed\n\n- Phase: ${nextPhase}\n- Status: ready_to_dispatch`
})
}
}
```
### Step 6: Completion
```javascript
// All phases done -- return control to coordinator Phase 5 (Report + Persist)
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "coordinator", to: "all",
type: "project_complete",
summary: `[coordinator] All ${totalPhases} phases complete.`,
ref: `${sessionFolder}/roadmap.md`
})
```
## Gap Closure Loop Diagram
```
VERIFY-{N}01 → gaps_found?
│ NO → Phase complete → next phase
│ YES ↓
PLAN-{N}02 (gaps only) → EXEC-{N}02 → VERIFY-{N}02
│ gaps_found?
│ NO → Phase complete
│ YES ↓
PLAN-{N}03 → EXEC-{N}03 → VERIFY-{N}03
│ gaps_found?
│ NO → Phase complete
│ YES → Max iterations (3) → ask user
```
## Forbidden Patterns
| Pattern | Why Forbidden | Alternative |
|---------|---------------|-------------|
| `setTimeout` / `sleep` | Models have no time concept | Synchronous Task() return |
| `setInterval` / polling loop | Wastes tokens, unreliable | Stop-Wait spawn pattern |
| `TaskOutput` with sleep polling | Indirect, fragile | `run_in_background: false` |
| `while (!done) { check() }` | Busy wait, no progress | Sequential synchronous calls |
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Worker Task() throws error | Log error, retry once. If still fails, report to user |
| Verification file missing | Treat as gap -- verifier may have crashed, re-spawn |
| Phase dispatch fails | Check roadmap integrity, report to user |
| User chooses "Stop" at gate | Invoke pause command: save state.md with coordinates, exit cleanly |
| Max gap iterations exceeded | Present to user with gap details, ask for guidance |

View File

@@ -0,0 +1,91 @@
# Command: pause
Save session state and exit cleanly. Allows resumption later via resume command.
## Purpose
Persist the current execution state (phase, step, pending tasks) to state.md so the session can be resumed from exactly where it stopped. This is the coordinator's mechanism for handling user "Stop" requests at phase boundaries or gap closure gates.
## When to Use
- User selects "Stop" at any interactive gate in monitor.md
- User requests pause during roadmap discussion
- External interruption requires graceful shutdown
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From coordinator | Session artifact directory |
| `currentPhase` | From monitor loop | Phase number at pause time |
| `currentStep` | From monitor loop | Step within phase (plan/exec/verify/gap_closure) |
| `gapIteration` | From monitor loop | Current gap closure iteration (0 = none) |
## Execution Steps
### Step 1: Capture Current State
```javascript
const state = Read(`${sessionFolder}/state.md`)
const timestamp = new Date().toISOString().slice(0, 19)
// Capture pending task states
const allTasks = TaskList()
const pendingTasks = allTasks.filter(t =>
t.status === 'pending' || t.status === 'in_progress'
)
```
### Step 2: Update state.md with Pause Marker
```javascript
// Find the current phase status line and update it
Edit(`${sessionFolder}/state.md`, {
old_string: `- Status: in_progress`,
new_string: `- Status: paused
- Paused At: ${timestamp}
- Paused Phase: ${currentPhase}
- Paused Step: ${currentStep}
- Gap Iteration: ${gapIteration}
- Pending Tasks: ${pendingTasks.map(t => t.subject).join(', ')}`
})
```
### Step 3: Log Pause Event
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "coordinator", to: "all",
type: "phase_paused",
summary: `[coordinator] Session paused at phase ${currentPhase}, step: ${currentStep}`,
ref: `${sessionFolder}/state.md`
})
```
### Step 4: Report to User
```javascript
// Output pause summary
const summary = `[coordinator] Session paused.
- Phase: ${currentPhase}
- Step: ${currentStep}
- Gap Iteration: ${gapIteration}
- Pending Tasks: ${pendingTasks.length}
To resume: Skill(skill="team-roadmap-dev", args="--resume ${sessionFolder}")
`
```
## Output
| Artifact | Path | Description |
|----------|------|-------------|
| state.md | `{sessionFolder}/state.md` | Updated with paused status and resume coordinates |
## Error Handling
| Scenario | Resolution |
|----------|------------|
| state.md edit fails | Write full state.md from scratch with pause info |
| Task list unavailable | Record phase/step only, skip task listing |

View File

@@ -0,0 +1,138 @@
# Command: resume
Resume a paused roadmap-dev session from its saved state. Reads pause coordinates from state.md and re-enters the monitor loop at the exact phase and step where execution was paused.
## Purpose
Restore execution context from a paused session and continue the monitor loop. This is the coordinator's mechanism for resuming long-running projects across sessions.
## When to Use
- User invokes `Skill(skill="team-roadmap-dev", args="--resume {sessionFolder}")`
- Coordinator detects a paused session during init
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From --resume argument | Session artifact directory to resume |
## Execution Steps
### Step 1: Validate Session State
```javascript
const stateContent = Read(`${sessionFolder}/state.md`)
// Check for paused status
if (!stateContent.includes('Status: paused')) {
// Session is not paused — check if it's in_progress or completed
if (stateContent.includes('Status: completed')) {
// Session already finished
return { error: "Session already completed", sessionFolder }
}
// Not paused, not completed — treat as fresh continue
}
// Parse resume coordinates
const pausedPhase = parseInt(stateContent.match(/Paused Phase: (\d+)/)?.[1] || '1')
const pausedStep = stateContent.match(/Paused Step: (\w+)/)?.[1] || 'plan'
const gapIteration = parseInt(stateContent.match(/Gap Iteration: (\d+)/)?.[1] || '0')
```
### Step 2: Load Session Context
```javascript
const roadmap = Read(`${sessionFolder}/roadmap.md`)
const config = JSON.parse(Read(`${sessionFolder}/config.json`))
// Load project context
const projectTech = JSON.parse(Read('.workflow/project-tech.json'))
```
### Step 3: Update State to In-Progress
```javascript
const timestamp = new Date().toISOString().slice(0, 19)
Edit(`${sessionFolder}/state.md`, {
old_string: `- Status: paused`,
new_string: `- Status: in_progress
- Resumed At: ${timestamp}
- Resumed From Phase: ${pausedPhase}, Step: ${pausedStep}`
})
```
### Step 4: Log Resume Event
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "coordinator", to: "all",
type: "phase_started",
summary: `[coordinator] Session resumed at phase ${pausedPhase}, step: ${pausedStep}`,
ref: `${sessionFolder}/state.md`
})
```
### Step 5: Re-enter Monitor Loop
```javascript
// Delegate to monitor.md with resume context
// monitor.md receives:
// - startPhase: pausedPhase (instead of 1)
// - startStep: pausedStep (plan/exec/verify/gap_closure)
// - gapIteration: gapIteration (for gap closure continuity)
Read("commands/monitor.md")
// Monitor will:
// 1. Skip phases before pausedPhase
// 2. Within pausedPhase, skip steps before pausedStep
// 3. Continue normal execution from that point
```
### Step 6: Determine Resume Entry Point
```javascript
// Map pausedStep to monitor entry point
switch (pausedStep) {
case 'plan':
// Re-dispatch planner for current phase
// Check if PLAN task exists and is pending/incomplete
break
case 'exec':
// Re-dispatch executor for current phase
// Check if EXEC task exists and is pending/incomplete
break
case 'verify':
// Re-dispatch verifier for current phase
break
case 'gap_closure':
// Re-enter gap closure loop at gapIteration
break
case 'transition':
// Phase was complete, proceed to next phase
break
}
```
## Output
| Artifact | Path | Description |
|----------|------|-------------|
| state.md | `{sessionFolder}/state.md` | Updated with resumed status |
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Session folder not found | Error with available session list |
| state.md missing | Error — session may be corrupted |
| Session not paused | Check if in_progress or completed, handle accordingly |
| Roadmap.md missing | Error — session artifacts may be incomplete |
| config.json missing | Use defaults (mode=interactive, depth=standard) |
| Tasks from prior run still pending | Re-use them, don't create duplicates |

View File

@@ -0,0 +1,287 @@
# Command: roadmap-discuss
Interactive roadmap discussion with the user. This is the KEY coordinator command -- no work begins until the roadmap is agreed upon.
## Purpose
Discuss project roadmap with the user using project-tech.json + project-guidelines.json as context. Elicit phases, requirements, success criteria, and execution preferences. Produces `roadmap.md` and `config.json` as session artifacts.
## When to Use
- Phase 2 of coordinator lifecycle (after init prerequisites, before dispatch)
- Called exactly once per session (re-entry updates existing roadmap)
## Strategy
Direct interaction via AskUserQuestion. No delegation to workers or subagents. Coordinator handles this entirely.
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From coordinator Phase 1 | Session artifact directory |
| `taskDescription` | From coordinator Phase 1 | User's original task description |
| `projectTech` | Loaded in Phase 1 | Parsed project-tech.json |
| `projectGuidelines` | Loaded in Phase 1 | Parsed project-guidelines.json (nullable) |
| `autoYes` | From -y/--yes flag | Skip interactive prompts, use defaults |
## Execution Steps
### Step 1: Load Project Context
```javascript
// Already loaded by coordinator Phase 1, but verify availability
const projectTech = JSON.parse(Read('.workflow/project-tech.json'))
let projectGuidelines = null
try {
projectGuidelines = JSON.parse(Read('.workflow/project-guidelines.json'))
} catch {}
```
### Step 2: Present Project Overview to User
```javascript
// Summarize what we know about the project
const overview = `[coordinator] Project context loaded.
- Project: ${projectTech.project_name}
- Tech Stack: ${projectTech.tech_stack?.join(', ')}
- Task: ${taskDescription}
${projectGuidelines ? `- Guidelines: ${projectGuidelines.conventions?.length || 0} conventions loaded` : '- Guidelines: not configured'}`
// Display overview (via direct output, not AskUserQuestion)
```
### Step 3: Confirm Project Goal and Scope
```javascript
// Skip if taskDescription is already detailed enough, or autoYes
if (!autoYes && !taskDescription) {
AskUserQuestion({
questions: [{
question: "What is the project goal and scope for this session?",
header: "Goal",
multiSelect: false,
options: [] // Free-form text input
}]
})
}
// Store response as `projectGoal`
const projectGoal = taskDescription || userResponse
```
### Step 4: Ask Execution Mode
```javascript
if (!autoYes) {
AskUserQuestion({
questions: [{
question: "How should phase transitions be handled?",
header: "Execution Mode",
multiSelect: false,
options: [
{ label: "interactive", description: "Ask for confirmation at each phase transition" },
{ label: "yolo", description: "Auto-execute all phases without stopping" },
{ label: "custom", description: "Choose which gates require confirmation" }
]
}]
})
} else {
mode = "yolo"
}
// If "custom" selected, follow up with gate selection:
if (mode === "custom") {
AskUserQuestion({
questions: [{
question: "Which gates should require confirmation?",
header: "Custom Gates",
multiSelect: true,
options: [
{ label: "plan_check", description: "Review plan before execution" },
{ label: "verifier", description: "Review verification results before next phase" },
{ label: "gap_closure", description: "Confirm gap closure before re-execution" }
]
}]
})
}
```
### Step 5: Ask Analysis Depth
```javascript
if (!autoYes) {
AskUserQuestion({
questions: [{
question: "How thorough should the analysis be?",
header: "Analysis Depth",
multiSelect: false,
options: [
{ label: "quick", description: "Fast scan, minimal context gathering (small tasks)" },
{ label: "standard", description: "Balanced analysis with key context (default)" },
{ label: "comprehensive", description: "Deep analysis, full codebase exploration (large refactors)" }
]
}]
})
} else {
depth = "standard"
}
```
### Step 6: Analyze Codebase and Generate Phased Roadmap
```javascript
// Use Gemini CLI (or cli-explore-agent) to analyze the codebase
// and generate a phased breakdown based on goal + project context
Bash({
command: `ccw cli -p "PURPOSE: Analyze codebase and generate phased execution roadmap for: ${projectGoal}
TASK: \
- Scan project structure and identify affected modules \
- Break goal into sequential phases (max 5) \
- Each phase: goal, requirements (REQ-IDs), success criteria (2-5 testable behaviors) \
- Order phases by dependency (foundational first)
MODE: analysis
CONTEXT: @**/* | Memory: Tech stack: ${projectTech.tech_stack?.join(', ')}
EXPECTED: Phased roadmap in markdown with REQ-IDs and testable success criteria
CONSTRAINTS: Max 5 phases | Each phase independently verifiable | No implementation details" \
--tool gemini --mode analysis --rule planning-breakdown-task-steps`,
run_in_background: false,
timeout: 300000
})
// Parse the CLI output into structured phases
```
### Step 7: Present Roadmap Draft for Confirmation
```javascript
// Display the generated roadmap to user
// Output the roadmap content directly, then ask for adjustments
AskUserQuestion({
questions: [{
question: "Review the roadmap above. Any adjustments needed?",
header: "Roadmap Review",
multiSelect: false,
options: [
{ label: "Looks good, proceed", description: "Accept roadmap as-is" },
{ label: "Adjust phases", description: "I want to modify the phase breakdown" },
{ label: "Add requirements", description: "I want to add missing requirements" },
{ label: "Change scope", description: "Narrow or expand the scope" }
]
}]
})
// If user requests adjustments, incorporate feedback and re-present
// Loop until user confirms "Looks good, proceed"
```
### Step 8: Generate Session Artifacts
#### roadmap.md
```javascript
Write(`${sessionFolder}/roadmap.md`, roadmapContent)
```
**roadmap.md format**:
```markdown
# Roadmap: {projectGoal}
Generated: {date}
Session: {sessionFolder}
Depth: {depth}
## Phase 1: {phase title}
**Goal**: {one-line goal}
**Requirements**:
- REQ-101: {requirement description}
- REQ-102: {requirement description}
**Success Criteria**:
- [ ] {testable behavior 1}
- [ ] {testable behavior 2}
- [ ] {testable behavior 3}
**Plan Count**: TBD
---
## Phase 2: {phase title}
**Goal**: {one-line goal}
**Requirements**:
- REQ-201: {requirement description}
**Success Criteria**:
- [ ] {testable behavior 1}
- [ ] {testable behavior 2}
**Plan Count**: TBD
---
(... additional phases ...)
```
**REQ-ID Convention**: `REQ-{phase}{seq}` (e.g., REQ-101 = Phase 1, requirement 1)
#### config.json
```javascript
Write(`${sessionFolder}/config.json`, JSON.stringify({
mode: mode, // "interactive" | "yolo" | "custom"
depth: depth, // "quick" | "standard" | "comprehensive"
auto_advance: mode === "yolo",
gates: {
plan_check: mode === "interactive" || (mode === "custom" && customGates.includes("plan_check")),
verifier: mode === "interactive" || (mode === "custom" && customGates.includes("verifier")),
gap_closure: mode === "interactive" || (mode === "custom" && customGates.includes("gap_closure"))
}
}, null, 2))
```
**config.json format**:
```json
{
"mode": "interactive",
"depth": "standard",
"auto_advance": false,
"gates": {
"plan_check": true,
"verifier": true,
"gap_closure": true
}
}
```
### Step 9: Update state.md
```javascript
// Transition Phase 0 → Phase 1
Edit(`${sessionFolder}/state.md`, {
old_string: "- Phase: 0 (Roadmap Discussion)\n- Status: initializing",
new_string: `- Phase: 1\n- Status: ready_to_dispatch\n- Roadmap: confirmed (${phaseCount} phases)\n- Mode: ${mode}\n- Depth: ${depth}`
})
```
## Output
| Artifact | Path | Description |
|----------|------|-------------|
| roadmap.md | `{sessionFolder}/roadmap.md` | Phased plan with REQ-IDs and success criteria |
| config.json | `{sessionFolder}/config.json` | Execution preferences |
| state.md | `{sessionFolder}/state.md` | Updated with phase transition |
## Error Handling
| Scenario | Resolution |
|----------|------------|
| User provides no goal | Re-prompt with examples |
| CLI analysis fails | Retry with simpler prompt, or ask user to describe phases manually |
| User keeps adjusting roadmap | Max 5 adjustment rounds, then proceed with latest version |
| autoYes flag set | Skip all AskUserQuestion calls, use defaults: mode=yolo, depth=standard |

View File

@@ -0,0 +1,202 @@
# Role: coordinator
Team coordinator. Manages the full project lifecycle: init prerequisites → roadmap discussion with user → phase dispatch → monitoring → transitions → completion.
**Key innovation**: Roadmap is discussed with the user via `commands/roadmap-discuss.md` before any work begins. Coordinator is the ONLY role that interacts with humans.
## Role Identity
- **Name**: `coordinator`
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
- **Responsibility**: Orchestration
- **Communication**: SendMessage to all teammates + AskUserQuestion to user
- **Output Tag**: `[coordinator]`
## Role Boundaries
### MUST
- All outputs must carry `[coordinator]` prefix
- Handle ALL human interaction (AskUserQuestion) — workers never interact with user
- Ensure init prerequisites before starting (project-tech.json)
- Discuss roadmap with user before dispatching work
- Manage state.md updates at every phase transition
- Route verifier gap results to planner for closure
### MUST NOT
- ❌ Execute any business tasks (code, analysis, testing, verification)
- ❌ Call code-developer, cli-explore-agent, or other implementation subagents
- ❌ Modify source code or generate implementation artifacts
- ❌ Bypass worker roles to do work directly
- ❌ Skip roadmap discussion phase
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `phase_started` | coordinator → workers | Phase dispatch | New phase initiated |
| `phase_complete` | coordinator → user | All phase tasks done | Phase results summary |
| `gap_closure` | coordinator → planner | Verifier found gaps | Trigger re-plan for gaps |
| `project_complete` | coordinator → user | All phases done | Final report |
| `error` | coordinator → user | Critical failure | Error report |
## Message Bus
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "coordinator", to: targetRole,
type: messageType,
summary: `[coordinator] ${messageSummary}`,
ref: artifactPath
})
```
### CLI Fallback
```javascript
Bash(`ccw team log --team "roadmap-dev" --from "coordinator" --to "${targetRole}" --type "${type}" --summary "[coordinator] ${summary}" --json`)
```
## Toolbox
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `roadmap-discuss` | [commands/roadmap-discuss.md](commands/roadmap-discuss.md) | Phase 1-2 | Discuss roadmap with user, generate session artifacts |
| `dispatch` | [commands/dispatch.md](commands/dispatch.md) | Phase 3 | Create task chain per phase |
| `monitor` | [commands/monitor.md](commands/monitor.md) | Phase 4 | Stop-Wait phase execution loop |
| `pause` | [commands/pause.md](commands/pause.md) | Any | Save state and exit cleanly |
| `resume` | [commands/resume.md](commands/resume.md) | Any | Resume from paused session |
## Execution
### Phase 1: Init Prerequisites + Requirement Parsing
```javascript
const args = "$ARGUMENTS"
const taskDescription = args.replace(/--\w+[=\s]+\S+/g, '').trim()
const autoYes = /\b(-y|--yes)\b/.test(args)
const resumeMatch = args.match(/--resume[=\s]+(.+?)(?:\s|$)/)
// Resume mode: skip init, load existing session
if (resumeMatch) {
const sessionFolder = resumeMatch[1].trim()
Read("commands/resume.md")
// Resume handles: validate state → load context → re-enter monitor
return
}
// 1. Ensure project-tech.json exists
const techExists = Bash(`test -f .workflow/project-tech.json && echo "EXISTS" || echo "NOT_FOUND"`).trim()
if (techExists === "NOT_FOUND") {
// Invoke workflow:init
Skill(skill="workflow:init")
}
// 2. Load project context
const projectTech = JSON.parse(Read('.workflow/project-tech.json'))
let projectGuidelines = null
try {
projectGuidelines = JSON.parse(Read('.workflow/project-guidelines.json'))
} catch {}
// 3. Create session directory
const slug = taskDescription.replace(/[^a-zA-Z0-9\u4e00-\u9fff]+/g, '-').slice(0, 30).toLowerCase()
const date = new Date().toISOString().slice(0, 10)
const sessionFolder = `.workflow/.team/RD-${slug}-${date}`
Bash(`mkdir -p "${sessionFolder}"`)
// 4. Initialize state.md
Write(`${sessionFolder}/state.md`, `# Roadmap Dev Session State
## Project Reference
- Name: ${projectTech.project_name}
- Session: RD-${slug}-${date}
- Started: ${date}
## Current Position
- Phase: 0 (Roadmap Discussion)
- Status: initializing
## Accumulated Context
- Task: ${taskDescription}
`)
```
### Phase 2: Roadmap Discussion (via command)
```javascript
// Delegate to roadmap-discuss command
Read("commands/roadmap-discuss.md")
// Execute roadmap discussion with user
// Produces: {sessionFolder}/roadmap.md, {sessionFolder}/config.json
// Updates: {sessionFolder}/state.md
```
**Command**: [commands/roadmap-discuss.md](commands/roadmap-discuss.md)
### Phase 3: Create Team + Dispatch First Phase
```javascript
// 1. Create team and spawn workers
TeamCreate({ team_name: "roadmap-dev" })
// Spawn planner, executor, verifier (see SKILL.md Coordinator Spawn Template)
// 2. Dispatch first phase
Read("commands/dispatch.md")
// Creates: PLAN-101 (phase 1 planning task)
```
**Command**: [commands/dispatch.md](commands/dispatch.md)
### Phase 4: Coordination Loop (Stop-Wait per phase)
```javascript
Read("commands/monitor.md")
// Executes: phase-by-phase Stop-Wait loop
// Handles: phase transitions, gap closure, next phase dispatch
// Continues until all roadmap phases complete
```
**Command**: [commands/monitor.md](commands/monitor.md)
### Phase 5: Report + Persist
```javascript
// 1. Update state.md with final status
const finalState = Read(`${sessionFolder}/state.md`)
// Update status to "completed"
// 2. Summary report to user
const roadmap = Read(`${sessionFolder}/roadmap.md`)
// Compile results from all phase summaries and verifications
// 3. Post-completion options
AskUserQuestion({
questions: [{
question: "项目执行完成。下一步?",
header: "Next",
multiSelect: false,
options: [
{ label: "提交代码", description: "git add + commit 所有变更" },
{ label: "继续下一个里程碑", description: "开始新的 roadmap discussion" },
{ label: "完成", description: "结束 session" }
]
}]
})
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| project-tech.json missing | Invoke /workflow:init automatically |
| User cancels roadmap discussion | Save session state, exit gracefully |
| Planner fails | Retry once, then ask user for guidance |
| Executor fails on plan | Mark plan as failed, continue with next |
| Verifier finds gaps (≤3 iterations) | Trigger gap closure: re-plan → re-execute → re-verify |
| Verifier gaps persist (>3 iterations) | Report to user, ask for manual intervention |
| Worker timeout | Kill worker, report partial results |

View File

@@ -0,0 +1,309 @@
# Command: implement
Wave-based task execution using code-developer subagent. Reads IMPL-*.json task files, computes execution waves from dependency graph, and executes sequentially by wave with parallel tasks within each wave.
## Purpose
Read IMPL-*.json task files for the current phase, compute wave groups from depends_on graph, and execute each task by delegating to a code-developer subagent. Produce summary-NN.md per task with structured YAML frontmatter for verifier and cross-task context.
## When to Use
- Phase 3 of executor execution (after loading tasks, before self-validation)
- Called once per EXEC-* task
## Strategy
Compute waves from dependency graph (topological sort). Sequential waves, parallel tasks within each wave. Each task is delegated to a code-developer subagent with the full task JSON plus prior summary context. After each task completes, a summary is written. After each wave completes, wave progress is reported.
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From EXEC-* task description | Session artifact directory |
| `phaseNumber` | From EXEC-* task description | Phase number (1-based) |
| `tasks` | From executor Phase 2 | Parsed task JSON objects |
| `waves` | From executor Phase 2 | Wave-grouped task map |
| `waveNumbers` | From executor Phase 2 | Sorted wave number array |
| `priorSummaries` | From executor Phase 2 | Summaries from earlier phases |
## Execution Steps
### Step 1: Compute Waves from Dependency Graph
```javascript
// Tasks loaded in executor Phase 2 from .task/IMPL-*.json
// Compute wave assignment from depends_on graph
function computeWaves(tasks) {
const waveMap = {} // taskId → waveNumber
const assigned = new Set()
let currentWave = 1
while (assigned.size < tasks.length) {
const ready = tasks.filter(t =>
!assigned.has(t.id) &&
(t.depends_on || []).every(d => assigned.has(d))
)
if (ready.length === 0 && assigned.size < tasks.length) {
// Cycle detected — force lowest unassigned
const unassigned = tasks.find(t => !assigned.has(t.id))
ready.push(unassigned)
}
for (const task of ready) {
waveMap[task.id] = currentWave
assigned.add(task.id)
}
currentWave++
}
// Group by wave
const waves = {}
for (const task of tasks) {
const w = waveMap[task.id]
if (!waves[w]) waves[w] = []
waves[w].push(task)
}
return {
waves,
waveNumbers: Object.keys(waves).map(Number).sort((a, b) => a - b),
totalWaves: currentWave - 1
}
}
const { waves, waveNumbers, totalWaves } = computeWaves(tasks)
const totalTasks = tasks.length
let completedTasks = 0
```
### Step 2: Sequential Wave Execution
```javascript
for (const waveNum of waveNumbers) {
const waveTasks = waves[waveNum]
for (const task of waveTasks) {
const startTime = Date.now()
// 2a. Build context from prior summaries
const contextSummaries = []
// From earlier phases
for (const ps of priorSummaries) {
contextSummaries.push(ps.content)
}
// From earlier waves in this phase
for (const earlierWave of waveNumbers.filter(w => w < waveNum)) {
for (const earlierTask of waves[earlierWave]) {
try {
const summaryFile = `${sessionFolder}/phase-${phaseNumber}/summary-${earlierTask.id}.md`
contextSummaries.push(Read(summaryFile))
} catch {}
}
}
const contextSection = contextSummaries.length > 0
? `## Prior Context\n\n${contextSummaries.join('\n\n---\n\n')}`
: "## Prior Context\n\nNone (first task in first wave)."
// 2b. Build implementation prompt from task JSON
const filesSection = (task.files || [])
.map(f => `- \`${f.path}\` (${f.action}): ${f.change}`)
.join('\n')
const stepsSection = (task.implementation || [])
.map((step, i) => typeof step === 'string' ? `${i + 1}. ${step}` : `${i + 1}. ${step.step}: ${step.description}`)
.join('\n')
const convergenceSection = task.convergence
? `## Success Criteria\n${(task.convergence.criteria || []).map(c => `- ${c}`).join('\n')}\n\n**Verification**: ${task.convergence.verification || 'N/A'}`
: ''
// 2c. Delegate to code-developer subagent
const implResult = Task({
subagent_type: "code-developer",
run_in_background: false,
prompt: `Implement the following task. Write production-quality code following existing patterns.
## Task: ${task.id} - ${task.title}
${task.description}
## Files
${filesSection}
## Implementation Steps
${stepsSection}
${convergenceSection}
${contextSection}
## Implementation Rules
- Follow existing code patterns and conventions in the project
- Write clean, minimal code that satisfies the task requirements
- Create all files listed with action "create"
- Modify files listed with action "modify" as described
- Handle errors appropriately
- Do NOT add unnecessary features beyond what the task specifies
- Do NOT modify files outside the task scope unless absolutely necessary
## Output
After implementation, report:
1. Files created or modified (with brief description of changes)
2. Key decisions made during implementation
3. Any deviations from the task (and why)
4. Capabilities provided (exports, APIs, components)
5. Technologies/patterns used`
})
const duration = Math.round((Date.now() - startTime) / 60000)
// 2d. Write summary
const summaryPath = `${sessionFolder}/phase-${phaseNumber}/summary-${task.id}.md`
const affectedPaths = (task.files || []).map(f => f.path)
Write(summaryPath, `---
phase: ${phaseNumber}
task: "${task.id}"
title: "${task.title}"
requires: [${(task.depends_on || []).map(d => `"${d}"`).join(', ')}]
provides: ["${task.id}"]
affects:
${affectedPaths.map(p => ` - "${p}"`).join('\n')}
tech-stack: []
key-files:
${affectedPaths.map(p => ` - "${p}"`).join('\n')}
key-decisions: []
patterns-established: []
convergence-met: pending
duration: ${duration}m
completed: ${new Date().toISOString().slice(0, 19)}
---
# Summary: ${task.id} - ${task.title}
## Implementation Result
${implResult || "Implementation delegated to code-developer subagent."}
## Files Affected
${affectedPaths.map(p => `- \`${p}\``).join('\n')}
## Convergence Criteria
${(task.convergence?.criteria || []).map(c => `- [ ] ${c}`).join('\n')}
`)
completedTasks++
}
// 2e. Report wave progress
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: "exec_progress",
summary: `[executor] Wave ${waveNum}/${totalWaves} complete (${completedTasks}/${totalTasks} tasks done)`,
ref: `${sessionFolder}/phase-${phaseNumber}/`
})
}
```
### Step 3: Report Execution Complete
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: "exec_complete",
summary: `[executor] All ${totalTasks} tasks executed across ${totalWaves} waves for phase ${phaseNumber}`,
ref: `${sessionFolder}/phase-${phaseNumber}/`
})
```
## Summary File Format
Each summary-{IMPL-ID}.md uses YAML frontmatter:
```yaml
---
phase: N
task: "IMPL-N"
title: "Task title"
requires: ["IMPL-N"]
provides: ["IMPL-N"]
affects: [paths]
tech-stack: [technologies]
key-files: [paths]
key-decisions: [decisions]
patterns-established: [patterns]
convergence-met: pending|pass|fail
duration: Xm
completed: timestamp
---
```
### Frontmatter Fields
| Field | Type | Description |
|-------|------|-------------|
| `phase` | number | Phase this summary belongs to |
| `task` | string | Task ID that was executed |
| `title` | string | Task title |
| `requires` | string[] | Dependency task IDs consumed |
| `provides` | string[] | Task ID provided to downstream |
| `affects` | string[] | File paths created or modified |
| `tech-stack` | string[] | Technologies/frameworks used |
| `key-files` | string[] | Primary files (subset of affects) |
| `key-decisions` | string[] | Decisions made during implementation |
| `patterns-established` | string[] | Patterns introduced |
| `convergence-met` | string | Whether convergence criteria passed |
| `duration` | string | Execution time |
| `completed` | string | ISO timestamp |
## Deviation Rules
| Deviation | Action | Report |
|-----------|--------|--------|
| **Bug found** in existing code | Auto-fix, continue | Log in summary key-decisions |
| **Missing critical** dependency | Add to scope, implement | Log in summary key-decisions |
| **Blocking dependency** (unresolvable) | Stop task execution | Report error to coordinator |
| **Architectural concern** | Do NOT auto-fix | Report error to coordinator, await guidance |
## Wave Execution Example
```
Phase 2, 4 tasks, 3 waves (computed from depends_on):
Wave 1: [IMPL-201 (types)] — no dependencies
-> delegate IMPL-201 to code-developer
-> write summary-IMPL-201.md
-> report: Wave 1/3 complete (1/4 tasks)
Wave 2: [IMPL-202 (API), IMPL-203 (UI)] — depend on IMPL-201
-> delegate IMPL-202 (loads summary-IMPL-201 as context)
-> write summary-IMPL-202.md
-> delegate IMPL-203 (loads summary-IMPL-201 as context)
-> write summary-IMPL-203.md
-> report: Wave 2/3 complete (3/4 tasks)
Wave 3: [IMPL-204 (tests)] — depends on IMPL-202, IMPL-203
-> delegate IMPL-204 (loads summaries 201-203 as context)
-> write summary-IMPL-204.md
-> report: Wave 3/3 complete (4/4 tasks)
-> report: exec_complete
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| code-developer subagent fails | Retry once. If still fails, write error summary, continue with next task |
| File write conflict | Last write wins. Log in summary. Verifier will validate |
| Task references non-existent file | Check if dependency task creates it. If yes, load summary. If no, log error |
| All tasks in a wave fail | Report wave failure to coordinator, attempt next wave |
| Summary write fails | Retry with Bash fallback. Critical — verifier needs summaries |

View File

@@ -0,0 +1,272 @@
# Role: executor
Code implementation per phase. Reads IMPL-*.json task files from the phase's .task/ directory, computes execution waves from the dependency graph, and executes sequentially by wave with parallel tasks within each wave. Each task is delegated to a code-developer subagent. Produces summary-{IMPL-ID}.md files for verifier consumption.
## Role Identity
- **Name**: `executor`
- **Task Prefix**: `EXEC-*`
- **Responsibility**: Code generation
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[executor]`
## Role Boundaries
### MUST
- All outputs must carry `[executor]` prefix
- Only process `EXEC-*` prefixed tasks
- Only communicate with coordinator (SendMessage)
- Delegate implementation to commands/implement.md
- Execute tasks in dependency order (sequential waves, parallel within wave)
- Write summary-{IMPL-ID}.md per task after execution
- Report wave progress to coordinator
### MUST NOT
- Create plans or modify IMPL-*.json task files
- Verify implementation against must_haves (that is verifier's job)
- Create tasks for other roles (TaskCreate)
- Interact with user (AskUserQuestion)
- Process PLAN-* or VERIFY-* tasks
- Skip loading prior summaries for cross-plan context
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `exec_complete` | executor -> coordinator | All plans executed | Implementation done, summaries written |
| `exec_progress` | executor -> coordinator | Wave completed | Wave N of M done |
| `error` | executor -> coordinator | Failure | Implementation failed |
## Message Bus
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: messageType,
summary: `[executor] ${messageSummary}`,
ref: artifactPath
})
```
### CLI Fallback
```javascript
Bash(`ccw team log --team "roadmap-dev" --from "executor" --to "coordinator" --type "${type}" --summary "[executor] ${summary}" --json`)
```
## Toolbox
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `implement` | [commands/implement.md](commands/implement.md) | Phase 3 | Wave-based plan execution via code-developer subagent |
### Available Subagents
| Subagent | Purpose | When |
|----------|---------|------|
| `code-developer` | Code implementation per plan | Phase 3: delegate each plan |
### CLI Tools
None. Executor delegates all implementation work to code-developer subagent.
## Execution
### Phase 1: Task Discovery
```javascript
// Find assigned EXEC-* task
const tasks = TaskList()
const execTask = tasks.find(t =>
t.subject.startsWith('EXEC-') &&
t.status === 'pending' &&
(!t.blockedBy || t.blockedBy.length === 0)
)
if (!execTask) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: "error",
summary: "[executor] No available EXEC-* task found"
})
return
}
TaskUpdate({ taskId: execTask.id, status: "in_progress" })
// Parse task description for session context
const taskDetails = TaskGet({ taskId: execTask.id })
const sessionFolder = parseSessionFolder(taskDetails.description)
const phaseNumber = parsePhaseNumber(taskDetails.description)
```
### Phase 2: Load Tasks
```javascript
// Read all task JSON files for this phase
const taskFiles = Glob(`${sessionFolder}/phase-${phaseNumber}/.task/IMPL-*.json`)
if (!taskFiles || taskFiles.length === 0) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: "error",
summary: `[executor] No task JSONs found in ${sessionFolder}/phase-${phaseNumber}/.task/`
})
return
}
// Parse all task JSONs
const tasks = []
for (const taskFile of taskFiles) {
const taskJson = JSON.parse(Read(taskFile))
tasks.push({
...taskJson,
file: taskFile
})
}
// Compute waves from dependency graph
function computeWaves(tasks) {
const waveMap = {}
const assigned = new Set()
let currentWave = 1
while (assigned.size < tasks.length) {
const ready = tasks.filter(t =>
!assigned.has(t.id) &&
(t.depends_on || []).every(d => assigned.has(d))
)
if (ready.length === 0 && assigned.size < tasks.length) {
const unassigned = tasks.find(t => !assigned.has(t.id))
ready.push(unassigned)
}
for (const task of ready) { waveMap[task.id] = currentWave; assigned.add(task.id) }
currentWave++
}
const waves = {}
for (const task of tasks) {
const w = waveMap[task.id]
if (!waves[w]) waves[w] = []
waves[w].push(task)
}
return { waves, waveNumbers: Object.keys(waves).map(Number).sort((a, b) => a - b) }
}
const { waves, waveNumbers } = computeWaves(tasks)
// Load prior summaries for cross-task context
const priorSummaries = []
for (let p = 1; p < phaseNumber; p++) {
try {
const summaryFiles = Glob(`${sessionFolder}/phase-${p}/summary-*.md`)
for (const sf of summaryFiles) {
priorSummaries.push({ phase: p, content: Read(sf) })
}
} catch {}
}
```
### Phase 3: Implement (via command)
```javascript
// Delegate to implement command
Read("commands/implement.md")
// Execute wave-based implementation:
// 1. Compute waves from depends_on graph
// 2. For each wave (sequential): execute all tasks in the wave
// 3. For each task in wave: delegate to code-developer subagent
// 4. Write summary-{IMPL-ID}.md per task
// 5. Report wave progress
//
// Produces: {sessionFolder}/phase-{N}/summary-IMPL-*.md
```
**Command**: [commands/implement.md](commands/implement.md)
### Phase 4: Self-Validation
```javascript
// Basic validation after implementation — NOT full verification (that is verifier's job)
const summaryFiles = Glob(`${sessionFolder}/phase-${phaseNumber}/summary-*.md`)
for (const summaryFile of summaryFiles) {
const summary = Read(summaryFile)
const frontmatter = parseYamlFrontmatter(summary)
const affectedFiles = frontmatter.affects || frontmatter['key-files'] || []
for (const filePath of affectedFiles) {
// 4a. Check file exists
const exists = Bash(`test -f "${filePath}" && echo "EXISTS" || echo "NOT_FOUND"`).trim()
if (exists === "NOT_FOUND") {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: "error",
summary: `[executor] Expected file not found after implementation: ${filePath}`,
ref: summaryFile
})
}
// 4b. Syntax check (basic — language-aware)
if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
const syntaxCheck = Bash(`npx tsc --noEmit "${filePath}" 2>&1 || true`)
if (syntaxCheck.includes('error TS')) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: "error",
summary: `[executor] TypeScript syntax errors in ${filePath}`,
ref: summaryFile
})
}
}
}
}
// 4c. Run lint once for all changes (best-effort)
Bash(`npm run lint 2>&1 || yarn lint 2>&1 || true`)
```
### Phase 5: Report to Coordinator
```javascript
const taskCount = tasks.length
const waveCount = waveNumbers.length
const writtenSummaries = Glob(`${sessionFolder}/phase-${phaseNumber}/summary-*.md`)
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "executor", to: "coordinator",
type: "exec_complete",
summary: `[executor] Phase ${phaseNumber} executed: ${taskCount} tasks across ${waveCount} waves. ${writtenSummaries.length} summaries written.`,
ref: `${sessionFolder}/phase-${phaseNumber}/`
})
SendMessage({
to: "coordinator",
message: `[executor] Phase ${phaseNumber} execution complete.
- Tasks executed: ${taskCount}
- Waves: ${waveCount}
- Summaries: ${writtenSummaries.map(f => f).join(', ')}
Ready for verification.`
})
TaskUpdate({ taskId: execTask.id, status: "completed" })
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No task JSON files found | Error to coordinator -- planner may have failed |
| code-developer subagent fails | Retry once. If still fails, log error in summary, continue with next plan |
| Syntax errors after implementation | Log in summary, continue -- verifier will catch remaining issues |
| Missing dependency from earlier wave | Error to coordinator -- dependency graph may be incorrect |
| File conflict between parallel plans | Log warning, last write wins -- verifier will validate correctness |

View File

@@ -0,0 +1,362 @@
# Command: create-plans
Generate execution plans via action-planning-agent. Produces IMPL_PLAN.md, .task/IMPL-*.json, and TODO_LIST.md — the same artifact format as workflow-plan skill.
## Purpose
Transform phase context into structured task JSONs and implementation plan. Delegates to action-planning-agent for document generation. Produces artifacts compatible with workflow-plan's output format, enabling reuse of executor and verifier logic.
## When to Use
- Phase 3 of planner execution (after research, before self-validation)
- Called once per PLAN-* task
## Strategy
Delegate to action-planning-agent with phase context (context.md + roadmap phase section). The agent produces task JSONs with convergence criteria (replacing the old must_haves concept), dependency graph (replacing wave numbering), and implementation steps.
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From PLAN-* task description | Session artifact directory |
| `phaseNumber` | From PLAN-* task description | Phase number (1-based) |
## Output Artifact Mapping (vs old plan-NN.md)
| Old (plan-NN.md) | New (IMPL-*.json) | Notes |
|-------------------|--------------------|-------|
| `plan: NN` | `id: "IMPL-N"` | Task identifier |
| `wave: N` | `depends_on: [...]` | Dependency graph replaces explicit waves |
| `files_modified: [...]` | `files: [{path, action, change}]` | Structured file list |
| `requirements: [REQ-IDs]` | `description` + `scope` | Requirements embedded in description |
| `must_haves.truths` | `convergence.criteria` | Observable behaviors → measurable criteria |
| `must_haves.artifacts` | `files` + `convergence.verification` | File checks in verification command |
| `must_haves.key_links` | `convergence.verification` | Import wiring in verification command |
| Plan body (implementation steps) | `implementation: [...]` | Step-by-step actions |
## Execution Steps
### Step 1: Load Phase Context
```javascript
const context = Read(`${sessionFolder}/phase-${phaseNumber}/context.md`)
const roadmap = Read(`${sessionFolder}/roadmap.md`)
const config = JSON.parse(Read(`${sessionFolder}/config.json`))
// Extract phase section from roadmap
const phaseGoal = extractPhaseGoal(roadmap, phaseNumber)
const requirements = extractRequirements(roadmap, phaseNumber)
const successCriteria = extractSuccessCriteria(roadmap, phaseNumber)
// Check for gap closure context
const isGapClosure = context.includes("Gap Closure Context")
// Load prior phase summaries for cross-phase context
const priorSummaries = []
for (let p = 1; p < phaseNumber; p++) {
try {
const summaryFiles = Glob(`${sessionFolder}/phase-${p}/summary-*.md`)
for (const sf of summaryFiles) {
priorSummaries.push(Read(sf))
}
} catch {}
}
```
### Step 2: Prepare Output Directories
```javascript
Bash(`mkdir -p "${sessionFolder}/phase-${phaseNumber}/.task"`)
```
### Step 3: Delegate to action-planning-agent
```javascript
const taskDir = `${sessionFolder}/phase-${phaseNumber}/.task`
const implPlanPath = `${sessionFolder}/phase-${phaseNumber}/IMPL_PLAN.md`
const todoListPath = `${sessionFolder}/phase-${phaseNumber}/TODO_LIST.md`
Task({
subagent_type: "action-planning-agent",
run_in_background: false,
description: `Generate phase ${phaseNumber} planning documents`,
prompt: `
## TASK OBJECTIVE
Generate implementation planning documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md) for roadmap-dev session phase ${phaseNumber}.
IMPORTANT: This is PLANNING ONLY - generate planning documents, NOT implementing code.
## PHASE CONTEXT
${context}
## ROADMAP PHASE ${phaseNumber}
Goal: ${phaseGoal}
Requirements:
${requirements.map(r => `- ${r.id}: ${r.desc}`).join('\n')}
Success Criteria:
${successCriteria.map(c => `- ${c}`).join('\n')}
${isGapClosure ? `## GAP CLOSURE
This is a gap closure iteration. Only address gaps listed in context — do NOT re-plan completed work.
Existing task JSONs in ${taskDir} represent prior work. Create gap-specific tasks starting from next available ID.` : ''}
${priorSummaries.length > 0 ? `## PRIOR PHASE CONTEXT
${priorSummaries.join('\n\n---\n\n')}` : ''}
## SESSION PATHS
Output:
- Task Dir: ${taskDir}
- IMPL_PLAN: ${implPlanPath}
- TODO_LIST: ${todoListPath}
## CONTEXT METADATA
Session: ${sessionFolder}
Phase: ${phaseNumber}
Depth: ${config.depth || 'standard'}
## USER CONFIGURATION
Execution Method: agent
Preferred CLI Tool: gemini
## EXPECTED DELIVERABLES
1. Task JSON Files (${taskDir}/IMPL-*.json)
- Unified flat schema (task-schema.json)
- Quantified requirements with explicit counts
- focus_paths from context.md relevant files
- convergence criteria derived from success criteria (goal-backward)
2. Implementation Plan (${implPlanPath})
- Phase goal and context
- Task breakdown and execution strategy
- Dependency graph
3. TODO List (${todoListPath})
- Flat structure with [ ] for pending
- Links to task JSONs
## TASK ID FORMAT
Use: IMPL-{phaseNumber}{seq} (e.g., IMPL-101, IMPL-102 for phase 1)
## CONVERGENCE CRITERIA RULES (replacing old must_haves)
Each task MUST include convergence:
- criteria: Measurable conditions derived from success criteria (goal-backward, not task-forward)
- Include file existence checks
- Include export/symbol presence checks
- Include test passage checks where applicable
- verification: Executable command to verify criteria
- definition_of_done: Business-language completion definition
## CLI EXECUTION ID FORMAT
Each task: cli_execution.id = "RD-${sessionFolder.split('/').pop()}-{task_id}"
## QUALITY STANDARDS
- Task count <= 10 per phase (hard limit)
- All requirements quantified
- Acceptance criteria measurable
- Dependencies form a valid DAG (no cycles)
`
})
```
### Step 4: Validate Generated Artifacts
```javascript
// 4a. Verify task JSONs were created
const taskFiles = Glob(`${taskDir}/IMPL-*.json`)
if (!taskFiles || taskFiles.length === 0) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "error",
summary: `[planner] action-planning-agent produced no task JSONs for phase ${phaseNumber}`
})
return
}
// 4b. Validate each task JSON
for (const taskFile of taskFiles) {
const taskJson = JSON.parse(Read(taskFile))
// Required fields check
const requiredFields = ['id', 'title', 'description', 'files', 'implementation', 'convergence']
for (const field of requiredFields) {
if (!taskJson[field]) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Warning: ${taskFile} missing field: ${field}`
})
}
}
// Convergence criteria check
if (!taskJson.convergence?.criteria || taskJson.convergence.criteria.length === 0) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Warning: ${taskFile} has no convergence criteria`
})
}
// Dependency cycle check (simple: task cannot depend on itself)
if (taskJson.depends_on?.includes(taskJson.id)) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "error",
summary: `[planner] Self-dependency detected in ${taskJson.id}`
})
}
}
// 4c. Validate dependency DAG (no cycles)
const allTasks = taskFiles.map(f => JSON.parse(Read(f)))
const taskIds = new Set(allTasks.map(t => t.id))
// Check all depends_on references are valid
for (const task of allTasks) {
for (const dep of (task.depends_on || [])) {
if (!taskIds.has(dep)) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Warning: ${task.id} depends on unknown task ${dep}`
})
}
}
}
// 4d. Verify IMPL_PLAN.md exists
const implPlanExists = Bash(`test -f "${implPlanPath}" && echo "EXISTS" || echo "NOT_FOUND"`).trim()
if (implPlanExists === "NOT_FOUND") {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Warning: IMPL_PLAN.md not generated, creating minimal version`
})
// Create minimal IMPL_PLAN.md from task JSONs
generateMinimalImplPlan(allTasks, implPlanPath, phaseGoal, phaseNumber)
}
```
### Step 5: Compute Wave Structure (for reporting)
```javascript
// Derive wave structure from dependency graph (for reporting only — executor uses depends_on directly)
function computeWaves(tasks) {
const waves = {}
const assigned = new Set()
let currentWave = 1
while (assigned.size < tasks.length) {
const waveMembers = tasks.filter(t =>
!assigned.has(t.id) &&
(t.depends_on || []).every(d => assigned.has(d))
)
if (waveMembers.length === 0 && assigned.size < tasks.length) {
const unassigned = tasks.find(t => !assigned.has(t.id))
waveMembers.push(unassigned)
}
for (const task of waveMembers) {
waves[task.id] = currentWave
assigned.add(task.id)
}
currentWave++
}
return { waves, totalWaves: currentWave - 1 }
}
const { waves, totalWaves } = computeWaves(allTasks)
```
### Step 6: Report Plan Structure
```javascript
const taskCount = allTasks.length
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Created ${taskCount} tasks across ${totalWaves} waves for phase ${phaseNumber}`,
ref: `${sessionFolder}/phase-${phaseNumber}/`
})
return {
taskCount,
totalWaves,
waves,
taskFiles,
implPlanPath,
todoListPath
}
```
## Gap Closure Plans
When creating plans for gap closure (re-planning after verification found gaps):
```javascript
if (isGapClosure) {
// 1. Existing IMPL-*.json files represent completed work
// 2. action-planning-agent receives gap context and creates gap-specific tasks
// 3. New task IDs start from next available (e.g., IMPL-103 if 101,102 exist)
// 4. convergence criteria should directly address gap descriptions from verification.md
// 5. Gap tasks may depend on existing completed tasks
}
```
## Helper: Minimal IMPL_PLAN.md Generation
```javascript
function generateMinimalImplPlan(tasks, outputPath, phaseGoal, phaseNumber) {
const content = `# Implementation Plan: Phase ${phaseNumber}
## Goal
${phaseGoal}
## Tasks
${tasks.map(t => `### ${t.id}: ${t.title}
${t.description}
**Files**: ${(t.files || []).map(f => f.path).join(', ')}
**Depends on**: ${(t.depends_on || []).join(', ') || 'None'}
**Convergence Criteria**:
${(t.convergence?.criteria || []).map(c => `- ${c}`).join('\n')}
`).join('\n---\n\n')}
## Dependency Graph
${'```'}
${tasks.map(t => `${t.id} → [${(t.depends_on || []).join(', ')}]`).join('\n')}
${'```'}
`
Write(outputPath, content)
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| context.md not found | Error — research phase was skipped or failed |
| action-planning-agent fails | Retry once. If still fails, error to coordinator |
| No task JSONs generated | Error to coordinator — agent may have misunderstood input |
| Dependency cycle detected | Log warning, break cycle at lowest-numbered task |
| Too many tasks (>10) | Log warning — agent should self-limit but validate |
| Missing convergence criteria | Log warning — every task should have at least one criterion |
| IMPL_PLAN.md not generated | Create minimal version from task JSONs |

View File

@@ -0,0 +1,219 @@
# Command: research
Gather context for a phase before creating execution plans. Explores the codebase, reads requirements from roadmap, and produces a structured context.md file.
## Purpose
Build a comprehensive understanding of the phase's scope by combining roadmap requirements, prior phase outputs, and codebase analysis. The resulting context.md is the sole input for the create-plans command.
## When to Use
- Phase 2 of planner execution (after task discovery, before plan creation)
- Called once per PLAN-* task (including gap closure iterations)
## Strategy
Subagent delegation (cli-explore-agent) for codebase exploration, supplemented by optional Gemini CLI for deep analysis when depth warrants it. Planner does NOT explore the codebase directly -- it delegates.
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From PLAN-* task description | Session artifact directory |
| `phaseNumber` | From PLAN-* task description | Phase to research (1-based) |
| `depth` | From config.json or task description | "quick" / "standard" / "comprehensive" |
## Execution Steps
### Step 1: Read Roadmap and Extract Phase Requirements
```javascript
const roadmap = Read(`${sessionFolder}/roadmap.md`)
const config = JSON.parse(Read(`${sessionFolder}/config.json`))
const depth = config.depth || "standard"
// Parse phase section from roadmap
// Extract: goal, requirements (REQ-IDs), success criteria
const phaseSection = extractPhaseSection(roadmap, phaseNumber)
const phaseGoal = phaseSection.goal
const requirements = phaseSection.requirements // [{id: "REQ-101", desc: "..."}, ...]
const successCriteria = phaseSection.successCriteria // ["testable behavior 1", ...]
```
### Step 2: Read Prior Phase Context (if applicable)
```javascript
const priorContext = []
if (phaseNumber > 1) {
// Load summaries from previous phases for dependency context
for (let p = 1; p < phaseNumber; p++) {
try {
const summary = Glob(`${sessionFolder}/phase-${p}/summary-*.md`)
for (const summaryFile of summary) {
priorContext.push({
phase: p,
file: summaryFile,
content: Read(summaryFile)
})
}
} catch {
// Prior phase may not have summaries yet (first phase)
}
// Also load verification results for dependency awareness
try {
const verification = Read(`${sessionFolder}/phase-${p}/verification.md`)
priorContext.push({
phase: p,
file: `${sessionFolder}/phase-${p}/verification.md`,
content: verification
})
} catch {}
}
}
// For gap closure: load the verification that triggered re-planning
const isGapClosure = planTaskDescription.includes("Gap closure")
let gapContext = null
if (isGapClosure) {
gapContext = Read(`${sessionFolder}/phase-${phaseNumber}/verification.md`)
}
```
### Step 3: Codebase Exploration via cli-explore-agent
```javascript
// Build exploration query from requirements
const explorationQuery = requirements.map(r => r.desc).join('; ')
const exploreResult = Task({
subagent_type: "cli-explore-agent",
run_in_background: false,
description: `Explore codebase for phase ${phaseNumber} requirements`,
prompt: `Explore this codebase to gather context for the following requirements:
## Phase Goal
${phaseGoal}
## Requirements
${requirements.map(r => `- ${r.id}: ${r.desc}`).join('\n')}
## Success Criteria
${successCriteria.map(c => `- ${c}`).join('\n')}
## What to Find
1. Files that will need modification to satisfy these requirements
2. Existing patterns and conventions relevant to this work
3. Dependencies and integration points
4. Test patterns used in this project
5. Configuration or schema files that may need updates
## Output Format
Provide a structured summary:
- **Relevant Files**: List of files with brief description of relevance
- **Patterns Found**: Coding patterns, naming conventions, architecture patterns
- **Dependencies**: Internal and external dependencies that affect this work
- **Test Infrastructure**: Test framework, test file locations, test patterns
- **Risks**: Potential issues or complications discovered`
})
```
### Step 4: Optional Deep Analysis via Gemini CLI
```javascript
// Only for comprehensive depth or complex phases
if (depth === "comprehensive") {
const analysisResult = Bash({
command: `ccw cli -p "PURPOSE: Deep codebase analysis for implementation planning. Phase goal: ${phaseGoal}
TASK: \
- Analyze module boundaries and coupling for affected files \
- Identify shared utilities and helpers that can be reused \
- Map data flow through affected components \
- Assess test coverage gaps in affected areas \
- Identify backward compatibility concerns
MODE: analysis
CONTEXT: @**/* | Memory: Requirements: ${requirements.map(r => r.desc).join(', ')}
EXPECTED: Structured analysis with: module map, reuse opportunities, data flow diagram, test gaps, compatibility risks
CONSTRAINTS: Focus on files relevant to phase ${phaseNumber} requirements" \
--tool gemini --mode analysis --rule analysis-analyze-code-patterns`,
run_in_background: false,
timeout: 300000
})
// Store deep analysis result for context.md
}
```
### Step 5: Write context.md
```javascript
Bash(`mkdir -p "${sessionFolder}/phase-${phaseNumber}"`)
const contextContent = `# Phase ${phaseNumber} Context
Generated: ${new Date().toISOString().slice(0, 19)}
Session: ${sessionFolder}
Depth: ${depth}
## Phase Goal
${phaseGoal}
## Requirements
${requirements.map(r => `- **${r.id}**: ${r.desc}`).join('\n')}
## Success Criteria
${successCriteria.map(c => `- [ ] ${c}`).join('\n')}
## Prior Phase Dependencies
${priorContext.length > 0
? priorContext.map(p => `### Phase ${p.phase}\n- Source: ${p.file}\n- Key outputs: ${extractKeyOutputs(p.content)}`).join('\n\n')
: 'None (this is the first phase)'}
${isGapClosure ? `## Gap Closure Context\n\nThis is a gap closure iteration. Gaps from previous verification:\n${gapContext}` : ''}
## Relevant Files
${exploreResult.relevantFiles.map(f => `- \`${f.path}\`: ${f.description}`).join('\n')}
## Patterns Identified
${exploreResult.patterns.map(p => `- **${p.name}**: ${p.description}`).join('\n')}
## Dependencies
${exploreResult.dependencies.map(d => `- ${d}`).join('\n')}
## Test Infrastructure
${exploreResult.testInfo || 'Not analyzed (quick depth)'}
${depth === "comprehensive" && analysisResult ? `## Deep Analysis\n\n${analysisResult}` : ''}
## Questions / Risks
${exploreResult.risks.map(r => `- ${r}`).join('\n')}
`
Write(`${sessionFolder}/phase-${phaseNumber}/context.md`, contextContent)
```
## Output
| Artifact | Path | Description |
|----------|------|-------------|
| context.md | `{sessionFolder}/phase-{N}/context.md` | Structured phase context for plan creation |
## Error Handling
| Scenario | Resolution |
|----------|------------|
| roadmap.md not found | Error to coordinator via message bus |
| cli-explore-agent fails | Retry once. Fallback: use ACE search_context directly |
| Gemini CLI fails | Skip deep analysis section, proceed with basic context |
| Prior phase summaries missing | Log warning, proceed without dependency context |
| Phase section not found in roadmap | Error to coordinator -- phase number may be invalid |

View File

@@ -0,0 +1,286 @@
# Role: planner
Research and plan creation per phase. Gathers codebase context via cli-explore-agent and Gemini CLI, then generates wave-based execution plans with must_haves verification criteria. Each plan is a self-contained unit of work that an executor can implement autonomously.
## Role Identity
- **Name**: `planner`
- **Task Prefix**: `PLAN-*`
- **Responsibility**: Orchestration (research + plan generation)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[planner]`
## Role Boundaries
### MUST
- All outputs must carry `[planner]` prefix
- Only process `PLAN-*` prefixed tasks
- Only communicate with coordinator (SendMessage)
- Delegate research to commands/research.md
- Delegate plan creation to commands/create-plans.md
- Reference real files discovered during research (never fabricate paths)
- Verify plans have no dependency cycles before reporting
### MUST NOT
- Direct code writing or modification
- Call code-developer or other implementation subagents
- Create tasks for other roles (TaskCreate)
- Interact with user (AskUserQuestion)
- Process EXEC-* or VERIFY-* tasks
- Skip the research phase
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `plan_ready` | planner -> coordinator | Plans created | Plan files written with wave structure |
| `plan_progress` | planner -> coordinator | Research complete | Context gathered, starting plan creation |
| `error` | planner -> coordinator | Failure | Research or planning failed |
## Message Bus
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: messageType,
summary: `[planner] ${messageSummary}`,
ref: artifactPath
})
```
### CLI Fallback
```javascript
Bash(`ccw team log --team "roadmap-dev" --from "planner" --to "coordinator" --type "${type}" --summary "[planner] ${summary}" --json`)
```
## Toolbox
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `research` | [commands/research.md](commands/research.md) | Phase 2 | Context gathering via codebase exploration |
| `create-plans` | [commands/create-plans.md](commands/create-plans.md) | Phase 3 | Wave-based plan file generation |
### Available Subagents
| Subagent | Purpose | When |
|----------|---------|------|
| `cli-explore-agent` | Codebase exploration (file discovery, pattern analysis) | Phase 2: Research |
| `action-planning-agent` | Task JSON + IMPL_PLAN.md generation | Phase 3: Create Plans |
### CLI Tools
| Tool | Mode | When |
|------|------|------|
| `gemini` | analysis | Deep analysis for complex phases (optional, depth=comprehensive) |
## Execution
### Phase 1: Task Discovery
```javascript
// Find assigned PLAN-* task
const tasks = TaskList()
const planTask = tasks.find(t =>
t.subject.startsWith('PLAN-') &&
t.status === 'pending' &&
(!t.blockedBy || t.blockedBy.length === 0)
)
if (!planTask) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "error",
summary: "[planner] No available PLAN-* task found"
})
return
}
TaskUpdate({ taskId: planTask.id, status: "in_progress" })
// Parse task description for session context
const taskDetails = TaskGet({ taskId: planTask.id })
const sessionFolder = parseSessionFolder(taskDetails.description)
const phaseNumber = parsePhaseNumber(taskDetails.description)
const depth = parseDepth(taskDetails.description) || "standard"
```
### Phase 2: Research (via command)
```javascript
// Delegate to research command
Read("commands/research.md")
// Execute research steps:
// 1. Read roadmap.md for phase goal and requirements
// 2. Read prior phase summaries (if any)
// 3. Launch cli-explore-agent for codebase exploration
// 4. Optional: Gemini CLI for deeper analysis (if depth=comprehensive)
// 5. Write context.md to {sessionFolder}/phase-{N}/context.md
//
// Produces: {sessionFolder}/phase-{N}/context.md
```
**Command**: [commands/research.md](commands/research.md)
```javascript
// Report research progress
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Research complete for phase ${phaseNumber}. Context written.`,
ref: `${sessionFolder}/phase-${phaseNumber}/context.md`
})
```
### Phase 3: Create Plans (via command)
```javascript
// Delegate to create-plans command
Read("commands/create-plans.md")
// Execute plan creation steps:
// 1. Load context.md for phase
// 2. Prepare output directories (.task/)
// 3. Delegate to action-planning-agent
// 4. Agent produces IMPL_PLAN.md + .task/IMPL-*.json + TODO_LIST.md
// 5. Validate generated artifacts
// 6. Return task count and dependency structure
//
// Produces: {sessionFolder}/phase-{N}/IMPL_PLAN.md
// {sessionFolder}/phase-{N}/.task/IMPL-*.json
// {sessionFolder}/phase-{N}/TODO_LIST.md
```
**Command**: [commands/create-plans.md](commands/create-plans.md)
### Phase 4: Self-Validation
```javascript
// Verify task JSONs before reporting
const taskFiles = Glob(`${sessionFolder}/phase-${phaseNumber}/.task/IMPL-*.json`)
for (const taskFile of taskFiles) {
const taskJson = JSON.parse(Read(taskFile))
// 4a. Verify referenced files exist (for modify actions only)
for (const fileEntry of (taskJson.files || [])) {
if (fileEntry.action === 'modify') {
const exists = Bash(`test -f "${fileEntry.path}" && echo "EXISTS" || echo "NOT_FOUND"`).trim()
if (exists === "NOT_FOUND") {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Warning: ${taskJson.id} references ${fileEntry.path} for modify but file not found`,
ref: taskFile
})
}
}
}
// 4b. Self-dependency check
if ((taskJson.depends_on || []).includes(taskJson.id)) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "error",
summary: `[planner] Self-dependency detected: ${taskJson.id}`,
ref: taskFile
})
}
// 4c. Convergence criteria check
if (!taskJson.convergence?.criteria?.length) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Warning: ${taskJson.id} has no convergence criteria`,
ref: taskFile
})
}
}
// 4d. Cross-dependency validation
const allTasks = taskFiles.map(f => JSON.parse(Read(f)))
const taskIds = new Set(allTasks.map(t => t.id))
for (const task of allTasks) {
for (const dep of (task.depends_on || [])) {
if (!taskIds.has(dep)) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_progress",
summary: `[planner] Warning: ${task.id} depends on unknown task ${dep}`
})
}
}
}
```
### Phase 5: Report to Coordinator
```javascript
const taskCount = allTasks.length
// Compute wave count from dependency graph
function computeWaveCount(tasks) {
const waves = {}
const assigned = new Set()
let wave = 1
while (assigned.size < tasks.length) {
const ready = tasks.filter(t =>
!assigned.has(t.id) &&
(t.depends_on || []).every(d => assigned.has(d))
)
if (ready.length === 0) break
for (const t of ready) { waves[t.id] = wave; assigned.add(t.id) }
wave++
}
return wave - 1
}
const waveCount = computeWaveCount(allTasks)
// Log plan_ready message
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "planner", to: "coordinator",
type: "plan_ready",
summary: `[planner] Phase ${phaseNumber} planned: ${taskCount} tasks across ${waveCount} waves`,
ref: `${sessionFolder}/phase-${phaseNumber}/`
})
// Send message to coordinator
SendMessage({
to: "coordinator",
message: `[planner] Phase ${phaseNumber} planning complete.
- Tasks: ${taskCount}
- Waves: ${waveCount}
- IMPL_PLAN: ${sessionFolder}/phase-${phaseNumber}/IMPL_PLAN.md
- Task JSONs: ${taskFiles.map(f => f).join(', ')}
All tasks validated. Ready for execution.`
})
// Mark task complete
TaskUpdate({ taskId: planTask.id, status: "completed" })
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| roadmap.md not found | Error to coordinator -- dispatch may have failed |
| cli-explore-agent fails | Retry once. If still fails, use direct ACE search as fallback |
| Gemini CLI fails | Skip deep analysis, proceed with basic context |
| action-planning-agent fails | Retry once. If still fails, error to coordinator |
| No task JSONs generated | Error to coordinator -- agent may have misunderstood input |
| No requirements found for phase | Error to coordinator -- roadmap may be malformed |
| Dependency cycle detected | Log warning, break cycle |
| Referenced file not found | Log warning. If file is from prior wave, acceptable |

View File

@@ -0,0 +1,335 @@
# Command: verify
Goal-backward verification of convergence criteria from IMPL-*.json task files against actual codebase state. Checks convergence criteria (measurable conditions), file operations (existence/content), and runs verification commands.
## Purpose
For each task's convergence criteria, verify that the expected goals are met in the actual codebase. This is goal-backward verification: check what should exist, NOT what tasks were done. Produce a structured pass/fail result per task with gap details for any failures.
## Key Principle
**Goal-backward, not task-forward.** Do not check "did the executor follow the steps?" — check "does the codebase now have the properties that were required?"
## When to Use
- Phase 3 of verifier execution (after loading targets, before compiling results)
- Called once per VERIFY-* task
## Strategy
For each task, check convergence criteria and file operations. Use Bash for verification commands, Read/Grep for file checks, and optionally Gemini CLI for semantic validation of complex criteria.
## Parameters
| Parameter | Source | Description |
|-----------|--------|-------------|
| `sessionFolder` | From VERIFY-* task description | Session artifact directory |
| `phaseNumber` | From VERIFY-* task description | Phase number (1-based) |
| `tasks` | From verifier Phase 2 | Parsed task JSON objects with convergence criteria |
| `summaries` | From verifier Phase 2 | Parsed summary objects for context |
## Execution Steps
### Step 1: Initialize Results
```javascript
const verificationResults = []
```
### Step 2: Verify Each Task
```javascript
for (const task of tasks) {
const taskResult = {
task: task.id,
title: task.title,
status: 'pass', // will be downgraded if any check fails
details: [],
gaps: []
}
// --- 2a. Check Convergence Criteria ---
const criteria = task.convergence?.criteria || []
for (const criterion of criteria) {
const check = checkCriterion(criterion, task)
taskResult.details.push({
type: 'criterion',
description: criterion,
passed: check.passed
})
if (!check.passed) {
taskResult.gaps.push({
task: task.id,
type: 'criterion',
item: criterion,
expected: criterion,
actual: check.actual || 'Check failed'
})
}
}
// --- 2b. Check File Operations ---
const files = task.files || []
for (const fileEntry of files) {
const fileChecks = checkFileEntry(fileEntry)
for (const check of fileChecks) {
taskResult.details.push(check.detail)
if (!check.passed) {
taskResult.gaps.push({
...check.gap,
task: task.id
})
}
}
}
// --- 2c. Run Verification Command ---
if (task.convergence?.verification) {
const verifyCheck = runVerificationCommand(task.convergence.verification)
taskResult.details.push({
type: 'verification_command',
description: `Verification: ${task.convergence.verification}`,
passed: verifyCheck.passed
})
if (!verifyCheck.passed) {
taskResult.gaps.push({
task: task.id,
type: 'verification_command',
item: task.convergence.verification,
expected: 'Command exits with code 0',
actual: verifyCheck.actual || 'Command failed'
})
}
}
// --- 2d. Score task ---
const totalChecks = taskResult.details.length
const passedChecks = taskResult.details.filter(d => d.passed).length
if (passedChecks === totalChecks) {
taskResult.status = 'pass'
} else if (passedChecks > 0) {
taskResult.status = 'partial'
} else {
taskResult.status = 'fail'
}
verificationResults.push(taskResult)
}
```
### Step 3: Criterion Checking Function
```javascript
function checkCriterion(criterion, task) {
// Criteria are measurable conditions
// Strategy: derive testable assertions from criterion text
// Attempt 1: If criterion mentions a test command, run it
const testMatch = criterion.match(/test[s]?\s+(pass|run|succeed)/i)
if (testMatch) {
const testResult = Bash(`npm test 2>&1 || yarn test 2>&1 || pytest 2>&1 || true`)
const passed = !testResult.includes('FAIL') && !testResult.includes('failed')
return { passed, actual: passed ? 'Tests pass' : 'Test failures detected' }
}
// Attempt 2: If criterion mentions specific counts or exports, check files
const filePaths = (task.files || []).map(f => f.path)
for (const filePath of filePaths) {
const exists = Bash(`test -f "${filePath}" && echo "EXISTS" || echo "NOT_FOUND"`).trim()
if (exists === "EXISTS") {
const content = Read(filePath)
// Check if criterion keywords appear in the implementation
const keywords = criterion.split(/\s+/).filter(w => w.length > 4)
const relevant = keywords.filter(kw =>
content.toLowerCase().includes(kw.toLowerCase())
)
if (relevant.length >= Math.ceil(keywords.length * 0.3)) {
return { passed: true, actual: 'Implementation contains relevant logic' }
}
}
}
// Attempt 3: Compile check for affected files
for (const filePath of filePaths) {
if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
const compileCheck = Bash(`npx tsc --noEmit "${filePath}" 2>&1 || true`)
if (compileCheck.includes('error TS')) {
return { passed: false, actual: `TypeScript errors in ${filePath}` }
}
}
}
// Default: mark as passed if files exist and compile
return { passed: true, actual: 'Files exist and compile without errors' }
}
```
### Step 4: File Entry Checking Function
```javascript
function checkFileEntry(fileEntry) {
const checks = []
const path = fileEntry.path
const action = fileEntry.action // create, modify, delete
// 4a. Check file existence based on action
const exists = Bash(`test -f "${path}" && echo "EXISTS" || echo "NOT_FOUND"`).trim()
if (action === 'create' || action === 'modify') {
checks.push({
passed: exists === "EXISTS",
detail: {
type: 'file',
description: `File exists: ${path} (${action})`,
passed: exists === "EXISTS"
},
gap: exists !== "EXISTS" ? {
type: 'file',
item: `file_exists: ${path}`,
expected: `File should exist (action: ${action})`,
actual: 'File not found'
} : null
})
if (exists !== "EXISTS") {
return checks.filter(c => c.gap !== null || c.passed)
}
// 4b. Check minimum content (non-empty for create)
if (action === 'create') {
const content = Read(path)
const lineCount = content.split('\n').length
const minLines = 3 // Minimum for a meaningful file
checks.push({
passed: lineCount >= minLines,
detail: {
type: 'file',
description: `${path}: has content (${lineCount} lines)`,
passed: lineCount >= minLines
},
gap: lineCount < minLines ? {
type: 'file',
item: `min_content: ${path}`,
expected: `>= ${minLines} lines`,
actual: `${lineCount} lines`
} : null
})
}
} else if (action === 'delete') {
checks.push({
passed: exists === "NOT_FOUND",
detail: {
type: 'file',
description: `File deleted: ${path}`,
passed: exists === "NOT_FOUND"
},
gap: exists !== "NOT_FOUND" ? {
type: 'file',
item: `file_deleted: ${path}`,
expected: 'File should be deleted',
actual: 'File still exists'
} : null
})
}
return checks.filter(c => c.gap !== null || c.passed)
}
```
### Step 5: Verification Command Runner
```javascript
function runVerificationCommand(command) {
try {
const result = Bash(`${command} 2>&1; echo "EXIT:$?"`)
const exitCodeMatch = result.match(/EXIT:(\d+)/)
const exitCode = exitCodeMatch ? parseInt(exitCodeMatch[1]) : 1
return {
passed: exitCode === 0,
actual: exitCode === 0 ? 'Command succeeded' : `Exit code: ${exitCode}\n${result.slice(0, 200)}`
}
} catch (e) {
return { passed: false, actual: `Command error: ${e.message}` }
}
}
```
### Step 6: Write verification.md
```javascript
const totalGaps = verificationResults.flatMap(r => r.gaps)
const overallStatus = totalGaps.length === 0 ? 'passed' : 'gaps_found'
Write(`${sessionFolder}/phase-${phaseNumber}/verification.md`, `---
phase: ${phaseNumber}
status: ${overallStatus}
tasks_checked: ${tasks.length}
tasks_passed: ${verificationResults.filter(r => r.status === 'pass').length}
gaps:
${totalGaps.map(g => ` - task: "${g.task}"
type: "${g.type}"
item: "${g.item}"
expected: "${g.expected}"
actual: "${g.actual}"`).join('\n')}
---
# Phase ${phaseNumber} Verification
## Summary
- **Status**: ${overallStatus}
- **Tasks Checked**: ${tasks.length}
- **Passed**: ${verificationResults.filter(r => r.status === 'pass').length}
- **Partial**: ${verificationResults.filter(r => r.status === 'partial').length}
- **Failed**: ${verificationResults.filter(r => r.status === 'fail').length}
- **Total Gaps**: ${totalGaps.length}
## Task Results
${verificationResults.map(r => `### ${r.task}: ${r.title}${r.status.toUpperCase()}
${r.details.map(d => `- [${d.passed ? 'x' : ' '}] (${d.type}) ${d.description}`).join('\n')}`).join('\n\n')}
${totalGaps.length > 0 ? `## Gaps for Re-Planning
The following gaps must be addressed in a gap closure iteration:
${totalGaps.map((g, i) => `### Gap ${i + 1}
- **Task**: ${g.task}
- **Type**: ${g.type}
- **Item**: ${g.item}
- **Expected**: ${g.expected}
- **Actual**: ${g.actual}`).join('\n\n')}` : '## All Goals Met'}
`)
```
## Verification Checklist
### Convergence Criteria
| Check Method | Tool | When |
|--------------|------|------|
| Run tests | Bash(`npm test`) | Criterion mentions "test" |
| Compile check | Bash(`npx tsc --noEmit`) | TypeScript files |
| Keyword match | Read + string match | General behavioral criteria |
| Verification command | Bash(convergence.verification) | Always if provided |
| Semantic check | Gemini CLI (analysis) | Complex criteria (optional) |
### File Operations
| Check | Tool | What |
|-------|------|------|
| File exists (create/modify) | Bash(`test -f`) | files[].path with action create/modify |
| File deleted | Bash(`test -f`) | files[].path with action delete |
| Minimum content | Read + line count | Newly created files |
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No task JSON files found | Error to coordinator -- planner may have failed |
| No summary files found | Error to coordinator -- executor may have failed |
| Verification command fails | Record as gap with error output |
| File referenced in task missing | Record as gap (file type) |
| Task JSON malformed (no convergence) | Log warning, score as pass (nothing to check) |
| All checks for a task fail | Score as 'fail', include all gaps |

View File

@@ -0,0 +1,267 @@
# Role: verifier
Goal-backward verification per phase. Reads convergence criteria from IMPL-*.json task files and checks them against the actual codebase state after execution. Does NOT modify code — read-only validation. Produces verification.md with pass/fail results and structured gap lists.
## Role Identity
- **Name**: `verifier`
- **Task Prefix**: `VERIFY-*`
- **Responsibility**: Validation
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[verifier]`
## Role Boundaries
### MUST
- All outputs must carry `[verifier]` prefix
- Only process `VERIFY-*` prefixed tasks
- Only communicate with coordinator (SendMessage)
- Delegate verification to commands/verify.md
- Check goals (what should exist), NOT tasks (what was done)
- Produce structured gap lists for failed items
- Remain read-only -- never modify source code
### MUST NOT
- Modify any source code or project files
- Create plans or execute implementations
- Create tasks for other roles (TaskCreate)
- Interact with user (AskUserQuestion)
- Process PLAN-* or EXEC-* tasks
- Auto-fix issues (report them, let planner/executor handle fixes)
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `verify_passed` | verifier -> coordinator | All must_haves met | Phase verification passed |
| `gaps_found` | verifier -> coordinator | Some must_haves failed | Structured gap list for re-planning |
| `error` | verifier -> coordinator | Failure | Verification process failed |
## Message Bus
```javascript
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "verifier", to: "coordinator",
type: messageType,
summary: `[verifier] ${messageSummary}`,
ref: artifactPath
})
```
### CLI Fallback
```javascript
Bash(`ccw team log --team "roadmap-dev" --from "verifier" --to "coordinator" --type "${type}" --summary "[verifier] ${summary}" --json`)
```
## Toolbox
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `verify` | [commands/verify.md](commands/verify.md) | Phase 3 | Goal-backward must_haves checking |
### Available Subagents
None. Verifier executes checks directly using built-in tools (Read, Grep, Bash).
### CLI Tools
| Tool | Mode | When |
|------|------|------|
| `gemini` | analysis | Deep semantic checks for complex truths (optional) |
## Execution
### Phase 1: Task Discovery
```javascript
// Find assigned VERIFY-* task
const tasks = TaskList()
const verifyTask = tasks.find(t =>
t.subject.startsWith('VERIFY-') &&
t.status === 'pending' &&
(!t.blockedBy || t.blockedBy.length === 0)
)
if (!verifyTask) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "verifier", to: "coordinator",
type: "error",
summary: "[verifier] No available VERIFY-* task found"
})
return
}
TaskUpdate({ taskId: verifyTask.id, status: "in_progress" })
// Parse task description for session context
const taskDetails = TaskGet({ taskId: verifyTask.id })
const sessionFolder = parseSessionFolder(taskDetails.description)
const phaseNumber = parsePhaseNumber(taskDetails.description)
```
### Phase 2: Load Verification Targets
```javascript
// Read all task JSON files for convergence criteria
const taskFiles = Glob(`${sessionFolder}/phase-${phaseNumber}/.task/IMPL-*.json`)
const tasks = []
for (const taskFile of taskFiles) {
const taskJson = JSON.parse(Read(taskFile))
tasks.push({
...taskJson,
file: taskFile
})
}
// Read all summary files for what was done
const summaryFiles = Glob(`${sessionFolder}/phase-${phaseNumber}/summary-*.md`)
const summaries = []
for (const summaryFile of summaryFiles) {
const content = Read(summaryFile)
const frontmatter = parseYamlFrontmatter(content)
summaries.push({
file: summaryFile,
task: frontmatter.task,
affects: frontmatter.affects || frontmatter['key-files'] || [],
provides: frontmatter.provides || []
})
}
if (tasks.length === 0) {
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "verifier", to: "coordinator",
type: "error",
summary: `[verifier] No task JSON files found in ${sessionFolder}/phase-${phaseNumber}/.task/`
})
return
}
```
### Phase 3: Goal-Backward Verification (via command)
```javascript
// Delegate to verify command
Read("commands/verify.md")
// Execute goal-backward verification:
// 1. For each task's convergence criteria: check criteria, files, verification command
// 2. Score each task: pass / partial / fail
// 3. Compile gap list
//
// Produces: verificationResults (structured data)
```
**Command**: [commands/verify.md](commands/verify.md)
### Phase 4: Compile Results
```javascript
// Aggregate pass/fail per task
const results = {
totalTasks: tasks.length,
passed: 0,
partial: 0,
failed: 0,
gaps: []
}
for (const taskResult of verificationResults) {
if (taskResult.status === 'pass') {
results.passed++
} else if (taskResult.status === 'partial') {
results.partial++
results.gaps.push(...taskResult.gaps)
} else {
results.failed++
results.gaps.push(...taskResult.gaps)
}
}
const overallStatus = results.gaps.length === 0 ? 'passed' : 'gaps_found'
```
### Phase 5: Write verification.md + Report
```javascript
const verificationPath = `${sessionFolder}/phase-${phaseNumber}/verification.md`
Write(verificationPath, `---
phase: ${phaseNumber}
status: ${overallStatus}
tasks_checked: ${results.totalTasks}
tasks_passed: ${results.passed}
gaps:
${results.gaps.map(g => ` - task: "${g.task}"
type: "${g.type}"
item: "${g.item}"
expected: "${g.expected}"
actual: "${g.actual}"`).join('\n')}
---
# Phase ${phaseNumber} Verification
## Summary
- **Status**: ${overallStatus}
- **Tasks Checked**: ${results.totalTasks}
- **Passed**: ${results.passed}
- **Partial**: ${results.partial}
- **Failed**: ${results.failed}
- **Total Gaps**: ${results.gaps.length}
## Task Results
${verificationResults.map(r => `### ${r.task}: ${r.title}${r.status.toUpperCase()}
${r.details.map(d => `- [${d.passed ? 'x' : ' '}] (${d.type}) ${d.description}`).join('\n')}`).join('\n\n')}
${results.gaps.length > 0 ? `## Gaps
${results.gaps.map((g, i) => `### Gap ${i + 1}: ${g.task} - ${g.type}
- **Expected**: ${g.expected}
- **Actual**: ${g.actual}
- **Item**: ${g.item}`).join('\n\n')}` : '## No Gaps Found'}
`)
const messageType = overallStatus === 'passed' ? 'verify_passed' : 'gaps_found'
mcp__ccw-tools__team_msg({
operation: "log", team: "roadmap-dev",
from: "verifier", to: "coordinator",
type: messageType,
summary: `[verifier] Phase ${phaseNumber} verification: ${overallStatus}. ${results.passed}/${results.totalTasks} tasks passed. ${results.gaps.length} gaps.`,
ref: verificationPath
})
SendMessage({
to: "coordinator",
message: `[verifier] Phase ${phaseNumber} verification complete.
- Status: ${overallStatus}
- Tasks: ${results.passed}/${results.totalTasks} passed
- Gaps: ${results.gaps.length}
${results.gaps.length > 0 ? `\nGap summary:\n${results.gaps.map(g => `- ${g.task}, ${g.type}: ${g.item}`).join('\n')}` : ''}
Verification written to: ${verificationPath}`
})
TaskUpdate({ taskId: verifyTask.id, status: "completed" })
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No task JSON files found | Error to coordinator -- planner may have failed |
| No summary files found | Error to coordinator -- executor may have failed |
| File referenced in task missing | Record as gap (file type) |
| Bash command fails during check | Record as gap with error message |
| Verification command fails | Record as gap with exit code |
| Gemini CLI fails | Fallback to direct checks, skip semantic analysis |

View File

@@ -0,0 +1,96 @@
{
"team_name": "roadmap-dev",
"team_display_name": "Roadmap Dev",
"skill_name": "team-roadmap-dev",
"skill_path": ".claude/skills/team-roadmap-dev/",
"design_source": "roadmap-driven development workflow design (2026-02-24)",
"pipeline_type": "Phased",
"pipeline": {
"stages": [
{ "name": "PLAN", "role": "planner", "blockedBy": [] },
{ "name": "EXEC", "role": "executor", "blockedBy": ["PLAN"] },
{ "name": "VERIFY", "role": "verifier", "blockedBy": ["EXEC"] }
],
"diagram": "Coordinator (roadmap) → PLAN → EXEC → VERIFY → Coordinator (transition)",
"gap_closure": "VERIFY fails → PLAN (gaps) → EXEC (gaps) → VERIFY (re-check), max 3 iterations"
},
"roles": [
{
"name": "coordinator",
"display_name": "RD Coordinator",
"responsibility_type": "Orchestration",
"task_prefix": null,
"description": "Human interaction, roadmap discussion, phase transitions, state management",
"commands": ["roadmap-discuss", "dispatch", "monitor", "pause", "resume"],
"message_types": ["phase_started", "phase_complete", "gap_closure", "project_complete", "error"]
},
{
"name": "planner",
"display_name": "RD Planner",
"responsibility_type": "Orchestration",
"task_prefix": "PLAN",
"description": "Research, context gathering, task JSON generation via action-planning-agent",
"commands": ["research", "create-plans"],
"subagents": ["cli-explore-agent", "action-planning-agent"],
"cli_tools": [{"tool": "gemini", "mode": "analysis"}],
"message_types": ["plan_ready", "plan_progress", "error"]
},
{
"name": "executor",
"display_name": "RD Executor",
"responsibility_type": "Code generation",
"task_prefix": "EXEC",
"description": "Code implementation from IMPL-*.json tasks, wave-based parallel execution",
"commands": ["implement"],
"subagents": ["code-developer"],
"message_types": ["exec_complete", "exec_progress", "error"]
},
{
"name": "verifier",
"display_name": "RD Verifier",
"responsibility_type": "Validation",
"task_prefix": "VERIFY",
"description": "Convergence criteria verification, gap detection, fix loop trigger",
"commands": ["verify"],
"cli_tools": [{"tool": "gemini", "mode": "analysis"}],
"message_types": ["verify_passed", "gaps_found", "error"]
}
],
"artifacts": {
"fixed": {
"roadmap.md": {
"created_by": "coordinator (roadmap-discuss)",
"purpose": "Phase plan with requirements and success criteria",
"lifecycle": "Created once, updated at phase transitions"
},
"state.md": {
"created_by": "coordinator",
"purpose": "Living memory (<100 lines)",
"lifecycle": "Updated every significant action"
},
"config.json": {
"created_by": "coordinator (roadmap-discuss)",
"purpose": "Session settings: mode, depth, gates",
"lifecycle": "Created once, rarely updated"
}
},
"dynamic": {
"context.md": { "created_by": "planner (research)", "per": "phase" },
"IMPL_PLAN.md": { "created_by": "planner (create-plans)", "per": "phase", "purpose": "Implementation overview with task dependency graph" },
"IMPL-*.json": { "created_by": "planner (create-plans)", "per": "phase", "path": ".task/", "schema": "unified-flat-schema", "purpose": "Task JSON files with convergence criteria" },
"TODO_LIST.md": { "created_by": "planner (create-plans)", "per": "phase", "purpose": "Checklist tracking for all tasks" },
"summary-{ID}.md": { "created_by": "executor (implement)", "per": "task", "yaml_frontmatter": true },
"verification.md": { "created_by": "verifier (verify)", "per": "phase" }
}
},
"init_prerequisite": {
"required_files": [".workflow/project-tech.json"],
"optional_files": [".workflow/project-guidelines.json"],
"init_command": "/workflow:init"
},
"_metadata": {
"created_at": "2026-02-24",
"version": "1.1.0",
"based_on": "roadmap-driven development workflow design"
}
}