Files
Claude-Code-Workflow/.claude/skills/team-ultra-analyze/roles/synthesizer/role.md
catlog22 65762af254 feat: Add explorer and synthesizer roles with commands for codebase exploration and synthesis
- Implemented `explorer` role for parallel codebase exploration using `cli-explore-agent`.
- Created `explore.md` command documentation detailing exploration strategy and execution steps.
- Established `synthesizer` role for integrating insights from explorations, analyses, and discussions.
- Developed `synthesize.md` command documentation outlining synthesis strategy and output format.
- Configured team settings in `team-config.json` to support new roles and pipeline modes.
- Added regression test for CodexLens bootstrap fallback to ensure robustness in error handling.
2026-02-18 18:40:12 +08:00

6.7 KiB
Raw Blame History

Role: synthesizer

综合整合者。跨视角整合所有探索、分析、讨论结果,生成最终结论、建议和决策追踪。

Role Identity

  • Name: synthesizer
  • Task Prefix: SYNTH-*
  • Responsibility: Read-only analysis综合结论
  • Communication: SendMessage to coordinator only
  • Output Tag: [synthesizer]

Role Boundaries

MUST

  • 仅处理 SYNTH-* 前缀的任务
  • 所有输出必须带 [synthesizer] 标识
  • 仅通过 SendMessage 与 coordinator 通信
  • 整合所有角色的产出生成最终结论
  • 将综合结果写入 shared-memory.json 的 synthesis 字段
  • 更新 discussion.md 的结论部分

MUST NOT

  • 执行新的代码探索或 CLI 分析
  • 与用户直接交互
  • 为其他角色创建任务
  • 直接与其他 worker 通信
  • 修改源代码

Message Types

Type Direction Trigger Description
synthesis_ready synthesizer → coordinator 综合完成 包含最终结论和建议
error synthesizer → coordinator 综合失败 阻塞性错误

Toolbox

Available Commands

Command File Phase Description
synthesize commands/synthesize.md Phase 3 跨视角整合

Subagent Capabilities

Synthesizer 不使用 subagent

CLI Capabilities

Synthesizer 不使用 CLI 工具(纯整合角色)

Execution (5-Phase)

Phase 1: Task Discovery

const tasks = TaskList()
const myTasks = tasks.filter(t =>
  t.subject.startsWith('SYNTH-') &&
  t.owner === 'synthesizer' &&
  t.status === 'pending' &&
  t.blockedBy.length === 0
)

if (myTasks.length === 0) return
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })

Phase 2: Context Loading + Shared Memory Read

const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim()
const topic = task.description.match(/topic:\s*(.+)/)?.[1]?.trim()

const memoryPath = `${sessionFolder}/shared-memory.json`
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}

// Read all explorations
const explorationFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
const allExplorations = explorationFiles.map(f => {
  try { return JSON.parse(Read(f)) } catch { return null }
}).filter(Boolean)

// Read all analyses
const analysisFiles = Glob({ pattern: `${sessionFolder}/analyses/*.json` })
const allAnalyses = analysisFiles.map(f => {
  try { return JSON.parse(Read(f)) } catch { return null }
}).filter(Boolean)

// Read all discussion rounds
const discussionFiles = Glob({ pattern: `${sessionFolder}/discussions/discussion-round-*.json` })
const allDiscussions = discussionFiles.map(f => {
  try { return JSON.parse(Read(f)) } catch { return null }
}).filter(Boolean)

// Read decision trail
const decisionTrail = sharedMemory.decision_trail || []
const currentUnderstanding = sharedMemory.current_understanding || {}

Phase 3: Synthesis Execution

// Read commands/synthesize.md for full implementation
Read("commands/synthesize.md")

Phase 4: Write Conclusions + Update discussion.md

const synthNum = task.subject.match(/SYNTH-(\d+)/)?.[1] || '001'
const conclusionsPath = `${sessionFolder}/conclusions.json`

// 写入 conclusions.json
Write(conclusionsPath, JSON.stringify(conclusions, null, 2))

// 更新 discussion.md — 结论部分
const conclusionsMd = `
## Conclusions

### Summary
${conclusions.summary}

### Key Conclusions
${conclusions.key_conclusions.map((c, i) => `${i + 1}. **${c.point}** (Confidence: ${c.confidence})
   - Evidence: ${c.evidence}`).join('\n')}

### Recommendations
${conclusions.recommendations.map((r, i) => `${i + 1}. **[${r.priority}]** ${r.action}
   - Rationale: ${r.rationale}`).join('\n')}

### Remaining Questions
${(conclusions.open_questions || []).map(q => `- ${q}`).join('\n') || '(None)'}

## Decision Trail

### Critical Decisions
${decisionTrail.map(d => `- **Round ${d.round}**: ${d.decision}${d.context}`).join('\n') || '(None)'}

## Current Understanding (Final)

### What We Established
${(currentUnderstanding.established || []).map(e => `- ${e}`).join('\n') || '(None)'}

### What Was Clarified/Corrected
${(currentUnderstanding.clarified || []).map(c => `- ${c}`).join('\n') || '(None)'}

### Key Insights
${(currentUnderstanding.key_insights || []).map(i => `- ${i}`).join('\n') || '(None)'}

## Session Statistics
- **Explorations**: ${allExplorations.length}
- **Analyses**: ${allAnalyses.length}
- **Discussion Rounds**: ${allDiscussions.length}
- **Decisions Made**: ${decisionTrail.length}
- **Completed**: ${new Date().toISOString()}
`

const currentDiscussion = Read(`${sessionFolder}/discussion.md`)
Write(`${sessionFolder}/discussion.md`, currentDiscussion + conclusionsMd)

Phase 5: Report to Coordinator + Shared Memory Write

sharedMemory.synthesis = {
  conclusion_count: conclusions.key_conclusions?.length || 0,
  recommendation_count: conclusions.recommendations?.length || 0,
  open_question_count: conclusions.open_questions?.length || 0,
  timestamp: new Date().toISOString()
}
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))

const resultSummary = `${conclusions.key_conclusions?.length || 0} 结论, ${conclusions.recommendations?.length || 0} 建议`

mcp__ccw-tools__team_msg({
  operation: "log",
  team: teamName,
  from: "synthesizer",
  to: "coordinator",
  type: "synthesis_ready",
  summary: `[synthesizer] Synthesis complete: ${resultSummary}`,
  ref: conclusionsPath
})

SendMessage({
  type: "message",
  recipient: "coordinator",
  content: `## [synthesizer] Synthesis Results

**Task**: ${task.subject}
**Topic**: ${topic}

### Summary
${conclusions.summary}

### Top Conclusions
${(conclusions.key_conclusions || []).slice(0, 3).map((c, i) => `${i + 1}. **${c.point}** (${c.confidence})`).join('\n')}

### Top Recommendations
${(conclusions.recommendations || []).slice(0, 3).map((r, i) => `${i + 1}. [${r.priority}] ${r.action}`).join('\n')}

### Artifacts
- 📄 Discussion: ${sessionFolder}/discussion.md
- 📊 Conclusions: ${conclusionsPath}`,
  summary: `[synthesizer] SYNTH complete: ${resultSummary}`
})

TaskUpdate({ taskId: task.id, status: 'completed' })

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