mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 13:13:50 +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,204 +1,300 @@
|
||||
# Role: executor
|
||||
# Executor Role
|
||||
|
||||
测试执行者。执行测试、收集覆盖率、尝试自动修复失败。作为 Generator-Critic 循环中的 Critic 角色。
|
||||
Test executor. Executes tests, collects coverage, attempts auto-fix for failures. Acts as the Critic in the Generator-Critic loop.
|
||||
|
||||
## Role Identity
|
||||
## Identity
|
||||
|
||||
- **Name**: `executor`
|
||||
- **Name**: `executor` | **Tag**: `[executor]`
|
||||
- **Task Prefix**: `TESTRUN-*`
|
||||
- **Responsibility**: Validation (测试执行与验证)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[executor]`
|
||||
- **Responsibility**: Validation (test execution and verification)
|
||||
|
||||
## Role Boundaries
|
||||
## Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `TESTRUN-*` 前缀的任务
|
||||
- 所有输出必须带 `[executor]` 标识
|
||||
- Phase 2 读取 shared-memory.json,Phase 5 写入 execution_results + defect_patterns
|
||||
- 报告覆盖率和通过率供 coordinator 做 GC 判断
|
||||
- Only process `TESTRUN-*` prefixed tasks
|
||||
- All output (SendMessage, team_msg, logs) must carry `[executor]` identifier
|
||||
- Only communicate with coordinator via SendMessage
|
||||
- Work strictly within validation responsibility scope
|
||||
- Phase 2: Read shared-memory.json
|
||||
- Phase 5: Write execution_results + defect_patterns to shared-memory.json
|
||||
- Report coverage and pass rate for coordinator's GC decision
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 生成新测试、制定策略或分析趋势
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 为其他角色创建任务
|
||||
- Execute work outside this role's responsibility scope (no test generation, strategy formulation, or trend analysis)
|
||||
- Communicate directly with other worker roles (must go through coordinator)
|
||||
- Create tasks for other roles (TaskCreate is coordinator-exclusive)
|
||||
- Modify files or resources outside this role's responsibility
|
||||
- Omit `[executor]` identifier in any output
|
||||
|
||||
---
|
||||
|
||||
## Toolbox
|
||||
|
||||
### Tool Capabilities
|
||||
|
||||
| Tool | Type | Used By | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| Read | Read | Phase 2 | Load shared-memory.json |
|
||||
| Glob | Read | Phase 2 | Find test files to execute |
|
||||
| Bash | Execute | Phase 3 | Run test commands |
|
||||
| Write | Write | Phase 3 | Save test results |
|
||||
| Task | Delegate | Phase 3 | Delegate fix to code-developer |
|
||||
| TaskUpdate | Write | Phase 5 | Mark task completed |
|
||||
| SendMessage | Write | Phase 5 | Report to coordinator |
|
||||
|
||||
---
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `tests_passed` | executor → coordinator | All tests pass + coverage met | 测试通过 |
|
||||
| `tests_failed` | executor → coordinator | Tests fail or coverage below target | 测试失败/覆盖不足 |
|
||||
| `coverage_report` | executor → coordinator | Coverage data collected | 覆盖率数据 |
|
||||
| `error` | executor → coordinator | Execution environment failure | 错误上报 |
|
||||
| `tests_passed` | executor -> coordinator | All tests pass + coverage met | Tests passed |
|
||||
| `tests_failed` | executor -> coordinator | Tests fail or coverage below target | Tests failed / coverage insufficient |
|
||||
| `coverage_report` | executor -> coordinator | Coverage data collected | Coverage data |
|
||||
| `error` | executor -> coordinator | Execution environment failure | Error report |
|
||||
|
||||
## Message Bus
|
||||
|
||||
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: "testing",
|
||||
from: "executor",
|
||||
to: "coordinator",
|
||||
type: <message-type>,
|
||||
summary: "[executor] TESTRUN complete: <summary>",
|
||||
ref: <artifact-path>
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team testing --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('TESTRUN-') &&
|
||||
t.owner === 'executor' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
if (myTasks.length === 0) return
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
|
||||
|
||||
Standard task discovery flow: TaskList -> filter by prefix `TESTRUN-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
**Input Sources**:
|
||||
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| Session path | Task description (Session: <path>) | Yes |
|
||||
| Shared memory | <session-folder>/shared-memory.json | Yes |
|
||||
| Test directory | Task description (Input: <path>) | Yes |
|
||||
| Coverage target | Task description | Yes |
|
||||
|
||||
**Loading steps**:
|
||||
|
||||
1. Extract session path from task description (look for `Session: <path>`)
|
||||
2. Extract test directory from task description (look for `Input: <path>`)
|
||||
3. Extract coverage target from task description (default: 80%)
|
||||
|
||||
```
|
||||
Read("<session-folder>/shared-memory.json")
|
||||
```
|
||||
|
||||
### Phase 2: Context Loading + Shared Memory Read
|
||||
4. Determine test framework from shared memory:
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
| Framework | Detection |
|
||||
|-----------|-----------|
|
||||
| Jest | sharedMemory.test_strategy.framework === "Jest" |
|
||||
| Pytest | sharedMemory.test_strategy.framework === "Pytest" |
|
||||
| Vitest | sharedMemory.test_strategy.framework === "Vitest" |
|
||||
| Unknown | Default to Jest |
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
5. Find test files to execute:
|
||||
|
||||
const framework = sharedMemory.test_strategy?.framework || 'Jest'
|
||||
const coverageTarget = parseInt(task.description.match(/覆盖率目标:\s*(\d+)/)?.[1] || '80')
|
||||
|
||||
// Find test files to execute
|
||||
const testDir = task.description.match(/输入:\s*([^\n]+)/)?.[1]?.trim()
|
||||
const testFiles = Glob({ pattern: `${sessionFolder}/${testDir || 'tests'}/**/*` })
|
||||
```
|
||||
Glob({ pattern: "<session-folder>/<test-dir>/**/*" })
|
||||
```
|
||||
|
||||
### Phase 3: Test Execution + Fix Cycle
|
||||
|
||||
```javascript
|
||||
// Determine test command based on framework
|
||||
const testCommands = {
|
||||
'Jest': `npx jest --coverage --json --outputFile=${sessionFolder}/results/jest-output.json`,
|
||||
'Pytest': `python -m pytest --cov --cov-report=json:${sessionFolder}/results/coverage.json -v`,
|
||||
'Vitest': `npx vitest run --coverage --reporter=json`
|
||||
**Iterative test-fix cycle** (max 3 iterations):
|
||||
|
||||
| Step | Action |
|
||||
|------|--------|
|
||||
| 1 | Run test command |
|
||||
| 2 | Parse results -> check pass rate |
|
||||
| 3 | Pass rate >= 95% AND coverage >= target -> exit loop (success) |
|
||||
| 4 | Extract failing test details |
|
||||
| 5 | Delegate fix to code-developer subagent |
|
||||
| 6 | Increment iteration counter |
|
||||
| 7 | Iteration >= MAX (3) -> exit loop (report failures) |
|
||||
| 8 | Go to Step 1 |
|
||||
|
||||
**Test commands by framework**:
|
||||
|
||||
| Framework | Command |
|
||||
|-----------|---------|
|
||||
| Jest | `npx jest --coverage --json --outputFile=<session>/results/jest-output.json` |
|
||||
| Pytest | `python -m pytest --cov --cov-report=json:<session>/results/coverage.json -v` |
|
||||
| Vitest | `npx vitest run --coverage --reporter=json` |
|
||||
|
||||
**Execution**:
|
||||
|
||||
```
|
||||
Bash("<test-command> 2>&1 || true")
|
||||
```
|
||||
|
||||
**Result parsing**:
|
||||
|
||||
| Metric | Parse Method |
|
||||
|--------|--------------|
|
||||
| Passed | Output does not contain "FAIL" or "FAILED" |
|
||||
| Pass rate | Parse from test output (e.g., "X passed, Y failed") |
|
||||
| Coverage | Parse from coverage output (e.g., "All files | XX") |
|
||||
|
||||
**Auto-fix delegation** (on failure):
|
||||
|
||||
```
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false,
|
||||
description: "Fix test failures (iteration <N>)",
|
||||
prompt: "Fix these test failures:
|
||||
|
||||
<test-output>
|
||||
|
||||
Only fix the test files, not the source code."
|
||||
})
|
||||
```
|
||||
|
||||
**Result data structure**:
|
||||
|
||||
```
|
||||
{
|
||||
run_id: "run-<N>",
|
||||
pass_rate: <0.0-1.0>,
|
||||
coverage: <percentage>,
|
||||
coverage_target: <target>,
|
||||
iterations: <N>,
|
||||
passed: <pass_rate >= 0.95 && coverage >= target>,
|
||||
failure_summary: <string or null>,
|
||||
timestamp: <ISO-date>
|
||||
}
|
||||
const testCommand = testCommands[framework] || testCommands['Jest']
|
||||
```
|
||||
|
||||
// Execute tests with auto-fix cycle (max 3 iterations)
|
||||
let iteration = 0
|
||||
const MAX_FIX_ITERATIONS = 3
|
||||
let lastResult = null
|
||||
let passRate = 0
|
||||
let coverage = 0
|
||||
**Save results**:
|
||||
|
||||
while (iteration < MAX_FIX_ITERATIONS) {
|
||||
lastResult = Bash(`${testCommand} 2>&1 || true`)
|
||||
|
||||
// Parse results
|
||||
const passed = !lastResult.includes('FAIL') && !lastResult.includes('FAILED')
|
||||
passRate = parsePassRate(lastResult)
|
||||
coverage = parseCoverage(lastResult)
|
||||
|
||||
if (passed && coverage >= coverageTarget) break
|
||||
|
||||
if (iteration < MAX_FIX_ITERATIONS - 1 && !passed) {
|
||||
// Attempt auto-fix for simple failures (import errors, type mismatches)
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false,
|
||||
description: `Fix test failures (iteration ${iteration + 1})`,
|
||||
prompt: `Fix these test failures:\n${lastResult.substring(0, 3000)}\n\nOnly fix the test files, not the source code.`
|
||||
})
|
||||
}
|
||||
|
||||
iteration++
|
||||
}
|
||||
|
||||
// Save results
|
||||
const runNum = task.subject.match(/TESTRUN-(\d+)/)?.[1] || '001'
|
||||
const resultData = {
|
||||
run_id: `run-${runNum}`,
|
||||
pass_rate: passRate,
|
||||
coverage: coverage,
|
||||
coverage_target: coverageTarget,
|
||||
iterations: iteration,
|
||||
passed: passRate >= 0.95 && coverage >= coverageTarget,
|
||||
failure_summary: passRate < 0.95 ? extractFailures(lastResult) : null,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
|
||||
Write(`${sessionFolder}/results/run-${runNum}.json`, JSON.stringify(resultData, null, 2))
|
||||
```
|
||||
Write("<session-folder>/results/run-<N>.json", <result-json>)
|
||||
```
|
||||
|
||||
### Phase 4: Defect Pattern Extraction
|
||||
|
||||
```javascript
|
||||
// Extract defect patterns from failures
|
||||
if (resultData.failure_summary) {
|
||||
const newPatterns = extractDefectPatterns(lastResult)
|
||||
// Common patterns: null reference, async timing, import errors, type mismatches
|
||||
resultData.defect_patterns = newPatterns
|
||||
}
|
||||
**Extract patterns from failures** (if failure_summary exists):
|
||||
|
||||
| Pattern Type | Detection |
|
||||
|--------------|-----------|
|
||||
| Null reference | "null", "undefined", "Cannot read property" |
|
||||
| Async timing | "timeout", "async", "await", "promise" |
|
||||
| Import errors | "Cannot find module", "import" |
|
||||
| Type mismatches | "type", "expected", "received" |
|
||||
|
||||
**Record effective test patterns** (if pass_rate > 0.8):
|
||||
|
||||
| Pattern | Detection |
|
||||
|---------|-----------|
|
||||
| Happy path | Tests with "should succeed" or "valid input" |
|
||||
| Edge cases | Tests with "edge", "boundary", "limit" |
|
||||
| Error handling | Tests with "should fail", "error", "throw" |
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
|
||||
|
||||
1. **Update shared memory**:
|
||||
|
||||
// Record effective test patterns (from passing tests)
|
||||
if (passRate > 0.8) {
|
||||
const effectivePatterns = extractEffectivePatterns(testFiles)
|
||||
resultData.effective_patterns = effectivePatterns
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
// Update shared memory
|
||||
sharedMemory.execution_results.push(resultData)
|
||||
if (resultData.defect_patterns) {
|
||||
sharedMemory.execution_results.push(<result-data>)
|
||||
if (<result-data>.defect_patterns) {
|
||||
sharedMemory.defect_patterns = [
|
||||
...sharedMemory.defect_patterns,
|
||||
...resultData.defect_patterns
|
||||
...<result-data>.defect_patterns
|
||||
]
|
||||
}
|
||||
if (resultData.effective_patterns) {
|
||||
if (<result-data>.effective_patterns) {
|
||||
sharedMemory.effective_test_patterns = [
|
||||
...new Set([...sharedMemory.effective_test_patterns, ...resultData.effective_patterns])
|
||||
...new Set([...sharedMemory.effective_test_patterns, ...<result-data>.effective_patterns])
|
||||
]
|
||||
}
|
||||
sharedMemory.coverage_history.push({
|
||||
layer: testDir,
|
||||
coverage: coverage,
|
||||
target: coverageTarget,
|
||||
pass_rate: passRate,
|
||||
timestamp: new Date().toISOString()
|
||||
layer: <test-dir>,
|
||||
coverage: <coverage>,
|
||||
target: <target>,
|
||||
pass_rate: <pass_rate>,
|
||||
timestamp: <ISO-date>
|
||||
})
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
Write("<session-folder>/shared-memory.json", <updated-json>)
|
||||
```
|
||||
|
||||
const msgType = resultData.passed ? "tests_passed" : "tests_failed"
|
||||
2. **Log via team_msg**:
|
||||
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "executor", to: "coordinator",
|
||||
type: msgType,
|
||||
summary: `[executor] ${msgType}: pass=${(passRate*100).toFixed(1)}%, coverage=${coverage}% (target: ${coverageTarget}%), iterations=${iteration}`,
|
||||
ref: `${sessionFolder}/results/run-${runNum}.json`
|
||||
operation: "log", team: "testing", from: "executor", to: "coordinator",
|
||||
type: <passed ? "tests_passed" : "tests_failed">,
|
||||
summary: "[executor] <passed|failed>: pass=<pass_rate>%, coverage=<coverage>% (target: <target>%), iterations=<N>",
|
||||
ref: "<session-folder>/results/run-<N>.json"
|
||||
})
|
||||
```
|
||||
|
||||
3. **SendMessage to coordinator**:
|
||||
|
||||
```
|
||||
SendMessage({
|
||||
type: "message", recipient: "coordinator",
|
||||
content: `## [executor] Test Execution Results
|
||||
content: "## [executor] Test Execution Results
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Pass Rate**: ${(passRate * 100).toFixed(1)}%
|
||||
**Coverage**: ${coverage}% (target: ${coverageTarget}%)
|
||||
**Fix Iterations**: ${iteration}/${MAX_FIX_ITERATIONS}
|
||||
**Status**: ${resultData.passed ? '✅ PASSED' : '❌ NEEDS REVISION'}
|
||||
**Task**: <task-subject>
|
||||
**Pass Rate**: <pass_rate>%
|
||||
**Coverage**: <coverage>% (target: <target>%)
|
||||
**Fix Iterations**: <N>/3
|
||||
**Status**: <PASSED|NEEDS REVISION>
|
||||
|
||||
${resultData.defect_patterns ? `### Defect Patterns\n${resultData.defect_patterns.map(p => `- ${p}`).join('\n')}` : ''}`,
|
||||
summary: `[executor] ${resultData.passed ? 'PASSED' : 'FAILED'}: ${coverage}% coverage`
|
||||
<if-defect-patterns>
|
||||
### Defect Patterns
|
||||
- <pattern-1>
|
||||
- <pattern-2>
|
||||
</if-defect-patterns>",
|
||||
summary: "[executor] <PASSED|FAILED>: <coverage>% coverage"
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
```
|
||||
|
||||
4. **TaskUpdate completed**:
|
||||
|
||||
```
|
||||
TaskUpdate({ taskId: <task-id>, status: "completed" })
|
||||
```
|
||||
|
||||
5. **Loop**: Return to Phase 1 to check next task
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No TESTRUN-* tasks | Idle |
|
||||
| No TESTRUN-* tasks available | Idle, wait for coordinator assignment |
|
||||
| Test command fails to start | Check framework installation, notify coordinator |
|
||||
| Coverage tool unavailable | Report pass rate only |
|
||||
| All tests timeout | Increase timeout, retry once |
|
||||
| Auto-fix makes tests worse | Revert, report original failures |
|
||||
| Shared memory not found | Notify coordinator, request location |
|
||||
| Context/Plan file not found | Notify coordinator, request location |
|
||||
|
||||
Reference in New Issue
Block a user