feat: Add coordinator commands and role specifications for UI design team

- Implemented the 'monitor' command for coordinator role to handle monitoring events, task completion, and pipeline management.
- Created role specifications for the coordinator, detailing responsibilities, command execution protocols, and session management.
- Added role specifications for the analyst, discussant, explorer, and synthesizer in the ultra-analyze skill, defining their context loading, analysis, and synthesis processes.
This commit is contained in:
catlog22
2026-03-03 23:35:41 +08:00
parent a7ed0365f7
commit 26bda9c634
188 changed files with 9332 additions and 3512 deletions

View File

@@ -82,7 +82,7 @@ if (mode === 'direct') {
Bash(`ccw cli -p "PURPOSE: Perform deep quality analysis on QA results to identify defect patterns, coverage trends, and improvement opportunities
TASK: • Classify defects by root cause pattern (logic errors, integration issues, missing validation, etc.) • Identify files with highest defect density • Analyze coverage gaps vs risk levels • Compare actual coverage to targets • Generate actionable improvement recommendations
MODE: analysis
CONTEXT: @${sessionFolder}/shared-memory.json @${sessionFolder}/results/**/*
CONTEXT: @${sessionFolder}/.msg/meta.json @${sessionFolder}/results/**/*
EXPECTED: Structured analysis with: defect pattern taxonomy, risk-coverage matrix, quality score rationale, top 5 improvement recommendations with expected impact
CONSTRAINTS: Be data-driven, avoid speculation without evidence" --tool gemini --mode analysis --rule analysis-analyze-code-patterns`, {
run_in_background: true
@@ -277,7 +277,7 @@ sharedMemory.coverage_history.push({
quality_score: analysis.quality_score,
issues: analysis.defect_patterns.total
})
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
Write(`${sessionFolder}/.msg/meta.json`, JSON.stringify(sharedMemory, null, 2))
function generateReportMarkdown(analysis) {
return `# Quality Assurance Report

View File

@@ -56,24 +56,21 @@ Quality analyst. Analyze defect patterns, coverage gaps, test effectiveness, and
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
**NOTE**: `team` must be **session ID** (e.g., `TQA-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "TQA-project-2026-02-27", NOT "quality-assurance"
session_id: <session-id>,
from: "analyst",
to: "coordinator",
type: <message-type>,
summary: "[analyst] quality score: <score>/100, defect patterns: <count>, coverage: <coverage>%",
ref: <report-path>
data: { ref: <report-path> }
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <session-id> --from analyst --to coordinator --type <message-type> --summary \"[analyst] analysis complete\" --ref <report-path> --json")
Bash("ccw team log --session-id <session-id> --from analyst --type <message-type> --json")
```
---
@@ -95,7 +92,7 @@ Standard task discovery flow: TaskList -> filter by prefix `QAANA-*` + owner mat
| Input | Source | Required |
|-------|--------|----------|
| Shared memory | <session-folder>/shared-memory.json | Yes |
| Shared memory | <session-folder>/.msg/meta.json | Yes |
| Discovered issues | sharedMemory.discovered_issues | No |
| Test strategy | sharedMemory.test_strategy | No |
| Generated tests | sharedMemory.generated_tests | No |

View File

@@ -2,7 +2,6 @@
> 任务链创建与依赖管理。根据 QA 模式创建 pipeline 任务链并分配给 worker 角色。
**NOTE**: `teamName` variable must be **session ID** (e.g., `TQA-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
## When to Use
@@ -114,9 +113,8 @@ const chainValid = chainTasks.length === pipeline.length
if (!chainValid) {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
operation: "log", session_id: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] 任务链创建不完整: ${chainTasks.length}/${pipeline.length}`
})
}
```

View File

@@ -2,7 +2,6 @@
> 阶段驱动的协调循环。按 pipeline 阶段顺序等待 worker 完成,路由消息,触发 GC 循环,执行质量门控。
**NOTE**: `teamName` variable must be **session ID** (e.g., `TQA-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
## When to Use
@@ -77,7 +76,7 @@ const autoYes = /\b(-y|--yes)\b/.test(args)
```javascript
// 从 shared memory 获取覆盖率目标
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const sharedMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
const strategy = sharedMemory.test_strategy || {}
const coverageTargets = {}
for (const layer of (strategy.layers || [])) {
@@ -108,9 +107,7 @@ for (const stageTask of pipelineTasks) {
if (!workerConfig) {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] 未知阶段前缀: ${stagePrefix},跳过`
operation: "log", session_id: teamName, from: "coordinator",
})
continue
}
@@ -119,36 +116,31 @@ for (const stageTask of pipelineTasks) {
TaskUpdate({ taskId: stageTask.id, status: 'in_progress' })
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
operation: "log", session_id: teamName, 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: "general-purpose",
subagent_type: "team-worker",
description: `Spawn ${workerConfig.role} worker for ${stageTask.subject}`,
team_name: teamName,
name: workerConfig.role,
prompt: `你是 team "${teamName}" 的 ${workerConfig.role.toUpperCase()}
prompt: `## Role Assignment
role: ${workerConfig.role}
role_spec: .claude/skills/team-quality-assurance/role-specs/${workerConfig.role}.md
session: ${sessionFolder}
session_id: ${sessionId}
team_name: ${teamName}
requirement: ${stageTask.description || taskDescription}
inner_loop: false
## ⚠️ 首要指令MUST
Skill(skill="team-quality-assurance", args="${workerConfig.skillArgs}")
## Current Task
- Task ID: ${stageTask.id}
- Task: ${stageTask.subject}
## 当前任务
- 任务 ID: ${stageTask.id}
- 任务: ${stageTask.subject}
- 描述: ${stageTask.description || taskDescription}
- Session: ${sessionFolder}
## 角色准则(强制)
- 所有输出必须带 [${workerConfig.role}] 标识前缀
- 仅与 coordinator 通信
## 工作流程
1. Skill(skill="team-quality-assurance", args="${workerConfig.skillArgs}") 获取角色定义
2. 执行任务 → 汇报结果
3. TaskUpdate({ taskId: "${stageTask.id}", status: "completed" })`,
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
})
@@ -159,9 +151,8 @@ Skill(skill="team-quality-assurance", args="${workerConfig.skillArgs}")
// Worker 返回但未标记 completed → 异常处理
if (autoYes) {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 未完成,自动跳过`
operation: "log", session_id: teamName, from: "coordinator",
type: "error",
})
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue
@@ -186,24 +177,21 @@ Skill(skill="team-quality-assurance", args="${workerConfig.skillArgs}")
continue
} else if (answer === "终止") {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
operation: "log", session_id: teamName, from: "coordinator",
to: "user", type: "shutdown",
summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}`
})
break
}
// 重试: continue to next iteration will re-process if logic wraps
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 阶段完成: ${stageTask.subject}`
operation: "log", session_id: teamName, from: "coordinator",
})
}
// 5. 阶段间检查QARUN 阶段检查覆盖率,决定 GC 循环)
if (stagePrefix === 'QARUN') {
const latestMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const latestMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
const coverage = latestMemory.execution_results?.coverage || 0
const targetLayer = stageTask.metadata?.layer || 'L1'
const target = coverageTargets[targetLayer] || 80
@@ -211,9 +199,8 @@ Skill(skill="team-quality-assurance", args="${workerConfig.skillArgs}")
if (coverage < target && gcIteration < MAX_GC_ITERATIONS) {
gcIteration++
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
operation: "log", session_id: teamName, from: "coordinator",
to: "generator", type: "gc_loop_trigger",
summary: `[coordinator] GC循环 #${gcIteration}: 覆盖率 ${coverage}% < ${target}%,请修复`
})
// 创建 GC 修复任务追加到 pipeline
}
@@ -247,16 +234,15 @@ function processMessage(msg, handler) {
case 'quality_gate': {
// 重新读取最新 shared memory
const latestMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const latestMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
const qualityScore = latestMemory.quality_score || 0
let status = 'PASS'
if (qualityScore < 60) status = 'FAIL'
else if (qualityScore < 80) status = 'CONDITIONAL'
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
operation: "log", session_id: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 质量门控: ${status} (score: ${qualityScore})`
})
break
}
@@ -266,7 +252,6 @@ function processMessage(msg, handler) {
if (severity === 'critical') {
SendMessage({
content: `## [coordinator] Critical Error from ${msg.from}\n\n${msg.summary}`,
summary: `[coordinator] Critical error: ${msg.summary}`
})
}
break
@@ -278,17 +263,13 @@ function handleGCDecision(coverage, targetLayer) {
if (gcIteration < MAX_GC_ITERATIONS) {
gcIteration++
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "generator", type: "gc_loop_trigger",
summary: `[coordinator] GC循环 #${gcIteration}: 覆盖率 ${coverage}% 未达标,请修复`,
operation: "log", session_id: teamName, from: "coordinator",
data: { iteration: gcIteration, layer: targetLayer, coverage }
})
// 创建 GC 修复任务(参见 dispatch.md createGCLoopTasks
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] GC循环已达上限(${MAX_GC_ITERATIONS}),接受当前覆盖率 ${coverage}%`
operation: "log", session_id: teamName, from: "coordinator",
})
}
}
@@ -298,7 +279,7 @@ function handleGCDecision(coverage, targetLayer) {
```javascript
// 汇总所有结果
const finalSharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const finalSharedMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
const allFinalTasks = TaskList()
const workerTasks = allFinalTasks.filter(t => t.owner && t.owner !== 'coordinator')
const summary = {

View File

@@ -26,18 +26,56 @@ Orchestrate the Quality Assurance workflow: requirement clarification, mode sele
---
## Command Execution Protocol
When coordinator needs to execute a command (dispatch, monitor):
1. **Read the command file**: `roles/coordinator/commands/<command-name>.md`
2. **Follow the workflow** defined in the command file (Phase 2-4 structure)
3. **Commands are inline execution guides** -- NOT separate agents or subprocesses
4. **Execute synchronously** -- complete the command workflow before proceeding
Example:
```
Phase 3 needs task dispatch
-> Read roles/coordinator/commands/dispatch.md
-> Execute Phase 2 (Context Loading)
-> Execute Phase 3 (Task Chain Creation)
-> Execute Phase 4 (Validation)
-> Continue to Phase 4
```
---
## Entry Router
When coordinator is invoked, first detect the invocation type:
When coordinator is invoked, detect invocation type:
| Detection | Condition | Handler |
|-----------|-----------|---------|
| Worker callback | Message contains `[role-name]` tag from a known worker role | -> handleCallback: auto-advance pipeline |
| Status check | Arguments contain "check" or "status" | -> handleCheck: output execution graph, no advancement |
| Manual resume | Arguments contain "resume" or "continue" | -> handleResume: check worker states, advance pipeline |
| New session | None of the above | -> Phase 0 (Session Resume Check) |
| Worker callback | Message contains role tag [scout], [strategist], [generator], [executor], [analyst] | -> handleCallback |
| Status check | Arguments contain "check" or "status" | -> handleCheck |
| Manual resume | Arguments contain "resume" or "continue" | -> handleResume |
| Pipeline complete | All tasks have status "completed" | -> handleComplete |
| Interrupted session | Active/paused session exists | -> Phase 0 (Session Resume Check) |
| New session | None of above | -> Phase 1 |
For callback/check/resume: load `commands/monitor.md` and execute the appropriate handler, then STOP.
For callback/check/resume/complete: load `commands/monitor.md` and execute matched handler, then STOP.
### Router Implementation
1. **Load session context** (if exists):
- Scan `.workflow/.team/QA-*/.msg/meta.json` for active/paused sessions
- If found, extract session folder path, status, and pipeline mode
2. **Parse $ARGUMENTS** for detection keywords:
- Check for role name tags in message content
- Check for "check", "status", "resume", "continue" keywords
3. **Route to handler**:
- For monitor handlers: Read `commands/monitor.md`, execute matched handler, STOP
- For Phase 0: Execute Session Resume Check below
- For Phase 1: Execute Requirement Clarification below
---
@@ -101,7 +139,7 @@ For callback/check/resume: load `commands/monitor.md` and execute the appropriat
1. Generate session ID
2. Create session folder
3. Call TeamCreate with team name
4. Initialize shared-memory.json with empty fields
4. Initialize .msg/meta.json with empty fields
5. Initialize wisdom directory (learnings.md, decisions.md, conventions.md, issues.md)
6. Write session file with: session_id, mode, scope, status="active"

View File

@@ -183,7 +183,7 @@ sharedMemory.execution_results = sharedMemory.execution_results || {}
sharedMemory.execution_results[targetLayer] = resultData
sharedMemory.execution_results.pass_rate = passRate
sharedMemory.execution_results.coverage = coverage
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
Write(`${sessionFolder}/.msg/meta.json`, JSON.stringify(sharedMemory, null, 2))
```
## Output Format

View File

@@ -57,25 +57,21 @@ Test executor. Run test suites, collect coverage data, and perform automatic fix
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
**NOTE**: `team` must be **session ID** (e.g., `TQA-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "TQA-project-2026-02-27", NOT "quality-assurance"
session_id: <session-id>,
from: "executor",
to: "coordinator",
type: <message-type>,
summary: "[executor] <layer>: <status-message>",
ref: <results-file>,
data: { pass_rate, coverage, iterations }
data: { ref: <results-file>, pass_rate, coverage, iterations }
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <session-id> --from executor --to coordinator --type <message-type> --summary \"[executor] test execution complete\" --ref <results-file> --json")
Bash("ccw team log --session-id <session-id> --from executor --type <message-type> --json")
```
---
@@ -99,7 +95,7 @@ For parallel instances, parse `--agent-name` from arguments for owner matching.
| Input | Source | Required |
|-------|--------|----------|
| Shared memory | <session-folder>/shared-memory.json | Yes |
| Shared memory | <session-folder>/.msg/meta.json | Yes |
| Test strategy | sharedMemory.test_strategy | Yes |
| Generated tests | sharedMemory.generated_tests | Yes |
| Target layer | task description | Yes |

View File

@@ -228,7 +228,7 @@ const testInfo = {
sharedMemory.generated_tests = sharedMemory.generated_tests || {}
sharedMemory.generated_tests[targetLayer] = testInfo
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
Write(`${sessionFolder}/.msg/meta.json`, JSON.stringify(sharedMemory, null, 2))
```
## Output Format

View File

@@ -57,24 +57,21 @@ Test case generator. Generate test code according to strategist's strategy and l
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
**NOTE**: `team` must be **session ID** (e.g., `TQA-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "TQA-project-2026-02-27", NOT "quality-assurance"
session_id: <session-id>,
from: "generator",
to: "coordinator",
type: <message-type>,
summary: "[generator] <layer> test generation complete: <file-count> files",
ref: <first-test-file>
data: { ref: <first-test-file> }
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <session-id> --from generator --to coordinator --type <message-type> --summary \"[generator] test generation complete\" --ref <test-file> --json")
Bash("ccw team log --session-id <session-id> --from generator --type <message-type> --json")
```
---
@@ -98,7 +95,7 @@ For parallel instances, parse `--agent-name` from arguments for owner matching.
| Input | Source | Required |
|-------|--------|----------|
| Shared memory | <session-folder>/shared-memory.json | Yes |
| Shared memory | <session-folder>/.msg/meta.json | Yes |
| Test strategy | sharedMemory.test_strategy | Yes |
| Target layer | task description or strategy.layers[0] | Yes |

View File

@@ -86,7 +86,7 @@ const changedFiles = Bash(`git diff --name-only HEAD~5 2>/dev/null || echo ""`)
// 读取 shared memory 获取历史缺陷模式
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1] || '.'
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`)) } catch {}
const knownPatterns = sharedMemory.defect_patterns || []
// 确定扫描视角
@@ -164,7 +164,7 @@ const discoveredIssues = allFindings.critical
// 更新 shared memory
sharedMemory.discovered_issues = discoveredIssues
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
Write(`${sessionFolder}/.msg/meta.json`, JSON.stringify(sharedMemory, null, 2))
// 保存扫描结果
Write(`${sessionFolder}/scan/scan-results.json`, JSON.stringify({
@@ -189,12 +189,10 @@ const resultSummary = `发现 ${discoveredIssues.length} 个问题Critical: $
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
session_id: teamName,
from: "scout",
to: "coordinator",
type: discoveredIssues.length > 0 ? "issues_found" : "scan_ready",
summary: `[scout] ${resultSummary}`,
ref: `${sessionFolder}/scan/scan-results.json`
data: { ref: `${sessionFolder}/scan/scan-results.json` }
})
SendMessage({

View File

@@ -55,24 +55,21 @@ Test strategist. Analyze change scope, determine test layers (L1-L3), define cov
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
**NOTE**: `team` must be **session ID** (e.g., `TQA-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "TQA-project-2026-02-27", NOT "quality-assurance"
session_id: <session-id>,
from: "strategist",
to: "coordinator",
type: <message-type>,
summary: "[strategist] QASTRAT complete: <layers-summary>",
ref: <artifact-path>
data: { ref: <artifact-path> }
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <session-id> --from strategist --to coordinator --type <message-type> --summary \"[strategist] QASTRAT complete\" --ref <artifact-path> --json")
Bash("ccw team log --session-id <session-id> --from strategist --type <message-type> --json")
```
---
@@ -94,7 +91,7 @@ Standard task discovery flow: TaskList -> filter by prefix `QASTRAT-*` + owner m
| Input | Source | Required |
|-------|--------|----------|
| Shared memory | <session-folder>/shared-memory.json | Yes |
| Shared memory | <session-folder>/.msg/meta.json | Yes |
| Discovered issues | sharedMemory.discovered_issues | No |
| Defect patterns | sharedMemory.defect_patterns | No |