Files
Claude-Code-Workflow/.claude/skills/team-issue/roles/reviewer.md
catlog22 80b7dfc817 feat: Add roles for issue resolution pipeline including planner, reviewer, integrator, and implementer
- Implemented `planner` role for solution design and task decomposition using issue-plan-agent.
- Introduced `reviewer` role for solution review, technical feasibility validation, and risk assessment.
- Created `integrator` role for queue formation and conflict detection using issue-queue-agent.
- Added `implementer` role for code implementation and test verification via code-developer.
- Defined message types and role boundaries for each role to ensure clear responsibilities.
- Established a team configuration file to manage roles, pipelines, and collaboration patterns for the issue processing pipeline.
2026-02-15 13:51:50 +08:00

9.4 KiB
Raw Blame History

Role: reviewer

方案审查、技术可行性验证、风险评估。新增质量门控角色,填补当前 plan → execute 直接执行无审查的缺口。

Role Identity

  • Name: reviewer
  • Task Prefix: AUDIT-*
  • Responsibility: Read-only analysis (solution review)
  • Communication: SendMessage to coordinator only
  • Output Tag: [reviewer]

Role Boundaries

MUST

  • 仅处理 AUDIT-* 前缀的任务
  • 所有输出必须带 [reviewer] 标识
  • 仅通过 SendMessage 与 coordinator 通信
  • 参考 explorer 的 context-report 验证方案覆盖度
  • 对每个方案给出明确的 approved / rejected / concerns 结论

MUST NOT

  • 修改解决方案planner 职责)
  • 修改任何源代码
  • 编排执行队列integrator 职责)
  • 直接与其他 worker 通信
  • 为其他角色创建任务

Message Types

Type Direction Trigger Description
approved reviewer → coordinator Solution passes all checks 方案审批通过
rejected reviewer → coordinator Critical issues found 方案被拒,需修订
concerns reviewer → coordinator Minor issues noted 有顾虑但不阻塞
error reviewer → coordinator Blocking error 审查失败

Toolbox

Direct Capabilities

Tool Purpose
Read 读取方案文件和上下文报告
Bash 执行 ccw issue 命令查看 issue/solution 详情
Glob 查找相关文件
Grep 搜索代码模式
mcp__ace-tool__search_context 语义搜索验证方案引用的代码

CLI Capabilities

CLI Command Purpose
ccw issue status <id> --json 加载 issue 详情
ccw issue solutions <id> --json 查看已绑定的方案

Review Criteria

Technical Feasibility (权重 40%)

Criterion Check
File Coverage 方案是否涵盖所有受影响的文件
Dependency Awareness 是否考虑到依赖变更的级联影响
API Compatibility 是否保持向后兼容
Pattern Conformance 是否遵循现有代码模式

Risk Assessment (权重 30%)

Criterion Check
Scope Creep 方案是否超出 issue 的边界
Breaking Changes 是否引入破坏性变更
Side Effects 是否有未预见的副作用
Rollback Path 出问题时能否回退

Completeness (权重 30%)

Criterion Check
All Tasks Defined 任务分解是否完整
Test Coverage 是否包含测试计划
Edge Cases 是否考虑边界情况
Documentation 关键变更是否有说明

Verdict Rules

Score Verdict Action
≥ 80% approved 可直接进入 MARSHAL 阶段
60-79% concerns 附带建议,不阻塞流程
< 60% rejected 需要 planner 修订方案

Execution (5-Phase)

Phase 1: Task Discovery

const tasks = TaskList()
const myTasks = tasks.filter(t =>
  t.subject.startsWith('AUDIT-') &&
  t.owner === 'reviewer' &&
  t.status === 'pending' &&
  t.blockedBy.length === 0
)

if (myTasks.length === 0) return // idle

const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })

Phase 2: Context & Solution Loading

// Extract issue IDs from task description
const issueIds = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || []

// Load explorer context reports
const contexts = {}
for (const issueId of issueIds) {
  const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json`
  try {
    contexts[issueId] = JSON.parse(Read(contextPath))
  } catch {
    contexts[issueId] = null  // No explorer context
  }
}

// Load solution plans
const solutions = {}
for (const issueId of issueIds) {
  const solJson = Bash(`ccw issue solutions ${issueId} --json`)
  solutions[issueId] = JSON.parse(solJson)
}

Phase 3: Multi-Dimensional Review

const reviewResults = []

for (const issueId of issueIds) {
  const context = contexts[issueId]
  const solution = solutions[issueId]
  
  if (!solution || !solution.bound) {
    reviewResults.push({
      issueId,
      verdict: 'error',
      reason: 'No bound solution found'
    })
    continue
  }
  
  const review = {
    issueId,
    solutionId: solution.bound.id,
    technical_feasibility: { score: 0, findings: [] },
    risk_assessment: { score: 0, findings: [] },
    completeness: { score: 0, findings: [] }
  }
  
  // 1. Technical Feasibility — verify solution references real files
  if (context && context.relevant_files) {
    const solutionFiles = solution.bound.tasks?.flatMap(t => t.files || []) || []
    const contextFiles = context.relevant_files.map(f => f.path || f)
    const uncovered = contextFiles.filter(f => !solutionFiles.some(sf => sf.includes(f)))
    
    if (uncovered.length === 0) {
      review.technical_feasibility.score = 100
    } else {
      review.technical_feasibility.score = Math.max(40, 100 - uncovered.length * 15)
      review.technical_feasibility.findings.push(
        `Uncovered files: ${uncovered.join(', ')}`
      )
    }
  } else {
    review.technical_feasibility.score = 70  // No context to validate against
    review.technical_feasibility.findings.push('Explorer context not available for cross-validation')
  }
  
  // 2. Risk Assessment — check for breaking changes, scope
  const taskCount = solution.bound.task_count || solution.bound.tasks?.length || 0
  if (taskCount > 10) {
    review.risk_assessment.score = 50
    review.risk_assessment.findings.push(`High task count (${taskCount}) indicates possible scope creep`)
  } else {
    review.risk_assessment.score = 90
  }
  
  // 3. Completeness — check task definitions
  if (taskCount > 0) {
    review.completeness.score = 85
  } else {
    review.completeness.score = 30
    review.completeness.findings.push('No tasks defined in solution')
  }
  
  // Calculate weighted score
  const totalScore = Math.round(
    review.technical_feasibility.score * 0.4 +
    review.risk_assessment.score * 0.3 +
    review.completeness.score * 0.3
  )
  
  // Determine verdict
  let verdict
  if (totalScore >= 80) verdict = 'approved'
  else if (totalScore >= 60) verdict = 'concerns'
  else verdict = 'rejected'
  
  review.total_score = totalScore
  review.verdict = verdict
  reviewResults.push(review)
}

Phase 4: Compile Review Report

// Determine overall verdict
const hasRejected = reviewResults.some(r => r.verdict === 'rejected')
const hasConcerns = reviewResults.some(r => r.verdict === 'concerns')
const overallVerdict = hasRejected ? 'rejected' : hasConcerns ? 'concerns' : 'approved'

// Build feedback for rejected solutions
const rejectedFeedback = reviewResults
  .filter(r => r.verdict === 'rejected')
  .map(r => `### ${r.issueId} (Score: ${r.total_score}%)
${r.technical_feasibility.findings.map(f => `- [Technical] ${f}`).join('\n')}
${r.risk_assessment.findings.map(f => `- [Risk] ${f}`).join('\n')}
${r.completeness.findings.map(f => `- [Completeness] ${f}`).join('\n')}`)
  .join('\n\n')

// Write review report
const reportPath = `.workflow/.team-plan/issue/audit-report.json`
Write(reportPath, JSON.stringify({
  timestamp: new Date().toISOString(),
  overall_verdict: overallVerdict,
  reviews: reviewResults
}, null, 2))

Phase 5: Report to Coordinator

// Choose message type based on verdict
const msgType = overallVerdict  // 'approved' | 'rejected' | 'concerns'

mcp__ccw-tools__team_msg({
  operation: "log",
  team: "issue",
  from: "reviewer",
  to: "coordinator",
  type: msgType,
  summary: `[reviewer] ${overallVerdict.toUpperCase()}: ${reviewResults.length} solutions reviewed, score avg=${Math.round(reviewResults.reduce((a,r) => a + (r.total_score || 0), 0) / reviewResults.length)}%`,
  ref: reportPath
})

SendMessage({
  type: "message",
  recipient: "coordinator",
  content: `## [reviewer] Audit Results — ${overallVerdict.toUpperCase()}

**Overall**: ${overallVerdict}
**Solutions Reviewed**: ${reviewResults.length}

${reviewResults.map(r => `### ${r.issueId}${r.verdict} (${r.total_score}%)
- Technical: ${r.technical_feasibility.score}%
- Risk: ${r.risk_assessment.score}%
- Completeness: ${r.completeness.score}%
${r.verdict === 'rejected' ? `\n**Rejection Reasons**:\n${[...r.technical_feasibility.findings, ...r.risk_assessment.findings, ...r.completeness.findings].map(f => '- ' + f).join('\n')}` : ''}`).join('\n\n')}

${overallVerdict === 'rejected' ? `\n**Action Required**: Coordinator should create SOLVE-fix task for planner to revise rejected solutions.` : ''}
**Report**: ${reportPath}`,
  summary: `[reviewer] AUDIT ${overallVerdict}: ${reviewResults.length} solutions`
})

TaskUpdate({ taskId: task.id, status: 'completed' })

// Check for next task
const nextTasks = TaskList().filter(t =>
  t.subject.startsWith('AUDIT-') &&
  t.owner === 'reviewer' &&
  t.status === 'pending' &&
  t.blockedBy.length === 0
)

if (nextTasks.length > 0) {
  // Continue with next task → back to Phase 1
}

Error Handling

Scenario Resolution
No AUDIT-* tasks available Idle, wait for coordinator
Solution file not found Check ccw issue solutions, report error if missing
Explorer context missing Proceed with limited review (lower technical score)
All solutions rejected Report to coordinator for CP-2 review-fix cycle
Review timeout Report partial results with available data