mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 13:03:53 +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,178 +6,180 @@ allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), Task
|
||||
|
||||
# Team Ultra Analyze
|
||||
|
||||
深度协作分析团队技能。将单体分析工作流拆分为 5 角色协作:探索→分析→讨论→综合。支持 Quick/Standard/Deep 三种管道模式,通过讨论循环实现用户引导的渐进式理解深化。所有成员通过 `--role=xxx` 路由到角色执行逻辑。
|
||||
Deep collaborative analysis team skill. Splits monolithic analysis into 5-role collaboration: explore -> analyze -> discuss -> synthesize. Supports Quick/Standard/Deep pipeline modes with configurable depth (N parallel agents). Discussion loops enable user-guided progressive understanding. All members route via `--role=xxx`.
|
||||
|
||||
## Architecture Overview
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Skill(skill="team-ultra-analyze", args="--role=xxx") │
|
||||
└──────────────────────┬──────────────────────────────────┘
|
||||
│ Role Router
|
||||
┌──────────┬───────┼───────────┬───────────┐
|
||||
↓ ↓ ↓ ↓ ↓
|
||||
┌────────┐┌────────┐┌────────┐┌──────────┐┌───────────┐
|
||||
│coordi- ││explorer││analyst ││discussant││synthesizer│
|
||||
│nator ││EXPLORE-││ANALYZE-││DISCUSS-* ││SYNTH-* │
|
||||
│ roles/ ││* roles/││* roles/││ roles/ ││ roles/ │
|
||||
└────────┘└────────┘└────────┘└──────────┘└───────────┘
|
||||
+-------------------------------------------------------------+
|
||||
| Skill(skill="team-ultra-analyze") |
|
||||
| args="topic description" or args="--role=xxx" |
|
||||
+----------------------------+--------------------------------+
|
||||
| Role Router
|
||||
+---- --role present? ----+
|
||||
| NO | YES
|
||||
v v
|
||||
Orchestration Mode Role Dispatch
|
||||
(auto -> coordinator) (route to role.md)
|
||||
|
|
||||
+-----+------+----------+-----------+
|
||||
v v v v v
|
||||
coordinator explorer analyst discussant synthesizer
|
||||
EXPLORE-* ANALYZE-* DISCUSS-* SYNTH-*
|
||||
```
|
||||
|
||||
## Command Architecture
|
||||
|
||||
```
|
||||
roles/
|
||||
├── coordinator/
|
||||
│ ├── role.md # 编排:话题澄清、管道选择、讨论循环、结果汇报
|
||||
│ └── commands/
|
||||
│ ├── dispatch.md # 任务链创建与依赖管理
|
||||
│ └── monitor.md # 进度监控 + 讨论循环
|
||||
├── explorer/
|
||||
│ ├── role.md # 代码库探索
|
||||
│ └── commands/
|
||||
│ └── explore.md # cli-explore-agent 并行探索
|
||||
├── analyst/
|
||||
│ ├── role.md # 深度分析
|
||||
│ └── commands/
|
||||
│ └── analyze.md # CLI 多视角分析
|
||||
├── discussant/
|
||||
│ ├── role.md # 讨论处理 + 方向调整
|
||||
│ └── commands/
|
||||
│ └── deepen.md # 深入探索
|
||||
└── synthesizer/
|
||||
├── role.md # 综合结论
|
||||
└── commands/
|
||||
└── synthesize.md # 跨视角整合
|
||||
+-- coordinator/
|
||||
| +-- role.md # Orchestration: topic clarification, pipeline selection, discussion loop, reporting
|
||||
| +-- commands/
|
||||
| +-- dispatch.md # Task chain creation and dependency management
|
||||
| +-- monitor.md # Progress monitoring + discussion loop
|
||||
+-- explorer/
|
||||
| +-- role.md # Codebase exploration
|
||||
| +-- commands/
|
||||
| +-- explore.md # cli-explore-agent parallel exploration
|
||||
+-- analyst/
|
||||
| +-- role.md # Deep analysis
|
||||
| +-- commands/
|
||||
| +-- analyze.md # CLI multi-perspective analysis
|
||||
+-- discussant/
|
||||
| +-- role.md # Discussion processing + direction adjustment
|
||||
| +-- commands/
|
||||
| +-- deepen.md # Deep-dive exploration
|
||||
+-- synthesizer/
|
||||
+-- role.md # Synthesis and conclusions
|
||||
+-- commands/
|
||||
+-- synthesize.md # Cross-perspective integration
|
||||
```
|
||||
|
||||
**设计原则**: role.md 保留 Phase 1(Task Discovery)和 Phase 5(Report)内联。Phase 2-4 根据复杂度决定内联或委派到 `commands/*.md`。
|
||||
**Design principle**: role.md retains Phase 1 (Task Discovery) and Phase 5 (Report) inline. Phase 2-4 delegate to `commands/*.md` based on complexity.
|
||||
|
||||
## Role Router
|
||||
|
||||
### Input Parsing
|
||||
|
||||
Parse `$ARGUMENTS` to extract `--role` and optional `--agent-name`:
|
||||
Parse `$ARGUMENTS` to extract `--role` and optional `--agent-name`. If `--role` is absent, enter Orchestration Mode (auto route to coordinator). The `--agent-name` parameter supports parallel instances (e.g., explorer-1, analyst-2) and is passed through to role.md for task discovery filtering.
|
||||
|
||||
```javascript
|
||||
const args = "$ARGUMENTS"
|
||||
const roleMatch = args.match(/--role[=\s]+(\w+)/)
|
||||
### Role Registry
|
||||
|
||||
if (!roleMatch) {
|
||||
throw new Error("Missing --role argument. Available roles: coordinator, explorer, analyst, discussant, synthesizer")
|
||||
}
|
||||
| Role | File | Task Prefix | Type | Compact |
|
||||
|------|------|-------------|------|---------|
|
||||
| coordinator | [roles/coordinator/role.md](roles/coordinator/role.md) | (none) | orchestrator | **compress: must re-read** |
|
||||
| explorer | [roles/explorer/role.md](roles/explorer/role.md) | EXPLORE-* | parallel worker | compress: must re-read |
|
||||
| analyst | [roles/analyst/role.md](roles/analyst/role.md) | ANALYZE-* | parallel worker | compress: must re-read |
|
||||
| discussant | [roles/discussant/role.md](roles/discussant/role.md) | DISCUSS-* | pipeline | compress: must re-read |
|
||||
| synthesizer | [roles/synthesizer/role.md](roles/synthesizer/role.md) | SYNTH-* | pipeline | compress: must re-read |
|
||||
|
||||
const role = roleMatch[1]
|
||||
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "ultra-analyze"
|
||||
// --agent-name for parallel instances (e.g., explorer-1, analyst-2)
|
||||
// Passed through to role.md for task discovery filtering
|
||||
const agentName = args.match(/--agent-name[=\s]+([\w-]+)/)?.[1] || role
|
||||
> **COMPACT PROTECTION**: Role files are execution documents, not reference material. When context compression occurs and role instructions are reduced to summaries, you **must immediately `Read` the corresponding role.md to reload before continuing execution**. Never execute any Phase based on compressed summaries alone.
|
||||
|
||||
### 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 the analysis topic.
|
||||
|
||||
**Invocation**: `Skill(skill="team-ultra-analyze", args="analysis topic description")`
|
||||
|
||||
**Lifecycle**:
|
||||
```
|
||||
User provides analysis topic
|
||||
-> coordinator Phase 1-3: topic clarification -> TeamCreate -> pipeline selection -> create task chain
|
||||
-> coordinator Phase 4: spawn depth explorers in parallel (background) -> STOP
|
||||
-> Explorers execute -> SendMessage callback -> coordinator spawns analysts
|
||||
-> Analysts execute -> SendMessage callback -> coordinator spawns discussant
|
||||
-> Discussion loop (Deep mode: user feedback -> deepen -> re-analyze -> repeat)
|
||||
-> coordinator spawns synthesizer -> final conclusions -> Phase 5 report
|
||||
```
|
||||
|
||||
### Role Dispatch
|
||||
**User Commands** (wake suspended coordinator):
|
||||
|
||||
```javascript
|
||||
const VALID_ROLES = {
|
||||
"coordinator": { file: "roles/coordinator/role.md", prefix: null },
|
||||
"explorer": { file: "roles/explorer/role.md", prefix: "EXPLORE" },
|
||||
"analyst": { file: "roles/analyst/role.md", prefix: "ANALYZE" },
|
||||
"discussant": { file: "roles/discussant/role.md", prefix: "DISCUSS" },
|
||||
"synthesizer": { file: "roles/synthesizer/role.md", prefix: "SYNTH" }
|
||||
}
|
||||
| Command | Action |
|
||||
|---------|--------|
|
||||
| `check` / `status` | Output execution status diagram, do not advance pipeline |
|
||||
| `resume` / `continue` | Check worker status, advance to next pipeline 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/role.md](roles/coordinator/role.md) |
|
||||
| `explorer` | EXPLORE-* | cli-explore-agent 多角度并行代码库探索 | [roles/explorer/role.md](roles/explorer/role.md) |
|
||||
| `analyst` | ANALYZE-* | CLI 多视角深度分析 | [roles/analyst/role.md](roles/analyst/role.md) |
|
||||
| `discussant` | DISCUSS-* | 用户反馈处理、方向调整、深入分析 | [roles/discussant/role.md](roles/discussant/role.md) |
|
||||
| `synthesizer` | SYNTH-* | 跨视角整合、结论生成、决策追踪 | [roles/synthesizer/role.md](roles/synthesizer/role.md) |
|
||||
---
|
||||
|
||||
## Shared Infrastructure
|
||||
|
||||
The following templates apply to all worker roles. Each role.md only needs to define **Phase 2-4** role-specific logic.
|
||||
|
||||
### Worker Phase 1: Task Discovery (shared by all workers)
|
||||
|
||||
Each 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 matches this agent's name + 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 recovery):
|
||||
- Check if this task's output artifacts already exist
|
||||
- Artifacts complete -> skip to Phase 5 report completion
|
||||
- Artifacts incomplete or missing -> execute Phase 2-4 normally
|
||||
|
||||
### Worker Phase 5: Report (shared by all workers)
|
||||
|
||||
Standard report flow after task completion:
|
||||
|
||||
1. **Message Bus**: Call `mcp__ccw-tools__team_msg` to log message
|
||||
- Parameters: operation="log", team=<team-name>, from=<role>, to="coordinator", type=<message-type>, summary="[<role>] <summary>", ref=<artifact-path>
|
||||
- **CLI fallback**: When MCP unavailable -> `ccw team log --team <team> --from <role> --to coordinator --type <type> --summary "[<role>] ..." --json`
|
||||
2. **SendMessage**: Send result to coordinator (both content and summary prefixed with `[<role>]`)
|
||||
3. **TaskUpdate**: Mark task completed
|
||||
4. **Loop**: Return to Phase 1 to check for next task
|
||||
|
||||
### Wisdom Accumulation (all roles)
|
||||
|
||||
Cross-task knowledge accumulation. Coordinator creates `wisdom/` directory during session initialization.
|
||||
|
||||
**Directory**:
|
||||
```
|
||||
<session-folder>/wisdom/
|
||||
+-- learnings.md # Patterns and insights
|
||||
+-- decisions.md # Analysis direction decisions
|
||||
+-- conventions.md # Codebase conventions discovered
|
||||
+-- 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 discoveries from this task into corresponding wisdom files.
|
||||
|
||||
### Role Isolation Rules
|
||||
|
||||
**核心原则**: 每个角色仅能执行自己职责范围内的工作。
|
||||
| Allowed | Prohibited |
|
||||
|---------|-----------|
|
||||
| Process tasks matching 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/*.md | Modify resources outside own responsibility |
|
||||
|
||||
#### Output Tagging(强制)
|
||||
Coordinator additionally prohibited: directly executing code exploration or analysis, directly calling cli-explore-agent or CLI analysis tools, bypassing workers to complete work.
|
||||
|
||||
所有角色的输出必须带 `[role_name]` 标识前缀:
|
||||
### Shared Memory
|
||||
|
||||
```javascript
|
||||
SendMessage({ content: `## [${role}] ...`, summary: `[${role}] ...` })
|
||||
mcp__ccw-tools__team_msg({ summary: `[${role}] ...` })
|
||||
```
|
||||
Core shared artifact stored at `<session-folder>/shared-memory.json`. Each role reads the full memory but writes only to its own designated field:
|
||||
|
||||
#### Coordinator 隔离
|
||||
| Role | Write Field |
|
||||
|------|-------------|
|
||||
| explorer | `explorations` |
|
||||
| analyst | `analyses` |
|
||||
| discussant | `discussions` |
|
||||
| synthesizer | `synthesis` |
|
||||
| coordinator | `decision_trail` + `current_understanding` |
|
||||
|
||||
| 允许 | 禁止 |
|
||||
|------|------|
|
||||
| 话题澄清 (AskUserQuestion) | ❌ 直接执行代码探索或分析 |
|
||||
| 创建任务链 (TaskCreate) | ❌ 直接调用 cli-explore-agent |
|
||||
| 管道选择 + 讨论循环驱动 | ❌ 直接调用 CLI 分析工具 |
|
||||
| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成 |
|
||||
|
||||
#### Worker 隔离
|
||||
|
||||
| 允许 | 禁止 |
|
||||
|------|------|
|
||||
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
|
||||
| 读写 shared-memory.json (自己的字段) | ❌ 为其他角色创建任务 |
|
||||
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
|
||||
|
||||
### Team Configuration
|
||||
|
||||
```javascript
|
||||
const TEAM_CONFIG = {
|
||||
name: "ultra-analyze",
|
||||
sessionDir: ".workflow/.team/UAN-{slug}-{date}/",
|
||||
sharedMemory: "shared-memory.json",
|
||||
analysisDimensions: ["architecture", "implementation", "performance", "security", "concept", "comparison", "decision"],
|
||||
maxDiscussionRounds: 5
|
||||
}
|
||||
```
|
||||
|
||||
### Shared Memory(核心产物)
|
||||
|
||||
```javascript
|
||||
// 各角色读取共享记忆
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
|
||||
// 各角色写入自己负责的字段:
|
||||
// explorer → sharedMemory.explorations
|
||||
// analyst → sharedMemory.analyses
|
||||
// discussant → sharedMemory.discussions
|
||||
// synthesizer → sharedMemory.synthesis
|
||||
// coordinator → sharedMemory.decision_trail + current_understanding
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
```
|
||||
On startup, read the file. After completing work, update own field and write back. If file does not exist, initialize with empty object.
|
||||
|
||||
### Message Bus (All Roles)
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: role,
|
||||
to: "coordinator",
|
||||
type: "<type>",
|
||||
summary: `[${role}] <summary>`,
|
||||
ref: "<file_path>"
|
||||
})
|
||||
```
|
||||
All roles log messages before sending via SendMessage. Call `mcp__ccw-tools__team_msg` with: operation="log", team=<team-name>, from=<role>, to="coordinator", type=<message-type>, summary="[<role>] <summary>", ref=<file-path>.
|
||||
|
||||
| Role | Types |
|
||||
|------|-------|
|
||||
@@ -187,286 +189,251 @@ mcp__ccw-tools__team_msg({
|
||||
| discussant | `discussion_processed`, `error` |
|
||||
| synthesizer | `synthesis_ready`, `error` |
|
||||
|
||||
### CLI 回退
|
||||
**CLI fallback**: When MCP unavailable -> `ccw team log --team "<team>" --from "<role>" --to "coordinator" --type "<type>" --summary "<summary>" --json`
|
||||
|
||||
```javascript
|
||||
Bash(`ccw team log --team "${teamName}" --from "${role}" --to "coordinator" --type "<type>" --summary "<摘要>" --json`)
|
||||
```
|
||||
|
||||
### Task Lifecycle (All Worker Roles)
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
|
||||
t.owner === role &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
if (myTasks.length === 0) return
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
|
||||
// Phase 2-4: Role-specific
|
||||
// Phase 5: Report + Loop
|
||||
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' })
|
||||
```
|
||||
---
|
||||
|
||||
## Three-Mode Pipeline Architecture
|
||||
|
||||
```
|
||||
Quick: EXPLORE-001 → ANALYZE-001 → SYNTH-001
|
||||
Standard: [EXPLORE-001..N](parallel) → [ANALYZE-001..N](parallel) → DISCUSS-001 → SYNTH-001
|
||||
Deep: [EXPLORE-001..N] → [ANALYZE-001..N] → DISCUSS-001 → ANALYZE-fix → DISCUSS-002 → ... → SYNTH-001
|
||||
Quick: EXPLORE-001 -> ANALYZE-001 -> SYNTH-001
|
||||
Standard: [EXPLORE-001..depth](parallel) -> [ANALYZE-001..depth](parallel) -> DISCUSS-001 -> SYNTH-001
|
||||
Deep: [EXPLORE-001..depth] -> [ANALYZE-001..depth] -> DISCUSS-001 -> ANALYZE-fix -> DISCUSS-002 -> ... -> SYNTH-001
|
||||
```
|
||||
|
||||
### Mode Auto-Detection
|
||||
|
||||
```javascript
|
||||
function detectPipelineMode(args, taskDescription) {
|
||||
const modeMatch = args.match(/--mode[=\s]+(quick|standard|deep)/)
|
||||
if (modeMatch) return modeMatch[1]
|
||||
// 自动检测
|
||||
if (/快速|quick|overview|概览/.test(taskDescription)) return 'quick'
|
||||
if (/深入|deep|thorough|详细|全面/.test(taskDescription)) return 'deep'
|
||||
return 'standard'
|
||||
}
|
||||
```
|
||||
Parse `--mode` from arguments first. If not specified, auto-detect from topic description:
|
||||
|
||||
| Condition | Mode | Depth |
|
||||
|-----------|------|-------|
|
||||
| `--mode=quick` explicit or topic contains "quick/overview/fast" | Quick | 1 |
|
||||
| `--mode=deep` explicit or topic contains "deep/thorough/detailed/comprehensive" | Deep | N (from perspectives) |
|
||||
| Default (no match) | Standard | N (from perspectives) |
|
||||
|
||||
**Depth** is determined by the number of selected analysis perspectives (e.g., architecture, implementation, performance, security, concept, comparison, decision). Quick mode always uses depth=1. Standard/Deep mode uses depth = number of selected perspectives.
|
||||
|
||||
### Discussion Loop (Deep Mode)
|
||||
|
||||
```
|
||||
coordinator(AskUser) → DISCUSS-N(deepen) → [optional ANALYZE-fix] → coordinator(AskUser) → ... → SYNTH
|
||||
coordinator(AskUser) -> DISCUSS-N(deepen) -> [optional ANALYZE-fix] -> coordinator(AskUser) -> ... -> SYNTH
|
||||
```
|
||||
|
||||
Maximum 5 discussion rounds. If exceeded, force synthesis and offer continuation option.
|
||||
|
||||
## Decision Recording Protocol
|
||||
|
||||
**⚠️ CRITICAL**: 继承自原 analyze-with-file 命令。分析过程中以下情况必须立即记录到 discussion.md:
|
||||
**CRITICAL**: Inherited from the original analyze-with-file command. During analysis, the following must be immediately recorded to discussion.md:
|
||||
|
||||
| Trigger | What to Record | Target Section |
|
||||
|---------|---------------|----------------|
|
||||
| **Direction choice** | 选择了什么、为什么、放弃了哪些替代方案 | `#### Decision Log` |
|
||||
| **Key finding** | 发现内容、影响范围、置信度 | `#### Key Findings` |
|
||||
| **Assumption change** | 旧假设→新理解、变更原因、影响 | `#### Corrected Assumptions` |
|
||||
| **User feedback** | 用户原始输入、采纳/调整理由 | `#### User Input` |
|
||||
| **Direction choice** | What was chosen, why, which alternatives were rejected | `#### Decision Log` |
|
||||
| **Key finding** | Discovery content, impact scope, confidence level | `#### Key Findings` |
|
||||
| **Assumption change** | Old assumption -> new understanding, reason for change, impact | `#### Corrected Assumptions` |
|
||||
| **User feedback** | User's raw input, adoption/adjustment rationale | `#### User Input` |
|
||||
|
||||
## Cadence Control
|
||||
|
||||
**Beat model**: Event-driven. Each beat = coordinator wakes -> processes callback -> spawns next phase -> STOP.
|
||||
|
||||
```
|
||||
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)
|
||||
=====================================================================
|
||||
```
|
||||
|
||||
**Discussion Loop Beat (Deep mode with configurable depth)**:
|
||||
|
||||
```
|
||||
Phase 1 (explore): Spawn depth explorers simultaneously
|
||||
EXPLORE-1, EXPLORE-2, ..., EXPLORE-depth (all parallel)
|
||||
-> All complete -> coordinator wakes
|
||||
|
||||
Phase 2 (analyze): Spawn depth analysts simultaneously
|
||||
ANALYZE-1, ANALYZE-2, ..., ANALYZE-depth (all parallel)
|
||||
-> All complete -> coordinator wakes
|
||||
|
||||
Phase 3 (discuss): Spawn 1 discussant
|
||||
DISCUSS-001
|
||||
-> Complete -> coordinator asks user for direction
|
||||
|
||||
Phase 3a (loop): If user requests deeper analysis (Deep mode only):
|
||||
-> Spawn ANALYZE-fix tasks -> DISCUSS-002 -> ask user -> repeat
|
||||
-> Maximum 5 rounds
|
||||
|
||||
Phase 4 (synth): Spawn 1 synthesizer
|
||||
SYNTHESIZE-001
|
||||
-> Complete -> coordinator reports to user
|
||||
```
|
||||
|
||||
**Pipeline Beat Views**:
|
||||
|
||||
```
|
||||
Quick (3 beats, serial)
|
||||
------------------------------------------------------
|
||||
Beat 1 2 3
|
||||
| | |
|
||||
EXPLORE -> ANALYZE -> SYNTH
|
||||
|
||||
Standard (4 beats, parallel windows)
|
||||
------------------------------------------------------
|
||||
Beat 1 2 3 4
|
||||
+----- ... ----+ +----- ... ----+ | |
|
||||
E1 || E2 || EN A1 || A2 || AN -> DISCUSS -> SYNTH
|
||||
+---- parallel ---+ +---- parallel ---+
|
||||
|
||||
Deep (4+ beats, with discussion loop)
|
||||
------------------------------------------------------
|
||||
Beat 1 2 3 3a... 4
|
||||
+-...-+ +-...-+ | +-- loop --+ |
|
||||
E1||EN A1||AN -> DISC -> A-fix->DISC -> SYNTH
|
||||
(max 5 rounds)
|
||||
```
|
||||
|
||||
**Checkpoints**:
|
||||
|
||||
| Trigger | Location | Behavior |
|
||||
|---------|----------|----------|
|
||||
| Discussion round (Deep mode) | After DISCUSS-N completes | Pause, AskUser for direction/continuation |
|
||||
| Discussion loop limit | >5 rounds | Force synthesis, offer continuation |
|
||||
| Pipeline stall | No ready + no running | Check missing tasks, report to user |
|
||||
|
||||
**Stall detection** (coordinator `handleCheck`):
|
||||
|
||||
| Check | Condition | Resolution |
|
||||
|-------|-----------|------------|
|
||||
| Worker unresponsive | in_progress task with no callback | Report waiting tasks, suggest user `resume` |
|
||||
| Pipeline deadlock | No ready + no running + has pending | Check blockedBy chain, report blockage |
|
||||
| Discussion loop over limit | DISCUSS round > 5 | Terminate loop, output latest discussion state |
|
||||
|
||||
## Task Metadata Registry
|
||||
|
||||
| Task ID | Role | Phase | Dependencies | Description |
|
||||
|---------|------|-------|-------------|-------------|
|
||||
| EXPLORE-1..depth | explorer | explore | (none) | Parallel codebase exploration, one per perspective |
|
||||
| ANALYZE-1..depth | analyst | analyze | EXPLORE-1..depth (all complete) | Parallel deep analysis, one per perspective |
|
||||
| DISCUSS-001 | discussant | discuss | ANALYZE-1..depth (all complete) | Process analysis results, identify gaps |
|
||||
| ANALYZE-fix-N | analyst | discuss-loop | DISCUSS-N | Re-analysis for specific areas (Deep mode only) |
|
||||
| DISCUSS-002..N | discussant | discuss-loop | ANALYZE-fix-N | Subsequent discussion rounds (Deep mode, max 5) |
|
||||
| SYNTHESIZE-001 | synthesizer | synthesize | Last DISCUSS-N | Cross-perspective integration and conclusions |
|
||||
|
||||
**Dynamic task creation**: Coordinator creates EXPLORE-1 through EXPLORE-depth and ANALYZE-1 through ANALYZE-depth based on the number of selected perspectives. Discussion loop tasks (ANALYZE-fix-N, DISCUSS-002+) are created dynamically in Deep mode based on user feedback.
|
||||
|
||||
## Coordinator Spawn Template
|
||||
|
||||
When coordinator spawns workers, use background mode (Spawn-and-Stop pattern). The coordinator determines the depth (number of parallel agents) based on selected perspectives.
|
||||
|
||||
**Phase 1 - Spawn Explorers**: Create depth explorer agents in parallel (EXPLORE-1 through EXPLORE-depth). Each explorer receives its assigned perspective/domain and agent name for task matching. All spawned with run_in_background:true. Coordinator stops after spawning and waits for callbacks.
|
||||
|
||||
**Phase 2 - Spawn Analysts**: After all explorers complete, create depth analyst agents in parallel (ANALYZE-1 through ANALYZE-depth). Each analyst receives its assigned perspective matching the corresponding explorer. All spawned with run_in_background:true. Coordinator stops.
|
||||
|
||||
**Phase 3 - Spawn Discussant**: After all analysts complete, create 1 discussant. It processes all analysis results and presents findings to user. Coordinator stops.
|
||||
|
||||
**Phase 3a - Discussion Loop** (Deep mode only): Based on user feedback, coordinator may create additional ANALYZE-fix and DISCUSS tasks. Loop continues until user is satisfied or 5 rounds reached.
|
||||
|
||||
**Phase 4 - Spawn Synthesizer**: After final discussion round, create 1 synthesizer. It integrates all explorations, analyses, and discussions into final conclusions. Coordinator stops.
|
||||
|
||||
**Quick mode exception**: When depth=1, spawn single explorer, single analyst, single discussant, single synthesizer -- all as simple agents without numbered suffixes.
|
||||
|
||||
**Single spawn example** (worker template used for all roles):
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: "Spawn <role> worker",
|
||||
team_name: <team-name>,
|
||||
name: "<agent-name>",
|
||||
run_in_background: true,
|
||||
prompt: `You are team "<team-name>" <ROLE> (<agent-name>).
|
||||
Your agent name is "<agent-name>", use it for task discovery owner matching.
|
||||
|
||||
## Primary Instruction
|
||||
All work must be executed by calling Skill for role definition:
|
||||
Skill(skill="team-ultra-analyze", args="--role=<role> --agent-name=<agent-name>")
|
||||
|
||||
Current topic: <task-description>
|
||||
Session: <session-folder>
|
||||
|
||||
## Role Rules
|
||||
- Only process <PREFIX>-* tasks where owner === "<agent-name>"
|
||||
- All output prefixed with [<role>] identifier
|
||||
- Communicate only 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. Execute role.md 5-Phase process
|
||||
3. team_msg + SendMessage result to coordinator
|
||||
4. TaskUpdate completed -> check next task`
|
||||
})
|
||||
```
|
||||
|
||||
## Team Configuration
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Team name | ultra-analyze |
|
||||
| Session directory | .workflow/.team/UAN-{slug}-{date}/ |
|
||||
| Shared memory file | shared-memory.json |
|
||||
| Analysis dimensions | architecture, implementation, performance, security, concept, comparison, decision |
|
||||
| Max discussion rounds | 5 |
|
||||
|
||||
## Unified Session Directory
|
||||
|
||||
```
|
||||
.workflow/.team/UAN-{slug}-{YYYY-MM-DD}/
|
||||
├── shared-memory.json # 探索/分析/讨论/综合 共享记忆
|
||||
├── discussion.md # ⭐ 理解演进 & 讨论时间线
|
||||
├── explorations/ # Explorer output
|
||||
│ ├── exploration-001.json
|
||||
│ └── exploration-002.json
|
||||
├── analyses/ # Analyst output
|
||||
│ ├── analysis-001.json
|
||||
│ └── analysis-002.json
|
||||
├── discussions/ # Discussant output
|
||||
│ └── discussion-round-001.json
|
||||
└── conclusions.json # Synthesizer output
|
||||
+-- shared-memory.json # Exploration/analysis/discussion/synthesis shared memory
|
||||
+-- discussion.md # Understanding evolution and discussion timeline
|
||||
+-- explorations/ # Explorer output
|
||||
| +-- exploration-001.json
|
||||
| +-- exploration-002.json
|
||||
+-- analyses/ # Analyst output
|
||||
| +-- analysis-001.json
|
||||
| +-- analysis-002.json
|
||||
+-- discussions/ # Discussant output
|
||||
| +-- discussion-round-001.json
|
||||
+-- conclusions.json # Synthesizer output
|
||||
+-- wisdom/ # Cross-task knowledge
|
||||
| +-- learnings.md
|
||||
| +-- decisions.md
|
||||
| +-- conventions.md
|
||||
| +-- issues.md
|
||||
```
|
||||
|
||||
## Coordinator Spawn Template
|
||||
## Session Resume
|
||||
|
||||
```javascript
|
||||
TeamCreate({ team_name: teamName })
|
||||
Coordinator supports `--resume` / `--continue` for interrupted sessions:
|
||||
|
||||
// ── Determine parallel agent count ──
|
||||
const perspectiveCount = selectedPerspectives.length
|
||||
const isParallel = perspectiveCount > 1
|
||||
|
||||
// ── Explorers ──
|
||||
// Quick mode (1 perspective): single "explorer"
|
||||
// Standard/Deep mode (N perspectives): "explorer-1", "explorer-2", ...
|
||||
if (isParallel) {
|
||||
for (let i = 0; i < perspectiveCount; i++) {
|
||||
const agentName = `explorer-${i + 1}`
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn ${agentName} worker`,
|
||||
team_name: teamName,
|
||||
name: agentName,
|
||||
prompt: `你是 team "${teamName}" 的 EXPLORER (${agentName})。
|
||||
你的 agent 名称是 "${agentName}",任务发现时用此名称匹配 owner。
|
||||
|
||||
当你收到 EXPLORE-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=explorer --agent-name=${agentName}") 执行。
|
||||
|
||||
当前需求: ${taskDescription}
|
||||
约束: ${constraints}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 owner 为 "${agentName}" 的 EXPLORE-* 前缀任务
|
||||
- 所有输出(SendMessage、team_msg)必须带 [explorer] 标识前缀
|
||||
- 仅与 coordinator 通信,不得直接联系其他 worker
|
||||
- 不得使用 TaskCreate 为其他角色创建任务
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 owner === "${agentName}" 的 EXPLORE-* 任务
|
||||
2. Skill(skill="team-ultra-analyze", args="--role=explorer --agent-name=${agentName}") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [explorer] 标识)
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Single explorer for quick mode
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn explorer worker`,
|
||||
team_name: teamName,
|
||||
name: "explorer",
|
||||
prompt: `你是 team "${teamName}" 的 EXPLORER。
|
||||
|
||||
当你收到 EXPLORE-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=explorer") 执行。
|
||||
|
||||
当前需求: ${taskDescription}
|
||||
约束: ${constraints}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 EXPLORE-* 前缀的任务,不得执行其他角色的工作
|
||||
- 所有输出(SendMessage、team_msg)必须带 [explorer] 标识前缀
|
||||
- 仅与 coordinator 通信,不得直接联系其他 worker
|
||||
- 不得使用 TaskCreate 为其他角色创建任务
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 EXPLORE-* 任务
|
||||
2. Skill(skill="team-ultra-analyze", args="--role=explorer") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [explorer] 标识)
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
}
|
||||
|
||||
// ── Analysts ──
|
||||
// Same pattern: parallel mode spawns N analysts, quick mode spawns 1
|
||||
if (isParallel) {
|
||||
for (let i = 0; i < perspectiveCount; i++) {
|
||||
const agentName = `analyst-${i + 1}`
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn ${agentName} worker`,
|
||||
team_name: teamName,
|
||||
name: agentName,
|
||||
prompt: `你是 team "${teamName}" 的 ANALYST (${agentName})。
|
||||
你的 agent 名称是 "${agentName}",任务发现时用此名称匹配 owner。
|
||||
|
||||
当你收到 ANALYZE-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=analyst --agent-name=${agentName}") 执行。
|
||||
|
||||
当前需求: ${taskDescription}
|
||||
约束: ${constraints}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 owner 为 "${agentName}" 的 ANALYZE-* 前缀任务
|
||||
- 所有输出必须带 [analyst] 标识前缀
|
||||
- 仅与 coordinator 通信
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 owner === "${agentName}" 的 ANALYZE-* 任务
|
||||
2. Skill(skill="team-ultra-analyze", args="--role=analyst --agent-name=${agentName}") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn analyst worker`,
|
||||
team_name: teamName,
|
||||
name: "analyst",
|
||||
prompt: `你是 team "${teamName}" 的 ANALYST。
|
||||
|
||||
当你收到 ANALYZE-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=analyst") 执行。
|
||||
|
||||
当前需求: ${taskDescription}
|
||||
约束: ${constraints}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 ANALYZE-* 前缀的任务
|
||||
- 所有输出必须带 [analyst] 标识前缀
|
||||
- 仅与 coordinator 通信
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 ANALYZE-* 任务
|
||||
2. Skill(skill="team-ultra-analyze", args="--role=analyst") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
}
|
||||
|
||||
// ── Discussant (always single) ──
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn discussant worker`,
|
||||
team_name: teamName,
|
||||
name: "discussant",
|
||||
prompt: `你是 team "${teamName}" 的 DISCUSSANT。
|
||||
|
||||
当你收到 DISCUSS-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=discussant") 执行。
|
||||
|
||||
当前需求: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 DISCUSS-* 前缀的任务
|
||||
- 所有输出必须带 [discussant] 标识前缀
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 DISCUSS-* 任务
|
||||
2. Skill(skill="team-ultra-analyze", args="--role=discussant") 执行
|
||||
3. team_msg log + SendMessage
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
|
||||
// ── Synthesizer (always single) ──
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn synthesizer worker`,
|
||||
team_name: teamName,
|
||||
name: "synthesizer",
|
||||
prompt: `你是 team "${teamName}" 的 SYNTHESIZER。
|
||||
|
||||
当你收到 SYNTH-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=synthesizer") 执行。
|
||||
|
||||
当前需求: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 SYNTH-* 前缀的任务
|
||||
- 所有输出必须带 [synthesizer] 标识前缀
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 SYNTH-* 任务
|
||||
2. Skill(skill="team-ultra-analyze", args="--role=synthesizer") 执行
|
||||
3. team_msg log + SendMessage
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
```
|
||||
1. Scan `.workflow/.team/UAN-*/` for active/paused sessions
|
||||
2. Multiple matches -> AskUserQuestion for selection
|
||||
3. Audit TaskList -> reconcile session state with task status
|
||||
4. Reset in_progress -> pending (interrupted tasks)
|
||||
5. Rebuild team and spawn needed workers only
|
||||
6. Create missing tasks with correct blockedBy
|
||||
7. Kick first executable task -> Phase 4 coordination loop
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| Unknown --role value | Error with available role list |
|
||||
| Missing --role arg | Error with usage hint |
|
||||
| Missing --role arg | Orchestration Mode -> coordinator |
|
||||
| Role file not found | Error with expected path (roles/{name}/role.md) |
|
||||
| Task prefix conflict | Log warning, proceed |
|
||||
| Discussion loop stuck >5 rounds | Force synthesis, offer continuation |
|
||||
| CLI tool unavailable | Fallback chain: gemini → codex → manual analysis |
|
||||
| CLI tool unavailable | Fallback chain: gemini -> codex -> manual analysis |
|
||||
| Explorer agent fails | Continue with available context, note limitation |
|
||||
|
||||
@@ -1,40 +1,35 @@
|
||||
# Role: analyst
|
||||
# Analyst Role
|
||||
|
||||
深度分析师。基于 explorer 的代码库探索结果,通过 CLI 多视角深度分析,生成结构化洞察和讨论要点。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `analyst`
|
||||
- **Name**: `analyst` | **Tag**: `[analyst]`
|
||||
- **Task Prefix**: `ANALYZE-*`
|
||||
- **Responsibility**: Read-only analysis(深度分析)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[analyst]`
|
||||
- **Responsibility**: Read-only analysis (深度分析)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `ANALYZE-*` 前缀的任务
|
||||
- 所有输出必须带 `[analyst]` 标识
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- 基于 explorer 的探索结果进行深度分析
|
||||
- 将分析结果写入 shared-memory.json 的 `analyses` 字段
|
||||
- Only process `ANALYZE-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[analyst]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within deep analysis responsibility scope
|
||||
- Base analysis on explorer exploration results
|
||||
- Write analysis results to shared-memory.json `analyses` field
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 执行代码库探索(属于 explorer)
|
||||
- ❌ 处理用户反馈(属于 discussant)
|
||||
- ❌ 生成最终结论(属于 synthesizer)
|
||||
- ❌ 为其他角色创建任务
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 修改源代码
|
||||
- Execute codebase exploration (belongs to explorer)
|
||||
- Handle user feedback (belongs to discussant)
|
||||
- Generate final conclusions (belongs to synthesizer)
|
||||
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
|
||||
- Communicate directly with other worker roles
|
||||
- Modify source code
|
||||
- Omit `[analyst]` identifier in any output
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `analysis_ready` | analyst → coordinator | 分析完成 | 包含洞察、讨论要点、开放问题 |
|
||||
| `error` | analyst → coordinator | 分析失败 | 阻塞性错误 |
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -44,11 +39,16 @@
|
||||
|---------|------|-------|-------------|
|
||||
| `analyze` | [commands/analyze.md](commands/analyze.md) | Phase 3 | CLI 多视角深度分析 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
> Analyst 不直接使用 subagent
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `Bash` | CLI | analyze.md | Execute ccw cli for analysis |
|
||||
| `Read` | File | analyst | Read exploration results and session context |
|
||||
| `Write` | File | analyst | Write analysis results |
|
||||
| `Glob` | File | analyst | Find exploration/analysis files |
|
||||
|
||||
### CLI Capabilities
|
||||
### CLI Tools
|
||||
|
||||
| CLI Tool | Mode | Used By | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
@@ -56,239 +56,196 @@
|
||||
| `codex` | analysis | analyze.md | 业务视角分析 |
|
||||
| `claude` | analysis | analyze.md | 架构视角分析 |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `analysis_ready` | analyst → coordinator | 分析完成 | 包含洞察、讨论要点、开放问题 |
|
||||
| `error` | analyst → coordinator | 分析失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: "ultra-analyze",
|
||||
from: "analyst",
|
||||
to: "coordinator",
|
||||
type: "analysis_ready",
|
||||
summary: "[analyst] ANALYZE complete: <summary>",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team ultra-analyze --from analyst --to coordinator --type analysis_ready --summary \"[analyst] ...\" --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
// Parse agent name from --agent-name arg (for parallel instances) or default to 'analyst'
|
||||
const agentNameMatch = args.match(/--agent-name[=\s]+([\w-]+)/)
|
||||
const agentName = agentNameMatch ? agentNameMatch[1] : 'analyst'
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('ANALYZE-') &&
|
||||
t.owner === agentName &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
Standard task discovery flow: TaskList -> filter by prefix `ANALYZE-*` + 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 `analyst` for single-instance roles.
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
```javascript
|
||||
// 从任务描述中提取上下文
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim()
|
||||
const topic = task.description.match(/topic:\s*(.+)/)?.[1]?.trim()
|
||||
const perspective = task.description.match(/perspective:\s*(.+)/)?.[1]?.trim() || 'technical'
|
||||
const dimensions = (task.description.match(/dimensions:\s*(.+)/)?.[1]?.trim() || 'general').split(', ')
|
||||
const isDirectionFix = task.description.includes('type: direction-fix')
|
||||
const adjustedFocus = task.description.match(/adjusted_focus:\s*(.+)/)?.[1]?.trim()
|
||||
**Loading steps**:
|
||||
|
||||
// 读取 shared memory
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
1. Extract session path from task description
|
||||
2. Extract topic, perspective, dimensions from task metadata
|
||||
3. Check for direction-fix type (补充分析)
|
||||
4. Read shared-memory.json for existing context
|
||||
5. Read corresponding exploration results
|
||||
|
||||
// 读取对应的探索结果
|
||||
const analyzeNum = task.subject.match(/ANALYZE-(\w+)/)?.[1] || '001'
|
||||
let explorationContext = {}
|
||||
**Context extraction**:
|
||||
|
||||
if (isDirectionFix) {
|
||||
// 方向调整:读取所有已有探索结果
|
||||
const explorationFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
|
||||
const allExplorations = explorationFiles.map(f => JSON.parse(Read(f)))
|
||||
explorationContext = {
|
||||
relevant_files: allExplorations.flatMap(e => e.relevant_files || []).slice(0, 10),
|
||||
patterns: allExplorations.flatMap(e => e.patterns || []),
|
||||
key_findings: allExplorations.flatMap(e => e.key_findings || [])
|
||||
}
|
||||
} else {
|
||||
// 正常分析:读取对应编号的探索结果
|
||||
try {
|
||||
explorationContext = JSON.parse(Read(`${sessionFolder}/explorations/exploration-${analyzeNum}.json`))
|
||||
} catch {
|
||||
// 尝试读取任意可用的探索结果
|
||||
const explorationFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
|
||||
if (explorationFiles.length > 0) {
|
||||
explorationContext = JSON.parse(Read(explorationFiles[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
| Field | Source | Pattern |
|
||||
|-------|--------|---------|
|
||||
| sessionFolder | task description | `session:\s*(.+)` |
|
||||
| topic | task description | `topic:\s*(.+)` |
|
||||
| perspective | task description | `perspective:\s*(.+)` or default "technical" |
|
||||
| dimensions | task description | `dimensions:\s*(.+)` or default "general" |
|
||||
| isDirectionFix | task description | `type:\s*direction-fix` |
|
||||
| adjustedFocus | task description | `adjusted_focus:\s*(.+)` |
|
||||
|
||||
// 确定 CLI 工具
|
||||
const PERSPECTIVE_TOOLS = {
|
||||
'technical': 'gemini',
|
||||
'architectural': 'claude',
|
||||
'business': 'codex',
|
||||
'domain_expert': 'gemini'
|
||||
}
|
||||
const cliTool = PERSPECTIVE_TOOLS[perspective] || 'gemini'
|
||||
```
|
||||
**Exploration context loading**:
|
||||
|
||||
| Condition | Source |
|
||||
|-----------|--------|
|
||||
| Direction fix | Read ALL exploration files, merge context |
|
||||
| Normal analysis | Read exploration file matching ANALYZE-N number |
|
||||
| Fallback | Read first available exploration file |
|
||||
|
||||
**CLI tool selection**:
|
||||
|
||||
| Perspective | CLI Tool |
|
||||
|-------------|----------|
|
||||
| technical | gemini |
|
||||
| architectural | claude |
|
||||
| business | codex |
|
||||
| domain_expert | gemini |
|
||||
|
||||
### Phase 3: Deep Analysis via CLI
|
||||
|
||||
```javascript
|
||||
// Read commands/analyze.md for full CLI analysis implementation
|
||||
Read("commands/analyze.md")
|
||||
Delegate to `commands/analyze.md` if available, otherwise execute inline.
|
||||
|
||||
**Analysis prompt structure** (Direction Fix):
|
||||
|
||||
```
|
||||
|
||||
**核心策略**: 基于探索结果,通过 CLI 执行深度分析
|
||||
|
||||
```javascript
|
||||
const analysisPrompt = isDirectionFix
|
||||
? `PURPOSE: 补充分析 - 方向调整至 "${adjustedFocus}"
|
||||
PURPOSE: 补充分析 - 方向调整至 "<adjusted_focus>"
|
||||
Success: 针对新方向的深入洞察
|
||||
|
||||
PRIOR EXPLORATION CONTEXT:
|
||||
- Key files: ${(explorationContext.relevant_files || []).slice(0, 5).map(f => f.path || f).join(', ')}
|
||||
- Patterns: ${(explorationContext.patterns || []).slice(0, 3).join(', ')}
|
||||
- Previous findings: ${(explorationContext.key_findings || []).slice(0, 3).join(', ')}
|
||||
- Key files: <top 5 files from exploration>
|
||||
- Patterns: <top 3 patterns>
|
||||
- Previous findings: <top 3 findings>
|
||||
|
||||
TASK:
|
||||
• Focus analysis on: ${adjustedFocus}
|
||||
• Build on previous exploration findings
|
||||
• Identify new insights from adjusted perspective
|
||||
• Generate discussion points for user
|
||||
- Focus analysis on: <adjusted_focus>
|
||||
- Build on previous exploration findings
|
||||
- Identify new insights from adjusted perspective
|
||||
- Generate discussion points for user
|
||||
|
||||
MODE: analysis
|
||||
CONTEXT: @**/* | Topic: ${topic}
|
||||
CONTEXT: @**/* | Topic: <topic>
|
||||
EXPECTED: Structured analysis with adjusted focus, new insights, updated discussion points
|
||||
CONSTRAINTS: Focus on ${adjustedFocus}`
|
||||
: `PURPOSE: Analyze topic '${topic}' from ${perspective} perspective across ${dimensions.join(', ')} dimensions
|
||||
CONSTRAINTS: Focus on <adjusted_focus>
|
||||
```
|
||||
|
||||
**Analysis prompt structure** (Normal):
|
||||
|
||||
```
|
||||
PURPOSE: Analyze topic '<topic>' from <perspective> perspective across <dimensions> dimensions
|
||||
Success: Actionable insights with clear reasoning and evidence
|
||||
|
||||
PRIOR EXPLORATION CONTEXT:
|
||||
- Key files: ${(explorationContext.relevant_files || []).slice(0, 5).map(f => f.path || f).join(', ')}
|
||||
- Patterns found: ${(explorationContext.patterns || []).slice(0, 3).join(', ')}
|
||||
- Key findings: ${(explorationContext.key_findings || []).slice(0, 3).join(', ')}
|
||||
- Key files: <top 5 files from exploration>
|
||||
- Patterns found: <top 3 patterns>
|
||||
- Key findings: <top 3 findings>
|
||||
|
||||
TASK:
|
||||
• Build on exploration findings above
|
||||
• Analyze from ${perspective} perspective: ${dimensions.join(', ')}
|
||||
• Identify patterns, anti-patterns, and opportunities
|
||||
• Generate discussion points for user clarification
|
||||
• Assess confidence level for each insight
|
||||
- Build on exploration findings above
|
||||
- Analyze from <perspective> perspective: <dimensions>
|
||||
- Identify patterns, anti-patterns, and opportunities
|
||||
- Generate discussion points for user clarification
|
||||
- Assess confidence level for each insight
|
||||
|
||||
MODE: analysis
|
||||
CONTEXT: @**/* | Topic: ${topic}
|
||||
CONTEXT: @**/* | Topic: <topic>
|
||||
EXPECTED: Structured analysis with: key insights (with confidence), discussion points, open questions, recommendations with rationale
|
||||
CONSTRAINTS: Focus on ${dimensions.join(', ')} | ${perspective} perspective`
|
||||
CONSTRAINTS: Focus on <dimensions> | <perspective> perspective
|
||||
```
|
||||
|
||||
**CLI execution**:
|
||||
|
||||
```
|
||||
Bash({
|
||||
command: `ccw cli -p "${analysisPrompt}" --tool ${cliTool} --mode analysis`,
|
||||
command: "ccw cli -p \"<analysis-prompt>\" --tool <cli-tool> --mode analysis",
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// ⚠️ STOP POINT: Wait for CLI callback
|
||||
// STOP POINT: Wait for CLI callback
|
||||
```
|
||||
|
||||
### Phase 4: Result Aggregation
|
||||
|
||||
```javascript
|
||||
// CLI 结果返回后,构建分析输出
|
||||
const outputPath = `${sessionFolder}/analyses/analysis-${analyzeNum}.json`
|
||||
**Analysis output structure**:
|
||||
|
||||
const analysisResult = {
|
||||
perspective,
|
||||
dimensions,
|
||||
is_direction_fix: isDirectionFix,
|
||||
adjusted_focus: adjustedFocus || null,
|
||||
key_insights: [], // 从 CLI 结果提取
|
||||
key_findings: [], // 具体发现
|
||||
discussion_points: [], // 讨论要点
|
||||
open_questions: [], // 开放问题
|
||||
recommendations: [], // 建议
|
||||
confidence_levels: {}, // 各洞察的置信度
|
||||
evidence: [], // 证据引用
|
||||
_metadata: {
|
||||
cli_tool: cliTool,
|
||||
perspective,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| perspective | Analysis perspective |
|
||||
| dimensions | Analysis dimensions |
|
||||
| is_direction_fix | Boolean for direction fix mode |
|
||||
| adjusted_focus | Focus area if direction fix |
|
||||
| key_insights | Main insights with confidence levels |
|
||||
| key_findings | Specific findings |
|
||||
| discussion_points | Points for user discussion |
|
||||
| open_questions | Unresolved questions |
|
||||
| recommendations | Actionable recommendations |
|
||||
| evidence | Supporting evidence references |
|
||||
|
||||
Write(outputPath, JSON.stringify(analysisResult, null, 2))
|
||||
```
|
||||
**Output path**: `<session-folder>/analyses/analysis-<num>.json`
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
// 更新 shared memory
|
||||
sharedMemory.analyses = sharedMemory.analyses || []
|
||||
sharedMemory.analyses.push({
|
||||
id: `analysis-${analyzeNum}`,
|
||||
perspective,
|
||||
is_direction_fix: isDirectionFix,
|
||||
insight_count: analysisResult.key_insights?.length || 0,
|
||||
finding_count: analysisResult.key_findings?.length || 0,
|
||||
timestamp: new Date().toISOString()
|
||||
})
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
const resultSummary = `${perspective} 视角: ${analysisResult.key_insights?.length || 0} 个洞察, ${analysisResult.discussion_points?.length || 0} 个讨论点`
|
||||
Standard report flow: team_msg log -> SendMessage with `[analyst]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "analyst",
|
||||
to: "coordinator",
|
||||
type: "analysis_ready",
|
||||
summary: `[analyst] ${resultSummary}`,
|
||||
ref: outputPath
|
||||
})
|
||||
**Shared memory update**:
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [analyst] Analysis Results
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Perspective**: ${perspective}${isDirectionFix ? ` (Direction Fix: ${adjustedFocus})` : ''}
|
||||
**CLI Tool**: ${cliTool}
|
||||
|
||||
### Summary
|
||||
${resultSummary}
|
||||
|
||||
### Key Insights
|
||||
${(analysisResult.key_insights || []).slice(0, 5).map(i => `- ${i}`).join('\n')}
|
||||
|
||||
### Discussion Points
|
||||
${(analysisResult.discussion_points || []).slice(0, 3).map(p => `- ${p}`).join('\n')}
|
||||
|
||||
### Open Questions
|
||||
${(analysisResult.open_questions || []).slice(0, 3).map(q => `- ${q}`).join('\n')}
|
||||
|
||||
### Output
|
||||
${outputPath}`,
|
||||
summary: `[analyst] ANALYZE complete: ${resultSummary}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('ANALYZE-') &&
|
||||
t.owner === agentName &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
|
||||
if (nextTasks.length > 0) {
|
||||
// Continue with next task → back to Phase 1
|
||||
}
|
||||
```
|
||||
sharedMemory.analyses.push({
|
||||
id: "analysis-<num>",
|
||||
perspective: <perspective>,
|
||||
is_direction_fix: <boolean>,
|
||||
insight_count: <count>,
|
||||
finding_count: <count>,
|
||||
timestamp: <timestamp>
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No ANALYZE-* tasks available | Idle, wait for coordinator assignment |
|
||||
| CLI tool unavailable | Fallback chain: gemini → codex → claude |
|
||||
| CLI tool unavailable | Fallback chain: gemini -> codex -> claude |
|
||||
| No exploration results found | Analyze with topic keywords only, note limitation |
|
||||
| CLI timeout | Use partial results, report incomplete |
|
||||
| Invalid exploration JSON | Skip context, analyze from scratch |
|
||||
| Command file not found | Fall back to inline execution |
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
# Role: coordinator
|
||||
# Coordinator Role
|
||||
|
||||
分析团队协调者。编排 pipeline:话题澄清 → 管道选择 → 团队创建 → 任务分发 → 讨论循环 → 结果汇报。
|
||||
|
||||
## 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**: Orchestration (Parse requirements -> Create team -> Dispatch tasks -> Monitor progress -> Report results)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
@@ -19,17 +16,42 @@
|
||||
- 通过 TaskCreate 创建任务并分配给 worker 角色
|
||||
- 通过消息总线监控 worker 进度并路由消息
|
||||
- 讨论循环中通过 AskUserQuestion 收集用户反馈
|
||||
- 维护会话状态持久化
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ **直接执行任何业务任务**(代码探索、CLI 分析、综合整合等)
|
||||
- ❌ 直接调用 cli-explore-agent、code-developer 等实现类 subagent
|
||||
- ❌ 直接调用 CLI 分析工具(ccw cli)
|
||||
- ❌ 绕过 worker 角色自行完成应委派的工作
|
||||
- ❌ 在输出中省略 `[coordinator]` 标识
|
||||
- 直接执行任何业务任务(代码探索、CLI 分析、综合整合等)
|
||||
- 直接调用 cli-explore-agent、code-developer 等实现类 subagent
|
||||
- 直接调用 CLI 分析工具(ccw cli)
|
||||
- 绕过 worker 角色自行完成应委派的工作
|
||||
- 在输出中省略 `[coordinator]` 标识
|
||||
|
||||
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Available Commands
|
||||
|
||||
| Command | File | Phase | Description |
|
||||
|---------|------|-------|-------------|
|
||||
| `dispatch` | [commands/dispatch.md](commands/dispatch.md) | Phase 3 | 任务链创建与依赖管理 |
|
||||
| `monitor` | [commands/monitor.md](commands/monitor.md) | Phase 4 | 讨论循环 + 进度监控 |
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `TaskCreate` | Task | coordinator | 创建任务并分配给 worker |
|
||||
| `TaskList` | Task | coordinator | 监控任务状态 |
|
||||
| `TeamCreate` | Team | coordinator | 创建分析团队 |
|
||||
| `AskUserQuestion` | Interaction | coordinator | 收集用户反馈 |
|
||||
| `SendMessage` | Communication | coordinator | 与 worker 通信 |
|
||||
| `Read/Write` | File | coordinator | 会话状态管理 |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
@@ -41,300 +63,290 @@
|
||||
| `error` | coordinator → user | 协调错误 | 阻塞性问题 |
|
||||
| `shutdown` | coordinator → all | 团队关闭 | 清理资源 |
|
||||
|
||||
## Toolbox
|
||||
## Message Bus
|
||||
|
||||
### Available Commands
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
| Command | File | Phase | Description |
|
||||
|---------|------|-------|-------------|
|
||||
| `dispatch` | [commands/dispatch.md](commands/dispatch.md) | Phase 3 | 任务链创建与依赖管理 |
|
||||
| `monitor` | [commands/monitor.md](commands/monitor.md) | Phase 4 | 讨论循环 + 进度监控 |
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: "ultra-analyze",
|
||||
from: "coordinator",
|
||||
to: "<recipient>",
|
||||
type: "<message-type>",
|
||||
summary: "[coordinator] <summary>",
|
||||
ref: "<artifact-path>"
|
||||
})
|
||||
```
|
||||
|
||||
### Subagent Capabilities
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
> Coordinator 不直接使用 subagent(通过 worker 角色间接使用)
|
||||
```
|
||||
Bash("ccw team log --team ultra-analyze --from coordinator --to <recipient> --type <type> --summary \"[coordinator] ...\" --ref <path> --json")
|
||||
```
|
||||
|
||||
### CLI Capabilities
|
||||
---
|
||||
|
||||
> Coordinator 不直接使用 CLI 分析工具
|
||||
## Entry Router
|
||||
|
||||
## Execution
|
||||
When coordinator is invoked, first detect the invocation type:
|
||||
|
||||
### Phase 1: Topic Understanding & Requirement Clarification
|
||||
| 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
|
||||
const args = "$ARGUMENTS"
|
||||
For callback/check/resume: load `commands/monitor.md` and execute the appropriate handler, then STOP.
|
||||
|
||||
// 提取话题描述
|
||||
const taskDescription = args.replace(/--role[=\s]+\w+/, '').replace(/--team[=\s]+[\w-]+/, '').replace(/--mode[=\s]+\w+/, '').trim()
|
||||
---
|
||||
|
||||
// ★ 统一 auto mode 检测
|
||||
const autoYes = /\b(-y|--yes)\b/.test(args)
|
||||
## Phase 0: Session Resume Check
|
||||
|
||||
// 管道模式选择
|
||||
function detectPipelineMode(args, desc) {
|
||||
const modeMatch = args.match(/--mode[=\s]+(quick|standard|deep)/)
|
||||
if (modeMatch) return modeMatch[1]
|
||||
if (/快速|quick|overview|概览/.test(desc)) return 'quick'
|
||||
if (/深入|deep|thorough|详细|全面/.test(desc)) return 'deep'
|
||||
return 'standard'
|
||||
}
|
||||
**Objective**: Detect and resume interrupted sessions before creating new ones.
|
||||
|
||||
let pipelineMode = detectPipelineMode(args, taskDescription)
|
||||
**Workflow**:
|
||||
|
||||
// 维度检测
|
||||
const DIMENSION_KEYWORDS = {
|
||||
architecture: /架构|architecture|design|structure|设计/,
|
||||
implementation: /实现|implement|code|coding|代码/,
|
||||
performance: /性能|performance|optimize|bottleneck|优化/,
|
||||
security: /安全|security|auth|permission|权限/,
|
||||
concept: /概念|concept|theory|principle|原理/,
|
||||
comparison: /比较|compare|vs|difference|区别/,
|
||||
decision: /决策|decision|choice|tradeoff|选择/
|
||||
}
|
||||
1. Scan `.workflow/.team/UAN-*/` 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
|
||||
|
||||
const detectedDimensions = Object.entries(DIMENSION_KEYWORDS)
|
||||
.filter(([_, regex]) => regex.test(taskDescription))
|
||||
.map(([dim]) => dim)
|
||||
**Session Reconciliation**:
|
||||
|
||||
const dimensions = detectedDimensions.length > 0 ? detectedDimensions : ['general']
|
||||
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
|
||||
|
||||
// 交互式澄清(非 auto 模式)
|
||||
if (!autoYes) {
|
||||
// 1. Focus 方向选择
|
||||
const DIMENSION_DIRECTIONS = {
|
||||
architecture: ['System Design', 'Component Interactions', 'Technology Choices', 'Design Patterns', 'Scalability Strategy'],
|
||||
implementation: ['Code Structure', 'Implementation Details', 'Code Patterns', 'Error Handling', 'Algorithm Analysis'],
|
||||
performance: ['Performance Bottlenecks', 'Optimization Opportunities', 'Resource Utilization', 'Caching Strategy'],
|
||||
security: ['Security Vulnerabilities', 'Authentication/Authorization', 'Access Control', 'Data Protection'],
|
||||
concept: ['Conceptual Foundation', 'Core Mechanisms', 'Fundamental Patterns', 'Trade-offs & Reasoning'],
|
||||
comparison: ['Solution Comparison', 'Pros & Cons Analysis', 'Technology Evaluation'],
|
||||
decision: ['Decision Criteria', 'Trade-off Analysis', 'Risk Assessment', 'Impact Analysis'],
|
||||
general: ['Overview', 'Key Patterns', 'Potential Issues', 'Improvement Opportunities']
|
||||
---
|
||||
|
||||
## Phase 1: Topic Understanding & Requirement Clarification
|
||||
|
||||
**Objective**: Parse user input and gather execution parameters.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. **Parse arguments** for explicit settings: mode, scope, focus areas
|
||||
|
||||
2. **Extract topic description**: Remove `--role`, `--team`, `--mode` flags from arguments
|
||||
|
||||
3. **Pipeline mode selection**:
|
||||
|
||||
| Condition | Mode |
|
||||
|-----------|------|
|
||||
| `--mode=quick` explicit or topic contains "quick/overview/fast" | Quick |
|
||||
| `--mode=deep` explicit or topic contains "deep/thorough/detailed/comprehensive" | Deep |
|
||||
| Default (no match) | Standard |
|
||||
|
||||
4. **Dimension detection** (from topic keywords):
|
||||
|
||||
| Dimension | Keywords |
|
||||
|-----------|----------|
|
||||
| architecture | 架构, architecture, design, structure, 设计 |
|
||||
| implementation | 实现, implement, code, 代码 |
|
||||
| performance | 性能, performance, optimize, 优化 |
|
||||
| security | 安全, security, auth, 权限 |
|
||||
| concept | 概念, concept, theory, 原理 |
|
||||
| comparison | 比较, compare, vs, 区别 |
|
||||
| decision | 决策, decision, choice, 选择 |
|
||||
|
||||
5. **Interactive clarification** (non-auto mode only):
|
||||
|
||||
| Question | Purpose |
|
||||
|----------|---------|
|
||||
| Analysis Focus | Multi-select focus directions |
|
||||
| Analysis Perspectives | Select technical/architectural/business/domain views |
|
||||
| Analysis Depth | Confirm Quick/Standard/Deep |
|
||||
|
||||
**Success**: All parameters captured, mode finalized.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Create Team + Initialize Session
|
||||
|
||||
**Objective**: Initialize team, session file, and wisdom directory.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. **Generate session ID**: `UAN-{slug}-{YYYY-MM-DD}`
|
||||
2. **Create session folder structure**:
|
||||
|
||||
```
|
||||
.workflow/.team/UAN-{slug}-{date}/
|
||||
+-- shared-memory.json
|
||||
+-- discussion.md
|
||||
+-- explorations/
|
||||
+-- analyses/
|
||||
+-- discussions/
|
||||
+-- wisdom/
|
||||
+-- learnings.md
|
||||
+-- decisions.md
|
||||
+-- conventions.md
|
||||
+-- issues.md
|
||||
```
|
||||
|
||||
3. **Initialize shared-memory.json**:
|
||||
|
||||
```json
|
||||
{
|
||||
"explorations": [],
|
||||
"analyses": [],
|
||||
"discussions": [],
|
||||
"synthesis": null,
|
||||
"decision_trail": [],
|
||||
"current_understanding": {
|
||||
"established": [],
|
||||
"clarified": [],
|
||||
"key_insights": []
|
||||
}
|
||||
|
||||
const directionOptions = dimensions.flatMap(d => (DIMENSION_DIRECTIONS[d] || []).slice(0, 3))
|
||||
.map(d => ({ label: d, description: `Focus on ${d}` }))
|
||||
|
||||
const focusResult = AskUserQuestion({
|
||||
questions: [{
|
||||
question: "选择分析方向(可多选)",
|
||||
header: "Analysis Focus",
|
||||
multiSelect: true,
|
||||
options: directionOptions
|
||||
}]
|
||||
})
|
||||
|
||||
// 2. 视角选择(Standard/Deep 模式)
|
||||
let selectedPerspectives = ['technical']
|
||||
if (pipelineMode !== 'quick') {
|
||||
const perspectiveResult = AskUserQuestion({
|
||||
questions: [{
|
||||
question: "选择分析视角(可多选,最多4个)",
|
||||
header: "Analysis Perspectives",
|
||||
multiSelect: true,
|
||||
options: [
|
||||
{ label: "Technical", description: "实现、代码模式、技术可行性" },
|
||||
{ label: "Architectural", description: "系统设计、可扩展性、组件交互" },
|
||||
{ label: "Business", description: "价值、ROI、利益相关者影响" },
|
||||
{ label: "Domain Expert", description: "领域特定模式、最佳实践、标准" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
// Parse selected perspectives
|
||||
}
|
||||
|
||||
// 3. 深度选择
|
||||
const depthResult = AskUserQuestion({
|
||||
questions: [{
|
||||
question: "选择分析深度",
|
||||
header: "Analysis Depth",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "Quick Overview", description: "快速概览 (10-15min)" },
|
||||
{ label: "Standard Analysis", description: "标准分析 (30-60min)" },
|
||||
{ label: "Deep Dive", description: "深度分析 (1-2hr)" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
const depthMap = { 'Quick Overview': 'quick', 'Standard Analysis': 'standard', 'Deep Dive': 'deep' }
|
||||
pipelineMode = depthMap[depthResult["Analysis Depth"]] || pipelineMode
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 2: Create Team + Initialize Session
|
||||
4. **Initialize discussion.md** with session metadata
|
||||
5. **Call TeamCreate** with team name "ultra-analyze"
|
||||
6. **Spawn worker roles** (see SKILL.md Coordinator Spawn Template)
|
||||
|
||||
```javascript
|
||||
const teamName = "ultra-analyze"
|
||||
const sessionSlug = taskDescription.slice(0, 30).replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '-')
|
||||
const sessionDate = new Date().toISOString().slice(0, 10)
|
||||
const sessionFolder = `.workflow/.team/UAN-${sessionSlug}-${sessionDate}`
|
||||
Bash(`mkdir -p "${sessionFolder}/explorations" "${sessionFolder}/analyses" "${sessionFolder}/discussions"`)
|
||||
**Success**: Team created, session file written, wisdom initialized, workers ready.
|
||||
|
||||
// 初始化 shared memory
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify({
|
||||
explorations: [],
|
||||
analyses: [],
|
||||
discussions: [],
|
||||
synthesis: null,
|
||||
decision_trail: [],
|
||||
current_understanding: {
|
||||
established: [],
|
||||
clarified: [],
|
||||
key_insights: []
|
||||
}
|
||||
}, null, 2))
|
||||
---
|
||||
|
||||
// 初始化 discussion.md
|
||||
Write(`${sessionFolder}/discussion.md`, `# Analysis Discussion
|
||||
## Phase 3: Create Task Chain
|
||||
|
||||
## Session Metadata
|
||||
- **ID**: UAN-${sessionSlug}-${sessionDate}
|
||||
- **Topic**: ${taskDescription}
|
||||
- **Started**: ${new Date().toISOString()}
|
||||
- **Dimensions**: ${dimensions.join(', ')}
|
||||
- **Pipeline**: ${pipelineMode}
|
||||
**Objective**: Dispatch tasks based on mode with proper dependencies.
|
||||
|
||||
## User Context
|
||||
- **Focus Areas**: ${dimensions.join(', ')}
|
||||
- **Analysis Depth**: ${pipelineMode}
|
||||
Delegate to `commands/dispatch.md` which creates the full task chain:
|
||||
|
||||
## Initial Understanding
|
||||
- **Dimensions**: ${dimensions.join(', ')}
|
||||
- **Scope**: ${taskDescription}
|
||||
**Quick Mode** (3 beats, serial):
|
||||
|
||||
## Discussion Timeline
|
||||
|
||||
`)
|
||||
|
||||
TeamCreate({ team_name: teamName })
|
||||
|
||||
// ⚠️ 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.
|
||||
// Quick mode: 1 explorer + 1 analyst (single agents)
|
||||
// Standard/Deep mode: N explorers + N analysts (parallel agents with distinct names)
|
||||
// explorer-1, explorer-2... / analyst-1, analyst-2... for true parallel execution
|
||||
// Discussant and Synthesizer are always single instances
|
||||
```
|
||||
|
||||
### Phase 3: Create Task Chain
|
||||
|
||||
根据 pipelineMode 创建不同的任务链:
|
||||
|
||||
```javascript
|
||||
// Read commands/dispatch.md for full implementation
|
||||
Read("commands/dispatch.md")
|
||||
```
|
||||
|
||||
**Quick Mode**:
|
||||
```
|
||||
EXPLORE-001 → ANALYZE-001 → SYNTH-001
|
||||
```
|
||||
|
||||
**Standard Mode**:
|
||||
**Standard Mode** (4 beats, parallel windows):
|
||||
|
||||
```
|
||||
[EXPLORE-001..N](parallel) → [ANALYZE-001..N](parallel) → DISCUSS-001 → SYNTH-001
|
||||
```
|
||||
|
||||
**Deep Mode**:
|
||||
**Deep Mode** (4+ beats, with discussion loop):
|
||||
|
||||
```
|
||||
[EXPLORE-001..N](parallel) → [ANALYZE-001..N](parallel) → DISCUSS-001 → [ANALYZE-fix] → DISCUSS-002 → ... → SYNTH-001
|
||||
[EXPLORE-001..N] → [ANALYZE-001..N] → DISCUSS-001 → [ANALYZE-fix] → DISCUSS-002 → ... → SYNTH-001
|
||||
```
|
||||
|
||||
### Phase 4: Discussion Loop + Coordination
|
||||
**Task chain rules**:
|
||||
|
||||
> **设计原则(Stop-Wait)**: 模型执行没有时间概念,禁止任何形式的轮询等待。
|
||||
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
|
||||
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用,Worker 返回 = 阶段完成信号
|
||||
>
|
||||
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
|
||||
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
|
||||
1. Reads SKILL.md Task Metadata Registry for task definitions
|
||||
2. Creates tasks via TaskCreate with correct blockedBy
|
||||
3. Assigns owner based on role mapping
|
||||
4. Includes `Session: <session-folder>` in every task description
|
||||
|
||||
```javascript
|
||||
// Read commands/monitor.md for full implementation
|
||||
Read("commands/monitor.md")
|
||||
```
|
||||
---
|
||||
|
||||
## Phase 4: Discussion Loop + Coordination
|
||||
|
||||
**Objective**: Spawn workers in background, monitor callbacks, drive discussion loop.
|
||||
|
||||
**Design**: Spawn-and-Stop + Callback pattern.
|
||||
|
||||
- Spawn workers with `Task(run_in_background: true)` -> immediately return
|
||||
- Worker completes -> SendMessage callback -> auto-advance
|
||||
- User can use "check" / "resume" to manually advance
|
||||
- Coordinator does one operation per invocation, then STOPS
|
||||
|
||||
**Workflow** (see `commands/monitor.md` for details):
|
||||
|
||||
1. Load `commands/monitor.md`
|
||||
2. Find tasks with: status=pending, blockedBy all resolved, owner assigned
|
||||
3. For each ready task -> spawn worker (see SKILL.md Spawn Template)
|
||||
4. Output status summary
|
||||
5. STOP
|
||||
|
||||
**Callback handlers**:
|
||||
|
||||
| Received Message | Action |
|
||||
|-----------------|--------|
|
||||
| `exploration_ready` | 标记 EXPLORE complete → 解锁 ANALYZE |
|
||||
| `analysis_ready` | 标记 ANALYZE complete → 解锁 DISCUSS 或 SYNTH |
|
||||
| `discussion_processed` | 标记 DISCUSS complete → AskUser → 决定下一步 |
|
||||
| `synthesis_ready` | 标记 SYNTH complete → 进入 Phase 5 |
|
||||
| Worker: `error` | 评估严重性 → 重试或上报用户 |
|
||||
| `exploration_ready` | Mark EXPLORE complete -> unblock ANALYZE |
|
||||
| `analysis_ready` | Mark ANALYZE complete -> unblock DISCUSS or SYNTH |
|
||||
| `discussion_processed` | Mark DISCUSS complete -> AskUser -> decide next |
|
||||
| `synthesis_ready` | Mark SYNTH complete -> Phase 5 |
|
||||
| Worker: `error` | Assess severity -> retry or report to user |
|
||||
|
||||
**讨论循环逻辑** (Standard/Deep mode):
|
||||
```javascript
|
||||
let discussionRound = 0
|
||||
const MAX_ROUNDS = pipelineMode === 'deep' ? 5 : 1
|
||||
**Discussion loop logic** (Standard/Deep mode):
|
||||
|
||||
while (discussionRound < MAX_ROUNDS) {
|
||||
// 等待 DISCUSS-N 完成
|
||||
// AskUserQuestion: 同意继续 / 调整方向 / 分析完成 / 有具体问题
|
||||
// 根据用户选择:
|
||||
// 同意继续 → 创建 DISCUSS-(N+1)
|
||||
// 调整方向 → 创建 ANALYZE-fix + DISCUSS-(N+1)
|
||||
// 分析完成 → 退出循环,创建 SYNTH-001
|
||||
// 有具体问题 → 创建 DISCUSS-(N+1) with questions
|
||||
discussionRound++
|
||||
}
|
||||
| Round | Action |
|
||||
|-------|--------|
|
||||
| After DISCUSS-N completes | AskUserQuestion: continue / adjust direction / complete / specific questions |
|
||||
| User: "继续深入" | Create DISCUSS-(N+1) |
|
||||
| User: "调整方向" | Create ANALYZE-fix + DISCUSS-(N+1) |
|
||||
| User: "分析完成" | Exit loop, create SYNTH-001 |
|
||||
| Round > MAX_ROUNDS (5) | Force synthesis, offer continuation |
|
||||
|
||||
**Pipeline advancement** driven by three wake sources:
|
||||
|
||||
- Worker callback (automatic) -> Entry Router -> handleCallback
|
||||
- User "check" -> handleCheck (status only)
|
||||
- User "resume" -> handleResume (advance)
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Report + Persist
|
||||
|
||||
**Objective**: Completion report and follow-up options.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. Load session state -> count completed tasks, duration
|
||||
2. List deliverables with output paths
|
||||
3. Update session status -> "completed"
|
||||
4. Output final report
|
||||
5. Offer next steps to user
|
||||
|
||||
**Report structure**:
|
||||
|
||||
```
|
||||
## [coordinator] Analysis Complete
|
||||
|
||||
**Mode**: <mode>
|
||||
**Topic**: <topic>
|
||||
**Explorations**: <count>
|
||||
**Analyses**: <count>
|
||||
**Discussion Rounds**: <count>
|
||||
**Decisions Made**: <count>
|
||||
|
||||
📄 Discussion: <session-folder>/discussion.md
|
||||
📊 Conclusions: <session-folder>/conclusions.json
|
||||
```
|
||||
|
||||
### Phase 5: Report + Persist
|
||||
**Next step options**:
|
||||
|
||||
```javascript
|
||||
// 读取 shared memory 汇总结果
|
||||
const memory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| 创建Issue | 基于结论创建 Issue |
|
||||
| 生成任务 | 启动 workflow-lite-plan 规划实施 |
|
||||
| 导出报告 | 生成独立分析报告 |
|
||||
| 关闭团队 | 关闭所有 teammate 并清理 |
|
||||
|
||||
const report = {
|
||||
mode: pipelineMode,
|
||||
topic: taskDescription,
|
||||
explorations_count: memory.explorations?.length || 0,
|
||||
analyses_count: memory.analyses?.length || 0,
|
||||
discussion_rounds: memory.discussions?.length || 0,
|
||||
decisions_made: memory.decision_trail?.length || 0,
|
||||
has_synthesis: !!memory.synthesis
|
||||
}
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator",
|
||||
to: "user", type: "pipeline_selected",
|
||||
summary: `[coordinator] 分析完成: ${report.explorations_count}次探索, ${report.analyses_count}次分析, ${report.discussion_rounds}轮讨论`
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
content: `## [coordinator] Analysis Complete\n\n${JSON.stringify(report, null, 2)}\n\n📄 Discussion: ${sessionFolder}/discussion.md\n📊 Conclusions: ${sessionFolder}/conclusions.json`,
|
||||
summary: `[coordinator] Analysis complete: ${pipelineMode} mode`
|
||||
})
|
||||
|
||||
// 询问下一步(auto 模式跳过,默认关闭团队)
|
||||
if (!autoYes) {
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "分析流程已完成。下一步:",
|
||||
header: "Next",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "创建Issue", description: "基于结论创建 Issue" },
|
||||
{ label: "生成任务", description: "启动 workflow-lite-plan 规划实施" },
|
||||
{ label: "导出报告", description: "生成独立分析报告" },
|
||||
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| Teammate unresponsive | Send follow-up, 2x → respawn |
|
||||
| Teammate unresponsive | Send follow-up, 2x -> respawn |
|
||||
| Explorer finds nothing | Continue with limited context, note limitation |
|
||||
| Discussion loop stuck >5 rounds | Force synthesis, offer continuation |
|
||||
| CLI unavailable | Fallback chain: gemini → codex → manual |
|
||||
| CLI unavailable | Fallback chain: gemini -> codex -> manual |
|
||||
| User timeout in discussion | Save state, show resume command |
|
||||
| Max rounds reached | Force synthesis, offer continuation option |
|
||||
| Session folder conflict | Append timestamp suffix |
|
||||
| Task timeout | Log, mark failed, ask user to retry or skip |
|
||||
| Worker crash | Respawn worker, reassign task |
|
||||
| Dependency cycle | Detect, report to user, halt |
|
||||
|
||||
@@ -1,40 +1,35 @@
|
||||
# Role: discussant
|
||||
# Discussant Role
|
||||
|
||||
讨论处理者。根据 coordinator 传递的用户反馈,执行方向调整、深入探索或补充分析,更新讨论时间线。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `discussant`
|
||||
- **Name**: `discussant` | **Tag**: `[discussant]`
|
||||
- **Task Prefix**: `DISCUSS-*`
|
||||
- **Responsibility**: Analysis + Exploration(讨论处理)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[discussant]`
|
||||
- **Responsibility**: Analysis + Exploration (讨论处理)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `DISCUSS-*` 前缀的任务
|
||||
- 所有输出必须带 `[discussant]` 标识
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- 基于用户反馈和已有分析结果执行深入探索
|
||||
- 将讨论结果写入 shared-memory.json 的 `discussions` 字段
|
||||
- 更新 discussion.md 的讨论时间线
|
||||
- Only process `DISCUSS-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[discussant]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within discussion processing responsibility scope
|
||||
- Execute deep exploration based on user feedback and existing analysis
|
||||
- Write discussion results to shared-memory.json `discussions` field
|
||||
- Update discussion.md discussion timeline
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 直接与用户交互(AskUserQuestion 由 coordinator 驱动)
|
||||
- ❌ 生成最终结论(属于 synthesizer)
|
||||
- ❌ 为其他角色创建任务
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 修改源代码
|
||||
- Interact directly with user (AskUserQuestion is coordinator-driven)
|
||||
- Generate final conclusions (belongs to synthesizer)
|
||||
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
|
||||
- Communicate directly with other worker roles
|
||||
- Modify source code
|
||||
- Omit `[discussant]` identifier in any output
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `discussion_processed` | discussant → coordinator | 讨论处理完成 | 包含更新的理解和新发现 |
|
||||
| `error` | discussant → coordinator | 处理失败 | 阻塞性错误 |
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -44,223 +39,179 @@
|
||||
|---------|------|-------|-------------|
|
||||
| `deepen` | [commands/deepen.md](commands/deepen.md) | Phase 3 | 深入探索与补充分析 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
| Agent Type | Used By | Purpose |
|
||||
|------------|---------|---------|
|
||||
| `cli-explore-agent` | deepen.md | 针对性代码库探索 |
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `Task` | Subagent | deepen.md | Spawn cli-explore-agent for targeted exploration |
|
||||
| `Bash` | CLI | deepen.md | Execute ccw cli for deep analysis |
|
||||
| `Read` | File | discussant | Read analysis results and session context |
|
||||
| `Write` | File | discussant | Write discussion results |
|
||||
| `Glob` | File | discussant | Find analysis/exploration files |
|
||||
|
||||
### CLI Capabilities
|
||||
### CLI Tools
|
||||
|
||||
| CLI Tool | Mode | Used By | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `gemini` | analysis | deepen.md | 深入分析 |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `discussion_processed` | discussant → coordinator | 讨论处理完成 | 包含更新的理解和新发现 |
|
||||
| `error` | discussant → coordinator | 处理失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: "ultra-analyze",
|
||||
from: "discussant",
|
||||
to: "coordinator",
|
||||
type: "discussion_processed",
|
||||
summary: "[discussant] DISCUSS complete: <summary>",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team ultra-analyze --from discussant --to coordinator --type discussion_processed --summary \"[discussant] ...\" --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('DISCUSS-') &&
|
||||
t.owner === 'discussant' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return // idle
|
||||
Standard task discovery flow: TaskList -> filter by prefix `DISCUSS-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Falls back to `discussant` for single-instance role.
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
```javascript
|
||||
// 从任务描述中提取上下文
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim()
|
||||
const topic = task.description.match(/topic:\s*(.+)/)?.[1]?.trim()
|
||||
const round = parseInt(task.description.match(/round:\s*(\d+)/)?.[1] || '1')
|
||||
const discussType = task.description.match(/type:\s*(.+)/)?.[1]?.trim() || 'initial'
|
||||
const userFeedback = task.description.match(/user_feedback:\s*(.+)/)?.[1]?.trim() || ''
|
||||
**Loading steps**:
|
||||
|
||||
// 读取 shared memory
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
1. Extract session path from task description
|
||||
2. Extract topic, round number, discussion type, user feedback
|
||||
3. Read shared-memory.json for existing context
|
||||
4. Read all analysis results
|
||||
5. Read all exploration results
|
||||
6. Aggregate current findings, insights, questions
|
||||
|
||||
// 读取已有分析结果
|
||||
const analysisFiles = Glob({ pattern: `${sessionFolder}/analyses/*.json` })
|
||||
const allAnalyses = analysisFiles.map(f => {
|
||||
try { return JSON.parse(Read(f)) } catch { return null }
|
||||
}).filter(Boolean)
|
||||
**Context extraction**:
|
||||
|
||||
// 读取已有探索结果
|
||||
const explorationFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
|
||||
const allExplorations = explorationFiles.map(f => {
|
||||
try { return JSON.parse(Read(f)) } catch { return null }
|
||||
}).filter(Boolean)
|
||||
| Field | Source | Pattern |
|
||||
|-------|--------|---------|
|
||||
| sessionFolder | task description | `session:\s*(.+)` |
|
||||
| topic | task description | `topic:\s*(.+)` |
|
||||
| round | task description | `round:\s*(\d+)` or default 1 |
|
||||
| discussType | task description | `type:\s*(.+)` or default "initial" |
|
||||
| userFeedback | task description | `user_feedback:\s*(.+)` or empty |
|
||||
|
||||
// 聚合当前理解
|
||||
const currentFindings = allAnalyses.flatMap(a => a.key_findings || [])
|
||||
const currentInsights = allAnalyses.flatMap(a => a.key_insights || [])
|
||||
const openQuestions = allAnalyses.flatMap(a => a.open_questions || [])
|
||||
const discussionPoints = allAnalyses.flatMap(a => a.discussion_points || [])
|
||||
```
|
||||
**Discussion types**:
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| initial | 首轮讨论:汇总所有分析结果,生成讨论摘要 |
|
||||
| deepen | 继续深入:在当前方向上进一步探索 |
|
||||
| direction-adjusted | 方向调整:基于新方向重新组织发现 |
|
||||
| specific-questions | 具体问题:针对用户问题进行分析 |
|
||||
|
||||
### Phase 3: Discussion Processing
|
||||
|
||||
```javascript
|
||||
// Read commands/deepen.md for full implementation
|
||||
Read("commands/deepen.md")
|
||||
```
|
||||
Delegate to `commands/deepen.md` if available, otherwise execute inline.
|
||||
|
||||
**根据 discussType 选择处理策略**:
|
||||
**Processing by discussion type**:
|
||||
|
||||
```javascript
|
||||
const discussNum = task.subject.match(/DISCUSS-(\d+)/)?.[1] || '001'
|
||||
const outputPath = `${sessionFolder}/discussions/discussion-round-${discussNum}.json`
|
||||
| Type | Strategy |
|
||||
|------|----------|
|
||||
| initial | Aggregate all analysis results, generate discussion summary with confirmed/corrected/new insights |
|
||||
| deepen | Focus on current direction, explore deeper with cli-explore-agent |
|
||||
| direction-adjusted | Re-organize findings around new focus, identify new patterns |
|
||||
| specific-questions | Targeted analysis addressing user's specific questions |
|
||||
|
||||
switch (discussType) {
|
||||
case 'initial':
|
||||
// 首轮讨论:汇总所有分析结果,生成讨论摘要
|
||||
processInitialDiscussion()
|
||||
break
|
||||
**Round content structure**:
|
||||
|
||||
case 'deepen':
|
||||
// 继续深入:在当前方向上进一步探索
|
||||
processDeepenDiscussion()
|
||||
break
|
||||
|
||||
case 'direction-adjusted':
|
||||
// 方向调整:基于新方向重新组织发现
|
||||
processDirectionAdjusted()
|
||||
break
|
||||
|
||||
case 'specific-questions':
|
||||
// 具体问题:针对用户问题进行分析
|
||||
processSpecificQuestions()
|
||||
break
|
||||
}
|
||||
```
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| round | Discussion round number |
|
||||
| type | Discussion type |
|
||||
| user_feedback | User input (if any) |
|
||||
| updated_understanding | confirmed, corrected, new_insights arrays |
|
||||
| new_findings | New discoveries |
|
||||
| new_questions | Open questions |
|
||||
| timestamp | ISO timestamp |
|
||||
|
||||
### Phase 4: Update Discussion Timeline
|
||||
|
||||
```javascript
|
||||
// 构建讨论轮次内容
|
||||
const roundContent = {
|
||||
round,
|
||||
type: discussType,
|
||||
user_feedback: userFeedback,
|
||||
updated_understanding: {
|
||||
confirmed: [], // 确认的假设
|
||||
corrected: [], // 纠正的假设
|
||||
new_insights: [] // 新发现
|
||||
},
|
||||
new_findings: [],
|
||||
new_questions: [],
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
**Output path**: `<session-folder>/discussions/discussion-round-<num>.json`
|
||||
|
||||
Write(outputPath, JSON.stringify(roundContent, null, 2))
|
||||
**discussion.md update template**:
|
||||
|
||||
// 更新 discussion.md
|
||||
const discussionMdContent = `
|
||||
### Round ${round + 1} - Discussion (${new Date().toISOString()})
|
||||
```markdown
|
||||
### Round <N> - Discussion (<timestamp>)
|
||||
|
||||
#### Type
|
||||
${discussType}
|
||||
<discussType>
|
||||
|
||||
#### User Input
|
||||
${userFeedback || '(Initial discussion round)'}
|
||||
<userFeedback or "(Initial discussion round)">
|
||||
|
||||
#### Updated Understanding
|
||||
${roundContent.updated_understanding.confirmed.length > 0
|
||||
? `**Confirmed**: ${roundContent.updated_understanding.confirmed.map(c => `\n- ✅ ${c}`).join('')}` : ''}
|
||||
${roundContent.updated_understanding.corrected.length > 0
|
||||
? `**Corrected**: ${roundContent.updated_understanding.corrected.map(c => `\n- 🔄 ${c}`).join('')}` : ''}
|
||||
${roundContent.updated_understanding.new_insights.length > 0
|
||||
? `**New Insights**: ${roundContent.updated_understanding.new_insights.map(i => `\n- 💡 ${i}`).join('')}` : ''}
|
||||
**Confirmed**: <list of confirmed assumptions>
|
||||
**Corrected**: <list of corrected assumptions>
|
||||
**New Insights**: <list of new insights>
|
||||
|
||||
#### New Findings
|
||||
${(roundContent.new_findings || []).map(f => `- ${f}`).join('\n') || '(None)'}
|
||||
<list of new findings or "(None)">
|
||||
|
||||
#### Open Questions
|
||||
${(roundContent.new_questions || []).map(q => `- ${q}`).join('\n') || '(None)'}
|
||||
`
|
||||
|
||||
const currentDiscussion = Read(`${sessionFolder}/discussion.md`)
|
||||
Write(`${sessionFolder}/discussion.md`, currentDiscussion + discussionMdContent)
|
||||
<list of open questions or "(None)">
|
||||
```
|
||||
|
||||
**Update steps**:
|
||||
|
||||
1. Write round content JSON to discussions folder
|
||||
2. Read current discussion.md
|
||||
3. Append new round section
|
||||
4. Write updated discussion.md
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
// 更新 shared memory
|
||||
sharedMemory.discussions = sharedMemory.discussions || []
|
||||
sharedMemory.discussions.push({
|
||||
id: `discussion-round-${discussNum}`,
|
||||
round,
|
||||
type: discussType,
|
||||
new_insight_count: roundContent.updated_understanding.new_insights?.length || 0,
|
||||
corrected_count: roundContent.updated_understanding.corrected?.length || 0,
|
||||
timestamp: new Date().toISOString()
|
||||
})
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
// 更新 current_understanding
|
||||
sharedMemory.current_understanding = sharedMemory.current_understanding || { established: [], clarified: [], key_insights: [] }
|
||||
sharedMemory.current_understanding.established.push(...(roundContent.updated_understanding.confirmed || []))
|
||||
sharedMemory.current_understanding.clarified.push(...(roundContent.updated_understanding.corrected || []))
|
||||
sharedMemory.current_understanding.key_insights.push(...(roundContent.updated_understanding.new_insights || []))
|
||||
Standard report flow: team_msg log -> SendMessage with `[discussant]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
**Shared memory update**:
|
||||
|
||||
const resultSummary = `Round ${round}: ${roundContent.updated_understanding.new_insights?.length || 0} 新洞察, ${roundContent.updated_understanding.corrected?.length || 0} 纠正`
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "discussant",
|
||||
to: "coordinator",
|
||||
type: "discussion_processed",
|
||||
summary: `[discussant] ${resultSummary}`,
|
||||
ref: outputPath
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [discussant] Discussion Round ${round} Results
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Type**: ${discussType}
|
||||
|
||||
### Summary
|
||||
${resultSummary}
|
||||
|
||||
### Key Updates
|
||||
${roundContent.updated_understanding.new_insights?.slice(0, 3).map(i => `- 💡 ${i}`).join('\n') || '(No new insights)'}
|
||||
${roundContent.updated_understanding.corrected?.slice(0, 3).map(c => `- 🔄 ${c}`).join('\n') || ''}
|
||||
|
||||
### Output
|
||||
${outputPath}`,
|
||||
summary: `[discussant] DISCUSS complete: ${resultSummary}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('DISCUSS-') &&
|
||||
t.owner === 'discussant' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
|
||||
if (nextTasks.length > 0) {
|
||||
// Continue with next task → back to Phase 1
|
||||
}
|
||||
```
|
||||
sharedMemory.discussions.push({
|
||||
id: "discussion-round-<num>",
|
||||
round: <round>,
|
||||
type: <discussType>,
|
||||
new_insight_count: <count>,
|
||||
corrected_count: <count>,
|
||||
timestamp: <timestamp>
|
||||
})
|
||||
|
||||
// Update current_understanding
|
||||
sharedMemory.current_understanding.established += confirmed
|
||||
sharedMemory.current_understanding.clarified += corrected
|
||||
sharedMemory.current_understanding.key_insights += new_insights
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -271,3 +222,4 @@ if (nextTasks.length > 0) {
|
||||
| CLI tool unavailable | Use existing analysis results for discussion |
|
||||
| User feedback unclear | Process as 'deepen' type, note ambiguity |
|
||||
| Session folder missing | Error to coordinator |
|
||||
| Command file not found | Fall back to inline execution |
|
||||
|
||||
@@ -1,39 +1,33 @@
|
||||
# Role: explorer
|
||||
# Explorer Role
|
||||
|
||||
代码库探索者。通过 cli-explore-agent 多角度并行探索代码库,收集结构化上下文供后续分析使用。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `explorer`
|
||||
- **Name**: `explorer` | **Tag**: `[explorer]`
|
||||
- **Task Prefix**: `EXPLORE-*`
|
||||
- **Responsibility**: Orchestration(代码库探索编排)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[explorer]`
|
||||
- **Responsibility**: Orchestration (代码库探索编排)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `EXPLORE-*` 前缀的任务
|
||||
- 所有输出必须带 `[explorer]` 标识
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- 严格在代码库探索职责范围内工作
|
||||
- 将探索结果写入 shared-memory.json 的 `explorations` 字段
|
||||
- Only process `EXPLORE-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[explorer]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within codebase exploration responsibility scope
|
||||
- Write exploration results to shared-memory.json `explorations` field
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 执行深度分析(属于 analyst)
|
||||
- ❌ 处理用户反馈(属于 discussant)
|
||||
- ❌ 生成结论或建议(属于 synthesizer)
|
||||
- ❌ 为其他角色创建任务
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- Execute deep analysis (belongs to analyst)
|
||||
- Handle user feedback (belongs to discussant)
|
||||
- Generate conclusions or recommendations (belongs to synthesizer)
|
||||
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
|
||||
- Communicate directly with other worker roles
|
||||
- Omit `[explorer]` identifier in any output
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `exploration_ready` | explorer → coordinator | 探索完成 | 包含发现的文件、模式、关键发现 |
|
||||
| `error` | explorer → coordinator | 探索失败 | 阻塞性错误 |
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -43,90 +37,117 @@
|
||||
|---------|------|-------|-------------|
|
||||
| `explore` | [commands/explore.md](commands/explore.md) | Phase 3 | cli-explore-agent 并行探索 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
| Agent Type | Used By | Purpose |
|
||||
|------------|---------|---------|
|
||||
| `cli-explore-agent` | explore.md | 多角度代码库探索 |
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `Task` | Subagent | explore.md | Spawn cli-explore-agent for codebase exploration |
|
||||
| `Read` | File | explorer | Read session files and exploration context |
|
||||
| `Write` | File | explorer | Write exploration results |
|
||||
| `Glob` | File | explorer | Find relevant files |
|
||||
| `mcp__ace-tool__search_context` | MCP | explorer | ACE semantic search fallback |
|
||||
| `Grep` | Search | explorer | Pattern search fallback |
|
||||
|
||||
### CLI Capabilities
|
||||
---
|
||||
|
||||
> Explorer 不直接使用 CLI 分析工具(通过 cli-explore-agent 间接使用)
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `exploration_ready` | explorer → coordinator | 探索完成 | 包含发现的文件、模式、关键发现 |
|
||||
| `error` | explorer → coordinator | 探索失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: "ultra-analyze",
|
||||
from: "explorer",
|
||||
to: "coordinator",
|
||||
type: "exploration_ready",
|
||||
summary: "[explorer] EXPLORE complete: <summary>",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team ultra-analyze --from explorer --to coordinator --type exploration_ready --summary \"[explorer] ...\" --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
// Parse agent name from --agent-name arg (for parallel instances) or default to 'explorer'
|
||||
const agentNameMatch = args.match(/--agent-name[=\s]+([\w-]+)/)
|
||||
const agentName = agentNameMatch ? agentNameMatch[1] : 'explorer'
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('EXPLORE-') &&
|
||||
t.owner === agentName &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
Standard task discovery flow: TaskList -> filter by prefix `EXPLORE-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
if (myTasks.length === 0) return // idle
|
||||
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
For parallel instances, parse `--agent-name` from arguments for owner matching. Falls back to `explorer` for single-instance roles.
|
||||
|
||||
### Phase 2: Context & Scope Assessment
|
||||
|
||||
```javascript
|
||||
// 从任务描述中提取上下文
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim()
|
||||
const topic = task.description.match(/topic:\s*(.+)/)?.[1]?.trim()
|
||||
const perspective = task.description.match(/perspective:\s*(.+)/)?.[1]?.trim() || 'general'
|
||||
const dimensions = (task.description.match(/dimensions:\s*(.+)/)?.[1]?.trim() || 'general').split(', ')
|
||||
**Loading steps**:
|
||||
|
||||
// 读取 shared memory
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
1. Extract session path from task description
|
||||
2. Extract topic, perspective, dimensions from task metadata
|
||||
3. Read shared-memory.json for existing context
|
||||
4. Determine exploration number from task subject (EXPLORE-N)
|
||||
|
||||
// 评估探索范围
|
||||
const exploreNum = task.subject.match(/EXPLORE-(\d+)/)?.[1] || '001'
|
||||
```
|
||||
**Context extraction**:
|
||||
|
||||
| Field | Source | Pattern |
|
||||
|-------|--------|---------|
|
||||
| sessionFolder | task description | `session:\s*(.+)` |
|
||||
| topic | task description | `topic:\s*(.+)` |
|
||||
| perspective | task description | `perspective:\s*(.+)` or default "general" |
|
||||
| dimensions | task description | `dimensions:\s*(.+)` or default "general" |
|
||||
|
||||
### Phase 3: Codebase Exploration
|
||||
|
||||
```javascript
|
||||
// Read commands/explore.md for full cli-explore-agent implementation
|
||||
Read("commands/explore.md")
|
||||
Delegate to `commands/explore.md` if available, otherwise execute inline.
|
||||
|
||||
**Exploration strategy**:
|
||||
|
||||
| Condition | Strategy |
|
||||
|-----------|----------|
|
||||
| Single perspective | Direct cli-explore-agent spawn |
|
||||
| Multi-perspective | Per-perspective exploration with focused prompts |
|
||||
| Limited context | ACE search + Grep fallback |
|
||||
|
||||
**cli-explore-agent spawn**:
|
||||
|
||||
```
|
||||
|
||||
**核心策略**: 通过 cli-explore-agent 执行代码库探索
|
||||
|
||||
```javascript
|
||||
Task({
|
||||
subagent_type: "cli-explore-agent",
|
||||
run_in_background: false,
|
||||
description: `Explore codebase: ${topic} (${perspective})`,
|
||||
description: "Explore codebase: <topic> (<perspective>)",
|
||||
prompt: `
|
||||
## Analysis Context
|
||||
Topic: ${topic}
|
||||
Perspective: ${perspective}
|
||||
Dimensions: ${dimensions.join(', ')}
|
||||
Session: ${sessionFolder}
|
||||
Topic: <topic>
|
||||
Perspective: <perspective>
|
||||
Dimensions: <dimensions>
|
||||
Session: <session-folder>
|
||||
|
||||
## MANDATORY FIRST STEPS
|
||||
1. Run: ccw tool exec get_modules_by_depth '{}'
|
||||
2. Execute relevant searches based on topic keywords
|
||||
3. Read: .workflow/project-tech.json (if exists)
|
||||
|
||||
## Exploration Focus (${perspective} angle)
|
||||
${dimensions.map(d => `- ${d}: Identify relevant code patterns and structures`).join('\n')}
|
||||
## Exploration Focus (<perspective> angle)
|
||||
<dimensions map to exploration focus areas>
|
||||
|
||||
## Output
|
||||
Write findings to: ${sessionFolder}/explorations/exploration-${exploreNum}.json
|
||||
Write findings to: <session-folder>/explorations/exploration-<num>.json
|
||||
|
||||
Schema: {
|
||||
perspective: "${perspective}",
|
||||
perspective: "<perspective>",
|
||||
relevant_files: [{path, relevance, summary}],
|
||||
patterns: [string],
|
||||
key_findings: [string],
|
||||
@@ -139,102 +160,50 @@ Schema: {
|
||||
|
||||
### Phase 4: Result Validation
|
||||
|
||||
```javascript
|
||||
// 验证探索结果
|
||||
const outputPath = `${sessionFolder}/explorations/exploration-${exploreNum}.json`
|
||||
let explorationResult = {}
|
||||
try {
|
||||
explorationResult = JSON.parse(Read(outputPath))
|
||||
} catch {
|
||||
// Agent 未写入文件,使用空结果
|
||||
explorationResult = {
|
||||
perspective,
|
||||
relevant_files: [],
|
||||
patterns: [],
|
||||
key_findings: ['Exploration produced no structured output'],
|
||||
questions_for_analysis: [],
|
||||
_metadata: { agent: 'cli-explore-agent', timestamp: new Date().toISOString(), status: 'partial' }
|
||||
}
|
||||
Write(outputPath, JSON.stringify(explorationResult, null, 2))
|
||||
}
|
||||
**Validation steps**:
|
||||
|
||||
// 基本质量检查
|
||||
const hasFiles = explorationResult.relevant_files?.length > 0
|
||||
const hasFindings = explorationResult.key_findings?.length > 0
|
||||
| Check | Method | Action on Failure |
|
||||
|-------|--------|-------------------|
|
||||
| Output file exists | Read output path | Create empty result structure |
|
||||
| Has relevant files | Check array length | Trigger ACE fallback |
|
||||
| Has findings | Check key_findings | Note partial results |
|
||||
|
||||
**ACE fallback** (when exploration produces no output):
|
||||
|
||||
if (!hasFiles && !hasFindings) {
|
||||
// 探索结果为空,尝试 ACE 搜索兜底
|
||||
const aceResults = mcp__ace-tool__search_context({
|
||||
project_root_path: ".",
|
||||
query: topic
|
||||
})
|
||||
// 补充到结果中
|
||||
}
|
||||
```
|
||||
mcp__ace-tool__search_context({
|
||||
project_root_path: ".",
|
||||
query: <topic>
|
||||
})
|
||||
```
|
||||
|
||||
**Quality validation**:
|
||||
|
||||
| Metric | Threshold | Action |
|
||||
|--------|-----------|--------|
|
||||
| relevant_files count | > 0 | Proceed |
|
||||
| key_findings count | > 0 | Proceed |
|
||||
| Both empty | - | Use ACE fallback, mark partial |
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
// 更新 shared memory
|
||||
sharedMemory.explorations = sharedMemory.explorations || []
|
||||
sharedMemory.explorations.push({
|
||||
id: `exploration-${exploreNum}`,
|
||||
perspective,
|
||||
file_count: explorationResult.relevant_files?.length || 0,
|
||||
finding_count: explorationResult.key_findings?.length || 0,
|
||||
timestamp: new Date().toISOString()
|
||||
})
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
const resultSummary = `${perspective} 视角: ${explorationResult.relevant_files?.length || 0} 个相关文件, ${explorationResult.key_findings?.length || 0} 个发现`
|
||||
Standard report flow: team_msg log -> SendMessage with `[explorer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "explorer",
|
||||
to: "coordinator",
|
||||
type: "exploration_ready",
|
||||
summary: `[explorer] ${resultSummary}`,
|
||||
ref: outputPath
|
||||
})
|
||||
**Shared memory update**:
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [explorer] Exploration Results
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Perspective**: ${perspective}
|
||||
**Status**: ${hasFiles || hasFindings ? 'Findings Available' : 'Limited Results'}
|
||||
|
||||
### Summary
|
||||
${resultSummary}
|
||||
|
||||
### Top Findings
|
||||
${(explorationResult.key_findings || []).slice(0, 5).map(f => `- ${f}`).join('\n')}
|
||||
|
||||
### Questions for Analysis
|
||||
${(explorationResult.questions_for_analysis || []).slice(0, 3).map(q => `- ${q}`).join('\n')}
|
||||
|
||||
### Output
|
||||
${outputPath}`,
|
||||
summary: `[explorer] EXPLORE complete: ${resultSummary}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('EXPLORE-') &&
|
||||
t.owner === agentName &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
|
||||
if (nextTasks.length > 0) {
|
||||
// Continue with next task → back to Phase 1
|
||||
}
|
||||
```
|
||||
sharedMemory.explorations.push({
|
||||
id: "exploration-<num>",
|
||||
perspective: <perspective>,
|
||||
file_count: <count>,
|
||||
finding_count: <count>,
|
||||
timestamp: <timestamp>
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -245,3 +214,4 @@ if (nextTasks.length > 0) {
|
||||
| Exploration scope too broad | Narrow to topic keywords, report partial |
|
||||
| Agent timeout | Use partial results, note incomplete |
|
||||
| Session folder missing | Create it, warn coordinator |
|
||||
| Context/Plan file not found | Notify coordinator, request location |
|
||||
|
||||
@@ -1,40 +1,35 @@
|
||||
# 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 (综合结论)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `SYNTH-*` 前缀的任务
|
||||
- 所有输出必须带 `[synthesizer]` 标识
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- 整合所有角色的产出生成最终结论
|
||||
- 将综合结果写入 shared-memory.json 的 `synthesis` 字段
|
||||
- 更新 discussion.md 的结论部分
|
||||
- Only process `SYNTH-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[synthesizer]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within synthesis responsibility scope
|
||||
- Integrate all role outputs to generate final conclusions
|
||||
- Write synthesis results to shared-memory.json `synthesis` field
|
||||
- Update discussion.md conclusions section
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 执行新的代码探索或 CLI 分析
|
||||
- ❌ 与用户直接交互
|
||||
- ❌ 为其他角色创建任务
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 修改源代码
|
||||
- Execute new code exploration or CLI analysis
|
||||
- Interact directly with user
|
||||
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
|
||||
- Communicate directly with other worker roles
|
||||
- Modify source code
|
||||
- Omit `[synthesizer]` identifier in any output
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `synthesis_ready` | synthesizer → coordinator | 综合完成 | 包含最终结论和建议 |
|
||||
| `error` | synthesizer → coordinator | 综合失败 | 阻塞性错误 |
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -44,175 +39,202 @@
|
||||
|---------|------|-------|-------------|
|
||||
| `synthesize` | [commands/synthesize.md](commands/synthesize.md) | Phase 3 | 跨视角整合 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
> Synthesizer 不使用 subagent
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `Read` | File | synthesizer | Read all session artifacts |
|
||||
| `Write` | File | synthesizer | Write conclusions and updates |
|
||||
| `Glob` | File | synthesizer | Find all exploration/analysis/discussion files |
|
||||
|
||||
### CLI Capabilities
|
||||
> Synthesizer does not use subagents or CLI tools (pure integration role).
|
||||
|
||||
> Synthesizer 不使用 CLI 工具(纯整合角色)
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `synthesis_ready` | synthesizer → coordinator | 综合完成 | 包含最终结论和建议 |
|
||||
| `error` | synthesizer → coordinator | 综合失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: "ultra-analyze",
|
||||
from: "synthesizer",
|
||||
to: "coordinator",
|
||||
type: "synthesis_ready",
|
||||
summary: "[synthesizer] SYNTH complete: <summary>",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team ultra-analyze --from synthesizer --to coordinator --type synthesis_ready --summary \"[synthesizer] ...\" --ref <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.
|
||||
|
||||
Falls back to `synthesizer` for single-instance role.
|
||||
|
||||
### Phase 2: Context Loading + Shared Memory Read
|
||||
|
||||
```javascript
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim()
|
||||
const topic = task.description.match(/topic:\s*(.+)/)?.[1]?.trim()
|
||||
**Loading steps**:
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
1. Extract session path from task description
|
||||
2. Extract topic
|
||||
3. Read shared-memory.json
|
||||
4. Read all exploration files
|
||||
5. Read all analysis files
|
||||
6. Read all discussion round files
|
||||
7. Extract decision trail and current understanding
|
||||
|
||||
// Read all explorations
|
||||
const explorationFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
|
||||
const allExplorations = explorationFiles.map(f => {
|
||||
try { return JSON.parse(Read(f)) } catch { return null }
|
||||
}).filter(Boolean)
|
||||
**Context extraction**:
|
||||
|
||||
// Read all analyses
|
||||
const analysisFiles = Glob({ pattern: `${sessionFolder}/analyses/*.json` })
|
||||
const allAnalyses = analysisFiles.map(f => {
|
||||
try { return JSON.parse(Read(f)) } catch { return null }
|
||||
}).filter(Boolean)
|
||||
| Field | Source | Pattern |
|
||||
|-------|--------|---------|
|
||||
| sessionFolder | task description | `session:\s*(.+)` |
|
||||
| topic | task description | `topic:\s*(.+)` |
|
||||
|
||||
// Read all discussion rounds
|
||||
const discussionFiles = Glob({ pattern: `${sessionFolder}/discussions/discussion-round-*.json` })
|
||||
const allDiscussions = discussionFiles.map(f => {
|
||||
try { return JSON.parse(Read(f)) } catch { return null }
|
||||
}).filter(Boolean)
|
||||
**File loading**:
|
||||
|
||||
// Read decision trail
|
||||
const decisionTrail = sharedMemory.decision_trail || []
|
||||
const currentUnderstanding = sharedMemory.current_understanding || {}
|
||||
```
|
||||
| Artifact | Path Pattern |
|
||||
|----------|--------------|
|
||||
| Explorations | `<session>/explorations/*.json` |
|
||||
| Analyses | `<session>/analyses/*.json` |
|
||||
| Discussions | `<session>/discussions/discussion-round-*.json` |
|
||||
| Decision trail | `sharedMemory.decision_trail` |
|
||||
| Current understanding | `sharedMemory.current_understanding` |
|
||||
|
||||
### Phase 3: Synthesis Execution
|
||||
|
||||
```javascript
|
||||
// Read commands/synthesize.md for full implementation
|
||||
Read("commands/synthesize.md")
|
||||
```
|
||||
Delegate to `commands/synthesize.md` if available, otherwise execute inline.
|
||||
|
||||
**Synthesis dimensions**:
|
||||
|
||||
| Dimension | Source | Purpose |
|
||||
|-----------|--------|---------|
|
||||
| Explorations | All exploration files | Cross-perspective file relevance |
|
||||
| Analyses | All analysis files | Key insights and discussion points |
|
||||
| Discussions | All discussion rounds | Understanding evolution |
|
||||
| Decision trail | sharedMemory | Critical decision history |
|
||||
|
||||
**Conclusions structure**:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| summary | Executive summary |
|
||||
| key_conclusions | Array of {point, confidence, evidence} |
|
||||
| recommendations | Array of {priority, action, rationale} |
|
||||
| open_questions | Remaining unresolved questions |
|
||||
| _metadata | Synthesis metadata |
|
||||
|
||||
**Confidence levels**:
|
||||
|
||||
| Level | Criteria |
|
||||
|-------|----------|
|
||||
| High | Multiple sources confirm, strong evidence |
|
||||
| Medium | Single source or partial evidence |
|
||||
| Low | Speculative, needs verification |
|
||||
|
||||
### Phase 4: Write Conclusions + Update discussion.md
|
||||
|
||||
```javascript
|
||||
const synthNum = task.subject.match(/SYNTH-(\d+)/)?.[1] || '001'
|
||||
const conclusionsPath = `${sessionFolder}/conclusions.json`
|
||||
**Output paths**:
|
||||
|
||||
// 写入 conclusions.json
|
||||
Write(conclusionsPath, JSON.stringify(conclusions, null, 2))
|
||||
| File | Path |
|
||||
|------|------|
|
||||
| Conclusions | `<session-folder>/conclusions.json` |
|
||||
| Discussion update | `<session-folder>/discussion.md` |
|
||||
|
||||
// 更新 discussion.md — 结论部分
|
||||
const conclusionsMd = `
|
||||
**discussion.md conclusions section**:
|
||||
|
||||
```markdown
|
||||
## Conclusions
|
||||
|
||||
### Summary
|
||||
${conclusions.summary}
|
||||
<conclusions.summary>
|
||||
|
||||
### Key Conclusions
|
||||
${conclusions.key_conclusions.map((c, i) => `${i + 1}. **${c.point}** (Confidence: ${c.confidence})
|
||||
- Evidence: ${c.evidence}`).join('\n')}
|
||||
1. **<point>** (Confidence: <confidence>)
|
||||
- Evidence: <evidence>
|
||||
2. ...
|
||||
|
||||
### Recommendations
|
||||
${conclusions.recommendations.map((r, i) => `${i + 1}. **[${r.priority}]** ${r.action}
|
||||
- Rationale: ${r.rationale}`).join('\n')}
|
||||
1. **[<priority>]** <action>
|
||||
- Rationale: <rationale>
|
||||
2. ...
|
||||
|
||||
### Remaining Questions
|
||||
${(conclusions.open_questions || []).map(q => `- ${q}`).join('\n') || '(None)'}
|
||||
- <question 1>
|
||||
- <question 2>
|
||||
|
||||
## Decision Trail
|
||||
|
||||
### Critical Decisions
|
||||
${decisionTrail.map(d => `- **Round ${d.round}**: ${d.decision} — ${d.context}`).join('\n') || '(None)'}
|
||||
- **Round N**: <decision> — <context>
|
||||
|
||||
## Current Understanding (Final)
|
||||
|
||||
### What We Established
|
||||
${(currentUnderstanding.established || []).map(e => `- ${e}`).join('\n') || '(None)'}
|
||||
- <established item 1>
|
||||
- <established item 2>
|
||||
|
||||
### What Was Clarified/Corrected
|
||||
${(currentUnderstanding.clarified || []).map(c => `- ${c}`).join('\n') || '(None)'}
|
||||
- <clarified item 1>
|
||||
- <clarified item 2>
|
||||
|
||||
### Key Insights
|
||||
${(currentUnderstanding.key_insights || []).map(i => `- ${i}`).join('\n') || '(None)'}
|
||||
- <insight 1>
|
||||
- <insight 2>
|
||||
|
||||
## Session Statistics
|
||||
- **Explorations**: ${allExplorations.length}
|
||||
- **Analyses**: ${allAnalyses.length}
|
||||
- **Discussion Rounds**: ${allDiscussions.length}
|
||||
- **Decisions Made**: ${decisionTrail.length}
|
||||
- **Completed**: ${new Date().toISOString()}
|
||||
`
|
||||
|
||||
const currentDiscussion = Read(`${sessionFolder}/discussion.md`)
|
||||
Write(`${sessionFolder}/discussion.md`, currentDiscussion + conclusionsMd)
|
||||
- **Explorations**: <count>
|
||||
- **Analyses**: <count>
|
||||
- **Discussion Rounds**: <count>
|
||||
- **Decisions Made**: <count>
|
||||
- **Completed**: <timestamp>
|
||||
```
|
||||
|
||||
**Update steps**:
|
||||
|
||||
1. Write conclusions.json
|
||||
2. Read current discussion.md
|
||||
3. Append conclusions section
|
||||
4. Write updated discussion.md
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
sharedMemory.synthesis = {
|
||||
conclusion_count: conclusions.key_conclusions?.length || 0,
|
||||
recommendation_count: conclusions.recommendations?.length || 0,
|
||||
open_question_count: conclusions.open_questions?.length || 0,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
const resultSummary = `${conclusions.key_conclusions?.length || 0} 结论, ${conclusions.recommendations?.length || 0} 建议`
|
||||
Standard report flow: team_msg log -> SendMessage with `[synthesizer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "synthesizer",
|
||||
to: "coordinator",
|
||||
type: "synthesis_ready",
|
||||
summary: `[synthesizer] Synthesis complete: ${resultSummary}`,
|
||||
ref: conclusionsPath
|
||||
})
|
||||
**Shared memory update**:
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [synthesizer] Synthesis Results
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Topic**: ${topic}
|
||||
|
||||
### Summary
|
||||
${conclusions.summary}
|
||||
|
||||
### Top Conclusions
|
||||
${(conclusions.key_conclusions || []).slice(0, 3).map((c, i) => `${i + 1}. **${c.point}** (${c.confidence})`).join('\n')}
|
||||
|
||||
### Top Recommendations
|
||||
${(conclusions.recommendations || []).slice(0, 3).map((r, i) => `${i + 1}. [${r.priority}] ${r.action}`).join('\n')}
|
||||
|
||||
### Artifacts
|
||||
- 📄 Discussion: ${sessionFolder}/discussion.md
|
||||
- 📊 Conclusions: ${conclusionsPath}`,
|
||||
summary: `[synthesizer] SYNTH complete: ${resultSummary}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
```
|
||||
sharedMemory.synthesis = {
|
||||
conclusion_count: <count>,
|
||||
recommendation_count: <count>,
|
||||
open_question_count: <count>,
|
||||
timestamp: <timestamp>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -223,3 +245,5 @@ TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
| Conflicting analyses | Present both sides, recommend user decision |
|
||||
| Empty shared memory | Generate minimal conclusions from discussion.md |
|
||||
| Only one perspective | Create focused single-perspective synthesis |
|
||||
| Command file not found | Fall back to inline execution |
|
||||
| Session folder missing | Error to coordinator |
|
||||
|
||||
Reference in New Issue
Block a user