Files
Claude-Code-Workflow/.claude/skills/review-code/phases/actions/action-generate-report.md
catlog22 29c8bb7a66 feat: Add orchestrator and state management for code review process
- Implemented orchestrator logic to manage code review phases, including state reading, action selection, and execution loop.
- Defined state schema for review process, including metadata, context, findings, and execution tracking.
- Created action catalog detailing actions for context collection, quick scan, deep review, report generation, and completion.
- Established error recovery strategies and termination conditions for robust review handling.
- Developed issue classification and quality standards documentation to guide review severity and categorization.
- Introduced review dimensions with detailed checklists for correctness, security, performance, readability, testing, and architecture.
- Added templates for issue reporting and review reports to standardize output and improve clarity.
2026-01-13 14:39:16 +08:00

6.2 KiB

Action: Generate Report

汇总所有发现,生成结构化审查报告。

Purpose

生成最终的代码审查报告:

  • 汇总所有维度的发现
  • 按严重程度排序
  • 提供统计摘要
  • 输出 Markdown 格式报告

Preconditions

  • state.status === 'running'
  • 所有维度已审查完成 (reviewed_dimensions.length === 6)

Execution

async function execute(state, workDir) {
  const context = state.context;
  const findings = state.findings;
  
  // 1. 汇总所有发现
  const allFindings = [
    ...findings.correctness,
    ...findings.readability,
    ...findings.performance,
    ...findings.security,
    ...findings.testing,
    ...findings.architecture
  ];
  
  // 2. 按严重程度排序
  const severityOrder = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
  allFindings.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
  
  // 3. 统计
  const stats = {
    total_issues: allFindings.length,
    critical: allFindings.filter(f => f.severity === 'critical').length,
    high: allFindings.filter(f => f.severity === 'high').length,
    medium: allFindings.filter(f => f.severity === 'medium').length,
    low: allFindings.filter(f => f.severity === 'low').length,
    info: allFindings.filter(f => f.severity === 'info').length,
    by_dimension: {
      correctness: findings.correctness.length,
      readability: findings.readability.length,
      performance: findings.performance.length,
      security: findings.security.length,
      testing: findings.testing.length,
      architecture: findings.architecture.length
    }
  };
  
  // 4. 生成报告
  const report = generateMarkdownReport(context, stats, allFindings, state.scan_summary);
  
  // 5. 保存报告
  const reportPath = `${workDir}/review-report.md`;
  Write(reportPath, report);
  
  return {
    stateUpdates: {
      report_generated: true,
      report_path: reportPath,
      summary: {
        ...stats,
        review_duration_ms: Date.now() - new Date(state.started_at).getTime()
      }
    }
  };
}

function generateMarkdownReport(context, stats, findings, scanSummary) {
  const severityEmoji = {
    critical: '🔴',
    high: '🟠',
    medium: '🟡',
    low: '🔵',
    info: '⚪'
  };
  
  let report = `# Code Review Report

## 审查概览

| 项目 | 值 |
|------|------|
| 目标路径 | \`${context.target_path}\` |
| 文件数量 | ${context.file_count} |
| 代码行数 | ${context.total_lines} |
| 主要语言 | ${context.language} |
| 框架 | ${context.framework || 'N/A'} |

## 问题统计

| 严重程度 | 数量 |
|----------|------|
| 🔴 Critical | ${stats.critical} |
| 🟠 High | ${stats.high} |
| 🟡 Medium | ${stats.medium} |
| 🔵 Low | ${stats.low} |
| ⚪ Info | ${stats.info} |
| **总计** | **${stats.total_issues}** |

### 按维度统计

| 维度 | 问题数 |
|------|--------|
| Correctness (正确性) | ${stats.by_dimension.correctness} |
| Security (安全性) | ${stats.by_dimension.security} |
| Performance (性能) | ${stats.by_dimension.performance} |
| Readability (可读性) | ${stats.by_dimension.readability} |
| Testing (测试) | ${stats.by_dimension.testing} |
| Architecture (架构) | ${stats.by_dimension.architecture} |

---

## 高风险区域

`;

  if (scanSummary?.risk_areas?.length > 0) {
    report += `| 文件 | 原因 | 优先级 |
|------|------|--------|
`;
    for (const area of scanSummary.risk_areas.slice(0, 10)) {
      report += `| \`${area.file}\` | ${area.reason} | ${area.priority} |\n`;
    }
  } else {
    report += `未发现明显的高风险区域。\n`;
  }

  report += `
---

## 问题详情

`;

  // 按维度分组输出
  const dimensions = ['correctness', 'security', 'performance', 'readability', 'testing', 'architecture'];
  const dimensionNames = {
    correctness: '正确性 (Correctness)',
    security: '安全性 (Security)',
    performance: '性能 (Performance)',
    readability: '可读性 (Readability)',
    testing: '测试 (Testing)',
    architecture: '架构 (Architecture)'
  };

  for (const dim of dimensions) {
    const dimFindings = findings.filter(f => f.dimension === dim);
    if (dimFindings.length === 0) continue;
    
    report += `### ${dimensionNames[dim]}

`;
    
    for (const finding of dimFindings) {
      report += `#### ${severityEmoji[finding.severity]} [${finding.id}] ${finding.category}

- **严重程度**: ${finding.severity.toUpperCase()}
- **文件**: \`${finding.file}\`${finding.line ? `:${finding.line}` : ''}
- **描述**: ${finding.description}
`;
      
      if (finding.code_snippet) {
        report += `
\`\`\`
${finding.code_snippet}
\`\`\`
`;
      }
      
      report += `
**建议**: ${finding.recommendation}
`;
      
      if (finding.fix_example) {
        report += `
**修复示例**:
\`\`\`
${finding.fix_example}
\`\`\`
`;
      }
      
      report += `
---

`;
    }
  }

  report += `
## 审查建议

### 必须修复 (Must Fix)

${stats.critical + stats.high > 0 
  ? `发现 ${stats.critical} 个严重问题和 ${stats.high} 个高优先级问题,建议在合并前修复。`
  : '未发现必须立即修复的问题。'}

### 建议改进 (Should Fix)

${stats.medium > 0 
  ? `发现 ${stats.medium} 个中等优先级问题,建议在后续迭代中改进。`
  : '代码质量良好,无明显需要改进的地方。'}

### 可选优化 (Nice to Have)

${stats.low + stats.info > 0 
  ? `发现 ${stats.low + stats.info} 个低优先级建议,可根据团队规范酌情处理。`
  : '无额外建议。'}

---

*报告生成时间: ${new Date().toISOString()}*
`;

  return report;
}

State Updates

return {
  stateUpdates: {
    report_generated: true,
    report_path: reportPath,
    summary: {
      total_issues: totalCount,
      critical: criticalCount,
      high: highCount,
      medium: mediumCount,
      low: lowCount,
      info: infoCount,
      review_duration_ms: duration
    }
  }
};

Output

  • File: review-report.md
  • Location: ${workDir}/review-report.md
  • Format: Markdown

Error Handling

Error Type Recovery
写入失败 尝试备用位置
模板错误 使用简化格式

Next Actions

  • 成功: action-complete