mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 15:03:57 +08:00
feat(skills): update 12 team skills to v3 design patterns
- Update all 12 team-* SKILL.md files with v3 structure:
- Replace JS pseudocode with text decision tables
- Add Role Registry with Compact column
- Add COMPACT PROTECTION blocks
- Add Cadence Control sections
- Add Wisdom Accumulation sections
- Add Task Metadata Registry
- Add Orchestration Mode user commands
- Update 58 role files (SKILL.md + roles/*):
- Flat-file skills: team-brainstorm, team-issue, team-testing,
team-uidesign, team-planex, team-iterdev
- Folder-based skills: team-review, team-roadmap-dev, team-frontend,
team-quality-assurance, team-tech-debt, team-ultra-analyze
- Preserve special architectures:
- team-planex: 2-member (planner + executor only)
- team-tech-debt: Stop-Wait strategy (run_in_background:false)
- team-iterdev: 7 behavior protocol tables in coordinator
- All 12 teams reviewed for content completeness (PASS)
This commit is contained in:
@@ -1,60 +1,30 @@
|
||||
# Role: assessor
|
||||
# Assessor Role
|
||||
|
||||
技术债务量化评估师。对扫描发现的每项债务进行影响评分(1-5)和修复成本评分(1-5),划分优先级象限,生成 priority-matrix.json。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `assessor`
|
||||
- **Name**: `assessor` | **Tag**: `[assessor]`
|
||||
- **Task Prefix**: `TDEVAL-*`
|
||||
- **Responsibility**: Read-only analysis(量化评估)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[assessor]`
|
||||
- **Responsibility**: Read-only analysis (量化评估)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `TDEVAL-*` 前缀的任务
|
||||
- 所有输出必须带 `[assessor]` 标识
|
||||
- 基于数据量化评估债务优先级
|
||||
- 更新 shared memory 中的 priority_matrix
|
||||
- Only process `TDEVAL-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[assessor]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within quantitative assessment responsibility scope
|
||||
- Base evaluations on data from debt inventory
|
||||
|
||||
### MUST NOT
|
||||
- Modify source code or test code
|
||||
- Execute fix operations
|
||||
- Create tasks for other roles
|
||||
- Communicate directly with other worker roles (must go through coordinator)
|
||||
- Omit `[assessor]` identifier in any output
|
||||
|
||||
- 修改源代码或测试代码
|
||||
- 执行修复操作
|
||||
- 为其他角色创建任务
|
||||
- 直接与其他 worker 通信
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `assessment_complete` | assessor → coordinator | 评估完成 | 包含优先级矩阵摘要 |
|
||||
| `error` | assessor → coordinator | 评估失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "assessor",
|
||||
to: "coordinator",
|
||||
type: "assessment_complete",
|
||||
summary: "[assessor] 评估完成: 12 quick-wins, 8 strategic, 15 backlog, 7 defer"
|
||||
})
|
||||
```
|
||||
|
||||
### CLI 回退
|
||||
|
||||
若 `mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
|
||||
|
||||
```javascript
|
||||
Bash(`echo '${JSON.stringify({ from: "assessor", to: "coordinator", type: "assessment_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
|
||||
```
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -64,192 +34,147 @@ Bash(`echo '${JSON.stringify({ from: "assessor", to: "coordinator", type: "asses
|
||||
|---------|------|-------|-------------|
|
||||
| `evaluate` | [commands/evaluate.md](commands/evaluate.md) | Phase 3 | 影响/成本矩阵评估 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
> Assessor 不直接使用 subagent
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `gemini` | CLI | evaluate.md | 债务影响与修复成本评估 |
|
||||
|
||||
### CLI Capabilities
|
||||
> Assessor does not directly use subagents
|
||||
|
||||
| CLI Tool | Mode | Used By | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `gemini` | analysis | evaluate.md | 债务影响与修复成本评估 |
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `assessment_complete` | assessor -> coordinator | 评估完成 | 包含优先级矩阵摘要 |
|
||||
| `error` | assessor -> coordinator | 评估失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "assessor",
|
||||
to: "coordinator",
|
||||
type: <message-type>,
|
||||
summary: "[assessor] <task-prefix> complete: <task-subject>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from assessor --to coordinator --type <message-type> --summary \"[assessor] ...\" --ref <artifact-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('TDEVAL-') &&
|
||||
t.owner === 'assessor' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return // idle
|
||||
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `TDEVAL-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Load Debt Inventory
|
||||
|
||||
```javascript
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
|
||||
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
|
||||
| Debt inventory | shared-memory.debt_inventory OR `<session-folder>/scan/debt-inventory.json` | Yes |
|
||||
|
||||
const debtInventory = sharedMemory.debt_inventory || []
|
||||
if (debtInventory.length === 0) {
|
||||
// 尝试从文件加载
|
||||
try {
|
||||
const inventoryFile = JSON.parse(Read(`${sessionFolder}/scan/debt-inventory.json`))
|
||||
debtInventory.push(...(inventoryFile.items || []))
|
||||
} catch {}
|
||||
}
|
||||
**Loading steps**:
|
||||
|
||||
if (debtInventory.length === 0) {
|
||||
// 无债务项,直接报告
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "assessor",
|
||||
to: "coordinator", type: "assessment_complete",
|
||||
summary: `[assessor] 无债务项需要评估`
|
||||
})
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
return
|
||||
}
|
||||
```
|
||||
1. Extract session path from task description
|
||||
2. Read shared-memory.json
|
||||
3. Load debt_inventory from shared memory or fallback to debt-inventory.json file
|
||||
4. If debt_inventory is empty -> report empty assessment and exit
|
||||
|
||||
### Phase 3: Evaluate Each Item
|
||||
|
||||
```javascript
|
||||
// Read commands/evaluate.md for full CLI evaluation implementation
|
||||
Read("commands/evaluate.md")
|
||||
```
|
||||
Delegate to `commands/evaluate.md` if available, otherwise execute inline.
|
||||
|
||||
**核心策略**: 对每项债务评估 impact(1-5) + cost(1-5) + priority quadrant
|
||||
**Core Strategy**: For each debt item, evaluate impact(1-5) + cost(1-5) + priority quadrant
|
||||
|
||||
```javascript
|
||||
const evaluatedItems = []
|
||||
**Impact Score Mapping**:
|
||||
|
||||
for (const item of debtInventory) {
|
||||
// CLI 分析评估(批量处理以节约 API 调用)
|
||||
const evaluation = {
|
||||
...item,
|
||||
impact_score: 0, // 1-5, 业务影响
|
||||
cost_score: 0, // 1-5, 修复成本
|
||||
risk_if_unfixed: '', // 风险描述
|
||||
priority_quadrant: '' // quick-win / strategic / backlog / defer
|
||||
}
|
||||
| Severity | Impact Score |
|
||||
|----------|--------------|
|
||||
| critical | 5 |
|
||||
| high | 4 |
|
||||
| medium | 3 |
|
||||
| low | 1 |
|
||||
|
||||
// 基于严重性预评估
|
||||
const severityImpact = { critical: 5, high: 4, medium: 3, low: 1 }
|
||||
evaluation.impact_score = severityImpact[item.severity] || 3
|
||||
**Cost Score Mapping**:
|
||||
|
||||
// 基于预估工作量预评估
|
||||
const effortCost = { small: 1, medium: 3, large: 5 }
|
||||
evaluation.cost_score = effortCost[item.estimated_effort] || 3
|
||||
| Estimated Effort | Cost Score |
|
||||
|------------------|------------|
|
||||
| small | 1 |
|
||||
| medium | 3 |
|
||||
| large | 5 |
|
||||
| unknown | 3 |
|
||||
|
||||
// 象限划分
|
||||
if (evaluation.impact_score >= 4 && evaluation.cost_score <= 2) {
|
||||
evaluation.priority_quadrant = 'quick-win'
|
||||
} else if (evaluation.impact_score >= 4 && evaluation.cost_score >= 3) {
|
||||
evaluation.priority_quadrant = 'strategic'
|
||||
} else if (evaluation.impact_score <= 3 && evaluation.cost_score <= 2) {
|
||||
evaluation.priority_quadrant = 'backlog'
|
||||
} else {
|
||||
evaluation.priority_quadrant = 'defer'
|
||||
}
|
||||
**Priority Quadrant Classification**:
|
||||
|
||||
evaluatedItems.push(evaluation)
|
||||
}
|
||||
```
|
||||
| Impact | Cost | Quadrant | Description |
|
||||
|--------|------|----------|-------------|
|
||||
| >= 4 | <= 2 | quick-win | High impact, low cost |
|
||||
| >= 4 | >= 3 | strategic | High impact, high cost |
|
||||
| <= 3 | <= 2 | backlog | Low impact, low cost |
|
||||
| <= 3 | >= 3 | defer | Low impact, high cost |
|
||||
|
||||
**Evaluation record**:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `impact_score` | 1-5, business impact |
|
||||
| `cost_score` | 1-5, fix effort |
|
||||
| `risk_if_unfixed` | Risk description |
|
||||
| `priority_quadrant` | quick-win/strategic/backlog/defer |
|
||||
|
||||
### Phase 4: Generate Priority Matrix
|
||||
|
||||
```javascript
|
||||
const priorityMatrix = {
|
||||
evaluation_date: new Date().toISOString(),
|
||||
total_items: evaluatedItems.length,
|
||||
by_quadrant: {
|
||||
'quick-win': evaluatedItems.filter(i => i.priority_quadrant === 'quick-win'),
|
||||
'strategic': evaluatedItems.filter(i => i.priority_quadrant === 'strategic'),
|
||||
'backlog': evaluatedItems.filter(i => i.priority_quadrant === 'backlog'),
|
||||
'defer': evaluatedItems.filter(i => i.priority_quadrant === 'defer')
|
||||
},
|
||||
summary: {
|
||||
'quick-win': evaluatedItems.filter(i => i.priority_quadrant === 'quick-win').length,
|
||||
'strategic': evaluatedItems.filter(i => i.priority_quadrant === 'strategic').length,
|
||||
'backlog': evaluatedItems.filter(i => i.priority_quadrant === 'backlog').length,
|
||||
'defer': evaluatedItems.filter(i => i.priority_quadrant === 'defer').length
|
||||
}
|
||||
}
|
||||
**Matrix structure**:
|
||||
|
||||
// 排序:每个象限内按 impact_score 降序
|
||||
for (const quadrant of Object.keys(priorityMatrix.by_quadrant)) {
|
||||
priorityMatrix.by_quadrant[quadrant].sort((a, b) => b.impact_score - a.impact_score)
|
||||
}
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `evaluation_date` | ISO timestamp |
|
||||
| `total_items` | Count of evaluated items |
|
||||
| `by_quadrant` | Items grouped by quadrant |
|
||||
| `summary` | Count per quadrant |
|
||||
|
||||
// 保存评估结果
|
||||
Bash(`mkdir -p "${sessionFolder}/assessment"`)
|
||||
Write(`${sessionFolder}/assessment/priority-matrix.json`, JSON.stringify(priorityMatrix, null, 2))
|
||||
**Sorting**: Within each quadrant, sort by impact_score descending
|
||||
|
||||
// 更新 shared memory
|
||||
sharedMemory.priority_matrix = priorityMatrix.summary
|
||||
sharedMemory.debt_inventory = evaluatedItems
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
```
|
||||
**Save outputs**:
|
||||
|
||||
1. Write `<session-folder>/assessment/priority-matrix.json`
|
||||
2. Update shared-memory.json with `priority_matrix` summary and evaluated `debt_inventory`
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
const summaryText = Object.entries(priorityMatrix.summary)
|
||||
.map(([q, c]) => `${q}: ${c}`)
|
||||
.join(', ')
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "assessor",
|
||||
to: "coordinator",
|
||||
type: "assessment_complete",
|
||||
summary: `[assessor] 评估完成: ${summaryText}`,
|
||||
ref: `${sessionFolder}/assessment/priority-matrix.json`
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[assessor]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [assessor] Assessment Results
|
||||
**Report content**:
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Total Items**: ${evaluatedItems.length}
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Task | task.subject |
|
||||
| Total Items | Count of evaluated items |
|
||||
| Priority Matrix | Count per quadrant |
|
||||
| Top Quick-Wins | Top 5 quick-win items with details |
|
||||
| Priority Matrix File | Path to priority-matrix.json |
|
||||
|
||||
### Priority Matrix
|
||||
| Quadrant | Count | Description |
|
||||
|----------|-------|-------------|
|
||||
| Quick-Win | ${priorityMatrix.summary['quick-win']} | High impact, low cost |
|
||||
| Strategic | ${priorityMatrix.summary['strategic']} | High impact, high cost |
|
||||
| Backlog | ${priorityMatrix.summary['backlog']} | Low impact, low cost |
|
||||
| Defer | ${priorityMatrix.summary['defer']} | Low impact, high cost |
|
||||
|
||||
### Top Quick-Wins
|
||||
${priorityMatrix.by_quadrant['quick-win'].slice(0, 5).map(i => `- **[${i.dimension}]** ${i.file} - ${i.description} (impact: ${i.impact_score}, cost: ${i.cost_score})`).join('\n')}
|
||||
|
||||
### Priority Matrix
|
||||
${sessionFolder}/assessment/priority-matrix.json`,
|
||||
summary: `[assessor] TDEVAL complete: ${summaryText}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('TDEVAL-') && t.owner === 'assessor' &&
|
||||
t.status === 'pending' && t.blockedBy.length === 0
|
||||
)
|
||||
if (nextTasks.length > 0) { /* back to Phase 1 */ }
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
|
||||
@@ -1,69 +1,48 @@
|
||||
# Role: coordinator
|
||||
# Coordinator Role
|
||||
|
||||
技术债务治理团队协调者。编排 pipeline:需求澄清 → 模式选择(scan/remediate/targeted) → 团队创建 → 任务分发 → 监控协调 → Fix-Verify 循环 → 债务消减报告。
|
||||
技术债务治理团队协调者。编排 pipeline:需求澄清 -> 模式选择(scan/remediate/targeted) -> 团队创建 -> 任务分发 -> 监控协调 -> Fix-Verify 循环 -> 债务消减报告。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `coordinator`
|
||||
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
|
||||
- **Responsibility**: Orchestration
|
||||
- **Communication**: SendMessage to all teammates
|
||||
- **Output Tag**: `[coordinator]`
|
||||
- **Name**: `coordinator` | **Tag**: `[coordinator]`
|
||||
- **Responsibility**: Parse requirements -> Create team -> Dispatch tasks -> Monitor progress -> Report results
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 所有输出(SendMessage、team_msg、日志)必须带 `[coordinator]` 标识
|
||||
- 仅负责需求澄清、模式选择、任务创建/分发、进度监控、质量门控、结果汇报
|
||||
- 通过 TaskCreate 创建任务并分配给 worker 角色
|
||||
- 通过消息总线监控 worker 进度并路由消息
|
||||
- All output (SendMessage, team_msg, logs) must carry `[coordinator]` identifier
|
||||
- Only responsible for: requirement clarification, mode selection, task creation/dispatch, progress monitoring, quality gates, result reporting
|
||||
- Create tasks via TaskCreate and assign to worker roles
|
||||
- Monitor worker progress via message bus and route messages
|
||||
- Maintain session state persistence
|
||||
|
||||
### MUST NOT
|
||||
- Execute tech debt work directly (delegate to workers)
|
||||
- Modify task outputs (workers own their deliverables)
|
||||
- Call implementation subagents directly (cli-explore-agent, code-developer, etc.)
|
||||
- Modify source code or generate artifact files directly
|
||||
- Bypass worker roles to complete delegated work
|
||||
- Skip dependency validation when creating task chains
|
||||
- Omit `[coordinator]` identifier in any output
|
||||
|
||||
- 直接执行任何业务任务(扫描、评估、规划、修复、验证等)
|
||||
- 直接调用 cli-explore-agent、code-developer 等实现类 subagent
|
||||
- 直接修改源代码或生成产物文件
|
||||
- 绕过 worker 角色自行完成应委派的工作
|
||||
- 在输出中省略 `[coordinator]` 标识
|
||||
> **Core principle**: coordinator is the orchestrator, not the executor. All actual work must be delegated to worker roles via TaskCreate.
|
||||
|
||||
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
|
||||
---
|
||||
|
||||
## Message Types
|
||||
## Entry Router
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `mode_selected` | coordinator → all | 模式确定 | scan/remediate/targeted |
|
||||
| `plan_approval` | coordinator → user | TDPLAN 完成 | 呈现治理方案供审批(批准/修订/终止) |
|
||||
| `worktree_created` | coordinator → user | TDFIX 前 | Worktree 和分支已创建 |
|
||||
| `pr_created` | coordinator → user | TDVAL 通过 | PR 已创建,worktree 已清理 |
|
||||
| `quality_gate` | coordinator → user | 质量评估 | 通过/不通过/有条件通过 |
|
||||
| `task_unblocked` | coordinator → worker | 依赖解除 | 任务可执行 |
|
||||
| `error` | coordinator → user | 协调错误 | 阻塞性问题 |
|
||||
| `shutdown` | coordinator → all | 团队关闭 | 清理资源 |
|
||||
When coordinator is invoked, first detect the invocation type:
|
||||
|
||||
## Message Bus
|
||||
| Detection | Condition | Handler |
|
||||
|-----------|-----------|---------|
|
||||
| Worker callback | Message contains `[role-name]` tag from a known worker role | -> handleCallback: auto-advance pipeline |
|
||||
| Status check | Arguments contain "check" or "status" | -> handleCheck: output execution graph, no advancement |
|
||||
| Manual resume | Arguments contain "resume" or "continue" | -> handleResume: check worker states, advance pipeline |
|
||||
| New session | None of the above | -> Phase 0 (Session Resume Check) |
|
||||
|
||||
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
|
||||
For callback/check/resume: load `commands/monitor.md` and execute the appropriate handler, then STOP.
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "coordinator",
|
||||
to: "user",
|
||||
type: "mode_selected",
|
||||
summary: "[coordinator] 模式已选择: remediate"
|
||||
})
|
||||
```
|
||||
|
||||
### CLI 回退
|
||||
|
||||
若 `mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
|
||||
|
||||
```javascript
|
||||
Bash(`echo '${JSON.stringify({ from: "coordinator", to: "user", type: "mode_selected", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
|
||||
```
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -74,251 +53,334 @@ Bash(`echo '${JSON.stringify({ from: "coordinator", to: "user", type: "mode_sele
|
||||
| `dispatch` | [commands/dispatch.md](commands/dispatch.md) | Phase 3 | 任务链创建与依赖管理 |
|
||||
| `monitor` | [commands/monitor.md](commands/monitor.md) | Phase 4 | 消息总线轮询与协调循环 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
> Coordinator 不直接使用 subagent(通过 worker 角色间接使用)
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `TeamCreate` | Tool | Phase 2 | Team initialization |
|
||||
| `TaskCreate` | Tool | Phase 3 | Task chain creation |
|
||||
| `Task` | Tool | Phase 4 | Worker spawning |
|
||||
| `AskUserQuestion` | Tool | Phase 1 | Requirement clarification |
|
||||
|
||||
### CLI Capabilities
|
||||
> Coordinator does not directly use CLI analysis tools or implementation subagents
|
||||
|
||||
> Coordinator 不直接使用 CLI 分析工具
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
## Message Types
|
||||
|
||||
### Phase 1: Parse Arguments & Mode Detection
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `mode_selected` | coordinator -> all | 模式确定 | scan/remediate/targeted |
|
||||
| `plan_approval` | coordinator -> user | TDPLAN 完成 | 呈现治理方案供审批 |
|
||||
| `worktree_created` | coordinator -> user | TDFIX 前 | Worktree 和分支已创建 |
|
||||
| `pr_created` | coordinator -> user | TDVAL 通过 | PR 已创建,worktree 已清理 |
|
||||
| `quality_gate` | coordinator -> user | 质量评估 | 通过/不通过/有条件通过 |
|
||||
| `task_unblocked` | coordinator -> worker | 依赖解除 | 任务可执行 |
|
||||
| `error` | coordinator -> user | 协调错误 | 阻塞性问题 |
|
||||
| `shutdown` | coordinator -> all | 团队关闭 | 清理资源 |
|
||||
|
||||
```javascript
|
||||
const args = "$ARGUMENTS"
|
||||
## Message Bus
|
||||
|
||||
// 提取任务描述
|
||||
const taskDescription = args.replace(/--role[=\s]+\w+/, '').replace(/--team[=\s]+[\w-]+/, '').replace(/--mode[=\s]+\w+/, '').trim()
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
// Three-Mode 检测
|
||||
function detectMode(args, desc) {
|
||||
const modeMatch = args.match(/--mode[=\s]+(scan|remediate|targeted)/)
|
||||
if (modeMatch) return modeMatch[1]
|
||||
if (/扫描|scan|审计|audit|评估|assess/.test(desc)) return 'scan'
|
||||
if (/定向|targeted|指定|specific|修复.*已知/.test(desc)) return 'targeted'
|
||||
return 'remediate'
|
||||
}
|
||||
|
||||
let pipelineMode = detectMode(args, taskDescription)
|
||||
|
||||
// 统一 auto mode 检测
|
||||
const autoYes = /\b(-y|--yes)\b/.test(args)
|
||||
|
||||
// 简单任务可跳过确认(auto 模式跳过)
|
||||
if (!autoYes && (!taskDescription || taskDescription.length < 10)) {
|
||||
const clarification = AskUserQuestion({
|
||||
questions: [{
|
||||
question: "请描述技术债务治理目标(哪些模块?关注哪些维度?)",
|
||||
header: "Tech Debt Target",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "自定义", description: "输入具体描述" },
|
||||
{ label: "全项目扫描", description: "多维度扫描并评估技术债务" },
|
||||
{ label: "完整治理", description: "扫描+评估+规划+修复+验证闭环" },
|
||||
{ label: "定向修复", description: "针对已知债务项进行修复" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 2: Create Team + Initialize Session
|
||||
|
||||
```javascript
|
||||
const teamName = "tech-debt"
|
||||
const sessionSlug = taskDescription.slice(0, 30).replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '-')
|
||||
const sessionDate = new Date().toISOString().slice(0, 10)
|
||||
const sessionFolder = `.workflow/.team/TD-${sessionSlug}-${sessionDate}`
|
||||
Bash(`mkdir -p "${sessionFolder}/scan" "${sessionFolder}/assessment" "${sessionFolder}/plan" "${sessionFolder}/fixes" "${sessionFolder}/validation"`)
|
||||
|
||||
// 初始化 shared memory
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify({
|
||||
debt_inventory: [],
|
||||
priority_matrix: {},
|
||||
remediation_plan: {},
|
||||
fix_results: {},
|
||||
validation_results: {},
|
||||
debt_score_before: null,
|
||||
debt_score_after: null
|
||||
}, null, 2))
|
||||
|
||||
TeamCreate({ team_name: teamName })
|
||||
|
||||
// ⚠️ 不在此阶段 spawn worker
|
||||
// Worker 在 Phase 4 (monitor) 中按阶段按需 spawn(Stop-Wait 策略)
|
||||
// 这避免了 worker 先启动但无任务可做的鸡生蛋问题
|
||||
```
|
||||
|
||||
### Phase 3: Create Task Chain
|
||||
|
||||
根据 pipelineMode 创建不同的任务链:
|
||||
|
||||
```javascript
|
||||
// Read commands/dispatch.md for full implementation
|
||||
Read("commands/dispatch.md")
|
||||
```
|
||||
|
||||
**Scan Mode**:
|
||||
```
|
||||
TDSCAN-001(多维度扫描) → TDEVAL-001(量化评估)
|
||||
```
|
||||
|
||||
**Remediate Mode**:
|
||||
```
|
||||
TDSCAN-001(扫描) → TDEVAL-001(评估) → TDPLAN-001(规划) → TDFIX-001(修复) → TDVAL-001(验证)
|
||||
```
|
||||
|
||||
**Targeted Mode**:
|
||||
```
|
||||
TDPLAN-001(规划) → TDFIX-001(修复) → TDVAL-001(验证)
|
||||
```
|
||||
|
||||
### Phase 4: Sequential Stage Execution (Stop-Wait)
|
||||
|
||||
```javascript
|
||||
// Read commands/monitor.md for full implementation
|
||||
Read("commands/monitor.md")
|
||||
```
|
||||
|
||||
> **策略**: 逐阶段 spawn worker,同步阻塞等待返回。Worker 返回即阶段完成,无需轮询。
|
||||
>
|
||||
> - ❌ 禁止: while 循环 + sleep + 检查状态
|
||||
> - ✅ 采用: `Task(run_in_background: false)` 同步调用 = 天然回调
|
||||
|
||||
**阶段流转**:
|
||||
|
||||
| 当前阶段 | Worker | 完成后 |
|
||||
|----------|--------|--------|
|
||||
| TDSCAN-001 | scanner | → 启动 TDEVAL |
|
||||
| TDEVAL-001 | assessor | → 启动 TDPLAN |
|
||||
| TDPLAN-001 | planner | → [Plan Approval Gate] → [Create Worktree] → 启动 TDFIX |
|
||||
| TDFIX-001 | executor (worktree) | → 启动 TDVAL |
|
||||
| TDVAL-001 | validator (worktree) | → 评估质量门控 → [Commit+PR] |
|
||||
|
||||
**Fix-Verify 循环**(TDVAL 阶段发现回归时):
|
||||
```javascript
|
||||
if (regressionFound && fixVerifyIteration < 3) {
|
||||
fixVerifyIteration++
|
||||
// 创建 TDFIX-fix + TDVAL-verify 任务,追加到 pipeline 继续执行
|
||||
} else if (fixVerifyIteration >= 3) {
|
||||
// 接受当前状态,继续汇报
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator",
|
||||
to: "user", type: "quality_gate",
|
||||
summary: `[coordinator] Fix-Verify 循环已达上限(3次),接受当前结果`
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 5: Report + Debt Reduction Metrics + PR
|
||||
|
||||
```javascript
|
||||
// 读取 shared memory 汇总结果
|
||||
const memory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
|
||||
// PR 创建(worktree 执行模式下,验证通过后)
|
||||
if (memory.worktree && memory.validation_results?.passed) {
|
||||
const { path: wtPath, branch } = memory.worktree
|
||||
|
||||
// Commit all changes in worktree
|
||||
Bash(`cd "${wtPath}" && git add -A && git commit -m "$(cat <<'EOF'
|
||||
tech-debt: ${taskDescription}
|
||||
|
||||
Automated tech debt cleanup via team-tech-debt pipeline.
|
||||
Mode: ${pipelineMode}
|
||||
EOF
|
||||
)"`)
|
||||
|
||||
// Push + Create PR
|
||||
Bash(`cd "${wtPath}" && git push -u origin "${branch}"`)
|
||||
|
||||
const prBody = `## Tech Debt Cleanup
|
||||
|
||||
**Mode**: ${pipelineMode}
|
||||
**Items fixed**: ${memory.fix_results?.items_fixed || 0}
|
||||
**Debt score**: ${memory.debt_score_before} → ${memory.debt_score_after}
|
||||
|
||||
### Validation
|
||||
- Tests: ${memory.validation_results?.checks?.test_suite?.status || 'N/A'}
|
||||
- Types: ${memory.validation_results?.checks?.type_check?.status || 'N/A'}
|
||||
- Lint: ${memory.validation_results?.checks?.lint_check?.status || 'N/A'}
|
||||
|
||||
### Session
|
||||
${sessionFolder}`
|
||||
|
||||
Bash(`cd "${wtPath}" && gh pr create --title "Tech Debt: ${taskDescription.slice(0, 50)}" --body "$(cat <<'EOF'
|
||||
${prBody}
|
||||
EOF
|
||||
)"`)
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator",
|
||||
to: "user", type: "pr_created",
|
||||
summary: `[coordinator] PR 已创建: branch ${branch}`
|
||||
})
|
||||
|
||||
// Cleanup worktree
|
||||
Bash(`git worktree remove "${wtPath}" 2>/dev/null || true`)
|
||||
} else if (memory.worktree && !memory.validation_results?.passed) {
|
||||
// 验证未通过,保留 worktree 供手动检查
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator",
|
||||
to: "user", type: "quality_gate",
|
||||
summary: `[coordinator] 验证未通过,worktree 保留于 ${memory.worktree.path},请手动检查`
|
||||
})
|
||||
}
|
||||
|
||||
const report = {
|
||||
mode: pipelineMode,
|
||||
debt_items_found: memory.debt_inventory?.length || 0,
|
||||
debt_score_before: memory.debt_score_before || 'N/A',
|
||||
debt_score_after: memory.debt_score_after || 'N/A',
|
||||
items_fixed: memory.fix_results?.items_fixed || 0,
|
||||
items_remaining: memory.fix_results?.items_remaining || 0,
|
||||
validation_passed: memory.validation_results?.passed || false,
|
||||
regressions: memory.validation_results?.regressions || 0
|
||||
}
|
||||
|
||||
// 计算债务消减率
|
||||
const reductionRate = report.debt_items_found > 0
|
||||
? Math.round((report.items_fixed / report.debt_items_found) * 100)
|
||||
: 0
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator",
|
||||
to: "user", type: "quality_gate",
|
||||
summary: `[coordinator] 技术债务治理完成: ${report.debt_items_found}项债务, 修复${report.items_fixed}项, 消减率${reductionRate}%`
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "coordinator",
|
||||
to: "user",
|
||||
type: <message-type>,
|
||||
summary: "[coordinator] <summary>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
content: `## [coordinator] Tech Debt Report\n\n${JSON.stringify(report, null, 2)}`,
|
||||
summary: `[coordinator] Debt reduction: ${reductionRate}%`
|
||||
})
|
||||
|
||||
// 询问下一步(auto 模式跳过,默认关闭团队)
|
||||
if (!autoYes) {
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "技术债务治理流程已完成。下一步:",
|
||||
header: "Next",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "新目标", description: "对新模块/维度执行债务治理" },
|
||||
{ label: "深度修复", description: "对剩余高优先级债务继续修复" },
|
||||
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from coordinator --to user --type <message-type> --summary \"[coordinator] ...\" --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Session Resume Check
|
||||
|
||||
**Objective**: Detect and resume interrupted sessions before creating new ones.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. Scan session directory for sessions with status "active" or "paused"
|
||||
2. No sessions found -> proceed to Phase 1
|
||||
3. Single session found -> resume it (-> Session Reconciliation)
|
||||
4. Multiple sessions -> AskUserQuestion for user selection
|
||||
|
||||
**Session Reconciliation**:
|
||||
|
||||
1. Audit TaskList -> get real status of all tasks
|
||||
2. Reconcile: session state <-> TaskList status (bidirectional sync)
|
||||
3. Reset any in_progress tasks -> pending (they were interrupted)
|
||||
4. Determine remaining pipeline from reconciled state
|
||||
5. Rebuild team if disbanded (TeamCreate + spawn needed workers only)
|
||||
6. Create missing tasks with correct blockedBy dependencies
|
||||
7. Verify dependency chain integrity
|
||||
8. Update session file with reconciled state
|
||||
9. Kick first executable task's worker -> Phase 4
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Requirement Clarification
|
||||
|
||||
**Objective**: Parse user input and gather execution parameters.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. **Parse arguments** for explicit settings: mode, scope, focus areas
|
||||
|
||||
2. **Mode Detection**:
|
||||
|
||||
| Detection | Condition | Mode |
|
||||
|-----------|-----------|------|
|
||||
| Explicit | `--mode=scan` specified | scan |
|
||||
| Explicit | `--mode=remediate` specified | remediate |
|
||||
| Explicit | `--mode=targeted` specified | targeted |
|
||||
| Keyword | Contains: 扫描, scan, 审计, audit, 评估, assess | scan |
|
||||
| Keyword | Contains: 定向, targeted, 指定, specific, 修复已知 | targeted |
|
||||
| Default | No match | remediate |
|
||||
|
||||
3. **Auto mode detection**:
|
||||
|
||||
| Flag | Behavior |
|
||||
|------|----------|
|
||||
| `-y` or `--yes` | Skip confirmations |
|
||||
|
||||
4. **Ask for missing parameters** via AskUserQuestion (skip if auto mode):
|
||||
|
||||
| Question | Options |
|
||||
|----------|---------|
|
||||
| Tech Debt Target | 自定义 / 全项目扫描 / 完整治理 / 定向修复 |
|
||||
|
||||
5. **Store requirements**: mode, scope, focus, constraints
|
||||
|
||||
**Success**: All parameters captured, mode finalized.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Create Team + Initialize Session
|
||||
|
||||
**Objective**: Initialize team, session file, and wisdom directory.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. Generate session ID: `TD-{slug}-{YYYY-MM-DD}`
|
||||
2. Create session folder structure:
|
||||
|
||||
```
|
||||
<session-folder>/
|
||||
├── scan/
|
||||
├── assessment/
|
||||
├── plan/
|
||||
├── fixes/
|
||||
├── validation/
|
||||
└── wisdom/
|
||||
├── learnings.md
|
||||
├── decisions.md
|
||||
├── conventions.md
|
||||
└── issues.md
|
||||
```
|
||||
|
||||
3. Initialize shared-memory.json:
|
||||
|
||||
| Field | Initial Value |
|
||||
|-------|---------------|
|
||||
| `debt_inventory` | [] |
|
||||
| `priority_matrix` | {} |
|
||||
| `remediation_plan` | {} |
|
||||
| `fix_results` | {} |
|
||||
| `validation_results` | {} |
|
||||
| `debt_score_before` | null |
|
||||
| `debt_score_after` | null |
|
||||
|
||||
4. Call TeamCreate with team name "tech-debt"
|
||||
|
||||
5. **Do NOT spawn workers yet** - Workers are spawned on-demand in Phase 4 (Stop-Wait strategy)
|
||||
|
||||
**Success**: Team created, session file written, wisdom initialized.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Create Task Chain
|
||||
|
||||
**Objective**: Dispatch tasks based on mode with proper dependencies.
|
||||
|
||||
Delegate to `commands/dispatch.md` which creates the full task chain.
|
||||
|
||||
**Task Chain by Mode**:
|
||||
|
||||
| Mode | Task Chain |
|
||||
|------|------------|
|
||||
| scan | TDSCAN-001 -> TDEVAL-001 |
|
||||
| remediate | TDSCAN-001 -> TDEVAL-001 -> TDPLAN-001 -> TDFIX-001 -> TDVAL-001 |
|
||||
| targeted | TDPLAN-001 -> TDFIX-001 -> TDVAL-001 |
|
||||
|
||||
**Task Metadata**:
|
||||
|
||||
| Task ID | Role | Dependencies | Description |
|
||||
|---------|------|--------------|-------------|
|
||||
| TDSCAN-001 | scanner | (none) | 多维度技术债务扫描 |
|
||||
| TDEVAL-001 | assessor | TDSCAN-001 | 量化评估与优先级排序 |
|
||||
| TDPLAN-001 | planner | TDEVAL-001 (or none in targeted) | 分阶段治理方案规划 |
|
||||
| TDFIX-001 | executor | TDPLAN-001 + Plan Approval | 债务清理执行(worktree) |
|
||||
| TDVAL-001 | validator | TDFIX-001 | 回归测试与质量验证 |
|
||||
|
||||
**Success**: Tasks created with correct dependencies, assigned to appropriate owners.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Sequential Stage Execution (Stop-Wait)
|
||||
|
||||
> **Strategy**: Spawn workers stage-by-stage, synchronous blocking wait. Worker returns = stage complete. No polling needed.
|
||||
|
||||
> **CRITICAL**: Use `Task(run_in_background: false)` for synchronous execution. This is intentionally different from the v3 default Spawn-and-Stop pattern.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. Load `commands/monitor.md` if available
|
||||
2. Find tasks with: status=pending, blockedBy all resolved, owner assigned
|
||||
3. For each ready task -> spawn worker (see SKILL.md Spawn Template)
|
||||
4. Output status summary
|
||||
5. STOP after spawning (wait for worker callback)
|
||||
|
||||
**Stage Transitions**:
|
||||
|
||||
| Current Stage | Worker | After Completion |
|
||||
|---------------|--------|------------------|
|
||||
| TDSCAN-001 | scanner | -> Start TDEVAL |
|
||||
| TDEVAL-001 | assessor | -> Start TDPLAN |
|
||||
| TDPLAN-001 | planner | -> [Plan Approval Gate] -> [Create Worktree] -> Start TDFIX |
|
||||
| TDFIX-001 | executor (worktree) | -> Start TDVAL |
|
||||
| TDVAL-001 | validator (worktree) | -> Quality Gate -> [Commit+PR] |
|
||||
|
||||
**Worker Spawn Template**:
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
description: "Spawn <role> worker",
|
||||
prompt: `你是 team "tech-debt" 的 <ROLE>.
|
||||
|
||||
## 首要指令(MUST)
|
||||
你的所有工作必须通过调用 Skill 获取角色定义后执行,禁止自行发挥:
|
||||
Skill(skill="team-tech-debt", args="--role=<role>")
|
||||
此调用会加载你的角色定义(role.md)、可用命令(commands/*.md)和完整执行逻辑。
|
||||
|
||||
当前需求: <task-description>
|
||||
Session: <session-folder>
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 <PREFIX>-* 前缀的任务,不得执行其他角色的工作
|
||||
- 所有输出(SendMessage、team_msg)必须带 [<role>] 标识前缀
|
||||
- 仅与 coordinator 通信,不得直接联系其他 worker
|
||||
- 不得使用 TaskCreate 为其他角色创建任务
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
## 工作流程(严格按顺序)
|
||||
1. 调用 Skill(skill="team-tech-debt", args="--role=<role>") 获取角色定义和执行逻辑
|
||||
2. 按 role.md 中的 5-Phase 流程执行(TaskList -> 找到 <PREFIX>-* 任务 -> 执行 -> 汇报)
|
||||
3. team_msg log + SendMessage 结果给 coordinator(带 [<role>] 标识)
|
||||
4. TaskUpdate completed -> 检查下一个任务 -> 回到步骤 1`,
|
||||
run_in_background: false // Stop-Wait: synchronous blocking
|
||||
})
|
||||
```
|
||||
|
||||
**Plan Approval Gate** (after TDPLAN completes):
|
||||
|
||||
1. Read remediation plan
|
||||
2. Present to user via AskUserQuestion:
|
||||
|
||||
| Option | Action |
|
||||
|--------|--------|
|
||||
| 批准 | Continue pipeline, create worktree |
|
||||
| 修订 | Request plan revision from planner |
|
||||
| 终止 | Stop pipeline, report current status |
|
||||
|
||||
**Worktree Creation** (before TDFIX):
|
||||
|
||||
1. Create worktree: `git worktree add <path> -b <branch>`
|
||||
2. Update shared-memory.json with worktree info
|
||||
3. Notify user via team_msg
|
||||
|
||||
**Fix-Verify Loop** (when TDVAL finds regressions):
|
||||
|
||||
| Condition | Action |
|
||||
|-----------|--------|
|
||||
| regressionFound && iteration < 3 | Create TDFIX-fix + TDVAL-verify tasks, continue |
|
||||
| iteration >= 3 | Accept current state, report with warning |
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Report + Debt Reduction Metrics + PR
|
||||
|
||||
**Objective**: Completion report and follow-up options.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. **Read shared memory** -> collect all results
|
||||
|
||||
2. **PR Creation** (worktree mode, validation passed):
|
||||
|
||||
| Step | Action |
|
||||
|------|--------|
|
||||
| Commit | `cd <worktree> && git add -A && git commit -m "tech-debt: <description>"` |
|
||||
| Push | `cd <worktree> && git push -u origin <branch>` |
|
||||
| Create PR | `cd <worktree> && gh pr create --title "Tech Debt: ..." --body "..."` |
|
||||
| Notify | team_msg with pr_created |
|
||||
| Cleanup | `git worktree remove <worktree>` (if validation passed) |
|
||||
|
||||
3. **Calculate metrics**:
|
||||
|
||||
| Metric | Calculation |
|
||||
|--------|-------------|
|
||||
| debt_items_found | debt_inventory.length |
|
||||
| items_fixed | fix_results.items_fixed |
|
||||
| reduction_rate | (items_fixed / debt_items_found) * 100 |
|
||||
|
||||
4. **Generate report**:
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| mode | scan/remediate/targeted |
|
||||
| debt_items_found | Count |
|
||||
| debt_score_before | Initial score |
|
||||
| debt_score_after | Final score |
|
||||
| items_fixed | Count |
|
||||
| items_remaining | Count |
|
||||
| validation_passed | Boolean |
|
||||
| regressions | Count |
|
||||
|
||||
5. **Output**: SendMessage with `[coordinator]` prefix + team_msg log
|
||||
|
||||
6. **Ask next steps** (skip if auto mode):
|
||||
|
||||
| Option | Action |
|
||||
|--------|--------|
|
||||
| 新目标 | New tech debt target |
|
||||
| 深度修复 | Continue with remaining high-priority items |
|
||||
| 关闭团队 | Cleanup and close |
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| Teammate unresponsive | Send follow-up, 2x → respawn |
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Task timeout | Log, mark failed, ask user to retry or skip |
|
||||
| Worker crash | Respawn worker, reassign task |
|
||||
| Dependency cycle | Detect, report to user, halt |
|
||||
| Invalid mode | Reject with error, ask to clarify |
|
||||
| Session corruption | Attempt recovery, fallback to manual reconciliation |
|
||||
| Teammate unresponsive | Send follow-up, 2x -> respawn |
|
||||
| Scanner finds no debt | Report clean codebase, skip to summary |
|
||||
| Fix-Verify loop stuck >3 iterations | Accept current state, continue pipeline |
|
||||
| Build/test environment broken | Notify user, suggest manual fix |
|
||||
|
||||
@@ -1,62 +1,32 @@
|
||||
# Role: executor
|
||||
# Executor Role
|
||||
|
||||
技术债务清理执行者。根据治理方案执行重构、依赖更新、代码清理、文档补充等操作。通过 code-developer subagent 分批执行修复任务,包含自验证环节。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `executor`
|
||||
- **Name**: `executor` | **Tag**: `[executor]`
|
||||
- **Task Prefix**: `TDFIX-*`
|
||||
- **Responsibility**: Code generation(债务清理执行)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[executor]`
|
||||
- **Responsibility**: Code generation (债务清理执行)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `TDFIX-*` 前缀的任务
|
||||
- 所有输出必须带 `[executor]` 标识
|
||||
- 按治理方案执行修复操作
|
||||
- 执行基本自验证(语法检查、lint)
|
||||
- Only process `TDFIX-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[executor]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within debt remediation responsibility scope
|
||||
- Execute fixes according to remediation plan
|
||||
- Perform self-validation (syntax check, lint)
|
||||
|
||||
### MUST NOT
|
||||
- Create new features from scratch (only cleanup debt)
|
||||
- Modify code outside the remediation plan
|
||||
- Create tasks for other roles
|
||||
- Communicate directly with other worker roles (must go through coordinator)
|
||||
- Skip self-validation step
|
||||
- Omit `[executor]` identifier in any output
|
||||
|
||||
- 从零创建新功能(仅清理债务)
|
||||
- 修改不在治理方案中的代码
|
||||
- 为其他角色创建任务
|
||||
- 直接与其他 worker 通信
|
||||
- 跳过自验证步骤
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `fix_complete` | executor → coordinator | 修复完成 | 包含修复摘要 |
|
||||
| `fix_progress` | executor → coordinator | 批次完成 | 进度更新 |
|
||||
| `error` | executor → coordinator | 执行失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "executor",
|
||||
to: "coordinator",
|
||||
type: "fix_complete",
|
||||
summary: "[executor] 修复完成: 15/20 items fixed"
|
||||
})
|
||||
```
|
||||
|
||||
### CLI 回退
|
||||
|
||||
若 `mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
|
||||
|
||||
```javascript
|
||||
Bash(`echo '${JSON.stringify({ from: "executor", to: "coordinator", type: "fix_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
|
||||
```
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -66,104 +36,134 @@ Bash(`echo '${JSON.stringify({ from: "executor", to: "coordinator", type: "fix_c
|
||||
|---------|------|-------|-------------|
|
||||
| `remediate` | [commands/remediate.md](commands/remediate.md) | Phase 3 | 分批委派 code-developer 执行修复 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
| Agent Type | Used By | Purpose |
|
||||
|------------|---------|---------|
|
||||
| `code-developer` | remediate.md | 代码修复执行 |
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `code-developer` | Subagent | remediate.md | 代码修复执行 |
|
||||
|
||||
### CLI Capabilities
|
||||
> Executor does not directly use CLI analysis tools (uses code-developer subagent indirectly)
|
||||
|
||||
> Executor 不直接使用 CLI 分析工具(通过 code-developer 间接使用)
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `fix_complete` | executor -> coordinator | 修复完成 | 包含修复摘要 |
|
||||
| `fix_progress` | executor -> coordinator | 批次完成 | 进度更新 |
|
||||
| `error` | executor -> coordinator | 执行失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "executor",
|
||||
to: "coordinator",
|
||||
type: <message-type>,
|
||||
summary: "[executor] <task-prefix> complete: <task-subject>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from executor --to coordinator --type <message-type> --summary \"[executor] ...\" --ref <artifact-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('TDFIX-') &&
|
||||
t.owner === 'executor' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return // idle
|
||||
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `TDFIX-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Load Remediation Plan
|
||||
|
||||
```javascript
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
|
||||
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
|
||||
| Remediation plan | `<session-folder>/plan/remediation-plan.json` | Yes |
|
||||
|
||||
// 加载 worktree 路径(由 coordinator 写入 shared memory)
|
||||
const worktreePath = sharedMemory.worktree?.path || null
|
||||
const worktreeBranch = sharedMemory.worktree?.branch || null
|
||||
**Loading steps**:
|
||||
|
||||
// 加载治理方案
|
||||
let plan = {}
|
||||
try {
|
||||
plan = JSON.parse(Read(`${sessionFolder}/plan/remediation-plan.json`))
|
||||
} catch {}
|
||||
1. Extract session path from task description
|
||||
2. Read shared-memory.json for worktree info:
|
||||
|
||||
// 确定要执行的 actions
|
||||
const allActions = plan.phases
|
||||
? plan.phases.flatMap(p => p.actions || [])
|
||||
: []
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `worktree.path` | Worktree directory path |
|
||||
| `worktree.branch` | Worktree branch name |
|
||||
|
||||
// 识别目标文件
|
||||
const targetFiles = [...new Set(allActions.map(a => a.file).filter(Boolean))]
|
||||
3. Read remediation-plan.json for actions
|
||||
4. Extract all actions from plan phases
|
||||
5. Identify target files (unique file paths from actions)
|
||||
6. Group actions by type for batch processing
|
||||
|
||||
// 按类型分批
|
||||
const batches = groupActionsByType(allActions)
|
||||
**Batch grouping**:
|
||||
|
||||
function groupActionsByType(actions) {
|
||||
const groups = {}
|
||||
for (const action of actions) {
|
||||
const type = action.type || 'refactor'
|
||||
if (!groups[type]) groups[type] = []
|
||||
groups[type].push(action)
|
||||
}
|
||||
return groups
|
||||
}
|
||||
```
|
||||
| Action Type | Description |
|
||||
|-------------|-------------|
|
||||
| refactor | Code refactoring |
|
||||
| restructure | Architecture changes |
|
||||
| add-tests | Test additions |
|
||||
| update-deps | Dependency updates |
|
||||
| add-docs | Documentation additions |
|
||||
|
||||
### Phase 3: Execute Fixes
|
||||
|
||||
```javascript
|
||||
// Read commands/remediate.md for full implementation
|
||||
Read("commands/remediate.md")
|
||||
Delegate to `commands/remediate.md` if available, otherwise execute inline.
|
||||
|
||||
**Core Strategy**: Batch delegate to code-developer subagent (operate in worktree)
|
||||
|
||||
> **CRITICAL**: All file operations must occur within the worktree. Use `run_in_background: false` for synchronous execution.
|
||||
|
||||
**Fix Results Tracking**:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `items_fixed` | Count of successfully fixed items |
|
||||
| `items_failed` | Count of failed items |
|
||||
| `items_remaining` | Count of remaining items |
|
||||
| `batches_completed` | Count of completed batches |
|
||||
| `files_modified` | Array of modified file paths |
|
||||
| `errors` | Array of error messages |
|
||||
|
||||
**Batch execution flow**:
|
||||
|
||||
For each batch type and its actions:
|
||||
1. Spawn code-developer subagent with worktree context
|
||||
2. Wait for completion (synchronous)
|
||||
3. Log progress via team_msg
|
||||
4. Increment batch counter
|
||||
|
||||
**Subagent prompt template**:
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false, // Stop-Wait: synchronous execution
|
||||
description: "Fix tech debt batch: <batch-type> (<count> items)",
|
||||
prompt: `## Goal
|
||||
Execute tech debt cleanup for <batch-type> items.
|
||||
|
||||
**核心策略**: 分批委派 code-developer 执行修复(在 worktree 中操作)
|
||||
## Worktree (Mandatory)
|
||||
- Working directory: <worktree-path>
|
||||
- **All file reads and modifications must be within <worktree-path>**
|
||||
- Read files using <worktree-path>/path/to/file
|
||||
- Prefix Bash commands with cd "<worktree-path>" && ...
|
||||
|
||||
```javascript
|
||||
const fixResults = {
|
||||
items_fixed: 0,
|
||||
items_failed: 0,
|
||||
items_remaining: 0,
|
||||
batches_completed: 0,
|
||||
files_modified: [],
|
||||
errors: []
|
||||
}
|
||||
|
||||
for (const [batchType, actions] of Object.entries(batches)) {
|
||||
// 委派给 code-developer
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false,
|
||||
description: `Fix tech debt batch: ${batchType} (${actions.length} items)`,
|
||||
prompt: `## Goal
|
||||
Execute tech debt cleanup for ${batchType} items.
|
||||
${worktreePath ? `\n## Worktree(强制)\n- 工作目录: ${worktreePath}\n- **所有文件读取和修改必须在 ${worktreePath} 下进行**\n- 读文件时使用 ${worktreePath}/path/to/file\n- Bash 命令使用 cd "${worktreePath}" && ... 前缀\n` : ''}
|
||||
## Actions
|
||||
${actions.map(a => `- [${a.debt_id}] ${a.action} (file: ${a.file})`).join('\n')}
|
||||
<action-list>
|
||||
|
||||
## Instructions
|
||||
- Read each target file before modifying
|
||||
@@ -172,93 +172,49 @@ ${actions.map(a => `- [${a.debt_id}] ${a.action} (file: ${a.file})`).join('\n')}
|
||||
- Do NOT introduce new features
|
||||
- Do NOT modify unrelated code
|
||||
- Run basic syntax check after each change`
|
||||
})
|
||||
|
||||
// 记录进度
|
||||
fixResults.batches_completed++
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "executor",
|
||||
to: "coordinator", type: "fix_progress",
|
||||
summary: `[executor] 批次 ${batchType} 完成 (${fixResults.batches_completed}/${Object.keys(batches).length})`
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 4: Self-Validation
|
||||
|
||||
```javascript
|
||||
// 基本语法检查(在 worktree 中执行)
|
||||
const cmdPrefix = worktreePath ? `cd "${worktreePath}" && ` : ''
|
||||
const syntaxResult = Bash(`${cmdPrefix}npx tsc --noEmit 2>&1 || python -m py_compile *.py 2>&1 || echo "skip"`)
|
||||
const hasSyntaxErrors = /error/i.test(syntaxResult) && !/skip/.test(syntaxResult)
|
||||
> **CRITICAL**: All commands must execute in worktree
|
||||
|
||||
// 基本 lint 检查
|
||||
const lintResult = Bash(`${cmdPrefix}npx eslint --no-error-on-unmatched-pattern src/ 2>&1 || echo "skip"`)
|
||||
const hasLintErrors = /error/i.test(lintResult) && !/skip/.test(lintResult)
|
||||
**Validation checks**:
|
||||
|
||||
// 更新修复统计
|
||||
fixResults.items_fixed = allActions.length - fixResults.items_failed
|
||||
fixResults.items_remaining = fixResults.items_failed
|
||||
fixResults.self_validation = {
|
||||
syntax_check: hasSyntaxErrors ? 'FAIL' : 'PASS',
|
||||
lint_check: hasLintErrors ? 'FAIL' : 'PASS'
|
||||
}
|
||||
| Check | Command | Pass Criteria |
|
||||
|-------|---------|---------------|
|
||||
| Syntax | `tsc --noEmit` or `python -m py_compile` | No errors |
|
||||
| Lint | `eslint --no-error-on-unmatched-pattern` | No errors |
|
||||
|
||||
// 保存修复日志
|
||||
Bash(`mkdir -p "${sessionFolder}/fixes"`)
|
||||
Write(`${sessionFolder}/fixes/fix-log.json`, JSON.stringify(fixResults, null, 2))
|
||||
**Command prefix** (if worktree): `cd "<worktree-path>" && `
|
||||
|
||||
// 更新 shared memory
|
||||
sharedMemory.fix_results = fixResults
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
```
|
||||
**Validation flow**:
|
||||
|
||||
1. Run syntax check -> record PASS/FAIL
|
||||
2. Run lint check -> record PASS/FAIL
|
||||
3. Update fix_results.self_validation
|
||||
4. Write `<session-folder>/fixes/fix-log.json`
|
||||
5. Update shared-memory.json with fix_results
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
const statusMsg = `修复 ${fixResults.items_fixed}/${allActions.length} 项, 语法: ${fixResults.self_validation.syntax_check}, lint: ${fixResults.self_validation.lint_check}`
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "executor",
|
||||
to: "coordinator",
|
||||
type: "fix_complete",
|
||||
summary: `[executor] ${statusMsg}`,
|
||||
ref: `${sessionFolder}/fixes/fix-log.json`,
|
||||
data: { items_fixed: fixResults.items_fixed, items_failed: fixResults.items_failed }
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[executor]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [executor] Fix Results
|
||||
**Report content**:
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Status**: ${fixResults.items_failed === 0 ? 'ALL FIXED' : 'PARTIAL'}
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Task | task.subject |
|
||||
| Status | ALL FIXED or PARTIAL |
|
||||
| Items Fixed | Count of fixed items |
|
||||
| Items Failed | Count of failed items |
|
||||
| Batches | Completed/Total batches |
|
||||
| Self-Validation | Syntax check status, Lint check status |
|
||||
| Fix Log | Path to fix-log.json |
|
||||
|
||||
### Summary
|
||||
- Items fixed: ${fixResults.items_fixed}
|
||||
- Items failed: ${fixResults.items_failed}
|
||||
- Batches: ${fixResults.batches_completed}/${Object.keys(batches).length}
|
||||
|
||||
### Self-Validation
|
||||
- Syntax check: ${fixResults.self_validation.syntax_check}
|
||||
- Lint check: ${fixResults.self_validation.lint_check}
|
||||
|
||||
### Fix Log
|
||||
${sessionFolder}/fixes/fix-log.json`,
|
||||
summary: `[executor] TDFIX complete: ${statusMsg}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('TDFIX-') && t.owner === 'executor' &&
|
||||
t.status === 'pending' && t.blockedBy.length === 0
|
||||
)
|
||||
if (nextTasks.length > 0) { /* back to Phase 1 */ }
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
|
||||
@@ -1,61 +1,30 @@
|
||||
# Role: planner
|
||||
# Planner Role
|
||||
|
||||
技术债务治理方案规划师。基于评估矩阵创建分阶段治理方案:quick-wins 立即执行、systematic 中期系统治理、prevention 长期预防机制。产出 remediation-plan.md。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `planner`
|
||||
- **Name**: `planner` | **Tag**: `[planner]`
|
||||
- **Task Prefix**: `TDPLAN-*`
|
||||
- **Responsibility**: Orchestration(治理规划)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[planner]`
|
||||
- **Responsibility**: Orchestration (治理规划)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `TDPLAN-*` 前缀的任务
|
||||
- 所有输出必须带 `[planner]` 标识
|
||||
- 基于评估数据制定可行的治理方案
|
||||
- 更新 shared memory 中的 remediation_plan
|
||||
- Only process `TDPLAN-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[planner]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within remediation planning responsibility scope
|
||||
- Base plans on assessment data from shared memory
|
||||
|
||||
### MUST NOT
|
||||
- Modify source code or test code
|
||||
- Execute fix operations
|
||||
- Create tasks for other roles
|
||||
- Communicate directly with other worker roles (must go through coordinator)
|
||||
- Omit `[planner]` identifier in any output
|
||||
|
||||
- 修改源代码或测试代码
|
||||
- 执行修复操作
|
||||
- 为其他角色创建任务
|
||||
- 直接与其他 worker 通信
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `plan_ready` | planner → coordinator | 方案完成 | 包含分阶段治理方案 |
|
||||
| `plan_revision` | planner → coordinator | 方案修订 | 根据反馈调整方案 |
|
||||
| `error` | planner → coordinator | 规划失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "planner",
|
||||
to: "coordinator",
|
||||
type: "plan_ready",
|
||||
summary: "[planner] 治理方案就绪: 3 phases, 12 quick-wins, 8 systematic"
|
||||
})
|
||||
```
|
||||
|
||||
### CLI 回退
|
||||
|
||||
若 `mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
|
||||
|
||||
```javascript
|
||||
Bash(`echo '${JSON.stringify({ from: "planner", to: "coordinator", type: "plan_ready", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
|
||||
```
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -65,216 +34,150 @@ Bash(`echo '${JSON.stringify({ from: "planner", to: "coordinator", type: "plan_r
|
||||
|---------|------|-------|-------------|
|
||||
| `create-plan` | [commands/create-plan.md](commands/create-plan.md) | Phase 3 | 分阶段治理方案生成 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
| Agent Type | Used By | Purpose |
|
||||
|------------|---------|---------|
|
||||
| `cli-explore-agent` | create-plan.md | 代码库探索验证方案可行性 |
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `cli-explore-agent` | Subagent | create-plan.md | 代码库探索验证方案可行性 |
|
||||
| `gemini` | CLI | create-plan.md | 治理方案生成 |
|
||||
|
||||
### CLI Capabilities
|
||||
---
|
||||
|
||||
| CLI Tool | Mode | Used By | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `gemini` | analysis | create-plan.md | 治理方案生成 |
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `plan_ready` | planner -> coordinator | 方案完成 | 包含分阶段治理方案 |
|
||||
| `plan_revision` | planner -> coordinator | 方案修订 | 根据反馈调整方案 |
|
||||
| `error` | planner -> coordinator | 规划失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "planner",
|
||||
to: "coordinator",
|
||||
type: <message-type>,
|
||||
summary: "[planner] <task-prefix> complete: <task-subject>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from planner --to coordinator --type <message-type> --summary \"[planner] ...\" --ref <artifact-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('TDPLAN-') &&
|
||||
t.owner === 'planner' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return // idle
|
||||
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `TDPLAN-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Load Assessment Data
|
||||
|
||||
```javascript
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
|
||||
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
|
||||
| Priority matrix | `<session-folder>/assessment/priority-matrix.json` | Yes |
|
||||
|
||||
const debtInventory = sharedMemory.debt_inventory || []
|
||||
**Loading steps**:
|
||||
|
||||
// 加载优先级矩阵
|
||||
let priorityMatrix = {}
|
||||
try {
|
||||
priorityMatrix = JSON.parse(Read(`${sessionFolder}/assessment/priority-matrix.json`))
|
||||
} catch {}
|
||||
1. Extract session path from task description
|
||||
2. Read shared-memory.json for debt_inventory
|
||||
3. Read priority-matrix.json for quadrant groupings
|
||||
4. Group items by priority quadrant:
|
||||
|
||||
// 分组
|
||||
const quickWins = debtInventory.filter(i => i.priority_quadrant === 'quick-win')
|
||||
const strategic = debtInventory.filter(i => i.priority_quadrant === 'strategic')
|
||||
const backlog = debtInventory.filter(i => i.priority_quadrant === 'backlog')
|
||||
const deferred = debtInventory.filter(i => i.priority_quadrant === 'defer')
|
||||
```
|
||||
| Quadrant | Filter |
|
||||
|----------|--------|
|
||||
| quickWins | priority_quadrant === 'quick-win' |
|
||||
| strategic | priority_quadrant === 'strategic' |
|
||||
| backlog | priority_quadrant === 'backlog' |
|
||||
| deferred | priority_quadrant === 'defer' |
|
||||
|
||||
### Phase 3: Create Remediation Plan
|
||||
|
||||
```javascript
|
||||
// Read commands/create-plan.md for full implementation
|
||||
Read("commands/create-plan.md")
|
||||
```
|
||||
Delegate to `commands/create-plan.md` if available, otherwise execute inline.
|
||||
|
||||
**核心策略**: 3 阶段治理方案
|
||||
**Core Strategy**: 3-phase remediation plan
|
||||
|
||||
```javascript
|
||||
const plan = {
|
||||
phases: [
|
||||
{
|
||||
name: 'Quick Wins',
|
||||
description: '高影响低成本项,立即执行',
|
||||
items: quickWins,
|
||||
estimated_effort: quickWins.reduce((s, i) => s + i.cost_score, 0),
|
||||
actions: quickWins.map(i => ({
|
||||
debt_id: i.id,
|
||||
action: i.suggestion || `Fix ${i.description}`,
|
||||
file: i.file,
|
||||
type: determineActionType(i)
|
||||
}))
|
||||
},
|
||||
{
|
||||
name: 'Systematic',
|
||||
description: '高影响高成本项,需系统规划',
|
||||
items: strategic,
|
||||
estimated_effort: strategic.reduce((s, i) => s + i.cost_score, 0),
|
||||
actions: strategic.map(i => ({
|
||||
debt_id: i.id,
|
||||
action: i.suggestion || `Refactor ${i.description}`,
|
||||
file: i.file,
|
||||
type: determineActionType(i)
|
||||
}))
|
||||
},
|
||||
{
|
||||
name: 'Prevention',
|
||||
description: '预防机制建设,长期生效',
|
||||
items: [],
|
||||
estimated_effort: 0,
|
||||
actions: generatePreventionActions(debtInventory)
|
||||
}
|
||||
]
|
||||
}
|
||||
| Phase | Name | Description | Items |
|
||||
|-------|------|-------------|-------|
|
||||
| 1 | Quick Wins | 高影响低成本项,立即执行 | quickWins |
|
||||
| 2 | Systematic | 高影响高成本项,需系统规划 | strategic |
|
||||
| 3 | Prevention | 预防机制建设,长期生效 | Generated from inventory |
|
||||
|
||||
function determineActionType(item) {
|
||||
const typeMap = {
|
||||
'code': 'refactor',
|
||||
'architecture': 'restructure',
|
||||
'testing': 'add-tests',
|
||||
'dependency': 'update-deps',
|
||||
'documentation': 'add-docs'
|
||||
}
|
||||
return typeMap[item.dimension] || 'refactor'
|
||||
}
|
||||
**Action Type Mapping**:
|
||||
|
||||
function generatePreventionActions(inventory) {
|
||||
const actions = []
|
||||
const dimensions = [...new Set(inventory.map(i => i.dimension))]
|
||||
for (const dim of dimensions) {
|
||||
const count = inventory.filter(i => i.dimension === dim).length
|
||||
if (count >= 3) {
|
||||
actions.push({
|
||||
action: getPreventionAction(dim),
|
||||
type: 'prevention',
|
||||
dimension: dim
|
||||
})
|
||||
}
|
||||
}
|
||||
return actions
|
||||
}
|
||||
| Dimension | Action Type |
|
||||
|-----------|-------------|
|
||||
| code | refactor |
|
||||
| architecture | restructure |
|
||||
| testing | add-tests |
|
||||
| dependency | update-deps |
|
||||
| documentation | add-docs |
|
||||
|
||||
function getPreventionAction(dimension) {
|
||||
const prevention = {
|
||||
'code': 'Add linting rules for complexity thresholds and code smell detection',
|
||||
'architecture': 'Introduce module boundary checks in CI pipeline',
|
||||
'testing': 'Set minimum coverage thresholds in CI and add pre-commit test hooks',
|
||||
'dependency': 'Configure automated dependency update bot (Renovate/Dependabot)',
|
||||
'documentation': 'Add JSDoc/docstring enforcement in linting rules'
|
||||
}
|
||||
return prevention[dimension] || 'Add automated checks for this category'
|
||||
}
|
||||
```
|
||||
**Prevention Action Generation**:
|
||||
|
||||
| Condition | Action |
|
||||
|-----------|--------|
|
||||
| dimension count >= 3 | Generate prevention action for that dimension |
|
||||
|
||||
| Dimension | Prevention Action |
|
||||
|-----------|-------------------|
|
||||
| code | Add linting rules for complexity thresholds and code smell detection |
|
||||
| architecture | Introduce module boundary checks in CI pipeline |
|
||||
| testing | Set minimum coverage thresholds in CI and add pre-commit test hooks |
|
||||
| dependency | Configure automated dependency update bot (Renovate/Dependabot) |
|
||||
| documentation | Add JSDoc/docstring enforcement in linting rules |
|
||||
|
||||
### Phase 4: Validate Plan Feasibility
|
||||
|
||||
```javascript
|
||||
// 验证方案可行性
|
||||
const validation = {
|
||||
total_actions: plan.phases.reduce((s, p) => s + p.actions.length, 0),
|
||||
total_effort: plan.phases.reduce((s, p) => s + p.estimated_effort, 0),
|
||||
files_affected: [...new Set(plan.phases.flatMap(p => p.actions.map(a => a.file)).filter(Boolean))],
|
||||
has_quick_wins: quickWins.length > 0,
|
||||
has_prevention: plan.phases[2].actions.length > 0
|
||||
}
|
||||
**Validation metrics**:
|
||||
|
||||
// 保存治理方案
|
||||
Bash(`mkdir -p "${sessionFolder}/plan"`)
|
||||
Write(`${sessionFolder}/plan/remediation-plan.md`, generatePlanMarkdown(plan, validation))
|
||||
Write(`${sessionFolder}/plan/remediation-plan.json`, JSON.stringify(plan, null, 2))
|
||||
| Metric | Description |
|
||||
|--------|-------------|
|
||||
| total_actions | Sum of actions across all phases |
|
||||
| total_effort | Sum of estimated effort scores |
|
||||
| files_affected | Unique files in action list |
|
||||
| has_quick_wins | Boolean: quickWins.length > 0 |
|
||||
| has_prevention | Boolean: prevention actions exist |
|
||||
|
||||
// 更新 shared memory
|
||||
sharedMemory.remediation_plan = {
|
||||
phases: plan.phases.map(p => ({ name: p.name, action_count: p.actions.length, effort: p.estimated_effort })),
|
||||
total_actions: validation.total_actions,
|
||||
files_affected: validation.files_affected.length
|
||||
}
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
```
|
||||
**Save outputs**:
|
||||
|
||||
1. Write `<session-folder>/plan/remediation-plan.md` (markdown format)
|
||||
2. Write `<session-folder>/plan/remediation-plan.json` (machine-readable)
|
||||
3. Update shared-memory.json with `remediation_plan` summary
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
const planSummary = plan.phases.map(p => `${p.name}: ${p.actions.length} actions`).join(', ')
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "planner",
|
||||
to: "coordinator",
|
||||
type: "plan_ready",
|
||||
summary: `[planner] 治理方案就绪: ${planSummary}`,
|
||||
ref: `${sessionFolder}/plan/remediation-plan.md`
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[planner]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [planner] Remediation Plan
|
||||
**Report content**:
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Total Actions**: ${validation.total_actions}
|
||||
**Files Affected**: ${validation.files_affected.length}
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Task | task.subject |
|
||||
| Total Actions | Count of all actions |
|
||||
| Files Affected | Count of unique files |
|
||||
| Phase 1: Quick Wins | Top 5 quick-win items |
|
||||
| Phase 2: Systematic | Top 3 strategic items |
|
||||
| Phase 3: Prevention | Top 3 prevention actions |
|
||||
| Plan Document | Path to remediation-plan.md |
|
||||
|
||||
### Phase 1: Quick Wins (${quickWins.length} items)
|
||||
${quickWins.slice(0, 5).map(i => `- ${i.file} - ${i.description}`).join('\n')}
|
||||
|
||||
### Phase 2: Systematic (${strategic.length} items)
|
||||
${strategic.slice(0, 3).map(i => `- ${i.file} - ${i.description}`).join('\n')}
|
||||
|
||||
### Phase 3: Prevention (${plan.phases[2].actions.length} items)
|
||||
${plan.phases[2].actions.slice(0, 3).map(a => `- ${a.action}`).join('\n')}
|
||||
|
||||
### Plan Document
|
||||
${sessionFolder}/plan/remediation-plan.md`,
|
||||
summary: `[planner] TDPLAN complete: ${planSummary}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('TDPLAN-') && t.owner === 'planner' &&
|
||||
t.status === 'pending' && t.blockedBy.length === 0
|
||||
)
|
||||
if (nextTasks.length > 0) { /* back to Phase 1 */ }
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
|
||||
@@ -1,61 +1,30 @@
|
||||
# Role: scanner
|
||||
# Scanner Role
|
||||
|
||||
多维度技术债务扫描器。扫描代码库的 5 个维度:代码质量、架构、测试、依赖、文档,生成结构化债务清单。通过 CLI Fan-out 并行分析,产出 debt-inventory.json。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `scanner`
|
||||
- **Name**: `scanner` | **Tag**: `[scanner]`
|
||||
- **Task Prefix**: `TDSCAN-*`
|
||||
- **Responsibility**: Orchestration(多维度扫描编排)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[scanner]`
|
||||
- **Responsibility**: Orchestration (多维度扫描编排)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `TDSCAN-*` 前缀的任务
|
||||
- 所有输出必须带 `[scanner]` 标识
|
||||
- 仅通过 SendMessage 与 coordinator 通信
|
||||
- 严格在债务扫描职责范围内工作
|
||||
- Only process `TDSCAN-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[scanner]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within debt scanning responsibility scope
|
||||
- Tag all findings with dimension (code, architecture, testing, dependency, documentation)
|
||||
|
||||
### MUST NOT
|
||||
- Write or modify any code
|
||||
- Execute fix operations
|
||||
- Create tasks for other roles
|
||||
- Communicate directly with other worker roles (must go through coordinator)
|
||||
- Omit `[scanner]` identifier in any output
|
||||
|
||||
- 编写或修改代码
|
||||
- 执行修复操作
|
||||
- 为其他角色创建任务
|
||||
- 直接与其他 worker 通信
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `scan_complete` | scanner → coordinator | 扫描完成 | 包含债务清单摘要 |
|
||||
| `debt_items_found` | scanner → coordinator | 发现高优先级债务 | 需要关注的关键发现 |
|
||||
| `error` | scanner → coordinator | 扫描失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "scanner",
|
||||
to: "coordinator",
|
||||
type: "scan_complete",
|
||||
summary: "[scanner] 多维度扫描完成: 42 项债务"
|
||||
})
|
||||
```
|
||||
|
||||
### CLI 回退
|
||||
|
||||
若 `mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
|
||||
|
||||
```javascript
|
||||
Bash(`echo '${JSON.stringify({ from: "scanner", to: "coordinator", type: "scan_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
|
||||
```
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -65,200 +34,184 @@ Bash(`echo '${JSON.stringify({ from: "scanner", to: "coordinator", type: "scan_c
|
||||
|---------|------|-------|-------------|
|
||||
| `scan-debt` | [commands/scan-debt.md](commands/scan-debt.md) | Phase 3 | 多维度 CLI Fan-out 扫描 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
| Agent Type | Used By | Purpose |
|
||||
|------------|---------|---------|
|
||||
| `cli-explore-agent` | scan-debt.md | 并行代码库结构探索(多角度 fan-out) |
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `gemini` | CLI | scan-debt.md | 多维度代码分析(dimension fan-out) |
|
||||
| `cli-explore-agent` | Subagent | scan-debt.md | 并行代码库结构探索 |
|
||||
|
||||
### CLI Capabilities
|
||||
---
|
||||
|
||||
| CLI Tool | Mode | Used By | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `gemini` | analysis | scan-debt.md | 多维度代码分析(dimension fan-out) |
|
||||
| `gemini` | analysis | scan-debt.md | 多视角深度分析(perspective fan-out) |
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `scan_complete` | scanner -> coordinator | 扫描完成 | 包含债务清单摘要 |
|
||||
| `debt_items_found` | scanner -> coordinator | 发现高优先级债务 | 需要关注的关键发现 |
|
||||
| `error` | scanner -> coordinator | 扫描失败 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "scanner",
|
||||
to: "coordinator",
|
||||
type: <message-type>,
|
||||
summary: "[scanner] <task-prefix> complete: <task-subject>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from scanner --to coordinator --type <message-type> --summary \"[scanner] ...\" --ref <artifact-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('TDSCAN-') &&
|
||||
t.owner === 'scanner' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return // idle
|
||||
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `TDSCAN-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
```javascript
|
||||
// 确定扫描范围
|
||||
const scanScope = task.description.match(/scope:\s*(.+)/)?.[1] || '**/*'
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Scan scope | task.description (regex: `scope:\s*(.+)`) | No (default: `**/*`) |
|
||||
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
|
||||
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
|
||||
|
||||
// 读取 shared memory
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
**Loading steps**:
|
||||
|
||||
// 检测项目类型和框架
|
||||
const projectRoot = Bash(`git rev-parse --show-toplevel 2>/dev/null || pwd`).trim()
|
||||
const hasPackageJson = Bash(`test -f package.json && echo "yes" || echo "no"`).trim() === 'yes'
|
||||
const hasPyProject = Bash(`test -f pyproject.toml -o -f requirements.txt && echo "yes" || echo "no"`).trim() === 'yes'
|
||||
const hasGoMod = Bash(`test -f go.mod && echo "yes" || echo "no"`).trim() === 'yes'
|
||||
1. Extract session path from task description
|
||||
2. Read shared-memory.json for team context
|
||||
3. Detect project type and framework:
|
||||
|
||||
// 5 个扫描维度
|
||||
const dimensions = ["code", "architecture", "testing", "dependency", "documentation"]
|
||||
| Detection | Method |
|
||||
|-----------|--------|
|
||||
| Node.js project | Check for package.json |
|
||||
| Python project | Check for pyproject.toml or requirements.txt |
|
||||
| Go project | Check for go.mod |
|
||||
|
||||
// 多视角 Gemini 分析(自动检测任务关键词)
|
||||
function detectPerspectives(desc) {
|
||||
const perspectives = []
|
||||
if (/security|auth|inject|xss|漏洞|安全/.test(desc)) perspectives.push("security")
|
||||
if (/performance|speed|optimize|memory|性能|优化/.test(desc)) perspectives.push("performance")
|
||||
if (/quality|clean|maintain|debt|质量|代码/.test(desc)) perspectives.push("code-quality")
|
||||
if (/architect|pattern|structure|架构|结构/.test(desc)) perspectives.push("architecture")
|
||||
// 默认至少 2 个视角
|
||||
if (perspectives.length === 0) perspectives.push("code-quality", "architecture")
|
||||
return perspectives
|
||||
}
|
||||
const perspectives = detectPerspectives(task.description)
|
||||
4. Determine scan dimensions (default: code, architecture, testing, dependency, documentation)
|
||||
5. Detect perspectives from task description:
|
||||
|
||||
// 评估复杂度
|
||||
function assessComplexity(desc) {
|
||||
let score = 0
|
||||
if (/全项目|全量|comprehensive|full/.test(desc)) score += 3
|
||||
if (/architecture|架构/.test(desc)) score += 1
|
||||
if (/multiple|across|cross|多模块/.test(desc)) score += 2
|
||||
return score >= 4 ? 'High' : score >= 2 ? 'Medium' : 'Low'
|
||||
}
|
||||
const complexity = assessComplexity(task.description)
|
||||
```
|
||||
| Condition | Perspective |
|
||||
|-----------|-------------|
|
||||
| `security\|auth\|inject\|xss` | security |
|
||||
| `performance\|speed\|optimize` | performance |
|
||||
| `quality\|clean\|maintain\|debt` | code-quality |
|
||||
| `architect\|pattern\|structure` | architecture |
|
||||
| Default | code-quality + architecture |
|
||||
|
||||
6. Assess complexity:
|
||||
|
||||
| Signal | Weight |
|
||||
|--------|--------|
|
||||
| `全项目\|全量\|comprehensive\|full` | +3 |
|
||||
| `architecture\|架构` | +1 |
|
||||
| `multiple\|across\|cross\|多模块` | +2 |
|
||||
|
||||
| Score | Complexity |
|
||||
|-------|------------|
|
||||
| >= 4 | High |
|
||||
| 2-3 | Medium |
|
||||
| 0-1 | Low |
|
||||
|
||||
### Phase 3: Multi-Dimension Scan
|
||||
|
||||
```javascript
|
||||
// Read commands/scan-debt.md for full CLI Fan-out implementation
|
||||
Read("commands/scan-debt.md")
|
||||
Delegate to `commands/scan-debt.md` if available, otherwise execute inline.
|
||||
|
||||
**Core Strategy**: Three-layer parallel Fan-out
|
||||
|
||||
| Complexity | Strategy |
|
||||
|------------|----------|
|
||||
| Low | Direct: ACE search + Grep inline scan |
|
||||
| Medium/High | Fan-out A: Subagent exploration (cli-explore-agent) + Fan-out B: CLI dimension analysis (gemini per dimension) + Fan-out C: Multi-perspective Gemini analysis |
|
||||
|
||||
**Fan-out Architecture**:
|
||||
|
||||
```
|
||||
Fan-out A: Subagent Exploration (parallel cli-explore)
|
||||
structure perspective | patterns perspective | deps perspective
|
||||
↓ merge
|
||||
Fan-out B: CLI Dimension Analysis (parallel gemini)
|
||||
code | architecture | testing | dependency | documentation
|
||||
↓ merge
|
||||
Fan-out C: Multi-Perspective Gemini (parallel)
|
||||
security | performance | code-quality | architecture
|
||||
↓ Fan-in aggregate
|
||||
debt-inventory.json
|
||||
```
|
||||
|
||||
**核心策略**: 三层并行 Fan-out(subagent 探索 + CLI 维度分析 + 多视角 Gemini)
|
||||
**Low Complexity Path** (inline):
|
||||
|
||||
```javascript
|
||||
if (complexity === 'Low') {
|
||||
// 直接使用 ACE 搜索 + Grep 进行快速扫描
|
||||
const aceResults = mcp__ace-tool__search_context({
|
||||
project_root_path: projectRoot,
|
||||
query: "code smells, TODO/FIXME, deprecated APIs, complex functions, missing tests"
|
||||
})
|
||||
} else {
|
||||
// Fan-out A: 并行 subagent 探索(codebase 结构理解)
|
||||
// Fan-out B: 每个维度一个 CLI 调用(并行 gemini 分析)
|
||||
// Fan-out C: 多视角 Gemini 深度分析(并行 perspective 分析)
|
||||
// → Fan-in: 聚合 + 去重 + 交叉引用
|
||||
Read("commands/scan-debt.md")
|
||||
}
|
||||
```
|
||||
mcp__ace-tool__search_context({
|
||||
project_root_path: <project-root>,
|
||||
query: "code smells, TODO/FIXME, deprecated APIs, complex functions, missing tests"
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 4: Aggregate into Debt Inventory
|
||||
|
||||
```javascript
|
||||
// 聚合所有维度的发现
|
||||
const debtInventory = []
|
||||
**Standardize findings**:
|
||||
|
||||
// 为每个发现项创建标准化条目
|
||||
for (const item of allFindings) {
|
||||
debtInventory.push({
|
||||
id: `TD-${String(debtInventory.length + 1).padStart(3, '0')}`,
|
||||
dimension: item.dimension,
|
||||
severity: item.severity,
|
||||
file: item.file,
|
||||
line: item.line,
|
||||
description: item.description,
|
||||
suggestion: item.suggestion,
|
||||
estimated_effort: item.effort || 'unknown'
|
||||
})
|
||||
}
|
||||
For each finding, create entry:
|
||||
|
||||
// 更新 shared memory
|
||||
sharedMemory.debt_inventory = debtInventory
|
||||
sharedMemory.debt_score_before = debtInventory.length
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `id` | `TD-NNN` (sequential) |
|
||||
| `dimension` | code, architecture, testing, dependency, documentation |
|
||||
| `severity` | critical, high, medium, low |
|
||||
| `file` | File path |
|
||||
| `line` | Line number |
|
||||
| `description` | Issue description |
|
||||
| `suggestion` | Fix suggestion |
|
||||
| `estimated_effort` | small, medium, large, unknown |
|
||||
|
||||
// 保存债务清单
|
||||
Write(`${sessionFolder}/scan/debt-inventory.json`, JSON.stringify({
|
||||
scan_date: new Date().toISOString(),
|
||||
dimensions: dimensions,
|
||||
total_items: debtInventory.length,
|
||||
by_dimension: dimensions.reduce((acc, d) => {
|
||||
acc[d] = debtInventory.filter(i => i.dimension === d).length
|
||||
return acc
|
||||
}, {}),
|
||||
by_severity: {
|
||||
critical: debtInventory.filter(i => i.severity === 'critical').length,
|
||||
high: debtInventory.filter(i => i.severity === 'high').length,
|
||||
medium: debtInventory.filter(i => i.severity === 'medium').length,
|
||||
low: debtInventory.filter(i => i.severity === 'low').length
|
||||
},
|
||||
items: debtInventory
|
||||
}, null, 2))
|
||||
```
|
||||
**Save outputs**:
|
||||
|
||||
1. Update shared-memory.json with `debt_inventory` and `debt_score_before`
|
||||
2. Write `<session-folder>/scan/debt-inventory.json`:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `scan_date` | ISO timestamp |
|
||||
| `dimensions` | Array of scanned dimensions |
|
||||
| `total_items` | Count of debt items |
|
||||
| `by_dimension` | Count per dimension |
|
||||
| `by_severity` | Count per severity level |
|
||||
| `items` | Array of debt entries |
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
const resultSummary = `发现 ${debtInventory.length} 项技术债务(${dimensions.map(d => `${d}: ${debtInventory.filter(i => i.dimension === d).length}`).join(', ')})`
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "scanner",
|
||||
to: "coordinator",
|
||||
type: debtInventory.length > 0 ? "debt_items_found" : "scan_complete",
|
||||
summary: `[scanner] ${resultSummary}`,
|
||||
ref: `${sessionFolder}/scan/debt-inventory.json`
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[scanner]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [scanner] Debt Scan Results
|
||||
**Report content**:
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Dimensions**: ${dimensions.join(', ')}
|
||||
**Status**: ${debtInventory.length > 0 ? 'Debt Found' : 'Clean'}
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Task | task.subject |
|
||||
| Dimensions | dimensions scanned |
|
||||
| Status | "Debt Found" or "Clean" |
|
||||
| Summary | Total items with dimension breakdown |
|
||||
| Top Debt Items | Top 5 critical/high severity items |
|
||||
| Debt Inventory | Path to debt-inventory.json |
|
||||
|
||||
### Summary
|
||||
${resultSummary}
|
||||
|
||||
### Top Debt Items
|
||||
${debtInventory.filter(i => i.severity === 'critical' || i.severity === 'high').slice(0, 5).map(i => `- **[${i.severity}]** [${i.dimension}] ${i.file}:${i.line} - ${i.description}`).join('\n')}
|
||||
|
||||
### Debt Inventory
|
||||
${sessionFolder}/scan/debt-inventory.json`,
|
||||
summary: `[scanner] TDSCAN complete: ${resultSummary}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('TDSCAN-') &&
|
||||
t.owner === 'scanner' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
|
||||
if (nextTasks.length > 0) {
|
||||
// Continue with next task → back to Phase 1
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
|
||||
@@ -1,61 +1,31 @@
|
||||
# Role: validator
|
||||
# Validator Role
|
||||
|
||||
技术债务清理结果验证者。运行测试套件验证无回归、执行类型检查和 lint、通过 CLI 分析代码质量改善程度。对比 before/after 债务分数,生成 validation-report.json。
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `validator`
|
||||
- **Name**: `validator` | **Tag**: `[validator]`
|
||||
- **Task Prefix**: `TDVAL-*`
|
||||
- **Responsibility**: Validation(清理结果验证)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[validator]`
|
||||
- **Responsibility**: Validation (清理结果验证)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `TDVAL-*` 前缀的任务
|
||||
- 所有输出必须带 `[validator]` 标识
|
||||
- 运行完整验证流程(测试、类型检查、lint、质量分析)
|
||||
- 如发现回归,报告 regression_found
|
||||
- Only process `TDVAL-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[validator]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within validation responsibility scope
|
||||
- Run complete validation flow (tests, type check, lint, quality analysis)
|
||||
- Report regression_found if regressions detected
|
||||
|
||||
### MUST NOT
|
||||
- Fix code directly (only attempt small fixes via code-developer)
|
||||
- Create tasks for other roles
|
||||
- Communicate directly with other worker roles (must go through coordinator)
|
||||
- Skip any validation step
|
||||
- Omit `[validator]` identifier in any output
|
||||
|
||||
- 直接修复代码(仅在小修复时通过 code-developer 尝试)
|
||||
- 为其他角色创建任务
|
||||
- 直接与其他 worker 通信
|
||||
- 跳过任何验证步骤
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `validation_complete` | validator → coordinator | 验证通过 | 包含 before/after 指标 |
|
||||
| `regression_found` | validator → coordinator | 发现回归 | 触发 Fix-Verify 循环 |
|
||||
| `error` | validator → coordinator | 验证环境错误 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "validator",
|
||||
to: "coordinator",
|
||||
type: "validation_complete",
|
||||
summary: "[validator] 验证通过: 0 regressions, debt score 42 → 18"
|
||||
})
|
||||
```
|
||||
|
||||
### CLI 回退
|
||||
|
||||
若 `mcp__ccw-tools__team_msg` 不可用,使用 Bash 写入日志文件:
|
||||
|
||||
```javascript
|
||||
Bash(`echo '${JSON.stringify({ from: "validator", to: "coordinator", type: "validation_complete", summary: msg, ts: new Date().toISOString() })}' >> "${sessionFolder}/message-log.jsonl"`)
|
||||
```
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
@@ -65,195 +35,195 @@ Bash(`echo '${JSON.stringify({ from: "validator", to: "coordinator", type: "vali
|
||||
|---------|------|-------|-------------|
|
||||
| `verify` | [commands/verify.md](commands/verify.md) | Phase 3 | 回归测试与质量验证 |
|
||||
|
||||
### Subagent Capabilities
|
||||
### Tool Capabilities
|
||||
|
||||
| Agent Type | Used By | Purpose |
|
||||
|------------|---------|---------|
|
||||
| `code-developer` | verify.md | 小修复尝试(验证失败时) |
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `code-developer` | Subagent | verify.md | 小修复尝试(验证失败时) |
|
||||
| `gemini` | CLI | verify.md | 代码质量改善分析 |
|
||||
|
||||
### CLI Capabilities
|
||||
---
|
||||
|
||||
| CLI Tool | Mode | Used By | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `gemini` | analysis | verify.md | 代码质量改善分析 |
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `validation_complete` | validator -> coordinator | 验证通过 | 包含 before/after 指标 |
|
||||
| `regression_found` | validator -> coordinator | 发现回归 | 触发 Fix-Verify 循环 |
|
||||
| `error` | validator -> coordinator | 验证环境错误 | 阻塞性错误 |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <team-name>,
|
||||
from: "validator",
|
||||
to: "coordinator",
|
||||
type: <message-type>,
|
||||
summary: "[validator] <task-prefix> complete: <task-subject>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <team-name> --from validator --to coordinator --type <message-type> --summary \"[validator] ...\" --ref <artifact-path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('TDVAL-') &&
|
||||
t.owner === 'validator' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
if (myTasks.length === 0) return // idle
|
||||
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
```
|
||||
Standard task discovery flow: TaskList -> filter by prefix `TDVAL-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Load Context
|
||||
|
||||
```javascript
|
||||
const sessionFolder = task.description.match(/session:\s*(.+)/)?.[1]?.trim() || '.'
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) } catch {}
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session folder | task.description (regex: `session:\s*(.+)`) | Yes |
|
||||
| Shared memory | `<session-folder>/shared-memory.json` | Yes |
|
||||
| Fix log | `<session-folder>/fixes/fix-log.json` | No |
|
||||
|
||||
// 加载 worktree 路径(由 coordinator 写入 shared memory)
|
||||
const worktreePath = sharedMemory.worktree?.path || null
|
||||
const cmdPrefix = worktreePath ? `cd "${worktreePath}" && ` : ''
|
||||
**Loading steps**:
|
||||
|
||||
const debtInventory = sharedMemory.debt_inventory || []
|
||||
const fixResults = sharedMemory.fix_results || {}
|
||||
const debtScoreBefore = sharedMemory.debt_score_before || debtInventory.length
|
||||
1. Extract session path from task description
|
||||
2. Read shared-memory.json for:
|
||||
|
||||
// 加载修复日志
|
||||
let fixLog = {}
|
||||
try { fixLog = JSON.parse(Read(`${sessionFolder}/fixes/fix-log.json`)) } catch {}
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `worktree.path` | Worktree directory path |
|
||||
| `debt_inventory` | Debt items list |
|
||||
| `fix_results` | Fix results from executor |
|
||||
| `debt_score_before` | Debt score before fixes |
|
||||
|
||||
const modifiedFiles = fixLog.files_modified || []
|
||||
```
|
||||
3. Determine command prefix for worktree:
|
||||
|
||||
| Condition | Command Prefix |
|
||||
|-----------|---------------|
|
||||
| worktree exists | `cd "<worktree-path>" && ` |
|
||||
| no worktree | Empty string |
|
||||
|
||||
4. Read fix-log.json for modified files list
|
||||
|
||||
### Phase 3: Run Validation Checks
|
||||
|
||||
```javascript
|
||||
// Read commands/verify.md for full implementation
|
||||
Read("commands/verify.md")
|
||||
```
|
||||
Delegate to `commands/verify.md` if available, otherwise execute inline.
|
||||
|
||||
**核心策略**: 4 层验证(所有命令在 worktree 中执行)
|
||||
**Core Strategy**: 4-layer validation (all commands in worktree)
|
||||
|
||||
```javascript
|
||||
const validationResults = {
|
||||
test_suite: { status: 'pending', regressions: 0 },
|
||||
type_check: { status: 'pending', errors: 0 },
|
||||
lint_check: { status: 'pending', errors: 0 },
|
||||
quality_analysis: { status: 'pending', improvement: 0 }
|
||||
}
|
||||
**Validation Results Structure**:
|
||||
|
||||
// 1. 测试套件(worktree 中执行)
|
||||
const testResult = Bash(`${cmdPrefix}npm test 2>&1 || ${cmdPrefix}npx vitest run 2>&1 || ${cmdPrefix}python -m pytest 2>&1 || echo "no-tests"`)
|
||||
const testsPassed = !/FAIL|error|failed/i.test(testResult) || /no-tests/.test(testResult)
|
||||
validationResults.test_suite = {
|
||||
status: testsPassed ? 'PASS' : 'FAIL',
|
||||
regressions: testsPassed ? 0 : (testResult.match(/(\d+) failed/)?.[1] || 1) * 1
|
||||
}
|
||||
| Check | Status Field | Details |
|
||||
|-------|--------------|---------|
|
||||
| Test Suite | test_suite.status | regressions count |
|
||||
| Type Check | type_check.status | errors count |
|
||||
| Lint Check | lint_check.status | errors count |
|
||||
| Quality Analysis | quality_analysis.status | improvement percentage |
|
||||
|
||||
// 2. 类型检查(worktree 中执行)
|
||||
const typeResult = Bash(`${cmdPrefix}npx tsc --noEmit 2>&1 || echo "skip"`)
|
||||
const typeErrors = (typeResult.match(/error TS/g) || []).length
|
||||
validationResults.type_check = {
|
||||
status: typeErrors === 0 || /skip/.test(typeResult) ? 'PASS' : 'FAIL',
|
||||
errors: typeErrors
|
||||
}
|
||||
**1. Test Suite** (in worktree):
|
||||
|
||||
// 3. Lint 检查(worktree 中执行)
|
||||
const lintResult = Bash(`${cmdPrefix}npx eslint --no-error-on-unmatched-pattern ${modifiedFiles.join(' ')} 2>&1 || echo "skip"`)
|
||||
const lintErrors = (lintResult.match(/\d+ error/)?.[0]?.match(/\d+/)?.[0] || 0) * 1
|
||||
validationResults.lint_check = {
|
||||
status: lintErrors === 0 || /skip/.test(lintResult) ? 'PASS' : 'FAIL',
|
||||
errors: lintErrors
|
||||
}
|
||||
| Detection | Command |
|
||||
|-----------|---------|
|
||||
| Node.js | `<cmdPrefix>npm test` or `<cmdPrefix>npx vitest run` |
|
||||
| Python | `<cmdPrefix>python -m pytest` |
|
||||
| No tests | Skip with "no-tests" note |
|
||||
|
||||
// 4. 质量分析(可选 CLI)
|
||||
// 通过对比债务分数评估改善
|
||||
const debtScoreAfter = debtInventory.filter(i =>
|
||||
!fixResults.files_modified?.includes(i.file)
|
||||
).length
|
||||
validationResults.quality_analysis = {
|
||||
status: debtScoreAfter < debtScoreBefore ? 'IMPROVED' : 'NO_CHANGE',
|
||||
debt_score_before: debtScoreBefore,
|
||||
debt_score_after: debtScoreAfter,
|
||||
improvement: debtScoreBefore - debtScoreAfter
|
||||
}
|
||||
```
|
||||
| Pass Criteria | Status |
|
||||
|---------------|--------|
|
||||
| No FAIL/error/failed keywords | PASS |
|
||||
| "no-tests" detected | PASS (skip) |
|
||||
| Otherwise | FAIL + count regressions |
|
||||
|
||||
**2. Type Check** (in worktree):
|
||||
|
||||
| Command | `<cmdPrefix>npx tsc --noEmit` |
|
||||
|---------|-------------------------------|
|
||||
|
||||
| Pass Criteria | Status |
|
||||
|---------------|--------|
|
||||
| No TS errors or "skip" | PASS |
|
||||
| TS errors found | FAIL + count errors |
|
||||
|
||||
**3. Lint Check** (in worktree):
|
||||
|
||||
| Command | `<cmdPrefix>npx eslint --no-error-on-unmatched-pattern <files>` |
|
||||
|---------|----------------------------------------------------------------|
|
||||
|
||||
| Pass Criteria | Status |
|
||||
|---------------|--------|
|
||||
| No errors or "skip" | PASS |
|
||||
| Errors found | FAIL + count errors |
|
||||
|
||||
**4. Quality Analysis**:
|
||||
|
||||
| Metric | Calculation |
|
||||
|--------|-------------|
|
||||
| debt_score_after | debtInventory.filter(not in modified files).length |
|
||||
| improvement | debt_score_before - debt_score_after |
|
||||
|
||||
| Condition | Status |
|
||||
|-----------|--------|
|
||||
| debt_score_after < debt_score_before | IMPROVED |
|
||||
| Otherwise | NO_CHANGE |
|
||||
|
||||
### Phase 4: Compare Before/After & Generate Report
|
||||
|
||||
```javascript
|
||||
const totalRegressions = validationResults.test_suite.regressions +
|
||||
validationResults.type_check.errors + validationResults.lint_check.errors
|
||||
const passed = totalRegressions === 0
|
||||
**Calculate totals**:
|
||||
|
||||
const report = {
|
||||
validation_date: new Date().toISOString(),
|
||||
passed,
|
||||
regressions: totalRegressions,
|
||||
checks: validationResults,
|
||||
debt_score_before: debtScoreBefore,
|
||||
debt_score_after: validationResults.quality_analysis.debt_score_after,
|
||||
improvement_percentage: debtScoreBefore > 0
|
||||
? Math.round(((debtScoreBefore - validationResults.quality_analysis.debt_score_after) / debtScoreBefore) * 100)
|
||||
: 0
|
||||
}
|
||||
| Metric | Calculation |
|
||||
|--------|-------------|
|
||||
| total_regressions | test_regressions + type_errors + lint_errors |
|
||||
| passed | total_regressions === 0 |
|
||||
|
||||
// 保存验证报告
|
||||
Bash(`mkdir -p "${sessionFolder}/validation"`)
|
||||
Write(`${sessionFolder}/validation/validation-report.json`, JSON.stringify(report, null, 2))
|
||||
**Report structure**:
|
||||
|
||||
// 更新 shared memory
|
||||
sharedMemory.validation_results = report
|
||||
sharedMemory.debt_score_after = report.debt_score_after
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
```
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `validation_date` | ISO timestamp |
|
||||
| `passed` | Boolean |
|
||||
| `regressions` | Total regression count |
|
||||
| `checks` | Validation results per check |
|
||||
| `debt_score_before` | Initial debt score |
|
||||
| `debt_score_after` | Final debt score |
|
||||
| `improvement_percentage` | Percentage improvement |
|
||||
|
||||
**Save outputs**:
|
||||
|
||||
1. Write `<session-folder>/validation/validation-report.json`
|
||||
2. Update shared-memory.json with `validation_results` and `debt_score_after`
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
const msgType = passed ? 'validation_complete' : 'regression_found'
|
||||
const statusMsg = passed
|
||||
? `验证通过: 0 regressions, debt ${debtScoreBefore} → ${report.debt_score_after} (${report.improvement_percentage}% 改善)`
|
||||
: `发现 ${totalRegressions} 个回归 (tests: ${validationResults.test_suite.regressions}, types: ${validationResults.type_check.errors}, lint: ${validationResults.lint_check.errors})`
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "validator",
|
||||
to: "coordinator",
|
||||
type: msgType,
|
||||
summary: `[validator] ${statusMsg}`,
|
||||
ref: `${sessionFolder}/validation/validation-report.json`,
|
||||
data: { passed, regressions: totalRegressions }
|
||||
})
|
||||
Standard report flow: team_msg log -> SendMessage with `[validator]` prefix -> TaskUpdate completed -> Loop to Phase 1 for next task.
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## [validator] Validation Results
|
||||
**Message type selection**:
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Status**: ${passed ? 'PASS' : 'FAIL - Regressions Found'}
|
||||
| Condition | Message Type |
|
||||
|-----------|--------------|
|
||||
| passed | validation_complete |
|
||||
| not passed | regression_found |
|
||||
|
||||
### Check Results
|
||||
| Check | Status | Details |
|
||||
|-------|--------|---------|
|
||||
| Test Suite | ${validationResults.test_suite.status} | ${validationResults.test_suite.regressions} regressions |
|
||||
| Type Check | ${validationResults.type_check.status} | ${validationResults.type_check.errors} errors |
|
||||
| Lint | ${validationResults.lint_check.status} | ${validationResults.lint_check.errors} errors |
|
||||
| Quality | ${validationResults.quality_analysis.status} | ${report.improvement_percentage}% improvement |
|
||||
**Report content**:
|
||||
|
||||
### Debt Score
|
||||
- Before: ${debtScoreBefore}
|
||||
- After: ${report.debt_score_after}
|
||||
- Improvement: ${report.improvement_percentage}%
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Task | task.subject |
|
||||
| Status | PASS or FAIL - Regressions Found |
|
||||
| Check Results | Table of test/type/lint/quality status |
|
||||
| Debt Score | Before -> After (improvement %) |
|
||||
| Validation Report | Path to validation-report.json |
|
||||
|
||||
### Validation Report
|
||||
${sessionFolder}/validation/validation-report.json`,
|
||||
summary: `[validator] TDVAL complete: ${statusMsg}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('TDVAL-') && t.owner === 'validator' &&
|
||||
t.status === 'pending' && t.blockedBy.length === 0
|
||||
)
|
||||
if (nextTasks.length > 0) { /* back to Phase 1 */ }
|
||||
```
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
|
||||
Reference in New Issue
Block a user