mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
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:
262
.claude/skills/team-tech-debt/roles/assessor/role.md
Normal file
262
.claude/skills/team-tech-debt/roles/assessor/role.md
Normal 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 |
|
||||
Reference in New Issue
Block a user