feat(skills): update 12 team skills to v3 design patterns

- Update all 12 team-* SKILL.md files with v3 structure:
  - Replace JS pseudocode with text decision tables
  - Add Role Registry with Compact column
  - Add COMPACT PROTECTION blocks
  - Add Cadence Control sections
  - Add Wisdom Accumulation sections
  - Add Task Metadata Registry
  - Add Orchestration Mode user commands

- Update 58 role files (SKILL.md + roles/*):
  - Flat-file skills: team-brainstorm, team-issue, team-testing,
    team-uidesign, team-planex, team-iterdev
  - Folder-based skills: team-review, team-roadmap-dev, team-frontend,
    team-quality-assurance, team-tech-debt, team-ultra-analyze

- Preserve special architectures:
  - team-planex: 2-member (planner + executor only)
  - team-tech-debt: Stop-Wait strategy (run_in_background:false)
  - team-iterdev: 7 behavior protocol tables in coordinator

- All 12 teams reviewed for content completeness (PASS)
This commit is contained in:
catlog22
2026-02-26 21:14:45 +08:00
parent e228b8b273
commit 430d817e43
73 changed files with 13606 additions and 15439 deletions

View File

@@ -1,40 +1,35 @@
# Role: discussant
# Discussant Role
讨论处理者。根据 coordinator 传递的用户反馈,执行方向调整、深入探索或补充分析,更新讨论时间线。
## Role Identity
## Identity
- **Name**: `discussant`
- **Name**: `discussant` | **Tag**: `[discussant]`
- **Task Prefix**: `DISCUSS-*`
- **Responsibility**: Analysis + Exploration讨论处理
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[discussant]`
- **Responsibility**: Analysis + Exploration (讨论处理)
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `DISCUSS-*` 前缀的任务
- 所有输出必须带 `[discussant]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 基于用户反馈和已有分析结果执行深入探索
- 将讨论结果写入 shared-memory.json 的 `discussions` 字段
- 更新 discussion.md 的讨论时间线
- Only process `DISCUSS-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[discussant]` identifier
- Only communicate with coordinator via SendMessage
- Work strictly within discussion processing responsibility scope
- Execute deep exploration based on user feedback and existing analysis
- Write discussion results to shared-memory.json `discussions` field
- Update discussion.md discussion timeline
### MUST NOT
- ❌ 直接与用户交互(AskUserQuestion coordinator 驱动)
- ❌ 生成最终结论(属于 synthesizer
- ❌ 为其他角色创建任务
- ❌ 直接与其他 worker 通信
- ❌ 修改源代码
- Interact directly with user (AskUserQuestion is coordinator-driven)
- Generate final conclusions (belongs to synthesizer)
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
- Communicate directly with other worker roles
- Modify source code
- Omit `[discussant]` identifier in any output
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `discussion_processed` | discussant → coordinator | 讨论处理完成 | 包含更新的理解和新发现 |
| `error` | discussant → coordinator | 处理失败 | 阻塞性错误 |
---
## Toolbox
@@ -44,223 +39,179 @@
|---------|------|-------|-------------|
| `deepen` | [commands/deepen.md](commands/deepen.md) | Phase 3 | 深入探索与补充分析 |
### Subagent Capabilities
### Tool Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `cli-explore-agent` | deepen.md | 针对性代码库探索 |
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `Task` | Subagent | deepen.md | Spawn cli-explore-agent for targeted exploration |
| `Bash` | CLI | deepen.md | Execute ccw cli for deep analysis |
| `Read` | File | discussant | Read analysis results and session context |
| `Write` | File | discussant | Write discussion results |
| `Glob` | File | discussant | Find analysis/exploration files |
### CLI Capabilities
### CLI Tools
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | deepen.md | 深入分析 |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `discussion_processed` | discussant → coordinator | 讨论处理完成 | 包含更新的理解和新发现 |
| `error` | discussant → coordinator | 处理失败 | 阻塞性错误 |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: "ultra-analyze",
from: "discussant",
to: "coordinator",
type: "discussion_processed",
summary: "[discussant] DISCUSS complete: <summary>",
ref: "<output-path>"
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team ultra-analyze --from discussant --to coordinator --type discussion_processed --summary \"[discussant] ...\" --ref <path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('DISCUSS-') &&
t.owner === 'discussant' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
Standard task discovery flow: TaskList -> filter by prefix `DISCUSS-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Falls back to `discussant` for single-instance role.
### Phase 2: Context Loading
```javascript
// 从任务描述中提取上下文
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim()
const topic = task.description.match(/topic:\s*(.+)/)?.[1]?.trim()
const round = parseInt(task.description.match(/round:\s*(\d+)/)?.[1] || '1')
const discussType = task.description.match(/type:\s*(.+)/)?.[1]?.trim() || 'initial'
const userFeedback = task.description.match(/user_feedback:\s*(.+)/)?.[1]?.trim() || ''
**Loading steps**:
// 读取 shared memory
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
1. Extract session path from task description
2. Extract topic, round number, discussion type, user feedback
3. Read shared-memory.json for existing context
4. Read all analysis results
5. Read all exploration results
6. Aggregate current findings, insights, questions
// 读取已有分析结果
const analysisFiles = Glob({ pattern: `${sessionFolder}/analyses/*.json` })
const allAnalyses = analysisFiles.map(f => {
try { return JSON.parse(Read(f)) } catch { return null }
}).filter(Boolean)
**Context extraction**:
// 读取已有探索结果
const explorationFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
const allExplorations = explorationFiles.map(f => {
try { return JSON.parse(Read(f)) } catch { return null }
}).filter(Boolean)
| Field | Source | Pattern |
|-------|--------|---------|
| sessionFolder | task description | `session:\s*(.+)` |
| topic | task description | `topic:\s*(.+)` |
| round | task description | `round:\s*(\d+)` or default 1 |
| discussType | task description | `type:\s*(.+)` or default "initial" |
| userFeedback | task description | `user_feedback:\s*(.+)` or empty |
// 聚合当前理解
const currentFindings = allAnalyses.flatMap(a => a.key_findings || [])
const currentInsights = allAnalyses.flatMap(a => a.key_insights || [])
const openQuestions = allAnalyses.flatMap(a => a.open_questions || [])
const discussionPoints = allAnalyses.flatMap(a => a.discussion_points || [])
```
**Discussion types**:
| Type | Description |
|------|-------------|
| initial | 首轮讨论:汇总所有分析结果,生成讨论摘要 |
| deepen | 继续深入:在当前方向上进一步探索 |
| direction-adjusted | 方向调整:基于新方向重新组织发现 |
| specific-questions | 具体问题:针对用户问题进行分析 |
### Phase 3: Discussion Processing
```javascript
// Read commands/deepen.md for full implementation
Read("commands/deepen.md")
```
Delegate to `commands/deepen.md` if available, otherwise execute inline.
**根据 discussType 选择处理策略**:
**Processing by discussion type**:
```javascript
const discussNum = task.subject.match(/DISCUSS-(\d+)/)?.[1] || '001'
const outputPath = `${sessionFolder}/discussions/discussion-round-${discussNum}.json`
| Type | Strategy |
|------|----------|
| initial | Aggregate all analysis results, generate discussion summary with confirmed/corrected/new insights |
| deepen | Focus on current direction, explore deeper with cli-explore-agent |
| direction-adjusted | Re-organize findings around new focus, identify new patterns |
| specific-questions | Targeted analysis addressing user's specific questions |
switch (discussType) {
case 'initial':
// 首轮讨论:汇总所有分析结果,生成讨论摘要
processInitialDiscussion()
break
**Round content structure**:
case 'deepen':
// 继续深入:在当前方向上进一步探索
processDeepenDiscussion()
break
case 'direction-adjusted':
// 方向调整:基于新方向重新组织发现
processDirectionAdjusted()
break
case 'specific-questions':
// 具体问题:针对用户问题进行分析
processSpecificQuestions()
break
}
```
| Field | Description |
|-------|-------------|
| round | Discussion round number |
| type | Discussion type |
| user_feedback | User input (if any) |
| updated_understanding | confirmed, corrected, new_insights arrays |
| new_findings | New discoveries |
| new_questions | Open questions |
| timestamp | ISO timestamp |
### Phase 4: Update Discussion Timeline
```javascript
// 构建讨论轮次内容
const roundContent = {
round,
type: discussType,
user_feedback: userFeedback,
updated_understanding: {
confirmed: [], // 确认的假设
corrected: [], // 纠正的假设
new_insights: [] // 新发现
},
new_findings: [],
new_questions: [],
timestamp: new Date().toISOString()
}
**Output path**: `<session-folder>/discussions/discussion-round-<num>.json`
Write(outputPath, JSON.stringify(roundContent, null, 2))
**discussion.md update template**:
// 更新 discussion.md
const discussionMdContent = `
### Round ${round + 1} - Discussion (${new Date().toISOString()})
```markdown
### Round <N> - Discussion (<timestamp>)
#### Type
${discussType}
<discussType>
#### User Input
${userFeedback || '(Initial discussion round)'}
<userFeedback or "(Initial discussion round)">
#### Updated Understanding
${roundContent.updated_understanding.confirmed.length > 0
? `**Confirmed**: ${roundContent.updated_understanding.confirmed.map(c => `\n- ✅ ${c}`).join('')}` : ''}
${roundContent.updated_understanding.corrected.length > 0
? `**Corrected**: ${roundContent.updated_understanding.corrected.map(c => `\n- 🔄 ${c}`).join('')}` : ''}
${roundContent.updated_understanding.new_insights.length > 0
? `**New Insights**: ${roundContent.updated_understanding.new_insights.map(i => `\n- 💡 ${i}`).join('')}` : ''}
**Confirmed**: <list of confirmed assumptions>
**Corrected**: <list of corrected assumptions>
**New Insights**: <list of new insights>
#### New Findings
${(roundContent.new_findings || []).map(f => `- ${f}`).join('\n') || '(None)'}
<list of new findings or "(None)">
#### Open Questions
${(roundContent.new_questions || []).map(q => `- ${q}`).join('\n') || '(None)'}
`
const currentDiscussion = Read(`${sessionFolder}/discussion.md`)
Write(`${sessionFolder}/discussion.md`, currentDiscussion + discussionMdContent)
<list of open questions or "(None)">
```
**Update steps**:
1. Write round content JSON to discussions folder
2. Read current discussion.md
3. Append new round section
4. Write updated discussion.md
### Phase 5: Report to Coordinator
```javascript
// 更新 shared memory
sharedMemory.discussions = sharedMemory.discussions || []
sharedMemory.discussions.push({
id: `discussion-round-${discussNum}`,
round,
type: discussType,
new_insight_count: roundContent.updated_understanding.new_insights?.length || 0,
corrected_count: roundContent.updated_understanding.corrected?.length || 0,
timestamp: new Date().toISOString()
})
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
// 更新 current_understanding
sharedMemory.current_understanding = sharedMemory.current_understanding || { established: [], clarified: [], key_insights: [] }
sharedMemory.current_understanding.established.push(...(roundContent.updated_understanding.confirmed || []))
sharedMemory.current_understanding.clarified.push(...(roundContent.updated_understanding.corrected || []))
sharedMemory.current_understanding.key_insights.push(...(roundContent.updated_understanding.new_insights || []))
Standard report flow: team_msg log -> SendMessage with `[discussant]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
**Shared memory update**:
const resultSummary = `Round ${round}: ${roundContent.updated_understanding.new_insights?.length || 0} 新洞察, ${roundContent.updated_understanding.corrected?.length || 0} 纠正`
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "discussant",
to: "coordinator",
type: "discussion_processed",
summary: `[discussant] ${resultSummary}`,
ref: outputPath
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [discussant] Discussion Round ${round} Results
**Task**: ${task.subject}
**Type**: ${discussType}
### Summary
${resultSummary}
### Key Updates
${roundContent.updated_understanding.new_insights?.slice(0, 3).map(i => `- 💡 ${i}`).join('\n') || '(No new insights)'}
${roundContent.updated_understanding.corrected?.slice(0, 3).map(c => `- 🔄 ${c}`).join('\n') || ''}
### Output
${outputPath}`,
summary: `[discussant] DISCUSS complete: ${resultSummary}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('DISCUSS-') &&
t.owner === 'discussant' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
sharedMemory.discussions.push({
id: "discussion-round-<num>",
round: <round>,
type: <discussType>,
new_insight_count: <count>,
corrected_count: <count>,
timestamp: <timestamp>
})
// Update current_understanding
sharedMemory.current_understanding.established += confirmed
sharedMemory.current_understanding.clarified += corrected
sharedMemory.current_understanding.key_insights += new_insights
```
---
## Error Handling
@@ -271,3 +222,4 @@ if (nextTasks.length > 0) {
| CLI tool unavailable | Use existing analysis results for discussion |
| User feedback unclear | Process as 'deepen' type, note ambiguity |
| Session folder missing | Error to coordinator |
| Command file not found | Fall back to inline execution |