feat: add team-tech-debt skill for tech debt identification and cleanup

6-role team (coordinator, scanner, assessor, planner, executor, validator)
with 3 pipeline modes (scan, remediate, targeted) and fix-verify loop.
Scanner performs 5-dimension analysis (code, architecture, testing,
dependency, documentation) via CLI fan-out. Follows team-skill-designer
patterns with self-contained role.md and command.md files.
This commit is contained in:
catlog22
2026-02-23 22:46:27 +08:00
parent 1efe2f469e
commit f60dd44d5b
15 changed files with 3451 additions and 0 deletions

View File

@@ -0,0 +1,404 @@
---
name: team-tech-debt
description: Unified team skill for tech debt identification and cleanup. All roles invoke this skill with --role arg for role-specific execution. Triggers on "team tech-debt", "tech debt cleanup", "技术债务".
allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*)
---
# Team Tech Debt
技术债务识别与清理团队。融合"债务扫描"、"量化评估"、"治理规划"、"清理执行"、"验证回归"五大能力域,形成"扫描→评估→规划→清理→验证"闭环。通过 Scanner 多维度扫描、Executor-Validator 修复验证循环、共享债务清单数据库,实现渐进式技术债务治理。所有成员通过 `--role=xxx` 路由到角色执行逻辑。
## Architecture Overview
```
┌──────────────────────────────────────────────────────────┐
│ Skill(skill="team-tech-debt", args="--role=xxx") │
└────────────────────────┬─────────────────────────────────┘
│ Role Router
┌────────┬───────────┼───────────┬──────────┬──────────┐
↓ ↓ ↓ ↓ ↓ ↓
┌────────┐┌────────┐┌──────────┐┌─────────┐┌────────┐┌─────────┐
│coordi- ││scanner ││assessor ││planner ││executor││validator│
│nator ││TDSCAN-*││TDEVAL-* ││TDPLAN-* ││TDFIX-* ││TDVAL-* │
│ roles/ ││ roles/ ││ roles/ ││ roles/ ││ roles/ ││ roles/ │
└────────┘└────────┘└──────────┘└─────────┘└────────┘└─────────┘
```
## Command Architecture
```
roles/
├── coordinator/
│ ├── role.md # Pipeline 编排(模式选择、任务分发、监控)
│ └── commands/
│ ├── dispatch.md # 任务链创建
│ └── monitor.md # 进度监控
├── scanner/
│ ├── role.md # 多维度技术债务扫描
│ └── commands/
│ └── scan-debt.md # 多维度 CLI Fan-out 扫描
├── assessor/
│ ├── role.md # 量化评估与优先级排序
│ └── commands/
│ └── evaluate.md # 影响/成本矩阵评估
├── planner/
│ ├── role.md # 治理方案规划
│ └── commands/
│ └── create-plan.md # 分阶段治理方案生成
├── executor/
│ ├── role.md # 债务清理执行
│ └── commands/
│ └── remediate.md # 重构/清理/更新执行
└── validator/
├── role.md # 清理结果验证
└── commands/
└── verify.md # 回归测试与质量验证
```
**设计原则**: role.md 保留 Phase 1Task Discovery和 Phase 5Report内联。Phase 2-4 根据复杂度决定内联或委派到 `commands/*.md`
## Role Router
### Input Parsing
Parse `$ARGUMENTS` to extract `--role` and optional `--agent-name`:
```javascript
const args = "$ARGUMENTS"
const roleMatch = args.match(/--role[=\s]+(\w+)/)
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "tech-debt"
if (!roleMatch) {
// No --role: Orchestration Mode → auto route to coordinator
// See "Orchestration Mode" section below
}
const role = roleMatch ? roleMatch[1] : "coordinator"
const agentName = args.match(/--agent-name[=\s]+([\w-]+)/)?.[1] || role
```
### Role Dispatch
```javascript
const VALID_ROLES = {
"coordinator": { file: "roles/coordinator/role.md", prefix: null },
"scanner": { file: "roles/scanner/role.md", prefix: "TDSCAN" },
"assessor": { file: "roles/assessor/role.md", prefix: "TDEVAL" },
"planner": { file: "roles/planner/role.md", prefix: "TDPLAN" },
"executor": { file: "roles/executor/role.md", prefix: "TDFIX" },
"validator": { file: "roles/validator/role.md", prefix: "TDVAL" }
}
if (!VALID_ROLES[role]) {
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
}
// Read and execute role-specific logic
Read(VALID_ROLES[role].file)
// → Execute the 5-phase process defined in that file
```
### Orchestration Mode无参数触发
当不带 `--role` 调用时,自动进入 coordinator 编排模式。
**触发方式**:
```javascript
// 用户调用(无 --role— 自动路由到 coordinator
Skill(skill="team-tech-debt", args="扫描并清理项目中的技术债务")
// 等价于
Skill(skill="team-tech-debt", args="--role=coordinator 扫描并清理项目中的技术债务")
```
**完整调用链**:
```
用户: Skill(args="任务描述")
├─ SKILL.md: 无 --role → Orchestration Mode → 读取 coordinator role.md
├─ coordinator Phase 2: TeamCreate + spawn workers
│ 每个 worker prompt 中包含 Skill(args="--role=xxx") 回调
├─ coordinator Phase 3: dispatch 任务链
├─ worker 收到任务 → Skill(args="--role=xxx") → SKILL.md Role Router → role.md
│ 每个 worker 自动获取:
│ ├─ 角色定义 (role.md: identity, boundaries, message types)
│ ├─ 可用命令 (commands/*.md)
│ └─ 执行逻辑 (5-phase process)
└─ coordinator Phase 4-5: 监控 → 结果汇报
```
### Available Roles
| Role | Task Prefix | Responsibility | Role File |
|------|-------------|----------------|-----------|
| `coordinator` | N/A | Pipeline 编排、模式选择、质量门控 | [roles/coordinator/role.md](roles/coordinator/role.md) |
| `scanner` | TDSCAN-* | 多维度技术债务扫描 | [roles/scanner/role.md](roles/scanner/role.md) |
| `assessor` | TDEVAL-* | 量化评估与优先级排序 | [roles/assessor/role.md](roles/assessor/role.md) |
| `planner` | TDPLAN-* | 分阶段治理方案规划 | [roles/planner/role.md](roles/planner/role.md) |
| `executor` | TDFIX-* | 重构/清理/更新执行 | [roles/executor/role.md](roles/executor/role.md) |
| `validator` | TDVAL-* | 回归测试与质量验证 | [roles/validator/role.md](roles/validator/role.md) |
## Shared Infrastructure
> 以下为编排级概览。具体实现代码Message Bus、Task Lifecycle、工具方法在各 role.md 中自包含。
### Team Configuration
```javascript
const TEAM_CONFIG = {
name: "tech-debt",
sessionDir: ".workflow/.team/TD-{slug}-{date}/",
sharedMemory: "shared-memory.json",
debtDimensions: ["code", "architecture", "testing", "dependency", "documentation"],
priorityMatrix: {
highImpact_lowCost: "立即修复 (Quick Win)",
highImpact_highCost: "战略规划 (Strategic)",
lowImpact_lowCost: "待办处理 (Backlog)",
lowImpact_highCost: "暂缓接受 (Defer)"
}
}
```
### Role Isolation Rules
**核心原则**: 每个角色仅能执行自己职责范围内的工作。
#### Output Tagging强制
所有角色的输出必须带 `[role_name]` 标识前缀。
#### Coordinator 隔离
| 允许 | 禁止 |
|------|------|
| 需求澄清 (AskUserQuestion) | ❌ 直接扫描代码 |
| 创建任务链 (TaskCreate) | ❌ 直接执行重构或清理 |
| 模式选择 + 质量门控 | ❌ 直接评估或规划 |
| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成 |
#### Worker 隔离
| 允许 | 禁止 |
|------|------|
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
| 读写 shared-memory.json (自己的字段) | ❌ 为其他角色创建任务 |
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
## Three-Mode Pipeline Architecture
```
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(验证)
```
### Mode Auto-Detection
```javascript
function detectMode(args, taskDescription) {
if (/--mode[=\s]+(scan|remediate|targeted)/.test(args)) {
return args.match(/--mode[=\s]+(\w+)/)[1]
}
if (/扫描|scan|审计|audit|评估|assess/.test(taskDescription)) return 'scan'
if (/定向|targeted|指定|specific|修复.*已知/.test(taskDescription)) return 'targeted'
return 'remediate'
}
```
### Fix-Verify Loop
```
TDFIX → TDVAL → (if regression or quality drop) → TDFIX-fix → TDVAL-2
(if all pass) → report
```
## Unified Session Directory
```
.workflow/.team/TD-{slug}-{YYYY-MM-DD}/
├── team-session.json
├── shared-memory.json # 债务清单 / 评估矩阵 / 治理方案 / 修复结果 / 验证结果
├── scan/ # Scanner output
│ └── debt-inventory.json
├── assessment/ # Assessor output
│ └── priority-matrix.json
├── plan/ # Planner output
│ └── remediation-plan.md
├── fixes/ # Executor output
│ └── fix-log.json
└── validation/ # Validator output
└── validation-report.json
```
## Coordinator Spawn Template
```javascript
TeamCreate({ team_name: teamName })
// Scanner
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "scanner",
prompt: `你是 team "${teamName}" 的 SCANNER。
## ⚠️ 首要指令MUST
你的所有工作必须通过调用 Skill 获取角色定义后执行,禁止自行发挥:
Skill(skill="team-tech-debt", args="--role=scanner")
此调用会加载你的角色定义role.md、可用命令commands/*.md和完整执行逻辑。
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 TDSCAN-* 前缀的任务,不得执行其他角色的工作
- 所有输出SendMessage、team_msg必须带 [scanner] 标识前缀
- 仅与 coordinator 通信,不得直接联系其他 worker
- 不得使用 TaskCreate 为其他角色创建任务
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
## 工作流程(严格按顺序)
1. 调用 Skill(skill="team-tech-debt", args="--role=scanner") 获取角色定义和执行逻辑
2. 按 role.md 中的 5-Phase 流程执行TaskList → 找到 TDSCAN-* 任务 → 执行 → 汇报)
3. team_msg log + SendMessage 结果给 coordinator带 [scanner] 标识)
4. TaskUpdate completed → 检查下一个任务 → 回到步骤 1`
})
// Assessor
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "assessor",
prompt: `你是 team "${teamName}" 的 ASSESSOR。
## ⚠️ 首要指令MUST
Skill(skill="team-tech-debt", args="--role=assessor")
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 TDEVAL-* 前缀的任务
- 所有输出必须带 [assessor] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
## 工作流程
1. Skill(skill="team-tech-debt", args="--role=assessor") 获取角色定义
2. TaskList → 找到 TDEVAL-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
// Planner
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "planner",
prompt: `你是 team "${teamName}" 的 PLANNER。
## ⚠️ 首要指令MUST
Skill(skill="team-tech-debt", args="--role=planner")
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 TDPLAN-* 前缀的任务
- 所有输出必须带 [planner] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
## 工作流程
1. Skill(skill="team-tech-debt", args="--role=planner") 获取角色定义
2. TaskList → 找到 TDPLAN-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
// Executor
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "executor",
prompt: `你是 team "${teamName}" 的 EXECUTOR。
## ⚠️ 首要指令MUST
Skill(skill="team-tech-debt", args="--role=executor")
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 TDFIX-* 前缀的任务
- 所有输出必须带 [executor] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
## 工作流程
1. Skill(skill="team-tech-debt", args="--role=executor") 获取角色定义
2. TaskList → 找到 TDFIX-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
// Validator
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "validator",
prompt: `你是 team "${teamName}" 的 VALIDATOR。
## ⚠️ 首要指令MUST
Skill(skill="team-tech-debt", args="--role=validator")
当前需求: ${taskDescription}
约束: ${constraints}
## 角色准则(强制)
- 你只能处理 TDVAL-* 前缀的任务
- 所有输出必须带 [validator] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
## 工作流程
1. Skill(skill="team-tech-debt", args="--role=validator") 获取角色定义
2. TaskList → 找到 TDVAL-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Unknown --role value | Error with available role list |
| Missing --role arg | Orchestration Mode → auto route to coordinator |
| Role file not found | Error with expected path (roles/{name}/role.md) |
| Command file not found | Fall back to inline execution in role.md |
| Task prefix conflict | Log warning, proceed |
| Scanner finds no debt | Report clean codebase, skip to summary |
| Fix introduces regression | Trigger Fix-Verify loop (max 3 iterations) |
| Validation repeatedly fails | Escalate to user with diagnosis |

View File

@@ -0,0 +1,164 @@
# Command: evaluate
> CLI 分析评估债务项。对每项债务评估业务影响(1-5)、修复成本(1-5)、未修复风险,产出优先级象限分配。
## When to Use
- Phase 3 of Assessor
- 需要对债务清单中的项目进行量化评估
- 债务项数量较多需要 CLI 辅助分析
**Trigger conditions**:
- TDEVAL-* 任务进入 Phase 3
- 债务清单包含 >10 项需要评估的条目
- 需要上下文理解来评估影响和成本
## Strategy
### Delegation Mode
**Mode**: CLI Batch Analysis
**CLI Tool**: `gemini` (primary)
**CLI Mode**: `analysis`
### Decision Logic
```javascript
// 评估策略选择
if (debtInventory.length <= 10) {
// 少量项目:内联评估(基于严重性和工作量启发式)
mode = 'heuristic'
} else if (debtInventory.length <= 50) {
// 中等规模:单次 CLI 批量评估
mode = 'cli-batch'
} else {
// 大规模:分批 CLI 评估
mode = 'cli-chunked'
chunkSize = 25
}
```
## Execution Steps
### Step 1: Context Preparation
```javascript
// 准备评估上下文
const debtSummary = debtInventory.map(item =>
`[${item.id}] [${item.dimension}] [${item.severity}] ${item.file}:${item.line} - ${item.description}`
).join('\n')
// 读取项目元信息用于上下文
const projectContext = []
try {
const pkg = JSON.parse(Read('package.json'))
projectContext.push(`Project: ${pkg.name}, Dependencies: ${Object.keys(pkg.dependencies || {}).length}`)
} catch {}
```
### Step 2: Execute Strategy
```javascript
if (mode === 'heuristic') {
// 内联启发式评估
for (const item of debtInventory) {
const severityImpact = { critical: 5, high: 4, medium: 3, low: 1 }
const effortCost = { small: 1, medium: 3, large: 5 }
item.impact_score = severityImpact[item.severity] || 3
item.cost_score = effortCost[item.estimated_effort] || 3
item.risk_if_unfixed = getRiskDescription(item)
item.priority_quadrant = assignQuadrant(item.impact_score, item.cost_score)
}
} else {
// CLI 批量评估
const prompt = `PURPOSE: Evaluate technical debt items for business impact and fix cost to create a priority matrix
TASK: • For each debt item, assess business impact (1-5 scale: 1=negligible, 5=critical) • Assess fix complexity/cost (1-5 scale: 1=trivial, 5=major refactor) • Describe risk if unfixed • Assign priority quadrant: quick-win (high impact + low cost), strategic (high impact + high cost), backlog (low impact + low cost), defer (low impact + high cost)
MODE: analysis
CONTEXT: ${projectContext.join(' | ')}
EXPECTED: JSON array with: [{id, impact_score, cost_score, risk_if_unfixed, priority_quadrant}] for each item
CONSTRAINTS: Be realistic about costs, consider dependencies between items
## Debt Items to Evaluate
${debtSummary}`
Bash(`ccw cli -p "${prompt}" --tool gemini --mode analysis --rule analysis-analyze-code-patterns`, {
run_in_background: true
})
// 等待 CLI 完成,解析结果,合并回 debtInventory
}
function assignQuadrant(impact, cost) {
if (impact >= 4 && cost <= 2) return 'quick-win'
if (impact >= 4 && cost >= 3) return 'strategic'
if (impact <= 3 && cost <= 2) return 'backlog'
return 'defer'
}
function getRiskDescription(item) {
const risks = {
'code': 'Increased maintenance cost and bug probability',
'architecture': 'Growing coupling makes changes harder and riskier',
'testing': 'Reduced confidence in changes, higher regression risk',
'dependency': 'Security vulnerabilities and compatibility issues',
'documentation': 'Onboarding friction and knowledge loss'
}
return risks[item.dimension] || 'Technical quality degradation over time'
}
```
### Step 3: Result Processing
```javascript
// 验证评估结果完整性
const evaluated = debtInventory.filter(i => i.priority_quadrant)
const unevaluated = debtInventory.filter(i => !i.priority_quadrant)
if (unevaluated.length > 0) {
// 未评估的项目使用启发式兜底
for (const item of unevaluated) {
item.impact_score = item.impact_score || 3
item.cost_score = item.cost_score || 3
item.priority_quadrant = assignQuadrant(item.impact_score, item.cost_score)
item.risk_if_unfixed = item.risk_if_unfixed || getRiskDescription(item)
}
}
// 生成统计
const stats = {
total: debtInventory.length,
evaluated_by_cli: evaluated.length,
evaluated_by_heuristic: unevaluated.length,
avg_impact: (debtInventory.reduce((s, i) => s + i.impact_score, 0) / debtInventory.length).toFixed(1),
avg_cost: (debtInventory.reduce((s, i) => s + i.cost_score, 0) / debtInventory.length).toFixed(1)
}
```
## Output Format
```
## Evaluation Results
### Method: [heuristic|cli-batch|cli-chunked]
### Total Items: [count]
### Average Impact: [score]/5
### Average Cost: [score]/5
### Priority Distribution
| Quadrant | Count | % |
|----------|-------|---|
| Quick-Win | [n] | [%] |
| Strategic | [n] | [%] |
| Backlog | [n] | [%] |
| Defer | [n] | [%] |
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| CLI returns invalid JSON | Fall back to heuristic scoring |
| CLI timeout | Evaluate processed items, heuristic for rest |
| Debt inventory too large (>200) | Chunk into batches of 25 |
| Missing severity/effort data | Use dimension-based defaults |
| All items same quadrant | Re-evaluate with adjusted thresholds |

View File

@@ -0,0 +1,262 @@
# Role: assessor
技术债务量化评估师。对扫描发现的每项债务进行影响评分(1-5)和修复成本评分(1-5),划分优先级象限,生成 priority-matrix.json。
## Role Identity
- **Name**: `assessor`
- **Task Prefix**: `TDEVAL-*`
- **Responsibility**: Read-only analysis量化评估
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[assessor]`
## Role Boundaries
### MUST
- 仅处理 `TDEVAL-*` 前缀的任务
- 所有输出必须带 `[assessor]` 标识
- 基于数据量化评估债务优先级
- 更新 shared memory 中的 priority_matrix
### MUST NOT
- 修改源代码或测试代码
- 执行修复操作
- 为其他角色创建任务
- 直接与其他 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
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `evaluate` | [commands/evaluate.md](commands/evaluate.md) | Phase 3 | 影响/成本矩阵评估 |
### Subagent Capabilities
> Assessor 不直接使用 subagent
### CLI Capabilities
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | evaluate.md | 债务影响与修复成本评估 |
## 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
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: '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 {}
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 {}
}
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
}
```
### Phase 3: Evaluate Each Item
```javascript
// Read commands/evaluate.md for full CLI evaluation implementation
Read("commands/evaluate.md")
```
**核心策略**: 对每项债务评估 impact(1-5) + cost(1-5) + priority quadrant
```javascript
const evaluatedItems = []
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
}
// 基于严重性预评估
const severityImpact = { critical: 5, high: 4, medium: 3, low: 1 }
evaluation.impact_score = severityImpact[item.severity] || 3
// 基于预估工作量预评估
const effortCost = { small: 1, medium: 3, large: 5 }
evaluation.cost_score = effortCost[item.estimated_effort] || 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'
}
evaluatedItems.push(evaluation)
}
```
### 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
}
}
// 排序:每个象限内按 impact_score 降序
for (const quadrant of Object.keys(priorityMatrix.by_quadrant)) {
priorityMatrix.by_quadrant[quadrant].sort((a, b) => b.impact_score - a.impact_score)
}
// 保存评估结果
Bash(`mkdir -p "${sessionFolder}/assessment"`)
Write(`${sessionFolder}/assessment/priority-matrix.json`, JSON.stringify(priorityMatrix, null, 2))
// 更新 shared memory
sharedMemory.priority_matrix = priorityMatrix.summary
sharedMemory.debt_inventory = evaluatedItems
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
```
### Phase 5: Report to Coordinator
```javascript
const summaryText = Object.entries(priorityMatrix.summary)
.map(([q, c]) => `${q}: ${c}`)
.join(', ')
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`
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [assessor] Assessment Results
**Task**: ${task.subject}
**Total Items**: ${evaluatedItems.length}
### 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
| Scenario | Resolution |
|----------|------------|
| No TDEVAL-* tasks available | Idle, wait for coordinator |
| Debt inventory empty | Report empty assessment, notify coordinator |
| Shared memory corrupted | Re-read from debt-inventory.json file |
| CLI analysis fails | Fall back to severity-based heuristic scoring |
| Too many items (>200) | Batch-evaluate top 50 critical/high first |

View File

@@ -0,0 +1,157 @@
# Command: dispatch
> 任务链创建与依赖管理。根据 pipeline 模式创建技术债务治理任务链并分配给 worker 角色。
## When to Use
- Phase 3 of Coordinator
- Pipeline 模式已确定,需要创建任务链
- 团队已创建worker 已 spawn
**Trigger conditions**:
- Coordinator Phase 2 完成后
- 模式切换需要重建任务链
- Fix-Verify 循环需要创建修复任务
## Strategy
### Delegation Mode
**Mode**: Directcoordinator 直接操作 TaskCreate/TaskUpdate
### Decision Logic
```javascript
// 根据 pipelineMode 选择 pipeline
function buildPipeline(pipelineMode, sessionFolder, taskDescription) {
const pipelines = {
'scan': [
{ prefix: 'TDSCAN', owner: 'scanner', desc: '多维度技术债务扫描', blockedBy: [] },
{ prefix: 'TDEVAL', owner: 'assessor', desc: '量化评估与优先级排序', blockedBy: ['TDSCAN'] }
],
'remediate': [
{ prefix: 'TDSCAN', owner: 'scanner', desc: '多维度技术债务扫描', blockedBy: [] },
{ prefix: 'TDEVAL', owner: 'assessor', desc: '量化评估与优先级排序', blockedBy: ['TDSCAN'] },
{ prefix: 'TDPLAN', owner: 'planner', desc: '分阶段治理方案规划', blockedBy: ['TDEVAL'] },
{ prefix: 'TDFIX', owner: 'executor', desc: '债务清理执行', blockedBy: ['TDPLAN'] },
{ prefix: 'TDVAL', owner: 'validator', desc: '清理结果验证', blockedBy: ['TDFIX'] }
],
'targeted': [
{ prefix: 'TDPLAN', owner: 'planner', desc: '定向修复方案规划', blockedBy: [] },
{ prefix: 'TDFIX', owner: 'executor', desc: '债务清理执行', blockedBy: ['TDPLAN'] },
{ prefix: 'TDVAL', owner: 'validator', desc: '清理结果验证', blockedBy: ['TDFIX'] }
]
}
return pipelines[pipelineMode] || pipelines['scan']
}
```
## Execution Steps
### Step 1: Context Preparation
```javascript
const pipeline = buildPipeline(pipelineMode, sessionFolder, taskDescription)
```
### Step 2: Execute Strategy
```javascript
const taskIds = {}
for (const stage of pipeline) {
// 构建任务描述(包含 session 和上下文信息)
const fullDesc = [
stage.desc,
`\nsession: ${sessionFolder}`,
`\n\n目标: ${taskDescription}`
].join('')
// 创建任务
TaskCreate({
subject: `${stage.prefix}-001: ${stage.desc}`,
description: fullDesc,
activeForm: `${stage.desc}进行中`
})
// 记录任务 ID
const allTasks = TaskList()
const newTask = allTasks.find(t => t.subject.startsWith(`${stage.prefix}-001`))
taskIds[stage.prefix] = newTask.id
// 设置 owner 和依赖
const blockedByIds = stage.blockedBy
.map(dep => taskIds[dep])
.filter(Boolean)
TaskUpdate({
taskId: newTask.id,
owner: stage.owner,
addBlockedBy: blockedByIds
})
}
```
### Step 3: Result Processing
```javascript
// 验证任务链
const allTasks = TaskList()
const chainTasks = pipeline.map(s => taskIds[s.prefix]).filter(Boolean)
const chainValid = chainTasks.length === pipeline.length
if (!chainValid) {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] 任务链创建不完整: ${chainTasks.length}/${pipeline.length}`
})
}
```
## Fix-Verify Loop Task Creation
当 validator 报告回归问题时coordinator 调用此逻辑追加任务:
```javascript
function createFixVerifyTasks(fixVerifyIteration, sessionFolder) {
// 创建修复任务
TaskCreate({
subject: `TDFIX-fix-${fixVerifyIteration}: 修复回归问题 (Fix-Verify #${fixVerifyIteration})`,
description: `修复验证发现的回归问题\nsession: ${sessionFolder}\ntype: fix-verify`,
activeForm: `Fix-Verify #${fixVerifyIteration} 修复中`
})
// 创建重新验证任务
TaskCreate({
subject: `TDVAL-verify-${fixVerifyIteration}: 重新验证 (Fix-Verify #${fixVerifyIteration})`,
description: `重新验证修复结果\nsession: ${sessionFolder}`,
activeForm: `Fix-Verify #${fixVerifyIteration} 验证中`
})
// 设置依赖: TDVAL-verify 依赖 TDFIX-fix
// ... TaskUpdate addBlockedBy
}
```
## Output Format
```
## Task Chain Created
### Mode: [scan|remediate|targeted]
### Pipeline Stages: [count]
- [prefix]-001: [description] (owner: [role], blocked by: [deps])
### Verification: PASS/FAIL
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Task creation fails | Retry once, then report to user |
| Dependency cycle detected | Flatten dependencies, warn coordinator |
| Invalid pipelineMode | Default to 'scan' mode |
| Agent/CLI failure | Retry once, then fallback to inline execution |
| Timeout (>5 min) | Report partial results, notify coordinator |

View File

@@ -0,0 +1,255 @@
# Command: monitor
> 阶段驱动的协调循环。按 pipeline 阶段顺序等待 worker 完成,路由消息,处理 Fix-Verify 循环,检测完成。
## When to Use
- Phase 4 of Coordinator
- 任务链已创建并分发
- 需要持续监控直到所有任务完成
**Trigger conditions**:
- dispatch 完成后立即启动
- Fix-Verify 循环创建新任务后重新进入
## Strategy
### Delegation Mode
**Mode**: Stage-driven按阶段顺序等待非轮询
### 设计原则
> **模型执行没有时间概念**。禁止空转 while 循环检查状态。
> 使用固定 sleep 间隔 + 最大轮询次数,避免无意义的 API 调用浪费。
### Decision Logic
```javascript
// 消息路由表
const routingTable = {
// Scanner 完成
'scan_complete': { action: 'Mark TDSCAN complete, unblock TDEVAL' },
'debt_items_found': { action: 'Mark TDSCAN complete with items, unblock TDEVAL' },
// Assessor 完成
'assessment_complete': { action: 'Mark TDEVAL complete, unblock TDPLAN' },
// Planner 完成
'plan_ready': { action: 'Mark TDPLAN complete, unblock TDFIX' },
'plan_revision': { action: 'Plan revised, re-evaluate dependencies' },
// Executor 完成
'fix_complete': { action: 'Mark TDFIX complete, unblock TDVAL' },
'fix_progress': { action: 'Log progress, continue waiting' },
// Validator 完成
'validation_complete': { action: 'Mark TDVAL complete, evaluate quality gate', special: 'quality_gate' },
'regression_found': { action: 'Evaluate regression, decide Fix-Verify loop', special: 'fix_verify_decision' },
// 错误
'error': { action: 'Assess severity, retry or escalate', special: 'error_handler' }
}
```
### 等待策略常量
```javascript
const POLL_INTERVAL_SEC = 300 // 每次检查间隔 5 分钟
const MAX_POLLS_PER_STAGE = 6 // 单阶段最多等待 6 次(~30 分钟)
const SLEEP_CMD = process.platform === 'win32'
? `timeout /t ${POLL_INTERVAL_SEC} /nobreak >nul 2>&1`
: `sleep ${POLL_INTERVAL_SEC}`
// 统一 auto mode 检测
const autoYes = /\b(-y|--yes)\b/.test(args)
```
## Execution Steps
### Step 1: Context Preparation
```javascript
// 从 shared memory 获取上下文
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
let fixVerifyIteration = 0
const MAX_FIX_VERIFY_ITERATIONS = 3
// 获取 pipeline 阶段列表
const allTasks = TaskList()
const pipelineTasks = allTasks
.filter(t => t.owner && t.owner !== 'coordinator')
.sort((a, b) => Number(a.id) - Number(b.id))
```
### Step 2: Stage-Driven Execution
> **核心**: 按 pipeline 阶段顺序,逐阶段等待完成。
> 每个阶段sleep → 检查消息 → 确认任务状态 → 处理结果 → 下一阶段。
```javascript
for (const stageTask of pipelineTasks) {
let stageComplete = false
let pollCount = 0
while (!stageComplete && pollCount < MAX_POLLS_PER_STAGE) {
Bash(SLEEP_CMD)
pollCount++
// 1. 检查消息总线
const messages = mcp__ccw-tools__team_msg({
operation: "list",
team: teamName,
last: 5
})
// 2. 路由消息
for (const msg of messages) {
const handler = routingTable[msg.type]
if (!handler) continue
processMessage(msg, handler)
}
// 3. 确认任务状态
const currentTask = TaskGet({ taskId: stageTask.id })
stageComplete = currentTask.status === 'completed' || currentTask.status === 'deleted'
}
// 阶段超时处理
if (!stageComplete) {
const elapsedMin = Math.round(pollCount * POLL_INTERVAL_SEC / 60)
if (autoYes) {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 超时 (${elapsedMin}min),自动跳过`
})
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue
}
const decision = AskUserQuestion({
questions: [{
question: `阶段 "${stageTask.subject}" 已等待 ${elapsedMin} 分钟仍未完成。如何处理?`,
header: "Stage Wait",
multiSelect: false,
options: [
{ label: "继续等待", description: `再等 ${MAX_POLLS_PER_STAGE}` },
{ label: "跳过此阶段", description: "标记为跳过,继续后续流水线" },
{ label: "终止流水线", description: "停止整个流程,汇报当前结果" }
]
}]
})
const answer = decision["Stage Wait"]
if (answer === "跳过此阶段") {
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue
} else if (answer === "终止流水线") {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "shutdown",
summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}`
})
break
}
}
}
```
### Step 2.1: Message Processing (processMessage)
```javascript
function processMessage(msg, handler) {
switch (handler.special) {
case 'quality_gate': {
const latestMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const debtBefore = latestMemory.debt_score_before || 0
const debtAfter = latestMemory.debt_score_after || 0
const improved = debtAfter < debtBefore
let status = 'PASS'
if (!improved && latestMemory.validation_results?.regressions > 0) status = 'FAIL'
else if (!improved) status = 'CONDITIONAL'
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 质量门控: ${status} (债务分 ${debtBefore}${debtAfter})`
})
break
}
case 'fix_verify_decision': {
const regressions = msg.data?.regressions || 0
if (regressions > 0 && fixVerifyIteration < MAX_FIX_VERIFY_ITERATIONS) {
fixVerifyIteration++
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "executor", type: "task_unblocked",
summary: `[coordinator] Fix-Verify #${fixVerifyIteration}: 发现 ${regressions} 个回归,请修复`,
data: { iteration: fixVerifyIteration, regressions }
})
// 创建 Fix-Verify 修复任务(参见 dispatch.md createFixVerifyTasks
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] Fix-Verify 循环已达上限(${MAX_FIX_VERIFY_ITERATIONS}),接受当前结果`
})
}
break
}
case 'error_handler': {
const severity = msg.data?.severity || 'medium'
if (severity === 'critical') {
SendMessage({
content: `## [coordinator] Critical Error from ${msg.from}\n\n${msg.summary}`,
summary: `[coordinator] Critical error: ${msg.summary}`
})
}
break
}
}
}
```
### Step 3: Result Processing
```javascript
// 汇总所有结果
const finalSharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const allFinalTasks = TaskList()
const workerTasks = allFinalTasks.filter(t => t.owner && t.owner !== 'coordinator')
const summary = {
total_tasks: workerTasks.length,
completed_tasks: workerTasks.filter(t => t.status === 'completed').length,
fix_verify_iterations: fixVerifyIteration,
debt_score_before: finalSharedMemory.debt_score_before,
debt_score_after: finalSharedMemory.debt_score_after
}
```
## Output Format
```
## Coordination Summary
### Pipeline Status: COMPLETE
### Tasks: [completed]/[total]
### Fix-Verify Iterations: [count]
### Debt Score: [before] → [after]
### Message Log (last 10)
- [timestamp] [from] → [to]: [type] - [summary]
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Message bus unavailable | Fall back to TaskList polling only |
| Stage timeout (交互模式) | AskUserQuestion: 继续等待 / 跳过 / 终止 |
| Stage timeout (自动模式 `-y`/`--yes`) | 自动跳过,记录日志 |
| Teammate unresponsive (2x no response) | Respawn teammate with same task |
| Deadlock detected | Identify cycle, manually unblock |
| Quality gate FAIL | Report to user, suggest targeted re-run |
| Fix-Verify loop stuck >3 iterations | Accept current state, continue pipeline |

View File

@@ -0,0 +1,264 @@
# Role: coordinator
技术债务治理团队协调者。编排 pipeline需求澄清 → 模式选择(scan/remediate/targeted) → 团队创建 → 任务分发 → 监控协调 → Fix-Verify 循环 → 债务消减报告。
## Role Identity
- **Name**: `coordinator`
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
- **Responsibility**: Orchestration
- **Communication**: SendMessage to all teammates
- **Output Tag**: `[coordinator]`
## Role Boundaries
### MUST
- 所有输出SendMessage、team_msg、日志必须带 `[coordinator]` 标识
- 仅负责需求澄清、模式选择、任务创建/分发、进度监控、质量门控、结果汇报
- 通过 TaskCreate 创建任务并分配给 worker 角色
- 通过消息总线监控 worker 进度并路由消息
### MUST NOT
- 直接执行任何业务任务(扫描、评估、规划、修复、验证等)
- 直接调用 cli-explore-agent、code-developer 等实现类 subagent
- 直接修改源代码或生成产物文件
- 绕过 worker 角色自行完成应委派的工作
- 在输出中省略 `[coordinator]` 标识
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `mode_selected` | coordinator → all | 模式确定 | scan/remediate/targeted |
| `quality_gate` | coordinator → user | 质量评估 | 通过/不通过/有条件通过 |
| `task_unblocked` | coordinator → worker | 依赖解除 | 任务可执行 |
| `error` | coordinator → user | 协调错误 | 阻塞性问题 |
| `shutdown` | coordinator → all | 团队关闭 | 清理资源 |
## Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
```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
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `dispatch` | [commands/dispatch.md](commands/dispatch.md) | Phase 3 | 任务链创建与依赖管理 |
| `monitor` | [commands/monitor.md](commands/monitor.md) | Phase 4 | 消息总线轮询与协调循环 |
### Subagent Capabilities
> Coordinator 不直接使用 subagent通过 worker 角色间接使用)
### CLI Capabilities
> Coordinator 不直接使用 CLI 分析工具
## Execution (5-Phase)
### Phase 1: Parse Arguments & Mode Detection
```javascript
const args = "$ARGUMENTS"
// 提取任务描述
const taskDescription = args.replace(/--role[=\s]+\w+/, '').replace(/--team[=\s]+[\w-]+/, '').replace(/--mode[=\s]+\w+/, '').trim()
// 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 + Spawn Teammates
```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 teammates (see SKILL.md Coordinator Spawn Template)
// Scanner, Assessor, Planner, Executor, Validator
```
### 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: Coordination Loop
```javascript
// Read commands/monitor.md for full implementation
Read("commands/monitor.md")
```
| Received Message | Action |
|-----------------|--------|
| `scan_complete` | 标记 TDSCAN complete → 解锁 TDEVAL |
| `assessment_complete` | 标记 TDEVAL complete → 解锁 TDPLAN |
| `plan_ready` | 标记 TDPLAN complete → 解锁 TDFIX |
| `fix_complete` | 标记 TDFIX complete → 解锁 TDVAL |
| `validation_complete` | 标记 TDVAL complete → 评估质量门控 |
| `regression_found` | 评估回归 → 触发 Fix-Verify 循环max 3 |
| Worker: `error` | 评估严重性 → 重试或上报用户 |
**Fix-Verify 循环逻辑**:
```javascript
if (regressionFound && fixVerifyIteration < 3) {
fixVerifyIteration++
// 创建 TDFIX-fix 任务 → TDVAL 重新验证
} 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
```javascript
// 读取 shared memory 汇总结果
const memory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
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}%`
})
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 并清理" }
]
}]
})
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| 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 |
| All tasks completed but debt_score_after > debt_score_before | Report with WARNING, suggest re-run |

View File

@@ -0,0 +1,176 @@
# Command: remediate
> 分批委派 code-developer 执行债务清理。按修复类型分组(重构、死代码移除、依赖更新、文档补充),每批委派给 code-developer。
## When to Use
- Phase 3 of Executor
- 治理方案已加载,修复 actions 已分批
- 需要通过 code-developer 执行代码修改
**Trigger conditions**:
- TDFIX-* 任务进入 Phase 3
- 修复 actions 列表非空
- 目标文件可访问
## Strategy
### Delegation Mode
**Mode**: Sequential Batch Delegation
**Subagent**: `code-developer`
**Batch Strategy**: 按修复类型分组,每组一个委派
### Decision Logic
```javascript
// 分批策略
const batchOrder = ['refactor', 'update-deps', 'add-tests', 'add-docs', 'restructure']
// 按优先级排序批次
function sortBatches(batches) {
const sorted = {}
for (const type of batchOrder) {
if (batches[type]) sorted[type] = batches[type]
}
// 追加未知类型
for (const [type, actions] of Object.entries(batches)) {
if (!sorted[type]) sorted[type] = actions
}
return sorted
}
```
## Execution Steps
### Step 1: Context Preparation
```javascript
// 按类型分组并排序
const sortedBatches = sortBatches(batches)
// 每批最大 items 数
const MAX_ITEMS_PER_BATCH = 10
// 如果单批过大,进一步拆分
function splitLargeBatches(batches) {
const result = {}
for (const [type, actions] of Object.entries(batches)) {
if (actions.length <= MAX_ITEMS_PER_BATCH) {
result[type] = actions
} else {
for (let i = 0; i < actions.length; i += MAX_ITEMS_PER_BATCH) {
const chunk = actions.slice(i, i + MAX_ITEMS_PER_BATCH)
result[`${type}-${Math.floor(i / MAX_ITEMS_PER_BATCH) + 1}`] = chunk
}
}
}
return result
}
const finalBatches = splitLargeBatches(sortedBatches)
```
### Step 2: Execute Strategy
```javascript
for (const [batchName, actions] of Object.entries(finalBatches)) {
// 构建修复上下文
const batchType = batchName.replace(/-\d+$/, '')
const fileList = actions.map(a => a.file).filter(Boolean)
// 根据类型选择修复提示
const typePrompts = {
'refactor': `Refactor the following code to reduce complexity and improve readability. Preserve all existing behavior.`,
'update-deps': `Update the specified dependencies. Check for breaking changes in changelogs.`,
'add-tests': `Add missing test coverage for the specified modules. Follow existing test patterns.`,
'add-docs': `Add documentation (JSDoc/docstrings) for the specified public APIs. Follow existing doc style.`,
'restructure': `Restructure module boundaries to reduce coupling. Move code to appropriate locations.`
}
const prompt = typePrompts[batchType] || 'Apply the specified fix to resolve technical debt.'
// 委派给 code-developer
Task({
subagent_type: "code-developer",
run_in_background: false,
description: `Tech debt cleanup: ${batchName} (${actions.length} items)`,
prompt: `## Goal
${prompt}
## Items to Fix
${actions.map(a => `### ${a.debt_id}: ${a.action}
- File: ${a.file || 'N/A'}
- Type: ${a.type}
${a.steps ? '- Steps:\n' + a.steps.map(s => ` 1. ${s}`).join('\n') : ''}`).join('\n\n')}
## Constraints
- Read each file BEFORE modifying
- Make minimal changes - fix only the specified debt item
- Preserve backward compatibility
- Do NOT skip tests or add @ts-ignore
- Do NOT introduce new dependencies unless explicitly required
- Run syntax check after modifications
## Files to Read First
${fileList.map(f => `- ${f}`).join('\n')}`
})
// 验证批次结果
const batchResult = {
batch: batchName,
items: actions.length,
status: 'completed'
}
// 检查文件是否被修改
for (const file of fileList) {
const modified = Bash(`git diff --name-only -- "${file}" 2>/dev/null`).trim()
if (modified) {
fixResults.files_modified.push(file)
}
}
}
```
### Step 3: Result Processing
```javascript
// 统计修复结果
const totalActions = Object.values(finalBatches).flat().length
fixResults.items_fixed = fixResults.files_modified.length
fixResults.items_failed = totalActions - fixResults.items_fixed
fixResults.items_remaining = fixResults.items_failed
// 生成修复摘要
const batchSummaries = Object.entries(finalBatches).map(([name, actions]) =>
`- ${name}: ${actions.length} items`
).join('\n')
```
## Output Format
```
## Remediation Results
### Batches Executed: [count]
### Items Fixed: [count]/[total]
### Files Modified: [count]
### Batch Details
- [batch-name]: [count] items - [status]
### Modified Files
- [file-path]
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| code-developer fails on a batch | Retry once, mark failed items |
| File locked or read-only | Skip file, log error |
| Syntax error after fix | Revert with git checkout, mark as failed |
| New import/dependency needed | Add minimally, document in fix log |
| Batch too large (>10 items) | Auto-split into sub-batches |
| Agent timeout | Use partial results, continue next batch |

View File

@@ -0,0 +1,267 @@
# Role: executor
技术债务清理执行者。根据治理方案执行重构、依赖更新、代码清理、文档补充等操作。通过 code-developer subagent 分批执行修复任务,包含自验证环节。
## Role Identity
- **Name**: `executor`
- **Task Prefix**: `TDFIX-*`
- **Responsibility**: Code generation债务清理执行
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[executor]`
## Role Boundaries
### MUST
- 仅处理 `TDFIX-*` 前缀的任务
- 所有输出必须带 `[executor]` 标识
- 按治理方案执行修复操作
- 执行基本自验证语法检查、lint
### MUST NOT
- 从零创建新功能(仅清理债务)
- 修改不在治理方案中的代码
- 为其他角色创建任务
- 直接与其他 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
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `remediate` | [commands/remediate.md](commands/remediate.md) | Phase 3 | 分批委派 code-developer 执行修复 |
### Subagent Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `code-developer` | remediate.md | 代码修复执行 |
### CLI Capabilities
> Executor 不直接使用 CLI 分析工具(通过 code-developer 间接使用)
## 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
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: '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 {}
// 加载治理方案
let plan = {}
try {
plan = JSON.parse(Read(`${sessionFolder}/plan/remediation-plan.json`))
} catch {}
// 确定要执行的 actions
const allActions = plan.phases
? plan.phases.flatMap(p => p.actions || [])
: []
// 识别目标文件
const targetFiles = [...new Set(allActions.map(a => a.file).filter(Boolean))]
// 按类型分批
const batches = groupActionsByType(allActions)
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
}
```
### Phase 3: Execute Fixes
```javascript
// Read commands/remediate.md for full implementation
Read("commands/remediate.md")
```
**核心策略**: 分批委派 code-developer 执行修复
```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.
## Actions
${actions.map(a => `- [${a.debt_id}] ${a.action} (file: ${a.file})`).join('\n')}
## Instructions
- Read each target file before modifying
- Apply the specified fix
- Preserve backward compatibility
- 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
// 基本语法检查
const syntaxResult = Bash(`npx tsc --noEmit 2>&1 || python -m py_compile *.py 2>&1 || echo "skip"`)
const hasSyntaxErrors = /error/i.test(syntaxResult) && !/skip/.test(syntaxResult)
// 基本 lint 检查
const lintResult = Bash(`npx eslint --no-error-on-unmatched-pattern src/ 2>&1 || echo "skip"`)
const hasLintErrors = /error/i.test(lintResult) && !/skip/.test(lintResult)
// 更新修复统计
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'
}
// 保存修复日志
Bash(`mkdir -p "${sessionFolder}/fixes"`)
Write(`${sessionFolder}/fixes/fix-log.json`, JSON.stringify(fixResults, null, 2))
// 更新 shared memory
sharedMemory.fix_results = fixResults
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
```
### Phase 5: Report to Coordinator
```javascript
const statusMsg = `修复 ${fixResults.items_fixed}/${allActions.length} 项, 语法: ${fixResults.self_validation.syntax_check}, lint: ${fixResults.self_validation.lint_check}`
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 }
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [executor] Fix Results
**Task**: ${task.subject}
**Status**: ${fixResults.items_failed === 0 ? 'ALL FIXED' : 'PARTIAL'}
### 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
| Scenario | Resolution |
|----------|------------|
| No TDFIX-* tasks available | Idle, wait for coordinator |
| Remediation plan missing | Request plan from shared memory, report error if empty |
| code-developer fails | Retry once, skip item on second failure |
| Syntax check fails after fix | Revert change, mark item as failed |
| Lint errors introduced | Attempt auto-fix with eslint --fix, report if persistent |
| File not found | Skip item, log warning |

View File

@@ -0,0 +1,165 @@
# Command: create-plan
> 使用 gemini CLI 创建结构化治理方案。将 quick-wins 归为立即执行systematic 归为中期治理,识别预防机制用于长期改善。输出 remediation-plan.md。
## When to Use
- Phase 3 of Planner
- 评估矩阵已就绪,需要创建治理方案
- 债务项已按优先级象限分组
**Trigger conditions**:
- TDPLAN-* 任务进入 Phase 3
- 评估数据可用priority-matrix.json
- 需要 CLI 辅助生成详细修复建议
## Strategy
### Delegation Mode
**Mode**: CLI Analysis + Template Generation
**CLI Tool**: `gemini` (primary)
**CLI Mode**: `analysis`
### Decision Logic
```javascript
// 方案生成策略
if (quickWins.length + strategic.length <= 5) {
// 少量项目:内联生成方案
mode = 'inline'
} else {
// 较多项目CLI 辅助生成详细修复步骤
mode = 'cli-assisted'
}
```
## Execution Steps
### Step 1: Context Preparation
```javascript
// 准备债务摘要供 CLI 分析
const debtSummary = debtInventory
.filter(i => i.priority_quadrant === 'quick-win' || i.priority_quadrant === 'strategic')
.map(i => `[${i.id}] [${i.priority_quadrant}] [${i.dimension}] ${i.file}:${i.line} - ${i.description} (impact: ${i.impact_score}, cost: ${i.cost_score})`)
.join('\n')
// 读取相关源文件获取上下文
const affectedFiles = [...new Set(debtInventory.map(i => i.file).filter(Boolean))]
const fileContext = affectedFiles.slice(0, 20).map(f => `@${f}`).join(' ')
```
### Step 2: Execute Strategy
```javascript
if (mode === 'inline') {
// 内联生成方案
for (const item of quickWins) {
item.remediation_steps = [
`Read ${item.file}`,
`Apply fix: ${item.suggestion || 'Resolve ' + item.description}`,
`Verify fix with relevant tests`
]
}
for (const item of strategic) {
item.remediation_steps = [
`Analyze impact scope of ${item.file}`,
`Plan refactoring: ${item.suggestion || 'Address ' + item.description}`,
`Implement changes incrementally`,
`Run full test suite to verify`
]
}
} else {
// CLI 辅助生成修复方案
const prompt = `PURPOSE: Create detailed remediation steps for each technical debt item, grouped into actionable phases
TASK: • For each quick-win item, generate specific fix steps (1-3 steps) • For each strategic item, generate a refactoring plan (3-5 steps) • Identify prevention mechanisms based on recurring patterns • Group related items that should be fixed together
MODE: analysis
CONTEXT: ${fileContext}
EXPECTED: Structured remediation plan with: phase name, items, steps per item, dependencies between fixes, estimated time per phase
CONSTRAINTS: Focus on backward-compatible changes, prefer incremental fixes over big-bang refactoring
## Debt Items to Plan
${debtSummary}
## Recurring Patterns
${[...new Set(debtInventory.map(i => i.dimension))].map(d => {
const count = debtInventory.filter(i => i.dimension === d).length
return `- ${d}: ${count} items`
}).join('\n')}`
Bash(`ccw cli -p "${prompt}" --tool gemini --mode analysis --rule planning-breakdown-task-steps`, {
run_in_background: true
})
// 等待 CLI 完成,解析结果
}
```
### Step 3: Result Processing
```javascript
// 生成 Markdown 治理方案
function generatePlanMarkdown(plan, validation) {
return `# Tech Debt Remediation Plan
## Overview
- **Total Actions**: ${validation.total_actions}
- **Files Affected**: ${validation.files_affected.length}
- **Total Estimated Effort**: ${validation.total_effort} points
## Phase 1: Quick Wins (Immediate)
> High impact, low cost items for immediate action.
${plan.phases[0].actions.map((a, i) => `### ${i + 1}. ${a.debt_id}: ${a.action}
- **File**: ${a.file || 'N/A'}
- **Type**: ${a.type}
${a.steps ? a.steps.map(s => `- [ ] ${s}`).join('\n') : ''}`).join('\n\n')}
## Phase 2: Systematic (Medium-term)
> High impact items requiring structured refactoring.
${plan.phases[1].actions.map((a, i) => `### ${i + 1}. ${a.debt_id}: ${a.action}
- **File**: ${a.file || 'N/A'}
- **Type**: ${a.type}
${a.steps ? a.steps.map(s => `- [ ] ${s}`).join('\n') : ''}`).join('\n\n')}
## Phase 3: Prevention (Long-term)
> Mechanisms to prevent future debt accumulation.
${plan.phases[2].actions.map((a, i) => `### ${i + 1}. ${a.action}
- **Dimension**: ${a.dimension || 'general'}
- **Type**: ${a.type}`).join('\n\n')}
## Execution Notes
- Execute Phase 1 first for maximum ROI
- Phase 2 items may require feature branches
- Phase 3 should be integrated into CI/CD pipeline
`
}
```
## Output Format
```
## Remediation Plan Created
### Phases: 3
### Quick Wins: [count] actions
### Systematic: [count] actions
### Prevention: [count] actions
### Files Affected: [count]
### Output: [sessionFolder]/plan/remediation-plan.md
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| CLI returns unstructured text | Parse manually, extract action items |
| No quick-wins available | Focus plan on systematic and prevention |
| File references invalid | Verify with Glob, skip non-existent files |
| CLI timeout | Generate plan from heuristic data only |
| Agent/CLI failure | Retry once, then inline generation |
| Timeout (>5 min) | Report partial plan, notify planner |

View File

@@ -0,0 +1,287 @@
# Role: planner
技术债务治理方案规划师。基于评估矩阵创建分阶段治理方案quick-wins 立即执行、systematic 中期系统治理、prevention 长期预防机制。产出 remediation-plan.md。
## Role Identity
- **Name**: `planner`
- **Task Prefix**: `TDPLAN-*`
- **Responsibility**: Orchestration治理规划
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[planner]`
## Role Boundaries
### MUST
- 仅处理 `TDPLAN-*` 前缀的任务
- 所有输出必须带 `[planner]` 标识
- 基于评估数据制定可行的治理方案
- 更新 shared memory 中的 remediation_plan
### MUST NOT
- 修改源代码或测试代码
- 执行修复操作
- 为其他角色创建任务
- 直接与其他 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
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `create-plan` | [commands/create-plan.md](commands/create-plan.md) | Phase 3 | 分阶段治理方案生成 |
### Subagent Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `cli-explore-agent` | create-plan.md | 代码库探索验证方案可行性 |
### CLI Capabilities
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | create-plan.md | 治理方案生成 |
## 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
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: '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 {}
const debtInventory = sharedMemory.debt_inventory || []
// 加载优先级矩阵
let priorityMatrix = {}
try {
priorityMatrix = JSON.parse(Read(`${sessionFolder}/assessment/priority-matrix.json`))
} catch {}
// 分组
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')
```
### Phase 3: Create Remediation Plan
```javascript
// Read commands/create-plan.md for full implementation
Read("commands/create-plan.md")
```
**核心策略**: 3 阶段治理方案
```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)
}
]
}
function determineActionType(item) {
const typeMap = {
'code': 'refactor',
'architecture': 'restructure',
'testing': 'add-tests',
'dependency': 'update-deps',
'documentation': 'add-docs'
}
return typeMap[item.dimension] || 'refactor'
}
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
}
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'
}
```
### 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
}
// 保存治理方案
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))
// 更新 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))
```
### Phase 5: Report to Coordinator
```javascript
const planSummary = plan.phases.map(p => `${p.name}: ${p.actions.length} actions`).join(', ')
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`
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [planner] Remediation Plan
**Task**: ${task.subject}
**Total Actions**: ${validation.total_actions}
**Files Affected**: ${validation.files_affected.length}
### 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
| Scenario | Resolution |
|----------|------------|
| No TDPLAN-* tasks available | Idle, wait for coordinator |
| Assessment data empty | Create minimal plan based on debt inventory |
| No quick-wins found | Skip Phase 1, focus on systematic |
| CLI analysis fails | Fall back to heuristic plan generation |
| Too many items for single plan | Split into multiple phases with priorities |

View File

@@ -0,0 +1,198 @@
# Command: scan-debt
> 多维度 CLI Fan-out 技术债务扫描。从代码质量、架构、测试、依赖、文档 5 个维度并行分析代码,发现技术债务。
## When to Use
- Phase 3 of Scanner
- 需要对代码库进行多维度技术债务扫描
- 复杂度为 Medium 或 High 时使用 CLI Fan-out
**Trigger conditions**:
- TDSCAN-* 任务进入 Phase 3
- 复杂度评估为 Medium/High
- 需要深度分析超出 ACE 搜索能力
## Strategy
### Delegation Mode
**Mode**: CLI Fan-out
**CLI Tool**: `gemini` (primary)
**CLI Mode**: `analysis`
**Parallel Dimensions**: 3-5根据复杂度
### Decision Logic
```javascript
// 复杂度决定扫描策略
if (complexity === 'Low') {
// ACE 搜索 + Grep 内联分析(不使用 CLI
mode = 'inline'
} else if (complexity === 'Medium') {
// CLI Fan-out: 3 个核心维度
mode = 'cli-fanout'
activeDimensions = ['code', 'testing', 'dependency']
} else {
// CLI Fan-out: 所有 5 个维度
mode = 'cli-fanout'
activeDimensions = dimensions
}
```
## Execution Steps
### Step 1: Context Preparation
```javascript
// 确定扫描范围
const projectRoot = Bash(`git rev-parse --show-toplevel 2>/dev/null || pwd`).trim()
const scanScope = task.description.match(/scope:\s*(.+)/)?.[1] || '**/*'
// 获取变更文件用于聚焦扫描
const changedFiles = Bash(`git diff --name-only HEAD~10 2>/dev/null || echo ""`)
.split('\n').filter(Boolean)
// 构建文件上下文
const fileContext = changedFiles.length > 0
? changedFiles.map(f => `@${f}`).join(' ')
: `@${scanScope}`
```
### Step 2: Execute Strategy
```javascript
if (mode === 'inline') {
// 快速内联扫描
const aceResults = mcp__ace-tool__search_context({
project_root_path: projectRoot,
query: "code smells, TODO/FIXME, deprecated APIs, complex functions, dead code, missing tests, circular imports"
})
// 解析 ACE 结果并分类到维度
} else {
// CLI Fan-out: 每个维度一个 CLI 调用
const dimensionPrompts = {
'code': `PURPOSE: Identify code quality debt - complexity, duplication, code smells
TASK: • Find functions with cyclomatic complexity > 10 • Detect code duplication (>20 lines) • Identify code smells (God class, long method, feature envy) • Find TODO/FIXME/HACK comments • Detect dead code and unused exports
MODE: analysis
CONTEXT: ${fileContext}
EXPECTED: List of findings with severity (critical/high/medium/low), file:line, description, estimated fix effort (small/medium/large)
CONSTRAINTS: Focus on actionable items, skip generated code`,
'architecture': `PURPOSE: Identify architecture debt - coupling, circular dependencies, layering violations
TASK: • Detect circular dependencies between modules • Find tight coupling between components • Identify layering violations (e.g., UI importing DB) • Check for God modules with too many responsibilities • Find missing abstraction layers
MODE: analysis
CONTEXT: ${fileContext}
EXPECTED: Architecture debt findings with severity, affected modules, dependency graph issues
CONSTRAINTS: Focus on structural issues, not style`,
'testing': `PURPOSE: Identify testing debt - coverage gaps, test quality, missing test types
TASK: • Find modules without any test files • Identify complex logic without test coverage • Check for test anti-patterns (flaky tests, hardcoded values) • Find missing edge case tests • Detect test files that import from test utilities incorrectly
MODE: analysis
CONTEXT: ${fileContext}
EXPECTED: Testing debt findings with severity, affected files, missing test type (unit/integration/e2e)
CONSTRAINTS: Focus on high-risk untested code paths`,
'dependency': `PURPOSE: Identify dependency debt - outdated packages, vulnerabilities, unnecessary deps
TASK: • Find outdated major-version dependencies • Identify known vulnerability packages • Detect unused dependencies • Find duplicate functionality from different packages • Check for pinned vs range versions
MODE: analysis
CONTEXT: @package.json @package-lock.json @requirements.txt @go.mod @pom.xml
EXPECTED: Dependency debt with severity, package name, current vs latest version, CVE references
CONSTRAINTS: Focus on security and compatibility risks`,
'documentation': `PURPOSE: Identify documentation debt - missing docs, stale docs, undocumented APIs
TASK: • Find public APIs without JSDoc/docstrings • Identify README files that are outdated • Check for missing architecture documentation • Find configuration options without documentation • Detect stale comments that don't match code
MODE: analysis
CONTEXT: ${fileContext}
EXPECTED: Documentation debt with severity, file:line, type (missing/stale/incomplete)
CONSTRAINTS: Focus on public interfaces and critical paths`
}
for (const dimension of activeDimensions) {
const prompt = dimensionPrompts[dimension]
if (!prompt) continue
Bash(`ccw cli -p "${prompt}" --tool gemini --mode analysis --rule analysis-analyze-code-patterns`, {
run_in_background: true
})
}
// 等待所有 CLI 完成hook 回调通知)
}
```
### Step 3: Result Processing
```javascript
// 聚合所有维度的结果
const allFindings = []
// 从 CLI 输出解析结果
for (const dimension of activeDimensions) {
const findings = parseCliOutput(cliResults[dimension])
for (const finding of findings) {
finding.dimension = dimension
allFindings.push(finding)
}
}
// 去重:相同 file:line 的发现合并
function deduplicateFindings(findings) {
const seen = new Set()
const unique = []
for (const f of findings) {
const key = `${f.file}:${f.line}:${f.dimension}`
if (!seen.has(key)) {
seen.add(key)
unique.push(f)
}
}
return unique
}
const deduped = deduplicateFindings(allFindings)
// 按严重性排序
deduped.sort((a, b) => {
const order = { critical: 0, high: 1, medium: 2, low: 3 }
return (order[a.severity] || 3) - (order[b.severity] || 3)
})
```
## Output Format
```
## Debt Scan Results
### Dimensions Scanned: [list]
### Complexity: [Low|Medium|High]
### Findings by Dimension
#### Code Quality ([count])
- [file:line] [severity] - [description]
#### Architecture ([count])
- [module] [severity] - [description]
#### Testing ([count])
- [file:line] [severity] - [description]
#### Dependency ([count])
- [package] [severity] - [description]
#### Documentation ([count])
- [file:line] [severity] - [description]
### Total Debt Items: [count]
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| CLI tool unavailable | Fall back to ACE search + Grep inline analysis |
| CLI returns empty for a dimension | Note incomplete dimension, continue others |
| Too many findings (>100) | Prioritize critical/high, summarize medium/low |
| Timeout on CLI call | Use partial results, note incomplete dimensions |
| Agent/CLI failure | Retry once, then fallback to inline execution |
| Timeout (>5 min per dimension) | Report partial results, notify scanner |

View File

@@ -0,0 +1,258 @@
# Role: scanner
多维度技术债务扫描器。扫描代码库的 5 个维度:代码质量、架构、测试、依赖、文档,生成结构化债务清单。通过 CLI Fan-out 并行分析,产出 debt-inventory.json。
## Role Identity
- **Name**: `scanner`
- **Task Prefix**: `TDSCAN-*`
- **Responsibility**: Orchestration多维度扫描编排
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[scanner]`
## Role Boundaries
### MUST
- 仅处理 `TDSCAN-*` 前缀的任务
- 所有输出必须带 `[scanner]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 严格在债务扫描职责范围内工作
### MUST NOT
- 编写或修改代码
- 执行修复操作
- 为其他角色创建任务
- 直接与其他 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
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `scan-debt` | [commands/scan-debt.md](commands/scan-debt.md) | Phase 3 | 多维度 CLI Fan-out 扫描 |
### Subagent Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `cli-explore-agent` | scan-debt.md | 代码库结构探索 |
### CLI Capabilities
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | scan-debt.md | 多维度代码分析 |
## 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
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Context Loading
```javascript
// 确定扫描范围
const scanScope = task.description.match(/scope:\s*(.+)/)?.[1] || '**/*'
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
// 读取 shared memory
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
// 检测项目类型和框架
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'
// 5 个扫描维度
const dimensions = ["code", "architecture", "testing", "dependency", "documentation"]
// 评估复杂度
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)
```
### Phase 3: Multi-Dimension Scan
```javascript
// Read commands/scan-debt.md for full CLI Fan-out implementation
Read("commands/scan-debt.md")
```
**核心策略**: 按维度并行执行 CLI 分析
```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 {
// CLI Fan-out: 每个维度一个 CLI 调用
for (const dimension of dimensions) {
Bash(`ccw cli -p "..." --tool gemini --mode analysis`, { run_in_background: true })
}
// 等待所有 CLI 完成
}
```
### Phase 4: Aggregate into Debt Inventory
```javascript
// 聚合所有维度的发现
const debtInventory = []
// 为每个发现项创建标准化条目
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'
})
}
// 更新 shared memory
sharedMemory.debt_inventory = debtInventory
sharedMemory.debt_score_before = debtInventory.length
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
// 保存债务清单
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))
```
### Phase 5: Report to Coordinator
```javascript
const resultSummary = `发现 ${debtInventory.length} 项技术债务(${dimensions.map(d => `${d}: ${debtInventory.filter(i => i.dimension === d).length}`).join(', ')}`
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`
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [scanner] Debt Scan Results
**Task**: ${task.subject}
**Dimensions**: ${dimensions.join(', ')}
**Status**: ${debtInventory.length > 0 ? 'Debt Found' : 'Clean'}
### 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
| Scenario | Resolution |
|----------|------------|
| No TDSCAN-* tasks available | Idle, wait for coordinator assignment |
| CLI tool unavailable | Fall back to ACE search + Grep inline analysis |
| Scan scope too broad | Narrow to src/ directory, report partial results |
| All dimensions return empty | Report clean scan, notify coordinator |
| CLI timeout | Use partial results, note incomplete dimensions |
| Critical issue beyond scope | SendMessage debt_items_found to coordinator |

View File

@@ -0,0 +1,199 @@
# Command: verify
> 回归测试与质量验证。运行测试套件、类型检查、lint、可选 CLI 质量分析。对比 debt_score_before vs debt_score_after 评估改善程度。
## When to Use
- Phase 3 of Validator
- 修复操作已完成,需要验证结果
- Fix-Verify 循环中的验证阶段
**Trigger conditions**:
- TDVAL-* 任务进入 Phase 3
- 修复日志可用fix-log.json
- 需要对比 before/after 指标
## Strategy
### Delegation Mode
**Mode**: Sequential Checks + Optional CLI Analysis
**CLI Tool**: `gemini` (for quality comparison)
**CLI Mode**: `analysis`
### Decision Logic
```javascript
// 验证策略选择
const checks = ['test_suite', 'type_check', 'lint_check']
// 可选CLI 质量分析(仅当修改文件较多时)
if (modifiedFiles.length > 5) {
checks.push('cli_quality_analysis')
}
// Fix-Verify 循环中的验证:聚焦于回归文件
const isFixVerify = task.description.includes('fix-verify')
if (isFixVerify) {
// 仅验证上次回归的文件
targetScope = 'regression_files_only'
}
```
## Execution Steps
### Step 1: Context Preparation
```javascript
// 获取修改文件列表
const modifiedFiles = fixLog.files_modified || []
// 获取原始债务分数
const debtScoreBefore = sharedMemory.debt_score_before || 0
// 检测可用的验证工具
const hasNpm = Bash(`which npm 2>/dev/null && echo "yes" || echo "no"`).trim() === 'yes'
const hasTsc = Bash(`which npx 2>/dev/null && npx tsc --version 2>/dev/null && echo "yes" || echo "no"`).includes('yes')
const hasEslint = Bash(`npx eslint --version 2>/dev/null && echo "yes" || echo "no"`).includes('yes')
const hasPytest = Bash(`which pytest 2>/dev/null && echo "yes" || echo "no"`).trim() === 'yes'
```
### Step 2: Execute Strategy
```javascript
// === Check 1: Test Suite ===
let testOutput = ''
let testsPassed = true
let testRegressions = 0
if (hasNpm) {
testOutput = Bash(`npm test 2>&1 || true`)
} else if (hasPytest) {
testOutput = Bash(`python -m pytest 2>&1 || true`)
} else {
testOutput = 'no-test-runner'
}
if (testOutput !== 'no-test-runner') {
testsPassed = !/FAIL|error|failed/i.test(testOutput)
testRegressions = testsPassed ? 0 : (testOutput.match(/(\d+) failed/)?.[1] || 1) * 1
}
// === Check 2: Type Checking ===
let typeErrors = 0
if (hasTsc) {
const tscOutput = Bash(`npx tsc --noEmit 2>&1 || true`)
typeErrors = (tscOutput.match(/error TS/g) || []).length
}
// === Check 3: Linting ===
let lintErrors = 0
if (hasEslint && modifiedFiles.length > 0) {
const lintOutput = Bash(`npx eslint --no-error-on-unmatched-pattern ${modifiedFiles.join(' ')} 2>&1 || true`)
lintErrors = (lintOutput.match(/(\d+) error/)?.[0]?.match(/\d+/)?.[0] || 0) * 1
}
// === Check 4: Optional CLI Quality Analysis ===
let qualityImprovement = 0
if (checks.includes('cli_quality_analysis')) {
const prompt = `PURPOSE: Compare code quality before and after tech debt cleanup to measure improvement
TASK: • Analyze the modified files for quality metrics • Compare complexity, duplication, naming quality • Assess if the changes actually reduced debt • Identify any new issues introduced
MODE: analysis
CONTEXT: ${modifiedFiles.map(f => `@${f}`).join(' ')}
EXPECTED: Quality comparison with: metrics_before, metrics_after, improvement_score (0-100), new_issues_found
CONSTRAINTS: Focus on the specific changes, not overall project quality`
Bash(`ccw cli -p "${prompt}" --tool gemini --mode analysis --rule analysis-review-code-quality`, {
run_in_background: true
})
// 等待 CLI 完成,解析质量改善分数
}
// === 计算债务分数 ===
// 已修复的项不计入 after 分数
const fixedDebtIds = new Set(
(sharedMemory.fix_results?.files_modified || [])
.flatMap(f => debtInventory.filter(i => i.file === f).map(i => i.id))
)
const debtScoreAfter = debtInventory.filter(i => !fixedDebtIds.has(i.id)).length
```
### Step 3: Result Processing
```javascript
const totalRegressions = testRegressions + typeErrors + lintErrors
const passed = totalRegressions === 0
// 如果有少量回归,尝试通过 code-developer 修复
if (totalRegressions > 0 && totalRegressions <= 3) {
const regressionDetails = []
if (testRegressions > 0) regressionDetails.push(`${testRegressions} test failures`)
if (typeErrors > 0) regressionDetails.push(`${typeErrors} type errors`)
if (lintErrors > 0) regressionDetails.push(`${lintErrors} lint errors`)
Task({
subagent_type: "code-developer",
run_in_background: false,
description: `Fix ${totalRegressions} regressions from debt cleanup`,
prompt: `## Goal
Fix regressions introduced by tech debt cleanup.
## Regressions
${regressionDetails.join('\n')}
## Modified Files
${modifiedFiles.map(f => `- ${f}`).join('\n')}
## Test Output (if failed)
${testOutput.split('\n').filter(l => /FAIL|Error|error/i.test(l)).slice(0, 20).join('\n')}
## Constraints
- Fix ONLY the regressions, do not undo the debt fixes
- Preserve the debt cleanup changes
- Do NOT skip tests or add suppressions`
})
// Re-run checks after fix attempt
// ... (simplified: re-check test suite)
}
// 生成最终验证结果
const validationReport = {
passed,
regressions: totalRegressions,
debt_score_before: debtScoreBefore,
debt_score_after: debtScoreAfter,
improvement_percentage: debtScoreBefore > 0
? Math.round(((debtScoreBefore - debtScoreAfter) / debtScoreBefore) * 100)
: 0
}
```
## Output Format
```
## Validation Results
### Status: [PASS|FAIL]
### Regressions: [count]
- Test Suite: [PASS|FAIL] ([n] regressions)
- Type Check: [PASS|FAIL] ([n] errors)
- Lint: [PASS|FAIL] ([n] errors)
- Quality: [IMPROVED|NO_CHANGE]
### Debt Score
- Before: [score]
- After: [score]
- Improvement: [%]%
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No test runner available | Skip test check, rely on type+lint |
| tsc not available | Skip type check, rely on test+lint |
| eslint not available | Skip lint check, rely on test+type |
| All checks unavailable | Report minimal validation, warn coordinator |
| Fix attempt introduces new regressions | Revert fix, report original regressions |
| CLI quality analysis times out | Skip quality analysis, use debt score comparison only |

View File

@@ -0,0 +1,263 @@
# Role: validator
技术债务清理结果验证者。运行测试套件验证无回归、执行类型检查和 lint、通过 CLI 分析代码质量改善程度。对比 before/after 债务分数,生成 validation-report.json。
## Role Identity
- **Name**: `validator`
- **Task Prefix**: `TDVAL-*`
- **Responsibility**: Validation清理结果验证
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[validator]`
## Role Boundaries
### MUST
- 仅处理 `TDVAL-*` 前缀的任务
- 所有输出必须带 `[validator]` 标识
- 运行完整验证流程测试、类型检查、lint、质量分析
- 如发现回归,报告 regression_found
### MUST NOT
- 直接修复代码(仅在小修复时通过 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
### Available Commands
| Command | File | Phase | Description |
|---------|------|-------|-------------|
| `verify` | [commands/verify.md](commands/verify.md) | Phase 3 | 回归测试与质量验证 |
### Subagent Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `code-developer` | verify.md | 小修复尝试(验证失败时) |
### CLI Capabilities
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `gemini` | analysis | verify.md | 代码质量改善分析 |
## 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
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: '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 {}
const debtInventory = sharedMemory.debt_inventory || []
const fixResults = sharedMemory.fix_results || {}
const debtScoreBefore = sharedMemory.debt_score_before || debtInventory.length
// 加载修复日志
let fixLog = {}
try { fixLog = JSON.parse(Read(`${sessionFolder}/fixes/fix-log.json`)) } catch {}
const modifiedFiles = fixLog.files_modified || []
```
### Phase 3: Run Validation Checks
```javascript
// Read commands/verify.md for full implementation
Read("commands/verify.md")
```
**核心策略**: 4 层验证
```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 }
}
// 1. 测试套件
const testResult = Bash(`npm test 2>&1 || npx vitest run 2>&1 || 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
}
// 2. 类型检查
const typeResult = Bash(`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
}
// 3. Lint 检查
const lintResult = Bash(`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
}
// 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
}
```
### 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
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
}
// 保存验证报告
Bash(`mkdir -p "${sessionFolder}/validation"`)
Write(`${sessionFolder}/validation/validation-report.json`, JSON.stringify(report, null, 2))
// 更新 shared memory
sharedMemory.validation_results = report
sharedMemory.debt_score_after = report.debt_score_after
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
```
### 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})`
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 }
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [validator] Validation Results
**Task**: ${task.subject}
**Status**: ${passed ? 'PASS' : 'FAIL - Regressions 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 |
### Debt Score
- Before: ${debtScoreBefore}
- After: ${report.debt_score_after}
- Improvement: ${report.improvement_percentage}%
### 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
| Scenario | Resolution |
|----------|------------|
| No TDVAL-* tasks available | Idle, wait for coordinator |
| Test environment broken | Report error, suggest manual fix |
| No test suite found | Skip test check, validate with type+lint only |
| Fix log empty | Validate all source files, report minimal analysis |
| Type check fails | Attempt code-developer fix for type errors |
| Critical regression (>10) | Report immediately, do not attempt fix |

View File

@@ -0,0 +1,132 @@
{
"team_name": "tech-debt",
"version": "1.0.0",
"description": "技术债务识别与清理团队 - 融合\"债务扫描\"、\"量化评估\"、\"治理规划\"、\"清理执行\"、\"验证回归\"五大能力域,形成扫描→评估→规划→清理→验证的闭环",
"skill_entry": "team-tech-debt",
"invocation": "Skill(skill=\"team-tech-debt\", args=\"--role=coordinator ...\")",
"roles": {
"coordinator": {
"name": "coordinator",
"responsibility": "Orchestration",
"task_prefix": null,
"description": "技术债务治理协调者。编排 pipeline需求澄清 → 模式选择 → 团队创建 → 任务分发 → 监控协调 → 质量门控 → 结果汇报",
"message_types_sent": ["mode_selected", "quality_gate", "task_unblocked", "error", "shutdown"],
"message_types_received": ["scan_complete", "assessment_complete", "plan_ready", "fix_complete", "validation_complete", "regression_found", "error"],
"commands": ["dispatch", "monitor"]
},
"scanner": {
"name": "scanner",
"responsibility": "Orchestration (多维度债务扫描)",
"task_prefix": "TDSCAN",
"description": "技术债务扫描员。多维度扫描代码库:代码债务、架构债务、测试债务、依赖债务、文档债务,生成债务清单",
"message_types_sent": ["scan_complete", "debt_items_found", "error"],
"message_types_received": [],
"commands": ["scan-debt"],
"cli_tools": ["gemini"],
"subagents": ["cli-explore-agent"]
},
"assessor": {
"name": "assessor",
"responsibility": "Read-only analysis (量化评估)",
"task_prefix": "TDEVAL",
"description": "技术债务评估师。量化评估债务项的影响和修复成本,按优先级矩阵排序,生成评估报告",
"message_types_sent": ["assessment_complete", "error"],
"message_types_received": [],
"commands": ["evaluate"],
"cli_tools": ["gemini"]
},
"planner": {
"name": "planner",
"responsibility": "Orchestration (治理规划)",
"task_prefix": "TDPLAN",
"description": "技术债务治理规划师。制定分阶段治理方案:短期速赢、中期系统性治理、长期预防机制",
"message_types_sent": ["plan_ready", "plan_revision", "error"],
"message_types_received": [],
"commands": ["create-plan"],
"cli_tools": ["gemini"],
"subagents": ["cli-explore-agent"]
},
"executor": {
"name": "executor",
"responsibility": "Code generation (债务清理执行)",
"task_prefix": "TDFIX",
"description": "技术债务清理执行者。按优先级执行重构、依赖更新、代码清理、测试补充等治理动作",
"message_types_sent": ["fix_complete", "fix_progress", "error"],
"message_types_received": [],
"commands": ["remediate"],
"subagents": ["code-developer"]
},
"validator": {
"name": "validator",
"responsibility": "Validation (清理验证)",
"task_prefix": "TDVAL",
"description": "技术债务清理验证者。验证清理后无回归、质量指标提升、债务确实消除",
"message_types_sent": ["validation_complete", "regression_found", "error"],
"message_types_received": [],
"commands": ["verify"],
"subagents": ["code-developer"],
"cli_tools": ["gemini"]
}
},
"pipeline_modes": {
"scan": {
"description": "仅扫描评估,不执行修复(审计模式)",
"stages": ["TDSCAN", "TDEVAL"],
"entry_role": "scanner"
},
"remediate": {
"description": "完整闭环:扫描 → 评估 → 规划 → 修复 → 验证",
"stages": ["TDSCAN", "TDEVAL", "TDPLAN", "TDFIX", "TDVAL"],
"entry_role": "scanner"
},
"targeted": {
"description": "定向修复:用户已知债务项,直接规划执行",
"stages": ["TDPLAN", "TDFIX", "TDVAL"],
"entry_role": "planner"
}
},
"fix_verify_loop": {
"max_iterations": 3,
"trigger": "validation fails or regression found",
"participants": ["executor", "validator"],
"flow": "TDFIX-fix → TDVAL-verify → evaluate"
},
"shared_memory": {
"file": "shared-memory.json",
"fields": {
"debt_inventory": { "owner": "scanner", "type": "array" },
"assessment_matrix": { "owner": "assessor", "type": "object" },
"remediation_plan": { "owner": "planner", "type": "object" },
"fix_results": { "owner": "executor", "type": "object" },
"validation_results": { "owner": "validator", "type": "object" },
"debt_score_before": { "owner": "assessor", "type": "number" },
"debt_score_after": { "owner": "validator", "type": "number" }
}
},
"collaboration_patterns": [
"CP-1: Linear Pipeline (scan/remediate/targeted mode)",
"CP-2: Review-Fix Cycle (Executor ↔ Validator loop)",
"CP-3: Fan-out (Scanner multi-dimension scan)",
"CP-5: Escalation (Worker → Coordinator → User)",
"CP-6: Incremental Delivery (batch remediation)",
"CP-10: Post-Mortem (debt reduction report)"
],
"debt_dimensions": {
"code": { "name": "代码债务", "tools": ["static-analysis", "complexity-metrics"] },
"architecture": { "name": "架构债务", "tools": ["dependency-graph", "coupling-analysis"] },
"testing": { "name": "测试债务", "tools": ["coverage-analysis", "test-quality"] },
"dependency": { "name": "依赖债务", "tools": ["outdated-check", "vulnerability-scan"] },
"documentation": { "name": "文档债务", "tools": ["doc-coverage", "api-doc-check"] }
},
"session_directory": {
"pattern": ".workflow/.team/TD-{slug}-{date}",
"subdirectories": ["scan", "assessment", "plan", "fixes", "validation"]
}
}