feat(skills): update 12 team skills to v3 design patterns

- Update all 12 team-* SKILL.md files with v3 structure:
  - Replace JS pseudocode with text decision tables
  - Add Role Registry with Compact column
  - Add COMPACT PROTECTION blocks
  - Add Cadence Control sections
  - Add Wisdom Accumulation sections
  - Add Task Metadata Registry
  - Add Orchestration Mode user commands

- Update 58 role files (SKILL.md + roles/*):
  - Flat-file skills: team-brainstorm, team-issue, team-testing,
    team-uidesign, team-planex, team-iterdev
  - Folder-based skills: team-review, team-roadmap-dev, team-frontend,
    team-quality-assurance, team-tech-debt, team-ultra-analyze

- Preserve special architectures:
  - team-planex: 2-member (planner + executor only)
  - team-tech-debt: Stop-Wait strategy (run_in_background:false)
  - team-iterdev: 7 behavior protocol tables in coordinator

- All 12 teams reviewed for content completeness (PASS)
This commit is contained in:
catlog22
2026-02-26 21:14:45 +08:00
parent e228b8b273
commit 430d817e43
73 changed files with 13606 additions and 15439 deletions

View File

@@ -6,160 +6,160 @@ allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), Task
# Team Issue Resolution
Unified team skill for issue processing pipeline. All team members invoke this skill with `--role=xxx` for role-specific execution.
Unified team skill: issue processing pipeline (explore → plan → implement → review → integrate). All team members invoke with `--role=xxx` to route to role-specific execution.
**Scope**: Issue 处理流程(plan → queue → execute)。Issue 创建/发现由 `issue-discover` 独立处理CRUD 管理由 `issue-manage` 独立处理。
**Scope**: Issue processing flow (plan → queue → execute). Issue creation/discovery handled by `issue-discover`, CRUD management by `issue-manage`.
## Architecture Overview
## Architecture
```
┌───────────────────────────────────────────┐
│ Skill(skill="team-issue") │
│ args="--role=xxx [issue-ids] [--mode=M]"
└───────────────┬───────────────────────────┘
│ Role Router
┌───────────┼───────────┬───────────┬───────────┬───────────┐
↓ ↓
┌──────────┐┌──────────┐┌──────────┐┌──────────┐┌──────────┐┌──────────┐
│coordinator││explorer ││planner ││reviewer ││integrator││implementer│
│ 编排调度 ││EXPLORE-* ││SOLVE-* ││AUDIT-* ││MARSHAL-* ││BUILD-* │
└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘
┌───────────────────────────────────────────────
│ Skill(skill="team-issue")
│ args="<issue-ids>" or args="--role=xxx"
└───────────────────┬───────────────────────────┘
│ Role Router
┌──── --role present? ────┐
│ NO │ YES
↓ ↓
Orchestration Mode Role Dispatch
(auto → coordinator) (route to role.md)
┌────┴────┬───────────┬───────────┬───────────┬───────────┐
↓ ↓ ↓ ↓ ↓ ↓
┌──────────┐┌─────────┐┌─────────┐┌─────────┐┌──────────┐┌──────────┐
│coordinator││explorer ││planner ││reviewer ││integrator││implementer│
│ ││EXPLORE-*││SOLVE-* ││AUDIT-* ││MARSHAL-* ││BUILD-* │
└──────────┘└─────────┘└─────────┘└─────────┘└──────────┘└──────────┘
```
## Command Architecture
```
roles/
├── coordinator.md # Pipeline 编排(Phase 1/5 inline, Phase 2-4 core logic
├── explorer.md # 上下文分析(ACE + cli-explore-agent
├── planner.md # 方案设计(wraps issue-plan-agent
├── reviewer.md # 方案审查(技术可行性 + 风险评估)
├── integrator.md # 队列编排(wraps issue-queue-agent
└── implementer.md # 代码实现(wraps code-developer
├── coordinator.md # Pipeline orchestration (Phase 1/5 inline, Phase 2-4 core logic)
├── explorer.md # Context analysis (ACE + cli-explore-agent)
├── planner.md # Solution design (wraps issue-plan-agent)
├── reviewer.md # Solution review (technical feasibility + risk assessment)
├── integrator.md # Queue orchestration (wraps issue-queue-agent)
└── implementer.md # Code implementation (wraps code-developer)
```
## Role Router
### Input Parsing
Parse `$ARGUMENTS` to extract `--role`:
Parse `$ARGUMENTS` to extract `--role`. If absent → Orchestration Mode (auto route to coordinator). Extract issue IDs and `--mode` from remaining arguments.
```javascript
const args = "$ARGUMENTS"
const roleMatch = args.match(/--role[=\s]+(\w+)/)
### Role Registry
if (!roleMatch) {
// No --role: this is a coordinator entry point
// Extract issue IDs and mode from args directly
// → Read roles/coordinator.md and execute
Read("roles/coordinator.md")
return
}
| Role | File | Task Prefix | Type | Compact |
|------|------|-------------|------|---------|
| coordinator | [roles/coordinator.md](roles/coordinator.md) | (none) | orchestrator | **⚠️ 压缩后必须重读** |
| explorer | [roles/explorer.md](roles/explorer.md) | EXPLORE-* | pipeline | 压缩后必须重读 |
| planner | [roles/planner.md](roles/planner.md) | SOLVE-* | pipeline | 压缩后必须重读 |
| reviewer | [roles/reviewer.md](roles/reviewer.md) | AUDIT-* | pipeline | 压缩后必须重读 |
| integrator | [roles/integrator.md](roles/integrator.md) | MARSHAL-* | pipeline | 压缩后必须重读 |
| implementer | [roles/implementer.md](roles/implementer.md) | BUILD-* | pipeline | 压缩后必须重读 |
const role = roleMatch[1]
const teamName = "issue"
const agentName = args.match(/--agent-name[=\s]+([\w-]+)/)?.[1] || role
> **⚠️ COMPACT PROTECTION**: 角色文件是执行文档,不是参考资料。当 context compression 发生后,角色指令仅剩摘要时,**必须立即 `Read` 对应 role.md 重新加载后再继续执行**。不得基于摘要执行任何 Phase。
### Dispatch
1. Extract `--role` from arguments
2. If no `--role` → route to coordinator (Orchestration Mode)
3. Look up role in registry → Read the role file → Execute its phases
### Orchestration Mode
When invoked without `--role`, coordinator auto-starts. User provides issue IDs and optional mode.
**Invocation**: `Skill(skill="team-issue", args="<issue-ids> [--mode=<mode>]")`
**Lifecycle**:
```
User provides issue IDs
→ coordinator Phase 1-3: Mode detection → TeamCreate → Create task chain
→ coordinator Phase 4: spawn first batch workers (background) → STOP
→ Worker executes → SendMessage callback → coordinator advances next step
→ Loop until pipeline complete → Phase 5 report
```
### Role Dispatch
**User Commands** (wake paused coordinator):
```javascript
const VALID_ROLES = {
"coordinator": { file: "roles/coordinator.md", prefix: null },
"explorer": { file: "roles/explorer.md", prefix: "EXPLORE" },
"planner": { file: "roles/planner.md", prefix: "SOLVE" },
"reviewer": { file: "roles/reviewer.md", prefix: "AUDIT" },
"integrator": { file: "roles/integrator.md", prefix: "MARSHAL" },
"implementer": { file: "roles/implementer.md", prefix: "BUILD" }
}
| Command | Action |
|---------|--------|
| `check` / `status` | Output execution status graph, no advancement |
| `resume` / `continue` | Check worker states, advance next step |
if (!VALID_ROLES[role]) {
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
}
// Read and execute role-specific logic
Read(VALID_ROLES[role].file)
// → Execute the 5-phase process defined in that file
```
### Available Roles
| Role | Task Prefix | Responsibility | Reuses Agent | Role File |
|------|-------------|----------------|--------------|-----------|
| `coordinator` | N/A | Pipeline 编排、模式选择、任务分派 | - | [roles/coordinator.md](roles/coordinator.md) |
| `explorer` | EXPLORE-* | 上下文分析、影响面评估 | cli-explore-agent | [roles/explorer.md](roles/explorer.md) |
| `planner` | SOLVE-* | 方案设计、任务分解 | issue-plan-agent | [roles/planner.md](roles/planner.md) |
| `reviewer` | AUDIT-* | 方案审查、风险评估 | - (新角色) | [roles/reviewer.md](roles/reviewer.md) |
| `integrator` | MARSHAL-* | 冲突检测、队列编排 | issue-queue-agent | [roles/integrator.md](roles/integrator.md) |
| `implementer` | BUILD-* | 代码实现、结果提交 | code-developer | [roles/implementer.md](roles/implementer.md) |
---
## Shared Infrastructure
The following templates apply to all worker roles. Each role.md only needs to write **Phase 2-4** role-specific logic.
### Worker Phase 1: Task Discovery (shared by all workers)
Every worker executes the same task discovery flow on startup:
1. Call `TaskList()` to get all tasks
2. Filter: subject matches this role's prefix + owner is this role + status is pending + blockedBy is empty
3. No tasks → idle wait
4. Has tasks → `TaskGet` for details → `TaskUpdate` mark in_progress
**Resume Artifact Check** (prevent duplicate output after resume):
- Check whether this task's output artifact already exists
- Artifact complete → skip to Phase 5 report completion
- Artifact incomplete or missing → normal Phase 2-4 execution
### Worker Phase 5: Report (shared by all workers)
Standard reporting flow after task completion:
1. **Message Bus**: Call `mcp__ccw-tools__team_msg` to log message
- Parameters: operation="log", team="issue", from=<role>, to="coordinator", type=<message-type>, summary="[<role>] <summary>", ref=<artifact-path>
- **CLI fallback**: When MCP unavailable → `ccw team log --team issue --from <role> --to coordinator --type <type> --summary "[<role>] ..." --json`
2. **SendMessage**: Send result to coordinator (content and summary both prefixed with `[<role>]`)
3. **TaskUpdate**: Mark task completed
4. **Loop**: Return to Phase 1 to check next task
### Wisdom Accumulation (all roles)
Cross-task knowledge accumulation. Coordinator creates `wisdom/` directory at session initialization.
**Directory**:
```
<session-folder>/wisdom/
├── learnings.md # Patterns and insights
├── decisions.md # Architecture and design decisions
├── conventions.md # Codebase conventions
└── issues.md # Known risks and issues
```
**Worker Load** (Phase 2): Extract `Session: <path>` from task description, read wisdom directory files.
**Worker Contribute** (Phase 4/5): Write this task's discoveries to corresponding wisdom files.
### Role Isolation Rules
**核心原则**: 每个角色仅能执行自己职责范围内的工作。
| Allowed | Forbidden |
|---------|-----------|
| Process tasks with own prefix | Process tasks with other role prefixes |
| SendMessage to coordinator | Communicate directly with other workers |
| Use tools declared in Toolbox | Create tasks for other roles |
| Delegate to reused agents | Modify resources outside own responsibility |
#### Output Tagging强制
Coordinator additional restrictions: Do not write/modify code directly, do not call implementation subagents (issue-plan-agent etc.), do not execute analysis/review directly.
所有角色的输出必须带 `[role_name]` 标识前缀:
### Output Tagging
```javascript
// SendMessage — content 和 summary 都必须带标识
SendMessage({
content: `## [${role}] ...`,
summary: `[${role}] ...`
})
// team_msg — summary 必须带标识
mcp__ccw-tools__team_msg({
summary: `[${role}] ...`
})
```
#### Coordinator 隔离
| 允许 | 禁止 |
|------|------|
| 需求澄清 (AskUserQuestion) | ❌ 直接编写/修改代码 |
| 创建任务链 (TaskCreate) | ❌ 调用 issue-plan-agent 等实现类 agent |
| 分发任务给 worker | ❌ 直接执行分析/审查 |
| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成任务 |
| 汇报结果给用户 | ❌ 修改源代码或产物文件 |
#### Worker 隔离
| 允许 | 禁止 |
|------|------|
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
| 使用 Toolbox 中声明的工具 | ❌ 为其他角色创建任务 (TaskCreate) |
| 委派给复用的 agent | ❌ 修改不属于本职责的资源 |
### Team Configuration
```javascript
const TEAM_CONFIG = {
name: "issue",
sessionDir: ".workflow/.team-plan/issue/",
issueDataDir: ".workflow/issues/"
}
```
All outputs must carry `[role_name]` prefix in both SendMessage content/summary and team_msg summary.
### Message Bus (All Roles)
Every SendMessage **before**, must call `mcp__ccw-tools__team_msg` to log:
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: role, // current role name
to: "coordinator",
type: "<type>",
summary: "[role] <summary>",
ref: "<file_path>" // optional
})
```
**Parameters**: operation="log", team="issue", from=<role>, to="coordinator", type=<message-type>, summary="[<role>] <summary>", ref=<artifact-path>
**CLI fallback**: When MCP unavailable → `ccw team log --team issue --from <role> --to coordinator --type <type> --summary "[<role>] ..." --json`
**Message types by role**:
@@ -172,38 +172,15 @@ mcp__ccw-tools__team_msg({
| integrator | `queue_ready`, `conflict_found`, `error` |
| implementer | `impl_complete`, `impl_failed`, `error` |
### CLI 回退
### Team Configuration
`mcp__ccw-tools__team_msg` MCP 不可用时:
| Setting | Value |
|---------|-------|
| Team name | issue |
| Session directory | `.workflow/.team-plan/issue/` |
| Issue data directory | `.workflow/issues/` |
```javascript
Bash(`ccw team log --team "issue" --from "${role}" --to "coordinator" --type "<type>" --summary "<摘要>" --json`)
```
### Task Lifecycle (All Roles)
```javascript
// Standard task lifecycle every role follows
// Phase 1: Discovery
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
t.owner === agentName && // Use agentName (e.g., 'explorer-1') instead of role
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
// Phase 2-4: Role-specific (see roles/{role}.md)
// Phase 5: Report + Loop — 所有输出必须带 [role] 标识
mcp__ccw-tools__team_msg({ operation: "log", team: "issue", from: role, to: "coordinator", type: "...", summary: `[${role}] ...` })
SendMessage({ type: "message", recipient: "coordinator", content: `## [${role}] ...`, summary: `[${role}] ...` })
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task → back to Phase 1
```
---
## Pipeline Modes
@@ -216,247 +193,221 @@ Full Mode (complex issues, with review):
└─(rejected)→ SOLVE-fix → AUDIT-002(re-review, max 2x)
Batch Mode (5-100 issues):
EXPLORE-001..N(batch5) → SOLVE-001..N(batch3) → AUDIT-001(batch) → MARSHAL-001 → BUILD-001..M(DAG parallel)
EXPLORE-001..N(batch<=5) → SOLVE-001..N(batch<=3) → AUDIT-001(batch) → MARSHAL-001 → BUILD-001..M(DAG parallel)
```
### Mode Auto-Detection
```javascript
function detectMode(issueIds, userMode) {
if (userMode) return userMode // 用户显式指定
When user does not specify `--mode`, auto-detect based on issue count and complexity:
| Condition | Mode | Description |
|-----------|------|-------------|
| User explicitly specifies `--mode=<M>` | Use specified mode | User override takes priority |
| Issue count <= 2 AND no high-priority issues (priority < 4) | `quick` | Simple issues, skip review step |
| Issue count <= 2 AND has high-priority issues (priority >= 4) | `full` | Complex issues need review gate |
| Issue count > 2 | `batch` | Multiple issues, parallel exploration and implementation |
### Review Gate (Full/Batch modes)
| AUDIT Verdict | Action |
|---------------|--------|
| approved | Proceed to MARSHAL → BUILD |
| rejected (round < 2) | Create SOLVE-fix task → AUDIT re-review |
| rejected (round >= 2) | Force proceed with warnings, report to user |
### Cadence Control
**Beat model**: Event-driven, each beat = coordinator wake → process → spawn → STOP. Issue beat: explore → plan → implement → review → integrate.
const count = issueIds.length
if (count <= 2) {
// Check complexity via issue priority
const issues = issueIds.map(id => JSON.parse(Bash(`ccw issue status ${id} --json`)))
const hasHighPriority = issues.some(i => i.priority >= 4)
return hasHighPriority ? 'full' : 'quick'
}
return 'batch'
}
```
Beat Cycle (single beat)
═══════════════════════════════════════════════════════════
Event Coordinator Workers
───────────────────────────────────────────────────────────
callback/resume ──→ ┌─ handleCallback ─┐
│ mark completed │
│ check pipeline │
├─ handleSpawnNext ─┤
│ find ready tasks │
│ spawn workers ───┼──→ [Worker A] Phase 1-5
│ (parallel OK) ──┼──→ [Worker B] Phase 1-5
└─ STOP (idle) ─────┘ │
callback ←─────────────────────────────────────────┘
(next beat) SendMessage + TaskUpdate(completed)
═══════════════════════════════════════════════════════════
```
**Pipeline beat views**:
```
Quick Mode (4 beats, strictly serial)
──────────────────────────────────────────────────────────
Beat 1 2 3 4
│ │ │ │
EXPLORE → SOLVE → MARSHAL ──→ BUILD
▲ ▲
pipeline pipeline
start done
EXPLORE=explorer SOLVE=planner MARSHAL=integrator BUILD=implementer
Full Mode (5-7 beats, with review gate)
──────────────────────────────────────────────────────────
Beat 1 2 3 4 5
│ │ │ │ │
EXPLORE → SOLVE → AUDIT ─┬─(ok)→ MARSHAL → BUILD
(rejected?)
SOLVE-fix → AUDIT-2 → MARSHAL → BUILD
Batch Mode (parallel windows)
──────────────────────────────────────────────────────────
Beat 1 2 3 4 5
┌────┴────┐ ┌────┴────┐ │ │ ┌────┴────┐
EXP-1..N → SOLVE-1..N → AUDIT → MARSHAL → BUILD-1..M
▲ ▲
parallel DAG parallel
window (<=5) window (<=3)
```
**Checkpoints**:
| Trigger | Location | Behavior |
|---------|----------|----------|
| Review gate | After AUDIT-* | If approved → MARSHAL; if rejected → SOLVE-fix (max 2 rounds) |
| Review loop limit | AUDIT round >= 2 | Force proceed with warnings |
| Pipeline stall | No ready + no running | Check missing tasks, report to user |
**Stall Detection** (coordinator `handleCheck` executes):
| Check | Condition | Resolution |
|-------|-----------|------------|
| Worker no response | in_progress task no callback | Report waiting task list, suggest user `resume` |
| Pipeline deadlock | no ready + no running + has pending | Check blockedBy dependency chain, report blocking point |
| Review loop exceeded | AUDIT rejection > 2 rounds | Terminate loop, force proceed with current solution |
### Task Metadata Registry
| Task ID | Role | Phase | Dependencies | Description |
|---------|------|-------|-------------|-------------|
| EXPLORE-001 | explorer | explore | (none) | Context analysis and impact assessment |
| EXPLORE-002..N | explorer | explore | (none) | Parallel exploration (Batch mode only) |
| SOLVE-001 | planner | plan | EXPLORE-001 (or all EXPLORE-*) | Solution design and task decomposition |
| SOLVE-002..N | planner | plan | EXPLORE-* | Parallel solution design (Batch mode only) |
| AUDIT-001 | reviewer | review | SOLVE-001 (or all SOLVE-*) | Technical feasibility and risk review |
| MARSHAL-001 | integrator | integrate | AUDIT-001 (or last SOLVE-*) | Conflict detection and queue orchestration |
| BUILD-001 | implementer | implement | MARSHAL-001 | Code implementation and result submission |
| BUILD-002..M | implementer | implement | MARSHAL-001 | Parallel implementation (Batch DAG parallel) |
---
## Coordinator Spawn Template
```javascript
TeamCreate({ team_name: "issue" })
When coordinator spawns workers, use background mode (Spawn-and-Stop).
// Explorer — conditional parallel spawn for Batch mode
const isBatchMode = mode === 'batch'
const maxParallelExplorers = Math.min(issueIds.length, 5)
**Standard spawn** (single agent per role): For Quick/Full mode, spawn one agent per role. Explorer, planner, reviewer, integrator each get a single agent.
if (isBatchMode && issueIds.length > 1) {
// Batch mode: spawn N explorers for parallel exploration
for (let i = 0; i < maxParallelExplorers; i++) {
const agentName = `explorer-${i + 1}`
Task({
subagent_type: "general-purpose",
description: `Spawn issue worker`,
team_name: "issue",
name: agentName,
prompt: `你是 team "issue" 的 EXPLORER (${agentName})。
你的 agent 名称是 "${agentName}",任务发现时用此名称匹配 owner。
**Parallel spawn** (Batch mode): For Batch mode with multiple issues, spawn N explorer agents in parallel (max 5) and M implementer agents in parallel (max 3). Each parallel agent only processes tasks where owner matches its agent name.
当你收到 EXPLORE-* 任务时,调用 Skill(skill="team-issue", args="--role=explorer --agent-name=${agentName}") 执行。
**Spawn template**:
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 owner 为 "${agentName}" 的 EXPLORE-* 前缀任务
- 所有输出SendMessage、team_msg必须带 [explorer] 标识前缀
- 仅与 coordinator 通信,不得直接联系其他 worker
- 不得使用 TaskCreate 为其他角色创建任务
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 owner === "${agentName}" 的 EXPLORE-* 任务
2. Skill(skill="team-issue", args="--role=explorer --agent-name=${agentName}") 执行
3. team_msg log + SendMessage 结果给 coordinator带 [explorer] 标识)
4. TaskUpdate completed → 检查下一个任务`
})
}
} else {
// Quick/Full mode: single explorer
Task({
subagent_type: "general-purpose",
description: `Spawn issue worker`,
team_name: "issue",
name: "explorer",
prompt: `你是 team "issue" 的 EXPLORER。
当你收到 EXPLORE-* 任务时,调用 Skill(skill="team-issue", args="--role=explorer") 执行。
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 EXPLORE-* 前缀的任务,不得执行其他角色的工作
- 所有输出SendMessage、team_msg必须带 [explorer] 标识前缀
- 仅与 coordinator 通信,不得直接联系其他 worker
- 不得使用 TaskCreate 为其他角色创建任务
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 EXPLORE-* 任务
2. Skill(skill="team-issue", args="--role=explorer") 执行
3. team_msg log + SendMessage 结果给 coordinator带 [explorer] 标识)
4. TaskUpdate completed → 检查下一个任务`
})
}
// Planner
```
Task({
subagent_type: "general-purpose",
description: `Spawn issue worker`,
description: "Spawn <role> worker",
team_name: "issue",
name: "planner",
prompt: `你是 team "issue" 的 PLANNER。
name: "<role>",
run_in_background: true,
prompt: `You are team "issue" <ROLE>.
当你收到 SOLVE-* 任务时,调用 Skill(skill="team-issue", args="--role=planner") 执行。
## Primary Directive
All your work must be executed through Skill to load role definition:
Skill(skill="team-issue", args="--role=<role>")
当前需求: ${taskDescription}
约束: ${constraints}
Current requirement: <task-description>
Session: <session-folder>
## 角色准则(强制)
- 你只能处理 SOLVE-* 前缀的任务
- 所有输出必须带 [planner] 标识前缀
- 仅与 coordinator 通信
## Role Guidelines
- Only process <PREFIX>-* tasks, do not execute other role work
- All output prefixed with [<role>] identifier
- Only communicate with coordinator
- Do not use TaskCreate for other roles
- Call mcp__ccw-tools__team_msg before every SendMessage
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 SOLVE-* 任务
2. Skill(skill="team-issue", args="--role=planner") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
## Workflow
1. Call Skill -> load role definition and execution logic
2. Follow role.md 5-Phase flow
3. team_msg + SendMessage results to coordinator
4. TaskUpdate completed -> check next task`
})
```
// Reviewer
### Parallel Spawn (Batch Mode)
> When Batch mode has parallel tasks assigned to the same role, spawn N distinct agents with unique names. A single agent can only process tasks serially.
**Explorer parallel spawn** (Batch mode, N issues):
| Condition | Action |
|-----------|--------|
| Batch mode with N issues (N > 1) | Spawn min(N, 5) agents: `explorer-1`, `explorer-2`, ... with `run_in_background: true` |
| Quick/Full mode (single explorer) | Standard spawn: single `explorer` agent |
**Implementer parallel spawn** (Batch mode, M BUILD tasks):
| Condition | Action |
|-----------|--------|
| Batch mode with M BUILD tasks (M > 2) | Spawn min(M, 3) agents: `implementer-1`, `implementer-2`, ... with `run_in_background: true` |
| Quick/Full mode (single implementer) | Standard spawn: single `implementer` agent |
**Parallel spawn template**:
```
Task({
subagent_type: "general-purpose",
description: `Spawn issue worker`,
description: "Spawn <role>-<N> worker",
team_name: "issue",
name: "reviewer",
prompt: `你是 team "issue" 的 REVIEWER。
name: "<role>-<N>",
run_in_background: true,
prompt: `You are team "issue" <ROLE> (<role>-<N>).
Your agent name is "<role>-<N>", use this name for task discovery owner matching.
当你收到 AUDIT-* 任务时,调用 Skill(skill="team-issue", args="--role=reviewer") 执行。
## Primary Directive
Skill(skill="team-issue", args="--role=<role> --agent-name=<role>-<N>")
当前需求: ${taskDescription}
约束: ${constraints}
## Role Guidelines
- Only process tasks where owner === "<role>-<N>" with <PREFIX>-* prefix
- All output prefixed with [<role>] identifier
## 角色准则(强制)
- 你只能处理 AUDIT-* 前缀的任务
- 所有输出必须带 [reviewer] 标识前缀
- 仅与 coordinator 通信
- 你是质量门控角色,审查方案但不修改代码
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 AUDIT-* 任务
2. Skill(skill="team-issue", args="--role=reviewer") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
## Workflow
1. TaskList -> find tasks where owner === "<role>-<N>" with <PREFIX>-* prefix
2. Skill -> execute role definition
3. team_msg + SendMessage results to coordinator
4. TaskUpdate completed -> check next task`
})
```
// Integrator
Task({
subagent_type: "general-purpose",
description: `Spawn issue worker`,
team_name: "issue",
name: "integrator",
prompt: `你是 team "issue" 的 INTEGRATOR。
**Dispatch must match agent names**: When dispatching parallel tasks, coordinator sets each task's owner to the corresponding instance name (`explorer-1`, `explorer-2`, etc. or `implementer-1`, `implementer-2`, etc.). In role.md, task discovery uses `--agent-name` for owner matching.
当你收到 MARSHAL-* 任务时,调用 Skill(skill="team-issue", args="--role=integrator") 执行。
---
当前需求: ${taskDescription}
约束: ${constraints}
## Session Directory
## 角色准则(强制)
- 你只能处理 MARSHAL-* 前缀的任务
- 所有输出必须带 [integrator] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 MARSHAL-* 任务
2. Skill(skill="team-issue", args="--role=integrator") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
// Implementer — conditional parallel spawn for Batch mode (DAG parallel BUILD tasks)
if (isBatchMode && issueIds.length > 2) {
// Batch mode: spawn multiple implementers for parallel BUILD execution
const maxParallelBuilders = Math.min(issueIds.length, 3)
for (let i = 0; i < maxParallelBuilders; i++) {
const agentName = `implementer-${i + 1}`
Task({
subagent_type: "general-purpose",
description: `Spawn issue worker`,
team_name: "issue",
name: agentName,
prompt: `你是 team "issue" 的 IMPLEMENTER (${agentName})。
你的 agent 名称是 "${agentName}",任务发现时用此名称匹配 owner。
当你收到 BUILD-* 任务时,调用 Skill(skill="team-issue", args="--role=implementer --agent-name=${agentName}") 执行。
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 owner 为 "${agentName}" 的 BUILD-* 前缀任务
- 所有输出必须带 [implementer] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 owner === "${agentName}" 的 BUILD-* 任务
2. Skill(skill="team-issue", args="--role=implementer --agent-name=${agentName}") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
}
} else {
// Quick/Full mode: single implementer
Task({
subagent_type: "general-purpose",
description: `Spawn issue worker`,
team_name: "issue",
name: "implementer",
prompt: `你是 team "issue" 的 IMPLEMENTER。
当你收到 BUILD-* 任务时,调用 Skill(skill="team-issue", args="--role=implementer") 执行。
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 BUILD-* 前缀的任务
- 所有输出必须带 [implementer] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 BUILD-* 任务
2. Skill(skill="team-issue", args="--role=implementer") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
}
```
.workflow/.team-plan/issue/
├── team-session.json # Session state
├── shared-memory.json # Cross-role state
├── wisdom/ # Cross-task knowledge
│ ├── learnings.md
│ ├── decisions.md
│ ├── conventions.md
│ └── issues.md
├── explorations/ # Explorer output
├── solutions/ # Planner output
├── audits/ # Reviewer output
├── queue/ # Integrator output
└── builds/ # Implementer output
```
## Error Handling
@@ -464,6 +415,8 @@ if (isBatchMode && issueIds.length > 2) {
| Scenario | Resolution |
|----------|------------|
| Unknown --role value | Error with available role list |
| Missing --role arg | Default to coordinator role |
| Role file not found | Error with expected path (roles/{name}.md) |
| Missing --role arg | Orchestration Mode → auto route to coordinator |
| Role file not found | Error with expected path (roles/<name>.md) |
| Task prefix conflict | Log warning, proceed |
| Review rejection exceeds 2 rounds | Force proceed with warnings |
| No issues found for given IDs | Coordinator reports error to user |

View File

@@ -1,319 +1,286 @@
# Role: coordinator
# Coordinator Role
Team coordinator. Orchestrates the issue resolution pipeline: requirement clarification mode selection team creation task chain dispatch monitoring reporting.
Orchestrate the issue resolution pipeline: requirement clarification -> mode selection -> team creation -> task chain -> dispatch -> monitoring -> reporting.
## Role Identity
## Identity
- **Name**: `coordinator`
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
- **Name**: `coordinator` | **Tag**: `[coordinator]`
- **Task Prefix**: N/A (coordinator creates tasks, does not receive them)
- **Responsibility**: Orchestration
- **Communication**: SendMessage to all teammates
- **Output Tag**: `[coordinator]`
## Role Boundaries
## Boundaries
### MUST
- 所有输出(SendMessageteam_msg、日志)必须带 `[coordinator]` 标识
- 仅负责需求澄清、模式选择、任务创建/分发、进度监控、结果汇报
- 通过 TaskCreate 创建任务并分配给 worker 角色
- 通过消息总线监控 worker 进度并路由消息
- All output (SendMessage, team_msg, logs) must carry `[coordinator]` identifier
- Responsible only for: requirement clarification, mode selection, task creation/dispatch, progress monitoring, result reporting
- Create tasks via TaskCreate and assign to worker roles
- Monitor worker progress via message bus and route messages
- Parse user requirements and clarify ambiguous inputs via AskUserQuestion
- Maintain session state persistence
- Dispatch tasks with proper dependency chains (see SKILL.md Task Metadata Registry)
### MUST NOT
- **直接执行任何业务任务**(代码编写、方案设计、审查等)
- ❌ 直接调用 issue-plan-agentissue-queue-agentcode-developer 等 agent
- ❌ 直接修改源代码或生成产物文件
- ❌ 绕过 worker 角色自行完成应委派的工作
- ❌ 在输出中省略 `[coordinator]` 标识
- Execute any business tasks directly (code writing, solution design, review, etc.)
- Call implementation subagents directly (issue-plan-agent, issue-queue-agent, code-developer, etc.)
- Modify source code or generated artifacts directly
- Bypass worker roles to complete delegated work
- Omit `[coordinator]` identifier in any output
- Skip dependency validation when creating task chains
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
> **Core principle**: coordinator is the orchestrator, not the executor. All actual work must be delegated to worker roles via TaskCreate.
---
## Toolbox
### Available Commands
> No command files -- all phases execute inline.
### Tool Capabilities
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `TeamCreate` | Team | coordinator | Initialize team |
| `TeamDelete` | Team | coordinator | Dissolve team |
| `SendMessage` | Team | coordinator | Communicate with workers/user |
| `TaskCreate` | Task | coordinator | Create and dispatch tasks |
| `TaskList` | Task | coordinator | Monitor task status |
| `TaskGet` | Task | coordinator | Get task details |
| `TaskUpdate` | Task | coordinator | Update task status |
| `AskUserQuestion` | UI | coordinator | Clarify requirements |
| `Read` | IO | coordinator | Read session files |
| `Write` | IO | coordinator | Write session files |
| `Bash` | System | coordinator | Execute ccw commands |
| `mcp__ccw-tools__team_msg` | Team | coordinator | Log messages to message bus |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `task_assigned` | coordinator worker | Task dispatched | 通知 worker 有新任务 |
| `pipeline_update` | coordinator user | Progress milestone | 流水线进度更新 |
| `escalation` | coordinator user | Unresolvable issue | 升级到用户决策 |
| `shutdown` | coordinator all | Team dissolved | 团队关闭 |
| `task_assigned` | coordinator -> worker | Task dispatched | Notify worker of new task |
| `pipeline_update` | coordinator -> user | Progress milestone | Pipeline progress update |
| `escalation` | coordinator -> user | Unresolvable issue | Escalate to user decision |
| `shutdown` | coordinator -> all | Team dissolved | Team shutdown notification |
## Execution
## Message Bus
### Phase 0: Session Resume
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```javascript
// Check for existing team session
const existingMsgs = mcp__ccw-tools__team_msg({ operation: "list", team: "issue" })
if (existingMsgs && existingMsgs.length > 0) {
// Resume: check pending tasks and continue coordination loop
// Skip Phase 1-3, go directly to Phase 4
}
```
### Phase 1: Requirement Clarification
Parse `$ARGUMENTS` for issue IDs and mode.
```javascript
const args = "$ARGUMENTS"
// Extract issue IDs (GH-xxx, ISS-xxx formats)
const issueIds = args.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || []
// Extract mode
const modeMatch = args.match(/--mode[=\s]+(quick|full|batch)/)
const explicitMode = modeMatch ? modeMatch[1] : null
// If --all-pending, load all pending issues
if (args.includes('--all-pending')) {
const pendingList = Bash(`ccw issue list --status registered,pending --json`)
const pending = JSON.parse(pendingList)
issueIds.push(...pending.map(i => i.id))
}
if (issueIds.length === 0) {
// Ask user for issue IDs
const answer = AskUserQuestion({
questions: [{
question: "请提供要处理的 issue ID支持多个逗号分隔",
header: "Issue IDs",
multiSelect: false,
options: [
{ label: "输入 ID", description: "手动输入 issue IDGH-123 或 ISS-20260215-120000" },
{ label: "全部 pending", description: "处理所有 registered/pending 状态的 issue" }
]
}]
})
}
// Auto-detect mode
const mode = detectMode(issueIds, explicitMode)
// Execution method selection (for BUILD phase)
const execSelection = AskUserQuestion({
questions: [
{
question: "选择代码执行方式:",
header: "Execution",
multiSelect: false,
options: [
{ label: "Agent", description: "code-developer agent同步适合简单任务" },
{ label: "Codex", description: "Codex CLI后台适合复杂任务" },
{ label: "Gemini", description: "Gemini CLI后台适合分析类任务" },
{ label: "Auto", description: "根据 solution task_count 自动选择(默认)" }
]
},
{
question: "实现后是否进行代码审查?",
header: "Code Review",
multiSelect: false,
options: [
{ label: "Skip", description: "不审查" },
{ label: "Gemini Review", description: "Gemini CLI 审查" },
{ label: "Codex Review", description: "Git-aware review--uncommitted" }
]
}
]
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "coordinator",
to: "<recipient>",
type: <message-type>,
summary: "[coordinator] <summary>",
ref: <artifact-path>
})
const executionMethod = execSelection.Execution || 'Auto'
const codeReviewTool = execSelection['Code Review'] || 'Skip'
```
**Mode Auto-Detection**:
```javascript
function detectMode(issueIds, userMode) {
if (userMode) return userMode
const count = issueIds.length
if (count <= 2) {
const issues = issueIds.map(id => JSON.parse(Bash(`ccw issue status ${id} --json`)))
const hasHighPriority = issues.some(i => i.priority >= 4)
return hasHighPriority ? 'full' : 'quick'
}
// 3-4 issues with review, 5+ triggers batch parallel processing
return count >= 5 ? 'batch' : 'full'
}
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team issue --from coordinator --to <recipient> --type <message-type> --summary \"[coordinator] ...\" --json")
```
### Phase 2: Create Team + Initialize Session
---
```javascript
TeamCreate({ team_name: "issue" })
## Entry Router
// ⚠️ Workers are NOT pre-spawned here.
// Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
//
// Worker roles available (spawned on-demand per pipeline stage):
// quick mode: explorer, planner, integrator, implementer
// full mode: explorer, planner, reviewer, integrator, implementer
When coordinator is invoked, first detect the invocation type:
| Detection | Condition | Handler |
|-----------|-----------|---------|
| Worker callback | Message contains `[role-name]` tag from a known worker role | -> handleCallback: auto-advance pipeline |
| Status check | Arguments contain "check" or "status" | -> handleCheck: output execution graph, no advancement |
| Manual resume | Arguments contain "resume" or "continue" | -> handleResume: check worker states, advance pipeline |
| New session | None of the above | -> Phase 0 (Session Resume Check) |
For callback/check/resume: execute the appropriate handler, then STOP.
---
## Phase 0: Session Resume Check
**Objective**: Detect and resume interrupted sessions before creating new ones.
**Workflow**:
1. Check for existing team session via team_msg list
2. No sessions found -> proceed to Phase 1
3. Single session found -> resume it (-> Session Reconciliation)
4. Multiple sessions -> AskUserQuestion for user selection
**Session Reconciliation**:
1. Audit TaskList -> get real status of all tasks
2. Reconcile: session state <-> TaskList status (bidirectional sync)
3. Reset any in_progress tasks -> pending (they were interrupted)
4. Determine remaining pipeline from reconciled state
5. Rebuild team if disbanded (TeamCreate + spawn needed workers only)
6. Create missing tasks with correct blockedBy dependencies
7. Verify dependency chain integrity
8. Update session file with reconciled state
9. Kick first executable task's worker -> Phase 4
---
## Phase 1: Requirement Clarification
**Objective**: Parse user input and gather execution parameters.
**Workflow**:
1. **Parse arguments** for issue IDs and mode:
| Pattern | Extraction |
|---------|------------|
| `GH-\d+` | GitHub issue ID |
| `ISS-\d{8}-\d{6}` | Local issue ID |
| `--mode=<mode>` | Explicit mode |
| `--all-pending` | Load all pending issues |
2. **Load pending issues** if `--all-pending`:
```
Bash("ccw issue list --status registered,pending --json")
```
### Phase 3: Create Task Chain
3. **Ask for missing parameters** via AskUserQuestion if no issue IDs found
**Quick Mode**:
```javascript
// EXPLORE → SOLVE → MARSHAL → BUILD
for (const issueId of issueIds) {
const exploreId = TaskCreate({
subject: `EXPLORE-001: Analyze context for ${issueId}`,
description: `Explore codebase context for issue ${issueId}. Load issue via ccw issue status ${issueId} --json, then perform ACE semantic search and impact analysis.`,
activeForm: `Exploring ${issueId}`,
owner: "explorer"
})
4. **Mode auto-detection** (when user does not specify `--mode`):
const solveId = TaskCreate({
subject: `SOLVE-001: Design solution for ${issueId}`,
description: `Design solution for issue ${issueId} using issue-plan-agent. Context report from EXPLORE-001.`,
activeForm: `Planning ${issueId}`,
owner: "planner",
addBlockedBy: [exploreId]
})
| Condition | Mode |
|-----------|------|
| Issue count <= 2 AND no high-priority (priority < 4) | `quick` |
| Issue count <= 2 AND has high-priority (priority >= 4) | `full` |
| Issue count >= 5 | `batch` |
| 3-4 issues | `full` |
const marshalId = TaskCreate({
subject: `MARSHAL-001: Form queue for ${issueId}`,
description: `Form execution queue for issue ${issueId} solution using issue-queue-agent.`,
activeForm: `Forming queue`,
owner: "integrator",
addBlockedBy: [solveId]
})
5. **Execution method selection** (for BUILD phase):
TaskCreate({
subject: `BUILD-001: Implement solution for ${issueId}`,
description: `Implement solution for issue ${issueId}. Load via ccw issue detail <item-id>, execute tasks, report via ccw issue done.\nexecution_method: ${executionMethod}\ncode_review: ${codeReviewTool}`,
activeForm: `Implementing ${issueId}`,
owner: "implementer",
addBlockedBy: [marshalId]
})
}
```
| Option | Description |
|--------|-------------|
| `Agent` | code-developer agent (sync, for simple tasks) |
| `Codex` | Codex CLI (background, for complex tasks) |
| `Gemini` | Gemini CLI (background, for analysis tasks) |
| `Auto` | Auto-select based on solution task_count (default) |
**Full Mode** (adds AUDIT between SOLVE and MARSHAL):
```javascript
for (const issueId of issueIds) {
const exploreId = TaskCreate({
subject: `EXPLORE-001: Analyze context for ${issueId}`,
description: `Explore codebase context for issue ${issueId}.`,
activeForm: `Exploring ${issueId}`,
owner: "explorer"
})
6. **Code review selection**:
const solveId = TaskCreate({
subject: `SOLVE-001: Design solution for ${issueId}`,
description: `Design solution for issue ${issueId} using issue-plan-agent.`,
activeForm: `Planning ${issueId}`,
owner: "planner",
addBlockedBy: [exploreId]
})
| Option | Description |
|--------|-------------|
| `Skip` | No review |
| `Gemini Review` | Gemini CLI review |
| `Codex Review` | Git-aware review (--uncommitted) |
const auditId = TaskCreate({
subject: `AUDIT-001: Review solution for ${issueId}`,
description: `Review solution quality, technical feasibility, and risks for issue ${issueId}. Read solution from .workflow/issues/solutions/${issueId}.jsonl.`,
activeForm: `Reviewing ${issueId}`,
owner: "reviewer",
addBlockedBy: [solveId]
})
**Success**: All parameters captured, mode finalized.
const marshalId = TaskCreate({
subject: `MARSHAL-001: Form queue for ${issueId}`,
description: `Form execution queue after review approval.`,
activeForm: `Forming queue`,
owner: "integrator",
addBlockedBy: [auditId]
})
---
TaskCreate({
subject: `BUILD-001: Implement solution for ${issueId}`,
description: `Implement approved solution for issue ${issueId}.\nexecution_method: ${executionMethod}\ncode_review: ${codeReviewTool}`,
activeForm: `Implementing ${issueId}`,
owner: "implementer",
addBlockedBy: [marshalId]
})
}
```
## Phase 2: Create Team + Initialize Session
**Batch Mode** (parallel EXPLORE and SOLVE batches):
```javascript
// Group issues into batches
const exploreBatches = chunkArray(issueIds, 5) // max 5 parallel
const solveBatches = chunkArray(issueIds, 3) // max 3 parallel
const maxParallelExplorers = Math.min(issueIds.length, 5)
const maxParallelBuilders = Math.min(issueIds.length, 3)
**Objective**: Initialize team, session file, and wisdom directory.
// Create EXPLORE tasks — distribute across parallel explorer agents (round-robin)
const exploreTaskIds = []
let prevBatchLastId = null
for (const [batchIdx, batch] of exploreBatches.entries()) {
const batchTaskIds = []
for (const [inBatchIdx, issueId] of batch.entries()) {
const globalIdx = exploreTaskIds.length
const explorerName = `explorer-${(globalIdx % maxParallelExplorers) + 1}`
const id = TaskCreate({
subject: `EXPLORE-${String(globalIdx + 1).padStart(3, '0')}: Context for ${issueId}`,
description: `Batch ${batchIdx + 1}: Explore codebase context for issue ${issueId}.`,
activeForm: `Exploring ${issueId}`,
owner: explorerName, // Distribute across explorer-1, explorer-2, etc.
// Only block on previous batch's LAST task (not within same batch)
addBlockedBy: prevBatchLastId ? [prevBatchLastId] : []
})
batchTaskIds.push(id)
exploreTaskIds.push(id)
}
prevBatchLastId = batchTaskIds[batchTaskIds.length - 1]
}
**Workflow**:
// Create SOLVE tasks (blocked by corresponding EXPLORE)
const solveTaskIds = []
for (const [i, issueId] of issueIds.entries()) {
const id = TaskCreate({
subject: `SOLVE-${String(i + 1).padStart(3, '0')}: Solution for ${issueId}`,
description: `Design solution for issue ${issueId}.`,
activeForm: `Planning ${issueId}`,
owner: "planner",
addBlockedBy: [exploreTaskIds[i]]
})
solveTaskIds.push(id)
}
1. Generate session ID
2. Create session folder
3. Call TeamCreate with team name "issue"
4. Initialize wisdom directory (learnings.md, decisions.md, conventions.md, issues.md)
5. Write session file with: session_id, mode, scope, status="active"
// AUDIT as batch review (blocked by all SOLVE tasks)
const auditId = TaskCreate({
subject: `AUDIT-001: Batch review all solutions`,
description: `Review all ${issueIds.length} solutions for quality and conflicts.`,
activeForm: `Batch reviewing`,
owner: "reviewer",
addBlockedBy: solveTaskIds
})
**Spawn template**: Workers are NOT pre-spawned here. Workers are spawned on-demand in Phase 4. See SKILL.md Coordinator Spawn Template for worker prompt templates.
// MARSHAL (blocked by AUDIT)
const marshalId = TaskCreate({
subject: `MARSHAL-001: Form execution queue`,
description: `Form DAG-based execution queue for all approved solutions.`,
activeForm: `Forming queue`,
owner: "integrator",
addBlockedBy: [auditId]
})
**Worker roles available**:
// BUILD tasks created dynamically after MARSHAL completes (based on DAG)
// Each BUILD-* task is assigned to implementer-1, implementer-2, etc. (round-robin)
// Each BUILD-* task description MUST include:
// execution_method: ${executionMethod}
// code_review: ${codeReviewTool}
```
- quick mode: explorer, planner, integrator, implementer
- full mode: explorer, planner, reviewer, integrator, implementer
- batch mode: parallel explorers (max 5), parallel implementers (max 3)
### Phase 4: Coordination Loop
**Success**: Team created, session file written, wisdom initialized.
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
---
Receive teammate messages, dispatch based on type.
## Phase 3: Create Task Chain
**Objective**: Dispatch tasks based on mode with proper dependencies.
### Quick Mode (4 beats, strictly serial)
Create task chain for each issue: EXPLORE -> SOLVE -> MARSHAL -> BUILD
| Task ID | Role | Dependencies | Description |
|---------|------|--------------|-------------|
| EXPLORE-001 | explorer | (none) | Context analysis |
| SOLVE-001 | planner | EXPLORE-001 | Solution design |
| MARSHAL-001 | integrator | SOLVE-001 | Queue formation |
| BUILD-001 | implementer | MARSHAL-001 | Code implementation |
### Full Mode (5-7 beats, with review gate)
Add AUDIT between SOLVE and MARSHAL:
| Task ID | Role | Dependencies | Description |
|---------|------|--------------|-------------|
| EXPLORE-001 | explorer | (none) | Context analysis |
| SOLVE-001 | planner | EXPLORE-001 | Solution design |
| AUDIT-001 | reviewer | SOLVE-001 | Solution review |
| MARSHAL-001 | integrator | AUDIT-001 | Queue formation |
| BUILD-001 | implementer | MARSHAL-001 | Code implementation |
### Batch Mode (parallel windows)
Create parallel task batches:
| Batch | Tasks | Parallel Limit |
|-------|-------|----------------|
| EXPLORE-001..N | explorer | max 5 parallel |
| SOLVE-001..N | planner | sequential |
| AUDIT-001 | reviewer | (all SOLVE complete) |
| MARSHAL-001 | integrator | (AUDIT complete) |
| BUILD-001..M | implementer | max 3 parallel |
**Task description must include**: execution_method, code_review settings from Phase 1.
---
## Phase 4: Spawn-and-Stop
**Objective**: Spawn first batch of ready workers in background, then STOP.
**Design**: Spawn-and-Stop + Callback pattern.
- Spawn workers with `Task(run_in_background: true)` -> immediately return
- Worker completes -> SendMessage callback -> auto-advance
- User can use "check" / "resume" to manually advance
- Coordinator does one operation per invocation, then STOPS
**Workflow**:
1. Find tasks with: status=pending, blockedBy all resolved, owner assigned
2. For each ready task -> spawn worker (see SKILL.md Spawn Template)
3. Output status summary
4. STOP
**Pipeline advancement** driven by three wake sources:
| Wake Source | Handler | Action |
|-------------|---------|--------|
| Worker callback | handleCallback | Auto-advance next step |
| User "check" | handleCheck | Status output only |
| User "resume" | handleResume | Advance pipeline |
### Message Handlers
| Received Message | Action |
|-----------------|--------|
|------------------|--------|
| `context_ready` from explorer | Unblock SOLVE-* tasks for this issue |
| `solution_ready` from planner | Quick: create MARSHAL-*; Full: create AUDIT-* |
| `multi_solution` from planner | AskUserQuestion for solution selection, then ccw issue bind |
@@ -323,74 +290,38 @@ Receive teammate messages, dispatch based on type.
| `queue_ready` from integrator | Create BUILD-* tasks based on DAG parallel batches |
| `conflict_found` from integrator | AskUserQuestion for conflict resolution |
| `impl_complete` from implementer | Refresh DAG, create next BUILD-* batch or complete |
| `impl_failed` from implementer | CP-5 escalation: retry / skip / abort |
| `error` from any worker | Assess severity retry or escalate to user |
| `impl_failed` from implementer | Escalation: retry / skip / abort |
| `error` from any worker | Assess severity -> retry or escalate to user |
**Review-Fix Cycle (CP-2)**max 2 rounds:
```javascript
let auditRound = 0
const MAX_AUDIT_ROUNDS = 2
### Review-Fix Cycle (max 2 rounds)
// On rejected message:
if (msg.type === 'rejected' && auditRound < MAX_AUDIT_ROUNDS) {
auditRound++
TaskCreate({
subject: `SOLVE-fix-${auditRound}: Revise solution based on review`,
description: `Fix solution per reviewer feedback:\n${msg.data.findings}\n\nThis is revision round ${auditRound}/${MAX_AUDIT_ROUNDS}.`,
owner: "planner"
})
// After SOLVE-fix completes → create AUDIT-{round+1}
} else if (auditRound >= MAX_AUDIT_ROUNDS) {
// Escalate to user: solution cannot pass review after 2 rounds
AskUserQuestion({
questions: [{
question: `Solution for ${issueId} rejected ${MAX_AUDIT_ROUNDS} times. How to proceed?`,
header: "Escalation",
options: [
{ label: "Force approve", description: "Skip review, proceed to execution" },
{ label: "Manual fix", description: "User will fix the solution" },
{ label: "Skip issue", description: "Skip this issue, continue with others" }
]
}]
})
}
```
| Round | Rejected Action |
|-------|-----------------|
| Round 1 | Create SOLVE-fix-1 task with reviewer feedback |
| Round 2 | Create SOLVE-fix-2 task with reviewer feedback |
| Round 3+ | Escalate to user: Force approve / Manual fix / Skip issue |
### Phase 5: Report + Handoff
---
```javascript
// Summarize results
const summary = {
mode,
issues_processed: issueIds.length,
solutions_approved: approvedCount,
builds_completed: completedBuilds,
builds_failed: failedBuilds
}
## Phase 5: Report + Next Steps
// Report to user
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "coordinator",
to: "user", type: "pipeline_update",
summary: `[coordinator] Pipeline complete: ${summary.issues_processed} issues processed`
})
**Objective**: Completion report and follow-up options.
// Ask for next action
AskUserQuestion({
questions: [{
question: "Issue 处理完成。下一步:",
header: "Next",
multiSelect: false,
options: [
{ label: "新一批 issue", description: "提交新的 issue ID 给当前团队处理" },
{ label: "查看结果", description: "查看实现结果和 git 变更" },
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
]
}]
})
// 新一批 → 回到 Phase 1
// 关闭 → shutdown → TeamDelete()
```
**Workflow**:
1. Load session state -> count completed tasks, duration
2. List deliverables with output paths
3. Update session status -> "completed"
4. Log via team_msg
5. Offer next steps to user:
| Option | Action |
|--------|--------|
| New batch | Return to Phase 1 with new issue IDs |
| View results | Show implementation results and git changes |
| Close team | TeamDelete() and cleanup |
---
## Error Handling
@@ -398,7 +329,12 @@ AskUserQuestion({
|----------|------------|
| No issue IDs provided | AskUserQuestion for IDs |
| Issue not found | Skip with warning, continue others |
| Worker unresponsive | Send follow-up, 2x respawn |
| Review rejected 2+ times | Escalate to user (CP-5 L3) |
| Worker unresponsive | Send follow-up, 2x -> respawn |
| Review rejected 2+ times | Escalate to user |
| Build failed | Retry once, then escalate |
| All workers error | Shutdown team, report to user |
| Task timeout | Log, mark failed, ask user to retry or skip |
| Worker crash | Respawn worker, reassign task |
| Dependency cycle | Detect, report to user, halt |
| Invalid mode | Reject with error, ask to clarify |
| Session corruption | Attempt recovery, fallback to manual reconciliation |

View File

@@ -1,134 +1,149 @@
# Role: explorer
# Explorer Role
Issue 上下文分析、代码探索、依赖识别、影响面评估。为 planner 和 reviewer 提供共享的 context report。
Issue context analysis, codebase exploration, dependency identification, impact assessment. Produces shared context report for planner and reviewer.
## Role Identity
## Identity
- **Name**: `explorer`
- **Name**: `explorer` | **Tag**: `[explorer]`
- **Task Prefix**: `EXPLORE-*`
- **Responsibility**: Orchestration (context gathering)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[explorer]`
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `EXPLORE-*` 前缀的任务
- 所有输出必须带 `[explorer]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 产出 context-report 供后续角色(planner, reviewer)使用
- Only process `EXPLORE-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[explorer]` identifier
- Only communicate with coordinator via SendMessage
- Produce context-report for subsequent roles (planner, reviewer)
- Work strictly within context gathering responsibility scope
### MUST NOT
- ❌ 设计解决方案planner 职责)
- ❌ 审查方案质量reviewer 职责)
- ❌ 修改任何源代码
- ❌ 直接与其他 worker 通信
- ❌ 为其他角色创建任务
- Design solutions (planner responsibility)
- Review solution quality (reviewer responsibility)
- Modify any source code
- Communicate directly with other worker roles
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
- Omit `[explorer]` identifier in any output
---
## Toolbox
### Available Commands
> No command files -- all phases execute inline.
### Tool Capabilities
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `Task` | Subagent | explorer | Spawn cli-explore-agent for deep exploration |
| `Read` | IO | explorer | Read context files and issue data |
| `Write` | IO | explorer | Write context report |
| `Bash` | System | explorer | Execute ccw commands |
| `mcp__ace-tool__search_context` | Search | explorer | Semantic code search |
| `mcp__ccw-tools__team_msg` | Team | explorer | Log messages to message bus |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `context_ready` | explorer coordinator | Context analysis complete | 上下文报告就绪 |
| `impact_assessed` | explorer coordinator | Impact scope determined | 影响面评估完成 |
| `error` | explorer coordinator | Blocking error | 无法完成探索 |
| `context_ready` | explorer -> coordinator | Context analysis complete | Context report ready |
| `impact_assessed` | explorer -> coordinator | Impact scope determined | Impact assessment complete |
| `error` | explorer -> coordinator | Blocking error | Cannot complete exploration |
## Toolbox
## Message Bus
### Subagent Capabilities
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
| Agent Type | Purpose |
|------------|---------|
| `cli-explore-agent` | Deep codebase exploration with module analysis |
```
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "explorer",
to: "coordinator",
type: <message-type>,
summary: "[explorer] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
### CLI Capabilities
**CLI fallback** (when MCP unavailable):
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue status <id> --json` | Load full issue details |
| `ccw tool exec get_modules_by_depth '{}'` | Get project module structure |
```
Bash("ccw team log --team issue --from explorer --to coordinator --type <message-type> --summary \"[explorer] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
// Parse agent name for parallel instances (e.g., explorer-1, explorer-2)
const agentNameMatch = args.match(/--agent-name[=\s]+([\w-]+)/)
const agentName = agentNameMatch ? agentNameMatch[1] : 'explorer'
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('EXPLORE-') &&
t.owner === agentName && // Use agentName (e.g., 'explorer-1') instead of hardcoded 'explorer'
t.status === 'pending' &&
t.blockedBy.length === 0
)
Standard task discovery flow: TaskList -> filter by prefix `EXPLORE-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
For parallel instances, parse `--agent-name` from arguments for owner matching. Falls back to `explorer` for single-instance roles.
### Phase 2: Issue Loading & Context Setup
```javascript
// Resolve project root from working directory
const projectRoot = Bash('pwd').trim()
**Input Sources**:
// Extract issue ID from task description
const issueIdMatch = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/)
const issueId = issueIdMatch ? issueIdMatch[0] : null
| Input | Source | Required |
|-------|--------|----------|
| Issue ID | Task description (GH-\d+ or ISS-\d{8}-\d{6}) | Yes |
| Issue details | `ccw issue status <id> --json` | Yes |
| Project root | Working directory | Yes |
if (!issueId) {
// Report error
mcp__ccw-tools__team_msg({ operation: "log", team: "issue", from: "explorer", to: "coordinator", type: "error", summary: "[explorer] No issue ID found in task" })
SendMessage({ type: "message", recipient: "coordinator", content: "## [explorer] Error\nNo issue ID in task description", summary: "[explorer] error: no issue ID" })
return
}
**Loading steps**:
1. Extract issue ID from task description via regex: `(?:GH-\d+|ISS-\d{8}-\d{6})`
2. If no issue ID found -> SendMessage error to coordinator, STOP
3. Load issue details:
// Load issue details
const issueJson = Bash(`ccw issue status ${issueId} --json`)
const issue = JSON.parse(issueJson)
```
Bash("ccw issue status <issueId> --json")
```
4. Parse JSON response for issue metadata (title, context, priority, labels, feedback)
### Phase 3: Codebase Exploration & Impact Analysis
```javascript
// Complexity assessment determines exploration depth
function assessComplexity(issue) {
let score = 0
if (/refactor|architect|restructure|module|system/i.test(issue.context)) score += 2
if (/multiple|across|cross/i.test(issue.context)) score += 2
if (/integrate|api|database/i.test(issue.context)) score += 1
if (issue.priority >= 4) score += 1
return score >= 4 ? 'High' : score >= 2 ? 'Medium' : 'Low'
}
**Complexity assessment determines exploration depth**:
const complexity = assessComplexity(issue)
| Signal | Weight | Keywords |
|--------|--------|----------|
| Structural change | +2 | refactor, architect, restructure, module, system |
| Cross-cutting | +2 | multiple, across, cross |
| Integration | +1 | integrate, api, database |
| High priority | +1 | priority >= 4 |
if (complexity === 'Low') {
// Direct ACE search
const results = mcp__ace-tool__search_context({
project_root_path: projectRoot,
query: `${issue.title}. ${issue.context}. Keywords: ${issue.labels?.join(', ') || ''}`
})
// Build context from ACE results
} else {
// Deep exploration via cli-explore-agent
Task({
subagent_type: "cli-explore-agent",
run_in_background: false,
description: `Explore context for ${issueId}`,
prompt: `
| Score | Complexity | Strategy |
|-------|------------|----------|
| >= 4 | High | Deep exploration via cli-explore-agent |
| 2-3 | Medium | Hybrid: ACE search + selective agent |
| 0-1 | Low | Direct ACE search only |
**Exploration execution**:
| Complexity | Execution |
|------------|-----------|
| Low | Direct ACE search: `mcp__ace-tool__search_context(project_root_path, query)` |
| Medium/High | Spawn cli-explore-agent: `Task({ subagent_type: "cli-explore-agent", run_in_background: false })` |
**cli-explore-agent prompt template**:
```
## Issue Context
ID: ${issueId}
Title: ${issue.title}
Description: ${issue.context}
Priority: ${issue.priority}
ID: <issueId>
Title: <issue.title>
Description: <issue.context>
Priority: <issue.priority>
## MANDATORY FIRST STEPS
1. Run: ccw tool exec get_modules_by_depth '{}'
@@ -143,99 +158,55 @@ Priority: ${issue.priority}
- Check for previous related changes (git log)
## Output
Write findings to: .workflow/.team-plan/issue/context-${issueId}.json
Write findings to: .workflow/.team-plan/issue/context-<issueId>.json
Schema: {
issue_id, relevant_files[], dependencies[], impact_scope,
existing_patterns[], related_changes[], key_findings[],
issue_id, relevant_files[], dependencies[], impact_scope,
existing_patterns[], related_changes[], key_findings[],
complexity_assessment, _metadata
}
`
})
}
```
### Phase 4: Context Report Generation
```javascript
// Read exploration results
const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json`
let contextReport
try {
contextReport = JSON.parse(Read(contextPath))
} catch {
// Build minimal report from ACE results
contextReport = {
issue_id: issueId,
relevant_files: [],
key_findings: [],
complexity_assessment: complexity
}
}
**Report assembly**:
// Enrich with issue metadata
contextReport.issue = {
id: issue.id,
title: issue.title,
priority: issue.priority,
status: issue.status,
labels: issue.labels,
feedback: issue.feedback // Previous failure history
1. Read exploration results from `.workflow/.team-plan/issue/context-<issueId>.json`
2. If file not found, build minimal report from ACE results
3. Enrich with issue metadata: id, title, priority, status, labels, feedback
**Report schema**:
```
{
issue_id: string,
issue: { id, title, priority, status, labels, feedback },
relevant_files: [{ path, relevance }], | string[],
dependencies: string[],
impact_scope: "low" | "medium" | "high",
existing_patterns: string[],
related_changes: string[],
key_findings: string[],
complexity_assessment: "Low" | "Medium" | "High"
}
```
### Phase 5: Report to Coordinator
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "explorer",
to: "coordinator",
type: "context_ready",
summary: `[explorer] Context ready for ${issueId}: ${contextReport.relevant_files?.length || 0} files, complexity=${complexity}`,
ref: contextPath
})
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [explorer] Context Analysis Results
Standard report flow: team_msg log -> SendMessage with `[explorer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
**Issue**: ${issueId} - ${issue.title}
**Complexity**: ${complexity}
**Files Identified**: ${contextReport.relevant_files?.length || 0}
**Impact Scope**: ${contextReport.impact_scope || 'unknown'}
### Key Findings
${(contextReport.key_findings || []).map(f => `- ${f}`).join('\n')}
### Context Report
Saved to: ${contextPath}`,
summary: `[explorer] EXPLORE complete: ${issueId}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('EXPLORE-') &&
t.owner === agentName && // Use agentName for parallel instance filtering
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
---
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No EXPLORE-* tasks available | Idle, wait for coordinator assignment |
| Issue ID not found in task | Notify coordinator with error |
| Issue ID not found in ccw | Notify coordinator with error |
| ACE search returns no results | Fallback to Glob/Grep, report limited context |
| cli-explore-agent failure | Retry once with simplified prompt, then report partial results |
| Context file write failure | Report via SendMessage with inline context |
| Context/Plan file not found | Notify coordinator, request location |

View File

@@ -1,113 +1,139 @@
# Role: implementer
# Implementer Role
加载 solution → 根据 execution_method 路由到对应后端Agent/Codex/Gemini→ 测试验证 → 提交。支持多种 CLI 执行后端,执行方式在 coordinator Phase 1 已确定(见 coordinator.md Execution Method Selection
Load solution -> route to backend (Agent/Codex/Gemini) based on execution_method -> test validation -> commit. Supports multiple CLI execution backends. Execution method is determined in coordinator Phase 1.
## Role Identity
## Identity
- **Name**: `implementer`
- **Name**: `implementer` | **Tag**: `[implementer]`
- **Task Prefix**: `BUILD-*`
- **Responsibility**: Code implementation (solution route to backend test commit)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[implementer]`
- **Responsibility**: Code implementation (solution -> route to backend -> test -> commit)
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `BUILD-*` 前缀的任务
- 所有输出必须带 `[implementer]` 标识
- 按照 BUILD-* 任务中的 `execution_method` 字段选择执行后端
- 每个 solution 完成后通知 coordinator
- 持续轮询新的 BUILD-* 任务
- Only process `BUILD-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[implementer]` identifier
- Only communicate with coordinator via SendMessage
- Select execution backend based on `execution_method` field in BUILD-* task
- Notify coordinator after each solution completes
- Continuously poll for new BUILD-* tasks
### MUST NOT
- ❌ 修改解决方案planner 职责)
- ❌ 审查其他实现结果reviewer 职责)
- ❌ 修改执行队列integrator 职责)
- ❌ 直接与其他 worker 通信
- ❌ 为其他角色创建任务
- Modify solutions (planner responsibility)
- Review implementation results (reviewer responsibility)
- Modify execution queue (integrator responsibility)
- Communicate directly with other worker roles
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
- Omit `[implementer]` identifier in any output
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `impl_complete` | implementer → coordinator | Implementation and tests pass | 实现完成 |
| `impl_failed` | implementer → coordinator | Implementation failed after retries | 实现失败 |
| `error` | implementer → coordinator | Blocking error | 执行错误 |
---
## Toolbox
### Available Commands
> No command files -- all phases execute inline.
### Execution Backends
| Backend | Tool | Invocation | Mode |
|---------|------|------------|------|
| `agent` | code-developer subagent | `Task({ subagent_type: "code-developer" })` | 同步 |
| `codex` | Codex CLI | `ccw cli --tool codex --mode write` | 后台 |
| `gemini` | Gemini CLI | `ccw cli --tool gemini --mode write` | 后台 |
| `agent` | code-developer subagent | `Task({ subagent_type: "code-developer" })` | Sync |
| `codex` | Codex CLI | `ccw cli --tool codex --mode write` | Background |
| `gemini` | Gemini CLI | `ccw cli --tool gemini --mode write` | Background |
### Direct Capabilities
### Tool Capabilities
| Tool | Purpose |
|------|---------|
| `Read` | 读取 solution plan 和队列文件 |
| `Write` | 写入实现产物 |
| `Edit` | 编辑源代码 |
| `Bash` | 运行测试、git 操作、CLI 调用 |
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `Task` | Subagent | implementer | Spawn code-developer for agent execution |
| `Read` | IO | implementer | Read solution plan and queue files |
| `Write` | IO | implementer | Write implementation artifacts |
| `Edit` | IO | implementer | Edit source code |
| `Bash` | System | implementer | Run tests, git operations, CLI calls |
| `mcp__ccw-tools__team_msg` | Team | implementer | Log messages to message bus |
### CLI Capabilities
---
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue status <id> --json` | 查看 issue 状态 |
| `ccw issue solutions <id> --json` | 加载 bound solution |
| `ccw issue update <id> --status in-progress` | 更新 issue 状态为进行中 |
| `ccw issue update <id> --status resolved` | 标记 issue 已解决 |
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `impl_complete` | implementer -> coordinator | Implementation and tests pass | Implementation complete |
| `impl_failed` | implementer -> coordinator | Implementation failed after retries | Implementation failed |
| `error` | implementer -> coordinator | Blocking error | Execution error |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "implementer",
to: "coordinator",
type: <message-type>,
summary: "[implementer] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team issue --from implementer --to coordinator --type <message-type> --summary \"[implementer] ...\" --ref <artifact-path> --json")
```
---
## Execution Method Resolution
BUILD-* 任务的 description 中解析执行方式:
Parse execution method from BUILD-* task description:
```javascript
// 从任务描述中解析 execution_method
function resolveExecutor(taskDesc, solutionTaskCount) {
const methodMatch = taskDesc.match(/execution_method:\s*(Agent|Codex|Gemini|Auto)/i)
const method = methodMatch ? methodMatch[1] : 'Auto'
| Pattern | Extraction |
|---------|------------|
| `execution_method:\s*Agent` | Use agent backend |
| `execution_method:\s*Codex` | Use codex backend |
| `execution_method:\s*Gemini` | Use gemini backend |
| `execution_method:\s*Auto` | Auto-select based on task count |
if (method.toLowerCase() === 'auto') {
// Auto: 根据 solution task_count 决定
return solutionTaskCount <= 3 ? 'agent' : 'codex'
}
return method.toLowerCase() // 'agent' | 'codex' | 'gemini'
}
**Auto-selection logic**:
// 从任务描述中解析 code_review 配置
function resolveCodeReview(taskDesc) {
const reviewMatch = taskDesc.match(/code_review:\s*(\S+)/i)
return reviewMatch ? reviewMatch[1] : 'Skip'
}
```
| Solution Task Count | Backend |
|---------------------|---------|
| <= 3 | agent |
| > 3 | codex |
**Code review resolution**:
| Pattern | Setting |
|---------|---------|
| `code_review:\s*Skip` | No review |
| `code_review:\s*Gemini Review` | Gemini CLI review |
| `code_review:\s*Codex Review` | Git-aware review (--uncommitted) |
| No match | Skip (default) |
---
## Execution Prompt Builder
统一的 prompt 构建,所有后端共用:
Unified prompt template for all backends:
```javascript
function buildExecutionPrompt(issueId, solution, explorerContext) {
return `
```
## Issue
ID: ${issueId}
Title: ${solution.bound.title || 'N/A'}
ID: <issueId>
Title: <solution.bound.title>
## Solution Plan
${JSON.stringify(solution.bound, null, 2)}
<solution.bound JSON>
${explorerContext ? `
## Codebase Context (from explorer)
Relevant files: ${explorerContext.relevant_files?.map(f => f.path || f).slice(0, 10).join(', ')}
Existing patterns: ${explorerContext.existing_patterns?.join('; ') || 'N/A'}
Dependencies: ${explorerContext.dependencies?.join(', ') || 'N/A'}
` : ''}
Relevant files: <explorerContext.relevant_files>
Existing patterns: <explorerContext.existing_patterns>
Dependencies: <explorerContext.dependencies>
## Implementation Requirements
@@ -115,7 +141,7 @@ Dependencies: ${explorerContext.dependencies?.join(', ') || 'N/A'}
2. Write clean, minimal code following existing patterns
3. Run tests after each significant change
4. Ensure all existing tests still pass
5. Do NOT over-engineer implement exactly what the solution specifies
5. Do NOT over-engineer -- implement exactly what the solution specifies
## Quality Checklist
- [ ] All solution tasks implemented
@@ -125,264 +151,160 @@ Dependencies: ${explorerContext.dependencies?.join(', ') || 'N/A'}
- [ ] No security vulnerabilities introduced
## Project Guidelines
@.workflow/project-guidelines.json
`
}
@.workflow/specs/*.md
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
// Parse agent name for parallel instances (e.g., implementer-1, implementer-2)
const agentNameMatch = args.match(/--agent-name[=\s]+([\w-]+)/)
const agentName = agentNameMatch ? agentNameMatch[1] : 'implementer'
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('BUILD-') &&
t.owner === agentName && // Use agentName (e.g., 'implementer-1') instead of hardcoded 'implementer'
t.status === 'pending' &&
t.blockedBy.length === 0
)
Standard task discovery flow: TaskList -> filter by prefix `BUILD-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
if (myTasks.length === 0) return // idle — wait for coordinator to create BUILD tasks
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
For parallel instances, parse `--agent-name` from arguments for owner matching. Falls back to `implementer` for single-instance roles.
### Phase 2: Load Solution & Resolve Executor
```javascript
// Extract issue ID from task description
const issueIdMatch = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/)
const issueId = issueIdMatch ? issueIdMatch[0] : null
**Input Sources**:
if (!issueId) {
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "implementer", to: "coordinator",
type: "error",
summary: "[implementer] No issue ID found in task"
})
SendMessage({
type: "message", recipient: "coordinator",
content: "## [implementer] Error\nNo issue ID in task description",
summary: "[implementer] error: no issue ID"
})
TaskUpdate({ taskId: task.id, status: 'completed' })
return
}
| Input | Source | Required |
|-------|--------|----------|
| Issue ID | Task description (GH-\d+ or ISS-\d{8}-\d{6}) | Yes |
| Bound solution | `ccw issue solutions <id> --json` | Yes |
| Explorer context | `.workflow/.team-plan/issue/context-<issueId>.json` | No |
| Execution method | Task description | Yes |
| Code review | Task description | No |
// Load solution plan
const solJson = Bash(`ccw issue solutions ${issueId} --json`)
const solution = JSON.parse(solJson)
**Loading steps**:
if (!solution.bound) {
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "implementer", to: "coordinator",
type: "error",
summary: `[implementer] No bound solution for ${issueId}`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [implementer] Error\nNo bound solution for ${issueId}`,
summary: `[implementer] error: no solution for ${issueId}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
return
}
1. Extract issue ID from task description
2. If no issue ID -> SendMessage error to coordinator, STOP
3. Load bound solution:
// Load explorer context for implementation guidance
let explorerContext = null
try {
const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json`
explorerContext = JSON.parse(Read(contextPath))
} catch {
// No explorer context
}
```
Bash("ccw issue solutions <issueId> --json")
```
// Resolve execution method from task description
const taskCount = solution.bound.task_count || solution.bound.tasks?.length || 0
const executor = resolveExecutor(task.description, taskCount)
const codeReview = resolveCodeReview(task.description)
4. If no bound solution -> SendMessage error to coordinator, STOP
5. Load explorer context (if available)
6. Resolve execution method from task description
7. Resolve code review setting from task description
8. Update issue status:
// Update issue status
Bash(`ccw issue update ${issueId} --status in-progress`)
```
Bash("ccw issue update <issueId> --status in-progress")
```
### Phase 3: Implementation (Multi-Backend Routing)
根据 `executor` 变量路由到对应后端:
Route to backend based on `executor` resolution:
#### Option A: Agent Execution (`executor === 'agent'`)
同步调用 code-developer subagent,适合简单任务(task_count ≤ 3
Sync call to code-developer subagent, suitable for simple tasks (task_count <= 3).
```javascript
if (executor === 'agent') {
const implResult = Task({
subagent_type: "code-developer",
run_in_background: false,
description: `Implement solution for ${issueId}`,
prompt: buildExecutionPrompt(issueId, solution, explorerContext)
})
}
```
Task({
subagent_type: "code-developer",
run_in_background: false,
description: "Implement solution for <issueId>",
prompt: <executionPrompt>
})
```
#### Option B: Codex CLI Execution (`executor === 'codex'`)
后台调用 Codex CLI适合复杂任务。使用固定 ID 支持 resume
Background call to Codex CLI, suitable for complex tasks. Uses fixed ID for resume support.
```javascript
if (executor === 'codex') {
const fixedId = `issue-${issueId}`
```
Bash("ccw cli -p \"<executionPrompt>\" --tool codex --mode write --id issue-<issueId>", { run_in_background: true })
```
Bash(
`ccw cli -p "${buildExecutionPrompt(issueId, solution, explorerContext)}" --tool codex --mode write --id ${fixedId}`,
{ run_in_background: true }
)
// STOP — CLI 后台执行,等待 task hook callback 通知完成
**On failure, resume with**:
// 失败时 resume:
// ccw cli -p "Continue implementation" --resume ${fixedId} --tool codex --mode write --id ${fixedId}-retry
}
```
ccw cli -p "Continue implementation" --resume issue-<issueId> --tool codex --mode write --id issue-<issueId>-retry
```
#### Option C: Gemini CLI Execution (`executor === 'gemini'`)
后台调用 Gemini CLI适合需要分析的复合任务。
Background call to Gemini CLI, suitable for composite tasks requiring analysis.
```javascript
if (executor === 'gemini') {
const fixedId = `issue-${issueId}`
Bash(
`ccw cli -p "${buildExecutionPrompt(issueId, solution, explorerContext)}" --tool gemini --mode write --id ${fixedId}`,
{ run_in_background: true }
)
// STOP — CLI 后台执行,等待 task hook callback 通知完成
}
```
Bash("ccw cli -p \"<executionPrompt>\" --tool gemini --mode write --id issue-<issueId>", { run_in_background: true })
```
### Phase 4: Verify & Commit
```javascript
// Detect test command from package.json or project config
let testCmd = 'npm test'
try {
const pkgJson = JSON.parse(Read('package.json'))
if (pkgJson.scripts?.test) testCmd = 'npm test'
else if (pkgJson.scripts?.['test:unit']) testCmd = 'npm run test:unit'
} catch {
// Fallback: try common test runners
const hasYarn = Bash('test -f yarn.lock && echo yes || echo no').trim() === 'yes'
if (hasYarn) testCmd = 'yarn test'
}
**Test detection**:
// Verify implementation
const testResult = Bash(`${testCmd} 2>&1 || echo "TEST_FAILED"`)
const testPassed = !testResult.includes('TEST_FAILED') && !testResult.includes('FAIL')
| Detection | Method |
|-----------|--------|
| Package.json exists | Check `scripts.test` or `scripts.test:unit` |
| Yarn.lock exists | Use `yarn test` |
| Fallback | Use `npm test` |
if (!testPassed) {
// Implementation failed — report to coordinator
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "implementer", to: "coordinator",
type: "impl_failed",
summary: `[implementer] Tests failing for ${issueId} after implementation (via ${executor})`
})
**Test execution**:
SendMessage({
type: "message", recipient: "coordinator",
content: `## [implementer] Implementation Failed
**Issue**: ${issueId}
**Executor**: ${executor}
**Status**: Tests failing after implementation
**Test Output** (truncated):
${testResult.slice(0, 500)}
**Action**: May need solution revision or manual intervention.
${executor !== 'agent' ? `**Resume**: \`ccw cli -p "Fix failing tests" --resume issue-${issueId} --tool ${executor} --mode write --id issue-${issueId}-fix\`` : ''}`,
summary: `[implementer] impl_failed: ${issueId} (${executor})`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
return
}
// Optional: Code review (if configured)
if (codeReview !== 'Skip') {
executeCodeReview(codeReview, issueId)
}
// Update issue status to resolved
Bash(`ccw issue update ${issueId} --status resolved`)
```
Bash("<testCmd> 2>&1 || echo \"TEST_FAILED\"")
```
### Code Review (Optional)
**Test result handling**:
```javascript
function executeCodeReview(reviewTool, issueId) {
const reviewPrompt = `PURPOSE: Code review for ${issueId} implementation against solution plan
TASK: • Verify solution convergence criteria • Check test coverage • Analyze code quality • Identify issues
MODE: analysis
CONTEXT: @**/* | Memory: Review issue team execution for ${issueId}
EXPECTED: Quality assessment with issue identification and recommendations
CONSTRAINTS: Focus on solution adherence and code quality | analysis=READ-ONLY`
| Condition | Action |
|-----------|--------|
| Tests pass | Proceed to optional code review |
| Tests fail | Report impl_failed to coordinator |
if (reviewTool === 'Gemini Review') {
Bash(`ccw cli -p "${reviewPrompt}" --tool gemini --mode analysis --id issue-review-${issueId}`,
{ run_in_background: true })
} else if (reviewTool === 'Codex Review') {
// Codex review: --uncommitted flag only (no prompt with target flags)
Bash(`ccw cli --tool codex --mode review --uncommitted`,
{ run_in_background: true })
}
}
**Failed test report**:
```
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "implementer", to: "coordinator",
type: "impl_failed",
summary: "[implementer] Tests failing for <issueId> after implementation (via <executor>)"
})
SendMessage({
type: "message", recipient: "coordinator",
content: "## [implementer] Implementation Failed\n\n**Issue**: <issueId>\n**Executor**: <executor>\n**Status**: Tests failing\n**Test Output** (truncated):\n<truncated output>\n\n**Action**: May need solution revision or manual intervention.",
summary: "[implementer] impl_failed: <issueId> (<executor>)"
})
```
**Optional code review** (if configured):
| Tool | Command |
|------|---------|
| Gemini Review | `ccw cli -p "<reviewPrompt>" --tool gemini --mode analysis --id issue-review-<issueId>` |
| Codex Review | `ccw cli --tool codex --mode review --uncommitted` |
**Success completion**:
```
Bash("ccw issue update <issueId> --status resolved")
```
### Phase 5: Report to Coordinator
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "implementer",
to: "coordinator",
type: "impl_complete",
summary: `[implementer] Implementation complete for ${issueId} via ${executor}, tests passing`
})
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [implementer] Implementation Complete
Standard report flow: team_msg log -> SendMessage with `[implementer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
**Issue**: ${issueId}
**Executor**: ${executor}
**Solution**: ${solution.bound.id}
**Code Review**: ${codeReview}
**Status**: All tests passing
**Issue Status**: Updated to resolved`,
summary: `[implementer] BUILD complete: ${issueId} (${executor})`
})
**Report content includes**:
TaskUpdate({ taskId: task.id, status: 'completed' })
- Issue ID
- Executor used
- Solution ID
- Code review status
- Test status
- Issue status update
// Check for next BUILD-* task (parallel BUILD tasks or new batches)
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('BUILD-') &&
t.owner === agentName && // Use agentName for parallel instance filtering
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
---
## Error Handling
@@ -396,4 +318,5 @@ if (nextTasks.length > 0) {
| CLI timeout | Use fixed ID `issue-{issueId}` for resume |
| Tests failing after implementation | Report impl_failed with test output + resume info |
| Issue status update failure | Log warning, continue with report |
| Dependency not yet complete | Wait task is blocked by blockedBy |
| Dependency not yet complete | Wait -- task is blocked by blockedBy |
| Context/Plan file not found | Notify coordinator, request location |

View File

@@ -1,127 +1,150 @@
# Role: integrator
# Integrator Role
队列编排、冲突检测、执行顺序优化。内部调用 issue-queue-agent 进行智能队列形成。
Queue orchestration, conflict detection, execution order optimization. Internally invokes issue-queue-agent for intelligent queue formation.
## Role Identity
## Identity
- **Name**: `integrator`
- **Name**: `integrator` | **Tag**: `[integrator]`
- **Task Prefix**: `MARSHAL-*`
- **Responsibility**: Orchestration (queue formation)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[integrator]`
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `MARSHAL-*` 前缀的任务
- 所有输出必须带 `[integrator]` 标识
- 使用 issue-queue-agent 进行队列编排
- 确保所有 issue 都有 bound solution 才能编排
- Only process `MARSHAL-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[integrator]` identifier
- Only communicate with coordinator via SendMessage
- Use issue-queue-agent for queue orchestration
- Ensure all issues have bound solutions before queue formation
### MUST NOT
- ❌ 修改解决方案planner 职责)
- ❌ 审查方案质量reviewer 职责)
- ❌ 实现代码implementer 职责)
- ❌ 直接与其他 worker 通信
- ❌ 为其他角色创建任务
- Modify solutions (planner responsibility)
- Review solution quality (reviewer responsibility)
- Implement code (implementer responsibility)
- Communicate directly with other worker roles
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
- Omit `[integrator]` identifier in any output
---
## Toolbox
### Available Commands
> No command files -- all phases execute inline.
### Tool Capabilities
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `Task` | Subagent | integrator | Spawn issue-queue-agent for queue formation |
| `Read` | IO | integrator | Read queue files and solution data |
| `Write` | IO | integrator | Write queue output |
| `Bash` | System | integrator | Execute ccw commands |
| `mcp__ccw-tools__team_msg` | Team | integrator | Log messages to message bus |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `queue_ready` | integrator coordinator | Queue formed successfully | 队列就绪,可执行 |
| `conflict_found` | integrator coordinator | File conflicts detected, user input needed | 发现冲突需要人工决策 |
| `error` | integrator coordinator | Blocking error | 队列编排失败 |
| `queue_ready` | integrator -> coordinator | Queue formed successfully | Queue ready for execution |
| `conflict_found` | integrator -> coordinator | File conflicts detected, user input needed | Conflicts need manual decision |
| `error` | integrator -> coordinator | Blocking error | Queue formation failed |
## Toolbox
## Message Bus
### Subagent Capabilities
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
| Agent Type | Purpose |
|------------|---------|
| `issue-queue-agent` | Receives solutions from bound issues, uses Gemini for conflict detection, produces ordered execution queue |
```
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "integrator",
to: "coordinator",
type: <message-type>,
summary: "[integrator] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
### CLI Capabilities
**CLI fallback** (when MCP unavailable):
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue status <id> --json` | Load issue details |
| `ccw issue solutions <id> --json` | Verify bound solution |
| `ccw issue list --status planned --json` | List planned issues |
```
Bash("ccw team log --team issue --from integrator --to coordinator --type <message-type> --summary \"[integrator] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('MARSHAL-') &&
t.owner === 'integrator' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Standard task discovery flow: TaskList -> filter by prefix `MARSHAL-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Collect Bound Solutions
```javascript
// Extract issue IDs from task description
const issueIds = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || []
**Input Sources**:
// Verify all issues have bound solutions
const unbound = []
const boundIssues = []
| Input | Source | Required |
|-------|--------|----------|
| Issue IDs | Task description (GH-\d+ or ISS-\d{8}-\d{6}) | Yes |
| Bound solutions | `ccw issue solutions <id> --json` | Yes |
for (const issueId of issueIds) {
const solJson = Bash(`ccw issue solutions ${issueId} --json`)
const sol = JSON.parse(solJson)
if (sol.bound) {
boundIssues.push({ id: issueId, solution: sol.bound })
} else {
unbound.push(issueId)
}
}
**Loading steps**:
if (unbound.length > 0) {
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "integrator", to: "coordinator",
type: "error",
summary: `[integrator] Unbound issues: ${unbound.join(', ')} — cannot form queue`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [integrator] Error: Unbound Issues\n\nThe following issues have no bound solution:\n${unbound.map(id => `- ${id}`).join('\n')}\n\nPlanner must create solutions before queue formation.`,
summary: `[integrator] error: ${unbound.length} unbound issues`
})
return
}
1. Extract issue IDs from task description via regex
2. Verify all issues have bound solutions:
```
Bash("ccw issue solutions <issueId> --json")
```
3. Check for unbound issues:
| Condition | Action |
|-----------|--------|
| All issues bound | Proceed to Phase 3 |
| Any issue unbound | Report error to coordinator, STOP |
**Unbound error report**:
```
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "integrator", to: "coordinator",
type: "error",
summary: "[integrator] Unbound issues: <issueIds> - cannot form queue"
})
SendMessage({
type: "message", recipient: "coordinator",
content: "## [integrator] Error: Unbound Issues\n\nThe following issues have no bound solution:\n<unbound list>\n\nPlanner must create solutions before queue formation.",
summary: "[integrator] error: <count> unbound issues"
})
```
### Phase 3: Queue Formation via issue-queue-agent
```javascript
// Invoke issue-queue-agent for intelligent queue formation
const agentResult = Task({
**Agent invocation**:
```
Task({
subagent_type: "issue-queue-agent",
run_in_background: false,
description: `Form queue for ${issueIds.length} issues`,
prompt: `
description: "Form queue for <count> issues",
prompt: "
## Issues to Queue
Issue IDs: ${issueIds.join(', ')}
Issue IDs: <issueIds>
## Bound Solutions
${boundIssues.map(bi => `- ${bi.id}: Solution ${bi.solution.id} (${bi.solution.task_count} tasks)`).join('\n')}
<solution list with issue_id, solution_id, task_count>
## Instructions
@@ -139,116 +162,73 @@ Schema: {
conflicts: [{ issues: [id1, id2], files: [...], resolution }],
parallel_groups: [{ group: N, issues: [...] }]
}
`
"
})
```
// Parse queue result
const queuePath = `.workflow/issues/queue/execution-queue.json`
let queueResult
try {
queueResult = JSON.parse(Read(queuePath))
} catch {
queueResult = null
}
**Parse queue result**:
```
Read(".workflow/issues/queue/execution-queue.json")
```
### Phase 4: Conflict Resolution
```javascript
if (!queueResult) {
// Queue formation failed
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "integrator", to: "coordinator",
type: "error",
summary: `[integrator] Queue formation failed — no output from issue-queue-agent`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [integrator] Error\n\nQueue formation failed. issue-queue-agent produced no output.`,
summary: `[integrator] error: queue formation failed`
})
return
}
**Queue validation**:
// Check for unresolved conflicts
const unresolvedConflicts = (queueResult.conflicts || []).filter(c => c.resolution === 'unresolved')
| Condition | Action |
|-----------|--------|
| Queue file exists | Check for unresolved conflicts |
| Queue file not found | Report error to coordinator, STOP |
if (unresolvedConflicts.length > 0) {
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "integrator", to: "coordinator",
type: "conflict_found",
summary: `[integrator] ${unresolvedConflicts.length} unresolved conflicts in queue`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [integrator] Conflicts Found
**Conflict handling**:
**Unresolved Conflicts**: ${unresolvedConflicts.length}
| Condition | Action |
|-----------|--------|
| No unresolved conflicts | Proceed to Phase 5 |
| Has unresolved conflicts | Report to coordinator for user decision |
${unresolvedConflicts.map((c, i) => `### Conflict ${i + 1}
- **Issues**: ${c.issues.join(' vs ')}
- **Files**: ${c.files.join(', ')}
- **Recommendation**: User decision needed — which issue takes priority`).join('\n\n')}
**Unresolved conflict report**:
**Action Required**: Coordinator should present conflicts to user for resolution, then re-trigger MARSHAL.`,
summary: `[integrator] conflict_found: ${unresolvedConflicts.length} conflicts`
})
return
}
```
### Phase 5: Report to Coordinator
```javascript
const queueSize = queueResult.queue?.length || 0
const parallelGroups = queueResult.parallel_groups?.length || 1
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "integrator",
to: "coordinator",
type: "queue_ready",
summary: `[integrator] Queue ready: ${queueSize} items in ${parallelGroups} parallel groups`,
ref: queuePath
operation: "log", team: "issue", from: "integrator", to: "coordinator",
type: "conflict_found",
summary: "[integrator] <count> unresolved conflicts in queue"
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [integrator] Queue Ready
**Queue Size**: ${queueSize} items
**Parallel Groups**: ${parallelGroups}
**Resolved Conflicts**: ${(queueResult.conflicts || []).filter(c => c.resolution !== 'unresolved').length}
### Execution Order
${(queueResult.queue || []).map((q, i) => `${i + 1}. ${q.issue_id} (Solution: ${q.solution_id})${q.depends_on?.length ? ` — depends on: ${q.depends_on.join(', ')}` : ''}`).join('\n')}
### Parallel Groups
${(queueResult.parallel_groups || []).map(g => `- Group ${g.group}: ${g.issues.join(', ')}`).join('\n')}
**Queue File**: ${queuePath}
**Status**: Ready for BUILD phase`,
summary: `[integrator] MARSHAL complete: ${queueSize} items queued`
type: "message", recipient: "coordinator",
content: "## [integrator] Conflicts Found\n\n**Unresolved Conflicts**: <count>\n\n<conflict details>\n\n**Action Required**: Coordinator should present conflicts to user for resolution, then re-trigger MARSHAL.",
summary: "[integrator] conflict_found: <count> conflicts"
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('MARSHAL-') &&
t.owner === 'integrator' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
**Queue metrics**:
| Metric | Source |
|--------|--------|
| Queue size | `queueResult.queue.length` |
| Parallel groups | `queueResult.parallel_groups.length` |
| Resolved conflicts | Count where `resolution !== 'unresolved'` |
### Phase 5: Report to Coordinator
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
Standard report flow: team_msg log -> SendMessage with `[integrator]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
**Report content includes**:
- Queue size
- Number of parallel groups
- Resolved conflicts count
- Execution order list
- Parallel groups breakdown
- Queue file path
---
## Error Handling
| Scenario | Resolution |
@@ -256,5 +236,6 @@ if (nextTasks.length > 0) {
| No MARSHAL-* tasks available | Idle, wait for coordinator |
| Issues without bound solutions | Report to coordinator, block queue formation |
| issue-queue-agent failure | Retry once, then report error |
| Unresolved file conflicts | Escalate to coordinator for user decision (CP-5) |
| Unresolved file conflicts | Escalate to coordinator for user decision |
| Single issue (no conflict possible) | Create trivial queue with one entry |
| Context/Plan file not found | Notify coordinator, request location |

View File

@@ -1,205 +1,199 @@
# Role: planner
# Planner Role
解决方案设计、任务分解。内部调用 issue-plan-agent 进行 ACE 探索和方案生成。
Solution design, task decomposition. Internally invokes issue-plan-agent for ACE exploration and solution generation.
## Role Identity
## Identity
- **Name**: `planner`
- **Name**: `planner` | **Tag**: `[planner]`
- **Task Prefix**: `SOLVE-*`
- **Responsibility**: Orchestration (solution design)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[planner]`
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `SOLVE-*` 前缀的任务
- 所有输出必须带 `[planner]` 标识
- 使用 issue-plan-agent 进行方案设计
- 参考 explorer 的 context-report 丰富方案上下文
- Only process `SOLVE-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[planner]` identifier
- Only communicate with coordinator via SendMessage
- Use issue-plan-agent for solution design
- Reference explorer's context-report for solution context
### MUST NOT
- ❌ 执行代码实现implementer 职责)
- ❌ 审查方案质量reviewer 职责)
- ❌ 编排执行队列integrator 职责)
- ❌ 直接与其他 worker 通信
- Execute code implementation (implementer responsibility)
- Review solution quality (reviewer responsibility)
- Orchestrate execution queue (integrator responsibility)
- Communicate directly with other worker roles
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
- Modify files or resources outside this role's responsibility
- Omit `[planner]` identifier in any output
---
## Toolbox
### Available Commands
> No command files -- all phases execute inline.
### Tool Capabilities
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `Task` | Subagent | planner | Spawn issue-plan-agent for solution design |
| `Read` | IO | planner | Read context reports |
| `Bash` | System | planner | Execute ccw commands |
| `mcp__ccw-tools__team_msg` | Team | planner | Log messages to message bus |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `solution_ready` | planner coordinator | Solution designed and bound | 单方案就绪 |
| `multi_solution` | planner coordinator | Multiple solutions, needs selection | 多方案待选 |
| `error` | planner coordinator | Blocking error | 方案设计失败 |
| `solution_ready` | planner -> coordinator | Solution designed and bound | Single solution ready |
| `multi_solution` | planner -> coordinator | Multiple solutions, needs selection | Multiple solutions pending selection |
| `error` | planner -> coordinator | Blocking error | Solution design failed |
## Toolbox
## Message Bus
### Subagent Capabilities
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
| Agent Type | Purpose |
|------------|---------|
| `issue-plan-agent` | Closed-loop planning: ACE exploration + solution generation + binding |
```
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "planner",
to: "coordinator",
type: <message-type>,
summary: "[planner] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
### CLI Capabilities
**CLI fallback** (when MCP unavailable):
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue status <id> --json` | Load issue details |
| `ccw issue bind <id> <sol-id>` | Bind solution to issue |
```
Bash("ccw team log --team issue --from planner --to coordinator --type <message-type> --summary \"[planner] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('SOLVE-') &&
t.owner === 'planner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Standard task discovery flow: TaskList -> filter by prefix `SOLVE-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Context Loading
```javascript
// Resolve project root from working directory
const projectRoot = Bash('pwd').trim()
**Input Sources**:
// Extract issue ID
const issueIdMatch = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/)
const issueId = issueIdMatch ? issueIdMatch[0] : null
| Input | Source | Required |
|-------|--------|----------|
| Issue ID | Task description (GH-\d+ or ISS-\d{8}-\d{6}) | Yes |
| Explorer context | `.workflow/.team-plan/issue/context-<issueId>.json` | No |
| Review feedback | Task description (for SOLVE-fix tasks) | No |
// Load explorer's context report (if available)
const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json`
let explorerContext = null
try {
explorerContext = JSON.parse(Read(contextPath))
} catch {
// Explorer context not available, issue-plan-agent will do its own exploration
}
**Loading steps**:
1. Extract issue ID from task description via regex: `(?:GH-\d+|ISS-\d{8}-\d{6})`
2. If no issue ID found -> SendMessage error to coordinator, STOP
3. Load explorer's context report (if available):
// Check if this is a revision task (SOLVE-fix-N)
const isRevision = task.subject.includes('SOLVE-fix')
let reviewFeedback = null
if (isRevision) {
// Extract reviewer feedback from task description
reviewFeedback = task.description
}
```
Read(".workflow/.team-plan/issue/context-<issueId>.json")
```
4. Check if this is a revision task (SOLVE-fix-N):
- If yes, extract reviewer feedback from task description
- Design alternative approach addressing reviewer concerns
### Phase 3: Solution Generation via issue-plan-agent
```javascript
// Invoke issue-plan-agent
const agentResult = Task({
**Agent invocation**:
```
Task({
subagent_type: "issue-plan-agent",
run_in_background: false,
description: `Plan solution for ${issueId}`,
prompt: `
issue_ids: ["${issueId}"]
project_root: "${projectRoot}"
description: "Plan solution for <issueId>",
prompt: "
issue_ids: [\"<issueId>\"]
project_root: \"<projectRoot>\"
${explorerContext ? `
## Explorer Context (pre-gathered)
Relevant files: ${explorerContext.relevant_files?.map(f => f.path || f).join(', ')}
Key findings: ${explorerContext.key_findings?.join('; ')}
Complexity: ${explorerContext.complexity_assessment}
` : ''}
Relevant files: <explorerContext.relevant_files>
Key findings: <explorerContext.key_findings>
Complexity: <explorerContext.complexity_assessment>
${reviewFeedback ? `
## Revision Required
## Revision Required (if SOLVE-fix)
Previous solution was rejected by reviewer. Feedback:
${reviewFeedback}
<reviewFeedback>
Design an ALTERNATIVE approach that addresses the reviewer's concerns.
` : ''}
`
"
})
// Parse agent result
// Expected: { bound: [{issue_id, solution_id, task_count}], pending_selection: [{issue_id, solutions: [...]}] }
```
**Expected agent result**:
| Field | Description |
|-------|-------------|
| `bound` | Array of auto-bound solutions: `[{issue_id, solution_id, task_count}]` |
| `pending_selection` | Array of multi-solution issues: `[{issue_id, solutions: [...]}]` |
### Phase 4: Solution Selection & Binding
```javascript
const result = agentResult // from Phase 3
**Outcome routing**:
if (result.bound && result.bound.length > 0) {
// Single solution auto-bound
const bound = result.bound[0]
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "planner", to: "coordinator",
type: "solution_ready",
summary: `[planner] Solution ${bound.solution_id} bound to ${bound.issue_id} (${bound.task_count} tasks)`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [planner] Solution Ready
| Condition | Action |
|-----------|--------|
| Single solution auto-bound | Report `solution_ready` to coordinator |
| Multiple solutions pending | Report `multi_solution` to coordinator for user selection |
| No solution generated | Report `error` to coordinator |
**Issue**: ${bound.issue_id}
**Solution**: ${bound.solution_id}
**Tasks**: ${bound.task_count}
**Status**: Auto-bound (single solution)
**Single solution report**:
Solution written to: .workflow/issues/solutions/${bound.issue_id}.jsonl`,
summary: `[planner] SOLVE complete: ${bound.issue_id}`
})
} else if (result.pending_selection && result.pending_selection.length > 0) {
// Multiple solutions need user selection
const pending = result.pending_selection[0]
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "planner", to: "coordinator",
type: "multi_solution",
summary: `[planner] ${pending.solutions.length} solutions for ${pending.issue_id}, user selection needed`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [planner] Multiple Solutions
```
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "planner", to: "coordinator",
type: "solution_ready",
summary: "[planner] Solution <solution_id> bound to <issue_id> (<task_count> tasks)"
})
**Issue**: ${pending.issue_id}
**Solutions**: ${pending.solutions.length} options
SendMessage({
type: "message", recipient: "coordinator",
content: "## [planner] Solution Ready\n\n**Issue**: <issue_id>\n**Solution**: <solution_id>\n**Tasks**: <task_count>\n**Status**: Auto-bound (single solution)",
summary: "[planner] SOLVE complete: <issue_id>"
})
```
${pending.solutions.map((s, i) => `### Option ${i + 1}: ${s.id}
${s.description}
Tasks: ${s.task_count}`).join('\n\n')}
**Multi-solution report**:
**Action Required**: Coordinator should present options to user for selection.`,
summary: `[planner] multi_solution: ${pending.issue_id}`
})
}
```
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "planner", to: "coordinator",
type: "multi_solution",
summary: "[planner] <count> solutions for <issue_id>, user selection needed"
})
SendMessage({
type: "message", recipient: "coordinator",
content: "## [planner] Multiple Solutions\n\n**Issue**: <issue_id>\n**Solutions**: <count> options\n\n### Options\n<solution details>\n\n**Action Required**: Coordinator should present options to user for selection.",
summary: "[planner] multi_solution: <issue_id>"
})
```
### Phase 5: Report to Coordinator
```javascript
TaskUpdate({ taskId: task.id, status: 'completed' })
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('SOLVE-') &&
t.owner === 'planner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
Standard report flow: TaskUpdate completed -> check for next SOLVE-* task -> if found, loop to Phase 1.
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
---
## Error Handling
@@ -208,5 +202,6 @@ if (nextTasks.length > 0) {
| No SOLVE-* tasks available | Idle, wait for coordinator |
| Issue not found | Notify coordinator with error |
| issue-plan-agent failure | Retry once, then report error |
| Explorer context missing | Proceed without agent does its own exploration |
| Explorer context missing | Proceed without - agent does its own exploration |
| Solution binding failure | Report to coordinator for manual binding |
| Context/Plan file not found | Notify coordinator, request location |

View File

@@ -1,317 +1,261 @@
# Role: reviewer
# Reviewer Role
方案审查、技术可行性验证、风险评估。**新增质量门控角色**,填补当前 plan execute 直接执行无审查的缺口。
Solution review, technical feasibility validation, risk assessment. **Quality gate role** that fills the gap between plan and execute phases.
## Role Identity
## Identity
- **Name**: `reviewer`
- **Name**: `reviewer` | **Tag**: `[reviewer]`
- **Task Prefix**: `AUDIT-*`
- **Responsibility**: Read-only analysis (solution review)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[reviewer]`
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `AUDIT-*` 前缀的任务
- 所有输出必须带 `[reviewer]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 参考 explorer context-report 验证方案覆盖度
- 对每个方案给出明确的 approved / rejected / concerns 结论
- Only process `AUDIT-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[reviewer]` identifier
- Only communicate with coordinator via SendMessage
- Reference explorer's context-report for solution coverage validation
- Provide clear verdict for each solution: approved / rejected / concerns
### MUST NOT
- ❌ 修改解决方案planner 职责)
- ❌ 修改任何源代码
- ❌ 编排执行队列integrator 职责)
- ❌ 直接与其他 worker 通信
- ❌ 为其他角色创建任务
- Modify solutions (planner responsibility)
- Modify any source code
- Orchestrate execution queue (integrator responsibility)
- Communicate directly with other worker roles
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
- Omit `[reviewer]` identifier in any output
---
## Toolbox
### Available Commands
> No command files -- all phases execute inline.
### Tool Capabilities
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `Read` | IO | reviewer | Read solution files and context reports |
| `Bash` | System | reviewer | Execute ccw issue commands |
| `Glob` | Search | reviewer | Find related files |
| `Grep` | Search | reviewer | Search code patterns |
| `mcp__ace-tool__search_context` | Search | reviewer | Semantic search for solution validation |
| `mcp__ccw-tools__team_msg` | Team | reviewer | Log messages to message bus |
| `Write` | IO | reviewer | Write audit report |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `approved` | reviewer coordinator | Solution passes all checks | 方案审批通过 |
| `rejected` | reviewer coordinator | Critical issues found | 方案被拒,需修订 |
| `concerns` | reviewer coordinator | Minor issues noted | 有顾虑但不阻塞 |
| `error` | reviewer coordinator | Blocking error | 审查失败 |
| `approved` | reviewer -> coordinator | Solution passes all checks | Solution approved |
| `rejected` | reviewer -> coordinator | Critical issues found | Solution rejected, needs revision |
| `concerns` | reviewer -> coordinator | Minor issues noted | Has concerns but non-blocking |
| `error` | reviewer -> coordinator | Blocking error | Review failed |
## Toolbox
## Message Bus
### Direct Capabilities
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
| Tool | Purpose |
|------|---------|
| `Read` | 读取方案文件和上下文报告 |
| `Bash` | 执行 ccw issue 命令查看 issue/solution 详情 |
| `Glob` | 查找相关文件 |
| `Grep` | 搜索代码模式 |
| `mcp__ace-tool__search_context` | 语义搜索验证方案引用的代码 |
### CLI Capabilities
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue status <id> --json` | 加载 issue 详情 |
| `ccw issue solutions <id> --json` | 查看已绑定的方案 |
## Review Criteria
### Technical Feasibility (权重 40%)
| Criterion | Check |
|-----------|-------|
| File Coverage | 方案是否涵盖所有受影响的文件 |
| Dependency Awareness | 是否考虑到依赖变更的级联影响 |
| API Compatibility | 是否保持向后兼容 |
| Pattern Conformance | 是否遵循现有代码模式 |
### Risk Assessment (权重 30%)
| Criterion | Check |
|-----------|-------|
| Scope Creep | 方案是否超出 issue 的边界 |
| Breaking Changes | 是否引入破坏性变更 |
| Side Effects | 是否有未预见的副作用 |
| Rollback Path | 出问题时能否回退 |
### Completeness (权重 30%)
| Criterion | Check |
|-----------|-------|
| All Tasks Defined | 任务分解是否完整 |
| Test Coverage | 是否包含测试计划 |
| Edge Cases | 是否考虑边界情况 |
| Documentation | 关键变更是否有说明 |
### Verdict Rules
| Score | Verdict | Action |
|-------|---------|--------|
| ≥ 80% | `approved` | 可直接进入 MARSHAL 阶段 |
| 60-79% | `concerns` | 附带建议,不阻塞流程 |
| < 60% | `rejected` | 需要 planner 修订方案 |
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('AUDIT-') &&
t.owner === 'reviewer' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Context & Solution Loading
```javascript
// Extract issue IDs from task description
const issueIds = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || []
// Load explorer context reports
const contexts = {}
for (const issueId of issueIds) {
const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json`
try {
contexts[issueId] = JSON.parse(Read(contextPath))
} catch {
contexts[issueId] = null // No explorer context
}
}
// Load solution plans
const solutions = {}
for (const issueId of issueIds) {
const solJson = Bash(`ccw issue solutions ${issueId} --json`)
solutions[issueId] = JSON.parse(solJson)
}
```
### Phase 3: Multi-Dimensional Review
```javascript
const reviewResults = []
for (const issueId of issueIds) {
const context = contexts[issueId]
const solution = solutions[issueId]
if (!solution || !solution.bound) {
reviewResults.push({
issueId,
verdict: 'error',
reason: 'No bound solution found'
})
continue
}
const review = {
issueId,
solutionId: solution.bound.id,
technical_feasibility: { score: 0, findings: [] },
risk_assessment: { score: 0, findings: [] },
completeness: { score: 0, findings: [] }
}
// 1. Technical Feasibility — verify solution references real files + semantic validation
if (context && context.relevant_files) {
const solutionFiles = solution.bound.tasks?.flatMap(t => t.files || []) || []
const contextFiles = context.relevant_files.map(f => f.path || f)
const uncovered = contextFiles.filter(f => !solutionFiles.some(sf => sf.includes(f)))
if (uncovered.length === 0) {
review.technical_feasibility.score = 100
} else {
review.technical_feasibility.score = Math.max(40, 100 - uncovered.length * 15)
review.technical_feasibility.findings.push(
`Uncovered files: ${uncovered.join(', ')}`
)
}
// Semantic validation via ACE — verify solution references exist in codebase
const projectRoot = Bash('pwd').trim()
const aceResults = mcp__ace-tool__search_context({
project_root_path: projectRoot,
query: `${solution.bound.title || issue.title}. Verify patterns: ${solutionFiles.slice(0, 5).join(', ')}`
})
if (aceResults && aceResults.length > 0) {
// Cross-check ACE results against solution's assumed patterns
const aceFiles = aceResults.map(r => r.file || r.path).filter(Boolean)
const missedByAce = solutionFiles.filter(sf => !aceFiles.some(af => af.includes(sf)))
if (missedByAce.length > solutionFiles.length * 0.5) {
review.technical_feasibility.score = Math.max(50, review.technical_feasibility.score - 10)
review.technical_feasibility.findings.push(
`ACE semantic search found divergent patterns — solution may reference outdated code`
)
}
}
} else {
review.technical_feasibility.score = 70 // No context to validate against
review.technical_feasibility.findings.push('Explorer context not available for cross-validation')
}
// 2. Risk Assessment — check for breaking changes, scope
const taskCount = solution.bound.task_count || solution.bound.tasks?.length || 0
if (taskCount > 10) {
review.risk_assessment.score = 50
review.risk_assessment.findings.push(`High task count (${taskCount}) indicates possible scope creep`)
} else {
review.risk_assessment.score = 90
}
// 3. Completeness — check task definitions
if (taskCount > 0) {
review.completeness.score = 85
} else {
review.completeness.score = 30
review.completeness.findings.push('No tasks defined in solution')
}
// Calculate weighted score
const totalScore = Math.round(
review.technical_feasibility.score * 0.4 +
review.risk_assessment.score * 0.3 +
review.completeness.score * 0.3
)
// Determine verdict
let verdict
if (totalScore >= 80) verdict = 'approved'
else if (totalScore >= 60) verdict = 'concerns'
else verdict = 'rejected'
review.total_score = totalScore
review.verdict = verdict
reviewResults.push(review)
}
```
### Phase 4: Compile Review Report
```javascript
// Determine overall verdict
const hasRejected = reviewResults.some(r => r.verdict === 'rejected')
const hasConcerns = reviewResults.some(r => r.verdict === 'concerns')
const overallVerdict = hasRejected ? 'rejected' : hasConcerns ? 'concerns' : 'approved'
// Build feedback for rejected solutions
const rejectedFeedback = reviewResults
.filter(r => r.verdict === 'rejected')
.map(r => `### ${r.issueId} (Score: ${r.total_score}%)
${r.technical_feasibility.findings.map(f => `- [Technical] ${f}`).join('\n')}
${r.risk_assessment.findings.map(f => `- [Risk] ${f}`).join('\n')}
${r.completeness.findings.map(f => `- [Completeness] ${f}`).join('\n')}`)
.join('\n\n')
// Write review report
const reportPath = `.workflow/.team-plan/issue/audit-report.json`
Write(reportPath, JSON.stringify({
timestamp: new Date().toISOString(),
overall_verdict: overallVerdict,
reviews: reviewResults
}, null, 2))
```
### Phase 5: Report to Coordinator
```javascript
// Choose message type based on verdict
const msgType = overallVerdict // 'approved' | 'rejected' | 'concerns'
mcp__ccw-tools__team_msg({
operation: "log",
team: "issue",
from: "reviewer",
to: "coordinator",
type: msgType,
summary: `[reviewer] ${overallVerdict.toUpperCase()}: ${reviewResults.length} solutions reviewed, score avg=${Math.round(reviewResults.reduce((a,r) => a + (r.total_score || 0), 0) / reviewResults.length)}%`,
ref: reportPath
type: <message-type>,
summary: "[reviewer] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [reviewer] Audit Results — ${overallVerdict.toUpperCase()}
**Overall**: ${overallVerdict}
**Solutions Reviewed**: ${reviewResults.length}
${reviewResults.map(r => `### ${r.issueId}${r.verdict} (${r.total_score}%)
- Technical: ${r.technical_feasibility.score}%
- Risk: ${r.risk_assessment.score}%
- Completeness: ${r.completeness.score}%
${r.verdict === 'rejected' ? `\n**Rejection Reasons**:\n${[...r.technical_feasibility.findings, ...r.risk_assessment.findings, ...r.completeness.findings].map(f => '- ' + f).join('\n')}` : ''}`).join('\n\n')}
${overallVerdict === 'rejected' ? `\n**Action Required**: Coordinator should create SOLVE-fix task for planner to revise rejected solutions.` : ''}
**Report**: ${reportPath}`,
summary: `[reviewer] AUDIT ${overallVerdict}: ${reviewResults.length} solutions`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('AUDIT-') &&
t.owner === 'reviewer' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team issue --from reviewer --to coordinator --type <message-type> --summary \"[reviewer] ...\" --ref <artifact-path> --json")
```
---
## Review Criteria
### Technical Feasibility (Weight 40%)
| Criterion | Check |
|-----------|-------|
| File Coverage | Solution covers all affected files |
| Dependency Awareness | Considers dependency cascade effects |
| API Compatibility | Maintains backward compatibility |
| Pattern Conformance | Follows existing code patterns |
### Risk Assessment (Weight 30%)
| Criterion | Check |
|-----------|-------|
| Scope Creep | Solution stays within issue boundary |
| Breaking Changes | No destructive modifications |
| Side Effects | No unforeseen side effects |
| Rollback Path | Can rollback if issues occur |
### Completeness (Weight 30%)
| Criterion | Check |
|-----------|-------|
| All Tasks Defined | Task decomposition is complete |
| Test Coverage | Includes test plan |
| Edge Cases | Considers boundary conditions |
| Documentation | Key changes are documented |
### Verdict Rules
| Score | Verdict | Action |
|-------|---------|--------|
| >= 80% | `approved` | Proceed to MARSHAL phase |
| 60-79% | `concerns` | Include suggestions, non-blocking |
| < 60% | `rejected` | Requires planner revision |
---
## Execution (5-Phase)
### Phase 1: Task Discovery
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
Standard task discovery flow: TaskList -> filter by prefix `AUDIT-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Context & Solution Loading
**Input Sources**:
| Input | Source | Required |
|-------|--------|----------|
| Issue IDs | Task description (GH-\d+ or ISS-\d{8}-\d{6}) | Yes |
| Explorer context | `.workflow/.team-plan/issue/context-<issueId>.json` | No |
| Bound solution | `ccw issue solutions <id> --json` | Yes |
**Loading steps**:
1. Extract issue IDs from task description via regex
2. Load explorer context reports for each issue:
```
Read(".workflow/.team-plan/issue/context-<issueId>.json")
```
3. Load bound solutions for each issue:
```
Bash("ccw issue solutions <issueId> --json")
```
### Phase 3: Multi-Dimensional Review
**Review execution for each issue**:
| Dimension | Weight | Validation Method |
|-----------|--------|-------------------|
| Technical Feasibility | 40% | Cross-check solution files against explorer context + ACE semantic validation |
| Risk Assessment | 30% | Analyze task count for scope creep, check for breaking changes |
| Completeness | 30% | Verify task definitions exist, check for test plan |
**Technical Feasibility validation**:
| Condition | Score Impact |
|-----------|--------------|
| All context files covered by solution | 100% |
| Partial coverage (some files missing) | -15% per uncovered file, min 40% |
| ACE results diverge from solution patterns | -10% |
| No explorer context available | 70% (limited validation) |
**Risk Assessment validation**:
| Condition | Score |
|-----------|-------|
| Task count <= 10 | 90% |
| Task count > 10 (possible scope creep) | 50% |
**Completeness validation**:
| Condition | Score |
|-----------|-------|
| Tasks defined (count > 0) | 85% |
| No tasks defined | 30% |
**ACE semantic validation**:
```
mcp__ace-tool__search_context({
project_root_path: <projectRoot>,
query: "<solution.title>. Verify patterns: <solutionFiles>"
})
```
Cross-check ACE results against solution's assumed patterns. If >50% of solution files not found in ACE results, flag as potentially outdated.
### Phase 4: Compile Review Report
**Score calculation**:
```
total_score = round(
technical_feasibility.score * 0.4 +
risk_assessment.score * 0.3 +
completeness.score * 0.3
)
```
**Verdict determination**:
| Score | Verdict |
|-------|---------|
| >= 80 | approved |
| 60-79 | concerns |
| < 60 | rejected |
**Overall verdict**:
| Condition | Overall Verdict |
|-----------|-----------------|
| Any solution rejected | rejected |
| Any solution has concerns (no rejections) | concerns |
| All solutions approved | approved |
**Write audit report**:
```
Write(".workflow/.team-plan/issue/audit-report.json", {
timestamp: <ISO timestamp>,
overall_verdict: <verdict>,
reviews: [{
issueId, solutionId, total_score, verdict,
technical_feasibility: { score, findings },
risk_assessment: { score, findings },
completeness: { score, findings }
}]
})
```
### Phase 5: Report to Coordinator
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
Standard report flow: team_msg log -> SendMessage with `[reviewer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
**Report content includes**:
- Overall verdict
- Per-issue scores and verdicts
- Rejection reasons (if any)
- Action required for rejected solutions
---
## Error Handling
| Scenario | Resolution |
@@ -319,5 +263,6 @@ if (nextTasks.length > 0) {
| No AUDIT-* tasks available | Idle, wait for coordinator |
| Solution file not found | Check ccw issue solutions, report error if missing |
| Explorer context missing | Proceed with limited review (lower technical score) |
| All solutions rejected | Report to coordinator for CP-2 review-fix cycle |
| All solutions rejected | Report to coordinator for review-fix cycle |
| Review timeout | Report partial results with available data |
| Context/Plan file not found | Notify coordinator, request location |