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,60 +1,30 @@
# Role: assessor
# Assessor Role
技术债务量化评估师。对扫描发现的每项债务进行影响评分(1-5)和修复成本评分(1-5),划分优先级象限,生成 priority-matrix.json。
## Role Identity
## Identity
- **Name**: `assessor`
- **Name**: `assessor` | **Tag**: `[assessor]`
- **Task Prefix**: `TDEVAL-*`
- **Responsibility**: Read-only analysis量化评估
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[assessor]`
- **Responsibility**: Read-only analysis (量化评估)
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `TDEVAL-*` 前缀的任务
- 所有输出必须带 `[assessor]` 标识
- 基于数据量化评估债务优先级
- 更新 shared memory 中的 priority_matrix
- Only process `TDEVAL-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[assessor]` identifier
- Only communicate with coordinator via SendMessage
- Work strictly within quantitative assessment responsibility scope
- Base evaluations on data from debt inventory
### MUST NOT
- Modify source code or test code
- Execute fix operations
- Create tasks for other roles
- Communicate directly with other worker roles (must go through coordinator)
- Omit `[assessor]` identifier in any output
- 修改源代码或测试代码
- 执行修复操作
- 为其他角色创建任务
- 直接与其他 worker 通信
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `assessment_complete` | assessor → coordinator | 评估完成 | 包含优先级矩阵摘要 |
| `error` | assessor → coordinator | 评估失败 | 阻塞性错误 |
## Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "assessor",
to: "coordinator",
type: "assessment_complete",
summary: "[assessor] 评估完成: 12 quick-wins, 8 strategic, 15 backlog, 7 defer"
})
```
### CLI 回退
`mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
```javascript
Bash(`echo '${JSON.stringify({ from: "assessor", to: "coordinator", type: "assessment_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
```
---
## Toolbox
@@ -64,192 +34,147 @@ Bash(`echo '${JSON.stringify({ from: "assessor", to: "coordinator", type: "asses
|---------|------|-------|-------------|
| `evaluate` | [commands/evaluate.md](commands/evaluate.md) | Phase 3 | 影响/成本矩阵评估 |
### Subagent Capabilities
### Tool Capabilities
> Assessor 不直接使用 subagent
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `gemini` | CLI | evaluate.md | 债务影响与修复成本评估 |
### CLI Capabilities
> Assessor does not directly use subagents
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | evaluate.md | 债务影响与修复成本评估 |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `assessment_complete` | assessor -> coordinator | 评估完成 | 包含优先级矩阵摘要 |
| `error` | assessor -> coordinator | 评估失败 | 阻塞性错误 |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <team-name>,
from: "assessor",
to: "coordinator",
type: <message-type>,
summary: "[assessor] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <team-name> --from assessor --to coordinator --type <message-type> --summary \"[assessor] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('TDEVAL-') &&
t.owner === 'assessor' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Standard task discovery flow: TaskList -> filter by prefix `TDEVAL-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Load Debt Inventory
```javascript
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
| Input | Source | Required |
|-------|--------|----------|
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
| Debt inventory | shared-memory.debt_inventory OR `<session-folder>/scan/debt-inventory.json` | Yes |
const debtInventory = sharedMemory.debt_inventory || []
if (debtInventory.length === 0) {
// 尝试从文件加载
try {
const inventoryFile = JSON.parse(Read(`${sessionFolder}/scan/debt-inventory.json`))
debtInventory.push(...(inventoryFile.items || []))
} catch {}
}
**Loading steps**:
if (debtInventory.length === 0) {
// 无债务项,直接报告
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "assessor",
to: "coordinator", type: "assessment_complete",
summary: `[assessor] 无债务项需要评估`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
return
}
```
1. Extract session path from task description
2. Read shared-memory.json
3. Load debt_inventory from shared memory or fallback to debt-inventory.json file
4. If debt_inventory is empty -> report empty assessment and exit
### Phase 3: Evaluate Each Item
```javascript
// Read commands/evaluate.md for full CLI evaluation implementation
Read("commands/evaluate.md")
```
Delegate to `commands/evaluate.md` if available, otherwise execute inline.
**核心策略**: 对每项债务评估 impact(1-5) + cost(1-5) + priority quadrant
**Core Strategy**: For each debt item, evaluate impact(1-5) + cost(1-5) + priority quadrant
```javascript
const evaluatedItems = []
**Impact Score Mapping**:
for (const item of debtInventory) {
// CLI 分析评估(批量处理以节约 API 调用)
const evaluation = {
...item,
impact_score: 0, // 1-5, 业务影响
cost_score: 0, // 1-5, 修复成本
risk_if_unfixed: '', // 风险描述
priority_quadrant: '' // quick-win / strategic / backlog / defer
}
| Severity | Impact Score |
|----------|--------------|
| critical | 5 |
| high | 4 |
| medium | 3 |
| low | 1 |
// 基于严重性预评估
const severityImpact = { critical: 5, high: 4, medium: 3, low: 1 }
evaluation.impact_score = severityImpact[item.severity] || 3
**Cost Score Mapping**:
// 基于预估工作量预评估
const effortCost = { small: 1, medium: 3, large: 5 }
evaluation.cost_score = effortCost[item.estimated_effort] || 3
| Estimated Effort | Cost Score |
|------------------|------------|
| small | 1 |
| medium | 3 |
| large | 5 |
| unknown | 3 |
// 象限划分
if (evaluation.impact_score >= 4 && evaluation.cost_score <= 2) {
evaluation.priority_quadrant = 'quick-win'
} else if (evaluation.impact_score >= 4 && evaluation.cost_score >= 3) {
evaluation.priority_quadrant = 'strategic'
} else if (evaluation.impact_score <= 3 && evaluation.cost_score <= 2) {
evaluation.priority_quadrant = 'backlog'
} else {
evaluation.priority_quadrant = 'defer'
}
**Priority Quadrant Classification**:
evaluatedItems.push(evaluation)
}
```
| Impact | Cost | Quadrant | Description |
|--------|------|----------|-------------|
| >= 4 | <= 2 | quick-win | High impact, low cost |
| >= 4 | >= 3 | strategic | High impact, high cost |
| <= 3 | <= 2 | backlog | Low impact, low cost |
| <= 3 | >= 3 | defer | Low impact, high cost |
**Evaluation record**:
| Field | Description |
|-------|-------------|
| `impact_score` | 1-5, business impact |
| `cost_score` | 1-5, fix effort |
| `risk_if_unfixed` | Risk description |
| `priority_quadrant` | quick-win/strategic/backlog/defer |
### Phase 4: Generate Priority Matrix
```javascript
const priorityMatrix = {
evaluation_date: new Date().toISOString(),
total_items: evaluatedItems.length,
by_quadrant: {
'quick-win': evaluatedItems.filter(i => i.priority_quadrant === 'quick-win'),
'strategic': evaluatedItems.filter(i => i.priority_quadrant === 'strategic'),
'backlog': evaluatedItems.filter(i => i.priority_quadrant === 'backlog'),
'defer': evaluatedItems.filter(i => i.priority_quadrant === 'defer')
},
summary: {
'quick-win': evaluatedItems.filter(i => i.priority_quadrant === 'quick-win').length,
'strategic': evaluatedItems.filter(i => i.priority_quadrant === 'strategic').length,
'backlog': evaluatedItems.filter(i => i.priority_quadrant === 'backlog').length,
'defer': evaluatedItems.filter(i => i.priority_quadrant === 'defer').length
}
}
**Matrix structure**:
// 排序:每个象限内按 impact_score 降序
for (const quadrant of Object.keys(priorityMatrix.by_quadrant)) {
priorityMatrix.by_quadrant[quadrant].sort((a, b) => b.impact_score - a.impact_score)
}
| Field | Description |
|-------|-------------|
| `evaluation_date` | ISO timestamp |
| `total_items` | Count of evaluated items |
| `by_quadrant` | Items grouped by quadrant |
| `summary` | Count per quadrant |
// 保存评估结果
Bash(`mkdir -p "${sessionFolder}/assessment"`)
Write(`${sessionFolder}/assessment/priority-matrix.json`, JSON.stringify(priorityMatrix, null, 2))
**Sorting**: Within each quadrant, sort by impact_score descending
// 更新 shared memory
sharedMemory.priority_matrix = priorityMatrix.summary
sharedMemory.debt_inventory = evaluatedItems
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
```
**Save outputs**:
1. Write `<session-folder>/assessment/priority-matrix.json`
2. Update shared-memory.json with `priority_matrix` summary and evaluated `debt_inventory`
### Phase 5: Report to Coordinator
```javascript
const summaryText = Object.entries(priorityMatrix.summary)
.map(([q, c]) => `${q}: ${c}`)
.join(', ')
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "assessor",
to: "coordinator",
type: "assessment_complete",
summary: `[assessor] 评估完成: ${summaryText}`,
ref: `${sessionFolder}/assessment/priority-matrix.json`
})
Standard report flow: team_msg log -> SendMessage with `[assessor]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [assessor] Assessment Results
**Report content**:
**Task**: ${task.subject}
**Total Items**: ${evaluatedItems.length}
| Field | Value |
|-------|-------|
| Task | task.subject |
| Total Items | Count of evaluated items |
| Priority Matrix | Count per quadrant |
| Top Quick-Wins | Top 5 quick-win items with details |
| Priority Matrix File | Path to priority-matrix.json |
### Priority Matrix
| Quadrant | Count | Description |
|----------|-------|-------------|
| Quick-Win | ${priorityMatrix.summary['quick-win']} | High impact, low cost |
| Strategic | ${priorityMatrix.summary['strategic']} | High impact, high cost |
| Backlog | ${priorityMatrix.summary['backlog']} | Low impact, low cost |
| Defer | ${priorityMatrix.summary['defer']} | Low impact, high cost |
### Top Quick-Wins
${priorityMatrix.by_quadrant['quick-win'].slice(0, 5).map(i => `- **[${i.dimension}]** ${i.file} - ${i.description} (impact: ${i.impact_score}, cost: ${i.cost_score})`).join('\n')}
### Priority Matrix
${sessionFolder}/assessment/priority-matrix.json`,
summary: `[assessor] TDEVAL complete: ${summaryText}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('TDEVAL-') && t.owner === 'assessor' &&
t.status === 'pending' && t.blockedBy.length === 0
)
if (nextTasks.length > 0) { /* back to Phase 1 */ }
```
---
## Error Handling

View File

@@ -1,69 +1,48 @@
# Role: coordinator
# Coordinator Role
技术债务治理团队协调者。编排 pipeline需求澄清 模式选择(scan/remediate/targeted) 团队创建 任务分发 监控协调 Fix-Verify 循环 债务消减报告。
技术债务治理团队协调者。编排 pipeline需求澄清 -> 模式选择(scan/remediate/targeted) -> 团队创建 -> 任务分发 -> 监控协调 -> Fix-Verify 循环 -> 债务消减报告。
## Role Identity
## Identity
- **Name**: `coordinator`
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
- **Responsibility**: Orchestration
- **Communication**: SendMessage to all teammates
- **Output Tag**: `[coordinator]`
- **Name**: `coordinator` | **Tag**: `[coordinator]`
- **Responsibility**: Parse requirements -> Create team -> Dispatch tasks -> Monitor progress -> Report results
## Role Boundaries
## Boundaries
### MUST
- 所有输出SendMessage、team_msg、日志必须带 `[coordinator]` 标识
- 仅负责需求澄清、模式选择、任务创建/分发、进度监控、质量门控、结果汇报
- 通过 TaskCreate 创建任务并分配给 worker 角色
- 通过消息总线监控 worker 进度并路由消息
- All output (SendMessage, team_msg, logs) must carry `[coordinator]` identifier
- Only responsible for: requirement clarification, mode selection, task creation/dispatch, progress monitoring, quality gates, result reporting
- Create tasks via TaskCreate and assign to worker roles
- Monitor worker progress via message bus and route messages
- Maintain session state persistence
### MUST NOT
- Execute tech debt work directly (delegate to workers)
- Modify task outputs (workers own their deliverables)
- Call implementation subagents directly (cli-explore-agent, code-developer, etc.)
- Modify source code or generate artifact files directly
- Bypass worker roles to complete delegated work
- Skip dependency validation when creating task chains
- Omit `[coordinator]` identifier in any output
- 直接执行任何业务任务(扫描、评估、规划、修复、验证等)
- 直接调用 cli-explore-agent、code-developer 等实现类 subagent
- 直接修改源代码或生成产物文件
- 绕过 worker 角色自行完成应委派的工作
- 在输出中省略 `[coordinator]` 标识
> **Core principle**: coordinator is the orchestrator, not the executor. All actual work must be delegated to worker roles via TaskCreate.
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
---
## Message Types
## Entry Router
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `mode_selected` | coordinator → all | 模式确定 | scan/remediate/targeted |
| `plan_approval` | coordinator → user | TDPLAN 完成 | 呈现治理方案供审批(批准/修订/终止) |
| `worktree_created` | coordinator → user | TDFIX 前 | Worktree 和分支已创建 |
| `pr_created` | coordinator → user | TDVAL 通过 | PR 已创建worktree 已清理 |
| `quality_gate` | coordinator → user | 质量评估 | 通过/不通过/有条件通过 |
| `task_unblocked` | coordinator → worker | 依赖解除 | 任务可执行 |
| `error` | coordinator → user | 协调错误 | 阻塞性问题 |
| `shutdown` | coordinator → all | 团队关闭 | 清理资源 |
When coordinator is invoked, first detect the invocation type:
## Message Bus
| 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) |
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
For callback/check/resume: load `commands/monitor.md` and execute the appropriate handler, then STOP.
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "coordinator",
to: "user",
type: "mode_selected",
summary: "[coordinator] 模式已选择: remediate"
})
```
### CLI 回退
`mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
```javascript
Bash(`echo '${JSON.stringify({ from: "coordinator", to: "user", type: "mode_selected", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
```
---
## Toolbox
@@ -74,251 +53,334 @@ Bash(`echo '${JSON.stringify({ from: "coordinator", to: "user", type: "mode_sele
| `dispatch` | [commands/dispatch.md](commands/dispatch.md) | Phase 3 | 任务链创建与依赖管理 |
| `monitor` | [commands/monitor.md](commands/monitor.md) | Phase 4 | 消息总线轮询与协调循环 |
### Subagent Capabilities
### Tool Capabilities
> Coordinator 不直接使用 subagent通过 worker 角色间接使用)
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `TeamCreate` | Tool | Phase 2 | Team initialization |
| `TaskCreate` | Tool | Phase 3 | Task chain creation |
| `Task` | Tool | Phase 4 | Worker spawning |
| `AskUserQuestion` | Tool | Phase 1 | Requirement clarification |
### CLI Capabilities
> Coordinator does not directly use CLI analysis tools or implementation subagents
> Coordinator 不直接使用 CLI 分析工具
---
## Execution (5-Phase)
## Message Types
### Phase 1: Parse Arguments & Mode Detection
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `mode_selected` | coordinator -> all | 模式确定 | scan/remediate/targeted |
| `plan_approval` | coordinator -> user | TDPLAN 完成 | 呈现治理方案供审批 |
| `worktree_created` | coordinator -> user | TDFIX 前 | Worktree 和分支已创建 |
| `pr_created` | coordinator -> user | TDVAL 通过 | PR 已创建worktree 已清理 |
| `quality_gate` | coordinator -> user | 质量评估 | 通过/不通过/有条件通过 |
| `task_unblocked` | coordinator -> worker | 依赖解除 | 任务可执行 |
| `error` | coordinator -> user | 协调错误 | 阻塞性问题 |
| `shutdown` | coordinator -> all | 团队关闭 | 清理资源 |
```javascript
const args = "$ARGUMENTS"
## Message Bus
// 提取任务描述
const taskDescription = args.replace(/--role[=\s]+\w+/, '').replace(/--team[=\s]+[\w-]+/, '').replace(/--mode[=\s]+\w+/, '').trim()
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
// Three-Mode 检测
function detectMode(args, desc) {
const modeMatch = args.match(/--mode[=\s]+(scan|remediate|targeted)/)
if (modeMatch) return modeMatch[1]
if (/扫描|scan|审计|audit|评估|assess/.test(desc)) return 'scan'
if (/定向|targeted|指定|specific|修复.*已知/.test(desc)) return 'targeted'
return 'remediate'
}
let pipelineMode = detectMode(args, taskDescription)
// 统一 auto mode 检测
const autoYes = /\b(-y|--yes)\b/.test(args)
// 简单任务可跳过确认auto 模式跳过)
if (!autoYes && (!taskDescription || taskDescription.length < 10)) {
const clarification = AskUserQuestion({
questions: [{
question: "请描述技术债务治理目标(哪些模块?关注哪些维度?)",
header: "Tech Debt Target",
multiSelect: false,
options: [
{ label: "自定义", description: "输入具体描述" },
{ label: "全项目扫描", description: "多维度扫描并评估技术债务" },
{ label: "完整治理", description: "扫描+评估+规划+修复+验证闭环" },
{ label: "定向修复", description: "针对已知债务项进行修复" }
]
}]
})
}
```
### Phase 2: Create Team + Initialize Session
```javascript
const teamName = "tech-debt"
const sessionSlug = taskDescription.slice(0, 30).replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '-')
const sessionDate = new Date().toISOString().slice(0, 10)
const sessionFolder = `.workflow/.team/TD-${sessionSlug}-${sessionDate}`
Bash(`mkdir -p "${sessionFolder}/scan" "${sessionFolder}/assessment" "${sessionFolder}/plan" "${sessionFolder}/fixes" "${sessionFolder}/validation"`)
// 初始化 shared memory
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify({
debt_inventory: [],
priority_matrix: {},
remediation_plan: {},
fix_results: {},
validation_results: {},
debt_score_before: null,
debt_score_after: null
}, null, 2))
TeamCreate({ team_name: teamName })
// ⚠️ 不在此阶段 spawn worker
// Worker 在 Phase 4 (monitor) 中按阶段按需 spawnStop-Wait 策略)
// 这避免了 worker 先启动但无任务可做的鸡生蛋问题
```
### Phase 3: Create Task Chain
根据 pipelineMode 创建不同的任务链:
```javascript
// Read commands/dispatch.md for full implementation
Read("commands/dispatch.md")
```
**Scan Mode**:
```
TDSCAN-001(多维度扫描) → TDEVAL-001(量化评估)
```
**Remediate Mode**:
```
TDSCAN-001(扫描) → TDEVAL-001(评估) → TDPLAN-001(规划) → TDFIX-001(修复) → TDVAL-001(验证)
```
**Targeted Mode**:
```
TDPLAN-001(规划) → TDFIX-001(修复) → TDVAL-001(验证)
```
### Phase 4: Sequential Stage Execution (Stop-Wait)
```javascript
// Read commands/monitor.md for full implementation
Read("commands/monitor.md")
```
> **策略**: 逐阶段 spawn worker同步阻塞等待返回。Worker 返回即阶段完成,无需轮询。
>
> - ❌ 禁止: while 循环 + sleep + 检查状态
> - ✅ 采用: `Task(run_in_background: false)` 同步调用 = 天然回调
**阶段流转**:
| 当前阶段 | Worker | 完成后 |
|----------|--------|--------|
| TDSCAN-001 | scanner | → 启动 TDEVAL |
| TDEVAL-001 | assessor | → 启动 TDPLAN |
| TDPLAN-001 | planner | → [Plan Approval Gate] → [Create Worktree] → 启动 TDFIX |
| TDFIX-001 | executor (worktree) | → 启动 TDVAL |
| TDVAL-001 | validator (worktree) | → 评估质量门控 → [Commit+PR] |
**Fix-Verify 循环**TDVAL 阶段发现回归时):
```javascript
if (regressionFound && fixVerifyIteration < 3) {
fixVerifyIteration++
// 创建 TDFIX-fix + TDVAL-verify 任务,追加到 pipeline 继续执行
} else if (fixVerifyIteration >= 3) {
// 接受当前状态,继续汇报
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] Fix-Verify 循环已达上限(3次),接受当前结果`
})
}
```
### Phase 5: Report + Debt Reduction Metrics + PR
```javascript
// 读取 shared memory 汇总结果
const memory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
// PR 创建worktree 执行模式下,验证通过后)
if (memory.worktree && memory.validation_results?.passed) {
const { path: wtPath, branch } = memory.worktree
// Commit all changes in worktree
Bash(`cd "${wtPath}" && git add -A && git commit -m "$(cat <<'EOF'
tech-debt: ${taskDescription}
Automated tech debt cleanup via team-tech-debt pipeline.
Mode: ${pipelineMode}
EOF
)"`)
// Push + Create PR
Bash(`cd "${wtPath}" && git push -u origin "${branch}"`)
const prBody = `## Tech Debt Cleanup
**Mode**: ${pipelineMode}
**Items fixed**: ${memory.fix_results?.items_fixed || 0}
**Debt score**: ${memory.debt_score_before}${memory.debt_score_after}
### Validation
- Tests: ${memory.validation_results?.checks?.test_suite?.status || 'N/A'}
- Types: ${memory.validation_results?.checks?.type_check?.status || 'N/A'}
- Lint: ${memory.validation_results?.checks?.lint_check?.status || 'N/A'}
### Session
${sessionFolder}`
Bash(`cd "${wtPath}" && gh pr create --title "Tech Debt: ${taskDescription.slice(0, 50)}" --body "$(cat <<'EOF'
${prBody}
EOF
)"`)
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "pr_created",
summary: `[coordinator] PR 已创建: branch ${branch}`
})
// Cleanup worktree
Bash(`git worktree remove "${wtPath}" 2>/dev/null || true`)
} else if (memory.worktree && !memory.validation_results?.passed) {
// 验证未通过,保留 worktree 供手动检查
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 验证未通过worktree 保留于 ${memory.worktree.path},请手动检查`
})
}
const report = {
mode: pipelineMode,
debt_items_found: memory.debt_inventory?.length || 0,
debt_score_before: memory.debt_score_before || 'N/A',
debt_score_after: memory.debt_score_after || 'N/A',
items_fixed: memory.fix_results?.items_fixed || 0,
items_remaining: memory.fix_results?.items_remaining || 0,
validation_passed: memory.validation_results?.passed || false,
regressions: memory.validation_results?.regressions || 0
}
// 计算债务消减率
const reductionRate = report.debt_items_found > 0
? Math.round((report.items_fixed / report.debt_items_found) * 100)
: 0
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 技术债务治理完成: ${report.debt_items_found}项债务, 修复${report.items_fixed}项, 消减率${reductionRate}%`
operation: "log",
team: <team-name>,
from: "coordinator",
to: "user",
type: <message-type>,
summary: "[coordinator] <summary>",
ref: <artifact-path>
})
SendMessage({
content: `## [coordinator] Tech Debt Report\n\n${JSON.stringify(report, null, 2)}`,
summary: `[coordinator] Debt reduction: ${reductionRate}%`
})
// 询问下一步auto 模式跳过,默认关闭团队)
if (!autoYes) {
AskUserQuestion({
questions: [{
question: "技术债务治理流程已完成。下一步:",
header: "Next",
multiSelect: false,
options: [
{ label: "新目标", description: "对新模块/维度执行债务治理" },
{ label: "深度修复", description: "对剩余高优先级债务继续修复" },
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
]
}]
})
}
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <team-name> --from coordinator --to user --type <message-type> --summary \"[coordinator] ...\" --json")
```
---
## Phase 0: Session Resume Check
**Objective**: Detect and resume interrupted sessions before creating new ones.
**Workflow**:
1. Scan session directory for sessions with status "active" or "paused"
2. No sessions found -> proceed to Phase 1
3. Single session found -> resume it (-> Session Reconciliation)
4. Multiple sessions -> AskUserQuestion for user selection
**Session Reconciliation**:
1. Audit TaskList -> get real status of all tasks
2. Reconcile: session state <-> TaskList status (bidirectional sync)
3. Reset any in_progress tasks -> pending (they were interrupted)
4. Determine remaining pipeline from reconciled state
5. Rebuild team if disbanded (TeamCreate + spawn needed workers only)
6. Create missing tasks with correct blockedBy dependencies
7. Verify dependency chain integrity
8. Update session file with reconciled state
9. Kick first executable task's worker -> Phase 4
---
## Phase 1: Requirement Clarification
**Objective**: Parse user input and gather execution parameters.
**Workflow**:
1. **Parse arguments** for explicit settings: mode, scope, focus areas
2. **Mode Detection**:
| Detection | Condition | Mode |
|-----------|-----------|------|
| Explicit | `--mode=scan` specified | scan |
| Explicit | `--mode=remediate` specified | remediate |
| Explicit | `--mode=targeted` specified | targeted |
| Keyword | Contains: 扫描, scan, 审计, audit, 评估, assess | scan |
| Keyword | Contains: 定向, targeted, 指定, specific, 修复已知 | targeted |
| Default | No match | remediate |
3. **Auto mode detection**:
| Flag | Behavior |
|------|----------|
| `-y` or `--yes` | Skip confirmations |
4. **Ask for missing parameters** via AskUserQuestion (skip if auto mode):
| Question | Options |
|----------|---------|
| Tech Debt Target | 自定义 / 全项目扫描 / 完整治理 / 定向修复 |
5. **Store requirements**: mode, scope, focus, constraints
**Success**: All parameters captured, mode finalized.
---
## Phase 2: Create Team + Initialize Session
**Objective**: Initialize team, session file, and wisdom directory.
**Workflow**:
1. Generate session ID: `TD-{slug}-{YYYY-MM-DD}`
2. Create session folder structure:
```
<session-folder>/
├── scan/
├── assessment/
├── plan/
├── fixes/
├── validation/
└── wisdom/
├── learnings.md
├── decisions.md
├── conventions.md
└── issues.md
```
3. Initialize shared-memory.json:
| Field | Initial Value |
|-------|---------------|
| `debt_inventory` | [] |
| `priority_matrix` | {} |
| `remediation_plan` | {} |
| `fix_results` | {} |
| `validation_results` | {} |
| `debt_score_before` | null |
| `debt_score_after` | null |
4. Call TeamCreate with team name "tech-debt"
5. **Do NOT spawn workers yet** - Workers are spawned on-demand in Phase 4 (Stop-Wait strategy)
**Success**: Team created, session file written, wisdom initialized.
---
## Phase 3: Create Task Chain
**Objective**: Dispatch tasks based on mode with proper dependencies.
Delegate to `commands/dispatch.md` which creates the full task chain.
**Task Chain by Mode**:
| Mode | Task Chain |
|------|------------|
| scan | TDSCAN-001 -> TDEVAL-001 |
| remediate | TDSCAN-001 -> TDEVAL-001 -> TDPLAN-001 -> TDFIX-001 -> TDVAL-001 |
| targeted | TDPLAN-001 -> TDFIX-001 -> TDVAL-001 |
**Task Metadata**:
| Task ID | Role | Dependencies | Description |
|---------|------|--------------|-------------|
| TDSCAN-001 | scanner | (none) | 多维度技术债务扫描 |
| TDEVAL-001 | assessor | TDSCAN-001 | 量化评估与优先级排序 |
| TDPLAN-001 | planner | TDEVAL-001 (or none in targeted) | 分阶段治理方案规划 |
| TDFIX-001 | executor | TDPLAN-001 + Plan Approval | 债务清理执行worktree |
| TDVAL-001 | validator | TDFIX-001 | 回归测试与质量验证 |
**Success**: Tasks created with correct dependencies, assigned to appropriate owners.
---
## Phase 4: Sequential Stage Execution (Stop-Wait)
> **Strategy**: Spawn workers stage-by-stage, synchronous blocking wait. Worker returns = stage complete. No polling needed.
> **CRITICAL**: Use `Task(run_in_background: false)` for synchronous execution. This is intentionally different from the v3 default Spawn-and-Stop pattern.
**Workflow**:
1. Load `commands/monitor.md` if available
2. Find tasks with: status=pending, blockedBy all resolved, owner assigned
3. For each ready task -> spawn worker (see SKILL.md Spawn Template)
4. Output status summary
5. STOP after spawning (wait for worker callback)
**Stage Transitions**:
| Current Stage | Worker | After Completion |
|---------------|--------|------------------|
| TDSCAN-001 | scanner | -> Start TDEVAL |
| TDEVAL-001 | assessor | -> Start TDPLAN |
| TDPLAN-001 | planner | -> [Plan Approval Gate] -> [Create Worktree] -> Start TDFIX |
| TDFIX-001 | executor (worktree) | -> Start TDVAL |
| TDVAL-001 | validator (worktree) | -> Quality Gate -> [Commit+PR] |
**Worker Spawn Template**:
```
Task({
subagent_type: "general-purpose",
description: "Spawn <role> worker",
prompt: `你是 team "tech-debt" 的 <ROLE>.
## 首要指令MUST
你的所有工作必须通过调用 Skill 获取角色定义后执行,禁止自行发挥:
Skill(skill="team-tech-debt", args="--role=<role>")
此调用会加载你的角色定义role.md、可用命令commands/*.md和完整执行逻辑。
当前需求: <task-description>
Session: <session-folder>
## 角色准则(强制)
- 你只能处理 <PREFIX>-* 前缀的任务,不得执行其他角色的工作
- 所有输出SendMessage、team_msg必须带 [<role>] 标识前缀
- 仅与 coordinator 通信,不得直接联系其他 worker
- 不得使用 TaskCreate 为其他角色创建任务
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
## 工作流程(严格按顺序)
1. 调用 Skill(skill="team-tech-debt", args="--role=<role>") 获取角色定义和执行逻辑
2. 按 role.md 中的 5-Phase 流程执行TaskList -> 找到 <PREFIX>-* 任务 -> 执行 -> 汇报)
3. team_msg log + SendMessage 结果给 coordinator带 [<role>] 标识)
4. TaskUpdate completed -> 检查下一个任务 -> 回到步骤 1`,
run_in_background: false // Stop-Wait: synchronous blocking
})
```
**Plan Approval Gate** (after TDPLAN completes):
1. Read remediation plan
2. Present to user via AskUserQuestion:
| Option | Action |
|--------|--------|
| 批准 | Continue pipeline, create worktree |
| 修订 | Request plan revision from planner |
| 终止 | Stop pipeline, report current status |
**Worktree Creation** (before TDFIX):
1. Create worktree: `git worktree add <path> -b <branch>`
2. Update shared-memory.json with worktree info
3. Notify user via team_msg
**Fix-Verify Loop** (when TDVAL finds regressions):
| Condition | Action |
|-----------|--------|
| regressionFound && iteration < 3 | Create TDFIX-fix + TDVAL-verify tasks, continue |
| iteration >= 3 | Accept current state, report with warning |
---
## Phase 5: Report + Debt Reduction Metrics + PR
**Objective**: Completion report and follow-up options.
**Workflow**:
1. **Read shared memory** -> collect all results
2. **PR Creation** (worktree mode, validation passed):
| Step | Action |
|------|--------|
| Commit | `cd <worktree> && git add -A && git commit -m "tech-debt: <description>"` |
| Push | `cd <worktree> && git push -u origin <branch>` |
| Create PR | `cd <worktree> && gh pr create --title "Tech Debt: ..." --body "..."` |
| Notify | team_msg with pr_created |
| Cleanup | `git worktree remove <worktree>` (if validation passed) |
3. **Calculate metrics**:
| Metric | Calculation |
|--------|-------------|
| debt_items_found | debt_inventory.length |
| items_fixed | fix_results.items_fixed |
| reduction_rate | (items_fixed / debt_items_found) * 100 |
4. **Generate report**:
| Field | Value |
|-------|-------|
| mode | scan/remediate/targeted |
| debt_items_found | Count |
| debt_score_before | Initial score |
| debt_score_after | Final score |
| items_fixed | Count |
| items_remaining | Count |
| validation_passed | Boolean |
| regressions | Count |
5. **Output**: SendMessage with `[coordinator]` prefix + team_msg log
6. **Ask next steps** (skip if auto mode):
| Option | Action |
|--------|--------|
| 新目标 | New tech debt target |
| 深度修复 | Continue with remaining high-priority items |
| 关闭团队 | Cleanup and close |
---
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Teammate unresponsive | Send follow-up, 2x → respawn |
| Error | Resolution |
|-------|------------|
| Task timeout | Log, mark failed, ask user to retry or skip |
| Worker crash | Respawn worker, reassign task |
| Dependency cycle | Detect, report to user, halt |
| Invalid mode | Reject with error, ask to clarify |
| Session corruption | Attempt recovery, fallback to manual reconciliation |
| Teammate unresponsive | Send follow-up, 2x -> respawn |
| Scanner finds no debt | Report clean codebase, skip to summary |
| Fix-Verify loop stuck >3 iterations | Accept current state, continue pipeline |
| Build/test environment broken | Notify user, suggest manual fix |

View File

@@ -1,62 +1,32 @@
# Role: executor
# Executor Role
技术债务清理执行者。根据治理方案执行重构、依赖更新、代码清理、文档补充等操作。通过 code-developer subagent 分批执行修复任务,包含自验证环节。
## Role Identity
## Identity
- **Name**: `executor`
- **Name**: `executor` | **Tag**: `[executor]`
- **Task Prefix**: `TDFIX-*`
- **Responsibility**: Code generation债务清理执行
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[executor]`
- **Responsibility**: Code generation (债务清理执行)
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `TDFIX-*` 前缀的任务
- 所有输出必须带 `[executor]` 标识
- 按治理方案执行修复操作
- 执行基本自验证语法检查、lint
- Only process `TDFIX-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[executor]` identifier
- Only communicate with coordinator via SendMessage
- Work strictly within debt remediation responsibility scope
- Execute fixes according to remediation plan
- Perform self-validation (syntax check, lint)
### MUST NOT
- Create new features from scratch (only cleanup debt)
- Modify code outside the remediation plan
- Create tasks for other roles
- Communicate directly with other worker roles (must go through coordinator)
- Skip self-validation step
- Omit `[executor]` identifier in any output
- 从零创建新功能(仅清理债务)
- 修改不在治理方案中的代码
- 为其他角色创建任务
- 直接与其他 worker 通信
- 跳过自验证步骤
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `fix_complete` | executor → coordinator | 修复完成 | 包含修复摘要 |
| `fix_progress` | executor → coordinator | 批次完成 | 进度更新 |
| `error` | executor → coordinator | 执行失败 | 阻塞性错误 |
## Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "executor",
to: "coordinator",
type: "fix_complete",
summary: "[executor] 修复完成: 15/20 items fixed"
})
```
### CLI 回退
`mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
```javascript
Bash(`echo '${JSON.stringify({ from: "executor", to: "coordinator", type: "fix_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
```
---
## Toolbox
@@ -66,104 +36,134 @@ Bash(`echo '${JSON.stringify({ from: "executor", to: "coordinator", type: "fix_c
|---------|------|-------|-------------|
| `remediate` | [commands/remediate.md](commands/remediate.md) | Phase 3 | 分批委派 code-developer 执行修复 |
### Subagent Capabilities
### Tool Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `code-developer` | remediate.md | 代码修复执行 |
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `code-developer` | Subagent | remediate.md | 代码修复执行 |
### CLI Capabilities
> Executor does not directly use CLI analysis tools (uses code-developer subagent indirectly)
> Executor 不直接使用 CLI 分析工具(通过 code-developer 间接使用)
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `fix_complete` | executor -> coordinator | 修复完成 | 包含修复摘要 |
| `fix_progress` | executor -> coordinator | 批次完成 | 进度更新 |
| `error` | executor -> coordinator | 执行失败 | 阻塞性错误 |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <team-name>,
from: "executor",
to: "coordinator",
type: <message-type>,
summary: "[executor] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <team-name> --from executor --to coordinator --type <message-type> --summary \"[executor] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('TDFIX-') &&
t.owner === 'executor' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Standard task discovery flow: TaskList -> filter by prefix `TDFIX-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Load Remediation Plan
```javascript
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
| Input | Source | Required |
|-------|--------|----------|
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
| Remediation plan | `<session-folder>/plan/remediation-plan.json` | Yes |
// 加载 worktree 路径(由 coordinator 写入 shared memory
const worktreePath = sharedMemory.worktree?.path || null
const worktreeBranch = sharedMemory.worktree?.branch || null
**Loading steps**:
// 加载治理方案
let plan = {}
try {
plan = JSON.parse(Read(`${sessionFolder}/plan/remediation-plan.json`))
} catch {}
1. Extract session path from task description
2. Read shared-memory.json for worktree info:
// 确定要执行的 actions
const allActions = plan.phases
? plan.phases.flatMap(p => p.actions || [])
: []
| Field | Description |
|-------|-------------|
| `worktree.path` | Worktree directory path |
| `worktree.branch` | Worktree branch name |
// 识别目标文件
const targetFiles = [...new Set(allActions.map(a => a.file).filter(Boolean))]
3. Read remediation-plan.json for actions
4. Extract all actions from plan phases
5. Identify target files (unique file paths from actions)
6. Group actions by type for batch processing
// 按类型分批
const batches = groupActionsByType(allActions)
**Batch grouping**:
function groupActionsByType(actions) {
const groups = {}
for (const action of actions) {
const type = action.type || 'refactor'
if (!groups[type]) groups[type] = []
groups[type].push(action)
}
return groups
}
```
| Action Type | Description |
|-------------|-------------|
| refactor | Code refactoring |
| restructure | Architecture changes |
| add-tests | Test additions |
| update-deps | Dependency updates |
| add-docs | Documentation additions |
### Phase 3: Execute Fixes
```javascript
// Read commands/remediate.md for full implementation
Read("commands/remediate.md")
Delegate to `commands/remediate.md` if available, otherwise execute inline.
**Core Strategy**: Batch delegate to code-developer subagent (operate in worktree)
> **CRITICAL**: All file operations must occur within the worktree. Use `run_in_background: false` for synchronous execution.
**Fix Results Tracking**:
| Field | Description |
|-------|-------------|
| `items_fixed` | Count of successfully fixed items |
| `items_failed` | Count of failed items |
| `items_remaining` | Count of remaining items |
| `batches_completed` | Count of completed batches |
| `files_modified` | Array of modified file paths |
| `errors` | Array of error messages |
**Batch execution flow**:
For each batch type and its actions:
1. Spawn code-developer subagent with worktree context
2. Wait for completion (synchronous)
3. Log progress via team_msg
4. Increment batch counter
**Subagent prompt template**:
```
Task({
subagent_type: "code-developer",
run_in_background: false, // Stop-Wait: synchronous execution
description: "Fix tech debt batch: <batch-type> (<count> items)",
prompt: `## Goal
Execute tech debt cleanup for <batch-type> items.
**核心策略**: 分批委派 code-developer 执行修复(在 worktree 中操作)
## Worktree (Mandatory)
- Working directory: <worktree-path>
- **All file reads and modifications must be within <worktree-path>**
- Read files using <worktree-path>/path/to/file
- Prefix Bash commands with cd "<worktree-path>" && ...
```javascript
const fixResults = {
items_fixed: 0,
items_failed: 0,
items_remaining: 0,
batches_completed: 0,
files_modified: [],
errors: []
}
for (const [batchType, actions] of Object.entries(batches)) {
// 委派给 code-developer
Task({
subagent_type: "code-developer",
run_in_background: false,
description: `Fix tech debt batch: ${batchType} (${actions.length} items)`,
prompt: `## Goal
Execute tech debt cleanup for ${batchType} items.
${worktreePath ? `\n## Worktree强制\n- 工作目录: ${worktreePath}\n- **所有文件读取和修改必须在 ${worktreePath} 下进行**\n- 读文件时使用 ${worktreePath}/path/to/file\n- Bash 命令使用 cd "${worktreePath}" && ... 前缀\n` : ''}
## Actions
${actions.map(a => `- [${a.debt_id}] ${a.action} (file: ${a.file})`).join('\n')}
<action-list>
## Instructions
- Read each target file before modifying
@@ -172,93 +172,49 @@ ${actions.map(a => `- [${a.debt_id}] ${a.action} (file: ${a.file})`).join('\n')}
- Do NOT introduce new features
- Do NOT modify unrelated code
- Run basic syntax check after each change`
})
// 记录进度
fixResults.batches_completed++
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "executor",
to: "coordinator", type: "fix_progress",
summary: `[executor] 批次 ${batchType} 完成 (${fixResults.batches_completed}/${Object.keys(batches).length})`
})
}
})
```
### Phase 4: Self-Validation
```javascript
// 基本语法检查(在 worktree 中执行)
const cmdPrefix = worktreePath ? `cd "${worktreePath}" && ` : ''
const syntaxResult = Bash(`${cmdPrefix}npx tsc --noEmit 2>&1 || python -m py_compile *.py 2>&1 || echo "skip"`)
const hasSyntaxErrors = /error/i.test(syntaxResult) && !/skip/.test(syntaxResult)
> **CRITICAL**: All commands must execute in worktree
// 基本 lint 检查
const lintResult = Bash(`${cmdPrefix}npx eslint --no-error-on-unmatched-pattern src/ 2>&1 || echo "skip"`)
const hasLintErrors = /error/i.test(lintResult) && !/skip/.test(lintResult)
**Validation checks**:
// 更新修复统计
fixResults.items_fixed = allActions.length - fixResults.items_failed
fixResults.items_remaining = fixResults.items_failed
fixResults.self_validation = {
syntax_check: hasSyntaxErrors ? 'FAIL' : 'PASS',
lint_check: hasLintErrors ? 'FAIL' : 'PASS'
}
| Check | Command | Pass Criteria |
|-------|---------|---------------|
| Syntax | `tsc --noEmit` or `python -m py_compile` | No errors |
| Lint | `eslint --no-error-on-unmatched-pattern` | No errors |
// 保存修复日志
Bash(`mkdir -p "${sessionFolder}/fixes"`)
Write(`${sessionFolder}/fixes/fix-log.json`, JSON.stringify(fixResults, null, 2))
**Command prefix** (if worktree): `cd "<worktree-path>" && `
// 更新 shared memory
sharedMemory.fix_results = fixResults
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
```
**Validation flow**:
1. Run syntax check -> record PASS/FAIL
2. Run lint check -> record PASS/FAIL
3. Update fix_results.self_validation
4. Write `<session-folder>/fixes/fix-log.json`
5. Update shared-memory.json with fix_results
### Phase 5: Report to Coordinator
```javascript
const statusMsg = `修复 ${fixResults.items_fixed}/${allActions.length} 项, 语法: ${fixResults.self_validation.syntax_check}, lint: ${fixResults.self_validation.lint_check}`
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "executor",
to: "coordinator",
type: "fix_complete",
summary: `[executor] ${statusMsg}`,
ref: `${sessionFolder}/fixes/fix-log.json`,
data: { items_fixed: fixResults.items_fixed, items_failed: fixResults.items_failed }
})
Standard report flow: team_msg log -> SendMessage with `[executor]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [executor] Fix Results
**Report content**:
**Task**: ${task.subject}
**Status**: ${fixResults.items_failed === 0 ? 'ALL FIXED' : 'PARTIAL'}
| Field | Value |
|-------|-------|
| Task | task.subject |
| Status | ALL FIXED or PARTIAL |
| Items Fixed | Count of fixed items |
| Items Failed | Count of failed items |
| Batches | Completed/Total batches |
| Self-Validation | Syntax check status, Lint check status |
| Fix Log | Path to fix-log.json |
### Summary
- Items fixed: ${fixResults.items_fixed}
- Items failed: ${fixResults.items_failed}
- Batches: ${fixResults.batches_completed}/${Object.keys(batches).length}
### Self-Validation
- Syntax check: ${fixResults.self_validation.syntax_check}
- Lint check: ${fixResults.self_validation.lint_check}
### Fix Log
${sessionFolder}/fixes/fix-log.json`,
summary: `[executor] TDFIX complete: ${statusMsg}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('TDFIX-') && t.owner === 'executor' &&
t.status === 'pending' && t.blockedBy.length === 0
)
if (nextTasks.length > 0) { /* back to Phase 1 */ }
```
---
## Error Handling

View File

@@ -1,61 +1,30 @@
# Role: planner
# Planner Role
技术债务治理方案规划师。基于评估矩阵创建分阶段治理方案quick-wins 立即执行、systematic 中期系统治理、prevention 长期预防机制。产出 remediation-plan.md。
## Role Identity
## Identity
- **Name**: `planner`
- **Name**: `planner` | **Tag**: `[planner]`
- **Task Prefix**: `TDPLAN-*`
- **Responsibility**: Orchestration治理规划
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[planner]`
- **Responsibility**: Orchestration (治理规划)
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `TDPLAN-*` 前缀的任务
- 所有输出必须带 `[planner]` 标识
- 基于评估数据制定可行的治理方案
- 更新 shared memory 中的 remediation_plan
- Only process `TDPLAN-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[planner]` identifier
- Only communicate with coordinator via SendMessage
- Work strictly within remediation planning responsibility scope
- Base plans on assessment data from shared memory
### MUST NOT
- Modify source code or test code
- Execute fix operations
- Create tasks for other roles
- Communicate directly with other worker roles (must go through coordinator)
- Omit `[planner]` identifier in any output
- 修改源代码或测试代码
- 执行修复操作
- 为其他角色创建任务
- 直接与其他 worker 通信
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `plan_ready` | planner → coordinator | 方案完成 | 包含分阶段治理方案 |
| `plan_revision` | planner → coordinator | 方案修订 | 根据反馈调整方案 |
| `error` | planner → coordinator | 规划失败 | 阻塞性错误 |
## Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "planner",
to: "coordinator",
type: "plan_ready",
summary: "[planner] 治理方案就绪: 3 phases, 12 quick-wins, 8 systematic"
})
```
### CLI 回退
`mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
```javascript
Bash(`echo '${JSON.stringify({ from: "planner", to: "coordinator", type: "plan_ready", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
```
---
## Toolbox
@@ -65,216 +34,150 @@ Bash(`echo '${JSON.stringify({ from: "planner", to: "coordinator", type: "plan_r
|---------|------|-------|-------------|
| `create-plan` | [commands/create-plan.md](commands/create-plan.md) | Phase 3 | 分阶段治理方案生成 |
### Subagent Capabilities
### Tool Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `cli-explore-agent` | create-plan.md | 代码库探索验证方案可行性 |
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `cli-explore-agent` | Subagent | create-plan.md | 代码库探索验证方案可行性 |
| `gemini` | CLI | create-plan.md | 治理方案生成 |
### CLI Capabilities
---
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | create-plan.md | 治理方案生成 |
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `plan_ready` | planner -> coordinator | 方案完成 | 包含分阶段治理方案 |
| `plan_revision` | planner -> coordinator | 方案修订 | 根据反馈调整方案 |
| `error` | planner -> coordinator | 规划失败 | 阻塞性错误 |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <team-name>,
from: "planner",
to: "coordinator",
type: <message-type>,
summary: "[planner] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <team-name> --from planner --to coordinator --type <message-type> --summary \"[planner] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('TDPLAN-') &&
t.owner === 'planner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Standard task discovery flow: TaskList -> filter by prefix `TDPLAN-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Load Assessment Data
```javascript
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
| Input | Source | Required |
|-------|--------|----------|
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
| Priority matrix | `<session-folder>/assessment/priority-matrix.json` | Yes |
const debtInventory = sharedMemory.debt_inventory || []
**Loading steps**:
// 加载优先级矩阵
let priorityMatrix = {}
try {
priorityMatrix = JSON.parse(Read(`${sessionFolder}/assessment/priority-matrix.json`))
} catch {}
1. Extract session path from task description
2. Read shared-memory.json for debt_inventory
3. Read priority-matrix.json for quadrant groupings
4. Group items by priority quadrant:
// 分组
const quickWins = debtInventory.filter(i => i.priority_quadrant === 'quick-win')
const strategic = debtInventory.filter(i => i.priority_quadrant === 'strategic')
const backlog = debtInventory.filter(i => i.priority_quadrant === 'backlog')
const deferred = debtInventory.filter(i => i.priority_quadrant === 'defer')
```
| Quadrant | Filter |
|----------|--------|
| quickWins | priority_quadrant === 'quick-win' |
| strategic | priority_quadrant === 'strategic' |
| backlog | priority_quadrant === 'backlog' |
| deferred | priority_quadrant === 'defer' |
### Phase 3: Create Remediation Plan
```javascript
// Read commands/create-plan.md for full implementation
Read("commands/create-plan.md")
```
Delegate to `commands/create-plan.md` if available, otherwise execute inline.
**核心策略**: 3 阶段治理方案
**Core Strategy**: 3-phase remediation plan
```javascript
const plan = {
phases: [
{
name: 'Quick Wins',
description: '高影响低成本项,立即执行',
items: quickWins,
estimated_effort: quickWins.reduce((s, i) => s + i.cost_score, 0),
actions: quickWins.map(i => ({
debt_id: i.id,
action: i.suggestion || `Fix ${i.description}`,
file: i.file,
type: determineActionType(i)
}))
},
{
name: 'Systematic',
description: '高影响高成本项,需系统规划',
items: strategic,
estimated_effort: strategic.reduce((s, i) => s + i.cost_score, 0),
actions: strategic.map(i => ({
debt_id: i.id,
action: i.suggestion || `Refactor ${i.description}`,
file: i.file,
type: determineActionType(i)
}))
},
{
name: 'Prevention',
description: '预防机制建设,长期生效',
items: [],
estimated_effort: 0,
actions: generatePreventionActions(debtInventory)
}
]
}
| Phase | Name | Description | Items |
|-------|------|-------------|-------|
| 1 | Quick Wins | 高影响低成本项,立即执行 | quickWins |
| 2 | Systematic | 高影响高成本项,需系统规划 | strategic |
| 3 | Prevention | 预防机制建设,长期生效 | Generated from inventory |
function determineActionType(item) {
const typeMap = {
'code': 'refactor',
'architecture': 'restructure',
'testing': 'add-tests',
'dependency': 'update-deps',
'documentation': 'add-docs'
}
return typeMap[item.dimension] || 'refactor'
}
**Action Type Mapping**:
function generatePreventionActions(inventory) {
const actions = []
const dimensions = [...new Set(inventory.map(i => i.dimension))]
for (const dim of dimensions) {
const count = inventory.filter(i => i.dimension === dim).length
if (count >= 3) {
actions.push({
action: getPreventionAction(dim),
type: 'prevention',
dimension: dim
})
}
}
return actions
}
| Dimension | Action Type |
|-----------|-------------|
| code | refactor |
| architecture | restructure |
| testing | add-tests |
| dependency | update-deps |
| documentation | add-docs |
function getPreventionAction(dimension) {
const prevention = {
'code': 'Add linting rules for complexity thresholds and code smell detection',
'architecture': 'Introduce module boundary checks in CI pipeline',
'testing': 'Set minimum coverage thresholds in CI and add pre-commit test hooks',
'dependency': 'Configure automated dependency update bot (Renovate/Dependabot)',
'documentation': 'Add JSDoc/docstring enforcement in linting rules'
}
return prevention[dimension] || 'Add automated checks for this category'
}
```
**Prevention Action Generation**:
| Condition | Action |
|-----------|--------|
| dimension count >= 3 | Generate prevention action for that dimension |
| Dimension | Prevention Action |
|-----------|-------------------|
| code | Add linting rules for complexity thresholds and code smell detection |
| architecture | Introduce module boundary checks in CI pipeline |
| testing | Set minimum coverage thresholds in CI and add pre-commit test hooks |
| dependency | Configure automated dependency update bot (Renovate/Dependabot) |
| documentation | Add JSDoc/docstring enforcement in linting rules |
### Phase 4: Validate Plan Feasibility
```javascript
// 验证方案可行性
const validation = {
total_actions: plan.phases.reduce((s, p) => s + p.actions.length, 0),
total_effort: plan.phases.reduce((s, p) => s + p.estimated_effort, 0),
files_affected: [...new Set(plan.phases.flatMap(p => p.actions.map(a => a.file)).filter(Boolean))],
has_quick_wins: quickWins.length > 0,
has_prevention: plan.phases[2].actions.length > 0
}
**Validation metrics**:
// 保存治理方案
Bash(`mkdir -p "${sessionFolder}/plan"`)
Write(`${sessionFolder}/plan/remediation-plan.md`, generatePlanMarkdown(plan, validation))
Write(`${sessionFolder}/plan/remediation-plan.json`, JSON.stringify(plan, null, 2))
| Metric | Description |
|--------|-------------|
| total_actions | Sum of actions across all phases |
| total_effort | Sum of estimated effort scores |
| files_affected | Unique files in action list |
| has_quick_wins | Boolean: quickWins.length > 0 |
| has_prevention | Boolean: prevention actions exist |
// 更新 shared memory
sharedMemory.remediation_plan = {
phases: plan.phases.map(p => ({ name: p.name, action_count: p.actions.length, effort: p.estimated_effort })),
total_actions: validation.total_actions,
files_affected: validation.files_affected.length
}
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
```
**Save outputs**:
1. Write `<session-folder>/plan/remediation-plan.md` (markdown format)
2. Write `<session-folder>/plan/remediation-plan.json` (machine-readable)
3. Update shared-memory.json with `remediation_plan` summary
### Phase 5: Report to Coordinator
```javascript
const planSummary = plan.phases.map(p => `${p.name}: ${p.actions.length} actions`).join(', ')
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "planner",
to: "coordinator",
type: "plan_ready",
summary: `[planner] 治理方案就绪: ${planSummary}`,
ref: `${sessionFolder}/plan/remediation-plan.md`
})
Standard report flow: team_msg log -> SendMessage with `[planner]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [planner] Remediation Plan
**Report content**:
**Task**: ${task.subject}
**Total Actions**: ${validation.total_actions}
**Files Affected**: ${validation.files_affected.length}
| Field | Value |
|-------|-------|
| Task | task.subject |
| Total Actions | Count of all actions |
| Files Affected | Count of unique files |
| Phase 1: Quick Wins | Top 5 quick-win items |
| Phase 2: Systematic | Top 3 strategic items |
| Phase 3: Prevention | Top 3 prevention actions |
| Plan Document | Path to remediation-plan.md |
### Phase 1: Quick Wins (${quickWins.length} items)
${quickWins.slice(0, 5).map(i => `- ${i.file} - ${i.description}`).join('\n')}
### Phase 2: Systematic (${strategic.length} items)
${strategic.slice(0, 3).map(i => `- ${i.file} - ${i.description}`).join('\n')}
### Phase 3: Prevention (${plan.phases[2].actions.length} items)
${plan.phases[2].actions.slice(0, 3).map(a => `- ${a.action}`).join('\n')}
### Plan Document
${sessionFolder}/plan/remediation-plan.md`,
summary: `[planner] TDPLAN complete: ${planSummary}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('TDPLAN-') && t.owner === 'planner' &&
t.status === 'pending' && t.blockedBy.length === 0
)
if (nextTasks.length > 0) { /* back to Phase 1 */ }
```
---
## Error Handling

View File

@@ -1,61 +1,30 @@
# Role: scanner
# Scanner Role
多维度技术债务扫描器。扫描代码库的 5 个维度:代码质量、架构、测试、依赖、文档,生成结构化债务清单。通过 CLI Fan-out 并行分析,产出 debt-inventory.json。
## Role Identity
## Identity
- **Name**: `scanner`
- **Name**: `scanner` | **Tag**: `[scanner]`
- **Task Prefix**: `TDSCAN-*`
- **Responsibility**: Orchestration多维度扫描编排
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[scanner]`
- **Responsibility**: Orchestration (多维度扫描编排)
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `TDSCAN-*` 前缀的任务
- 所有输出必须带 `[scanner]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 严格在债务扫描职责范围内工作
- Only process `TDSCAN-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[scanner]` identifier
- Only communicate with coordinator via SendMessage
- Work strictly within debt scanning responsibility scope
- Tag all findings with dimension (code, architecture, testing, dependency, documentation)
### MUST NOT
- Write or modify any code
- Execute fix operations
- Create tasks for other roles
- Communicate directly with other worker roles (must go through coordinator)
- Omit `[scanner]` identifier in any output
- 编写或修改代码
- 执行修复操作
- 为其他角色创建任务
- 直接与其他 worker 通信
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `scan_complete` | scanner → coordinator | 扫描完成 | 包含债务清单摘要 |
| `debt_items_found` | scanner → coordinator | 发现高优先级债务 | 需要关注的关键发现 |
| `error` | scanner → coordinator | 扫描失败 | 阻塞性错误 |
## Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "scanner",
to: "coordinator",
type: "scan_complete",
summary: "[scanner] 多维度扫描完成: 42 项债务"
})
```
### CLI 回退
`mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
```javascript
Bash(`echo '${JSON.stringify({ from: "scanner", to: "coordinator", type: "scan_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
```
---
## Toolbox
@@ -65,200 +34,184 @@ Bash(`echo '${JSON.stringify({ from: "scanner", to: "coordinator", type: "scan_c
|---------|------|-------|-------------|
| `scan-debt` | [commands/scan-debt.md](commands/scan-debt.md) | Phase 3 | 多维度 CLI Fan-out 扫描 |
### Subagent Capabilities
### Tool Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `cli-explore-agent` | scan-debt.md | 并行代码库结构探索(多角度 fan-out |
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `gemini` | CLI | scan-debt.md | 多维度代码分析dimension fan-out |
| `cli-explore-agent` | Subagent | scan-debt.md | 并行代码库结构探索 |
### CLI Capabilities
---
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | scan-debt.md | 多维度代码分析dimension fan-out |
| `gemini` | analysis | scan-debt.md | 多视角深度分析perspective fan-out |
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `scan_complete` | scanner -> coordinator | 扫描完成 | 包含债务清单摘要 |
| `debt_items_found` | scanner -> coordinator | 发现高优先级债务 | 需要关注的关键发现 |
| `error` | scanner -> coordinator | 扫描失败 | 阻塞性错误 |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <team-name>,
from: "scanner",
to: "coordinator",
type: <message-type>,
summary: "[scanner] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <team-name> --from scanner --to coordinator --type <message-type> --summary \"[scanner] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('TDSCAN-') &&
t.owner === 'scanner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Standard task discovery flow: TaskList -> filter by prefix `TDSCAN-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Context Loading
```javascript
// 确定扫描范围
const scanScope = task.description.match(/scope:\s*(.+)/)?.[1] || '**/*'
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
| Input | Source | Required |
|-------|--------|----------|
| Scan scope | task.description (regex: `scope:\s*(.+)`) | No (default: `**/*`) |
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
// 读取 shared memory
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
**Loading steps**:
// 检测项目类型和框架
const projectRoot = Bash(`git rev-parse --show-toplevel 2>/dev/null || pwd`).trim()
const hasPackageJson = Bash(`test -f package.json && echo "yes" || echo "no"`).trim() === 'yes'
const hasPyProject = Bash(`test -f pyproject.toml -o -f requirements.txt && echo "yes" || echo "no"`).trim() === 'yes'
const hasGoMod = Bash(`test -f go.mod && echo "yes" || echo "no"`).trim() === 'yes'
1. Extract session path from task description
2. Read shared-memory.json for team context
3. Detect project type and framework:
// 5 个扫描维度
const dimensions = ["code", "architecture", "testing", "dependency", "documentation"]
| Detection | Method |
|-----------|--------|
| Node.js project | Check for package.json |
| Python project | Check for pyproject.toml or requirements.txt |
| Go project | Check for go.mod |
// 多视角 Gemini 分析(自动检测任务关键词)
function detectPerspectives(desc) {
const perspectives = []
if (/security|auth|inject|xss|漏洞|安全/.test(desc)) perspectives.push("security")
if (/performance|speed|optimize|memory|性能|优化/.test(desc)) perspectives.push("performance")
if (/quality|clean|maintain|debt|质量|代码/.test(desc)) perspectives.push("code-quality")
if (/architect|pattern|structure|架构|结构/.test(desc)) perspectives.push("architecture")
// 默认至少 2 个视角
if (perspectives.length === 0) perspectives.push("code-quality", "architecture")
return perspectives
}
const perspectives = detectPerspectives(task.description)
4. Determine scan dimensions (default: code, architecture, testing, dependency, documentation)
5. Detect perspectives from task description:
// 评估复杂度
function assessComplexity(desc) {
let score = 0
if (/全项目|全量|comprehensive|full/.test(desc)) score += 3
if (/architecture|架构/.test(desc)) score += 1
if (/multiple|across|cross|多模块/.test(desc)) score += 2
return score >= 4 ? 'High' : score >= 2 ? 'Medium' : 'Low'
}
const complexity = assessComplexity(task.description)
```
| Condition | Perspective |
|-----------|-------------|
| `security\|auth\|inject\|xss` | security |
| `performance\|speed\|optimize` | performance |
| `quality\|clean\|maintain\|debt` | code-quality |
| `architect\|pattern\|structure` | architecture |
| Default | code-quality + architecture |
6. Assess complexity:
| Signal | Weight |
|--------|--------|
| `全项目\|全量\|comprehensive\|full` | +3 |
| `architecture\|架构` | +1 |
| `multiple\|across\|cross\|多模块` | +2 |
| Score | Complexity |
|-------|------------|
| >= 4 | High |
| 2-3 | Medium |
| 0-1 | Low |
### Phase 3: Multi-Dimension Scan
```javascript
// Read commands/scan-debt.md for full CLI Fan-out implementation
Read("commands/scan-debt.md")
Delegate to `commands/scan-debt.md` if available, otherwise execute inline.
**Core Strategy**: Three-layer parallel Fan-out
| Complexity | Strategy |
|------------|----------|
| Low | Direct: ACE search + Grep inline scan |
| Medium/High | Fan-out A: Subagent exploration (cli-explore-agent) + Fan-out B: CLI dimension analysis (gemini per dimension) + Fan-out C: Multi-perspective Gemini analysis |
**Fan-out Architecture**:
```
Fan-out A: Subagent Exploration (parallel cli-explore)
structure perspective | patterns perspective | deps perspective
↓ merge
Fan-out B: CLI Dimension Analysis (parallel gemini)
code | architecture | testing | dependency | documentation
↓ merge
Fan-out C: Multi-Perspective Gemini (parallel)
security | performance | code-quality | architecture
↓ Fan-in aggregate
debt-inventory.json
```
**核心策略**: 三层并行 Fan-outsubagent 探索 + CLI 维度分析 + 多视角 Gemini
**Low Complexity Path** (inline):
```javascript
if (complexity === 'Low') {
// 直接使用 ACE 搜索 + Grep 进行快速扫描
const aceResults = mcp__ace-tool__search_context({
project_root_path: projectRoot,
query: "code smells, TODO/FIXME, deprecated APIs, complex functions, missing tests"
})
} else {
// Fan-out A: 并行 subagent 探索codebase 结构理解)
// Fan-out B: 每个维度一个 CLI 调用(并行 gemini 分析)
// Fan-out C: 多视角 Gemini 深度分析(并行 perspective 分析)
// → Fan-in: 聚合 + 去重 + 交叉引用
Read("commands/scan-debt.md")
}
```
mcp__ace-tool__search_context({
project_root_path: <project-root>,
query: "code smells, TODO/FIXME, deprecated APIs, complex functions, missing tests"
})
```
### Phase 4: Aggregate into Debt Inventory
```javascript
// 聚合所有维度的发现
const debtInventory = []
**Standardize findings**:
// 为每个发现项创建标准化条目
for (const item of allFindings) {
debtInventory.push({
id: `TD-${String(debtInventory.length + 1).padStart(3, '0')}`,
dimension: item.dimension,
severity: item.severity,
file: item.file,
line: item.line,
description: item.description,
suggestion: item.suggestion,
estimated_effort: item.effort || 'unknown'
})
}
For each finding, create entry:
// 更新 shared memory
sharedMemory.debt_inventory = debtInventory
sharedMemory.debt_score_before = debtInventory.length
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
| Field | Description |
|-------|-------------|
| `id` | `TD-NNN` (sequential) |
| `dimension` | code, architecture, testing, dependency, documentation |
| `severity` | critical, high, medium, low |
| `file` | File path |
| `line` | Line number |
| `description` | Issue description |
| `suggestion` | Fix suggestion |
| `estimated_effort` | small, medium, large, unknown |
// 保存债务清单
Write(`${sessionFolder}/scan/debt-inventory.json`, JSON.stringify({
scan_date: new Date().toISOString(),
dimensions: dimensions,
total_items: debtInventory.length,
by_dimension: dimensions.reduce((acc, d) => {
acc[d] = debtInventory.filter(i => i.dimension === d).length
return acc
}, {}),
by_severity: {
critical: debtInventory.filter(i => i.severity === 'critical').length,
high: debtInventory.filter(i => i.severity === 'high').length,
medium: debtInventory.filter(i => i.severity === 'medium').length,
low: debtInventory.filter(i => i.severity === 'low').length
},
items: debtInventory
}, null, 2))
```
**Save outputs**:
1. Update shared-memory.json with `debt_inventory` and `debt_score_before`
2. Write `<session-folder>/scan/debt-inventory.json`:
| Field | Description |
|-------|-------------|
| `scan_date` | ISO timestamp |
| `dimensions` | Array of scanned dimensions |
| `total_items` | Count of debt items |
| `by_dimension` | Count per dimension |
| `by_severity` | Count per severity level |
| `items` | Array of debt entries |
### Phase 5: Report to Coordinator
```javascript
const resultSummary = `发现 ${debtInventory.length} 项技术债务(${dimensions.map(d => `${d}: ${debtInventory.filter(i => i.dimension === d).length}`).join(', ')}`
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "scanner",
to: "coordinator",
type: debtInventory.length > 0 ? "debt_items_found" : "scan_complete",
summary: `[scanner] ${resultSummary}`,
ref: `${sessionFolder}/scan/debt-inventory.json`
})
Standard report flow: team_msg log -> SendMessage with `[scanner]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [scanner] Debt Scan Results
**Report content**:
**Task**: ${task.subject}
**Dimensions**: ${dimensions.join(', ')}
**Status**: ${debtInventory.length > 0 ? 'Debt Found' : 'Clean'}
| Field | Value |
|-------|-------|
| Task | task.subject |
| Dimensions | dimensions scanned |
| Status | "Debt Found" or "Clean" |
| Summary | Total items with dimension breakdown |
| Top Debt Items | Top 5 critical/high severity items |
| Debt Inventory | Path to debt-inventory.json |
### Summary
${resultSummary}
### Top Debt Items
${debtInventory.filter(i => i.severity === 'critical' || i.severity === 'high').slice(0, 5).map(i => `- **[${i.severity}]** [${i.dimension}] ${i.file}:${i.line} - ${i.description}`).join('\n')}
### Debt Inventory
${sessionFolder}/scan/debt-inventory.json`,
summary: `[scanner] TDSCAN complete: ${resultSummary}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('TDSCAN-') &&
t.owner === 'scanner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
---
## Error Handling

View File

@@ -1,61 +1,31 @@
# Role: validator
# Validator Role
技术债务清理结果验证者。运行测试套件验证无回归、执行类型检查和 lint、通过 CLI 分析代码质量改善程度。对比 before/after 债务分数,生成 validation-report.json。
## Role Identity
## Identity
- **Name**: `validator`
- **Name**: `validator` | **Tag**: `[validator]`
- **Task Prefix**: `TDVAL-*`
- **Responsibility**: Validation清理结果验证
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[validator]`
- **Responsibility**: Validation (清理结果验证)
## Role Boundaries
## Boundaries
### MUST
- 仅处理 `TDVAL-*` 前缀的任务
- 所有输出必须带 `[validator]` 标识
- 运行完整验证流程测试、类型检查、lint、质量分析
- 如发现回归,报告 regression_found
- Only process `TDVAL-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[validator]` identifier
- Only communicate with coordinator via SendMessage
- Work strictly within validation responsibility scope
- Run complete validation flow (tests, type check, lint, quality analysis)
- Report regression_found if regressions detected
### MUST NOT
- Fix code directly (only attempt small fixes via code-developer)
- Create tasks for other roles
- Communicate directly with other worker roles (must go through coordinator)
- Skip any validation step
- Omit `[validator]` identifier in any output
- 直接修复代码(仅在小修复时通过 code-developer 尝试)
- 为其他角色创建任务
- 直接与其他 worker 通信
- 跳过任何验证步骤
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `validation_complete` | validator → coordinator | 验证通过 | 包含 before/after 指标 |
| `regression_found` | validator → coordinator | 发现回归 | 触发 Fix-Verify 循环 |
| `error` | validator → coordinator | 验证环境错误 | 阻塞性错误 |
## Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "validator",
to: "coordinator",
type: "validation_complete",
summary: "[validator] 验证通过: 0 regressions, debt score 42 → 18"
})
```
### CLI 回退
`mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
```javascript
Bash(`echo '${JSON.stringify({ from: "validator", to: "coordinator", type: "validation_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
```
---
## Toolbox
@@ -65,195 +35,195 @@ Bash(`echo '${JSON.stringify({ from: "validator", to: "coordinator", type: "vali
|---------|------|-------|-------------|
| `verify` | [commands/verify.md](commands/verify.md) | Phase 3 | 回归测试与质量验证 |
### Subagent Capabilities
### Tool Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `code-developer` | verify.md | 小修复尝试(验证失败时) |
| Tool | Type | Used By | Purpose |
|------|------|---------|---------|
| `code-developer` | Subagent | verify.md | 小修复尝试(验证失败时) |
| `gemini` | CLI | verify.md | 代码质量改善分析 |
### CLI Capabilities
---
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | verify.md | 代码质量改善分析 |
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `validation_complete` | validator -> coordinator | 验证通过 | 包含 before/after 指标 |
| `regression_found` | validator -> coordinator | 发现回归 | 触发 Fix-Verify 循环 |
| `error` | validator -> coordinator | 验证环境错误 | 阻塞性错误 |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <team-name>,
from: "validator",
to: "coordinator",
type: <message-type>,
summary: "[validator] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <team-name> --from validator --to coordinator --type <message-type> --summary \"[validator] ...\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('TDVAL-') &&
t.owner === 'validator' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
Standard task discovery flow: TaskList -> filter by prefix `TDVAL-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Load Context
```javascript
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
| Input | Source | Required |
|-------|--------|----------|
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
| Fix log | `<session-folder>/fixes/fix-log.json` | No |
// 加载 worktree 路径(由 coordinator 写入 shared memory
const worktreePath = sharedMemory.worktree?.path || null
const cmdPrefix = worktreePath ? `cd "${worktreePath}" && ` : ''
**Loading steps**:
const debtInventory = sharedMemory.debt_inventory || []
const fixResults = sharedMemory.fix_results || {}
const debtScoreBefore = sharedMemory.debt_score_before || debtInventory.length
1. Extract session path from task description
2. Read shared-memory.json for:
// 加载修复日志
let fixLog = {}
try { fixLog = JSON.parse(Read(`${sessionFolder}/fixes/fix-log.json`)) } catch {}
| Field | Description |
|-------|-------------|
| `worktree.path` | Worktree directory path |
| `debt_inventory` | Debt items list |
| `fix_results` | Fix results from executor |
| `debt_score_before` | Debt score before fixes |
const modifiedFiles = fixLog.files_modified || []
```
3. Determine command prefix for worktree:
| Condition | Command Prefix |
|-----------|---------------|
| worktree exists | `cd "<worktree-path>" && ` |
| no worktree | Empty string |
4. Read fix-log.json for modified files list
### Phase 3: Run Validation Checks
```javascript
// Read commands/verify.md for full implementation
Read("commands/verify.md")
```
Delegate to `commands/verify.md` if available, otherwise execute inline.
**核心策略**: 4 层验证(所有命令在 worktree 中执行)
**Core Strategy**: 4-layer validation (all commands in worktree)
```javascript
const validationResults = {
test_suite: { status: 'pending', regressions: 0 },
type_check: { status: 'pending', errors: 0 },
lint_check: { status: 'pending', errors: 0 },
quality_analysis: { status: 'pending', improvement: 0 }
}
**Validation Results Structure**:
// 1. 测试套件worktree 中执行)
const testResult = Bash(`${cmdPrefix}npm test 2>&1 || ${cmdPrefix}npx vitest run 2>&1 || ${cmdPrefix}python -m pytest 2>&1 || echo "no-tests"`)
const testsPassed = !/FAIL|error|failed/i.test(testResult) || /no-tests/.test(testResult)
validationResults.test_suite = {
status: testsPassed ? 'PASS' : 'FAIL',
regressions: testsPassed ? 0 : (testResult.match(/(\d+) failed/)?.[1] || 1) * 1
}
| Check | Status Field | Details |
|-------|--------------|---------|
| Test Suite | test_suite.status | regressions count |
| Type Check | type_check.status | errors count |
| Lint Check | lint_check.status | errors count |
| Quality Analysis | quality_analysis.status | improvement percentage |
// 2. 类型检查(worktree 中执行)
const typeResult = Bash(`${cmdPrefix}npx tsc --noEmit 2>&1 || echo "skip"`)
const typeErrors = (typeResult.match(/error TS/g) || []).length
validationResults.type_check = {
status: typeErrors === 0 || /skip/.test(typeResult) ? 'PASS' : 'FAIL',
errors: typeErrors
}
**1. Test Suite** (in worktree):
// 3. Lint 检查worktree 中执行)
const lintResult = Bash(`${cmdPrefix}npx eslint --no-error-on-unmatched-pattern ${modifiedFiles.join(' ')} 2>&1 || echo "skip"`)
const lintErrors = (lintResult.match(/\d+ error/)?.[0]?.match(/\d+/)?.[0] || 0) * 1
validationResults.lint_check = {
status: lintErrors === 0 || /skip/.test(lintResult) ? 'PASS' : 'FAIL',
errors: lintErrors
}
| Detection | Command |
|-----------|---------|
| Node.js | `<cmdPrefix>npm test` or `<cmdPrefix>npx vitest run` |
| Python | `<cmdPrefix>python -m pytest` |
| No tests | Skip with "no-tests" note |
// 4. 质量分析(可选 CLI
// 通过对比债务分数评估改善
const debtScoreAfter = debtInventory.filter(i =>
!fixResults.files_modified?.includes(i.file)
).length
validationResults.quality_analysis = {
status: debtScoreAfter < debtScoreBefore ? 'IMPROVED' : 'NO_CHANGE',
debt_score_before: debtScoreBefore,
debt_score_after: debtScoreAfter,
improvement: debtScoreBefore - debtScoreAfter
}
```
| Pass Criteria | Status |
|---------------|--------|
| No FAIL/error/failed keywords | PASS |
| "no-tests" detected | PASS (skip) |
| Otherwise | FAIL + count regressions |
**2. Type Check** (in worktree):
| Command | `<cmdPrefix>npx tsc --noEmit` |
|---------|-------------------------------|
| Pass Criteria | Status |
|---------------|--------|
| No TS errors or "skip" | PASS |
| TS errors found | FAIL + count errors |
**3. Lint Check** (in worktree):
| Command | `<cmdPrefix>npx eslint --no-error-on-unmatched-pattern <files>` |
|---------|----------------------------------------------------------------|
| Pass Criteria | Status |
|---------------|--------|
| No errors or "skip" | PASS |
| Errors found | FAIL + count errors |
**4. Quality Analysis**:
| Metric | Calculation |
|--------|-------------|
| debt_score_after | debtInventory.filter(not in modified files).length |
| improvement | debt_score_before - debt_score_after |
| Condition | Status |
|-----------|--------|
| debt_score_after < debt_score_before | IMPROVED |
| Otherwise | NO_CHANGE |
### Phase 4: Compare Before/After & Generate Report
```javascript
const totalRegressions = validationResults.test_suite.regressions +
validationResults.type_check.errors + validationResults.lint_check.errors
const passed = totalRegressions === 0
**Calculate totals**:
const report = {
validation_date: new Date().toISOString(),
passed,
regressions: totalRegressions,
checks: validationResults,
debt_score_before: debtScoreBefore,
debt_score_after: validationResults.quality_analysis.debt_score_after,
improvement_percentage: debtScoreBefore > 0
? Math.round(((debtScoreBefore - validationResults.quality_analysis.debt_score_after) / debtScoreBefore) * 100)
: 0
}
| Metric | Calculation |
|--------|-------------|
| total_regressions | test_regressions + type_errors + lint_errors |
| passed | total_regressions === 0 |
// 保存验证报告
Bash(`mkdir -p "${sessionFolder}/validation"`)
Write(`${sessionFolder}/validation/validation-report.json`, JSON.stringify(report, null, 2))
**Report structure**:
// 更新 shared memory
sharedMemory.validation_results = report
sharedMemory.debt_score_after = report.debt_score_after
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
```
| Field | Description |
|-------|-------------|
| `validation_date` | ISO timestamp |
| `passed` | Boolean |
| `regressions` | Total regression count |
| `checks` | Validation results per check |
| `debt_score_before` | Initial debt score |
| `debt_score_after` | Final debt score |
| `improvement_percentage` | Percentage improvement |
**Save outputs**:
1. Write `<session-folder>/validation/validation-report.json`
2. Update shared-memory.json with `validation_results` and `debt_score_after`
### Phase 5: Report to Coordinator
```javascript
const msgType = passed ? 'validation_complete' : 'regression_found'
const statusMsg = passed
? `验证通过: 0 regressions, debt ${debtScoreBefore}${report.debt_score_after} (${report.improvement_percentage}% 改善)`
: `发现 ${totalRegressions} 个回归 (tests: ${validationResults.test_suite.regressions}, types: ${validationResults.type_check.errors}, lint: ${validationResults.lint_check.errors})`
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "validator",
to: "coordinator",
type: msgType,
summary: `[validator] ${statusMsg}`,
ref: `${sessionFolder}/validation/validation-report.json`,
data: { passed, regressions: totalRegressions }
})
Standard report flow: team_msg log -> SendMessage with `[validator]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [validator] Validation Results
**Message type selection**:
**Task**: ${task.subject}
**Status**: ${passed ? 'PASS' : 'FAIL - Regressions Found'}
| Condition | Message Type |
|-----------|--------------|
| passed | validation_complete |
| not passed | regression_found |
### Check Results
| Check | Status | Details |
|-------|--------|---------|
| Test Suite | ${validationResults.test_suite.status} | ${validationResults.test_suite.regressions} regressions |
| Type Check | ${validationResults.type_check.status} | ${validationResults.type_check.errors} errors |
| Lint | ${validationResults.lint_check.status} | ${validationResults.lint_check.errors} errors |
| Quality | ${validationResults.quality_analysis.status} | ${report.improvement_percentage}% improvement |
**Report content**:
### Debt Score
- Before: ${debtScoreBefore}
- After: ${report.debt_score_after}
- Improvement: ${report.improvement_percentage}%
| Field | Value |
|-------|-------|
| Task | task.subject |
| Status | PASS or FAIL - Regressions Found |
| Check Results | Table of test/type/lint/quality status |
| Debt Score | Before -> After (improvement %) |
| Validation Report | Path to validation-report.json |
### Validation Report
${sessionFolder}/validation/validation-report.json`,
summary: `[validator] TDVAL complete: ${statusMsg}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('TDVAL-') && t.owner === 'validator' &&
t.status === 'pending' && t.blockedBy.length === 0
)
if (nextTasks.length > 0) { /* back to Phase 1 */ }
```
---
## Error Handling