mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-06 16:31:12 +08:00
Refactor team collaboration skills and update documentation
- Renamed `team-lifecycle-v5` to `team-lifecycle` across various documentation files for consistency. - Updated references in code examples and usage sections to reflect the new skill name. - Added a new command file for the `monitor` functionality in the `team-iterdev` skill, detailing the coordinator's monitoring events and task management. - Introduced new components for dynamic pipeline visualization and session coordinates display in the frontend. - Implemented utility functions for pipeline stage detection and status derivation based on message history. - Enhanced the team role panel to map members to their respective pipeline roles with status indicators. - Updated Chinese documentation to reflect the changes in skill names and descriptions.
This commit is contained in:
@@ -11,21 +11,23 @@ Deep collaborative analysis team skill. Splits monolithic analysis into 5-role c
|
||||
## Architecture
|
||||
|
||||
```
|
||||
+-------------------------------------------------------------+
|
||||
| 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-*
|
||||
+---------------------------------------------------+
|
||||
| Skill(skill="team-ultra-analyze") |
|
||||
| args="<topic-description>" |
|
||||
+-------------------+-------------------------------+
|
||||
|
|
||||
Orchestration Mode (auto -> coordinator)
|
||||
|
|
||||
Coordinator (inline)
|
||||
Phase 0-5 orchestration
|
||||
|
|
||||
+-------+-------+-------+-------+
|
||||
v v v v
|
||||
[tw] [tw] [tw] [tw]
|
||||
explor- analy- discu- synthe-
|
||||
er st ssant sizer
|
||||
|
||||
(tw) = team-worker agent
|
||||
```
|
||||
|
||||
## Command Architecture
|
||||
@@ -65,13 +67,13 @@ Parse `$ARGUMENTS` to extract `--role` and optional `--agent-name`. If `--role`
|
||||
|
||||
### Role Registry
|
||||
|
||||
| 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 |
|
||||
| Role | Spec | Task Prefix | Inner Loop |
|
||||
|------|------|-------------|------------|
|
||||
| coordinator | [roles/coordinator/role.md](roles/coordinator/role.md) | (none) | - |
|
||||
| explorer | [role-specs/explorer.md](role-specs/explorer.md) | EXPLORE-* | false |
|
||||
| analyst | [role-specs/analyst.md](role-specs/analyst.md) | ANALYZE-* | false |
|
||||
| discussant | [role-specs/discussant.md](role-specs/discussant.md) | DISCUSS-* | false |
|
||||
| synthesizer | [role-specs/synthesizer.md](role-specs/synthesizer.md) | SYNTH-* | false |
|
||||
|
||||
> **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.
|
||||
|
||||
@@ -338,51 +340,43 @@ Beat 1 2 3 3a... 4
|
||||
|
||||
## 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.
|
||||
### v5 Worker Spawn (all roles)
|
||||
|
||||
**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.
|
||||
When coordinator spawns workers, use `team-worker` agent with role-spec path. The coordinator determines depth (number of parallel agents) based on selected perspectives.
|
||||
|
||||
**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 1 - Spawn Explorers**: Create depth explorer team-worker agents in parallel (EXPLORE-1 through EXPLORE-depth). Each receives its assigned perspective/domain and agent name for task matching.
|
||||
|
||||
**Phase 3 - Spawn Discussant**: After all analysts complete, create 1 discussant. It processes all analysis results and presents findings to user. Coordinator stops.
|
||||
**Phase 2 - Spawn Analysts**: After all explorers complete, create depth analyst team-worker agents in parallel (ANALYZE-1 through ANALYZE-depth).
|
||||
|
||||
**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 3 - Spawn Discussant**: After all analysts complete, create 1 discussant. Coordinator stops.
|
||||
|
||||
**Phase 4 - Spawn Synthesizer**: After final discussion round, create 1 synthesizer. It integrates all explorations, analyses, and discussions into final conclusions. Coordinator stops.
|
||||
**Phase 3a - Discussion Loop** (Deep mode only): Based on user feedback, coordinator may create additional ANALYZE-fix and DISCUSS tasks.
|
||||
|
||||
**Quick mode exception**: When depth=1, spawn single explorer, single analyst, single discussant, single synthesizer -- all as simple agents without numbered suffixes.
|
||||
**Phase 4 - Spawn Synthesizer**: After final discussion round, create 1 synthesizer.
|
||||
|
||||
**Single spawn example** (worker template used for all roles):
|
||||
**Quick mode exception**: When depth=1, spawn single explorer, single analyst, single discussant, single synthesizer without numbered suffixes.
|
||||
|
||||
**Single spawn template** (worker template used for all roles):
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
subagent_type: "team-worker",
|
||||
description: "Spawn <role> worker",
|
||||
team_name: <team-name>,
|
||||
team_name: "ultra-analyze",
|
||||
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.
|
||||
prompt: `## Role Assignment
|
||||
role: <role>
|
||||
role_spec: .claude/skills/team-ultra-analyze/role-specs/<role>.md
|
||||
session: <session-folder>
|
||||
session_id: <session-id>
|
||||
team_name: ultra-analyze
|
||||
requirement: <topic-description>
|
||||
agent_name: <agent-name>
|
||||
inner_loop: false
|
||||
|
||||
## 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`
|
||||
Read role_spec file to load Phase 2-4 domain instructions.
|
||||
Execute built-in Phase 1 (task discovery, owner=<agent-name>) -> role-spec Phase 2-4 -> built-in Phase 5 (report).`
|
||||
})
|
||||
```
|
||||
|
||||
@@ -419,6 +413,31 @@ Session: <session-folder>
|
||||
| +-- issues.md
|
||||
```
|
||||
|
||||
## Completion Action
|
||||
|
||||
When the pipeline completes (all tasks done, coordinator Phase 5):
|
||||
|
||||
```
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "Ultra-Analyze pipeline complete. What would you like to do?",
|
||||
header: "Completion",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "Archive & Clean (Recommended)", description: "Archive session, clean up tasks and team resources" },
|
||||
{ label: "Keep Active", description: "Keep session active for follow-up work or inspection" },
|
||||
{ label: "Export Results", description: "Export deliverables to a specified location, then clean" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
```
|
||||
|
||||
| Choice | Action |
|
||||
|--------|--------|
|
||||
| Archive & Clean | Update session status="completed" -> TeamDelete(ultra-analyze) -> output final summary |
|
||||
| Keep Active | Update session status="paused" -> output resume instructions: `Skill(skill="team-ultra-analyze", args="resume")` |
|
||||
| Export Results | AskUserQuestion for target path -> copy deliverables -> Archive & Clean |
|
||||
|
||||
## Session Resume
|
||||
|
||||
Coordinator supports `--resume` / `--continue` for interrupted sessions:
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
# Command: analyze
|
||||
|
||||
> CLI 多视角深度分析。基于探索结果,通过 CLI 工具执行深度分析并生成结构化洞察。
|
||||
|
||||
## When to Use
|
||||
|
||||
- Phase 3 of Analyst
|
||||
- 探索结果已就绪,需要深度分析
|
||||
- 每个 ANALYZE-* 任务触发一次
|
||||
|
||||
**Trigger conditions**:
|
||||
- Analyst Phase 2 完成后(上下文已加载)
|
||||
- 方向调整时创建的 ANALYZE-fix 任务
|
||||
|
||||
## Strategy
|
||||
|
||||
### Delegation Mode
|
||||
|
||||
**Mode**: CLI(通过 ccw cli 执行分析,Bash run_in_background: true)
|
||||
|
||||
### Decision Logic
|
||||
|
||||
```javascript
|
||||
// 根据 perspective 选择 CLI 工具和分析模板
|
||||
function buildAnalysisConfig(perspective, isDirectionFix) {
|
||||
const configs = {
|
||||
'technical': {
|
||||
tool: 'gemini',
|
||||
rule: 'analysis-analyze-code-patterns',
|
||||
focus: 'Implementation patterns, code quality, technical debt, feasibility',
|
||||
tasks: [
|
||||
'Analyze code structure and organization patterns',
|
||||
'Identify technical debt and anti-patterns',
|
||||
'Evaluate error handling and edge cases',
|
||||
'Assess testing coverage and quality'
|
||||
]
|
||||
},
|
||||
'architectural': {
|
||||
tool: 'claude',
|
||||
rule: 'analysis-review-architecture',
|
||||
focus: 'System design, scalability, component coupling, boundaries',
|
||||
tasks: [
|
||||
'Evaluate module boundaries and coupling',
|
||||
'Analyze data flow and component interactions',
|
||||
'Assess scalability and extensibility',
|
||||
'Review design pattern usage and consistency'
|
||||
]
|
||||
},
|
||||
'business': {
|
||||
tool: 'codex',
|
||||
rule: 'analysis-analyze-code-patterns',
|
||||
focus: 'Business logic, domain models, value delivery, stakeholder impact',
|
||||
tasks: [
|
||||
'Map business logic to code implementation',
|
||||
'Identify domain model completeness',
|
||||
'Evaluate business rule enforcement',
|
||||
'Assess impact on stakeholders and users'
|
||||
]
|
||||
},
|
||||
'domain_expert': {
|
||||
tool: 'gemini',
|
||||
rule: 'analysis-analyze-code-patterns',
|
||||
focus: 'Domain-specific patterns, standards compliance, best practices',
|
||||
tasks: [
|
||||
'Compare against domain best practices',
|
||||
'Check standards and convention compliance',
|
||||
'Identify domain-specific anti-patterns',
|
||||
'Evaluate domain model accuracy'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const config = configs[perspective] || configs['technical']
|
||||
|
||||
if (isDirectionFix) {
|
||||
config.rule = 'analysis-diagnose-bug-root-cause'
|
||||
config.tasks = [
|
||||
'Re-analyze from adjusted perspective',
|
||||
'Identify previously missed patterns',
|
||||
'Generate new insights from fresh angle',
|
||||
'Update discussion points based on direction change'
|
||||
]
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
```
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Context Preparation
|
||||
|
||||
```javascript
|
||||
const config = buildAnalysisConfig(perspective, isDirectionFix)
|
||||
|
||||
// 构建探索上下文摘要
|
||||
const explorationSummary = `
|
||||
PRIOR EXPLORATION CONTEXT:
|
||||
- Key files: ${(explorationContext.relevant_files || []).slice(0, 8).map(f => f.path || f).join(', ')}
|
||||
- Patterns found: ${(explorationContext.patterns || []).slice(0, 5).join('; ')}
|
||||
- Key findings: ${(explorationContext.key_findings || []).slice(0, 5).join('; ')}
|
||||
- Questions from exploration: ${(explorationContext.questions_for_analysis || []).slice(0, 3).join('; ')}`
|
||||
```
|
||||
|
||||
### Step 2: Execute CLI Analysis
|
||||
|
||||
```javascript
|
||||
const cliPrompt = `PURPOSE: ${isDirectionFix
|
||||
? `Supplementary analysis with adjusted focus on "${adjustedFocus}" for topic "${topic}"`
|
||||
: `Deep analysis of "${topic}" from ${perspective} perspective`}
|
||||
Success: ${isDirectionFix
|
||||
? 'New insights from adjusted direction with clear evidence'
|
||||
: 'Actionable insights with confidence levels and evidence references'}
|
||||
|
||||
${explorationSummary}
|
||||
|
||||
TASK:
|
||||
${config.tasks.map(t => `• ${t}`).join('\n')}
|
||||
• Generate structured findings with confidence levels (high/medium/low)
|
||||
• Identify discussion points requiring user input
|
||||
• List open questions needing further exploration
|
||||
|
||||
MODE: analysis
|
||||
CONTEXT: @**/* | Topic: ${topic}
|
||||
EXPECTED: JSON-structured analysis with sections: key_insights (with confidence), key_findings (with evidence), discussion_points, open_questions, recommendations (with priority)
|
||||
CONSTRAINTS: Focus on ${perspective} perspective | ${dimensions.join(', ')} dimensions${isDirectionFix ? ` | Adjusted focus: ${adjustedFocus}` : ''}`
|
||||
|
||||
Bash({
|
||||
command: `ccw cli -p "${cliPrompt}" --tool ${config.tool} --mode analysis --rule ${config.rule}`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// ⚠️ STOP POINT: Wait for CLI callback before continuing
|
||||
```
|
||||
|
||||
### Step 3: Result Processing
|
||||
|
||||
```javascript
|
||||
// CLI 结果返回后,解析并结构化
|
||||
const outputPath = `${sessionFolder}/analyses/analysis-${analyzeNum}.json`
|
||||
|
||||
// 从 CLI 输出中提取结构化数据
|
||||
// CLI 输出通常是 markdown,需要解析为 JSON
|
||||
const analysisResult = {
|
||||
perspective,
|
||||
dimensions,
|
||||
is_direction_fix: isDirectionFix,
|
||||
adjusted_focus: adjustedFocus || null,
|
||||
key_insights: [
|
||||
// 从 CLI 输出提取,每个包含 {insight, confidence, evidence}
|
||||
],
|
||||
key_findings: [
|
||||
// 具体发现 {finding, file_ref, impact}
|
||||
],
|
||||
discussion_points: [
|
||||
// 需要用户输入的讨论要点
|
||||
],
|
||||
open_questions: [
|
||||
// 未解决的问题
|
||||
],
|
||||
recommendations: [
|
||||
// {action, rationale, priority}
|
||||
],
|
||||
_metadata: {
|
||||
cli_tool: config.tool,
|
||||
cli_rule: config.rule,
|
||||
perspective,
|
||||
is_direction_fix: isDirectionFix,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
|
||||
Write(outputPath, JSON.stringify(analysisResult, null, 2))
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
```json
|
||||
{
|
||||
"perspective": "technical",
|
||||
"dimensions": ["architecture", "implementation"],
|
||||
"is_direction_fix": false,
|
||||
"key_insights": [
|
||||
{"insight": "Authentication uses stateless JWT", "confidence": "high", "evidence": "src/auth/jwt.ts:L42"}
|
||||
],
|
||||
"key_findings": [
|
||||
{"finding": "No rate limiting on login endpoint", "file_ref": "src/routes/auth.ts:L15", "impact": "Security risk"}
|
||||
],
|
||||
"discussion_points": [
|
||||
"Should we implement token rotation for refresh tokens?"
|
||||
],
|
||||
"open_questions": [
|
||||
"What is the expected concurrent user load?"
|
||||
],
|
||||
"recommendations": [
|
||||
{"action": "Add rate limiting to auth endpoints", "rationale": "Prevent brute force attacks", "priority": "high"}
|
||||
],
|
||||
"_metadata": {"cli_tool": "gemini", "cli_rule": "analysis-analyze-code-patterns", "timestamp": "..."}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| CLI tool unavailable | Try fallback: gemini → codex → claude |
|
||||
| CLI timeout | Retry with shorter prompt, or use exploration results directly |
|
||||
| CLI returns empty | Use exploration findings as-is, note analysis gap |
|
||||
| Invalid CLI output | Extract what's parseable, fill gaps with defaults |
|
||||
| Exploration context missing | Analyze with topic keywords only |
|
||||
@@ -1,251 +0,0 @@
|
||||
# Analyst Role
|
||||
|
||||
深度分析师。基于 explorer 的代码库探索结果,通过 CLI 多视角深度分析,生成结构化洞察和讨论要点。
|
||||
|
||||
## Identity
|
||||
|
||||
- **Name**: `analyst` | **Tag**: `[analyst]`
|
||||
- **Task Prefix**: `ANALYZE-*`
|
||||
- **Responsibility**: Read-only analysis (深度分析)
|
||||
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 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
|
||||
- Share analysis results via team_msg(type='state_update')
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Available Commands
|
||||
|
||||
| Command | File | Phase | Description |
|
||||
|---------|------|-------|-------------|
|
||||
| `analyze` | [commands/analyze.md](commands/analyze.md) | Phase 3 | CLI 多视角深度分析 |
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| 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 Tools
|
||||
|
||||
| CLI Tool | Mode | Used By | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `gemini` | analysis | analyze.md | 技术/领域分析 |
|
||||
| `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",
|
||||
session_id: <session-id>,
|
||||
from: "analyst",
|
||||
type: "analysis_ready",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
> `to` and `summary` are auto-defaulted by the tool.
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --session-id <session-id> --from analyst --type analysis_ready --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
Standard task discovery flow: TaskList -> filter by prefix `ANALYZE-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate 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
|
||||
|
||||
**Loading steps**:
|
||||
|
||||
1. Extract session path from task description
|
||||
2. Extract topic, perspective, dimensions from task metadata
|
||||
3. Check for direction-fix type (补充分析)
|
||||
4. Read role states via team_msg(operation="get_state") for existing context
|
||||
5. Read corresponding exploration results
|
||||
|
||||
**Context extraction**:
|
||||
|
||||
| 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*(.+)` |
|
||||
|
||||
**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
|
||||
|
||||
Delegate to `commands/analyze.md` if available, otherwise execute inline.
|
||||
|
||||
**Analysis prompt structure** (Direction Fix):
|
||||
|
||||
```
|
||||
PURPOSE: 补充分析 - 方向调整至 "<adjusted_focus>"
|
||||
Success: 针对新方向的深入洞察
|
||||
|
||||
PRIOR EXPLORATION CONTEXT:
|
||||
- Key files: <top 5 files from exploration>
|
||||
- Patterns: <top 3 patterns>
|
||||
- Previous findings: <top 3 findings>
|
||||
|
||||
TASK:
|
||||
- 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>
|
||||
EXPECTED: Structured analysis with adjusted focus, new insights, updated discussion points
|
||||
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: <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>
|
||||
- Identify patterns, anti-patterns, and opportunities
|
||||
- Generate discussion points for user clarification
|
||||
- Assess confidence level for each insight
|
||||
|
||||
MODE: analysis
|
||||
CONTEXT: @**/* | Topic: <topic>
|
||||
EXPECTED: Structured analysis with: key insights (with confidence), discussion points, open questions, recommendations with rationale
|
||||
CONSTRAINTS: Focus on <dimensions> | <perspective> perspective
|
||||
```
|
||||
|
||||
**CLI execution**:
|
||||
|
||||
```
|
||||
Bash({
|
||||
command: "ccw cli -p \"<analysis-prompt>\" --tool <cli-tool> --mode analysis",
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// STOP POINT: Wait for CLI callback
|
||||
```
|
||||
|
||||
### Phase 4: Result Aggregation
|
||||
|
||||
**Analysis output structure**:
|
||||
|
||||
| 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 |
|
||||
|
||||
**Output path**: `<session-folder>/analyses/analysis-<num>.json`
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
Standard report flow: team_msg log -> SendMessage with `[analyst]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
**Shared memory update**:
|
||||
|
||||
```
|
||||
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 |
|
||||
| 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,461 +1,324 @@
|
||||
# Command: monitor
|
||||
# Command: Monitor
|
||||
|
||||
> 阶段驱动的协调循环 + 讨论循环。按 pipeline 阶段顺序等待 worker 完成,驱动讨论循环,执行最终综合触发。
|
||||
Handle all coordinator monitoring events: worker callbacks, status checks, pipeline advancement, discussion loop control, and completion.
|
||||
|
||||
## When to Use
|
||||
## Constants
|
||||
|
||||
- Phase 4 of Coordinator
|
||||
- 任务链已创建并分发
|
||||
- 需要持续监控直到所有任务完成
|
||||
| Key | Value |
|
||||
|-----|-------|
|
||||
| SPAWN_MODE | background |
|
||||
| ONE_STEP_PER_INVOCATION | true |
|
||||
| WORKER_AGENT | team-worker |
|
||||
| MAX_DISCUSSION_ROUNDS_QUICK | 0 |
|
||||
| MAX_DISCUSSION_ROUNDS_STANDARD | 1 |
|
||||
| MAX_DISCUSSION_ROUNDS_DEEP | 5 |
|
||||
|
||||
**Trigger conditions**:
|
||||
- dispatch 完成后立即启动
|
||||
- 讨论循环创建新任务后重新进入
|
||||
## Phase 2: Context Loading
|
||||
|
||||
## Strategy
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session state | `<session>/session.json` | Yes |
|
||||
| Task list | `TaskList()` | Yes |
|
||||
| Trigger event | From Entry Router detection | Yes |
|
||||
| Pipeline mode | From session.json `pipeline_mode` | Yes |
|
||||
| Discussion round | From session.json `discussion_round` | Yes |
|
||||
|
||||
### Delegation Mode
|
||||
1. Load session.json for current state, `pipeline_mode`, `discussion_round`
|
||||
2. Run `TaskList()` to get current task statuses
|
||||
3. Identify trigger event type from Entry Router
|
||||
4. Compute max discussion rounds from pipeline mode:
|
||||
|
||||
**Mode**: Stage-driven(按阶段顺序等待,非轮询)+ Discussion-loop(讨论循环由 coordinator 驱动)
|
||||
|
||||
### 设计原则
|
||||
|
||||
> **模型执行没有时间概念,禁止任何形式的轮询等待。**
|
||||
>
|
||||
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态(空转浪费 API 轮次)
|
||||
> - ❌ 禁止: `Bash(sleep N)` / `Bash(timeout /t N)` 作为等待手段
|
||||
> - ✅ 采用: 同步 `Task()` 调用(`run_in_background: false`),call 本身即等待
|
||||
> - ✅ 采用: Worker 返回 = 阶段完成信号(天然回调)
|
||||
>
|
||||
> **原理**: `Task(run_in_background: false)` 是阻塞调用,coordinator 自动挂起直到 worker 返回。
|
||||
> 无需 sleep,无需轮询,无需消息总线监控。Worker 的返回就是回调。
|
||||
|
||||
### Decision Logic
|
||||
|
||||
```javascript
|
||||
// 消息路由表
|
||||
const routingTable = {
|
||||
// Explorer 完成
|
||||
'exploration_ready': { action: 'Mark EXPLORE complete, unblock ANALYZE' },
|
||||
// Analyst 完成
|
||||
'analysis_ready': { action: 'Mark ANALYZE complete, unblock DISCUSS or SYNTH' },
|
||||
// Discussant 完成
|
||||
'discussion_processed': { action: 'Mark DISCUSS complete, trigger user feedback collection', special: 'discussion_feedback' },
|
||||
// Synthesizer 完成
|
||||
'synthesis_ready': { action: 'Mark SYNTH complete, prepare final report', special: 'finalize' },
|
||||
// 错误
|
||||
'error': { action: 'Assess severity, retry or escalate', special: 'error_handler' }
|
||||
}
|
||||
```
|
||||
MAX_ROUNDS = pipeline_mode === 'deep' ? 5
|
||||
: pipeline_mode === 'standard' ? 1
|
||||
: 0
|
||||
```
|
||||
|
||||
### Stage-Worker 映射表
|
||||
## Phase 3: Event Handlers
|
||||
|
||||
```javascript
|
||||
const STAGE_WORKER_MAP = {
|
||||
'EXPLORE': { role: 'explorer', skillArgs: '--role=explorer' },
|
||||
'ANALYZE': { role: 'analyst', skillArgs: '--role=analyst' },
|
||||
'DISCUSS': { role: 'discussant', skillArgs: '--role=discussant' },
|
||||
'SYNTH': { role: 'synthesizer', skillArgs: '--role=synthesizer' }
|
||||
}
|
||||
### handleCallback
|
||||
|
||||
// ★ 统一 auto mode 检测
|
||||
const autoYes = /\b(-y|--yes)\b/.test(args)
|
||||
Triggered when a worker sends completion message (via SendMessage callback).
|
||||
|
||||
1. Parse message to identify role and task ID:
|
||||
|
||||
| Message Pattern | Role Detection |
|
||||
|----------------|---------------|
|
||||
| `[explorer]` or task ID `EXPLORE-*` | explorer |
|
||||
| `[analyst]` or task ID `ANALYZE-*` | analyst |
|
||||
| `[discussant]` or task ID `DISCUSS-*` | discussant |
|
||||
| `[synthesizer]` or task ID `SYNTH-*` | synthesizer |
|
||||
|
||||
2. Mark task as completed:
|
||||
|
||||
```
|
||||
TaskUpdate({ taskId: "<task-id>", status: "completed" })
|
||||
```
|
||||
|
||||
## Execution Steps
|
||||
3. Record completion in session state via team_msg
|
||||
|
||||
### Step 1: Context Preparation
|
||||
4. **Role-specific post-completion logic**:
|
||||
|
||||
```javascript
|
||||
// 从 role state 获取当前状态
|
||||
const sharedMemory = mcp__ccw-tools__team_msg({ operation: "get_state", session_id: sessionId })
|
||||
| Completed Role | Pipeline Mode | Post-Completion Action |
|
||||
|---------------|---------------|------------------------|
|
||||
| explorer | all | Log: exploration ready. Proceed to handleSpawnNext |
|
||||
| analyst | all | Log: analysis ready. Proceed to handleSpawnNext |
|
||||
| discussant | all | **Discussion feedback gate** (see below) |
|
||||
| synthesizer | all | Proceed to handleComplete |
|
||||
|
||||
let discussionRound = 0
|
||||
const MAX_DISCUSSION_ROUNDS = pipelineMode === 'deep' ? 5 : (pipelineMode === 'standard' ? 1 : 0)
|
||||
5. **Discussion Feedback Gate** (when discussant completes):
|
||||
|
||||
When a DISCUSS-* task completes, the coordinator collects user feedback BEFORE spawning the next task. This replaces any while-loop pattern.
|
||||
|
||||
// 获取 pipeline 阶段列表(来自 dispatch 创建的任务链)
|
||||
const allTasks = TaskList()
|
||||
const pipelineTasks = allTasks
|
||||
.filter(t => t.owner && t.owner !== 'coordinator')
|
||||
.sort((a, b) => Number(a.id) - Number(b.id))
|
||||
```
|
||||
// Read current discussion_round from session state
|
||||
discussion_round = session.discussion_round || 0
|
||||
discussion_round++
|
||||
|
||||
### Step 2: Sequential Stage Execution (Stop-Wait) — Exploration + Analysis
|
||||
// Update session state
|
||||
Update session.json: discussion_round = discussion_round
|
||||
|
||||
> **核心**: 逐阶段 spawn worker,同步阻塞等待返回。
|
||||
> Worker 返回 = 阶段完成。无 sleep、无轮询、无消息总线监控。
|
||||
// Check if discussion loop applies
|
||||
IF pipeline_mode === 'quick':
|
||||
// No discussion in quick mode -- proceed to handleSpawnNext (SYNTH)
|
||||
-> handleSpawnNext
|
||||
|
||||
```javascript
|
||||
// 处理 EXPLORE 和 ANALYZE 阶段
|
||||
const preDiscussionTasks = pipelineTasks.filter(t =>
|
||||
t.subject.startsWith('EXPLORE-') || t.subject.startsWith('ANALYZE-')
|
||||
)
|
||||
ELSE IF discussion_round >= MAX_ROUNDS:
|
||||
// Reached max rounds -- force proceed to synthesis
|
||||
Log: "Max discussion rounds reached, proceeding to synthesis"
|
||||
IF no SYNTH-001 task exists:
|
||||
Create SYNTH-001 task blocked by last DISCUSS task
|
||||
-> handleSpawnNext
|
||||
|
||||
for (const stageTask of preDiscussionTasks) {
|
||||
// 1. 提取阶段前缀 → 确定 worker 角色
|
||||
const stagePrefix = stageTask.subject.match(/^(\w+)-/)?.[1]
|
||||
const workerConfig = STAGE_WORKER_MAP[stagePrefix]
|
||||
|
||||
if (!workerConfig) continue
|
||||
|
||||
// 2. 标记任务为执行中
|
||||
TaskUpdate({ taskId: stageTask.id, status: 'in_progress' })
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
to: workerConfig.role, type: "task_unblocked",
|
||||
summary: `[coordinator] 启动阶段: ${stageTask.subject} → ${workerConfig.role}`
|
||||
})
|
||||
|
||||
// 3. 同步 spawn worker — 阻塞直到 worker 返回(Stop-Wait 核心)
|
||||
const workerResult = Task({
|
||||
subagent_type: "team-worker",
|
||||
description: `Spawn ${workerConfig.role} worker for ${stageTask.subject}`,
|
||||
team_name: teamName,
|
||||
name: workerConfig.role,
|
||||
prompt: `## Role Assignment
|
||||
role: ${workerConfig.role}
|
||||
role_spec: .claude/skills/team-ultra-analyze/role-specs/${workerConfig.role}.md
|
||||
session: ${sessionFolder}
|
||||
session_id: ${sessionId}
|
||||
team_name: ${teamName}
|
||||
requirement: ${stageTask.description || taskDescription}
|
||||
inner_loop: false
|
||||
|
||||
## Current Task
|
||||
- Task ID: ${stageTask.id}
|
||||
- Task: ${stageTask.subject}
|
||||
|
||||
Read role_spec file to load Phase 2-4 domain instructions.
|
||||
Execute built-in Phase 1 -> role-spec Phase 2-4 -> built-in Phase 5.`,
|
||||
run_in_background: false
|
||||
})
|
||||
|
||||
// 4. Worker 已返回 — 检查结果
|
||||
const taskState = TaskGet({ taskId: stageTask.id })
|
||||
|
||||
if (taskState.status !== 'completed') {
|
||||
handleStageTimeout(stageTask, 0, autoYes)
|
||||
} else {
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
to: "user", type: "quality_gate",
|
||||
summary: `[coordinator] 阶段完成: ${stageTask.subject}`
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2.1: Update discussion.md with Round 1
|
||||
|
||||
```javascript
|
||||
// 读取所有探索和分析结果
|
||||
const explorationFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
|
||||
const analysisFiles = Glob({ pattern: `${sessionFolder}/analyses/*.json` })
|
||||
|
||||
const explorations = explorationFiles.map(f => JSON.parse(Read(f)))
|
||||
const analyses = analysisFiles.map(f => JSON.parse(Read(f)))
|
||||
|
||||
// 更新 discussion.md — Round 1
|
||||
const round1Content = `
|
||||
### Round 1 - Initial Exploration & Analysis (${new Date().toISOString()})
|
||||
|
||||
#### Exploration Results
|
||||
${explorations.map(e => `- **${e.perspective || 'general'}**: ${e.key_findings?.slice(0, 3).join('; ') || 'No findings'}`).join('\n')}
|
||||
|
||||
#### Analysis Results
|
||||
${analyses.map(a => `- **${a.perspective || 'general'}**: ${a.key_insights?.slice(0, 3).join('; ') || 'No insights'}`).join('\n')}
|
||||
|
||||
#### Key Findings
|
||||
${analyses.flatMap(a => a.key_findings || []).slice(0, 5).map(f => `- ${f}`).join('\n')}
|
||||
|
||||
#### Discussion Points
|
||||
${analyses.flatMap(a => a.discussion_points || []).slice(0, 5).map(p => `- ${p}`).join('\n')}
|
||||
|
||||
#### Decision Log
|
||||
> **Decision**: Selected ${pipelineMode} pipeline with ${explorations.length} exploration(s) and ${analyses.length} analysis perspective(s)
|
||||
> - **Context**: Topic analysis and user preference
|
||||
> - **Chosen**: ${pipelineMode} mode — **Reason**: ${pipelineMode === 'quick' ? 'Fast overview requested' : pipelineMode === 'deep' ? 'Thorough analysis needed' : 'Balanced depth and breadth'}
|
||||
`
|
||||
|
||||
Edit({
|
||||
file_path: `${sessionFolder}/discussion.md`,
|
||||
old_string: '## Discussion Timeline\n',
|
||||
new_string: `## Discussion Timeline\n${round1Content}\n`
|
||||
})
|
||||
```
|
||||
|
||||
### Step 3: Discussion Loop (Standard/Deep mode)
|
||||
|
||||
```javascript
|
||||
if (MAX_DISCUSSION_ROUNDS === 0) {
|
||||
// Quick mode: skip discussion, go to synthesis
|
||||
createSynthesisTask(sessionFolder, [lastAnalyzeTaskId])
|
||||
} else {
|
||||
// Wait for initial DISCUSS-001 to complete
|
||||
// Then enter discussion loop
|
||||
|
||||
while (discussionRound < MAX_DISCUSSION_ROUNDS) {
|
||||
// 等待当前 DISCUSS 任务完成(Stop-Wait: spawn discussant worker)
|
||||
const currentDiscussId = `DISCUSS-${String(discussionRound + 1).padStart(3, '0')}`
|
||||
const discussTask = pipelineTasks.find(t => t.subject.startsWith(currentDiscussId))
|
||||
if (discussTask) {
|
||||
TaskUpdate({ taskId: discussTask.id, status: 'in_progress' })
|
||||
const discussResult = Task({
|
||||
subagent_type: "team-worker",
|
||||
description: `Spawn discussant worker for ${discussTask.subject}`,
|
||||
team_name: teamName,
|
||||
name: "discussant",
|
||||
prompt: `## Role Assignment
|
||||
role: discussant
|
||||
role_spec: .claude/skills/team-ultra-analyze/role-specs/discussant.md
|
||||
session: ${sessionFolder}
|
||||
session_id: ${sessionId}
|
||||
team_name: ${teamName}
|
||||
requirement: Discussion round ${discussionRound + 1}
|
||||
inner_loop: false
|
||||
|
||||
## Current Task
|
||||
- Task ID: ${discussTask.id}
|
||||
- Task: ${discussTask.subject}
|
||||
|
||||
Read role_spec file to load Phase 2-4 domain instructions.
|
||||
Execute built-in Phase 1 -> role-spec Phase 2-4 -> built-in Phase 5.`,
|
||||
run_in_background: false
|
||||
})
|
||||
}
|
||||
|
||||
// 收集用户反馈
|
||||
const feedbackResult = AskUserQuestion({
|
||||
ELSE:
|
||||
// Collect user feedback
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: `Round ${discussionRound + 1} 分析结果已就绪。请选择下一步:`,
|
||||
question: "Discussion round <N> complete. What next?",
|
||||
header: "Discussion Feedback",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "同意,继续深入", description: "分析方向正确,继续深入探索" },
|
||||
{ label: "需要调整方向", description: "有不同理解或关注点" },
|
||||
{ label: "分析完成", description: "已获得足够信息" },
|
||||
{ label: "有具体问题", description: "有特定问题需要解答" }
|
||||
{ label: "Continue deeper", description: "Current direction is good, go deeper" },
|
||||
{ label: "Adjust direction", description: "Shift analysis focus" },
|
||||
{ label: "Done", description: "Sufficient depth, proceed to synthesis" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
const feedback = feedbackResult["Discussion Feedback"]
|
||||
|
||||
// 📌 记录用户反馈到 decision_trail
|
||||
const latestMemory = mcp__ccw-tools__team_msg({ operation: "get_state", session_id: sessionId })
|
||||
latestMemory.decision_trail = latestMemory.decision_trail || []
|
||||
latestMemory.decision_trail.push({
|
||||
round: discussionRound + 1,
|
||||
decision: feedback,
|
||||
context: `User feedback at discussion round ${discussionRound + 1}`,
|
||||
timestamp: new Date().toISOString()
|
||||
})
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "state_update",
|
||||
data: { decision_trail: latestMemory.decision_trail }
|
||||
})
|
||||
|
||||
if (feedback === "分析完成") {
|
||||
// 📌 Record completion decision
|
||||
appendToDiscussion(sessionFolder, discussionRound + 1, {
|
||||
user_input: "分析完成",
|
||||
decision: "Exit discussion loop, proceed to synthesis",
|
||||
reason: "User satisfied with current analysis depth"
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
if (feedback === "需要调整方向") {
|
||||
// 收集调整方向
|
||||
const directionResult = AskUserQuestion({
|
||||
questions: [{
|
||||
question: "请选择新的关注方向:",
|
||||
header: "Direction Adjustment",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "代码细节", description: "深入具体代码实现" },
|
||||
{ label: "架构层面", description: "关注系统架构设计" },
|
||||
{ label: "最佳实践", description: "对比行业最佳实践" },
|
||||
{ label: "自定义", description: "输入自定义方向" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
const newDirection = directionResult["Direction Adjustment"]
|
||||
|
||||
// 📌 Record direction change
|
||||
appendToDiscussion(sessionFolder, discussionRound + 1, {
|
||||
user_input: `调整方向: ${newDirection}`,
|
||||
decision: `Direction adjusted to: ${newDirection}`,
|
||||
reason: "User requested focus change"
|
||||
})
|
||||
|
||||
// 创建补充分析 + 新讨论任务
|
||||
const fixId = createAnalysisFix(discussionRound + 1, newDirection, sessionFolder)
|
||||
discussionRound++
|
||||
createDiscussionTask(discussionRound + 1, 'direction-adjusted', newDirection, sessionFolder)
|
||||
continue
|
||||
}
|
||||
|
||||
if (feedback === "有具体问题") {
|
||||
// 📌 Record question
|
||||
appendToDiscussion(sessionFolder, discussionRound + 1, {
|
||||
user_input: "有具体问题(由 discussant 处理)",
|
||||
decision: "Create discussion task for specific questions"
|
||||
})
|
||||
|
||||
discussionRound++
|
||||
createDiscussionTask(discussionRound + 1, 'specific-questions', 'User has specific questions', sessionFolder)
|
||||
continue
|
||||
}
|
||||
|
||||
// 同意,继续深入
|
||||
appendToDiscussion(sessionFolder, discussionRound + 1, {
|
||||
user_input: "同意,继续深入",
|
||||
decision: "Continue deepening in current direction"
|
||||
})
|
||||
|
||||
discussionRound++
|
||||
if (discussionRound < MAX_DISCUSSION_ROUNDS) {
|
||||
createDiscussionTask(discussionRound + 1, 'deepen', 'Continue current direction', sessionFolder)
|
||||
}
|
||||
}
|
||||
|
||||
// 创建最终综合任务
|
||||
const lastDiscussTaskId = getLastCompletedTaskId('DISCUSS')
|
||||
createSynthesisTask(sessionFolder, [lastDiscussTaskId])
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3.1: Discussion Helper Functions
|
||||
6. **Feedback handling** (still inside handleCallback, after AskUserQuestion returns):
|
||||
|
||||
```javascript
|
||||
function appendToDiscussion(sessionFolder, round, data) {
|
||||
const roundContent = `
|
||||
### Round ${round + 1} - Discussion (${new Date().toISOString()})
|
||||
| Feedback | Action |
|
||||
|----------|--------|
|
||||
| "Continue deeper" | Create new DISCUSS-`<N+1>` task (pending, no blockedBy). Record decision in discussion.md. Proceed to handleSpawnNext |
|
||||
| "Adjust direction" | AskUserQuestion for new focus. Create ANALYZE-fix-`<N>` task (pending). Create DISCUSS-`<N+1>` task (pending, blockedBy ANALYZE-fix-`<N>`). Record direction change in discussion.md. Proceed to handleSpawnNext |
|
||||
| "Done" | Create SYNTH-001 task (pending, blockedBy last DISCUSS). Record decision in discussion.md. Proceed to handleSpawnNext |
|
||||
|
||||
#### User Input
|
||||
${data.user_input}
|
||||
**Dynamic task creation templates**:
|
||||
|
||||
#### Decision Log
|
||||
> **Decision**: ${data.decision}
|
||||
> - **Context**: Discussion round ${round + 1}
|
||||
> - **Reason**: ${data.reason || 'User-directed'}
|
||||
|
||||
#### Updated Understanding
|
||||
${data.updated_understanding || '(Updated by discussant)'}
|
||||
|
||||
`
|
||||
// Append to discussion.md
|
||||
const currentContent = Read(`${sessionFolder}/discussion.md`)
|
||||
Write(`${sessionFolder}/discussion.md`, currentContent + roundContent)
|
||||
}
|
||||
|
||||
function handleStageTimeout(stageTask, _unused, autoYes) {
|
||||
if (autoYes) {
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
to: "user", type: "error",
|
||||
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} worker 返回但未完成,自动跳过`
|
||||
})
|
||||
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
|
||||
return
|
||||
}
|
||||
|
||||
const decision = AskUserQuestion({
|
||||
questions: [{
|
||||
question: `阶段 "${stageTask.subject}" worker 返回但未完成。如何处理?`,
|
||||
header: "Stage Fail",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "重试", description: "重新 spawn worker 执行此阶段" },
|
||||
{ label: "跳过此阶段", description: "标记为跳过,继续后续流水线" },
|
||||
{ label: "终止流水线", description: "停止整个分析流程" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
const answer = decision["Stage Fail"]
|
||||
if (answer === "跳过此阶段") {
|
||||
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
|
||||
} else if (answer === "终止流水线") {
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
to: "user", type: "shutdown",
|
||||
summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}`
|
||||
})
|
||||
}
|
||||
}
|
||||
DISCUSS-N (subsequent round):
|
||||
```
|
||||
TaskCreate({
|
||||
subject: "DISCUSS-<NNN>",
|
||||
description: "PURPOSE: Process discussion round <N> | Success: Updated understanding
|
||||
TASK:
|
||||
- Process previous round results
|
||||
- Execute <type> discussion strategy
|
||||
- Update discussion timeline
|
||||
CONTEXT:
|
||||
- Session: <session-folder>
|
||||
- Topic: <topic>
|
||||
- Round: <N>
|
||||
- Type: <deepen|direction-adjusted|specific-questions>
|
||||
- Shared memory: <session>/wisdom/.msg/meta.json
|
||||
EXPECTED: <session>/discussions/discussion-round-<NNN>.json
|
||||
---
|
||||
InnerLoop: false",
|
||||
status: "pending"
|
||||
})
|
||||
```
|
||||
|
||||
### Step 4: Wait for Synthesis + Result Processing
|
||||
|
||||
```javascript
|
||||
// 等待 SYNTH-001 完成(Stop-Wait: spawn synthesizer worker)
|
||||
const synthTask = pipelineTasks.find(t => t.subject.startsWith('SYNTH-'))
|
||||
if (synthTask) {
|
||||
TaskUpdate({ taskId: synthTask.id, status: 'in_progress' })
|
||||
const synthResult = Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: `Spawn synthesizer worker for ${synthTask.subject}`,
|
||||
team_name: teamName,
|
||||
name: "synthesizer",
|
||||
prompt: `你是 team "${teamName}" 的 SYNTHESIZER。
|
||||
|
||||
## Primary Directive
|
||||
Skill(skill="team-ultra-analyze", args="--role=synthesizer")
|
||||
|
||||
## Assignment
|
||||
- Task ID: ${synthTask.id}
|
||||
- Task: ${synthTask.subject}
|
||||
- Session: ${sessionFolder}
|
||||
|
||||
## Workflow
|
||||
1. Skill(skill="team-ultra-analyze", args="--role=synthesizer") to load role definition
|
||||
2. Execute task per role.md
|
||||
3. TaskUpdate({ taskId: "${synthTask.id}", status: "completed" })
|
||||
|
||||
All outputs carry [synthesizer] tag.`,
|
||||
run_in_background: false
|
||||
})
|
||||
}
|
||||
|
||||
// 汇总所有结果
|
||||
const finalMemory = mcp__ccw-tools__team_msg({ operation: "get_state", session_id: sessionId })
|
||||
const allFinalTasks = TaskList()
|
||||
const workerTasks = allFinalTasks.filter(t => t.owner && t.owner !== 'coordinator')
|
||||
const summary = {
|
||||
total_tasks: workerTasks.length,
|
||||
completed_tasks: workerTasks.filter(t => t.status === 'completed').length,
|
||||
discussion_rounds: discussionRound,
|
||||
has_synthesis: !!finalMemory.synthesis,
|
||||
decisions_made: finalMemory.decision_trail?.length || 0
|
||||
}
|
||||
ANALYZE-fix-N (direction adjustment):
|
||||
```
|
||||
TaskCreate({
|
||||
subject: "ANALYZE-fix-<N>",
|
||||
description: "PURPOSE: Supplementary analysis with adjusted focus | Success: New insights from adjusted direction
|
||||
TASK:
|
||||
- Re-analyze from adjusted perspective: <adjusted_focus>
|
||||
- Build on previous exploration findings
|
||||
- Generate updated discussion points
|
||||
CONTEXT:
|
||||
- Session: <session-folder>
|
||||
- Topic: <topic>
|
||||
- Type: direction-fix
|
||||
- Adjusted focus: <adjusted_focus>
|
||||
- Shared memory: <session>/wisdom/.msg/meta.json
|
||||
EXPECTED: <session>/analyses/analysis-fix-<N>.json
|
||||
---
|
||||
InnerLoop: false",
|
||||
status: "pending"
|
||||
})
|
||||
```
|
||||
|
||||
## Output Format
|
||||
SYNTH-001 (created dynamically in deep mode):
|
||||
```
|
||||
TaskCreate({
|
||||
subject: "SYNTH-001",
|
||||
description: "PURPOSE: Integrate all analysis into final conclusions | Success: Executive summary with recommendations
|
||||
TASK:
|
||||
- Load all exploration, analysis, and discussion artifacts
|
||||
- Extract themes, consolidate evidence, prioritize recommendations
|
||||
- Write conclusions and update discussion.md
|
||||
CONTEXT:
|
||||
- Session: <session-folder>
|
||||
- Topic: <topic>
|
||||
- Upstream artifacts: explorations/*.json, analyses/*.json, discussions/*.json
|
||||
- Shared memory: <session>/wisdom/.msg/meta.json
|
||||
EXPECTED: <session>/conclusions.json + discussion.md update
|
||||
CONSTRAINTS: Pure integration, no new exploration
|
||||
---
|
||||
InnerLoop: false",
|
||||
blockedBy: ["<last-DISCUSS-task-id>"],
|
||||
status: "pending"
|
||||
})
|
||||
```
|
||||
|
||||
7. Record user feedback to decision_trail via team_msg:
|
||||
|
||||
```
|
||||
## Coordination Summary
|
||||
|
||||
### Pipeline Status: COMPLETE
|
||||
### Mode: [quick|standard|deep]
|
||||
### Tasks: [completed]/[total]
|
||||
### Discussion Rounds: [count]
|
||||
### Decisions Made: [count]
|
||||
|
||||
### Message Log (last 10)
|
||||
- [timestamp] [from] → [to]: [type] - [summary]
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "state_update",
|
||||
data: { decision_trail_entry: {
|
||||
round: discussion_round,
|
||||
decision: feedback,
|
||||
context: "User feedback at discussion round N",
|
||||
timestamp: current ISO timestamp
|
||||
}}
|
||||
})
|
||||
```
|
||||
|
||||
8. Proceed to handleSpawnNext
|
||||
|
||||
### handleSpawnNext
|
||||
|
||||
Find and spawn the next ready tasks.
|
||||
|
||||
1. Scan task list for tasks where:
|
||||
- Status is "pending"
|
||||
- All blockedBy tasks have status "completed"
|
||||
|
||||
2. For each ready task, determine role from task prefix:
|
||||
|
||||
| Task Prefix | Role | Role Spec |
|
||||
|-------------|------|-----------|
|
||||
| `EXPLORE-*` | explorer | `.claude/skills/team-ultra-analyze/role-specs/explorer.md` |
|
||||
| `ANALYZE-*` | analyst | `.claude/skills/team-ultra-analyze/role-specs/analyst.md` |
|
||||
| `DISCUSS-*` | discussant | `.claude/skills/team-ultra-analyze/role-specs/discussant.md` |
|
||||
| `SYNTH-*` | synthesizer | `.claude/skills/team-ultra-analyze/role-specs/synthesizer.md` |
|
||||
|
||||
3. Spawn team-worker for each ready task:
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "team-worker",
|
||||
description: "Spawn <role> worker for <task-subject>",
|
||||
team_name: "ultra-analyze",
|
||||
name: "<agent-name>",
|
||||
run_in_background: true,
|
||||
prompt: `## Role Assignment
|
||||
role: <role>
|
||||
role_spec: .claude/skills/team-ultra-analyze/role-specs/<role>.md
|
||||
session: <session-folder>
|
||||
session_id: <session-id>
|
||||
team_name: ultra-analyze
|
||||
requirement: <task-description>
|
||||
agent_name: <agent-name>
|
||||
inner_loop: false
|
||||
|
||||
## Current Task
|
||||
- Task ID: <task-id>
|
||||
- Task: <task-subject>
|
||||
|
||||
Read role_spec file to load Phase 2-4 domain instructions.
|
||||
Execute built-in Phase 1 (task discovery, owner=<agent-name>) -> role-spec Phase 2-4 -> built-in Phase 5 (report).`
|
||||
})
|
||||
```
|
||||
|
||||
4. **Parallel spawn rules**:
|
||||
|
||||
| Mode | Stage | Spawn Behavior |
|
||||
|------|-------|---------------|
|
||||
| quick | All stages | One worker at a time (serial pipeline) |
|
||||
| standard/deep | EXPLORE phase | Spawn all EXPLORE-001..N in parallel |
|
||||
| standard/deep | ANALYZE phase | Spawn all ANALYZE-001..N in parallel |
|
||||
| all | DISCUSS phase | One discussant at a time |
|
||||
| all | SYNTH phase | One synthesizer |
|
||||
|
||||
5. **STOP** after spawning -- wait for next callback
|
||||
|
||||
### handleCheck
|
||||
|
||||
Output current pipeline status without advancing.
|
||||
|
||||
```
|
||||
Pipeline Status (<mode> mode):
|
||||
[DONE] EXPLORE-001 (explorer) -> exploration-001.json
|
||||
[DONE] EXPLORE-002 (explorer) -> exploration-002.json
|
||||
[DONE] ANALYZE-001 (analyst) -> analysis-001.json
|
||||
[RUN] ANALYZE-002 (analyst) -> analyzing...
|
||||
[WAIT] DISCUSS-001 (discussant) -> blocked by ANALYZE-002
|
||||
[----] SYNTH-001 (synthesizer) -> blocked by DISCUSS-001
|
||||
|
||||
Discussion Rounds: 0/<max>
|
||||
Pipeline Mode: <mode>
|
||||
Session: <session-id>
|
||||
```
|
||||
|
||||
Output status -- do NOT advance pipeline.
|
||||
|
||||
### handleResume
|
||||
|
||||
Resume pipeline after user pause or interruption.
|
||||
|
||||
1. Audit task list for inconsistencies:
|
||||
- Tasks stuck in "in_progress" -> reset to "pending"
|
||||
- Tasks with completed blockers but still "pending" -> include in spawn list
|
||||
2. Proceed to handleSpawnNext
|
||||
|
||||
### handleComplete
|
||||
|
||||
Triggered when all pipeline tasks are completed.
|
||||
|
||||
**Completion check**:
|
||||
|
||||
| Mode | Completion Condition |
|
||||
|------|---------------------|
|
||||
| quick | EXPLORE-001 + ANALYZE-001 + SYNTH-001 all completed |
|
||||
| standard | All EXPLORE + ANALYZE + DISCUSS-001 + SYNTH-001 completed |
|
||||
| deep | All EXPLORE + ANALYZE + all DISCUSS-N + SYNTH-001 completed |
|
||||
|
||||
1. Verify all tasks completed. If any not completed, return to handleSpawnNext
|
||||
2. If all completed, transition to coordinator Phase 5
|
||||
|
||||
## Phase 4: State Persistence
|
||||
|
||||
After every handler execution:
|
||||
|
||||
1. Update session.json with current state:
|
||||
- `discussion_round`: current round count
|
||||
- `last_event`: event type and timestamp
|
||||
- `active_tasks`: list of in-progress task IDs
|
||||
2. Verify task list consistency (no orphan tasks, no broken dependencies)
|
||||
3. **STOP** and wait for next event
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| Worker 返回但未 completed (交互模式) | AskUserQuestion: 重试 / 跳过 / 终止 |
|
||||
| Worker 返回但未 completed (自动模式) | 自动跳过,记录日志 |
|
||||
| Worker spawn 失败 | 重试一次,仍失败则上报用户 |
|
||||
| Discussion loop stuck >5 rounds | Force synthesis, offer continuation |
|
||||
| Synthesis fails | Report partial results from analyses |
|
||||
| Worker callback but task not completed | Log warning, reset task to pending, include in next handleSpawnNext |
|
||||
| Worker spawn fails | Retry once. If still fails, report to user via AskUserQuestion: retry / skip / abort |
|
||||
| Discussion loop exceeds max rounds | Force create SYNTH-001, proceed to synthesis |
|
||||
| Synthesis fails | Report partial results from analyses and discussions |
|
||||
| Pipeline stall (no ready + no running) | Check blockedBy chains, report blockage to user |
|
||||
| Missing task artifacts | Log warning, continue with available data |
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
# Command: deepen
|
||||
|
||||
> 深入探索与补充分析。根据讨论类型执行针对性的代码探索或 CLI 分析。
|
||||
|
||||
## When to Use
|
||||
|
||||
- Phase 3 of Discussant
|
||||
- 用户反馈已收集,需要深入处理
|
||||
- 每个 DISCUSS-* 任务触发一次
|
||||
|
||||
**Trigger conditions**:
|
||||
- initial: 首轮讨论,汇总分析结果
|
||||
- deepen: 继续深入当前方向
|
||||
- direction-adjusted: 方向调整后重新分析
|
||||
- specific-questions: 回答用户具体问题
|
||||
|
||||
## Strategy
|
||||
|
||||
### Delegation Mode
|
||||
|
||||
**Mode**: Mixed(简单汇总内联,深入探索用 subagent/CLI)
|
||||
|
||||
### Decision Logic
|
||||
|
||||
```javascript
|
||||
function selectDeepenStrategy(discussType, complexity) {
|
||||
const strategies = {
|
||||
'initial': {
|
||||
mode: 'inline',
|
||||
description: 'Summarize all analysis results into discussion format'
|
||||
},
|
||||
'deepen': {
|
||||
mode: complexity === 'High' ? 'cli' : 'subagent',
|
||||
description: 'Further exploration in current direction'
|
||||
},
|
||||
'direction-adjusted': {
|
||||
mode: 'cli',
|
||||
description: 'Re-analyze from new perspective'
|
||||
},
|
||||
'specific-questions': {
|
||||
mode: 'subagent',
|
||||
description: 'Targeted exploration to answer questions'
|
||||
}
|
||||
}
|
||||
return strategies[discussType] || strategies['initial']
|
||||
}
|
||||
```
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Strategy Selection
|
||||
|
||||
```javascript
|
||||
const strategy = selectDeepenStrategy(discussType, assessComplexity(userFeedback))
|
||||
```
|
||||
|
||||
### Step 2: Execute by Type
|
||||
|
||||
#### Initial Discussion
|
||||
|
||||
```javascript
|
||||
function processInitialDiscussion() {
|
||||
// 汇总所有分析结果
|
||||
const summary = {
|
||||
perspectives_analyzed: allAnalyses.map(a => a.perspective),
|
||||
total_insights: currentInsights.length,
|
||||
total_findings: currentFindings.length,
|
||||
convergent_themes: identifyConvergentThemes(allAnalyses),
|
||||
conflicting_views: identifyConflicts(allAnalyses),
|
||||
top_discussion_points: discussionPoints.slice(0, 5),
|
||||
open_questions: openQuestions.slice(0, 5)
|
||||
}
|
||||
|
||||
roundContent.updated_understanding.new_insights = summary.convergent_themes
|
||||
roundContent.new_findings = currentFindings.slice(0, 10)
|
||||
roundContent.new_questions = openQuestions.slice(0, 5)
|
||||
}
|
||||
|
||||
function identifyConvergentThemes(analyses) {
|
||||
// 跨视角找共同主题
|
||||
const allInsights = analyses.flatMap(a =>
|
||||
(a.key_insights || []).map(i => typeof i === 'string' ? i : i.insight)
|
||||
)
|
||||
// 简单去重 + 聚合
|
||||
return [...new Set(allInsights)].slice(0, 5)
|
||||
}
|
||||
|
||||
function identifyConflicts(analyses) {
|
||||
// 识别视角间的矛盾
|
||||
return [] // 由实际分析结果决定
|
||||
}
|
||||
```
|
||||
|
||||
#### Deepen Discussion
|
||||
|
||||
```javascript
|
||||
function processDeepenDiscussion() {
|
||||
// 在当前方向上进一步探索
|
||||
Task({
|
||||
subagent_type: "cli-explore-agent",
|
||||
run_in_background: false,
|
||||
description: `Deepen exploration: ${topic} (round ${round})`,
|
||||
prompt: `
|
||||
## Context
|
||||
Topic: ${topic}
|
||||
Round: ${round}
|
||||
Previous findings: ${currentFindings.slice(0, 5).join('; ')}
|
||||
Open questions: ${openQuestions.slice(0, 3).join('; ')}
|
||||
|
||||
## MANDATORY FIRST STEPS
|
||||
1. Focus on open questions from previous analysis
|
||||
2. Search for specific patterns mentioned in findings
|
||||
3. Look for edge cases and exceptions
|
||||
|
||||
## Exploration Focus
|
||||
- Deepen understanding of confirmed patterns
|
||||
- Investigate open questions
|
||||
- Find additional evidence for uncertain insights
|
||||
|
||||
## Output
|
||||
Write to: ${sessionFolder}/discussions/deepen-${discussNum}.json
|
||||
Schema: {new_findings, answered_questions, remaining_questions, evidence}
|
||||
`
|
||||
})
|
||||
|
||||
// 读取深入探索结果
|
||||
let deepenResult = {}
|
||||
try {
|
||||
deepenResult = JSON.parse(Read(`${sessionFolder}/discussions/deepen-${discussNum}.json`))
|
||||
} catch {}
|
||||
|
||||
roundContent.updated_understanding.new_insights = deepenResult.new_findings || []
|
||||
roundContent.new_findings = deepenResult.new_findings || []
|
||||
roundContent.new_questions = deepenResult.remaining_questions || []
|
||||
}
|
||||
```
|
||||
|
||||
#### Direction Adjusted
|
||||
|
||||
```javascript
|
||||
function processDirectionAdjusted() {
|
||||
// 方向调整后,通过 CLI 重新分析
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Re-analyze '${topic}' with adjusted focus on '${userFeedback}'
|
||||
Success: New insights from adjusted direction
|
||||
|
||||
PREVIOUS ANALYSIS CONTEXT:
|
||||
- Previous insights: ${currentInsights.slice(0, 5).map(i => typeof i === 'string' ? i : i.insight).join('; ')}
|
||||
- Direction change reason: User requested focus on '${userFeedback}'
|
||||
|
||||
TASK:
|
||||
• Re-evaluate findings from new perspective
|
||||
• Identify what changes with adjusted focus
|
||||
• Find new patterns relevant to adjusted direction
|
||||
• Note what previous findings remain valid
|
||||
|
||||
MODE: analysis
|
||||
CONTEXT: @**/* | Topic: ${topic}
|
||||
EXPECTED: Updated analysis with: validated findings, new insights, invalidated assumptions
|
||||
CONSTRAINTS: Focus on ${userFeedback}
|
||||
" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// ⚠️ STOP: Wait for CLI callback
|
||||
|
||||
roundContent.updated_understanding.corrected = ['Direction adjusted per user request']
|
||||
roundContent.updated_understanding.new_insights = [] // From CLI result
|
||||
}
|
||||
```
|
||||
|
||||
#### Specific Questions
|
||||
|
||||
```javascript
|
||||
function processSpecificQuestions() {
|
||||
// 针对用户问题进行探索
|
||||
Task({
|
||||
subagent_type: "cli-explore-agent",
|
||||
run_in_background: false,
|
||||
description: `Answer questions: ${topic}`,
|
||||
prompt: `
|
||||
## Context
|
||||
Topic: ${topic}
|
||||
User questions: ${userFeedback}
|
||||
Known findings: ${currentFindings.slice(0, 5).join('; ')}
|
||||
|
||||
## MANDATORY FIRST STEPS
|
||||
1. Search for code related to user's questions
|
||||
2. Trace execution paths relevant to questions
|
||||
3. Check configuration and environment factors
|
||||
|
||||
## Output
|
||||
Write to: ${sessionFolder}/discussions/questions-${discussNum}.json
|
||||
Schema: {answers: [{question, answer, evidence, confidence}], follow_up_questions}
|
||||
`
|
||||
})
|
||||
|
||||
let questionResult = {}
|
||||
try {
|
||||
questionResult = JSON.parse(Read(`${sessionFolder}/discussions/questions-${discussNum}.json`))
|
||||
} catch {}
|
||||
|
||||
roundContent.updated_understanding.new_insights =
|
||||
(questionResult.answers || []).map(a => `Q: ${a.question} → A: ${a.answer}`)
|
||||
roundContent.new_questions = questionResult.follow_up_questions || []
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Result Processing
|
||||
|
||||
```javascript
|
||||
// 结果已写入 roundContent,由 role.md Phase 4 处理
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| cli-explore-agent fails | Use existing analysis results, note limitation |
|
||||
| CLI timeout | Report partial results |
|
||||
| No previous analyses | Process as initial with empty context |
|
||||
| User feedback unparseable | Treat as 'deepen' type |
|
||||
@@ -1,225 +0,0 @@
|
||||
# Discussant Role
|
||||
|
||||
讨论处理者。根据 coordinator 传递的用户反馈,执行方向调整、深入探索或补充分析,更新讨论时间线。
|
||||
|
||||
## Identity
|
||||
|
||||
- **Name**: `discussant` | **Tag**: `[discussant]`
|
||||
- **Task Prefix**: `DISCUSS-*`
|
||||
- **Responsibility**: Analysis + Exploration (讨论处理)
|
||||
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 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
|
||||
- Share discussion results via team_msg(type='state_update')
|
||||
- Update discussion.md discussion timeline
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Available Commands
|
||||
|
||||
| Command | File | Phase | Description |
|
||||
|---------|------|-------|-------------|
|
||||
| `deepen` | [commands/deepen.md](commands/deepen.md) | Phase 3 | 深入探索与补充分析 |
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| 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 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",
|
||||
session_id: <session-id>,
|
||||
from: "discussant",
|
||||
type: "discussion_processed",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
> `to` and `summary` are auto-defaulted by the tool.
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --session-id <session-id> --from discussant --type discussion_processed --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
Standard task discovery flow: TaskList -> filter by prefix `DISCUSS-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
Falls back to `discussant` for single-instance role.
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
**Loading steps**:
|
||||
|
||||
1. Extract session path from task description
|
||||
2. Extract topic, round number, discussion type, user feedback
|
||||
3. Read role states via team_msg(operation="get_state") for existing context
|
||||
4. Read all analysis results
|
||||
5. Read all exploration results
|
||||
6. Aggregate current findings, insights, questions
|
||||
|
||||
**Context extraction**:
|
||||
|
||||
| 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 |
|
||||
|
||||
**Discussion types**:
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| initial | 首轮讨论:汇总所有分析结果,生成讨论摘要 |
|
||||
| deepen | 继续深入:在当前方向上进一步探索 |
|
||||
| direction-adjusted | 方向调整:基于新方向重新组织发现 |
|
||||
| specific-questions | 具体问题:针对用户问题进行分析 |
|
||||
|
||||
### Phase 3: Discussion Processing
|
||||
|
||||
Delegate to `commands/deepen.md` if available, otherwise execute inline.
|
||||
|
||||
**Processing by discussion type**:
|
||||
|
||||
| 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 |
|
||||
|
||||
**Round content structure**:
|
||||
|
||||
| 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
|
||||
|
||||
**Output path**: `<session-folder>/discussions/discussion-round-<num>.json`
|
||||
|
||||
**discussion.md update template**:
|
||||
|
||||
```markdown
|
||||
### Round <N> - Discussion (<timestamp>)
|
||||
|
||||
#### Type
|
||||
<discussType>
|
||||
|
||||
#### User Input
|
||||
<userFeedback or "(Initial discussion round)">
|
||||
|
||||
#### Updated Understanding
|
||||
**Confirmed**: <list of confirmed assumptions>
|
||||
**Corrected**: <list of corrected assumptions>
|
||||
**New Insights**: <list of new insights>
|
||||
|
||||
#### New Findings
|
||||
<list of new findings or "(None)">
|
||||
|
||||
#### Open Questions
|
||||
<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
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
Standard report flow: team_msg log -> SendMessage with `[discussant]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
**Shared memory update**:
|
||||
|
||||
```
|
||||
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
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No DISCUSS-* tasks available | Idle, wait for coordinator assignment |
|
||||
| No analysis results found | Report empty discussion, notify coordinator |
|
||||
| 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,194 +0,0 @@
|
||||
# Command: explore
|
||||
|
||||
> cli-explore-agent 并行代码库探索。根据话题和视角,通过 subagent 收集代码库上下文。
|
||||
|
||||
## When to Use
|
||||
|
||||
- Phase 3 of Explorer
|
||||
- 需要收集代码库上下文供后续分析
|
||||
- 每个 EXPLORE-* 任务触发一次
|
||||
|
||||
**Trigger conditions**:
|
||||
- Explorer Phase 2 完成后
|
||||
- 任务包含明确的 perspective 和 dimensions
|
||||
|
||||
## Strategy
|
||||
|
||||
### Delegation Mode
|
||||
|
||||
**Mode**: Subagent(cli-explore-agent 执行实际探索)
|
||||
|
||||
### Decision Logic
|
||||
|
||||
```javascript
|
||||
// 根据 perspective 确定探索策略
|
||||
function buildExplorationStrategy(perspective, dimensions, topic) {
|
||||
const strategies = {
|
||||
'general': {
|
||||
focus: 'Overall codebase structure and patterns',
|
||||
searches: [topic, ...dimensions],
|
||||
depth: 'broad'
|
||||
},
|
||||
'technical': {
|
||||
focus: 'Implementation details, code patterns, technical feasibility',
|
||||
searches: [`${topic} implementation`, `${topic} pattern`, `${topic} handler`],
|
||||
depth: 'medium'
|
||||
},
|
||||
'architectural': {
|
||||
focus: 'System design, module boundaries, component interactions',
|
||||
searches: [`${topic} module`, `${topic} service`, `${topic} interface`],
|
||||
depth: 'broad'
|
||||
},
|
||||
'business': {
|
||||
focus: 'Business logic, domain models, value flows',
|
||||
searches: [`${topic} model`, `${topic} domain`, `${topic} workflow`],
|
||||
depth: 'medium'
|
||||
},
|
||||
'domain_expert': {
|
||||
focus: 'Domain-specific patterns, standards compliance, best practices',
|
||||
searches: [`${topic} standard`, `${topic} convention`, `${topic} best practice`],
|
||||
depth: 'deep'
|
||||
}
|
||||
}
|
||||
return strategies[perspective] || strategies['general']
|
||||
}
|
||||
```
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Context Preparation
|
||||
|
||||
```javascript
|
||||
const strategy = buildExplorationStrategy(perspective, dimensions, topic)
|
||||
const exploreNum = task.subject.match(/EXPLORE-(\d+)/)?.[1] || '001'
|
||||
const outputPath = `${sessionFolder}/explorations/exploration-${exploreNum}.json`
|
||||
```
|
||||
|
||||
### Step 2: Execute Exploration
|
||||
|
||||
```javascript
|
||||
Task({
|
||||
subagent_type: "cli-explore-agent",
|
||||
run_in_background: false,
|
||||
description: `Explore codebase: ${topic} (${perspective})`,
|
||||
prompt: `
|
||||
## Analysis Context
|
||||
Topic: ${topic}
|
||||
Perspective: ${perspective} — ${strategy.focus}
|
||||
Dimensions: ${dimensions.join(', ')}
|
||||
Session: ${sessionFolder}
|
||||
|
||||
## MANDATORY FIRST STEPS
|
||||
1. Run: ccw tool exec get_modules_by_depth '{}'
|
||||
2. Execute searches: ${strategy.searches.map(s => `"${s}"`).join(', ')}
|
||||
3. Run: ccw spec load --category exploration
|
||||
|
||||
## Exploration Focus (${perspective} angle)
|
||||
- **Depth**: ${strategy.depth}
|
||||
- **Focus**: ${strategy.focus}
|
||||
${dimensions.map(d => `- ${d}: Identify relevant code patterns, structures, and relationships`).join('\n')}
|
||||
|
||||
## Search Strategy
|
||||
${strategy.searches.map((s, i) => `${i + 1}. Search for: "${s}" — find related files, functions, types`).join('\n')}
|
||||
|
||||
## Additional Exploration
|
||||
- Identify entry points related to the topic
|
||||
- Map dependencies between relevant modules
|
||||
- Note any configuration or environment dependencies
|
||||
- Look for test files that reveal expected behavior
|
||||
|
||||
## Output
|
||||
Write findings to: ${outputPath}
|
||||
|
||||
Schema:
|
||||
{
|
||||
"perspective": "${perspective}",
|
||||
"relevant_files": [
|
||||
{"path": "string", "relevance": "high|medium|low", "summary": "what this file does"}
|
||||
],
|
||||
"patterns": ["pattern descriptions found in codebase"],
|
||||
"key_findings": ["important discoveries"],
|
||||
"module_map": {"module_name": ["related_files"]},
|
||||
"questions_for_analysis": ["questions that need deeper analysis"],
|
||||
"_metadata": {
|
||||
"agent": "cli-explore-agent",
|
||||
"perspective": "${perspective}",
|
||||
"search_queries": ${JSON.stringify(strategy.searches)},
|
||||
"timestamp": "ISO string"
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
```
|
||||
|
||||
### Step 3: Result Processing
|
||||
|
||||
```javascript
|
||||
// 验证输出文件
|
||||
let result = {}
|
||||
try {
|
||||
result = JSON.parse(Read(outputPath))
|
||||
} catch {
|
||||
// Fallback: ACE search
|
||||
const aceResults = mcp__ace-tool__search_context({
|
||||
project_root_path: ".",
|
||||
query: `${topic} ${perspective}`
|
||||
})
|
||||
|
||||
result = {
|
||||
perspective,
|
||||
relevant_files: [],
|
||||
patterns: [],
|
||||
key_findings: [`ACE fallback: ${aceResults?.summary || 'No results'}`],
|
||||
questions_for_analysis: [`What is the ${perspective} perspective on ${topic}?`],
|
||||
_metadata: {
|
||||
agent: 'ace-fallback',
|
||||
perspective,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
Write(outputPath, JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
// 质量验证
|
||||
const quality = {
|
||||
has_files: (result.relevant_files?.length || 0) > 0,
|
||||
has_findings: (result.key_findings?.length || 0) > 0,
|
||||
has_patterns: (result.patterns?.length || 0) > 0
|
||||
}
|
||||
|
||||
if (!quality.has_files && !quality.has_findings) {
|
||||
// 补充搜索
|
||||
const supplementary = mcp__ace-tool__search_context({
|
||||
project_root_path: ".",
|
||||
query: topic
|
||||
})
|
||||
// Merge supplementary results
|
||||
}
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
```json
|
||||
{
|
||||
"perspective": "technical",
|
||||
"relevant_files": [
|
||||
{"path": "src/auth/handler.ts", "relevance": "high", "summary": "Authentication request handler"}
|
||||
],
|
||||
"patterns": ["Repository pattern used for data access", "Middleware chain for auth"],
|
||||
"key_findings": ["JWT tokens stored in HTTP-only cookies", "Rate limiting at gateway level"],
|
||||
"module_map": {"auth": ["src/auth/handler.ts", "src/auth/middleware.ts"]},
|
||||
"questions_for_analysis": ["Is the token refresh mechanism secure?"],
|
||||
"_metadata": {"agent": "cli-explore-agent", "perspective": "technical", "timestamp": "..."}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| cli-explore-agent unavailable | Fall back to ACE search + Grep |
|
||||
| Agent produces no output file | Create minimal result with ACE fallback |
|
||||
| Agent timeout | Use partial results if available |
|
||||
| Invalid JSON output | Attempt repair, fall back to raw text extraction |
|
||||
| Session folder missing | Create directory, continue |
|
||||
@@ -1,217 +0,0 @@
|
||||
# Explorer Role
|
||||
|
||||
代码库探索者。通过 cli-explore-agent 多角度并行探索代码库,收集结构化上下文供后续分析使用。
|
||||
|
||||
## Identity
|
||||
|
||||
- **Name**: `explorer` | **Tag**: `[explorer]`
|
||||
- **Task Prefix**: `EXPLORE-*`
|
||||
- **Responsibility**: Orchestration (代码库探索编排)
|
||||
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 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
|
||||
- Share exploration results via team_msg(type='state_update')
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Available Commands
|
||||
|
||||
| Command | File | Phase | Description |
|
||||
|---------|------|-------|-------------|
|
||||
| `explore` | [commands/explore.md](commands/explore.md) | Phase 3 | cli-explore-agent 并行探索 |
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
## 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",
|
||||
session_id: <session-id>,
|
||||
from: "explorer",
|
||||
type: "exploration_ready",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
> `to` and `summary` are auto-defaulted by the tool.
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --session-id <session-id> --from explorer --type exploration_ready --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
Standard task discovery flow: TaskList -> filter by prefix `EXPLORE-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate 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
|
||||
|
||||
**Loading steps**:
|
||||
|
||||
1. Extract session path from task description
|
||||
2. Extract topic, perspective, dimensions from task metadata
|
||||
3. Read role states via team_msg(operation="get_state") for existing context
|
||||
4. Determine exploration number from task subject (EXPLORE-N)
|
||||
|
||||
**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
|
||||
|
||||
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**:
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "cli-explore-agent",
|
||||
run_in_background: false,
|
||||
description: "Explore codebase: <topic> (<perspective>)",
|
||||
prompt: `
|
||||
## Analysis Context
|
||||
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. Run: ccw spec load --category exploration
|
||||
|
||||
## Exploration Focus (<perspective> angle)
|
||||
<dimensions map to exploration focus areas>
|
||||
|
||||
## Output
|
||||
Write findings to: <session-folder>/explorations/exploration-<num>.json
|
||||
|
||||
Schema: {
|
||||
perspective: "<perspective>",
|
||||
relevant_files: [{path, relevance, summary}],
|
||||
patterns: [string],
|
||||
key_findings: [string],
|
||||
questions_for_analysis: [string],
|
||||
_metadata: {agent: "cli-explore-agent", timestamp}
|
||||
}
|
||||
`
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 4: Result Validation
|
||||
|
||||
**Validation steps**:
|
||||
|
||||
| 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):
|
||||
|
||||
```
|
||||
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
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
Standard report flow: team_msg log -> SendMessage with `[explorer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
**Shared memory update**:
|
||||
|
||||
```
|
||||
sharedMemory.explorations.push({
|
||||
id: "exploration-<num>",
|
||||
perspective: <perspective>,
|
||||
file_count: <count>,
|
||||
finding_count: <count>,
|
||||
timestamp: <timestamp>
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No EXPLORE-* tasks available | Idle, wait for coordinator assignment |
|
||||
| cli-explore-agent fails | Fall back to ACE search + Grep inline |
|
||||
| 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,255 +0,0 @@
|
||||
# Command: synthesize
|
||||
|
||||
> 跨视角整合。从所有探索、分析、讨论结果中提取主题、解决冲突、生成最终结论和建议。
|
||||
|
||||
## When to Use
|
||||
|
||||
- Phase 3 of Synthesizer
|
||||
- 所有探索、分析、讨论已完成
|
||||
- 每个 SYNTH-* 任务触发一次
|
||||
|
||||
**Trigger conditions**:
|
||||
- 讨论循环结束后(用户选择"分析完成"或达到最大轮次)
|
||||
- Quick 模式下分析完成后直接触发
|
||||
|
||||
## Strategy
|
||||
|
||||
### Delegation Mode
|
||||
|
||||
**Mode**: Inline(纯整合,不调用外部工具)
|
||||
|
||||
### Decision Logic
|
||||
|
||||
```javascript
|
||||
function buildSynthesisStrategy(explorationCount, analysisCount, discussionCount) {
|
||||
if (analysisCount <= 1 && discussionCount === 0) {
|
||||
return 'simple' // Quick mode: 单视角直接总结
|
||||
}
|
||||
if (discussionCount > 2) {
|
||||
return 'deep' // Deep mode: 多轮讨论需要追踪演进
|
||||
}
|
||||
return 'standard' // Standard: 多视角交叉整合
|
||||
}
|
||||
```
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Context Preparation
|
||||
|
||||
```javascript
|
||||
const strategy = buildSynthesisStrategy(
|
||||
allExplorations.length, allAnalyses.length, allDiscussions.length
|
||||
)
|
||||
|
||||
// 提取所有洞察
|
||||
const allInsights = allAnalyses.flatMap(a =>
|
||||
(a.key_insights || []).map(i => ({
|
||||
...(typeof i === 'string' ? { insight: i } : i),
|
||||
perspective: a.perspective
|
||||
}))
|
||||
)
|
||||
|
||||
// 提取所有发现
|
||||
const allFindings = allAnalyses.flatMap(a =>
|
||||
(a.key_findings || []).map(f => ({
|
||||
...(typeof f === 'string' ? { finding: f } : f),
|
||||
perspective: a.perspective
|
||||
}))
|
||||
)
|
||||
|
||||
// 提取所有建议
|
||||
const allRecommendations = allAnalyses.flatMap(a =>
|
||||
(a.recommendations || []).map(r => ({
|
||||
...(typeof r === 'string' ? { action: r } : r),
|
||||
perspective: a.perspective
|
||||
}))
|
||||
)
|
||||
|
||||
// 提取讨论演进
|
||||
const discussionEvolution = allDiscussions.map(d => ({
|
||||
round: d.round,
|
||||
type: d.type,
|
||||
confirmed: d.updated_understanding?.confirmed || [],
|
||||
corrected: d.updated_understanding?.corrected || [],
|
||||
new_insights: d.updated_understanding?.new_insights || []
|
||||
}))
|
||||
```
|
||||
|
||||
### Step 2: Cross-Perspective Synthesis
|
||||
|
||||
```javascript
|
||||
// 1. Theme Extraction — 跨视角共同主题
|
||||
const themes = extractThemes(allInsights)
|
||||
|
||||
// 2. Conflict Resolution — 视角间矛盾
|
||||
const conflicts = identifyConflicts(allAnalyses)
|
||||
|
||||
// 3. Evidence Consolidation — 证据汇总
|
||||
const consolidatedEvidence = consolidateEvidence(allFindings)
|
||||
|
||||
// 4. Recommendation Prioritization — 建议优先级排序
|
||||
const prioritizedRecommendations = prioritizeRecommendations(allRecommendations)
|
||||
|
||||
// 5. Decision Trail Integration — 决策追踪整合
|
||||
const decisionSummary = summarizeDecisions(decisionTrail)
|
||||
|
||||
function extractThemes(insights) {
|
||||
// 按关键词聚类,识别跨视角共同主题
|
||||
const themeMap = {}
|
||||
for (const insight of insights) {
|
||||
const text = insight.insight || insight
|
||||
// 简单聚类:相似洞察归为同一主题
|
||||
const key = text.slice(0, 30)
|
||||
if (!themeMap[key]) {
|
||||
themeMap[key] = { theme: text, perspectives: [], count: 0 }
|
||||
}
|
||||
themeMap[key].perspectives.push(insight.perspective)
|
||||
themeMap[key].count++
|
||||
}
|
||||
return Object.values(themeMap)
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, 10)
|
||||
}
|
||||
|
||||
function identifyConflicts(analyses) {
|
||||
// 识别不同视角间的矛盾发现
|
||||
const conflicts = []
|
||||
for (let i = 0; i < analyses.length; i++) {
|
||||
for (let j = i + 1; j < analyses.length; j++) {
|
||||
// 比较两个视角的发现是否矛盾
|
||||
// 实际实现中需要语义比较
|
||||
}
|
||||
}
|
||||
return conflicts
|
||||
}
|
||||
|
||||
function consolidateEvidence(findings) {
|
||||
// 去重并按文件引用聚合
|
||||
const byFile = {}
|
||||
for (const f of findings) {
|
||||
const ref = f.file_ref || f.finding
|
||||
if (!byFile[ref]) byFile[ref] = []
|
||||
byFile[ref].push(f)
|
||||
}
|
||||
return byFile
|
||||
}
|
||||
|
||||
function prioritizeRecommendations(recommendations) {
|
||||
const priorityOrder = { high: 0, medium: 1, low: 2 }
|
||||
return recommendations
|
||||
.sort((a, b) => (priorityOrder[a.priority] || 2) - (priorityOrder[b.priority] || 2))
|
||||
.slice(0, 10)
|
||||
}
|
||||
|
||||
function summarizeDecisions(trail) {
|
||||
return trail.map(d => ({
|
||||
round: d.round,
|
||||
decision: d.decision,
|
||||
context: d.context,
|
||||
impact: d.impact || 'Shaped analysis direction'
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Build Conclusions
|
||||
|
||||
```javascript
|
||||
const conclusions = {
|
||||
session_id: sessionFolder.split('/').pop(),
|
||||
topic,
|
||||
completed: new Date().toISOString(),
|
||||
total_rounds: allDiscussions.length,
|
||||
strategy_used: strategy,
|
||||
|
||||
summary: generateSummary(themes, allFindings, allDiscussions),
|
||||
|
||||
key_conclusions: themes.slice(0, 7).map(t => ({
|
||||
point: t.theme,
|
||||
evidence: t.perspectives.join(', ') + ' perspectives',
|
||||
confidence: t.count >= 3 ? 'high' : t.count >= 2 ? 'medium' : 'low'
|
||||
})),
|
||||
|
||||
recommendations: prioritizedRecommendations.map(r => ({
|
||||
action: r.action,
|
||||
rationale: r.rationale || 'Based on analysis findings',
|
||||
priority: r.priority || 'medium',
|
||||
source_perspective: r.perspective
|
||||
})),
|
||||
|
||||
open_questions: allAnalyses
|
||||
.flatMap(a => a.open_questions || [])
|
||||
.filter((q, i, arr) => arr.indexOf(q) === i)
|
||||
.slice(0, 5),
|
||||
|
||||
follow_up_suggestions: generateFollowUps(conclusions),
|
||||
|
||||
decision_trail: decisionSummary,
|
||||
|
||||
cross_perspective_synthesis: {
|
||||
convergent_themes: themes.filter(t => t.perspectives.length > 1),
|
||||
conflicts_resolved: conflicts,
|
||||
unique_contributions: allAnalyses.map(a => ({
|
||||
perspective: a.perspective,
|
||||
unique_insights: (a.key_insights || []).slice(0, 2)
|
||||
}))
|
||||
},
|
||||
|
||||
_metadata: {
|
||||
explorations: allExplorations.length,
|
||||
analyses: allAnalyses.length,
|
||||
discussions: allDiscussions.length,
|
||||
decisions: decisionTrail.length,
|
||||
synthesis_strategy: strategy
|
||||
}
|
||||
}
|
||||
|
||||
function generateSummary(themes, findings, discussions) {
|
||||
const topThemes = themes.slice(0, 3).map(t => t.theme).join('; ')
|
||||
const roundCount = discussions.length
|
||||
return `Analysis of "${topic}" identified ${themes.length} key themes across ${allAnalyses.length} perspective(s) and ${roundCount} discussion round(s). Top themes: ${topThemes}`
|
||||
}
|
||||
|
||||
function generateFollowUps(conclusions) {
|
||||
const suggestions = []
|
||||
if ((conclusions.open_questions || []).length > 2) {
|
||||
suggestions.push({ type: 'deeper-analysis', summary: 'Further analysis needed for open questions' })
|
||||
}
|
||||
if ((conclusions.recommendations || []).some(r => r.priority === 'high')) {
|
||||
suggestions.push({ type: 'issue-creation', summary: 'Create issues for high-priority recommendations' })
|
||||
}
|
||||
suggestions.push({ type: 'implementation-plan', summary: 'Generate implementation plan from recommendations' })
|
||||
return suggestions
|
||||
}
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "UAN-auth-analysis-2026-02-18",
|
||||
"topic": "认证架构优化",
|
||||
"completed": "2026-02-18T...",
|
||||
"total_rounds": 2,
|
||||
"summary": "Analysis identified 5 key themes...",
|
||||
"key_conclusions": [
|
||||
{"point": "JWT stateless approach is sound", "evidence": "technical, architectural", "confidence": "high"}
|
||||
],
|
||||
"recommendations": [
|
||||
{"action": "Add rate limiting", "rationale": "Prevent brute force", "priority": "high"}
|
||||
],
|
||||
"open_questions": ["Token rotation strategy?"],
|
||||
"decision_trail": [
|
||||
{"round": 1, "decision": "Focus on security", "context": "User preference"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No analyses available | Synthesize from explorations only |
|
||||
| Single perspective only | Generate focused synthesis without cross-perspective |
|
||||
| Irreconcilable conflicts | Present both sides with trade-off analysis |
|
||||
| Empty discussion rounds | Skip discussion evolution, focus on analysis results |
|
||||
| Shared memory corrupted | Rebuild from individual JSON files |
|
||||
@@ -1,249 +0,0 @@
|
||||
# Synthesizer Role
|
||||
|
||||
综合整合者。跨视角整合所有探索、分析、讨论结果,生成最终结论、建议和决策追踪。
|
||||
|
||||
## Identity
|
||||
|
||||
- **Name**: `synthesizer` | **Tag**: `[synthesizer]`
|
||||
- **Task Prefix**: `SYNTH-*`
|
||||
- **Responsibility**: Read-only analysis (综合结论)
|
||||
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 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
|
||||
- Share synthesis results via team_msg(type='state_update')
|
||||
- Update discussion.md conclusions section
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Available Commands
|
||||
|
||||
| Command | File | Phase | Description |
|
||||
|---------|------|-------|-------------|
|
||||
| `synthesize` | [commands/synthesize.md](commands/synthesize.md) | Phase 3 | 跨视角整合 |
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| 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 |
|
||||
|
||||
> Synthesizer does not use subagents or CLI tools (pure integration role).
|
||||
|
||||
---
|
||||
|
||||
## 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",
|
||||
session_id: <session-id>,
|
||||
from: "synthesizer",
|
||||
type: "synthesis_ready",
|
||||
ref: "<output-path>"
|
||||
})
|
||||
```
|
||||
|
||||
> `to` and `summary` are auto-defaulted by the tool.
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --session-id <session-id> --from synthesizer --type synthesis_ready --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
Standard task discovery flow: TaskList -> filter by prefix `SYNTH-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
Falls back to `synthesizer` for single-instance role.
|
||||
|
||||
### Phase 2: Context Loading + Shared Memory Read
|
||||
|
||||
**Loading steps**:
|
||||
|
||||
1. Extract session path from task description
|
||||
2. Extract topic
|
||||
3. Read role states via team_msg(operation="get_state")
|
||||
4. Read all exploration files
|
||||
5. Read all analysis files
|
||||
6. Read all discussion round files
|
||||
7. Extract decision trail and current understanding
|
||||
|
||||
**Context extraction**:
|
||||
|
||||
| Field | Source | Pattern |
|
||||
|-------|--------|---------|
|
||||
| sessionFolder | task description | `session:\s*(.+)` |
|
||||
| topic | task description | `topic:\s*(.+)` |
|
||||
|
||||
**File loading**:
|
||||
|
||||
| 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
|
||||
|
||||
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
|
||||
|
||||
**Output paths**:
|
||||
|
||||
| File | Path |
|
||||
|------|------|
|
||||
| Conclusions | `<session-folder>/conclusions.json` |
|
||||
| Discussion update | `<session-folder>/discussion.md` |
|
||||
|
||||
**discussion.md conclusions section**:
|
||||
|
||||
```markdown
|
||||
## Conclusions
|
||||
|
||||
### Summary
|
||||
<conclusions.summary>
|
||||
|
||||
### Key Conclusions
|
||||
1. **<point>** (Confidence: <confidence>)
|
||||
- Evidence: <evidence>
|
||||
2. ...
|
||||
|
||||
### Recommendations
|
||||
1. **[<priority>]** <action>
|
||||
- Rationale: <rationale>
|
||||
2. ...
|
||||
|
||||
### Remaining Questions
|
||||
- <question 1>
|
||||
- <question 2>
|
||||
|
||||
## Decision Trail
|
||||
|
||||
### Critical Decisions
|
||||
- **Round N**: <decision> — <context>
|
||||
|
||||
## Current Understanding (Final)
|
||||
|
||||
### What We Established
|
||||
- <established item 1>
|
||||
- <established item 2>
|
||||
|
||||
### What Was Clarified/Corrected
|
||||
- <clarified item 1>
|
||||
- <clarified item 2>
|
||||
|
||||
### Key Insights
|
||||
- <insight 1>
|
||||
- <insight 2>
|
||||
|
||||
## Session Statistics
|
||||
- **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
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
Standard report flow: team_msg log -> SendMessage with `[synthesizer]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
**Shared memory update**:
|
||||
|
||||
```
|
||||
sharedMemory.synthesis = {
|
||||
conclusion_count: <count>,
|
||||
recommendation_count: <count>,
|
||||
open_question_count: <count>,
|
||||
timestamp: <timestamp>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No SYNTH-* tasks | Idle, wait for assignment |
|
||||
| No analyses/discussions found | Synthesize from explorations only |
|
||||
| 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