Files
Claude-Code-Workflow/.claude/skills/team-testing/roles/analyst.md
catlog22 0d56396710 feat: Add 4 new team skills with Generator-Critic loops, shared memory, and dynamic pipelines
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.
2026-02-15 18:09:57 +08:00

7.1 KiB
Raw Blame History

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