mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +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,157 +6,145 @@ allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), Task
|
||||
|
||||
# Team Brainstorm
|
||||
|
||||
头脑风暴团队技能。通过 Generator-Critic 循环、共享记忆和动态管道选择,实现多角度创意发散、挑战验证和收敛筛选。所有团队成员通过 `--role=xxx` 路由到角色执行逻辑。
|
||||
Unified team skill: multi-angle brainstorming via Generator-Critic loops, shared memory, and dynamic pipeline selection. All team members invoke with `--role=xxx` to route to role-specific execution.
|
||||
|
||||
## Architecture Overview
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────┐
|
||||
│ Skill(skill="team-brainstorm", args="--role=xxx") │
|
||||
│ Skill(skill="team-brainstorm") │
|
||||
│ args="<topic>" or args="--role=xxx" │
|
||||
└───────────────────┬───────────────────────────────┘
|
||||
│ Role Router
|
||||
┌───────────┬───┼───────────┬───────────┐
|
||||
↓ ↓ ↓ ↓ ↓
|
||||
┌──────────┐┌───────┐┌──────────┐┌──────────┐┌─────────┐
|
||||
│coordinator││ideator││challenger││synthesizer││evaluator│
|
||||
│ roles/ ││roles/ ││ roles/ ││ roles/ ││ roles/ │
|
||||
└──────────┘└───────┘└──────────┘└──────────┘└─────────┘
|
||||
┌──── --role present? ────┐
|
||||
│ NO │ YES
|
||||
↓ ↓
|
||||
Orchestration Mode Role Dispatch
|
||||
(auto → coordinator) (route to role.md)
|
||||
│
|
||||
┌────┴────┬───────────┬───────────┬───────────┐
|
||||
↓ ↓ ↓ ↓ ↓
|
||||
┌──────────┐┌─────────┐┌──────────┐┌──────────┐┌─────────┐
|
||||
│coordinator││ ideator ││challenger││synthesizer││evaluator│
|
||||
│ ││ IDEA-* ││CHALLENGE-*││ SYNTH-* ││ EVAL-* │
|
||||
└──────────┘└─────────┘└──────────┘└──────────┘└─────────┘
|
||||
```
|
||||
|
||||
## Role Router
|
||||
|
||||
### Input Parsing
|
||||
|
||||
Parse `$ARGUMENTS` to extract `--role`:
|
||||
Parse `$ARGUMENTS` to extract `--role`. If absent → Orchestration Mode (auto route to coordinator).
|
||||
|
||||
```javascript
|
||||
const args = "$ARGUMENTS"
|
||||
const roleMatch = args.match(/--role[=\s]+(\w+)/)
|
||||
### Role Registry
|
||||
|
||||
if (!roleMatch) {
|
||||
throw new Error("Missing --role argument. Available roles: coordinator, ideator, challenger, synthesizer, evaluator")
|
||||
}
|
||||
| Role | File | Task Prefix | Type | Compact |
|
||||
|------|------|-------------|------|---------|
|
||||
| coordinator | [roles/coordinator.md](roles/coordinator.md) | (none) | orchestrator | **⚠️ 压缩后必须重读** |
|
||||
| ideator | [roles/ideator.md](roles/ideator.md) | IDEA-* | pipeline | 压缩后必须重读 |
|
||||
| challenger | [roles/challenger.md](roles/challenger.md) | CHALLENGE-* | pipeline | 压缩后必须重读 |
|
||||
| synthesizer | [roles/synthesizer.md](roles/synthesizer.md) | SYNTH-* | pipeline | 压缩后必须重读 |
|
||||
| evaluator | [roles/evaluator.md](roles/evaluator.md) | EVAL-* | pipeline | 压缩后必须重读 |
|
||||
|
||||
const role = roleMatch[1]
|
||||
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "brainstorm"
|
||||
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 just provides topic description.
|
||||
|
||||
**Invocation**: `Skill(skill="team-brainstorm", args="<topic-description>")`
|
||||
|
||||
**Lifecycle**:
|
||||
```
|
||||
User provides topic description
|
||||
→ coordinator Phase 1-3: Topic clarification → 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 },
|
||||
"ideator": { file: "roles/ideator.md", prefix: "IDEA" },
|
||||
"challenger": { file: "roles/challenger.md", prefix: "CHALLENGE" },
|
||||
"synthesizer": { file: "roles/synthesizer.md", prefix: "SYNTH" },
|
||||
"evaluator": { file: "roles/evaluator.md", prefix: "EVAL" }
|
||||
}
|
||||
| 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 | Role File |
|
||||
|------|-------------|----------------|-----------|
|
||||
| `coordinator` | N/A | 话题澄清、复杂度评估、管道选择、收敛监控 | [roles/coordinator.md](roles/coordinator.md) |
|
||||
| `ideator` | IDEA-* | 多角度创意生成、概念探索、发散思维 | [roles/ideator.md](roles/ideator.md) |
|
||||
| `challenger` | CHALLENGE-* | 魔鬼代言人、假设挑战、可行性质疑 | [roles/challenger.md](roles/challenger.md) |
|
||||
| `synthesizer` | SYNTH-* | 跨想法整合、主题提取、冲突解决 | [roles/synthesizer.md](roles/synthesizer.md) |
|
||||
| `evaluator` | EVAL-* | 评分排序、优先级推荐、最终筛选 | [roles/evaluator.md](roles/evaluator.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="brainstorm", from=<role>, to="coordinator", type=<message-type>, summary="[<role>] <summary>", ref=<artifact-path>
|
||||
- **CLI fallback**: When MCP unavailable → `ccw team log --team brainstorm --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 |
|
||||
| Read/write shared-memory.json (own fields) | Create tasks for other roles |
|
||||
| Delegate to commands/ files | Modify resources outside own responsibility |
|
||||
|
||||
#### Output Tagging(强制)
|
||||
Coordinator additional restrictions: Do not generate ideas directly, do not evaluate/challenge ideas, do not execute analysis/synthesis, do not bypass workers.
|
||||
|
||||
所有角色的输出必须带 `[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) | ❌ 直接评估/挑战想法 |
|
||||
| 分发任务给 worker | ❌ 直接执行分析/综合 |
|
||||
| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成任务 |
|
||||
| 汇报结果给用户 | ❌ 修改源代码或产物文件 |
|
||||
|
||||
#### Worker 隔离
|
||||
|
||||
| 允许 | 禁止 |
|
||||
|------|------|
|
||||
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
|
||||
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
|
||||
| 读取 shared-memory.json | ❌ 为其他角色创建任务 (TaskCreate) |
|
||||
| 写入 shared-memory.json (自己的字段) | ❌ 修改不属于本职责的资源 |
|
||||
|
||||
### Team Configuration
|
||||
|
||||
```javascript
|
||||
const TEAM_CONFIG = {
|
||||
name: "brainstorm",
|
||||
sessionDir: ".workflow/.team/BRS-{slug}-{date}/",
|
||||
sharedMemory: "shared-memory.json"
|
||||
}
|
||||
```
|
||||
|
||||
### Shared Memory (创新模式)
|
||||
|
||||
所有角色在 Phase 2 读取、Phase 5 写入 `shared-memory.json`:
|
||||
|
||||
```javascript
|
||||
// Phase 2: 读取共享记忆
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
|
||||
// Phase 5: 写入共享记忆(仅更新自己负责的字段)
|
||||
// ideator → sharedMemory.generated_ideas
|
||||
// challenger → sharedMemory.critique_insights
|
||||
// synthesizer → sharedMemory.synthesis_themes
|
||||
// evaluator → sharedMemory.evaluation_scores
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
```
|
||||
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: teamName,
|
||||
from: role,
|
||||
to: "coordinator",
|
||||
type: "<type>",
|
||||
summary: `[${role}] <summary>`,
|
||||
ref: "<file_path>"
|
||||
})
|
||||
```
|
||||
**Parameters**: operation="log", team="brainstorm", from=<role>, to="coordinator", type=<message-type>, summary="[<role>] <summary>", ref=<artifact-path>
|
||||
|
||||
**CLI fallback**: When MCP unavailable → `ccw team log --team brainstorm --from <role> --to coordinator --type <type> --summary "[<role>] ..." --json`
|
||||
|
||||
**Message types by role**:
|
||||
|
||||
@@ -168,36 +156,26 @@ mcp__ccw-tools__team_msg({
|
||||
| synthesizer | `synthesis_ready`, `error` |
|
||||
| evaluator | `evaluation_ready`, `error` |
|
||||
|
||||
### CLI Fallback
|
||||
### Shared Memory
|
||||
|
||||
When `mcp__ccw-tools__team_msg` MCP is unavailable:
|
||||
All roles read in Phase 2 and write in Phase 5 to `shared-memory.json`:
|
||||
|
||||
```javascript
|
||||
Bash(`ccw team log --team "${teamName}" --from "${role}" --to "coordinator" --type "<type>" --summary "<summary>" --json`)
|
||||
```
|
||||
| Role | Field |
|
||||
|------|-------|
|
||||
| ideator | `generated_ideas` |
|
||||
| challenger | `critique_insights` |
|
||||
| synthesizer | `synthesis_themes` |
|
||||
| evaluator | `evaluation_scores` |
|
||||
|
||||
### Task Lifecycle (All Worker Roles)
|
||||
### Team Configuration
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
|
||||
t.owner === agentName && // Use agentName (e.g., 'ideator-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' })
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Team name | brainstorm |
|
||||
| Session directory | `.workflow/.team/BRS-<slug>-<date>/` |
|
||||
| Shared memory | `shared-memory.json` in session dir |
|
||||
|
||||
// Phase 2-4: Role-specific (see roles/{role}.md)
|
||||
|
||||
// Phase 5: Report + Loop — 所有输出必须带 [role] 标识
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, 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
|
||||
```
|
||||
---
|
||||
|
||||
## Three-Pipeline Architecture
|
||||
|
||||
@@ -214,19 +192,193 @@ Full (Fan-out + Generator-Critic):
|
||||
|
||||
### Generator-Critic Loop
|
||||
|
||||
ideator ↔ challenger 循环,最多2轮:
|
||||
ideator <-> challenger loop, max 2 rounds:
|
||||
|
||||
```
|
||||
IDEA → CHALLENGE → (if critique.severity >= HIGH) → IDEA-fix → CHALLENGE-2 → SYNTH
|
||||
(if critique.severity < HIGH) → SYNTH
|
||||
```
|
||||
|
||||
### Cadence Control
|
||||
|
||||
**Beat model**: Event-driven, each beat = coordinator wake → process → spawn → STOP. Brainstorm beat: generate → challenge → synthesize → evaluate.
|
||||
|
||||
```
|
||||
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 (3 beats, strictly serial)
|
||||
──────────────────────────────────────────────────────────
|
||||
Beat 1 2 3
|
||||
│ │ │
|
||||
IDEA → CHALLENGE ──→ SYNTH
|
||||
▲ ▲
|
||||
pipeline pipeline
|
||||
start done
|
||||
|
||||
IDEA=ideator CHALLENGE=challenger SYNTH=synthesizer
|
||||
|
||||
Deep (5-6 beats, with Generator-Critic loop)
|
||||
──────────────────────────────────────────────────────────
|
||||
Beat 1 2 3 4 5 6
|
||||
│ │ │ │ │ │
|
||||
IDEA → CHALLENGE → (GC loop?) → IDEA-fix → SYNTH → EVAL
|
||||
│
|
||||
severity check
|
||||
(< HIGH → skip to SYNTH)
|
||||
|
||||
Full (4-7 beats, fan-out + Generator-Critic)
|
||||
──────────────────────────────────────────────────────────
|
||||
Beat 1 2 3-4 5 6
|
||||
┌────┴────┐ │ │ │ │
|
||||
IDEA-1 ∥ IDEA-2 ∥ IDEA-3 → CHALLENGE → (GC loop) → SYNTH → EVAL
|
||||
▲ ▲
|
||||
parallel pipeline
|
||||
window done
|
||||
```
|
||||
|
||||
**Checkpoints**:
|
||||
|
||||
| Trigger | Location | Behavior |
|
||||
|---------|----------|----------|
|
||||
| Generator-Critic loop | After CHALLENGE-* | If severity >= HIGH → create IDEA-fix task; else proceed to SYNTH |
|
||||
| GC loop limit | Max 2 rounds | Exceeds limit → force convergence to SYNTH |
|
||||
| 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 |
|
||||
| GC loop exceeded | ideator/challenger iteration > 2 rounds | Terminate loop, force convergence to synthesizer |
|
||||
|
||||
### Task Metadata Registry
|
||||
|
||||
| Task ID | Role | Phase | Dependencies | Description |
|
||||
|---------|------|-------|-------------|-------------|
|
||||
| IDEA-001 | ideator | generate | (none) | Multi-angle idea generation |
|
||||
| IDEA-002 | ideator | generate | (none) | Parallel angle (Full pipeline only) |
|
||||
| IDEA-003 | ideator | generate | (none) | Parallel angle (Full pipeline only) |
|
||||
| CHALLENGE-001 | challenger | challenge | IDEA-001 (or all IDEA-*) | Devil's advocate critique and feasibility challenge |
|
||||
| IDEA-004 | ideator | gc-fix | CHALLENGE-001 | Revision based on critique (GC loop, if triggered) |
|
||||
| CHALLENGE-002 | challenger | gc-fix | IDEA-004 | Re-critique of revised ideas (GC loop round 2) |
|
||||
| SYNTH-001 | synthesizer | synthesize | last CHALLENGE-* | Cross-idea integration, theme extraction, conflict resolution |
|
||||
| EVAL-001 | evaluator | evaluate | SYNTH-001 | Scoring, ranking, priority recommendation, final selection |
|
||||
|
||||
---
|
||||
|
||||
## Coordinator Spawn Template
|
||||
|
||||
When coordinator spawns workers, use background mode (Spawn-and-Stop).
|
||||
|
||||
**Standard spawn** (single agent per role): For Quick/Deep pipeline, spawn one ideator. Challenger, synthesizer, and evaluator are always single agents.
|
||||
|
||||
**Parallel spawn** (Full pipeline): For Full pipeline with N idea angles, spawn N ideator agents in parallel (`ideator-1`, `ideator-2`, ...) with `run_in_background: true`. Each parallel ideator only processes tasks where owner matches its agent name. After all parallel ideators complete, proceed with single challenger for batch critique.
|
||||
|
||||
**Spawn template**:
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: "Spawn <role> worker",
|
||||
team_name: "brainstorm",
|
||||
name: "<role>",
|
||||
run_in_background: true,
|
||||
prompt: `You are team "brainstorm" <ROLE>.
|
||||
|
||||
## Primary Directive
|
||||
All your work must be executed through Skill to load role definition:
|
||||
Skill(skill="team-brainstorm", args="--role=<role>")
|
||||
|
||||
Current topic: <topic-description>
|
||||
Session: <session-folder>
|
||||
|
||||
## 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
|
||||
|
||||
## 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`
|
||||
})
|
||||
```
|
||||
|
||||
**Parallel ideator spawn** (Full pipeline with N angles):
|
||||
|
||||
> When Full pipeline has N parallel IDEA tasks assigned to ideator role, spawn N distinct agents named `ideator-1`, `ideator-2`, etc. Each agent only processes tasks where owner matches its agent name.
|
||||
|
||||
| Condition | Action |
|
||||
|-----------|--------|
|
||||
| Full pipeline with N idea angles (N > 1) | Spawn N agents: `ideator-1`, `ideator-2`, ... `ideator-N` with `run_in_background: true` |
|
||||
| Quick/Deep pipeline (single ideator) | Standard spawn: single `ideator` agent |
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: "Spawn ideator-<N> worker",
|
||||
team_name: "brainstorm",
|
||||
name: "ideator-<N>",
|
||||
run_in_background: true,
|
||||
prompt: `You are team "brainstorm" IDEATOR (ideator-<N>).
|
||||
Your agent name is "ideator-<N>", use this name for task discovery owner matching.
|
||||
|
||||
## Primary Directive
|
||||
Skill(skill="team-brainstorm", args="--role=ideator --agent-name=ideator-<N>")
|
||||
|
||||
Current topic: <topic-description>
|
||||
Session: <session-folder>
|
||||
|
||||
## Role Guidelines
|
||||
- Only process tasks where owner === "ideator-<N>" with IDEA-* prefix
|
||||
- All output prefixed with [ideator] identifier
|
||||
|
||||
## Workflow
|
||||
1. TaskList -> find tasks where owner === "ideator-<N>" with IDEA-* prefix
|
||||
2. Skill -> execute role definition
|
||||
3. team_msg + SendMessage results to coordinator
|
||||
4. TaskUpdate completed -> check next task`
|
||||
})
|
||||
```
|
||||
|
||||
**Dispatch must match agent names**: When dispatching parallel IDEA tasks, coordinator sets each task's owner to the corresponding instance name (`ideator-1`, `ideator-2`, etc.). In role.md, task discovery uses `--agent-name` for owner matching.
|
||||
|
||||
---
|
||||
|
||||
## Unified Session Directory
|
||||
|
||||
```
|
||||
.workflow/.team/BRS-{slug}-{YYYY-MM-DD}/
|
||||
.workflow/.team/BRS-<slug>-<YYYY-MM-DD>/
|
||||
├── team-session.json # Session state
|
||||
├── shared-memory.json # 累积: generated_ideas / critique_insights / synthesis_themes / evaluation_scores
|
||||
├── shared-memory.json # Cumulative: generated_ideas / critique_insights / synthesis_themes / evaluation_scores
|
||||
├── wisdom/ # Cross-task knowledge
|
||||
│ ├── learnings.md
|
||||
│ ├── decisions.md
|
||||
│ ├── conventions.md
|
||||
│ └── issues.md
|
||||
├── ideas/ # Ideator output
|
||||
│ ├── idea-001.md
|
||||
│ ├── idea-002.md
|
||||
@@ -240,159 +392,13 @@ IDEA → CHALLENGE → (if critique.severity >= HIGH) → IDEA-fix → CHALLENGE
|
||||
└── evaluation-001.md
|
||||
```
|
||||
|
||||
## Coordinator Spawn Template
|
||||
|
||||
```javascript
|
||||
TeamCreate({ team_name: teamName })
|
||||
|
||||
// Ideator — conditional parallel spawn for Full pipeline (multiple angles)
|
||||
const isFullPipeline = selectedPipeline === 'full'
|
||||
const ideaAngles = selectedAngles || []
|
||||
|
||||
if (isFullPipeline && ideaAngles.length > 1) {
|
||||
// Full pipeline: spawn N ideators for N parallel angle tasks
|
||||
for (let i = 0; i < ideaAngles.length; i++) {
|
||||
const agentName = `ideator-${i + 1}`
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn ${agentName} worker`,
|
||||
team_name: teamName,
|
||||
name: agentName,
|
||||
prompt: `你是 team "${teamName}" 的 IDEATOR (${agentName})。
|
||||
你的 agent 名称是 "${agentName}",任务发现时用此名称匹配 owner。
|
||||
|
||||
当你收到 IDEA-* 任务时,调用 Skill(skill="team-brainstorm", args="--role=ideator --agent-name=${agentName}") 执行。
|
||||
当前话题: ${taskDescription}
|
||||
约束: ${constraints}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 owner 为 "${agentName}" 的 IDEA-* 前缀任务
|
||||
- 所有输出(SendMessage、team_msg)必须带 [ideator] 标识前缀
|
||||
- 仅与 coordinator 通信,不得直接联系其他 worker
|
||||
- 不得使用 TaskCreate 为其他角色创建任务
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 owner === "${agentName}" 的 IDEA-* 任务
|
||||
2. Skill(skill="team-brainstorm", args="--role=ideator --agent-name=${agentName}") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [ideator] 标识)
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Quick/Deep pipeline: single ideator
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn ideator worker`,
|
||||
team_name: teamName,
|
||||
name: "ideator",
|
||||
prompt: `你是 team "${teamName}" 的 IDEATOR。
|
||||
当你收到 IDEA-* 任务时,调用 Skill(skill="team-brainstorm", args="--role=ideator") 执行。
|
||||
当前话题: ${taskDescription}
|
||||
约束: ${constraints}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 IDEA-* 前缀的任务,不得执行其他角色的工作
|
||||
- 所有输出(SendMessage、team_msg)必须带 [ideator] 标识前缀
|
||||
- 仅与 coordinator 通信,不得直接联系其他 worker
|
||||
- 不得使用 TaskCreate 为其他角色创建任务
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 IDEA-* 任务
|
||||
2. Skill(skill="team-brainstorm", args="--role=ideator") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [ideator] 标识)
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
}
|
||||
|
||||
// Challenger
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn challenger worker`,
|
||||
team_name: teamName,
|
||||
name: "challenger",
|
||||
prompt: `你是 team "${teamName}" 的 CHALLENGER。
|
||||
当你收到 CHALLENGE-* 任务时,调用 Skill(skill="team-brainstorm", args="--role=challenger") 执行。
|
||||
当前话题: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 CHALLENGE-* 前缀的任务
|
||||
- 所有输出必须带 [challenger] 标识前缀
|
||||
- 仅与 coordinator 通信
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 CHALLENGE-* 任务
|
||||
2. Skill(skill="team-brainstorm", args="--role=challenger") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [challenger] 标识)
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
|
||||
// Synthesizer
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn synthesizer worker`,
|
||||
team_name: teamName,
|
||||
name: "synthesizer",
|
||||
prompt: `你是 team "${teamName}" 的 SYNTHESIZER。
|
||||
当你收到 SYNTH-* 任务时,调用 Skill(skill="team-brainstorm", args="--role=synthesizer") 执行。
|
||||
当前话题: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 SYNTH-* 前缀的任务
|
||||
- 所有输出必须带 [synthesizer] 标识前缀
|
||||
- 仅与 coordinator 通信
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 SYNTH-* 任务
|
||||
2. Skill(skill="team-brainstorm", args="--role=synthesizer") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [synthesizer] 标识)
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
|
||||
// Evaluator
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn evaluator worker`,
|
||||
team_name: teamName,
|
||||
name: "evaluator",
|
||||
prompt: `你是 team "${teamName}" 的 EVALUATOR。
|
||||
当你收到 EVAL-* 任务时,调用 Skill(skill="team-brainstorm", args="--role=evaluator") 执行。
|
||||
当前话题: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 EVAL-* 前缀的任务
|
||||
- 所有输出必须带 [evaluator] 标识前缀
|
||||
- 仅与 coordinator 通信
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 EVAL-* 任务
|
||||
2. Skill(skill="team-brainstorm", args="--role=evaluator") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [evaluator] 标识)
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| Unknown --role value | Error with available role list |
|
||||
| Missing --role arg | Error with usage hint |
|
||||
| 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 |
|
||||
| Generator-Critic loop exceeds 2 rounds | Force convergence → SYNTH |
|
||||
| No ideas generated | Coordinator prompts with seed questions |
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# Role: challenger
|
||||
# Challenger Role
|
||||
|
||||
魔鬼代言人角色。负责假设挑战、可行性质疑、风险识别。作为 Generator-Critic 循环中的 Critic 角色。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `challenger`
|
||||
- **Name**: `challenger` | **Tag**: `[challenger]`
|
||||
- **Task Prefix**: `CHALLENGE-*`
|
||||
- **Responsibility**: Read-only analysis (批判性分析)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[challenger]`
|
||||
- **Responsibility**: Read-only analysis (critical analysis)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
@@ -22,181 +20,141 @@
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 生成创意、综合想法或评估排序
|
||||
- ❌ 直接与其他 worker 角色通信
|
||||
- ❌ 为其他角色创建任务
|
||||
- ❌ 修改 shared-memory.json 中不属于自己的字段
|
||||
- 生成创意、综合想法或评估排序
|
||||
- 直接与其他 worker 角色通信
|
||||
- 为其他角色创建任务
|
||||
- 修改 shared-memory.json 中不属于自己的字段
|
||||
- 在输出中省略 `[challenger]` 标识
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `TaskList` | Built-in | Phase 1 | Discover pending CHALLENGE-* tasks |
|
||||
| `TaskGet` | Built-in | Phase 1 | Get task details |
|
||||
| `TaskUpdate` | Built-in | Phase 1/5 | Update task status |
|
||||
| `Read` | Built-in | Phase 2 | Read shared-memory.json, idea files |
|
||||
| `Write` | Built-in | Phase 3/5 | Write critique files, update shared memory |
|
||||
| `Glob` | Built-in | Phase 2 | Find idea files |
|
||||
| `SendMessage` | Built-in | Phase 5 | Report to coordinator |
|
||||
| `mcp__ccw-tools__team_msg` | MCP | Phase 5 | Log communication |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `critique_ready` | challenger → coordinator | Critique completed | 挑战分析完成 |
|
||||
| `error` | challenger → coordinator | Processing failure | 错误上报 |
|
||||
| `critique_ready` | challenger -> coordinator | Critique completed | Critical analysis complete |
|
||||
| `error` | challenger -> coordinator | Processing failure | Error report |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "challenger",
|
||||
to: "coordinator",
|
||||
type: "critique_ready",
|
||||
summary: "[challenger] Critique complete: <critical>C/<high>H/<medium>M/<low>L -- Signal: <signal>",
|
||||
ref: <output-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from challenger --to coordinator --type critique_ready --summary \"[challenger] Critique complete\" --ref <output-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('CHALLENGE-') &&
|
||||
t.owner === 'challenger' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `CHALLENGE-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Context Loading + Shared Memory Read
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | Task description (Session: line) | Yes |
|
||||
| Ideas | ideas/*.md files | Yes |
|
||||
| Previous critiques | shared-memory.json.critique_insights | No (avoid repeating) |
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
**Loading steps**:
|
||||
|
||||
// Read all idea files referenced in task
|
||||
const ideaFiles = Glob({ pattern: `${sessionFolder}/ideas/*.md` })
|
||||
const ideas = ideaFiles.map(f => Read(f))
|
||||
|
||||
// Read previous critiques for context (avoid repeating)
|
||||
const prevCritiques = sharedMemory.critique_insights || []
|
||||
```
|
||||
1. Extract session path from task description (match "Session: <path>")
|
||||
2. Glob idea files from session folder
|
||||
3. Read all idea files for analysis
|
||||
4. Read shared-memory.json.critique_insights to avoid repeating
|
||||
|
||||
### Phase 3: Critical Analysis
|
||||
|
||||
```javascript
|
||||
// For each idea, apply 4 challenge dimensions:
|
||||
// 1. Assumption Validity — 核心假设是否成立?有什么反例?
|
||||
// 2. Feasibility — 技术/资源/时间上是否可行?
|
||||
// 3. Risk Assessment — 最坏情况是什么?有什么隐藏风险?
|
||||
// 4. Competitive Analysis — 已有更好的替代方案吗?
|
||||
**Challenge Dimensions** (apply to each idea):
|
||||
|
||||
// Severity classification:
|
||||
// LOW — Minor concern, does not invalidate the idea
|
||||
// MEDIUM — Notable weakness, needs consideration
|
||||
// HIGH — Significant flaw, requires revision
|
||||
// CRITICAL — Fundamental issue, idea may need replacement
|
||||
| Dimension | Focus |
|
||||
|-----------|-------|
|
||||
| Assumption Validity | Does the core assumption hold? Any counter-examples? |
|
||||
| Feasibility | Technical/resource/time feasibility? |
|
||||
| Risk Assessment | Worst case scenario? Hidden risks? |
|
||||
| Competitive Analysis | Better alternatives already exist? |
|
||||
|
||||
const challengeNum = task.subject.match(/CHALLENGE-(\d+)/)?.[1] || '001'
|
||||
const outputPath = `${sessionFolder}/critiques/critique-${challengeNum}.md`
|
||||
**Severity Classification**:
|
||||
|
||||
const critiqueContent = `# Critique — Round ${challengeNum}
|
||||
| Severity | Criteria |
|
||||
|----------|----------|
|
||||
| CRITICAL | Fundamental issue, idea may need replacement |
|
||||
| HIGH | Significant flaw, requires revision |
|
||||
| MEDIUM | Notable weakness, needs consideration |
|
||||
| LOW | Minor concern, does not invalidate the idea |
|
||||
|
||||
**Ideas Reviewed**: ${ideas.length} files
|
||||
**Challenge Dimensions**: Assumption Validity, Feasibility, Risk, Competition
|
||||
**Generator-Critic Signal**:
|
||||
|
||||
## Challenges
|
||||
| Condition | Signal |
|
||||
|-----------|--------|
|
||||
| Any CRITICAL or HIGH severity | REVISION_NEEDED -> ideator must revise |
|
||||
| All MEDIUM or lower | CONVERGED -> ready for synthesis |
|
||||
|
||||
${challenges.map((c, i) => `### Idea: ${c.ideaTitle}
|
||||
|
||||
**Severity**: ${c.severity}
|
||||
|
||||
| Dimension | Finding |
|
||||
|-----------|---------|
|
||||
| Assumption Validity | ${c.assumption} |
|
||||
| Feasibility | ${c.feasibility} |
|
||||
| Risk Assessment | ${c.risk} |
|
||||
| Competitive Analysis | ${c.competition} |
|
||||
|
||||
**Key Challenge**: ${c.keyChallenge}
|
||||
**Suggested Direction**: ${c.suggestion}
|
||||
`).join('\n')}
|
||||
|
||||
## Summary
|
||||
|
||||
| Severity | Count |
|
||||
|----------|-------|
|
||||
| CRITICAL | ${challenges.filter(c => c.severity === 'CRITICAL').length} |
|
||||
| HIGH | ${challenges.filter(c => c.severity === 'HIGH').length} |
|
||||
| MEDIUM | ${challenges.filter(c => c.severity === 'MEDIUM').length} |
|
||||
| LOW | ${challenges.filter(c => c.severity === 'LOW').length} |
|
||||
|
||||
**Generator-Critic Signal**: ${
|
||||
challenges.some(c => c.severity === 'CRITICAL' || c.severity === 'HIGH')
|
||||
? 'REVISION_NEEDED — Critical/High issues require ideator revision'
|
||||
: 'CONVERGED — No critical issues, ready for synthesis'
|
||||
}
|
||||
`
|
||||
|
||||
Write(outputPath, critiqueContent)
|
||||
```
|
||||
**Output file structure**:
|
||||
- File: `<session>/critiques/critique-<num>.md`
|
||||
- Sections: Ideas Reviewed, Challenge Dimensions, Per-idea challenges with severity table, Summary table with counts, GC Signal
|
||||
|
||||
### Phase 4: Severity Summary
|
||||
|
||||
```javascript
|
||||
// Aggregate severity counts for coordinator decision
|
||||
const severitySummary = {
|
||||
critical: challenges.filter(c => c.severity === 'CRITICAL').length,
|
||||
high: challenges.filter(c => c.severity === 'HIGH').length,
|
||||
medium: challenges.filter(c => c.severity === 'MEDIUM').length,
|
||||
low: challenges.filter(c => c.severity === 'LOW').length,
|
||||
signal: (challenges.some(c => c.severity === 'CRITICAL' || c.severity === 'HIGH'))
|
||||
? 'REVISION_NEEDED' : 'CONVERGED'
|
||||
}
|
||||
```
|
||||
**Aggregation**:
|
||||
1. Count challenges by severity level
|
||||
2. Determine signal based on presence of CRITICAL/HIGH
|
||||
|
||||
| Metric | Source |
|
||||
|--------|--------|
|
||||
| critical count | challenges with severity CRITICAL |
|
||||
| high count | challenges with severity HIGH |
|
||||
| medium count | challenges with severity MEDIUM |
|
||||
| low count | challenges with severity LOW |
|
||||
| signal | REVISION_NEEDED if critical+high > 0, else CONVERGED |
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
// Update shared memory
|
||||
sharedMemory.critique_insights = [
|
||||
...sharedMemory.critique_insights,
|
||||
...challenges.map(c => ({
|
||||
idea: c.ideaTitle,
|
||||
severity: c.severity,
|
||||
key_challenge: c.keyChallenge,
|
||||
round: parseInt(challengeNum)
|
||||
}))
|
||||
]
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "challenger",
|
||||
to: "coordinator",
|
||||
type: "critique_ready",
|
||||
summary: `[challenger] Critique complete: ${severitySummary.critical}C/${severitySummary.high}H/${severitySummary.medium}M/${severitySummary.low}L — Signal: ${severitySummary.signal}`,
|
||||
ref: outputPath
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[challenger]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [challenger] Critique Results
|
||||
**Shared Memory Update**:
|
||||
1. Append challenges to shared-memory.json.critique_insights
|
||||
2. Each entry: idea, severity, key_challenge, round
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Signal**: ${severitySummary.signal}
|
||||
**Severity**: ${severitySummary.critical} Critical, ${severitySummary.high} High, ${severitySummary.medium} Medium, ${severitySummary.low} Low
|
||||
**Output**: ${outputPath}
|
||||
|
||||
${severitySummary.signal === 'REVISION_NEEDED'
|
||||
? '### Requires Revision\n' + challenges.filter(c => ['CRITICAL', 'HIGH'].includes(c.severity)).map(c => `- **${c.ideaTitle}** (${c.severity}): ${c.keyChallenge}`).join('\n')
|
||||
: '### All Clear — Ready for Synthesis'}`,
|
||||
summary: `[challenger] Critique: ${severitySummary.signal}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('CHALLENGE-') &&
|
||||
t.owner === 'challenger' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
if (nextTasks.length > 0) {
|
||||
// back to Phase 1
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -206,3 +164,4 @@ if (nextTasks.length > 0) {
|
||||
| Ideas file not found | Notify coordinator |
|
||||
| All ideas trivially good | Mark all LOW, signal CONVERGED |
|
||||
| Cannot assess feasibility | Mark MEDIUM with note, suggest deeper analysis |
|
||||
| Critical issue beyond scope | SendMessage error to coordinator |
|
||||
|
||||
@@ -1,315 +1,257 @@
|
||||
# Role: coordinator
|
||||
# Coordinator Role
|
||||
|
||||
头脑风暴团队协调者。负责话题澄清、复杂度评估、管道选择、Generator-Critic 循环控制和收敛监控。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `coordinator`
|
||||
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
|
||||
- **Responsibility**: Orchestration
|
||||
- **Communication**: SendMessage to all teammates
|
||||
- **Output Tag**: `[coordinator]`
|
||||
- **Name**: `coordinator` | **Tag**: `[coordinator]`
|
||||
- **Responsibility**: Parse requirements -> Create team -> Dispatch tasks -> Monitor progress -> Report results
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 所有输出(SendMessage、team_msg、日志)必须带 `[coordinator]` 标识
|
||||
- 仅负责话题澄清、任务创建/分发、进度监控、结果汇报
|
||||
- 通过 TaskCreate 创建任务并分配给 worker 角色
|
||||
- 解析用户需求,通过 AskUserQuestion 澄清模糊输入
|
||||
- 创建团队并通过 TaskCreate 分配任务给 worker 角色
|
||||
- 通过消息总线监控 worker 进度并路由消息
|
||||
- 管理 Generator-Critic 循环计数,决定是否继续迭代
|
||||
- 维护 session 状态持久化
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ **直接生成创意、挑战假设、综合想法或评估排序**
|
||||
- ❌ 直接调用实现类 subagent
|
||||
- ❌ 直接修改产物文件(ideas/*.md, critiques/*.md 等)
|
||||
- ❌ 绕过 worker 角色自行完成应委派的工作
|
||||
- ❌ 在输出中省略 `[coordinator]` 标识
|
||||
- 直接生成创意、挑战假设、综合想法或评估排序
|
||||
- 直接调用实现类 subagent
|
||||
- 直接修改产物文件(ideas/*.md, critiques/*.md 等)
|
||||
- 绕过 worker 角色自行完成应委派的工作
|
||||
- 在输出中省略 `[coordinator]` 标识
|
||||
|
||||
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `pipeline_selected` | coordinator → all | Pipeline decided | Notify selected pipeline mode |
|
||||
| `gc_loop_trigger` | coordinator → ideator | Critique severity >= HIGH | Trigger ideator to revise |
|
||||
| `task_unblocked` | coordinator → any | Dependency resolved | Notify worker of available task |
|
||||
| `error` | coordinator → all | Critical system error | Escalation to user |
|
||||
| `shutdown` | coordinator → all | Team being dissolved | Clean shutdown signal |
|
||||
| `pipeline_selected` | coordinator -> all | Pipeline decided | Notify selected pipeline mode |
|
||||
| `gc_loop_trigger` | coordinator -> ideator | Critique severity >= HIGH | Trigger ideator to revise |
|
||||
| `task_unblocked` | coordinator -> any | Dependency resolved | Notify worker of available task |
|
||||
| `error` | coordinator -> all | Critical system error | Escalation to user |
|
||||
| `shutdown` | coordinator -> all | Team being dissolved | Clean shutdown signal |
|
||||
|
||||
## Execution
|
||||
## Message Bus
|
||||
|
||||
### Phase 1: Topic Clarification + Complexity Assessment
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```javascript
|
||||
const args = "$ARGUMENTS"
|
||||
const teamNameMatch = args.match(/--team-name[=\s]+([\w-]+)/)
|
||||
const teamName = teamNameMatch ? teamNameMatch[1] : `brainstorm-${Date.now().toString(36)}`
|
||||
const taskDescription = args.replace(/--team-name[=\s]+[\w-]+/, '').replace(/--role[=\s]+\w+/, '').trim()
|
||||
```
|
||||
|
||||
Assess topic complexity and select pipeline:
|
||||
|
||||
```javascript
|
||||
function assessComplexity(topic) {
|
||||
let score = 0
|
||||
if (/strategy|architecture|system|framework|paradigm/.test(topic)) score += 3
|
||||
if (/multiple|compare|tradeoff|versus|alternative/.test(topic)) score += 2
|
||||
if (/innovative|creative|novel|breakthrough/.test(topic)) score += 2
|
||||
if (/simple|quick|straightforward|basic/.test(topic)) score -= 2
|
||||
return score >= 4 ? 'high' : score >= 2 ? 'medium' : 'low'
|
||||
}
|
||||
|
||||
const complexity = assessComplexity(taskDescription)
|
||||
```
|
||||
|
||||
```javascript
|
||||
AskUserQuestion({
|
||||
questions: [
|
||||
{
|
||||
question: "选择头脑风暴模式:",
|
||||
header: "Mode",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: complexity === 'low' ? "quick (推荐)" : "quick", description: "快速模式:创意→挑战→综合(3步)" },
|
||||
{ label: complexity === 'medium' ? "deep (推荐)" : "deep", description: "深度模式:含 Generator-Critic 循环(6步)" },
|
||||
{ label: complexity === 'high' ? "full (推荐)" : "full", description: "完整模式:并行发散 + 循环 + 评估(7步)" }
|
||||
]
|
||||
},
|
||||
{
|
||||
question: "创意发散角度:",
|
||||
header: "Angles",
|
||||
multiSelect: true,
|
||||
options: [
|
||||
{ label: "技术视角", description: "技术可行性、实现方案、架构设计" },
|
||||
{ label: "产品视角", description: "用户需求、市场定位、商业模式" },
|
||||
{ label: "创新视角", description: "颠覆性思路、跨领域借鉴、未来趋势" },
|
||||
{ label: "风险视角", description: "潜在问题、约束条件、替代方案" }
|
||||
]
|
||||
}
|
||||
]
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "coordinator",
|
||||
to: <recipient>,
|
||||
type: <message-type>,
|
||||
summary: "[coordinator] <action> complete: <subject>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 2: Create Team + Initialize Session
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```javascript
|
||||
TeamCreate({ team_name: teamName })
|
||||
|
||||
const topicSlug = taskDescription.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 40)
|
||||
const dateStr = new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString().substring(0, 10)
|
||||
const sessionId = `BRS-${topicSlug}-${dateStr}`
|
||||
const sessionFolder = `.workflow/.team/${sessionId}`
|
||||
|
||||
Bash(`mkdir -p "${sessionFolder}/ideas" "${sessionFolder}/critiques" "${sessionFolder}/synthesis" "${sessionFolder}/evaluation"`)
|
||||
|
||||
// Initialize shared memory
|
||||
const sharedMemory = {
|
||||
topic: taskDescription,
|
||||
pipeline: selectedPipeline,
|
||||
angles: selectedAngles,
|
||||
gc_round: 0,
|
||||
max_gc_rounds: 2,
|
||||
generated_ideas: [],
|
||||
critique_insights: [],
|
||||
synthesis_themes: [],
|
||||
evaluation_scores: []
|
||||
}
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
// Create team-session.json
|
||||
const teamSession = {
|
||||
session_id: sessionId,
|
||||
team_name: teamName,
|
||||
topic: taskDescription,
|
||||
pipeline: selectedPipeline,
|
||||
status: "active",
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
gc_round: 0,
|
||||
completed_tasks: []
|
||||
}
|
||||
Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2))
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from coordinator --to <recipient> --type <message-type> --summary \"[coordinator] <action> complete\" --ref <artifact-path> --json")
|
||||
```
|
||||
|
||||
// ⚠️ 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.
|
||||
---
|
||||
|
||||
### Phase 3: Create Task Chain
|
||||
## Entry Router
|
||||
|
||||
Task chain depends on the selected pipeline.
|
||||
When coordinator is invoked, first detect the invocation type:
|
||||
|
||||
#### Quick Pipeline
|
||||
| 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) |
|
||||
|
||||
```javascript
|
||||
// IDEA-001: 创意生成
|
||||
TaskCreate({ subject: "IDEA-001: 多角度创意生成", description: `话题: ${taskDescription}\n\nSession: ${sessionFolder}\n角度: ${selectedAngles.join(', ')}\n输出: ${sessionFolder}/ideas/idea-001.md\n\n要求: 每个角度至少产出3个创意,总计不少于6个`, activeForm: "生成创意中" })
|
||||
TaskUpdate({ taskId: ideaId, owner: "ideator" })
|
||||
For callback/check/resume: load monitor logic and execute the appropriate handler, then STOP.
|
||||
|
||||
// CHALLENGE-001: 挑战质疑 (blockedBy IDEA-001)
|
||||
TaskCreate({ subject: "CHALLENGE-001: 假设挑战与可行性质疑", description: `对 IDEA-001 的创意进行批判性分析\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/ideas/idea-001.md\n输出: ${sessionFolder}/critiques/critique-001.md\n\n要求: 标记每个创意的挑战严重度 (LOW/MEDIUM/HIGH/CRITICAL)`, activeForm: "挑战创意中" })
|
||||
TaskUpdate({ taskId: challengeId, owner: "challenger", addBlockedBy: [ideaId] })
|
||||
---
|
||||
|
||||
// SYNTH-001: 综合整合 (blockedBy CHALLENGE-001)
|
||||
TaskCreate({ subject: "SYNTH-001: 跨想法整合与主题提取", description: `整合所有创意和挑战反馈\n\nSession: ${sessionFolder}\n输入: ideas/ + critiques/\n输出: ${sessionFolder}/synthesis/synthesis-001.md\n\n要求: 提取核心主题、解决冲突、生成整合方案`, activeForm: "综合整合中" })
|
||||
TaskUpdate({ taskId: synthId, owner: "synthesizer", addBlockedBy: [challengeId] })
|
||||
```
|
||||
## Phase 0: Session Resume Check
|
||||
|
||||
#### Deep Pipeline (with Generator-Critic Loop)
|
||||
**Objective**: Detect and resume interrupted sessions before creating new ones.
|
||||
|
||||
```javascript
|
||||
// IDEA-001 → CHALLENGE-001 → IDEA-002(fix) → CHALLENGE-002 → SYNTH-001 → EVAL-001
|
||||
**Workflow**:
|
||||
1. Scan session directory for sessions with status "active" or "paused"
|
||||
2. No sessions found -> proceed to Phase 1
|
||||
3. Single session found -> resume it (-> Session Reconciliation)
|
||||
4. Multiple sessions -> AskUserQuestion for user selection
|
||||
|
||||
TaskCreate({ subject: "IDEA-001: 初始创意生成", description: `话题: ${taskDescription}\n\nSession: ${sessionFolder}\n输出: ${sessionFolder}/ideas/idea-001.md`, activeForm: "生成创意中" })
|
||||
TaskUpdate({ taskId: idea1Id, owner: "ideator" })
|
||||
**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
|
||||
|
||||
TaskCreate({ subject: "CHALLENGE-001: 第一轮挑战", description: `挑战 IDEA-001 的创意\n\nSession: ${sessionFolder}\n输入: ideas/idea-001.md\n输出: critiques/critique-001.md\n标记严重度`, activeForm: "挑战中" })
|
||||
TaskUpdate({ taskId: challenge1Id, owner: "challenger", addBlockedBy: [idea1Id] })
|
||||
---
|
||||
|
||||
TaskCreate({ subject: "IDEA-002: 创意修订(Generator-Critic Round 1)", description: `基于 CHALLENGE-001 的反馈修订创意\n\nSession: ${sessionFolder}\n输入: ideas/idea-001.md + critiques/critique-001.md\n输出: ideas/idea-002.md\n\n要求: 针对 HIGH/CRITICAL 严重度的挑战进行修订或替换`, activeForm: "修订创意中" })
|
||||
TaskUpdate({ taskId: idea2Id, owner: "ideator", addBlockedBy: [challenge1Id] })
|
||||
## Phase 1: Topic Clarification + Complexity Assessment
|
||||
|
||||
TaskCreate({ subject: "CHALLENGE-002: 第二轮验证", description: `验证修订后的创意\n\nSession: ${sessionFolder}\n输入: ideas/idea-002.md + critiques/critique-001.md\n输出: critiques/critique-002.md`, activeForm: "验证中" })
|
||||
TaskUpdate({ taskId: challenge2Id, owner: "challenger", addBlockedBy: [idea2Id] })
|
||||
**Objective**: Parse user input, assess complexity, select pipeline mode.
|
||||
|
||||
TaskCreate({ subject: "SYNTH-001: 综合整合", description: `整合全部创意和挑战反馈\n\nSession: ${sessionFolder}\n输入: ideas/ + critiques/\n输出: synthesis/synthesis-001.md`, activeForm: "综合中" })
|
||||
TaskUpdate({ taskId: synthId, owner: "synthesizer", addBlockedBy: [challenge2Id] })
|
||||
**Workflow**:
|
||||
|
||||
TaskCreate({ subject: "EVAL-001: 评分排序与最终筛选", description: `对综合方案评分排序\n\nSession: ${sessionFolder}\n输入: synthesis/synthesis-001.md + shared-memory.json\n输出: evaluation/evaluation-001.md\n\n评分维度: 可行性(30%) + 创新性(25%) + 影响力(25%) + 实施成本(20%)`, activeForm: "评估中" })
|
||||
TaskUpdate({ taskId: evalId, owner: "evaluator", addBlockedBy: [synthId] })
|
||||
```
|
||||
1. Parse arguments for `--team-name` and task description
|
||||
|
||||
#### Full Pipeline (Fan-out + Generator-Critic)
|
||||
2. Assess topic complexity:
|
||||
|
||||
```javascript
|
||||
// 并行创意: IDEA-001 + IDEA-002 + IDEA-003 (no dependencies between them)
|
||||
// Each gets a distinct agent owner for true parallel execution
|
||||
const ideaAngles = selectedAngles.slice(0, 3)
|
||||
ideaAngles.forEach((angle, i) => {
|
||||
const ideatorName = ideaAngles.length > 1 ? `ideator-${i+1}` : 'ideator'
|
||||
TaskCreate({ subject: `IDEA-00${i+1}: ${angle}角度创意生成`, description: `话题: ${taskDescription}\n角度: ${angle}\n\nSession: ${sessionFolder}\n输出: ideas/idea-00${i+1}.md`, activeForm: `${angle}创意生成中` })
|
||||
TaskUpdate({ taskId: ideaIds[i], owner: ideatorName })
|
||||
})
|
||||
| Signal | Weight | Keywords |
|
||||
|--------|--------|----------|
|
||||
| Strategic/systemic | +3 | strategy, architecture, system, framework, paradigm |
|
||||
| Multi-dimensional | +2 | multiple, compare, tradeoff, versus, alternative |
|
||||
| Innovation-focused | +2 | innovative, creative, novel, breakthrough |
|
||||
| Simple/basic | -2 | simple, quick, straightforward, basic |
|
||||
|
||||
// CHALLENGE-001: 批量挑战 (blockedBy all IDEA-001..003)
|
||||
TaskCreate({ subject: "CHALLENGE-001: 批量创意挑战", description: `批量挑战所有角度的创意\n\nSession: ${sessionFolder}\n输入: ideas/idea-001..003.md\n输出: critiques/critique-001.md`, activeForm: "批量挑战中" })
|
||||
TaskUpdate({ taskId: challenge1Id, owner: "challenger", addBlockedBy: ideaIds })
|
||||
| Score | Complexity | Pipeline Recommendation |
|
||||
|-------|------------|-------------------------|
|
||||
| >= 4 | High | full |
|
||||
| 2-3 | Medium | deep |
|
||||
| 0-1 | Low | quick |
|
||||
|
||||
// IDEA-004: 修订 (blockedBy CHALLENGE-001)
|
||||
TaskCreate({ subject: "IDEA-004: 创意修订", description: `基于批量挑战反馈修订\n\nSession: ${sessionFolder}\n输入: ideas/ + critiques/critique-001.md\n输出: ideas/idea-004.md`, activeForm: "修订中" })
|
||||
TaskUpdate({ taskId: idea4Id, owner: "ideator", addBlockedBy: [challenge1Id] })
|
||||
3. Ask for missing parameters via AskUserQuestion:
|
||||
|
||||
// SYNTH-001 (blockedBy IDEA-004)
|
||||
TaskCreate({ subject: "SYNTH-001: 综合整合", description: `整合全部创意\n\nSession: ${sessionFolder}\n输入: ideas/ + critiques/\n输出: synthesis/synthesis-001.md`, activeForm: "综合中" })
|
||||
TaskUpdate({ taskId: synthId, owner: "synthesizer", addBlockedBy: [idea4Id] })
|
||||
| Question | Header | Options |
|
||||
|----------|--------|---------|
|
||||
| Pipeline mode | Mode | quick (3-step), deep (6-step with GC loop), full (7-step parallel + GC) |
|
||||
| Divergence angles | Angles | Multi-select: Technical, Product, Innovation, Risk |
|
||||
|
||||
// EVAL-001 (blockedBy SYNTH-001)
|
||||
TaskCreate({ subject: "EVAL-001: 评分排序", description: `最终评估\n\nSession: ${sessionFolder}\n输入: synthesis/ + shared-memory.json\n输出: evaluation/evaluation-001.md`, activeForm: "评估中" })
|
||||
TaskUpdate({ taskId: evalId, owner: "evaluator", addBlockedBy: [synthId] })
|
||||
```
|
||||
4. Store requirements: mode, scope, angles, constraints
|
||||
|
||||
### Phase 4: Coordination Loop + Generator-Critic Control
|
||||
**Success**: All parameters captured, pipeline finalized.
|
||||
|
||||
> **设计原则(Stop-Wait)**: 模型执行没有时间概念,禁止任何形式的轮询等待。
|
||||
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
|
||||
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用,Worker 返回 = 阶段完成信号
|
||||
>
|
||||
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
|
||||
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
|
||||
---
|
||||
|
||||
## Phase 2: Create Team + Initialize Session
|
||||
|
||||
**Objective**: Initialize team, session file, and shared memory.
|
||||
|
||||
**Workflow**:
|
||||
1. Generate session ID: `BRS-<topic-slug>-<date>`
|
||||
2. Create session folder structure
|
||||
3. Call TeamCreate with team name
|
||||
4. Initialize subdirectories: ideas/, critiques/, synthesis/, evaluation/
|
||||
5. Initialize shared-memory.json with: topic, pipeline, angles, gc_round, generated_ideas, critique_insights, synthesis_themes, evaluation_scores
|
||||
6. Write team-session.json with: session_id, team_name, topic, pipeline, status="active", created_at, updated_at
|
||||
7. Workers are NOT pre-spawned here -> spawned per-stage in Phase 4
|
||||
|
||||
**Success**: Team created, session file written, directories initialized.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Create Task Chain
|
||||
|
||||
**Objective**: Dispatch tasks based on selected pipeline with proper dependencies.
|
||||
|
||||
### Quick Pipeline
|
||||
|
||||
| Task ID | Subject | Owner | BlockedBy |
|
||||
|---------|---------|-------|-----------|
|
||||
| IDEA-001 | Multi-angle idea generation | ideator | - |
|
||||
| CHALLENGE-001 | Assumption challenges | challenger | IDEA-001 |
|
||||
| SYNTH-001 | Cross-idea synthesis | synthesizer | CHALLENGE-001 |
|
||||
|
||||
### Deep Pipeline (with Generator-Critic Loop)
|
||||
|
||||
| Task ID | Subject | Owner | BlockedBy |
|
||||
|---------|---------|-------|-----------|
|
||||
| IDEA-001 | Initial idea generation | ideator | - |
|
||||
| CHALLENGE-001 | First round critique | challenger | IDEA-001 |
|
||||
| IDEA-002 | Idea revision (GC Round 1) | ideator | CHALLENGE-001 |
|
||||
| CHALLENGE-002 | Second round validation | challenger | IDEA-002 |
|
||||
| SYNTH-001 | Synthesis | synthesizer | CHALLENGE-002 |
|
||||
| EVAL-001 | Scoring and ranking | evaluator | SYNTH-001 |
|
||||
|
||||
### Full Pipeline (Fan-out + Generator-Critic)
|
||||
|
||||
| Task ID | Subject | Owner | BlockedBy |
|
||||
|---------|---------|-------|-----------|
|
||||
| IDEA-001 | Technical angle ideas | ideator-1 | - |
|
||||
| IDEA-002 | Product angle ideas | ideator-2 | - |
|
||||
| IDEA-003 | Innovation angle ideas | ideator-3 | - |
|
||||
| CHALLENGE-001 | Batch critique | challenger | IDEA-001, IDEA-002, IDEA-003 |
|
||||
| IDEA-004 | Revised ideas | ideator | CHALLENGE-001 |
|
||||
| SYNTH-001 | Synthesis | synthesizer | IDEA-004 |
|
||||
| EVAL-001 | Evaluation | evaluator | SYNTH-001 |
|
||||
|
||||
**Success**: All tasks created with correct dependencies and owners assigned.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Coordination Loop + Generator-Critic Control
|
||||
|
||||
**Objective**: Monitor worker callbacks and advance pipeline.
|
||||
|
||||
> **Design Principle (Stop-Wait)**: No time-based polling. Worker return = stage complete signal.
|
||||
|
||||
| Received Message | Action |
|
||||
|-----------------|--------|
|
||||
| ideator: ideas_ready | Read ideas → team_msg log → TaskUpdate completed → unblock CHALLENGE |
|
||||
| challenger: critique_ready | Read critique → **Generator-Critic 判断** → 决定是否触发 IDEA-fix |
|
||||
| ideator: ideas_revised | Read revised ideas → team_msg log → TaskUpdate completed → unblock CHALLENGE-2 |
|
||||
| synthesizer: synthesis_ready | Read synthesis → team_msg log → TaskUpdate completed → unblock EVAL (if exists) |
|
||||
| evaluator: evaluation_ready | Read evaluation → team_msg log → TaskUpdate completed → Phase 5 |
|
||||
| All tasks completed | → Phase 5 |
|
||||
| ideator: ideas_ready | Read ideas -> team_msg log -> TaskUpdate completed -> unblock CHALLENGE |
|
||||
| challenger: critique_ready | Read critique -> **Generator-Critic decision** -> decide if IDEA-fix needed |
|
||||
| ideator: ideas_revised | Read revised ideas -> team_msg log -> TaskUpdate completed -> unblock next CHALLENGE |
|
||||
| synthesizer: synthesis_ready | Read synthesis -> team_msg log -> TaskUpdate completed -> unblock EVAL (if exists) |
|
||||
| evaluator: evaluation_ready | Read evaluation -> team_msg log -> TaskUpdate completed -> Phase 5 |
|
||||
| All tasks completed | -> Phase 5 |
|
||||
|
||||
#### Generator-Critic Loop Control
|
||||
### Generator-Critic Loop Control
|
||||
|
||||
```javascript
|
||||
if (msgType === 'critique_ready') {
|
||||
const critique = Read(`${sessionFolder}/critiques/critique-${round}.md`)
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
|
||||
// Count HIGH/CRITICAL severity challenges
|
||||
const criticalCount = (critique.match(/severity:\s*(HIGH|CRITICAL)/gi) || []).length
|
||||
const gcRound = sharedMemory.gc_round || 0
|
||||
|
||||
if (criticalCount > 0 && gcRound < sharedMemory.max_gc_rounds) {
|
||||
// Trigger another ideator round
|
||||
sharedMemory.gc_round = gcRound + 1
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator", to: "ideator",
|
||||
type: "gc_loop_trigger",
|
||||
summary: `[coordinator] Generator-Critic round ${gcRound + 1}: ${criticalCount} critical challenges need revision`
|
||||
})
|
||||
// Unblock IDEA-fix task
|
||||
} else {
|
||||
// Converged → unblock SYNTH
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator", to: "synthesizer",
|
||||
type: "task_unblocked",
|
||||
summary: `[coordinator] Critique converged (round ${gcRound}), proceeding to synthesis`
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
| Condition | Action |
|
||||
|-----------|--------|
|
||||
| critique_ready + criticalCount > 0 + gcRound < maxRounds | Trigger IDEA-fix task, increment gc_round |
|
||||
| critique_ready + (criticalCount == 0 OR gcRound >= maxRounds) | Converged -> unblock SYNTH task |
|
||||
|
||||
### Phase 5: Report + Persist
|
||||
**GC Round Tracking**:
|
||||
1. Read critique file
|
||||
2. Count severity: HIGH and CRITICAL
|
||||
3. Read shared-memory.json for gc_round
|
||||
4. If criticalCount > 0 AND gcRound < max_gc_rounds:
|
||||
- Increment gc_round in shared-memory.json
|
||||
- Log team_msg with type "gc_loop_trigger"
|
||||
- Unblock IDEA-fix task
|
||||
5. Else: Log team_msg with type "task_unblocked", unblock SYNTH
|
||||
|
||||
```javascript
|
||||
// Read final results
|
||||
const synthesis = Read(`${sessionFolder}/synthesis/synthesis-001.md`)
|
||||
const evaluation = selectedPipeline !== 'quick' ? Read(`${sessionFolder}/evaluation/evaluation-001.md`) : null
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
---
|
||||
|
||||
// Report to user
|
||||
SendMessage({
|
||||
content: `## [coordinator] 头脑风暴完成
|
||||
## Phase 5: Report + Persist
|
||||
|
||||
**话题**: ${taskDescription}
|
||||
**管道**: ${selectedPipeline}
|
||||
**Generator-Critic 轮次**: ${sharedMemory.gc_round}
|
||||
**创意总数**: ${sharedMemory.generated_ideas.length}
|
||||
**Objective**: Completion report and follow-up options.
|
||||
|
||||
### 综合结果
|
||||
${synthesis}
|
||||
**Workflow**:
|
||||
1. Load session state -> count completed tasks, duration
|
||||
2. Read synthesis and evaluation results
|
||||
3. Generate summary with: topic, pipeline, GC rounds, total ideas
|
||||
4. Update session status -> "completed"
|
||||
5. Report to user via SendMessage
|
||||
6. Offer next steps via AskUserQuestion:
|
||||
- New topic (continue brainstorming)
|
||||
- Deep dive (analyze top-ranked idea)
|
||||
- Close team (cleanup)
|
||||
|
||||
${evaluation ? `### 评估排序\n${evaluation}` : ''}`,
|
||||
summary: `[coordinator] Brainstorm complete: ${sharedMemory.generated_ideas.length} ideas, ${sharedMemory.gc_round} GC rounds`
|
||||
})
|
||||
|
||||
// Update session
|
||||
updateSession(sessionFolder, { status: 'completed', completed_at: new Date().toISOString() })
|
||||
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "头脑风暴已完成。下一步:",
|
||||
header: "Next",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "新话题", description: "继续头脑风暴新话题" },
|
||||
{ label: "深化探索", description: "对排名最高的创意进行深入分析" },
|
||||
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| Teammate 无响应 | 发追踪消息,2次无响应 → 重新 spawn |
|
||||
| Generator-Critic 循环超限 | 强制收敛到 SYNTH 阶段 |
|
||||
| Ideator 无法产出 | Coordinator 提供种子问题引导 |
|
||||
| Challenger 全部标记 LOW | 直接进入 SYNTH,跳过修订 |
|
||||
| 综合冲突无法解决 | 上报用户,AskUserQuestion 决定方向 |
|
||||
| Teammate unresponsive | Send tracking message, 2 failures -> respawn worker |
|
||||
| Generator-Critic loop exceeded | Force convergence to SYNTH stage |
|
||||
| Ideator cannot produce | Provide seed questions as guidance |
|
||||
| Challenger all LOW severity | Skip revision, proceed directly to SYNTH |
|
||||
| Synthesis conflict unresolved | Report to user, AskUserQuestion for direction |
|
||||
| Session corruption | Attempt recovery, fallback to manual reconciliation |
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# Role: evaluator
|
||||
# Evaluator Role
|
||||
|
||||
评分排序与最终筛选。负责对综合方案进行多维度评分、优先级推荐、生成最终排名。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `evaluator`
|
||||
- **Name**: `evaluator` | **Tag**: `[evaluator]`
|
||||
- **Task Prefix**: `EVAL-*`
|
||||
- **Responsibility**: Validation (评估验证)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[evaluator]`
|
||||
- **Responsibility**: Validation (evaluation and ranking)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
@@ -19,171 +17,134 @@
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- Phase 2 读取 shared-memory.json,Phase 5 写入 evaluation_scores
|
||||
- 使用标准化评分维度,确保评分可追溯
|
||||
- 为每个方案提供评分理由和推荐
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 生成新创意、挑战假设或综合整合
|
||||
- ❌ 直接与其他 worker 角色通信
|
||||
- ❌ 为其他角色创建任务
|
||||
- ❌ 修改 shared-memory.json 中不属于自己的字段
|
||||
- 生成新创意、挑战假设或综合整合
|
||||
- 直接与其他 worker 角色通信
|
||||
- 为其他角色创建任务
|
||||
- 修改 shared-memory.json 中不属于自己的字段
|
||||
- 在输出中省略 `[evaluator]` 标识
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `TaskList` | Built-in | Phase 1 | Discover pending EVAL-* tasks |
|
||||
| `TaskGet` | Built-in | Phase 1 | Get task details |
|
||||
| `TaskUpdate` | Built-in | Phase 1/5 | Update task status |
|
||||
| `Read` | Built-in | Phase 2 | Read shared-memory.json, synthesis files, ideas, critiques |
|
||||
| `Write` | Built-in | Phase 3/5 | Write evaluation files, update shared memory |
|
||||
| `Glob` | Built-in | Phase 2 | Find synthesis, idea, critique files |
|
||||
| `SendMessage` | Built-in | Phase 5 | Report to coordinator |
|
||||
| `mcp__ccw-tools__team_msg` | MCP | Phase 5 | Log communication |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `evaluation_ready` | evaluator → coordinator | Evaluation completed | 评估排序完成 |
|
||||
| `error` | evaluator → coordinator | Processing failure | 错误上报 |
|
||||
| `evaluation_ready` | evaluator -> coordinator | Evaluation completed | Scoring and ranking complete |
|
||||
| `error` | evaluator -> coordinator | Processing failure | Error report |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "evaluator",
|
||||
to: "coordinator",
|
||||
type: "evaluation_ready",
|
||||
summary: "[evaluator] Evaluation complete: Top pick \"<title>\" (<score>/10)",
|
||||
ref: <output-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from evaluator --to coordinator --type evaluation_ready --summary \"[evaluator] Evaluation complete\" --ref <output-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('EVAL-') &&
|
||||
t.owner === 'evaluator' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `EVAL-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Context Loading + Shared Memory Read
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | Task description (Session: line) | Yes |
|
||||
| Synthesis results | synthesis/*.md files | Yes |
|
||||
| All ideas | ideas/*.md files | No (for context) |
|
||||
| All critiques | critiques/*.md files | No (for context) |
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
**Loading steps**:
|
||||
|
||||
// Read synthesis results
|
||||
const synthesisFiles = Glob({ pattern: `${sessionFolder}/synthesis/*.md` })
|
||||
const synthesis = synthesisFiles.map(f => Read(f))
|
||||
1. Extract session path from task description (match "Session: <path>")
|
||||
2. Glob synthesis files from session/synthesis/
|
||||
3. Read all synthesis files for evaluation
|
||||
4. Optionally read ideas and critiques for full context
|
||||
|
||||
// Read all ideas and critiques for full context
|
||||
const ideaFiles = Glob({ pattern: `${sessionFolder}/ideas/*.md` })
|
||||
const critiqueFiles = Glob({ pattern: `${sessionFolder}/critiques/*.md` })
|
||||
### Phase 3: Evaluation and Scoring
|
||||
|
||||
**Scoring Dimensions**:
|
||||
|
||||
| Dimension | Weight | Focus |
|
||||
|-----------|--------|-------|
|
||||
| Feasibility | 30% | Technical feasibility, resource needs, timeline |
|
||||
| Innovation | 25% | Novelty, differentiation, breakthrough potential |
|
||||
| Impact | 25% | Scope of impact, value creation, problem resolution |
|
||||
| Cost Efficiency | 20% | Implementation cost, risk cost, opportunity cost |
|
||||
|
||||
**Weighted Score Calculation**:
|
||||
```
|
||||
weightedScore = (Feasibility * 0.30) + (Innovation * 0.25) + (Impact * 0.25) + (Cost * 0.20)
|
||||
```
|
||||
|
||||
### Phase 3: Evaluation & Scoring
|
||||
**Evaluation Structure per Proposal**:
|
||||
- Score for each dimension (1-10)
|
||||
- Rationale for each score
|
||||
- Overall recommendation (Strong Recommend / Recommend / Consider / Pass)
|
||||
|
||||
```javascript
|
||||
// Scoring dimensions:
|
||||
// 1. Feasibility (30%) — 技术可行性、资源需求、时间框架
|
||||
// 2. Innovation (25%) — 新颖性、差异化、突破性
|
||||
// 3. Impact (25%) — 影响范围、价值创造、问题解决度
|
||||
// 4. Cost (20%) — 实施成本、风险成本、机会成本
|
||||
|
||||
const evalNum = task.subject.match(/EVAL-(\d+)/)?.[1] || '001'
|
||||
const outputPath = `${sessionFolder}/evaluation/evaluation-${evalNum}.md`
|
||||
|
||||
const evaluationContent = `# Evaluation — Round ${evalNum}
|
||||
|
||||
**Input**: ${synthesisFiles.length} synthesis files
|
||||
**Scoring Dimensions**: Feasibility(30%), Innovation(25%), Impact(25%), Cost(20%)
|
||||
|
||||
## Scoring Matrix
|
||||
|
||||
| Rank | Proposal | Feasibility | Innovation | Impact | Cost | **Weighted Score** |
|
||||
|------|----------|-------------|------------|--------|------|-------------------|
|
||||
${scoredProposals.map((p, i) => `| ${i + 1} | ${p.title} | ${p.feasibility}/10 | ${p.innovation}/10 | ${p.impact}/10 | ${p.cost}/10 | **${p.weightedScore.toFixed(1)}** |`).join('\n')}
|
||||
|
||||
## Detailed Evaluation
|
||||
|
||||
${scoredProposals.map((p, i) => `### ${i + 1}. ${p.title} (Score: ${p.weightedScore.toFixed(1)}/10)
|
||||
|
||||
**Feasibility** (${p.feasibility}/10):
|
||||
${p.feasibilityRationale}
|
||||
|
||||
**Innovation** (${p.innovation}/10):
|
||||
${p.innovationRationale}
|
||||
|
||||
**Impact** (${p.impact}/10):
|
||||
${p.impactRationale}
|
||||
|
||||
**Cost Efficiency** (${p.cost}/10):
|
||||
${p.costRationale}
|
||||
|
||||
**Recommendation**: ${p.recommendation}
|
||||
`).join('\n')}
|
||||
|
||||
## Final Recommendation
|
||||
|
||||
**Top Pick**: ${scoredProposals[0].title}
|
||||
**Runner-up**: ${scoredProposals.length > 1 ? scoredProposals[1].title : 'N/A'}
|
||||
|
||||
### Action Items
|
||||
${actionItems.map((item, i) => `${i + 1}. ${item}`).join('\n')}
|
||||
|
||||
### Risk Summary
|
||||
${riskSummary.map(r => `- **${r.risk}**: ${r.mitigation}`).join('\n')}
|
||||
`
|
||||
|
||||
Write(outputPath, evaluationContent)
|
||||
```
|
||||
**Output file structure**:
|
||||
- File: `<session>/evaluation/evaluation-<num>.md`
|
||||
- Sections: Input summary, Scoring Matrix (ranked table), Detailed Evaluation per proposal, Final Recommendation, Action Items, Risk Summary
|
||||
|
||||
### Phase 4: Consistency Check
|
||||
|
||||
```javascript
|
||||
// Verify scoring consistency
|
||||
// - No proposal should have all 10s
|
||||
// - Scores should reflect critique findings
|
||||
// - Rankings should be deterministic
|
||||
const maxScore = Math.max(...scoredProposals.map(p => p.weightedScore))
|
||||
const minScore = Math.min(...scoredProposals.map(p => p.weightedScore))
|
||||
const spread = maxScore - minScore
|
||||
|
||||
if (spread < 0.5 && scoredProposals.length > 1) {
|
||||
// Too close — re-evaluate differentiators
|
||||
}
|
||||
```
|
||||
| Check | Pass Criteria | Action on Failure |
|
||||
|-------|---------------|-------------------|
|
||||
| Score spread | max - min >= 0.5 (with >1 proposal) | Re-evaluate differentiators |
|
||||
| No perfect scores | Not all 10s | Adjust scores to reflect critique findings |
|
||||
| Ranking deterministic | Consistent ranking | Verify calculation |
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
sharedMemory.evaluation_scores = scoredProposals.map(p => ({
|
||||
title: p.title,
|
||||
weighted_score: p.weightedScore,
|
||||
rank: p.rank,
|
||||
recommendation: p.recommendation
|
||||
}))
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "evaluator",
|
||||
to: "coordinator",
|
||||
type: "evaluation_ready",
|
||||
summary: `[evaluator] Evaluation complete: Top pick "${scoredProposals[0].title}" (${scoredProposals[0].weightedScore.toFixed(1)}/10)`,
|
||||
ref: outputPath
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[evaluator]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [evaluator] Evaluation Results
|
||||
**Shared Memory Update**:
|
||||
1. Set shared-memory.json.evaluation_scores
|
||||
2. Each entry: title, weighted_score, rank, recommendation
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Proposals Evaluated**: ${scoredProposals.length}
|
||||
**Output**: ${outputPath}
|
||||
|
||||
### Rankings
|
||||
${scoredProposals.map((p, i) => `${i + 1}. **${p.title}** — ${p.weightedScore.toFixed(1)}/10 (${p.recommendation})`).join('\n')}
|
||||
|
||||
### Top Pick: ${scoredProposals[0].title}
|
||||
${scoredProposals[0].feasibilityRationale}`,
|
||||
summary: `[evaluator] Top: ${scoredProposals[0].title} (${scoredProposals[0].weightedScore.toFixed(1)}/10)`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -193,3 +154,4 @@ TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
| Synthesis files not found | Notify coordinator |
|
||||
| Only one proposal | Evaluate against absolute criteria, recommend or reject |
|
||||
| All proposals score below 5 | Flag all as weak, recommend re-brainstorming |
|
||||
| Critical issue beyond scope | SendMessage error to coordinator |
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# Role: ideator
|
||||
# Ideator Role
|
||||
|
||||
多角度创意生成者。负责发散思维、概念探索、创意修订。作为 Generator-Critic 循环中的 Generator 角色。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `ideator`
|
||||
- **Name**: `ideator` | **Tag**: `[ideator]`
|
||||
- **Task Prefix**: `IDEA-*`
|
||||
- **Responsibility**: Read-only analysis (创意生成不修改代码)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[ideator]`
|
||||
- **Responsibility**: Read-only analysis (idea generation, no code modification)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
@@ -18,205 +16,137 @@
|
||||
- 所有输出(SendMessage、team_msg、日志)必须带 `[ideator]` 标识
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- Phase 2 读取 shared-memory.json,Phase 5 写入 generated_ideas
|
||||
- 针对每个指定角度产出至少3个创意
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 执行挑战/评估/综合等其他角色工作
|
||||
- ❌ 直接与其他 worker 角色通信
|
||||
- ❌ 为其他角色创建任务(TaskCreate 是 coordinator 专属)
|
||||
- ❌ 修改 shared-memory.json 中不属于自己的字段
|
||||
- 执行挑战/评估/综合等其他角色工作
|
||||
- 直接与其他 worker 角色通信
|
||||
- 为其他角色创建任务(TaskCreate 是 coordinator 专属)
|
||||
- 修改 shared-memory.json 中不属于自己的字段
|
||||
- 在输出中省略 `[ideator]` 标识
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `TaskList` | Built-in | Phase 1 | Discover pending IDEA-* tasks |
|
||||
| `TaskGet` | Built-in | Phase 1 | Get task details |
|
||||
| `TaskUpdate` | Built-in | Phase 1/5 | Update task status |
|
||||
| `Read` | Built-in | Phase 2 | Read shared-memory.json, critique files |
|
||||
| `Write` | Built-in | Phase 3/5 | Write idea files, update shared memory |
|
||||
| `Glob` | Built-in | Phase 2 | Find critique files |
|
||||
| `SendMessage` | Built-in | Phase 5 | Report to coordinator |
|
||||
| `mcp__ccw-tools__team_msg` | MCP | Phase 5 | Log communication |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `ideas_ready` | ideator → coordinator | Initial ideas generated | 初始创意完成 |
|
||||
| `ideas_revised` | ideator → coordinator | Ideas revised after critique | 修订创意完成 (GC 循环) |
|
||||
| `error` | ideator → coordinator | Processing failure | 错误上报 |
|
||||
| `ideas_ready` | ideator -> coordinator | Initial ideas generated | Initial idea generation complete |
|
||||
| `ideas_revised` | ideator -> coordinator | Ideas revised after critique | Revised ideas complete (GC loop) |
|
||||
| `error` | ideator -> coordinator | Processing failure | Error report |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "ideator",
|
||||
to: "coordinator",
|
||||
type: <ideas_ready|ideas_revised>,
|
||||
summary: "[ideator] <Generated|Revised> <count> ideas (round <num>)",
|
||||
ref: <output-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from ideator --to coordinator --type <message-type> --summary \"[ideator] ideas complete\" --ref <output-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
// Parse agent name for parallel instances (e.g., ideator-1, ideator-2)
|
||||
const agentNameMatch = args.match(/--agent-name[=\s]+([\w-]+)/)
|
||||
const agentName = agentNameMatch ? agentNameMatch[1] : 'ideator'
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('IDEA-') &&
|
||||
t.owner === agentName && // Use agentName (e.g., 'ideator-1') instead of hardcoded 'ideator'
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
Standard task discovery flow: TaskList -> filter by prefix `IDEA-*` + 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 `ideator` for single-instance roles.
|
||||
|
||||
### Phase 2: Context Loading + Shared Memory Read
|
||||
|
||||
```javascript
|
||||
// Extract session folder from task description
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | Task description (Session: line) | Yes |
|
||||
| Topic | shared-memory.json | Yes |
|
||||
| Angles | shared-memory.json | Yes |
|
||||
| GC Round | shared-memory.json | Yes |
|
||||
| Previous critique | critiques/*.md | For revision tasks only |
|
||||
| Previous ideas | shared-memory.json.generated_ideas | No |
|
||||
|
||||
// Read shared memory
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
**Loading steps**:
|
||||
|
||||
const topic = sharedMemory.topic || task.description
|
||||
const angles = sharedMemory.angles || ['技术', '产品', '创新']
|
||||
const gcRound = sharedMemory.gc_round || 0
|
||||
|
||||
// If this is a revision task (GC loop), read previous critique
|
||||
let previousCritique = null
|
||||
if (task.subject.includes('修订') || task.subject.includes('fix')) {
|
||||
const critiqueFiles = Glob({ pattern: `${sessionFolder}/critiques/*.md` })
|
||||
if (critiqueFiles.length > 0) {
|
||||
previousCritique = Read(critiqueFiles[critiqueFiles.length - 1])
|
||||
}
|
||||
}
|
||||
|
||||
// Read previous ideas for context
|
||||
const previousIdeas = sharedMemory.generated_ideas || []
|
||||
```
|
||||
1. Extract session path from task description (match "Session: <path>")
|
||||
2. Read shared-memory.json for topic, angles, gc_round
|
||||
3. If task is revision (subject contains "revision" or "fix"):
|
||||
- Glob critique files
|
||||
- Read latest critique for revision context
|
||||
4. Read previous ideas from shared-memory.generated_ideas
|
||||
|
||||
### Phase 3: Idea Generation
|
||||
|
||||
```javascript
|
||||
// Determine generation mode
|
||||
const isRevision = !!previousCritique
|
||||
| Mode | Condition | Focus |
|
||||
|------|-----------|-------|
|
||||
| Initial Generation | No previous critique | Multi-angle divergent thinking |
|
||||
| GC Revision | Previous critique exists | Address HIGH/CRITICAL challenges |
|
||||
|
||||
if (isRevision) {
|
||||
// === Generator-Critic Revision Mode ===
|
||||
// Focus on HIGH/CRITICAL severity challenges
|
||||
// Revise or replace challenged ideas
|
||||
// Keep unchallenged ideas intact
|
||||
|
||||
// Output structure:
|
||||
// - Retained ideas (unchallenged)
|
||||
// - Revised ideas (with revision rationale)
|
||||
// - New replacement ideas (for unsalvageable ones)
|
||||
} else {
|
||||
// === Initial Generation Mode ===
|
||||
// For each angle, generate 3+ ideas
|
||||
// Each idea includes:
|
||||
// - Title
|
||||
// - Description (2-3 sentences)
|
||||
// - Key assumption
|
||||
// - Potential impact
|
||||
// - Implementation hint
|
||||
}
|
||||
**Initial Generation Mode**:
|
||||
- For each angle, generate 3+ ideas
|
||||
- Each idea includes: title, description (2-3 sentences), key assumption, potential impact, implementation hint
|
||||
|
||||
// Write ideas to file
|
||||
const ideaNum = task.subject.match(/IDEA-(\d+)/)?.[1] || '001'
|
||||
const outputPath = `${sessionFolder}/ideas/idea-${ideaNum}.md`
|
||||
**GC Revision Mode**:
|
||||
- Focus on HIGH/CRITICAL severity challenges from critique
|
||||
- Retain unchallenged ideas intact
|
||||
- Revise ideas with revision rationale
|
||||
- Replace unsalvageable ideas with new alternatives
|
||||
|
||||
const ideaContent = `# ${isRevision ? 'Revised' : 'Initial'} Ideas — Round ${ideaNum}
|
||||
|
||||
**Topic**: ${topic}
|
||||
**Angles**: ${angles.join(', ')}
|
||||
**Mode**: ${isRevision ? 'Generator-Critic Revision (Round ' + gcRound + ')' : 'Initial Generation'}
|
||||
|
||||
${isRevision ? `## Revision Context\n\nBased on critique feedback:\n${previousCritique}\n\n` : ''}
|
||||
|
||||
## Ideas
|
||||
|
||||
${generatedIdeas.map((idea, i) => `### Idea ${i + 1}: ${idea.title}
|
||||
|
||||
**Description**: ${idea.description}
|
||||
**Key Assumption**: ${idea.assumption}
|
||||
**Potential Impact**: ${idea.impact}
|
||||
**Implementation Hint**: ${idea.implementation}
|
||||
${isRevision ? `**Revision Note**: ${idea.revision_note || 'New idea'}` : ''}
|
||||
`).join('\n')}
|
||||
|
||||
## Summary
|
||||
|
||||
- Total ideas: ${generatedIdeas.length}
|
||||
- ${isRevision ? `Retained: ${retainedCount}, Revised: ${revisedCount}, New: ${newCount}` : `Per angle: ${angles.map(a => `${a}: ${countByAngle[a]}`).join(', ')}`}
|
||||
`
|
||||
|
||||
Write(outputPath, ideaContent)
|
||||
```
|
||||
**Output file structure**:
|
||||
- File: `<session>/ideas/idea-<num>.md`
|
||||
- Sections: Topic, Angles, Mode, [Revision Context if applicable], Ideas list, Summary
|
||||
|
||||
### Phase 4: Self-Review
|
||||
|
||||
```javascript
|
||||
// Verify minimum idea count
|
||||
const ideaCount = generatedIdeas.length
|
||||
const minimumRequired = isRevision ? 3 : 6
|
||||
|
||||
if (ideaCount < minimumRequired) {
|
||||
// Generate additional ideas to meet minimum
|
||||
}
|
||||
|
||||
// Verify no duplicate ideas
|
||||
const titles = generatedIdeas.map(i => i.title.toLowerCase())
|
||||
const duplicates = titles.filter((t, i) => titles.indexOf(t) !== i)
|
||||
if (duplicates.length > 0) {
|
||||
// Replace duplicates
|
||||
}
|
||||
```
|
||||
| Check | Pass Criteria | Action on Failure |
|
||||
|-------|---------------|-------------------|
|
||||
| Minimum count | >= 6 (initial) or >= 3 (revision) | Generate additional ideas |
|
||||
| No duplicates | All titles unique | Replace duplicates |
|
||||
| Angle coverage | At least 1 idea per angle | Generate missing angle ideas |
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
// Update shared memory
|
||||
sharedMemory.generated_ideas = [
|
||||
...sharedMemory.generated_ideas,
|
||||
...generatedIdeas.map(i => ({
|
||||
id: `idea-${ideaNum}-${i.index}`,
|
||||
title: i.title,
|
||||
round: parseInt(ideaNum),
|
||||
revised: isRevision
|
||||
}))
|
||||
]
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
// Log message
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "ideator",
|
||||
to: "coordinator",
|
||||
type: isRevision ? "ideas_revised" : "ideas_ready",
|
||||
summary: `[ideator] ${isRevision ? 'Revised' : 'Generated'} ${ideaCount} ideas (round ${ideaNum})`,
|
||||
ref: outputPath
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[ideator]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [ideator] ${isRevision ? 'Ideas Revised' : 'Ideas Generated'}
|
||||
**Shared Memory Update**:
|
||||
1. Append new ideas to shared-memory.json.generated_ideas
|
||||
2. Each entry: id, title, round, revised flag
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Ideas**: ${ideaCount}
|
||||
**Output**: ${outputPath}
|
||||
|
||||
### Highlights
|
||||
${generatedIdeas.slice(0, 3).map(i => `- **${i.title}**: ${i.description.substring(0, 100)}...`).join('\n')}`,
|
||||
summary: `[ideator] ${ideaCount} ideas ${isRevision ? 'revised' : 'generated'}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('IDEA-') &&
|
||||
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
|
||||
|
||||
@@ -226,4 +156,5 @@ if (nextTasks.length > 0) {
|
||||
| Session folder not found | Notify coordinator, request path |
|
||||
| Shared memory read fails | Initialize empty, proceed with generation |
|
||||
| Topic too vague | Generate meta-questions as seed ideas |
|
||||
| Previous critique not found (revision) | Generate new ideas instead of revising |
|
||||
| Previous critique not found (revision task) | Generate new ideas instead of revising |
|
||||
| Critical issue beyond scope | SendMessage error to coordinator |
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# Role: synthesizer
|
||||
# Synthesizer Role
|
||||
|
||||
跨想法整合者。负责从多个创意和挑战反馈中提取主题、解决冲突、生成整合方案。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `synthesizer`
|
||||
- **Name**: `synthesizer` | **Tag**: `[synthesizer]`
|
||||
- **Task Prefix**: `SYNTH-*`
|
||||
- **Responsibility**: Read-only analysis (综合整合)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[synthesizer]`
|
||||
- **Responsibility**: Read-only analysis (synthesis and integration)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
@@ -18,182 +16,146 @@
|
||||
- 所有输出必须带 `[synthesizer]` 标识
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- Phase 2 读取 shared-memory.json,Phase 5 写入 synthesis_themes
|
||||
- 从所有创意和挑战中提取共同主题
|
||||
- 解决相互矛盾的想法,生成整合方案
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 生成新创意、挑战假设或评分排序
|
||||
- ❌ 直接与其他 worker 角色通信
|
||||
- ❌ 为其他角色创建任务
|
||||
- ❌ 修改 shared-memory.json 中不属于自己的字段
|
||||
- 生成新创意、挑战假设或评分排序
|
||||
- 直接与其他 worker 角色通信
|
||||
- 为其他角色创建任务
|
||||
- 修改 shared-memory.json 中不属于自己的字段
|
||||
- 在输出中省略 `[synthesizer]` 标识
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `TaskList` | Built-in | Phase 1 | Discover pending SYNTH-* tasks |
|
||||
| `TaskGet` | Built-in | Phase 1 | Get task details |
|
||||
| `TaskUpdate` | Built-in | Phase 1/5 | Update task status |
|
||||
| `Read` | Built-in | Phase 2 | Read shared-memory.json, idea files, critique files |
|
||||
| `Write` | Built-in | Phase 3/5 | Write synthesis files, update shared memory |
|
||||
| `Glob` | Built-in | Phase 2 | Find idea and critique files |
|
||||
| `SendMessage` | Built-in | Phase 5 | Report to coordinator |
|
||||
| `mcp__ccw-tools__team_msg` | MCP | Phase 5 | Log communication |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `synthesis_ready` | synthesizer → coordinator | Synthesis completed | 综合整合完成 |
|
||||
| `error` | synthesizer → coordinator | Processing failure | 错误上报 |
|
||||
| `synthesis_ready` | synthesizer -> coordinator | Synthesis completed | Cross-idea synthesis complete |
|
||||
| `error` | synthesizer -> coordinator | Processing failure | Error report |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "synthesizer",
|
||||
to: "coordinator",
|
||||
type: "synthesis_ready",
|
||||
summary: "[synthesizer] Synthesis complete: <themeCount> themes, <proposalCount> proposals",
|
||||
ref: <output-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from synthesizer --to coordinator --type synthesis_ready --summary \"[synthesizer] Synthesis complete\" --ref <output-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('SYNTH-') &&
|
||||
t.owner === 'synthesizer' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `SYNTH-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Context Loading + Shared Memory Read
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | Task description (Session: line) | Yes |
|
||||
| All ideas | ideas/*.md files | Yes |
|
||||
| All critiques | critiques/*.md files | Yes |
|
||||
| GC rounds completed | shared-memory.json.gc_round | Yes |
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
**Loading steps**:
|
||||
|
||||
// Read all ideas and critiques
|
||||
const ideaFiles = Glob({ pattern: `${sessionFolder}/ideas/*.md` })
|
||||
const critiqueFiles = Glob({ pattern: `${sessionFolder}/critiques/*.md` })
|
||||
const allIdeas = ideaFiles.map(f => Read(f))
|
||||
const allCritiques = critiqueFiles.map(f => Read(f))
|
||||
```
|
||||
1. Extract session path from task description (match "Session: <path>")
|
||||
2. Glob all idea files from session/ideas/
|
||||
3. Glob all critique files from session/critiques/
|
||||
4. Read all idea and critique files for synthesis
|
||||
5. Read shared-memory.json for context
|
||||
|
||||
### Phase 3: Synthesis Execution
|
||||
|
||||
```javascript
|
||||
// Synthesis process:
|
||||
// 1. Theme Extraction — 识别跨创意的共同主题
|
||||
// 2. Conflict Resolution — 解决相互矛盾的想法
|
||||
// 3. Complementary Grouping — 将互补的创意组合
|
||||
// 4. Gap Identification — 发现未覆盖的视角
|
||||
// 5. Integrated Proposal — 生成1-3个整合方案
|
||||
**Synthesis Process**:
|
||||
|
||||
const synthNum = task.subject.match(/SYNTH-(\d+)/)?.[1] || '001'
|
||||
const outputPath = `${sessionFolder}/synthesis/synthesis-${synthNum}.md`
|
||||
| Step | Action |
|
||||
|------|--------|
|
||||
| 1. Theme Extraction | Identify common themes across ideas |
|
||||
| 2. Conflict Resolution | Resolve contradictory ideas |
|
||||
| 3. Complementary Grouping | Group complementary ideas together |
|
||||
| 4. Gap Identification | Discover uncovered perspectives |
|
||||
| 5. Integrated Proposal | Generate 1-3 consolidated proposals |
|
||||
|
||||
const synthesisContent = `# Synthesis — Round ${synthNum}
|
||||
**Theme Extraction**:
|
||||
- Cross-reference ideas for shared concepts
|
||||
- Rate theme strength (1-10)
|
||||
- List supporting ideas per theme
|
||||
|
||||
**Input**: ${ideaFiles.length} idea files, ${critiqueFiles.length} critique files
|
||||
**GC Rounds Completed**: ${sharedMemory.gc_round || 0}
|
||||
**Conflict Resolution**:
|
||||
- Identify contradictory ideas
|
||||
- Determine resolution approach
|
||||
- Document rationale for resolution
|
||||
|
||||
## Extracted Themes
|
||||
**Integrated Proposal Structure**:
|
||||
- Core concept description
|
||||
- Source ideas combined
|
||||
- Addressed challenges from critiques
|
||||
- Feasibility score (1-10)
|
||||
- Innovation score (1-10)
|
||||
- Key benefits list
|
||||
- Remaining risks list
|
||||
|
||||
${themes.map((theme, i) => `### Theme ${i + 1}: ${theme.name}
|
||||
|
||||
**Description**: ${theme.description}
|
||||
**Supporting Ideas**: ${theme.supportingIdeas.join(', ')}
|
||||
**Strength**: ${theme.strength}/10
|
||||
`).join('\n')}
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
${conflicts.map(c => `### ${c.idea1} vs ${c.idea2}
|
||||
|
||||
**Nature**: ${c.nature}
|
||||
**Resolution**: ${c.resolution}
|
||||
**Rationale**: ${c.rationale}
|
||||
`).join('\n')}
|
||||
|
||||
## Integrated Proposals
|
||||
|
||||
${proposals.map((p, i) => `### Proposal ${i + 1}: ${p.title}
|
||||
|
||||
**Core Concept**: ${p.concept}
|
||||
**Combines**: ${p.sourceIdeas.join(' + ')}
|
||||
**Addresses Challenges**: ${p.addressedChallenges.join(', ')}
|
||||
**Feasibility**: ${p.feasibility}/10
|
||||
**Innovation**: ${p.innovation}/10
|
||||
|
||||
**Description**:
|
||||
${p.description}
|
||||
|
||||
**Key Benefits**:
|
||||
${p.benefits.map(b => `- ${b}`).join('\n')}
|
||||
|
||||
**Remaining Risks**:
|
||||
${p.risks.map(r => `- ${r}`).join('\n')}
|
||||
`).join('\n')}
|
||||
|
||||
## Coverage Analysis
|
||||
|
||||
| Aspect | Covered | Gaps |
|
||||
|--------|---------|------|
|
||||
${coverageAnalysis.map(a => `| ${a.aspect} | ${a.covered ? '✅' : '❌'} | ${a.gap || '—'} |`).join('\n')}
|
||||
`
|
||||
|
||||
Write(outputPath, synthesisContent)
|
||||
```
|
||||
**Output file structure**:
|
||||
- File: `<session>/synthesis/synthesis-<num>.md`
|
||||
- Sections: Input summary, Extracted Themes, Conflict Resolution, Integrated Proposals, Coverage Analysis
|
||||
|
||||
### Phase 4: Quality Check
|
||||
|
||||
```javascript
|
||||
// Verify synthesis quality
|
||||
const proposalCount = proposals.length
|
||||
const themeCount = themes.length
|
||||
|
||||
if (proposalCount === 0) {
|
||||
// At least one proposal required
|
||||
}
|
||||
|
||||
if (themeCount < 2) {
|
||||
// May need to look for more patterns
|
||||
}
|
||||
```
|
||||
| Check | Pass Criteria | Action on Failure |
|
||||
|-------|---------------|-------------------|
|
||||
| Proposal count | >= 1 proposal | Generate at least one proposal |
|
||||
| Theme count | >= 2 themes | Look for more patterns |
|
||||
| Conflict resolution | All conflicts documented | Address unresolved conflicts |
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
sharedMemory.synthesis_themes = themes.map(t => ({
|
||||
name: t.name,
|
||||
strength: t.strength,
|
||||
supporting_ideas: t.supportingIdeas
|
||||
}))
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "synthesizer",
|
||||
to: "coordinator",
|
||||
type: "synthesis_ready",
|
||||
summary: `[synthesizer] Synthesis complete: ${themeCount} themes, ${proposalCount} proposals`,
|
||||
ref: outputPath
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[synthesizer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [synthesizer] Synthesis Results
|
||||
**Shared Memory Update**:
|
||||
1. Set shared-memory.json.synthesis_themes
|
||||
2. Each entry: name, strength, supporting_ideas
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Themes**: ${themeCount}
|
||||
**Proposals**: ${proposalCount}
|
||||
**Conflicts Resolved**: ${conflicts.length}
|
||||
**Output**: ${outputPath}
|
||||
|
||||
### Top Proposals
|
||||
${proposals.slice(0, 3).map((p, i) => `${i + 1}. **${p.title}** — ${p.concept} (Feasibility: ${p.feasibility}/10, Innovation: ${p.innovation}/10)`).join('\n')}`,
|
||||
summary: `[synthesizer] ${themeCount} themes, ${proposalCount} proposals`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('SYNTH-') && t.owner === 'synthesizer' &&
|
||||
t.status === 'pending' && t.blockedBy.length === 0
|
||||
)
|
||||
if (nextTasks.length > 0) { /* back to Phase 1 */ }
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -203,3 +165,4 @@ if (nextTasks.length > 0) { /* back to Phase 1 */ }
|
||||
| No ideas/critiques found | Notify coordinator |
|
||||
| Irreconcilable conflicts | Present both sides, recommend user decision |
|
||||
| Only one idea survives | Create single focused proposal |
|
||||
| Critical issue beyond scope | SendMessage error to coordinator |
|
||||
|
||||
Reference in New Issue
Block a user