Skip to content

Commit 65762af

Browse files
author
catlog22
committed
feat: Add explorer and synthesizer roles with commands for codebase exploration and synthesis
- Implemented `explorer` role for parallel codebase exploration using `cli-explore-agent`. - Created `explore.md` command documentation detailing exploration strategy and execution steps. - Established `synthesizer` role for integrating insights from explorations, analyses, and discussions. - Developed `synthesize.md` command documentation outlining synthesis strategy and output format. - Configured team settings in `team-config.json` to support new roles and pipeline modes. - Added regression test for CodexLens bootstrap fallback to ensure robustness in error handling.
1 parent 32d2d53 commit 65762af

14 files changed

Lines changed: 3465 additions & 0 deletions

File tree

Lines changed: 391 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
---
2+
name: team-ultra-analyze
3+
description: Unified team skill for deep collaborative analysis. All roles invoke this skill with --role arg for role-specific execution. Triggers on "team ultra-analyze", "team analyze".
4+
allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*)
5+
---
6+
7+
# Team Ultra Analyze
8+
9+
深度协作分析团队技能。将单体分析工作流拆分为 5 角色协作:探索→分析→讨论→综合。支持 Quick/Standard/Deep 三种管道模式,通过讨论循环实现用户引导的渐进式理解深化。所有成员通过 `--role=xxx` 路由到角色执行逻辑。
10+
11+
## Architecture Overview
12+
13+
```
14+
┌─────────────────────────────────────────────────────────┐
15+
│ Skill(skill="team-ultra-analyze", args="--role=xxx") │
16+
└──────────────────────┬──────────────────────────────────┘
17+
│ Role Router
18+
┌──────────┬───────┼───────────┬───────────┐
19+
↓ ↓ ↓ ↓ ↓
20+
┌────────┐┌────────┐┌────────┐┌──────────┐┌───────────┐
21+
│coordi- ││explorer││analyst ││discussant││synthesizer│
22+
│nator ││EXPLORE-││ANALYZE-││DISCUSS-* ││SYNTH-* │
23+
│ roles/ ││* roles/││* roles/││ roles/ ││ roles/ │
24+
└────────┘└────────┘└────────┘└──────────┘└───────────┘
25+
```
26+
27+
## Command Architecture
28+
29+
```
30+
roles/
31+
├── coordinator/
32+
│ ├── role.md # 编排:话题澄清、管道选择、讨论循环、结果汇报
33+
│ └── commands/
34+
│ ├── dispatch.md # 任务链创建与依赖管理
35+
│ └── monitor.md # 进度监控 + 讨论循环
36+
├── explorer/
37+
│ ├── role.md # 代码库探索
38+
│ └── commands/
39+
│ └── explore.md # cli-explore-agent 并行探索
40+
├── analyst/
41+
│ ├── role.md # 深度分析
42+
│ └── commands/
43+
│ └── analyze.md # CLI 多视角分析
44+
├── discussant/
45+
│ ├── role.md # 讨论处理 + 方向调整
46+
│ └── commands/
47+
│ └── deepen.md # 深入探索
48+
└── synthesizer/
49+
├── role.md # 综合结论
50+
└── commands/
51+
└── synthesize.md # 跨视角整合
52+
```
53+
54+
**设计原则**: role.md 保留 Phase 1(Task Discovery)和 Phase 5(Report)内联。Phase 2-4 根据复杂度决定内联或委派到 `commands/*.md`
55+
56+
## Role Router
57+
58+
### Input Parsing
59+
60+
Parse `$ARGUMENTS` to extract `--role`:
61+
62+
```javascript
63+
const args = "$ARGUMENTS"
64+
const roleMatch = args.match(/--role[=\s]+(\w+)/)
65+
66+
if (!roleMatch) {
67+
throw new Error("Missing --role argument. Available roles: coordinator, explorer, analyst, discussant, synthesizer")
68+
}
69+
70+
const role = roleMatch[1]
71+
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "ultra-analyze"
72+
```
73+
74+
### Role Dispatch
75+
76+
```javascript
77+
const VALID_ROLES = {
78+
"coordinator": { file: "roles/coordinator/role.md", prefix: null },
79+
"explorer": { file: "roles/explorer/role.md", prefix: "EXPLORE" },
80+
"analyst": { file: "roles/analyst/role.md", prefix: "ANALYZE" },
81+
"discussant": { file: "roles/discussant/role.md", prefix: "DISCUSS" },
82+
"synthesizer": { file: "roles/synthesizer/role.md", prefix: "SYNTH" }
83+
}
84+
85+
if (!VALID_ROLES[role]) {
86+
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
87+
}
88+
89+
// Read and execute role-specific logic
90+
Read(VALID_ROLES[role].file)
91+
// → Execute the 5-phase process defined in that file
92+
```
93+
94+
### Available Roles
95+
96+
| Role | Task Prefix | Responsibility | Role File |
97+
|------|-------------|----------------|-----------|
98+
| `coordinator` | N/A | 话题澄清、管道选择、会话管理、讨论循环 | [roles/coordinator/role.md](roles/coordinator/role.md) |
99+
| `explorer` | EXPLORE-* | cli-explore-agent 多角度并行代码库探索 | [roles/explorer/role.md](roles/explorer/role.md) |
100+
| `analyst` | ANALYZE-* | CLI 多视角深度分析 | [roles/analyst/role.md](roles/analyst/role.md) |
101+
| `discussant` | DISCUSS-* | 用户反馈处理、方向调整、深入分析 | [roles/discussant/role.md](roles/discussant/role.md) |
102+
| `synthesizer` | SYNTH-* | 跨视角整合、结论生成、决策追踪 | [roles/synthesizer/role.md](roles/synthesizer/role.md) |
103+
104+
## Shared Infrastructure
105+
106+
### Role Isolation Rules
107+
108+
**核心原则**: 每个角色仅能执行自己职责范围内的工作。
109+
110+
#### Output Tagging(强制)
111+
112+
所有角色的输出必须带 `[role_name]` 标识前缀:
113+
114+
```javascript
115+
SendMessage({ content: `## [${role}] ...`, summary: `[${role}] ...` })
116+
mcp__ccw-tools__team_msg({ summary: `[${role}] ...` })
117+
```
118+
119+
#### Coordinator 隔离
120+
121+
| 允许 | 禁止 |
122+
|------|------|
123+
| 话题澄清 (AskUserQuestion) | ❌ 直接执行代码探索或分析 |
124+
| 创建任务链 (TaskCreate) | ❌ 直接调用 cli-explore-agent |
125+
| 管道选择 + 讨论循环驱动 | ❌ 直接调用 CLI 分析工具 |
126+
| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成 |
127+
128+
#### Worker 隔离
129+
130+
| 允许 | 禁止 |
131+
|------|------|
132+
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
133+
| 读写 shared-memory.json (自己的字段) | ❌ 为其他角色创建任务 |
134+
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
135+
136+
### Team Configuration
137+
138+
```javascript
139+
const TEAM_CONFIG = {
140+
name: "ultra-analyze",
141+
sessionDir: ".workflow/.team/UAN-{slug}-{date}/",
142+
msgDir: ".workflow/.team-msg/ultra-analyze/",
143+
sharedMemory: "shared-memory.json",
144+
analysisDimensions: ["architecture", "implementation", "performance", "security", "concept", "comparison", "decision"],
145+
maxDiscussionRounds: 5
146+
}
147+
```
148+
149+
### Shared Memory(核心产物)
150+
151+
```javascript
152+
// 各角色读取共享记忆
153+
const memoryPath = `${sessionFolder}/shared-memory.json`
154+
let sharedMemory = {}
155+
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
156+
157+
// 各角色写入自己负责的字段:
158+
// explorer → sharedMemory.explorations
159+
// analyst → sharedMemory.analyses
160+
// discussant → sharedMemory.discussions
161+
// synthesizer → sharedMemory.synthesis
162+
// coordinator → sharedMemory.decision_trail + current_understanding
163+
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
164+
```
165+
166+
### Message Bus (All Roles)
167+
168+
```javascript
169+
mcp__ccw-tools__team_msg({
170+
operation: "log",
171+
team: teamName,
172+
from: role,
173+
to: "coordinator",
174+
type: "<type>",
175+
summary: `[${role}] <summary>`,
176+
ref: "<file_path>"
177+
})
178+
```
179+
180+
| Role | Types |
181+
|------|-------|
182+
| coordinator | `pipeline_selected`, `discussion_round`, `direction_adjusted`, `task_unblocked`, `error`, `shutdown` |
183+
| explorer | `exploration_ready`, `error` |
184+
| analyst | `analysis_ready`, `error` |
185+
| discussant | `discussion_processed`, `error` |
186+
| synthesizer | `synthesis_ready`, `error` |
187+
188+
### CLI 回退
189+
190+
```javascript
191+
Bash(`ccw team log --team "${teamName}" --from "${role}" --to "coordinator" --type "<type>" --summary "<摘要>" --json`)
192+
```
193+
194+
### Task Lifecycle (All Worker Roles)
195+
196+
```javascript
197+
const tasks = TaskList()
198+
const myTasks = tasks.filter(t =>
199+
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
200+
t.owner === role &&
201+
t.status === 'pending' &&
202+
t.blockedBy.length === 0
203+
)
204+
if (myTasks.length === 0) return
205+
const task = TaskGet({ taskId: myTasks[0].id })
206+
TaskUpdate({ taskId: task.id, status: 'in_progress' })
207+
208+
// Phase 2-4: Role-specific
209+
// Phase 5: Report + Loop
210+
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: role, to: "coordinator", type: "...", summary: `[${role}] ...` })
211+
SendMessage({ type: "message", recipient: "coordinator", content: `## [${role}] ...`, summary: `[${role}] ...` })
212+
TaskUpdate({ taskId: task.id, status: 'completed' })
213+
```
214+
215+
## Three-Mode Pipeline Architecture
216+
217+
```
218+
Quick: EXPLORE-001ANALYZE-001SYNTH-001
219+
Standard: [EXPLORE-001..N](parallel) → [ANALYZE-001..N](parallel) → DISCUSS-001SYNTH-001
220+
Deep: [EXPLORE-001..N] → [ANALYZE-001..N] → DISCUSS-001ANALYZE-fix → DISCUSS-002...SYNTH-001
221+
```
222+
223+
### Mode Auto-Detection
224+
225+
```javascript
226+
function detectPipelineMode(args, taskDescription) {
227+
const modeMatch = args.match(/--mode[=\s]+(quick|standard|deep)/)
228+
if (modeMatch) return modeMatch[1]
229+
// 自动检测
230+
if (/快速|quick|overview|概览/.test(taskDescription)) return 'quick'
231+
if (/深入|deep|thorough|详细|全面/.test(taskDescription)) return 'deep'
232+
return 'standard'
233+
}
234+
```
235+
236+
### Discussion Loop (Deep Mode)
237+
238+
```
239+
coordinator(AskUser) → DISCUSS-N(deepen) → [optional ANALYZE-fix] → coordinator(AskUser) → ... → SYNTH
240+
```
241+
242+
## Decision Recording Protocol
243+
244+
**⚠️ CRITICAL**: 继承自原 analyze-with-file 命令。分析过程中以下情况必须立即记录到 discussion.md:
245+
246+
| Trigger | What to Record | Target Section |
247+
|---------|---------------|----------------|
248+
| **Direction choice** | 选择了什么、为什么、放弃了哪些替代方案 | `#### Decision Log` |
249+
| **Key finding** | 发现内容、影响范围、置信度 | `#### Key Findings` |
250+
| **Assumption change** | 旧假设→新理解、变更原因、影响 | `#### Corrected Assumptions` |
251+
| **User feedback** | 用户原始输入、采纳/调整理由 | `#### User Input` |
252+
253+
## Unified Session Directory
254+
255+
```
256+
.workflow/.team/UAN-{slug}-{YYYY-MM-DD}/
257+
├── shared-memory.json # 探索/分析/讨论/综合 共享记忆
258+
├── discussion.md # ⭐ 理解演进 & 讨论时间线
259+
├── explorations/ # Explorer output
260+
│ ├── exploration-001.json
261+
│ └── exploration-002.json
262+
├── analyses/ # Analyst output
263+
│ ├── analysis-001.json
264+
│ └── analysis-002.json
265+
├── discussions/ # Discussant output
266+
│ └── discussion-round-001.json
267+
└── conclusions.json # Synthesizer output
268+
```
269+
270+
## Coordinator Spawn Template
271+
272+
```javascript
273+
TeamCreate({ team_name: teamName })
274+
275+
// Explorer
276+
Task({
277+
subagent_type: "general-purpose",
278+
team_name: teamName,
279+
name: "explorer",
280+
prompt: `你是 team "${teamName}" 的 EXPLORER。
281+
282+
当你收到 EXPLORE-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=explorer") 执行。
283+
284+
当前需求: ${taskDescription}
285+
约束: ${constraints}
286+
287+
## 角色准则(强制)
288+
- 你只能处理 EXPLORE-* 前缀的任务,不得执行其他角色的工作
289+
- 所有输出(SendMessage、team_msg)必须带 [explorer] 标识前缀
290+
- 仅与 coordinator 通信,不得直接联系其他 worker
291+
- 不得使用 TaskCreate 为其他角色创建任务
292+
293+
## 消息总线(必须)
294+
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
295+
296+
工作流程:
297+
1. TaskList → 找到 EXPLORE-* 任务
298+
2. Skill(skill="team-ultra-analyze", args="--role=explorer") 执行
299+
3. team_msg log + SendMessage 结果给 coordinator(带 [explorer] 标识)
300+
4. TaskUpdate completed → 检查下一个任务`
301+
})
302+
303+
// Analyst
304+
Task({
305+
subagent_type: "general-purpose",
306+
team_name: teamName,
307+
name: "analyst",
308+
prompt: `你是 team "${teamName}" 的 ANALYST。
309+
310+
当你收到 ANALYZE-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=analyst") 执行。
311+
312+
当前需求: ${taskDescription}
313+
约束: ${constraints}
314+
315+
## 角色准则(强制)
316+
- 你只能处理 ANALYZE-* 前缀的任务
317+
- 所有输出必须带 [analyst] 标识前缀
318+
- 仅与 coordinator 通信
319+
320+
## 消息总线(必须)
321+
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
322+
323+
工作流程:
324+
1. TaskList → 找到 ANALYZE-* 任务
325+
2. Skill(skill="team-ultra-analyze", args="--role=analyst") 执行
326+
3. team_msg log + SendMessage 结果给 coordinator
327+
4. TaskUpdate completed → 检查下一个任务`
328+
})
329+
330+
// Discussant
331+
Task({
332+
subagent_type: "general-purpose",
333+
team_name: teamName,
334+
name: "discussant",
335+
prompt: `你是 team "${teamName}" 的 DISCUSSANT。
336+
337+
当你收到 DISCUSS-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=discussant") 执行。
338+
339+
当前需求: ${taskDescription}
340+
341+
## 角色准则(强制)
342+
- 你只能处理 DISCUSS-* 前缀的任务
343+
- 所有输出必须带 [discussant] 标识前缀
344+
345+
## 消息总线(必须)
346+
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
347+
348+
工作流程:
349+
1. TaskList → 找到 DISCUSS-* 任务
350+
2. Skill(skill="team-ultra-analyze", args="--role=discussant") 执行
351+
3. team_msg log + SendMessage
352+
4. TaskUpdate completed → 检查下一个任务`
353+
})
354+
355+
// Synthesizer
356+
Task({
357+
subagent_type: "general-purpose",
358+
team_name: teamName,
359+
name: "synthesizer",
360+
prompt: `你是 team "${teamName}" 的 SYNTHESIZER。
361+
362+
当你收到 SYNTH-* 任务时,调用 Skill(skill="team-ultra-analyze", args="--role=synthesizer") 执行。
363+
364+
当前需求: ${taskDescription}
365+
366+
## 角色准则(强制)
367+
- 你只能处理 SYNTH-* 前缀的任务
368+
- 所有输出必须带 [synthesizer] 标识前缀
369+
370+
## 消息总线(必须)
371+
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
372+
373+
工作流程:
374+
1. TaskList → 找到 SYNTH-* 任务
375+
2. Skill(skill="team-ultra-analyze", args="--role=synthesizer") 执行
376+
3. team_msg log + SendMessage
377+
4. TaskUpdate completed → 检查下一个任务`
378+
})
379+
```
380+
381+
## Error Handling
382+
383+
| Scenario | Resolution |
384+
|----------|------------|
385+
| Unknown --role value | Error with available role list |
386+
| Missing --role arg | Error with usage hint |
387+
| Role file not found | Error with expected path (roles/{name}/role.md) |
388+
| Task prefix conflict | Log warning, proceed |
389+
| Discussion loop stuck >5 rounds | Force synthesis, offer continuation |
390+
| CLI tool unavailable | Fallback chain: gemini → codex → manual analysis |
391+
| Explorer agent fails | Continue with available context, note limitation |

0 commit comments

Comments
 (0)