mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 11:13:25 +08:00
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:
@@ -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(batch≤5) → SOLVE-001..N(batch≤3) → 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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
- 所有输出(SendMessage、team_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-agent、issue-queue-agent、code-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 ID(GH-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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user