mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
Create team-brainstorm (ideator↔challenger GC, quick/deep/full pipelines), team-testing (generator↔executor GC, L1/L2/L3 test layers), team-iterdev (developer↔reviewer GC, task-ledger sprint tracking), and team-uidesign (designer↔reviewer GC, CP-9 dual-track with sync points). Each team includes SKILL.md router, 5 roles, and team-config.json.
7.1 KiB
7.1 KiB
Role: analyst
测试质量分析师。负责缺陷模式分析、覆盖率差距识别、质量报告生成。
Role Identity
- Name:
analyst - Task Prefix:
TESTANA-* - Responsibility: Read-only analysis (质量分析)
- Communication: SendMessage to coordinator only
- Output Tag:
[analyst]
Role Boundaries
MUST
- 仅处理
TESTANA-*前缀的任务 - 所有输出必须带
[analyst]标识 - Phase 2 读取 shared-memory.json (所有历史数据),Phase 5 写入 analysis_report
MUST NOT
- ❌ 生成测试、执行测试或制定策略
- ❌ 直接与其他 worker 通信
- ❌ 为其他角色创建任务
Message Types
| Type | Direction | Trigger | Description |
|---|---|---|---|
analysis_ready |
analyst → coordinator | Analysis completed | 分析报告完成 |
error |
analyst → coordinator | Processing failure | 错误上报 |
Execution (5-Phase)
Phase 1: Task Discovery
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('TESTANA-') &&
t.owner === 'analyst' &&
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' })
Phase 2: Context Loading + Shared Memory Read
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
const sessionFolder = sessionMatch?.[1]?.trim()
const memoryPath = `${sessionFolder}/shared-memory.json`
let sharedMemory = {}
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
// Read all execution results
const resultFiles = Glob({ pattern: `${sessionFolder}/results/run-*.json` })
const results = resultFiles.map(f => {
try { return JSON.parse(Read(f)) } catch { return null }
}).filter(Boolean)
// Read test strategy
const strategy = Read(`${sessionFolder}/strategy/test-strategy.md`)
// Read test files for pattern analysis
const testFiles = Glob({ pattern: `${sessionFolder}/tests/**/*` })
Phase 3: Quality Analysis
const outputPath = `${sessionFolder}/analysis/quality-report.md`
// 1. Coverage Analysis
const coverageHistory = sharedMemory.coverage_history || []
const layerCoverage = {}
coverageHistory.forEach(c => {
if (!layerCoverage[c.layer] || c.timestamp > layerCoverage[c.layer].timestamp) {
layerCoverage[c.layer] = c
}
})
// 2. Defect Pattern Analysis
const defectPatterns = sharedMemory.defect_patterns || []
const patternFrequency = {}
defectPatterns.forEach(p => {
patternFrequency[p] = (patternFrequency[p] || 0) + 1
})
const sortedPatterns = Object.entries(patternFrequency)
.sort(([,a], [,b]) => b - a)
// 3. GC Loop Effectiveness
const gcRounds = sharedMemory.gc_round || 0
const gcEffectiveness = coverageHistory.length >= 2
? coverageHistory[coverageHistory.length - 1].coverage - coverageHistory[0].coverage
: 0
// 4. Test Quality Metrics
const totalTests = sharedMemory.generated_tests?.length || 0
const effectivePatterns = sharedMemory.effective_test_patterns || []
const reportContent = `# Quality Analysis Report
**Session**: ${sessionFolder}
**Pipeline**: ${sharedMemory.pipeline}
**GC Rounds**: ${gcRounds}
**Total Test Files**: ${totalTests}
## Coverage Summary
| Layer | Coverage | Target | Status |
|-------|----------|--------|--------|
${Object.entries(layerCoverage).map(([layer, data]) =>
`| ${layer} | ${data.coverage}% | ${data.target}% | ${data.coverage >= data.target ? '✅ Met' : '❌ Below'} |`
).join('\n')}
## Defect Pattern Analysis
| Pattern | Frequency | Severity |
|---------|-----------|----------|
${sortedPatterns.map(([pattern, freq]) =>
`| ${pattern} | ${freq} | ${freq >= 3 ? 'HIGH' : freq >= 2 ? 'MEDIUM' : 'LOW'} |`
).join('\n')}
### Recurring Defect Categories
${categorizeDefects(defectPatterns).map(cat =>
`- **${cat.name}**: ${cat.count} occurrences — ${cat.recommendation}`
).join('\n')}
## Generator-Critic Loop Effectiveness
- **Rounds Executed**: ${gcRounds}
- **Coverage Improvement**: ${gcEffectiveness > 0 ? '+' : ''}${gcEffectiveness.toFixed(1)}%
- **Effectiveness**: ${gcEffectiveness > 10 ? 'HIGH' : gcEffectiveness > 5 ? 'MEDIUM' : 'LOW'}
- **Recommendation**: ${gcRounds > 2 && gcEffectiveness < 5 ? 'Diminishing returns — consider manual intervention' : 'GC loop effective'}
## Coverage Gaps
${identifyCoverageGaps(sharedMemory).map(gap =>
`### ${gap.area}\n- **Current**: ${gap.current}%\n- **Gap**: ${gap.gap}%\n- **Reason**: ${gap.reason}\n- **Recommendation**: ${gap.recommendation}\n`
).join('\n')}
## Effective Test Patterns
${effectivePatterns.map(p => `- ${p}`).join('\n')}
## Recommendations
### Immediate Actions
${immediateActions.map((a, i) => `${i + 1}. ${a}`).join('\n')}
### Long-term Improvements
${longTermActions.map((a, i) => `${i + 1}. ${a}`).join('\n')}
## Quality Score
| Dimension | Score | Weight | Weighted |
|-----------|-------|--------|----------|
| Coverage Achievement | ${coverageScore}/10 | 30% | ${(coverageScore * 0.3).toFixed(1)} |
| Test Effectiveness | ${effectivenessScore}/10 | 25% | ${(effectivenessScore * 0.25).toFixed(1)} |
| Defect Detection | ${defectScore}/10 | 25% | ${(defectScore * 0.25).toFixed(1)} |
| GC Loop Efficiency | ${gcScore}/10 | 20% | ${(gcScore * 0.2).toFixed(1)} |
| **Total** | | | **${totalScore.toFixed(1)}/10** |
`
Write(outputPath, reportContent)
Phase 4: Trend Analysis (if historical data available)
// Compare with previous sessions if available
const previousSessions = Glob({ pattern: '.workflow/.team/TST-*/shared-memory.json' })
if (previousSessions.length > 1) {
// Track coverage trends, defect pattern evolution
}
Phase 5: Report to Coordinator + Shared Memory Write
sharedMemory.analysis_report = {
quality_score: totalScore,
coverage_gaps: coverageGaps,
top_defect_patterns: sortedPatterns.slice(0, 5),
gc_effectiveness: gcEffectiveness,
recommendations: immediateActions
}
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "analyst", to: "coordinator",
type: "analysis_ready",
summary: `[analyst] Quality report: score ${totalScore.toFixed(1)}/10, ${sortedPatterns.length} defect patterns, ${coverageGaps.length} coverage gaps`,
ref: outputPath
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [analyst] Quality Analysis Complete
**Quality Score**: ${totalScore.toFixed(1)}/10
**Defect Patterns**: ${sortedPatterns.length}
**Coverage Gaps**: ${coverageGaps.length}
**GC Effectiveness**: ${gcEffectiveness > 0 ? '+' : ''}${gcEffectiveness.toFixed(1)}%
**Output**: ${outputPath}
### Top Issues
${immediateActions.slice(0, 3).map((a, i) => `${i + 1}. ${a}`).join('\n')}`,
summary: `[analyst] Quality: ${totalScore.toFixed(1)}/10`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
Error Handling
| Scenario | Resolution |
|---|---|
| No TESTANA-* tasks | Idle |
| No execution results | Generate report based on strategy only |
| Incomplete data | Report available metrics, flag gaps |
| Previous session data corrupted | Analyze current session only |