From ecc55158c139079403fd9bf17ada94514ba09c5b Mon Sep 17 00:00:00 2001 From: AuraK Developer Date: Mon, 31 Aug 2026 11:37:03 +0800 Subject: [PATCH] chore: sync local changes, add Chinese docs and opencode config --- CHANGELOG.md | 19 + CODE_REVIEW_GRAPH_ZH.md | 566 ++++++++ CODE_REVIEW_GUIDE_ZH.md | 729 +++++++++++ README.md | 25 + code_review_graph/__init__.py | 2 +- code_review_graph/assets/report-template.html | 98 +- code_review_graph/changes.py | 17 +- .../docs/LLM-OPTIMIZED-REFERENCE.md | 31 +- code_review_graph/main.py | 362 ++++- code_review_graph/prompts.py | 21 +- code_review_graph/scoring.py | 1166 ++++++++++++++++- code_review_graph/skills.py | 13 +- code_review_graph/tools/__init__.py | 12 +- code_review_graph/tools/scoring_tools.py | 422 +++++- .../command/code-review-graph-build-graph.md | 39 + .../code-review-graph-project-review.md | 42 + .../command/code-review-graph-review-delta.md | 47 + .../command/code-review-graph-review-pr.md | 67 + .../code-review-graph-unified-review.md | 43 + opencode配置/command/rulegen.md | 40 + opencode配置/opencode.json | 31 + opencode配置/skill/build-graph/SKILL.md | 38 + opencode配置/skill/debug-issue/SKILL.md | 27 + opencode配置/skill/explore-codebase/SKILL.md | 28 + opencode配置/skill/project-review/SKILL.md | 273 ++++ .../references/common-mistakes.md | 19 + .../references/deep-read-pipeline.md | 168 +++ .../manual-review/data-migration.md | 12 + .../manual-review/distributed-lock.md | 11 + .../references/manual-review/inventory.md | 11 + .../references/manual-review/order.md | 12 + .../references/manual-review/payment.md | 14 + .../references/manual-review/permission.md | 11 + .../references/report-schema.md | 174 +++ .../references/report-template.html | 238 ++++ .../references/review-checklist.md | 82 ++ .../references/specialists/api-contract.md | 13 + .../references/specialists/data-migration.md | 15 + .../references/specialists/maintainability.md | 16 + .../references/specialists/performance.md | 14 + .../references/specialists/red-team.md | 18 + .../references/specialists/security.md | 17 + .../references/specialists/testing.md | 14 + .../scripts/aggregate_deep_read.py | 287 ++++ .../project-review/verify-line-coverage.ps1 | 151 +++ .../skill/project-review/verify-report.ps1 | 124 ++ .../project-review/verify-spot-check.ps1 | 152 +++ opencode配置/skill/refactor-safely/SKILL.md | 28 + opencode配置/skill/review-changes/SKILL.md | 29 + opencode配置/skill/review-delta/SKILL.md | 46 + opencode配置/skill/review-pr/SKILL.md | 66 + opencode配置/skill/unified-review/SKILL.md | 69 + .../references/common-mistakes.md | 19 + .../manual-review/data-migration.md | 12 + .../manual-review/distributed-lock.md | 11 + .../references/manual-review/inventory.md | 11 + .../references/manual-review/order.md | 12 + .../references/manual-review/payment.md | 14 + .../references/manual-review/permission.md | 11 + .../references/report-template.html | 142 ++ .../references/review-checklist.md | 82 ++ .../references/specialists/api-contract.md | 13 + .../references/specialists/data-migration.md | 15 + .../references/specialists/maintainability.md | 16 + .../references/specialists/performance.md | 14 + .../references/specialists/red-team.md | 18 + .../references/specialists/security.md | 17 + .../references/specialists/testing.md | 14 + pyproject.toml | 2 +- skills/project-review/SKILL.md | 32 +- .../references/report-template.html | 98 +- skills/unified-review/SKILL.md | 2 +- .../references/report-template.html | 98 +- tests/test_coverage.py | 421 ++++++ tests/test_line_coverage.py | 332 +++++ tests/test_main.py | 34 +- tests/test_progress_bridge.py | 223 ++++ tests/test_prompts.py | 7 +- tests/test_report.py | 135 ++ tests/test_scoring.py | 13 + uv.lock | 2 +- 81 files changed, 7645 insertions(+), 144 deletions(-) create mode 100644 CODE_REVIEW_GRAPH_ZH.md create mode 100644 CODE_REVIEW_GUIDE_ZH.md create mode 100644 opencode配置/command/code-review-graph-build-graph.md create mode 100644 opencode配置/command/code-review-graph-project-review.md create mode 100644 opencode配置/command/code-review-graph-review-delta.md create mode 100644 opencode配置/command/code-review-graph-review-pr.md create mode 100644 opencode配置/command/code-review-graph-unified-review.md create mode 100644 opencode配置/command/rulegen.md create mode 100644 opencode配置/opencode.json create mode 100644 opencode配置/skill/build-graph/SKILL.md create mode 100644 opencode配置/skill/debug-issue/SKILL.md create mode 100644 opencode配置/skill/explore-codebase/SKILL.md create mode 100644 opencode配置/skill/project-review/SKILL.md create mode 100644 opencode配置/skill/project-review/references/common-mistakes.md create mode 100644 opencode配置/skill/project-review/references/deep-read-pipeline.md create mode 100644 opencode配置/skill/project-review/references/manual-review/data-migration.md create mode 100644 opencode配置/skill/project-review/references/manual-review/distributed-lock.md create mode 100644 opencode配置/skill/project-review/references/manual-review/inventory.md create mode 100644 opencode配置/skill/project-review/references/manual-review/order.md create mode 100644 opencode配置/skill/project-review/references/manual-review/payment.md create mode 100644 opencode配置/skill/project-review/references/manual-review/permission.md create mode 100644 opencode配置/skill/project-review/references/report-schema.md create mode 100644 opencode配置/skill/project-review/references/report-template.html create mode 100644 opencode配置/skill/project-review/references/review-checklist.md create mode 100644 opencode配置/skill/project-review/references/specialists/api-contract.md create mode 100644 opencode配置/skill/project-review/references/specialists/data-migration.md create mode 100644 opencode配置/skill/project-review/references/specialists/maintainability.md create mode 100644 opencode配置/skill/project-review/references/specialists/performance.md create mode 100644 opencode配置/skill/project-review/references/specialists/red-team.md create mode 100644 opencode配置/skill/project-review/references/specialists/security.md create mode 100644 opencode配置/skill/project-review/references/specialists/testing.md create mode 100644 opencode配置/skill/project-review/scripts/aggregate_deep_read.py create mode 100644 opencode配置/skill/project-review/verify-line-coverage.ps1 create mode 100644 opencode配置/skill/project-review/verify-report.ps1 create mode 100644 opencode配置/skill/project-review/verify-spot-check.ps1 create mode 100644 opencode配置/skill/refactor-safely/SKILL.md create mode 100644 opencode配置/skill/review-changes/SKILL.md create mode 100644 opencode配置/skill/review-delta/SKILL.md create mode 100644 opencode配置/skill/review-pr/SKILL.md create mode 100644 opencode配置/skill/unified-review/SKILL.md create mode 100644 opencode配置/skill/unified-review/references/common-mistakes.md create mode 100644 opencode配置/skill/unified-review/references/manual-review/data-migration.md create mode 100644 opencode配置/skill/unified-review/references/manual-review/distributed-lock.md create mode 100644 opencode配置/skill/unified-review/references/manual-review/inventory.md create mode 100644 opencode配置/skill/unified-review/references/manual-review/order.md create mode 100644 opencode配置/skill/unified-review/references/manual-review/payment.md create mode 100644 opencode配置/skill/unified-review/references/manual-review/permission.md create mode 100644 opencode配置/skill/unified-review/references/report-template.html create mode 100644 opencode配置/skill/unified-review/references/review-checklist.md create mode 100644 opencode配置/skill/unified-review/references/specialists/api-contract.md create mode 100644 opencode配置/skill/unified-review/references/specialists/data-migration.md create mode 100644 opencode配置/skill/unified-review/references/specialists/maintainability.md create mode 100644 opencode配置/skill/unified-review/references/specialists/performance.md create mode 100644 opencode配置/skill/unified-review/references/specialists/red-team.md create mode 100644 opencode配置/skill/unified-review/references/specialists/security.md create mode 100644 opencode配置/skill/unified-review/references/specialists/testing.md create mode 100644 tests/test_coverage.py create mode 100644 tests/test_line_coverage.py create mode 100644 tests/test_progress_bridge.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f2ee048..067fe72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ ### Added +- **Coverage-driven deep-read planning** for whole-project reviews. New + `deep_read_plan_tool` greedily selects the highest-risk files needed to + close the risk-weighted coverage gap, groups them by directory so each + batch maps to one parallel sub-agent, and returns the priority file list. + `coverage_tool` now also returns `remaining_weight_to_target` and + `priority_deep_read_files` so the reviewing agent knows exactly what still + needs to be read to reach the target. +- **Configurable coverage gate.** `coverage_tool` / `compute_coverage` + gained a `gate` parameter: `high_risk` (default, G3 semantics), + `overall` (all source files), or `both` (overall **and** high-risk must + meet the target). Weight computation was factored into `_file_weights` + and is now shared by `compute_coverage` and `deep_read_plan`. +- **Cross-round incremental coverage index.** `save_coverage_index_tool` + persists the deep-read file list to `.code-review-graph/coverage-index.json` + with per-file SHAs. `coverage_tool(include_prior=True)` and + `deep_read_plan_tool(include_prior=True)` merge files whose SHA is still + current, so later review rounds only re-read files that actually changed + or are new instead of starting from zero each time. + - Added the **unified-review** skill that fuses CRG graph context with the ai-code-review three-layer scoring methodology and the gstack-review fix-first workflow. The skill is read-only: every finding waits for a diff --git a/CODE_REVIEW_GRAPH_ZH.md b/CODE_REVIEW_GRAPH_ZH.md new file mode 100644 index 0000000..122c7f8 --- /dev/null +++ b/CODE_REVIEW_GRAPH_ZH.md @@ -0,0 +1,566 @@ +# code-review-graph 功能文档 + +> **停止燃烧 token,让 AI 审查真正的代码。** +> +> code-review-graph 是一个本地优先的**代码审查引擎**:以 Tree-sitter 知识图谱为底座, +> 为 AI 编程助手提供精准的代码上下文与结构化的审查工作流——从 diff 影响面分析、 +> 客观量化评分、并行深读覆盖度门禁,到最终的双格式审查报告,全流程只读、可审计。 + +- 当前版本:v2.5.1(本地定制版) +- 语言要求:Python 3.10+ +- 运行形态:本地源码部署(venv / uv),MCP stdio 服务接入 AI 编程工具 +- 数据形态:图谱存储于仓库本地 `.code-review-graph/`(SQLite),零遥测,源码不出本机 + +--- + +## 目录 + +1. [工具概述](#1-工具概述) +2. [核心原理](#2-核心原理) +3. [代码审查工作流](#3-代码审查工作流) +4. [MCP 工具(37 个)](#4-mcp-工具37-个) +5. [MCP Prompts(7 个)](#5-mcp-prompts7-个) +6. [CLI 命令参考](#6-cli-命令参考) +7. [opencode 本机集成现状](#7-opencode-本机集成现状) +8. [配置与环境变量](#8-配置与环境变量) +9. [已知局限](#9-已知局限) + +--- + +## 1. 工具概述 + +AI 编程工具执行代码审查时,往往反复扫描大量文件造成严重 token 浪费,且缺乏统一的 +审查方法论与量化标准。code-review-graph 的解决方式是: + +- 使用 **Tree-sitter** 将仓库解析为知识图谱:节点(函数/类/导入/测试)+ 边(调用/继承/测试覆盖) +- 审查时通过图谱查询计算需要读取的**最小文件集合**(Blast-radius 分析) +- 在图谱之上提供**三套开箱即用的审查工作流**(diff 统一审查 / 全项目审查 / 单功能审查) +- 用**客观指标评分**(SQL 风险、异常分支覆盖、冗余率等)替代"凭感觉审完" +- 用**并行深读管线 + 覆盖度门禁**保证"审过了"不是由感觉决定,而是有数据支撑 +- 最终产出自包含的中文 HTML + Markdown 双格式审查报告 + +核心特性一览: + +| 特性 | 说明 | +| --- | --- | +| 本地优先 | 图谱存本机 SQLite,无需外部数据库;云端 embedding 为显式可选 | +| 增量更新 | 只重解析变更文件(SHA-256 比对),后续更新秒级完成 | +| 零遥测 | 不向任何外部服务发送源码 | +| 多语言 | 40+ 编程语言,支持自定义语言扩展 | +| 三种审查入口 | unified-review(diff)/ project-review(全项目)/ project-review(单功能) | +| 客观量化 | 5 项 Layer-2 指标 + good/warn/fail 分级,blocker 一票否决 | +| 覆盖度门禁 | 文件数口径 + 行覆盖 + 语义单元三件套,双目标(全库 ≥85% 且高风险 ≥95%) | +| 双格式报告 | 自包含中文 HTML(浏览器直开)+ Markdown(入库/PR 复用),全程只读不改代码 | + +--- + +## 2. 核心原理 + +### 2.1 架构管线 + +``` +仓库 → Tree-sitter 解析 → SQLite 图谱 → Blast-radius 分析 → 最小审查集 + ↓ + detect_changes 风险评分 → score_review 客观指标 + ↓ + deep_read 并行深读 → coverage 门禁 → dedupe 合并 + ↓ + generate_report(HTML + Markdown) +``` + +### 2.2 从代码到图谱 + +`code-review-graph build` 用 Tree-sitter 把源码解析为 AST,提取: + +- **节点**:函数、类、导入语句、测试函数等代码实体 +- **边**:调用关系、继承关系、测试覆盖关系等结构联系 + +图谱把「代码长什么样」升级为「代码之间有什么关系」,这是后续一切审查能力的底座。 +解析完成后图谱存储在仓库本地 `.code-review-graph/graph.db`。 + +### 2.3 Blast-radius(爆炸半径)分析 + +文件发生变更时,图谱追踪所有可能受影响的调用方、依赖方与测试: + +- 变更波及面(谁调用了它、谁依赖它、哪些测试覆盖它) +- AI 只读取受影响文件而非扫描整个项目,token 消耗显著下降 + +### 2.4 增量更新 + +每次保存文件或 git commit 时计算变更文件的 SHA-256 哈希,只重新解析变化的文件, +再按图谱关系局部更新相关节点。配合 watch 模式 / 平台 hooks / crg-daemon 守护进程, +图谱始终贴近当前代码状态,不需要"用一次就过期"的全量重建。 + +--- + +## 3. 代码审查工作流 + +### 3.1 三种审查入口对比 + +| 维度 | unified-review(diff 审查) | project-review(全项目) | project-review(单功能) | +| --- | --- | --- | --- | +| **审查对象** | git diff(默认 `HEAD~1..HEAD`) | 图谱内全部源文件 | 目标功能/模块相关文件 + 影响面 | +| **触发指令** | "审查"、"检查代码"、"review" | "对项目代码进行全面审查"、"全面审查"、"整个项目" | "审查支付功能的代码"、"审查 auth 模块" | +| **入口** | `/code-review-graph-unified-review` | `/code-review-graph-project-review` | `/code-review-graph-project-review` | +| **核心工具** | `detect_changes` + `score_review` | `score_review(all_files=True)` + 深读管线 | `semantic_search` + `get_impact_radius` + `score_review` | +| **典型场景** | 合并前检查本次改动 | 代码质量体检、架构审计、发布前全面体检 | 上线前审查某个功能 | + +三者共享同一套评分/去重/报告工具,流程结构一致: +**图谱上下文 → 客观评分 → 链路分解 → 去重 → 人工裁决 → 报告**,区别仅在范围获取方式。 + +### 3.2 unified-review:三层统一审查(diff) + +``` +触发 → 范围/档位判定 → [图谱上下文] → Layer 1 八分类 + CRITICAL 检查 → [score_review 量化] +→ [specialist 并行派发] → [dedupe 合并去重] → 人工裁决(只读)→ 验收门禁 → [HTML + Markdown 报告] → 持久化 +``` + +| 步骤 | 内容 | +| --- | --- | +| Step 0 范围/档位 | 读 `.code-review.yaml` 确定 tier(fast / standard / strict);检测语言/框架加载对应 checklist;判定 change/file/service/chain 级范围 | +| Step 1 图谱上下文 | `build_or_update_graph` → `get_review_context`(blast radius + 源码片段)→ `detect_changes`(风险分 + 测试缺口 + 受影响流) | +| Step 2 Layer 1 链路分解 | 八分类逐类检查(接口/业务/数据/工具/错误处理/安全/性能/可观测性),叠加 CRITICAL 五类(SQL 数据安全、竞态并发、LLM 信任边界、Shell 注入、枚举完整性) | +| Step 3 Layer 2 量化评分 | `score_review_tool` 计算 5 项客观指标;需求覆盖/逻辑对齐等由 LLM 判断(`llm_judged` 标注,无需求文档时 0.5× 降权) | +| Step 4 specialist 派发 | diff ≥ 50 行时并行派发 testing/maintainability/security/performance/data-migration/api-contract 子代理;security 与 data-migration 为保险型永不 gate | +| Step 5 合并去重 | `dedupe_findings_tool` 按 `path:line:category` 指纹合并、多源确认置信 +1、计算 PR 质量分、抑制历史已跳过项 | +| Step 6 人工裁决 | **只读**。每条 finding 带 severity + 置信度 + file:line + 修复建议,按 severity 批量呈现;blocker 不可批量跳过 | +| Step 7 验收门禁 | 任一 🔴 blocker → verdict `❌ FAIL`;分类 Ready / Needs Fix / Unusable | +| Step 8 报告 | `generate_report_tool`(默认 `format="both"`)产出中文报告 | +| Step 9 持久化 | 记录审查结果供后续去重抑制,不可用时静默跳过 | + +### 3.3 project-review:全项目深读管线 + +全项目审查的关键难题是**覆盖度不能靠感觉**。主上下文无法逐文件深读数百个文件, +必须走并行子代理深读流水线: + +``` +a. deep_read_plan_tool(target_coverage=85) + → 按风险权重贪心选出待深读文件并分组 +b. 按组并行派发 explore 子代理,每个子代理完整深读该组全部文件, + 逐文件返回 read_ranges / semantic_units / findings[](每条 finding 必须带 file:line 证据) +c. 三件套质量门禁(coverage_tool gate="both+line"): + ① 单元完整性:semantic_units 与图谱单元一一对应 + ② 行覆盖:union(read_ranges) / 真实行数 ≥ 95% + ③ 防伪抽验:主代理抽样回读比对,防子代理假读 +d. line_gap ∪ unit_gap 非空 → 补轮重读直至清空,禁止静默降级 +e. 未达标 → 按 priority_deep_read_files 补一轮,循环至达标 +f. 报告生成后 save_coverage_index_tool 写跨轮覆盖索引(file + SHA + ranges), + 下轮审查 include_prior=True 自动复用未变更文件,实现增量累积 +``` + +**覆盖度双口径门禁**: + +- 全库覆盖 = 已深读文件数 / 全部源文件数(目标 ≥85%) +- 高风险覆盖 = 已深读高风险文件数 / 信号点名文件数(目标 ≥95%) +- `target_reached=false` → 报告顶部标 🔴 覆盖不足;覆盖率结果完整透传进报告 `## 覆盖度` 区块 + +其余步骤(架构全景 → 高风险定位 → `score_review(all_files=True)` → 八分类 + CRITICAL → +dedupe → 人工裁决 → 报告)与 unified-review 同构。 + +单功能(feature)流程则先用 `semantic_search_nodes(query=target)` 定位代码, +再 `query_graph(children_of)` 聚合文件、`get_impact_radius` 扩影响面, +之后聚焦这些文件走同一套评分与裁决流程。 + +### 3.4 报告成果物 + +每次审查默认产出两份中文报告(`generate_report_tool format="both"`): + +- **`code-review-report.html`** — 自包含单文件(内联样式、零外部依赖),浏览器直接打开。 + 含结论(PASS/FAIL)、PR 质量分、客观指标表、问题清单(severity + 置信度 + 位置 + 修复建议)、 + 覆盖度区块、人工审查清单 +- **`code-review-report.md`** — Markdown 版,便于 git 提交、PR 描述、内部文档复用 + +`format="html"` / `format="markdown"` 可单独产出;`output_path` 指定输出基础路径 +(推荐归档到 `docs/reviews/{name}-review-{YYYY-MM-DD-HHMMSS}`,避免同名覆盖且便于追溯)。 + +**报告均为只读产物**:审查本身不修改任何代码,所有修复决定由人工确认后执行。 + +--- + +## 4. MCP 工具(37 个) + +图谱构建完成后,AI 助手通过 MCP 自动使用以下工具(共 37 个,按类分组)。 + +### 4.1 图谱核心与上下文(12) + +| 工具 | 描述 | +| --- | --- | +| `build_or_update_graph_tool` | 构建或增量更新图谱 | +| `run_postprocess_tool` | 重跑流检测、社区检测与 FTS 索引 | +| `get_minimal_context_tool` | 超紧凑上下文(~100 token),任何任务的第一个调用 | +| `get_impact_radius_tool` | 变更文件的爆炸半径分析 | +| `get_review_context_tool` | token 优化的审查上下文 + 结构摘要 + 源码片段 | +| `detect_changes_tool` | **风险评分的变更影响分析**:diff 映射到受影响函数/流/测试缺口,产出风险分与优先审查建议 | +| `query_graph_tool` | 关系模式查询:callers_of / callees_of / imports_of / tests_for / inheritors_of 等 | +| `traverse_graph_tool` | 从任意节点 BFS/DFS 探索,带深度与 token 预算 | +| `semantic_search_nodes_tool` | 向量语义搜索代码实体(需先 embed),无向量时回退 FTS 关键词匹配 | +| `embed_graph_tool` | 为全部图节点计算向量 embedding(local/openai/google/minimax/voyage) | +| `list_graph_stats_tool` | 图谱规模与健康状况统计 | +| `find_large_functions_tool` | 查找超过行数阈值的函数/类/文件(巨型文件审计) | + +### 4.2 执行流与社区架构(11) + +| 工具 | 描述 | +| --- | --- | +| `list_flows_tool` | 按关键度排序列出执行流(从入口点追踪的调用链) | +| `get_flow_tool` | 查看单个执行流的完整调用路径 | +| `get_affected_flows_tool` | 查找受变更文件影响的用户级执行路径 | +| `list_communities_tool` | 列出 Leiden 算法聚类出的代码社区 | +| `get_community_tool` | 查看单个社区详情(规模/内聚度/成员) | +| `get_architecture_overview_tool` | 从社区结构生成架构总览与耦合警告 | +| `get_hub_nodes_tool` | 找出连接最多的节点(架构热点,改动爆炸半径大) | +| `get_bridge_nodes_tool` | 通过介数中心性找出架构瓶颈(桥接节点) | +| `get_knowledge_gaps_tool` | 识别孤立节点、未测试热点、薄弱社区等结构弱点 | +| `get_surprising_connections_tool` | 检测意外耦合:跨社区/跨语言/外围到 Hub 的边 | +| `get_suggested_questions_tool` | 从图谱分析自动生成审查问题(桥/hub/惊喜耦合驱动) | + +### 4.3 审查分析与报告(8) + +| 工具 | 描述 | +| --- | --- | +| `score_review_tool` | **客观 Layer-2 指标**:SQL 风险、异常分支覆盖、冗余率、高风险密度、漏洞启发式五项,带 good/warn/fail 分级与证据;支持 `all_files=True` 全量评分;`llm_judged` 字段列出需 LLM 补判项 | +| `dedupe_findings_tool` | **Finding 合并去重**:按 `path:line:category` 指纹合并、多源置信 +1(上限 10)、低置信移附录、抑制历史已跳过项、计算 PR 质量分 `max(0, 10 - (critical×2 + informational×0.5))` | +| `generate_report_tool` | **报告生成**:渲染为自包含中文 HTML 与 Markdown(默认双格式),自动渲染结论/指标表/问题清单/覆盖度区块 | +| `refactor_tool` | 重命名预览、框架感知死代码检测、社区驱动重构建议 | +| `apply_refactor_tool` | 应用此前预览过的重构(精确字符串替换) | +| `generate_wiki_tool` | 从社区结构生成 markdown wiki(`.code-review-graph/wiki/`) | +| `get_wiki_page_tool` | 获取特定 wiki 页面 | +| `get_docs_section_tool` | 获取内置 LLM 优化文档的指定章节(usage/review-pr/troubleshooting 等) | + +### 4.4 深读管线、覆盖度与多仓(6) + +| 工具 | 描述 | +| --- | --- | +| `deep_read_plan_tool` | 生成按风险权重贪心分组的深读计划(groups + planned_files + estimated_batches),支持增量排除上轮已读文件 | +| `coverage_tool` | **覆盖度三件套门禁**:文件数口径 + 行覆盖 + 语义单元覆盖三重计算;`gate="both+line"` 时四项 AND 判定;返回缺口文件与补读优先级队列;`include_prior=True` 合并跨轮索引实现增量 | +| `save_coverage_index_tool` | 持久化深读名单到 `.code-review-graph/coverage-index.json`(file + per-file SHA + ranges),供下轮审查增量复用 | +| `community_health_tool` | 检查 nodes.community_id 归属健康度,归属率 <90% 时提示先 postprocess 再算覆盖度,防止失真 | +| `list_repos_tool` | 列出多仓注册表中已注册仓库 | +| `cross_repo_search_tool` | 跨所有已注册仓库搜索代码实体,按仓内 rank 交错返回 | + +--- + +## 5. MCP Prompts(7 个) + +MCP 协议层的 7 个预构建工作流模板,支持 MCP prompts 的客户端将其呈现为 "/" 可调用命令。 +全部强制 token 效率模式:先调 `get_minimal_context`,默认 `detail_level="minimal"`。 + +| "/" 可调用命令 | 功能 | 参数 | +| --- | --- | --- | +| `/review_changes` | 提交前审查:`detect_changes` + 受影响执行流 + 测试缺口 | `base="HEAD~1"` | +| `/architecture_map` | 架构文档:社区、执行流、Mermaid 图 + 耦合警告 | 无 | +| `/debug_issue` | 引导式调试:语义搜索 + 调用链追踪 + 执行流定位根因 | `description=""` | +| `/onboard_developer` | 新成员入职指南:统计、架构、关键执行流 | 无 | +| `/pre_merge_check` | 合并前就绪检查:风险评分、测试缺口、死代码 | `base="HEAD~1"` | +| `/unified_review` | 三层统一审查(只读):图谱上下文 → 客观评分 → 人工裁决 → 去重 → 双格式报告。任何 blocker 判 FAIL | `base="HEAD~1"`、`tier="standard"`(fast/standard/strict) | +| `/project_review` | 项目级审查(非 diff):全项目或单功能,由用户自然语言指令决定范围,只读 | `scope="whole-project"`、`target=""` | + +--- + +## 6. CLI 命令参考 + +### 6.1 安装与部署 + +```bash +code-review-graph install # 自动检测并配置所有支持的 AI 平台(MCP/hooks/skills/规则注入) +code-review-graph install --platform # 仅配置单个平台 +code-review-graph install --dry-run # 预览动作不写入 +code-review-graph init # install 别名 +code-review-graph uninstall --dry-run # 对称卸载预览(只移除本工具拥有的组件) +code-review-graph uninstall --keep-data # 移除集成但保留图谱数据库 +code-review-graph uninstall --all-repos # 同时清理所有已注册仓库 +``` + +支持平台:Codex、Claude Code、CodeBuddy Code、Cursor、Windsurf、Zed、Continue、 +OpenCode、Antigravity、Gemini CLI、Qwen、Qoder、Kiro、GitHub Copilot(含 CLI)。 + +### 6.2 图谱构建与维护 + +```bash +code-review-graph build # 全量解析整个代码库 +code-review-graph build --skip-flows # 跳过流检测 +code-review-graph build --skip-postprocess # 跳过后处理(流/社区/FTS) +code-review-graph update # 增量更新(仅变更文件) +code-review-graph update --base # 指定 git diff 基线 +code-review-graph update --brief # 刷新后打印 Token Savings 面板 +code-review-graph update --verify # 用 tiktoken 交叉校验 token 估算 +code-review-graph postprocess # 重跑后处理 +code-review-graph postprocess --no-flows # 跳过流检测 +code-review-graph postprocess --no-communities# 跳过社区检测 +code-review-graph postprocess --no-fts # 跳过 FTS 重建 +code-review-graph watch # 监听文件变更自动增量更新 +code-review-graph status [--json] # 图谱统计 +code-review-graph forget [--dry-run] # 从图谱移除已解析文件(免全量重建) +code-review-graph embed --provider local # 计算 embedding(--model all-MiniLM-L6-v2) +``` + +通用参数:绝大多数命令支持 `--repo ` 显式指定仓库根(默认自动探测); +`--data-dir` 可覆盖图谱数据目录。 + +### 6.3 分析与审查 + +```bash +code-review-graph detect-changes --brief # 风险面板 + token 节省估算(只读) +code-review-graph detect-changes --base # 指定 diff 基线(默认 HEAD~1) +code-review-graph detect-changes --churn # 风险评分加入变更频率因子 +code-review-graph impact --files ... # 变更爆炸半径(--depth/--max-results/--base) +code-review-graph query # 图谱关系查询(callers_of/callees_of/imports_of 等) +code-review-graph search [--kind] # FTS/语义混合搜索图谱实体 +code-review-graph dead-code [--kind] [--file-pattern] [--json] # 死代码检测 +code-review-graph large-functions --min-lines 150 [--path] [--kind] # 巨型函数/文件审计 +code-review-graph refactor rename --old-name X --new-name Y # 重命名预览 +code-review-graph refactor dead_code|suggest # 死代码/重构建议 +``` + +### 6.4 结构浏览 + +```bash +code-review-graph flows [--limit 50] [--kind] [--sort] # 执行流列表 +code-review-graph flow --id 3 [--source] # 单个执行流详情(可含源码片段) +code-review-graph communities [--min-size] [--sort] # 社区列表 +code-review-graph community --id 71 [--members] # 单个社区详情 +code-review-graph architecture [--detail-level minimal|standard] # 架构总览 +code-review-graph visualize [--format json|graphml|svg|obsidian|cypher] [--serve] +code-review-graph wiki [--force] # 从社区生成 markdown wiki +``` + +### 6.5 多仓与服务 + +```bash +code-review-graph register [--alias] # 注册仓库到多仓注册表 +code-review-graph unregister # 移除注册 +code-review-graph repos # 列出已注册仓库 +code-review-graph eval [--benchmark ...] [--all] [--report] # 评估基准 + +code-review-graph serve # 启动 MCP stdio 服务 +code-review-graph serve --repo # 指定仓库根 +code-review-graph serve --http --host 127.0.0.1 --port 5555 # Streamable HTTP 模式 +code-review-graph serve --tools t1,t2 # 仅暴露部分 MCP 工具(token 受限环境) +code-review-graph serve --auto-watch # 服务期间自动增量更新 +code-review-graph mcp # serve 别名 +``` + +### 6.6 多仓守护进程(crg-daemon) + +编辑器不支持 hooks 或希望后台保持多仓图谱新鲜时使用,随主程序一并安装: + +```bash +crg-daemon add ~/project-a --alias proj-a # 注册监听(写 ~/.code-review-graph/watch.toml) +crg-daemon start # 后台启动,每 30s 健康检查并重启死掉的 watcher +crg-daemon status # 查看守护进程与各仓库 watcher 状态 +crg-daemon logs --repo proj-a --follow # 追踪某仓库日志 +crg-daemon stop # 停止守护进程与全部 watcher +``` + +也支持 `code-review-graph daemon start|stop|restart|status|logs|add|remove`。 + +--- + +## 7. opencode 本机集成现状 + +本机采用**源码部署**方式:工具代码位于 `D:\code-review-graph\code-review-graph-main`, +venv 内的可执行文件被 MCP 配置以绝对路径引用。 + +### 7.1 MCP 配置(两处) + +```json +// D:\AuraSpace\.mcp.json(项目级) +{ + "mcpServers": { + "code-review-graph": { + "command": "D:\\code-review-graph\\code-review-graph-main\\.venv\\Scripts\\code-review-graph.exe", + "args": ["serve", "--repo", "D:\\AuraSpace"], + "cwd": "D:\\AuraSpace", + "type": "stdio" + } + } +} +``` + +```json +// %USERPROFILE%\.config\opencode\opencode.json(全局级,节选) +{ + "mcp": { + "code-review-graph": { + "type": "local", + "command": [ + "D:\\code-review-graph\\code-review-graph-main\\.venv\\Scripts\\code-review-graph.exe", + "serve", "--repo", "D:\\AuraSpace" + ], + "timeout": 600000, + "env": { "CRG_REPO_ROOT": "D:\\AuraSpace" } + } + } +} +``` + +### 7.2 已安装的 skills(`%USERPROFILE%\.config\opencode\skills\`,9 个) + +| Skill | 功能 | +| --- | --- | +| `build-graph` | 构建/重建代码图谱 | +| `explore-codebase` | 图谱结构探索导航 | +| `debug-issue` | 图谱引导式调试 | +| `refactor-safely` | 依赖分析驱动的安全重构 | +| `review-changes` | 变更审查(change detection + impact) | +| `review-delta` | 自上次提交以来的增量审查 | +| `review-pr` | PR/分支完整审查 | +| `unified-review` | 三层统一审查:CRG 图谱上下文 + ai-code-review 评分方法论 + gstack-review 流程 | +| `project-review` | 项目级审查(全项目/单功能):并行深读管线 + 三件套覆盖度门禁 + 双格式报告 | + +其中 `project-review` 附带 PowerShell 校验脚本(verify-report / verify-line-coverage / +verify-spot-check.ps1)与 Python 聚合脚本(aggregate_deep_read.py), +skill 文档内引用了绝对路径,迁移机器时需同步修改。 + +### 7.3 已安装的斜杠命令(`command\`,5 个) + +| 命令 | 功能 | +| --- | --- | +| `/code-review-graph-build-graph` | 构建/更新图谱 | +| `/code-review-graph-unified-review` | diff 三层统一审查(只读) | +| `/code-review-graph-project-review` | 项目级审查:全项目或单功能(只读) | +| `/code-review-graph-review-pr` | PR/branch diff 审查 | +| `/code-review-graph-review-delta` | 自上次提交以来的变更审查 | + +### 7.4 本地部署步骤(新机器/重建环境) + +```powershell +# 前置:Python 3.10+ 与 uv +cd D:\code-review-graph\code-review-graph-main +uv sync # 按 uv.lock 重建 .venv(国内网络先设 UV_INDEX_URL 镜像) +.\.venv\Scripts\code-review-graph.exe --version # 应输出 2.5.x +``` + +**配置 opencode.json(全局 MCP 注册)** + +文件位于 `%USERPROFILE%\.config\opencode\opencode.json`,将 code-review-graph 段加入 `mcp` 对象 +(若已有 `plugin`、`playwright` 等其他配置项则保留不动): + +```json +"code-review-graph": { + "type": "local", + "command": [ + "D:\\code-review-graph\\code-review-graph-main\\.venv\\Scripts\\code-review-graph.exe", + "serve", "--repo", "D:\\AuraSpace" + ], + "timeout": 600000, + "env": { "CRG_REPO_ROOT": "D:\\AuraSpace" } +} +``` + +按新机器实际修改 3 处:`command[0]` 的 exe 绝对路径、`--repo` 的仓库根、`env.CRG_REPO_ROOT`。 +项目级 `.mcp.json`(可选)参考 §7.1。 + +然后核对 §7.1 的 `.mcp.json` 与本节 opencode.json 中的绝对路径与新机一致, +复制 7.2/7.3 的 skills 与 commands,重启 opencode 即生效。 + +> **使用前提**:先构建图谱(首次 `code-review-graph build` 或 `/code-review-graph-build-graph`), +> 否则图谱工具返回 `not_ready`。 + +--- + +## 8. 配置与环境变量 + +### 8.1 排除路径(`.code-review-graphignore`) + +在仓库根目录创建 `.code-review-graphignore` 排除已跟踪文件的索引: + +``` +generated/** +*.generated.ts +vendor/** +node_modules/** +``` + +> git 仓库中默认只索引被跟踪文件(`git ls-files`),gitignore 文件自动跳过。 +> `.code-review-graphignore` 用于排除已跟踪文件或 git 不可用的场景。 + +### 8.2 可选依赖组 + +```bash +pip install "code-review-graph[embeddings]" # 本地向量 embedding(sentence-transformers) +pip install "code-review-graph[google-embeddings]" # Google Gemini embeddings +pip install "code-review-graph[communities]" # 社区检测(igraph) +pip install "code-review-graph[enrichment]" # Python 调用解析富化(Jedi) +pip install "code-review-graph[eval]" # 评估基准 +pip install "code-review-graph[wiki]" # Wiki 生成 + LLM 摘要(ollama) +pip install "code-review-graph[all]" # 全部可选依赖 +``` + +源码部署时对应 `uv sync --extra ` 或在 venv 内 `pip install -e .[]`。 + +### 8.3 环境变量 + +| 变量 | 描述 | 默认 | +| --- | --- | --- | +| `CRG_REPO_ROOT` | 显式指定仓库根(opencode 全局配置中使用) | - | +| `CRG_DATA_DIR` | 覆盖图谱数据库与生成产物的目录 | - | +| `CRG_GIT_TIMEOUT` | Git 操作超时(秒) | `30` | +| `CRG_TOOLS` | serve 时暴露的 MCP 工具允许列表(逗号分隔) | - | +| `CRG_TOOL_TIMEOUT` | 有界 MCP 工具的可选超时(秒,`0` 禁用) | `0` | +| `CRG_MAX_IMPACT_NODES` | 影响分析中最多包含的节点数 | `500` | +| `CRG_MAX_IMPACT_DEPTH` | 爆炸半径分析搜索深度 | `2` | +| `CRG_MAX_BFS_DEPTH` | 图谱遍历最大深度 | `15` | +| `CRG_MAX_SEARCH_RESULTS` | 搜索结果数上限 | `20` | +| `CRG_MAX_CHANGED_FUNCS` | 单次变更报告分析的最大变更函数数 | `500` | +| `CRG_MAX_TRANSITIVE_FRONTIER` | 传递调用方/被调用方展开的最大前沿大小 | `50` | +| `CRG_RECURSE_SUBMODULES` | 设为 `1`/`true`/`yes` 时包含 git 子模块文件 | - | +| `CRG_SERIAL_PARSE` | 设为 `1` 禁用并行解析(调试用) | - | +| `NO_COLOR` | 设置后禁用终端 ANSI 颜色 | - | + +**Embedding 相关**(可选功能,全部默认关闭): + +| 变量 | 描述 | 默认 | +| --- | --- | --- | +| `CRG_EMBEDDING_MODEL` | 本地 embedding 默认模型 | `all-MiniLM-L6-v2` | +| `GOOGLE_API_KEY` | Google Gemini embedding 的 API key | - | +| `MINIMAX_API_KEY` | MiniMax embedding 的 API key | - | +| `VOYAGE_API_KEY` / `CRG_VOYAGE_*` | Voyage embedding 密钥与模型/维度/批大小等参数 | `voyage-code-3` | +| `CRG_OPENAI_BASE_URL` / `CRG_OPENAI_API_KEY` / `CRG_OPENAI_MODEL` | OpenAI 兼容端点(真实 OpenAI、Azure、new-api、LiteLLM、vLLM、LocalAI 等) | - | +| `CRG_ACCEPT_CLOUD_EMBEDDINGS` | 显式确认后抑制云端 embedding 出口警告 | - | +| `CRG_ALLOW_REMOTE_CODE` | 允许需要 `trust_remote_code=True` 的 HuggingFace 模型 | `0` | + +隐私说明:embedding 只处理标识符、签名、结构上下文与首段 docstring 摘要, +**不传输函数体**;例行构建默认不刷新 embedding,刷新需显式传 provider + model。 + +### 8.4 语言覆盖 + +解析器覆盖函数、类、导入、调用点、继承与测试检测: + +- **Web**:JavaScript / TypeScript / TSX、PHP、Ruby、Vue/Svelte SFC、Astro、Blade +- **后端**:Python、Go、Java、C/C++、C#、VB.NET、Kotlin、Scala、Elixir、R +- **系统**:Rust、Zig、Objective-C、Nix、Shell、Verilog/SystemVerilog、SQL +- **移动**:Swift、Kotlin、Objective-C +- **脚本**:Perl / Perl XS、Lua/Luau、PowerShell、Julia、ReScript、GDScript +- **配置/结构**:Terraform/OpenTofu(`.tf`)、Ansible playbook/role/task、Solidity、Dart +- **笔记本**:Jupyter / Databricks(`.ipynb`) + +> 通用 YAML 不视为源码。PHP 项目额外获得 Composer PSR-4 解析、Blade 引用与 +> Laravel Route/Eloquent 语义边(基于证据门控)。 + +### 8.5 自定义语言(无需改代码) + +在仓库 `.code-review-graph/languages.toml` 将扩展名映射到 `tree_sitter_language_pack` +中任意已捆绑语法,并声明函数/类/导入/调用的 tree-sitter 节点类型: + +```toml +[languages.erlang] +extensions = [".erl"] +grammar = "erlang" +function_node_types = ["function_clause"] +class_node_types = ["record_decl"] +import_node_types = ["import_attribute"] +call_node_types = ["call"] +``` + +通用 tree-sitter 遍历器即可完成提取;内置语言永远不会被覆盖。 +详见本仓库 `docs/CUSTOM_LANGUAGES.md`。 + +- **如何验证工具正常工作?** `code-review-graph status`、`detect-changes --brief`, + 或在 MCP 客户端中查看 code-review-graph 服务是否列出工具。 +- **图谱何时需要重建?** 日常由 watch/hooks/crg-daemon 自动增量维护;仅在切换分支大范围 + 变更、怀疑图谱过期或升级版本后建议全量 `build`。 +- **审查会修改我的代码吗?** 不会。三种审查工作流全程只读,报告落盘于 + `docs/reviews/`(或指定的 `output_path`),修复决定始终由人工执行。 +- **MCP 报 not_ready?** 该仓库尚未构建图谱,先运行一次 `build`。 + diff --git a/CODE_REVIEW_GUIDE_ZH.md b/CODE_REVIEW_GUIDE_ZH.md new file mode 100644 index 0000000..c6c43b3 --- /dev/null +++ b/CODE_REVIEW_GUIDE_ZH.md @@ -0,0 +1,729 @@ +# 代码审查功能文档 + +> 代码审查能力由**两个独立工作流**组成:`unified-review`(diff 审查)与 `project-review`(项目级审查)。本文聚焦**审查工作流**的操作细节(流程、覆盖度机制、客观指标、报告产物、实操踩坑)。 +> +> 📖 **文档分工**: +> - **本文**(`CODE_REVIEW_GUIDE_ZH.md`)— 审查流程 / 指标解读 / 覆盖度机制 / 报告产物 / 踩坑记录 +> - **工具总览**(`CODE_REVIEW_GRAPH_ZH.md`)— 工具定位、MCP 工具清单、CLI 命令、配置与部署、opencode 集成现状 + +--- + +## 目录 + +1. [两种审查工作流](#1-两种审查工作流) +2. [unified-review:diff 代码审查](#2-unified-reviewdiff-代码审查) +3. [project-review:项目级代码审查](#3-project-review项目级代码审查) +4. [并行深读流水线](#36-并行深读流水线whole-project-强制) +5. [审查调用的 MCP 工具](#4-审查调用的-mcp-工具) +6. [5 项客观指标详解](#5-5-项客观指标详解) +7. [审查 Skill 体系](#6-审查-skill-体系) +8. [审查报告成果物](#7-审查报告成果物) +9. [快速上手](#8-快速上手) + +--- + +## 1. 两种审查工作流 + +| 维度 | unified-review | project-review | +| --- | --- | --- | +| **审查对象** | git diff(默认 `HEAD~1..HEAD`)| 全部源文件 / 单个功能 | +| **范围来源** | 自动检测 git diff | 由用户自然语言指令决定 | +| **opencode 命令** | `/code-review-graph-unified-review` | `/code-review-graph-project-review` | +| **MCP prompt** | `/code-review-graph:unified_review` | `/code-review-graph:project_review` | + +**共同特性**: +- **只读**:不修改代码,所有修复由人工裁决 +- **客观评分**:统一走 `score_review_tool` 的 5 项量化指标 +- **去重合并**:统一走 `dedupe_findings_tool` +- **双格式报告**:默认产出中文 HTML + Markdown +- **验收门禁**:任一 🔴 blocker → 判定 `❌ FAIL` + +--- + +## 2. unified-review:diff 代码审查 + +### 2.1 执行流程 + +| 步骤 | 做了什么 | 起到什么功能 | +| --- | --- | --- | +| **Step 0 范围** | 固定 `standard` 档位(全层审查);检测语言/框架;判定 change/file/service/chain 级范围 | 决定审查深度与范围粒度,避免对简单改动做全量审查,对高风险模块自动升级审查强度 | +| **Step 1 图谱上下文** | `build_or_update_graph` 确保图谱最新;`get_review_context` 拿 blast radius + 源码片段;`detect_changes` 拿风险分、测试缺口、受影响流 | 让 AI 只读变更波及的最小文件集,建立"改了什么、影响了谁"的全貌,token 高效 | +| **Step 2 Layer 1 链路分解** | 八分类检查(接口/业务/数据/工具/错误处理/安全/性能/可观测性)+ gstack CRITICAL 五类(SQL 数据安全、竞态并发、LLM 信任边界、Shell 注入、枚举完整性) | 逐类排查 AI 易漏的高风险缺陷(注入、竞态、信任边界、枚举遗漏),建立分类清单 | +| **Step 3 Layer 2 量化评分** | `score_review_tool` 计算 5 项客观指标(SQL 风险/异常分支/冗余率/高风险密度/漏洞启发式);需求覆盖、逻辑对齐等由 LLM 判断(`llm_judged` 标注) | 用数据支撑评分而非主观判断:指标带 good/warn/fail 分级与证据,明确哪些需 LLM 补判 | +| **Step 4 specialist 派发** | diff ≥ 50 行时并行派发 testing/maintainability/security/performance/data-migration/api-contract 子代理,各自独立审查 | 用"多个专注专家并行独立审查"覆盖单一视角盲区,多专家确认的 finding 置信度更高 | +| **Step 5 合并去重** | `dedupe_findings_tool` 按 `path:line:category` 指纹合并、多源确认置信 +1、低置信抑制、计算 PR 质量分 | 把主审查 + 各 specialist 的 findings 合并成唯一清单,去除重复噪音,量化整体质量 | +| **Step 6 人工裁决** | **只读**。每条 finding 带 severity + 置信度 + file:line + 修复建议,按 severity 批量呈现,逐个决定修/不修 | 把关决策权交给人工,防止 AI 擅自改码;blocker 不可批量跳过,确保高风险项被确认 | +| **Step 7 验收门禁** | 任一 🔴 blocker → verdict `❌ FAIL`;分类 Ready / Needs Fix / Unusable | 给出明确的合并/上线结论,任何阻塞项都阻止通过,避免带病合并 | +| **Step 8 报告** | `generate_report_tool`(`format="both"`)产出中文 HTML + Markdown 报告 | 生成可分发、可存档的审查成果物,供 PR 描述、文档、评审留痕 | +| **Step 9 持久化** | 若 `gstack-review-log` 可用则记录审查结果,否则静默跳过 | 供跨次审查去重抑制与 /ship 识别,形成审查历史 | + +### 2.2 档位 + +审查默认运行在 `standard` 档位(全层审查:Layer 1 链路分解 + Layer 2 客观评分 + 报告)。`tier` 参数支持 `fast` / `standard` / `strict` 三档,其中 `fast` / `strict` 由 `.code-review.yaml` 配置或 MCP prompt 调用时指定;`/code-review-graph-unified-review` 命令固定 `standard`。覆盖度目标固定为双目标:全库 ≥85% **且** 高风险 ≥95%(project-review 三件套口径见 §3.5.4)。 + +--- + +## 3. project-review:项目级代码审查 + +### 3.1 范围解析(Step 0) + +| 用户指令 | 解析结果 | +| --- | --- | +| "对项目代码进行全面审查" / "全面审查" / "整个项目" | `scope="whole-project"` | +| "对支付功能的代码进行审查" / "审查 auth 模块" | `scope="feature"`, `target=<关键词>` | + +### 3.2 全项目流程(whole-project) + +| 步骤 | 做了什么 | 起到什么功能 | +| --- | --- | --- | +| **Step 0 范围解析** | 从用户指令解析出 `scope="whole-project"` | 明确本次审查是整个项目而非 diff/单功能 | +| **Step 1 图谱就绪 + 最小上下文** | `build_or_update_graph_tool()` 确保图谱最新;`get_minimal_context_tool(task="project review")` 拿节点/边/社区/风险概览 | 保证后续查询基于最新代码结构;最小上下文把全库概览压缩为几百 token,避免主上下文被 500+ 文件淹没 | +| **Step 2 架构全景** | `get_architecture_overview` + `list_communities`(模块地图) | 先建立全局模块结构认知,为后续定位高风险区域提供上下文 | +| **Step 3 高风险定位** | `get_knowledge_gaps`(未测试热点/孤立节点)+ `get_hub_nodes`(热点)+ `get_bridge_nodes`(瓶颈)+ `find_large_functions`(超大函数)+ `get_surprising_connections`(异常耦合) | 图论分析(节点度、介数中心性、社区划分、测试覆盖边),不读代码内容——它能告诉你"这个函数被 20 处调用,改动影响大",但说不出代码写得如何。 | +| **Step 4 全量客观评分** | `score_review_tool(all_files=True)` 评分全部源文件;`community_health_tool()` 前置检查图谱健康 | 对每个源文件跑 5 项客观指标,文本质量扫描(_iter_source_lines 读文件逐行匹配正则),不关心调用关系——它能告诉你"这个文件异常处理薄弱",但看不出它是架构瓶颈。社区归属率 <90% 需先 `postprocess` 重建,否则覆盖度失真。 | +| **Step 5 并行深读流水线** | `deep_read_plan_tool(target_coverage=85, include_prior=True)` 生成风险加权分组 → 每次并行派发 4-6 个 explore 子代理分组深读(每组 ≤40 文件)→ 子代理返回 `deep_read_files` + findings(每条必须带 file:line 证据)→ `coverage_tool(deep_read_files=<全清单>, gate="both", include_prior=True)` 复算 | 主上下文不逐文件读 500+ 文件,改为子代理流水线分摊。**这是 whole-project 覆盖达标的唯一可行路径**。深读计划按风险权重贪心,85% 全库计划先选满全部高风险文件,天然逼近高风险 95%。详见 §3.6 | +| **Step 6 覆盖度门禁与补轮** | 双目标未达标(全库 <85% 或 高风险 <95%)→ 按 `coverage_tool` 返回的 `priority_deep_read_files` 补派 1-3 个子代理;`silent_files` 随机抽 15% 深读(G2),发现 ≥1 major 则升级全量 | 可量化兜底"该读的都读了",防止审查深度由感觉决定 | +| **Step 7 合并去重** | `dedupe_findings_tool` 合并去重 + PR 质量分 | 统一 findings 清单,量化整体质量 | +| **Step 8 人工裁决 + 门禁** | 只读裁决;任一 🔴 blocker → `❌ FAIL` | 人工把关 + 明确的审查结论 | +| **Step 9 报告 + 自检** | `generate_report_tool(review_data=..., output_path="docs/reviews/...")` 产出 HTML + Markdown;Step 9.5 打开生成的 md 自检(问题清单数、三要素、客观指标表);Step 9.6 跑 `verify-report.ps1` 命名自检 | 全项目体检报告,可分发存档;自检防"空报告/漏命名"回归 | +| **Step 10 持久化** | `save_coverage_index_tool(deep_read_files=<本轮全量深读清单>)` 写跨轮覆盖索引(file + per-file SHA) | 下一轮 `include_prior=True` 自动复用未变更文件,多轮后增量归零即全覆盖 | + +### 3.3 单功能流程(feature) + +| 步骤 | 做了什么 | 起到什么功能 | +| --- | --- | --- | +| **Step 0 范围解析** | 从用户指令解析出 `scope="feature"`, `target=<关键词>` | 明确只审查目标功能,缩小范围 | +| **Step 1 图谱就绪** | `build_or_update_graph_tool()` + `get_minimal_context_tool` | 保证查询基于最新代码 | +| **Step 2 定位功能代码** | `semantic_search_nodes(query=target)`(语义定位)+ `query_graph(children_of, target=<模块>)`(模块展开)→ 聚合功能涉及文件 `files=[...]` | 把"功能关键词"转化为具体文件清单,确定审查对象 | +| **Step 3 影响面分析** | `get_impact_radius(changed_files=files)` | 找出该功能波及的调用方/依赖方,评估改动影响范围 | +| **Step 4 客观评分** | `score_review_tool(changed_files=files + 影响文件)` | 对功能代码跑 5 项客观指标 | +| **Step 5 链路分解 + 深读** | Layer 1 八分类 + CRITICAL 检查(聚焦功能文件);文件多时也可用子代理分组深读 | 逐类排查功能内的高风险缺陷 | +| **Step 6 覆盖度计算** | `coverage_tool(deep_read_files=<功能文件>, gate="both")` 复算 | 功能级覆盖兜底 | +| **Step 7 合并去重** | `dedupe_findings_tool` 合并去重 + PR 质量分 | 统一 findings 清单 | +| **Step 8 人工裁决 + 门禁** | 只读裁决;任一 🔴 blocker → `❌ FAIL` | 人工把关 + 结论 | +| **Step 9 报告 + 自检** | `generate_report_tool(format="both")`;md 自检 + verify-report.ps1 | 功能审查报告,防回归 | +| **Step 10 持久化** | `save_coverage_index_tool` 写覆盖索引 | 跨轮增量复用 | + +### 3.4 `all_files` 参数 + +`score_review_tool(all_files=True)` 评分图谱内**全部源文件**,忽略 `changed_files` 与 git diff,用于全项目审查。默认 `False`。 + +### 3.5 覆盖度保障机制 + +> 目标:保证"该深读的都读了,不该漏的没漏",用可量化的方式兜底非热点文件。本节是 project-review 的增强约定,unified-review 可复用(把"深读名单"理解为"变更文件 + 高风险文件")。 + +#### 3.5.1 三层覆盖模型 + +| 层 | 对应步骤 | 覆盖范围 | 手段 | +| --- | --- | --- | --- | +| L1 全量机械扫描 | Step 4 `all_files=True` | **100% 文件** × 5 项指标 | 正则启发式,查机械性风险 | +| L2 并集信号 → 深读名单 | Step 3 + 本节 | 任一信号点名的文件 | 多信号并集,无上限 | +| L3 深度审查 | Step 5.5 子代理深读 | 名单内全部文件 | 逐文件通读(大文件分段),产出带 file:line 证据的 finding | + +#### 3.5.2 深读名单(并集信号,无上限) + +```text +进名单 = 任一命中: + ① 拓扑热点:hub / bridge / large_functions / knowledge_gaps 标记 + ② Step 4 指标 fail 或 warn 的文件 + ③ churn 热点(≥3 次提交) + ④ 测试缺口热点(untested_hotspots) + +任一命中 → 必须深读(无上限) +未被任何信号点名 → 记入"未深读文件清单",在报告中显式列出 +``` + +关键原则:**不覆盖不可怕,不知道没覆盖才可怕**。报告必须附带"未深读文件清单",把覆盖边界显式化。 + +#### 3.5.3 静默文件抽检 + +- 从未被信号点名的文件("静默文件")随机抽 **15%** 深读 +- **升级规则**:抽检中发现 ≥1 个 major → 该文件升级为全量深读,并触发同社区/同类文件追加抽检一轮 + +#### 3.5.4 覆盖度度量(文件数口径 + 三件套质量口径,`gate="both+line"`) + +**由引擎 `coverage_tool` 自动计算**(`code-review-graph` v2.5.0+,三件套口径 v2.5.1 起),审查代理只需传入 `deep_read_files`(本轮实际深读清单)、`gate` 与三件套数据(`file_read_ranges` / `file_semantic_units`)。 + +```text +双重文件数口径: + 全库覆盖 coverage_pct = 已深读文件数 / 全部源文件数 + 高风险覆盖 high_risk_coverage_pct = 已深读高风险文件数 / 信号点名文件数 + +三件套质量口径(gate="both+line" 时生效): + ① 单元完整性 unit_coverage_pct = 语义单元无缺口的深读文件数 / 深读文件数 + 语义单元 = 图谱 Function/Class/Test 节点;子代理上报 semantic_units 与其差集必须为空 + 巨型文件豁免(最大单元行占比 >80%,如 migrations.rs run_migrations 98%)→ 仅按行覆盖校验 + ② 行覆盖 line_coverage_pct = 行覆盖达标的深读文件数 / 深读文件数 + 分子 = union(read_ranges);分母 = 真实文件行数(非图谱 line_end,±1 偏差已修正) + ③ 防伪抽验(主代理执行,非引擎) = 每组抽 2 文件 × 2-3 单元回读比对 note,每波 ≤40 次; + 结果落盘 spot_check_*.json 并注入 review_data.spot_check(顶层字段), + 由 verify-spot-check.ps1 强制校验"已执行"(引擎无法防假读,抽样是唯一手段) + +gate 取值: + "overall" — 只看全库口径 + "high_risk" — 只看高风险口径 + "both" — 全库 + 高风险都要达标(保持原语义,向后兼容) + "both+line" — both + 行覆盖 ≥95% + 单元完整性无缺口(whole-project 新默认,见下) +``` + +**目标值(固定 standard 档位)**:`gate="both+line"` 时要求**全库 ≥85% 且 高风险 ≥95% 且 行覆盖 ≥95% 且 单元完整性无缺口**(`line_target=95`,`unit_target=100` 差集为空)。`target_reached=false` → 报告顶部标 🔴 覆盖不足,并给出 `remaining_files_to_target`(还差几个文件)与 `priority_deep_read_files`(按风险权重降序的待深读清单)驱动补轮;`both+line` 额外返回 `line_gap_files` / `unit_gap_files` / `unit_exempt_files` 定位具体缺口文件。 + +**增量语义(include_prior=True)**:`save_coverage_index_tool` 在每轮报告后写 `.code-review-graph/coverage-index.json`(v2:相对路径 → per-file SHA + `ranges` 行区间)。SHA 来源为图谱 `nodes.file_hash`(一次 SQL 查询,零 subprocess——已修复 v2.5.0 逐文件 `git hash-object` 超时问题)。下一轮 `include_prior=True` 时自动复用 SHA 未变文件的深读状态**及行区间**,只要求重读新增/变更文件,多轮后增量归零即全覆盖。 + +> ⚠️ **图谱同 range 多节点噪声豁免**:TS/TSX 图谱可能对**同一行**解析出多个箭头函数节点(如 `const a = ..., x = ...` 各占一行但 range 相同),导致单元完整性差集永远非空(one-to-one 匹配下无解)。处理原则:**仅当该文件行覆盖已达 100%(或 ≥95%)**,判定为图谱解析噪声,将该文件从 `unit_gap` 中豁免并在报告显式标注"图谱同 range 多节点豁免",不要反复补读。`unit_gap_files` 的判定须结合具体 uncovered 单元名与行号人工确认是否噪声(对比源码该行是否有多个符号)。 + +> ⚠️ **0 字节空文件处理**:深读计划可能选中空文件(如 `web/src/components/evm/EvmConfigModal.tsx`,0 字节且无引用)。引擎对空文件报 `unreadable/empty file` 计入 `line_gap_files`。处理:验证文件字节数与引用情况,确认死文件后从深读清单移除,并作为一条 finding(死代码残留)记录在报告中。 + +#### 3.5.5 三道闸门 + +- **G1 名单完整性**:名单外文件须确认"被评估过"而非"被忽略",未被任何信号点名的文件记入**未深读文件清单**并在报告显式列出 +- **G1.5 三件套质量门禁复核**(v2.5.1+):报告前复核三件套聚合结果——`line_gap_files ∪ unit_gap_files` 必须为空(已补读至空);**图谱同 range 多节点噪声豁免的文件须在报告中显式列出**(每文件注明"行覆盖已 100%,图谱同 range 多节点豁免"),0 字节空文件须从清单移除并单列 finding;`verified_files` 与 `coverage_tool` 的 `deep_read_files` 一致;防伪抽验记录(抽了几组/几个单元/有无假读)附入报告,并由 `verify-spot-check.ps1`(Step 8.8)强制校验 +- **G2 抽检执行**:用 `coverage_tool` 返回的 `silent_files` 随机抽 15% 深读;抽检中发现 ≥1 个 major → 该文件升级为全量深读,并触发同社区/同类文件追加抽检一轮;抽检记录附入报告(抽了几份、发现几个 major、有无升级) +- **G3 覆盖度收尾**:`coverage_tool` 自动计算,`gate="both+line"` 时全库 ≥85% 且 高风险 ≥95% 且 行覆盖 ≥95% 且 单元完整性无缺口才算达标,低于目标在报告顶部告警 + +#### 3.5.6 执行前的前置检查 + +运行覆盖度流程前先确认图谱健康——调用 `community_health_tool`: + +1. `attribution_pct` = `nodes.community_id` 非空 / 非 File 节点数 的百分比 +2. `needs_postprocess=true`(归属率 <90%)→ 先跑 `code-review-graph postprocess` 重建社区归属,再开始审查 + +> 已知问题:`incremental_detect_communities` 在 nodes 重建后可能因 `community_id` 全 NULL 而判定"无社区受影响"跳过写回,导致 `communities.size` 与 `nodes.community_id` 失同步。`community_health_tool` 可检出该状态,遇此情况用全量 `postprocess` 修复。 + +#### 3.5.7 报告覆盖度透传(防 0/0 渲染) + +`coverage_tool` 的返回值必须**完整透传**进 `generate_report_tool` 的 `review_data.coverage`(全部字段:`coverage_pct`/`high_risk_coverage_pct`/`grade`/`deep_read_count`/`total_files`/`high_risk_total_files`/`high_risk_deep_count`/`deep_read_weight`/`total_weight`/`target_reached`/`target`/`gate`/`remaining_files_to_target`/`remaining_weight_to_target`/`priority_deep_read_files`/`uncovered_files`/`silent_files`/`note`)。**不要手挑子集**——`build_report_data` 只读固定键名,缺字段会导致报告覆盖度区块渲染成 `0/0` 或 `N/A`。报告会自动渲染 `## 覆盖度` 区块。 + +--- + +### 3.6 并行深读流水线(whole-project 强制) + +> 主上下文无法逐文件深读 500+ 文件;必须用并行 explore 子代理分组深读,否则全库覆盖永远卡在 2-5%。覆盖率为**文件数口径**,且每个深读文件需通过**三件套质量门禁**(单元完整性 / 行覆盖 / 防伪抽验,见 §3.5.4)。 + +### 3.6.1 流程 + +```text +a. deep_read_plan_tool(target_coverage=85, include_prior=True) + → 返回 groups[{name, weight, files[]}] + remaining_files + (引擎按风险权重 + 目录贪心分组,每组 ≤40 文件;include_prior 排除上轮已深读未变更文件) +b. 按组并行派发 explore 子代理(每次 4-6 个,分多批),每组深读全部文件,返回(落盘到临时目录): + - outputs[]:每文件含 path / total_lines / read_ranges[[s,e]..] / + semantic_units[{range,kind,name,note}] / findings[] + - findings[]:每条含 severity/category/confidence/file:line/message/fix + 【证据铁律】无 file:line 证据的条目视为未深读 → 该文件须重读 +c. 每波子代理完成后跑三件套门禁(引擎原生支持): + coverage_tool(deep_read_files=, gate="both+line", + file_read_ranges=<{rel:[[s,e]..]}>, file_semantic_units=<{rel:[...]}>) + → line_gap_files ∪ unit_gap_files → 补读队列;verified → 计入本轮 deep_read_files + (引擎不可用时兜底:python skills/project-review/scripts/aggregate_deep_read.py <落盘目录>) +d. 防伪抽验:每组抽 2 文件、该文件抽 2-3 个语义单元回读比对 note(每波 ≤40 次); + 结果落盘 spot_check_.json,抽到假读 → 该组重读并升级抽验率 +e. 主代理合并全部 verified_files(去重)→ + coverage_tool(deep_read_files=<全清单>, gate="both+line", include_prior=True) 复算 + (include_prior 自动复用跨轮索引中 SHA 未变文件及其 read_ranges) +f. 未达标(文件数 <85%/<95% 或行覆盖 <95% 或单元有缺口)→ 对 priority_deep_read_files / line_gap_files / unit_gap_files 补派 1-3 个子代理 → 循环直至全达标 +g. G2:对 silent_files 随机抽 15% 深读(见 §3.5.5) +h. 报告生成前:聚合全部 spot_check_*.json → 注入 review_data.spot_check(顶层字段) +i. 报告生成 + 命名自检后:verify-spot-check.ps1(Step 8.8)→ save_coverage_index_tool(deep_read_files=, file_read_ranges=) 写跨轮索引 +``` + +### 3.6.2 子代理分组参考(AuraSpace 实测,约 508 文件) + +| # | 组 | 约文件数 | +| --- | --- | --- | +| 1-2 | `server/src/api`(1/2、2/2) | 60 | +| 3-4 | `server/src/services`(1/2、2/2) | 66 | +| 5 | `server/src/domain` + `deepwiki` + `infrastructure` | 88 | +| 6 | `server/tests` + `bin` + `models` | 17 | +| 7-8 | `web/src/views`(1/2、2/2) | 60 | +| 9-11 | `web/src/components`(1/3、2/3、3/3) | 110 | +| 12 | `web/src/store` + `utils` + `api` | 50 | +| 13 | `web/tests` + `scripts` + SQL | 57 | + +> 实际分组以 `deep_read_plan_tool` 返回为准;每次并行 **4-6 个**子代理,其余排队,避免 MCP 并发压力与上下文风暴。 + +### 3.6.3 质量控制与防伪 + +| 风险 | 对策 | +| --- | --- | +| 子代理"声称读了"但没真读 | 强制三件套字段(total_lines/read_ranges/semantic_units)+ findings 带行号证据;聚合脚本按①单元差集+②行并集双校验;主代理③抽样回读 | +| 子代理漏读文件 | outputs 与分组清单 diff,漏读文件计入覆盖率缺口,触发补轮 | +| 子代理宽 range 冒充全读 | 单元完整性 one-to-one 匹配:一个上报 range 只能覆盖一个单元,无法用整文件 range 覆盖所有单元 | +| 各子代理口径不一 | 统一八分类 + CRITICAL 子轮 + severity/confidence 标准(子代理 prompt 模板) | +| 增量掩盖新代码 | `include_prior=True` 按 per-file SHA 判定;变更文件自动失效重读 | +| 并发压力 | 每批 4-6 个并行,其余排队;batch_size 40 控制单组体量 | +| 主上下文被大 JSON 撑爆 | 落盘机制:子代理写临时文件,主代理只读聚合摘要 | + +### 3.6.4 "深读"的含义边界 + +- **文件级保证(可量化)**:`deep_read_files` 是文件数口径,覆盖 85% 表示 85% 的文件被"读过"(高风险子集要求 95%) +- **行级保证(v2.5.1 起可量化)**:`read_ranges` 的并集 / 真实文件行数 ≥95%;分母为真实文件行数(图谱 `line_end` 有 ±1 偏差,已弃用)。子代理对每个文件上报 `total_lines` + `read_ranges` + `semantic_units`,聚合脚本/引擎逐文件校验 +- **单元级保证(v2.5.1 起可量化)**:`semantic_units` 与图谱 Function/Class/Test 节点差集必须为空(one-to-one 匹配,宽 range 不能冒充);巨型文件(最大单元行占比 >80%)豁免,仅按行覆盖校验 +- **防伪机制**:findings 必须带 `file:line` 证据;主代理每轮 ≤15 次单元回读(引擎无法防假读,抽样是唯一手段);抽到假读 → 该组重读并升级抽验率 + +### 3.6.5 跨轮增量(多轮累积) + +- 每轮报告后 `save_coverage_index_tool` 写 `.code-review-graph/coverage-index.json`(v2:相对路径 → per-file SHA + `ranges` 行区间) +- SHA 来源为图谱 `nodes.file_hash`(一次 SQL 查询,零 subprocess;已修复 v2.5.0 逐文件 `git hash-object` 超时) +- 下一轮 `deep_read_plan_tool` / `coverage_tool` 传 `include_prior=True` 自动复用 SHA 未变文件及其行区间 → 增量任务 = 新增文件 + 变更文件 +- 多轮后增量归零即实现全库全覆盖,避免每轮从 2-5% 起步 + +### 3.6.6 行级覆盖率执行步骤(新窗口 / 全新审查) + +> 本节给出"行级覆盖率如何落地到一次实际审查"的**分步操作**。三件套门禁中,行覆盖是唯一有精确数值的维度(`union(read_ranges) / 真实行数 ≥95%`),本节聚焦它的完整执行链路;单元完整性(差集=空)与防伪抽验在 §3.6.1/§3.6.3 已述。 + +**行级覆盖率的口径(引擎 `scoring.py::compute_coverage`)**: +```text +行覆盖率(每文件) = |union(read_ranges)| / len(Path(repo/f).read_text().splitlines()) +行覆盖达标 = 行覆盖率 >= 95% (line_target,可参数覆盖) +line_coverage_pct = 行覆盖达标的深读文件数 / 深读文件数 +line_gap_files = 行覆盖率 <95% 的文件 [path, coverage_pct, total_lines, covered_lines] +``` +- **分母 = 真实文件行数**(读取源文件,`_real_line_count` 带缓存)——**不用图谱 `line_end`**(实测 ±1 偏差) +- **分子 = `read_ranges` 并集**——子代理实际上报的读取区间(分段读即天然分段) +- **无 ranges 上报的文件**:行覆盖视为通过(不设硬卡),仅依赖单元完整性 + 抽验 + +**执行步骤(主代理在全新会话中)**: + +```text +Step 0 前置(新窗口) + - 确认无残留进程:Get-Process code-review-graph → 无输出 + - 首次调用 get_minimal_context_tool 会拉起 MCP serve(加载新引擎,含 both+line) + +Step 1 建图 + 概览 + - build_or_update_graph_tool() 图谱最新 + - get_minimal_context_tool(task="project review") 全库概览 + +Step 2 架构 + 高风险扫描(同旧流程,产出风险权重信号) + +Step 3 客观评分 + - score_review_tool(all_files=True) + community_health_tool(前置健康检查) + +Step 4 深读分组 + - deep_read_plan_tool(target_coverage=85, include_prior=True) + → groups[{name, weight, files[]}](≤40/组) + +Step 5 并行派发子代理(严格模式) + - 每次 4-6 个 explore 子代理,prompt 见 references/deep-read-pipeline.md §二 + - 每文件必须返回 total_lines / read_ranges[[s,e]..] / semantic_units[{range,kind,name,note}] + - semantic_units 必须逐一列出图谱全部单元(含 Props/interface/小函数,严格模式) + - 结果落盘到临时目录(勿回传大 JSON) + +Step 6 聚合脚本(每波后) + - python skills/project-review/scripts/aggregate_deep_read.py <落盘目录> + - 输出 verified_files / line_gap_files / unit_gap_files / unit_exempt_files + - 行覆盖判定就在这里:line_gap_files 列出所有 <95% 的文件 + +Step 7 引擎门禁(行级覆盖率正式数值) + - coverage_tool(deep_read_files=, gate="both+line", + file_read_ranges=<{rel:[[s,e]..]}>, file_semantic_units=<{rel:[...]}>) + - 返回 line_coverage_pct / unit_coverage_pct / line_gap_files / unit_gap_files / unit_exempt_files + - ⚠️ 必须传 file_read_ranges/file_semantic_units,否则行/单元覆盖不计算 + +Step 8 补轮(禁止降级) + - line_gap_files ∪ unit_gap_files 非空 → 对缺口文件重派子代理补报/重读 + - 禁止回退 gate="both" 静默跳过三件套;必须补至空,或报告显式标注 🔴 + +Step 9 报告 + - generate_report_tool(review_data.coverage = coverage_tool 全量透传) + - "## 覆盖度" 区块须含行覆盖/单元覆盖(line_coverage_pct/unit_coverage_pct) + +Step 10 持久化 + - save_coverage_index_tool(deep_read_files=, file_read_ranges=) + - 写 v2 索引(sha + ranges,SHA 来自 nodes.file_hash,<1s) +``` + +**新窗口首轮验证(Step 0 后建议先跑一次冒烟)**: +```text +coverage_tool(deep_read_files=["server/src/services/auth_service.rs"], + gate="both+line", + file_read_ranges={"server/src/services/auth_service.rs": [[1,66]]}, + file_semantic_units={"server/src/services/auth_service.rs": [全部 6 单元]}) +→ 期望 line_coverage_pct=100, unit_coverage_pct=100, line_gap_files=[] + (即 V2.1 E2E 验证通过,确认引擎加载了新代码) +``` + +**常见坑**: +- 子代理漏 `read_ranges` → 该文件行覆盖不计算(不算 gap 但也不验证),依赖单元完整性兜底;严格模式应要求 read_ranges 覆盖整文件 +- 大文件分段时 read_ranges 各段要有重叠边界或连续覆盖,避免 1 行缝隙拉低覆盖率 +- 全库 508 文件行覆盖聚合约 1-2s(分母读取带缓存);`save_coverage_index` 用 file_hash 后 <1s(不再有逐文件 git subprocess 超时) + +### 3.6.7 实测踩坑与绕行方案(2026-08-18 全库审查实战记录) + +> 本节是 508 文件全库审查(`full-project-review-2026-08-18-144500`)实测中暴露的、文档正文未覆盖的坑与对应解法。深读流水线各环节的坑按出现顺序记录。 + +| # | 环节 | 坑 | 症状 | 解法 | +| --- | --- | --- | --- | --- | +| 1 | 子代理输出落盘 | 子代理 JSON 是**容器格式** `{"group":..., "outputs":[{path, read_ranges, semantic_units, findings}]}`,而 `aggregate_deep_read.py` 期望**单文件记录**(每条记录的 `path` 在顶层) | 聚合脚本 `verified=0`、全部文件被跳过,且无任何报错 | 先**解包**:读容器 → 把 `outputs` 数组逐条拆成独立 JSON 文件(`batchN_idx_.json`)→ 再跑聚合脚本。可用一段 Python 脚本完成,见下 | +| 2 | 聚合脚本 | 子代理用 `write` 写 JSON 可能带 **UTF-8 BOM** | 报错 `Unexpected UTF-8 BOM (decode using utf-8-sig)` | 聚合前批量剥 BOM:读字节,若前 3 字节为 `EF BB BF` 则写入 `bytes[3:]` | +| 3 | 单元完整性补读 | 首轮聚合 `unit_gap` 可达 **92 个文件**(子代理漏报 serde `visit_*` 小方法、几行的 struct/Props interface) | `unit_gap_files` 非空 → 三件套门禁不通过 | **不要整文件重读**。生成 `gap_manifest.json`(含每文件 `uncovered` 单元及精确 range),派 1-2 个"补读子代理"按 range 精准读取缺失单元、产出 `supplement.json`,主代理按 `(path, range)` 合并回原 payload 后再聚合 | +| 4 | 单元完整性 | 图谱对**同一行解析出多个箭头函数节点**(如 `AgentConfigPanel.tsx` 的 `a`/`x` 同 range 420;`DataPermissionManagement.tsx` 的 `d`/`childrenOf` 同 range 76) | 该文件 `total_units` 高但永远 `covered_units` 差 1-3 个,**one-to-one 匹配不可能满足**(一个 range 只能匹配一个单元) | 判断为图谱解析噪声:文件行覆盖已 100% 即视为已深读,在报告中显式标注"该文件存在图谱同 range 多节点,单元完整性豁免";不要反复重读 | +| 5 | 深读清单 | 深读计划可能选中 **0 字节空文件**(如 `web/src/components/evm/EvmConfigModal.tsx`) | `line_gap_files` 报 `unreadable/empty file`,且该文件无任何引用(死文件残留) | 验证文件大小与引用:空文件 + 无引用 → 从深读清单移除,作为一条 finding(死代码)单独记录 | +| 6 | 补读子代理 | 补读子代理若只返回"补了 X 个单元"的**一句话**而不落盘补充 JSON | 主代理拿不到补充的 semantic_units,无法合并 | 强制补读子代理也必须**落盘** `supplement*.json`(结构化 range+note),主代理脚本合并后重跑聚合 | +| 7 | MCP 大 JSON | `dedupe_findings_tool` / `generate_report_tool` 直传 400+ 条 findings 时 **MCP JSON 解析失败**(`Invalid escape character` / `Expected '}'`) | 工具调用直接报 invalid input,报告无法生成 | **绕行**:直接在 Python 里调用引擎函数 `code_review_graph.tools.generate_report_func(review_data, output_path=...)` / `coverage_func(...)`(`sys.path.insert(0, )` 后 import),输出与 MCP 工具完全一致(见 §4.5) | +| 8 | 报告统计 | MD 报告的"问题统计"只读 `counts` 的 **`critical` / `informational` 键**(不读 blocker/major/minor) | 传 `{"blocker":20,"major":141,"minor":315}` 时统计显示 "20 严重 · 0 次要",major 数丢失 | `counts` 传 `{"critical":, "major":, "informational":}` 才能正确渲染 | + +**解包 + 剥 BOM 参考脚本(主代理每轮可复用)**: +```python +# 1) 剥 BOM +for f in glob.glob(dir + "/*.json"): + b = Path(f).read_bytes() + if b[:3] == b"\xef\xbb\xbf": + Path(f).write_bytes(b[3:]) +# 2) 解包 outputs → 单文件记录 +data = json.load(open(batch, encoding="utf-8")) +for i, rec in enumerate(data["outputs"]): + out = dir / f"{basename}_{i}_{rec['path'].replace('/','_')}.json" + out.write_text(json.dumps(rec, ensure_ascii=False), encoding="utf-8") +``` + +**合并 supplement 参考脚本**: +```python +bypath = defaultdict(list) # path -> [semantic_units...] +for s in supp1 + supp2: bypath[s["path"]] += s["semantic_units"] +for rec in payloads: # 每个单文件记录 + if rec["path"] in bypath: + have = {tuple(u["range"]): u for u in rec.get("semantic_units", [])} + for u in bypath[rec["path"]]: + have.setdefault(tuple(u["range"]), u) # 按 range 幂等合并 + rec["semantic_units"] = list(have.values()) +``` + +**教训**:深读流水线的"三件套门禁"把质量控制在引擎侧,但**子代理与主代理之间的数据契约(容器格式、BOM、补读落盘)是纯人工编排**,任何一处契约不一致都会让 verified 计数归零或三件套不达标。建议每波子代理完成后先跑一次聚合脚本看 `verified` 数,而非等到全部结束才校验。 + +--- + +## 4. 审查调用的 MCP 工具 + +### 4.1 核心审查工具 + +| 工具 | 功能 | +| --- | --- | +| `score_review_tool` | **客观 Layer-2 审查指标**:SQL 风险、异常分支覆盖、代码冗余率、高风险场景密度、漏洞启发式 5 项,每项带 good/warn/fail 分级、阈值与证据。支持 `all_files` 全量评分、`include_churn`。`llm_judged` 列出需 LLM 补判的指标 | +| `dedupe_findings_tool` | **Finding 合并去重**:按 `path:line:category` 指纹合并;多源确认置信 +1(上限 10);低置信移附录或抑制;计算 PR 质量分 `max(0, 10 - (critical×2 + informational×0.5))`;支持抑制历史已跳过项 | +| `generate_report_tool` | **审查报告生成**:中文 HTML + Markdown(默认 `format="both"`);`output_path` 传归档目标文件名(含 `docs/reviews/` 前缀,不含扩展名) | +| `coverage_tool` | **覆盖度计算**(v2.5.0 / 三件套 v2.5.1):传入 `deep_read_files` + `gate`(默认 `high_risk`,可选 `overall` / `both` / `both+line`),引擎自动算双重文件数口径(全库 / 高风险)、未深读清单、静默文件清单、达标状态与待补深读优先级。`gate="both+line"` 时额外支持 `file_read_ranges` / `file_semantic_units`,返回行/单元覆盖三件套(`line_coverage_pct` / `unit_coverage_pct` / `line_gap_files` / `unit_gap_files` / `unit_exempt_files`) | +| `deep_read_plan_tool` | **深读分组规划**(v2.5.0):`deep_read_plan_tool(target_coverage=85, include_prior=True, batch_size=40)`(**无 `gate` 参数**),按风险权重 + 目录贪心生成 `groups[{name, weight, files[]}]` + `remaining_files`,主代理据此并行派发子代理 | +| `save_coverage_index_tool` | **跨轮覆盖索引持久化**(v2.5.0 / v2 索引):把本轮深读清单(file + per-file SHA + 可选 `ranges` 行区间)写入 `.code-review-graph/coverage-index.json`,供下一轮 `include_prior=True` 增量复用。v2.5.1 起 SHA 来源为图谱 `nodes.file_hash`(零 subprocess,根治逐文件 `git hash-object` 超时) | +| `community_health_tool` | **社区归属健康检查**(v2.4.0+):返回 `nodes.community_id` 归属率与 `needs_postprocess`,前置检查用 | + +### 4.2 图谱上下文工具 + +| 工具 | 用途 | +| --- | --- | +| `build_or_update_graph_tool` | 确保图谱最新 | +| `get_minimal_context_tool` | 全库概览压缩(节点/边/社区/风险/受影响的流),project-review 主上下文第一步 | +| `get_review_context_tool` | 变更文件 + blast radius + 源码片段 + 审查指引 | +| `detect_changes_tool` | 风险评分 + 变更函数 + 测试缺口 + 受影响流 | +| `get_affected_flows_tool` | 受影响执行流 | +| `query_graph_tool` | 调用方/被调用方/测试/继承查询 | + +### 4.3 图谱全景工具(project-review 用) + +| 工具 | 用途 | +| --- | --- | +| `get_architecture_overview_tool` | 社区耦合总览 | +| `list_communities_tool` | 模块清单 | +| `get_knowledge_gaps_tool` | 结构弱点:孤立节点、未测试热点 | +| `get_hub_nodes_tool` | 最连接节点(架构热点) | +| `get_bridge_nodes_tool` | 架构瓶颈 | +| `find_large_functions_tool` | 超大函数/类 | +| `get_surprising_connections_tool` | 意外跨社区耦合 | +| `semantic_search_nodes_tool` | 按关键词定位代码(单功能) | +| `get_impact_radius_tool` | 单功能的 blast radius | + +### 4.4 工具调用链 + +```text +unified-review(diff): + build_or_update_graph → get_review_context → detect_changes + → score_review_tool → [specialist 子代理] → dedupe_findings_tool → generate_report_tool + +project-review(全项目): + build_or_update_graph → get_minimal_context → 架构全景 + 高风险定位(6 个图谱工具) + → score_review_tool(all_files=True) + community_health_tool(前置检查) + → deep_read_plan_tool → [4-6 并行 explore 子代理 × N 批] → coverage_tool(gate="both+line") + → [未达标]补轮 → [G2]silent 抽检 15% + → dedupe_findings_tool → generate_report_tool(coverage 完整透传) + → verify-report.ps1(命名自检) → save_coverage_index_tool(跨轮索引) + +project-review(单功能): + build_or_update_graph → get_minimal_context → semantic_search_nodes / query_graph 定位功能文件 + → get_impact_radius → score_review_tool(changed_files=<功能文件>) + → coverage_tool(deep_read_files=<功能文件>) → dedupe_findings_tool → generate_report_tool +``` + +### 4.5 引擎函数直调绕行(MCP 大 JSON 失败时的兜底) + +`dedupe_findings_tool` / `generate_report_tool` / `coverage_tool` 通过 MCP 传输 JSON 参数,当 findings 超过数百条(如全库审查 476 条)时可能因 **MCP 参数解析失败**(`Invalid escape character` / `Expected '}'`)而无法调用。此时可**绕开 MCP 直调引擎 Python 函数**,输出与 MCP 工具完全一致: + +```python +import sys, json +sys.path.insert(0, r"D:\code-review-graph\code-review-graph-main") # CRG 引擎本地路径 +import code_review_graph.tools as t + +# 等价于 generate_report_tool +res = t.generate_report_func( + review_data, # 与 MCP 版同构的 review_data dict + output_path=r"D:\AuraSpace\docs\reviews\full-project-review-2026-08-18-144500", + repo_root=r"D:\AuraSpace", + format="both", +) +# 等价于 coverage_tool(gate="both+line") +res = t.coverage_func( + deep_read_files=paths, + gate="both+line", + file_read_ranges=ranges_map, # {rel: [[s,e]..]} + file_semantic_units=units_map, # {rel: [{range,kind,name,note}..]} + repo_root=r"D:\AuraSpace", +) +``` + +> 触发条件:工具调用返回 invalid input / JSON Parse error,且 payload 确认超过 MCP 承载上限(实测 ≥400 条 findings 时出现)。直调入口统一为 `code_review_graph.tools` 下的同名函数;`coverage_func` 的签名见 §3.6.6 的 `compute_coverage` 说明。 + +### 4.6 深读子代理类型选择 + +深读子代理使用 **`explore` 类型**(与 project-review skill 及实际审查一致)。子代理需**写 JSON 落盘**回传三件套数据(容器格式 `{group, outputs[]}`,每条含 path/read_ranges/semantic_units/findings),因此派发前须确认子代理工具集包含 **write 落盘能力**。若子代理无法落盘,主代理拿不到三件套数据,verified 计数会归零。 + +--- + +## 5. 5 项客观指标详解 + +`score_review_tool`(unified-review Step 3 / project-review Step 4)计算 5 项客观 Layer-2 指标。这些指标由**静态正则启发式**实现(源码:`code_review_graph/scoring.py`),扫描变更文件的行级文本(`_iter_source_lines`),不执行代码、不理解语义,因此**会产生误报和漏报,需人工核实后再行动**。阈值定义在 `scoring.py` 的 `THRESHOLDS`。 + +### 5.1 指标总览 + +| 指标 | 值类型 | 评级方向 | good | warn | fail | +| --- | --- | --- | --- | --- | --- | +| `SQL 注入风险` | 命中行数 | 越低越好 | `= 0` | `1-2` | `≥ 3` | +| `异常分支覆盖` | 异常行占比 % | 越高越好 | `≥ 50%` | `30%–50%` | `< 30%` | +| `代码冗余率` | 重复行占比 % | 越低越好 | `≤ 10%` | `10%–20%` | `> 20%` | +| `high_risk_density` | 覆盖行占比 % | 越高越好 | `≥ 90%` | `≥ 70%` | 其余;无高风险行则为 `na` | +| `vulnerability_risk` | 命中行数 | 越低越好 | `= 0` | `1-2` | `≥ 2` | + +**整体客观评级取 5 项中最差项**(`worst`,任一 fail → 整体 FAIL;否则任一 warn → WARN;全 good → GOOD)。 + +### 5.2 这些指标有什么用处 + +核心用途一句话:**把"凭感觉"的审查,变成"有证据、有优先级"的审查清单**。它们不是给代码打分的考试成绩,而是**审查者的导航仪**——告诉你这份代码里"哪些行值得停下来细看",并给这个判断一个可复现的数字证据。 + +| 指标 | 实际帮你做什么 | 没有它的代价 | +| --- | --- | --- | +| `SQL 注入风险` | 直接给出行号,逐个确认"这些是不是注入点",其余 SQL 不用看 | 要么漏看注入,要么浪费时间通读所有 SQL | +| `异常分支覆盖` | 一眼知道错误处理厚薄,决定是否要重点查边界 | 不知道这模块错误处理是优是劣,全靠碰运气 | +| `代码冗余率` | 告诉你有没有"复制粘贴三份"的代码,决定是否值得重构 | 靠肉眼扫重复,扫不全 | +| `high_risk_density` | 标出所有含并发/事务/权限/缓存的行,提醒"这些别跳过" | 容易忽略数据一致性风险点 | +| `vulnerability_risk` | 机械扫硬编码密钥/XSS/shell 特征,做安全快筛 | 靠人工记忆检查常见漏洞模式 | + +**为什么这个设计关键**:审查最贵的成本是**注意力**。一份 diff 或一个功能可能上千行,逐行细看不现实。这 5 项指标把注意力压缩到三件事: +- **哪些行**(evidence 给出 file:line) +- **怀疑什么**(sql/vulnerability 给出关键词模式) +- **薄弱在哪里**(exception_coverage 低 = 错误处理该补查) + +**注意"触发器而非结论"**:命中 ≠ 缺陷。每个指标都带 `evidence` 供逐一人工核实,`score_review_tool` 的 note 反复强调这一点(如 `sql_risk=1` 可能是 JSX 误报)。 + +**与 git diff 无关**:指标扫描的是传入 `changed_files` 清单的**文件全文**,不依赖 git diff。unified-review 的清单来自 git diff,project-review 的清单来自用户指令 → `semantic_search`/`query_graph` 聚合(feature)或 `all_files=True`(whole-project),二者喂给指标的只是不同的文件来源,指标引擎同一套。project-review 的只读、不碰 git 约束天然成立。 + +**分工边界**:指标只覆盖"机械化风险",抓不住 IDOR、越权、竞态、LLM 信任边界等业务逻辑缺陷——那些由 Layer 1 人工链路分解 + specialist 子代理覆盖(见 §5.3 与 §5.2.5 注意)。 + +### 5.3 各指标收集方式与评分标准 + +#### 5.3.1 `sql_risk` — SQL 注入风险 +- **收集方式**:用 6 条正则扫描每行,匹配字符串插值/未参数化 SQL 特征:`"SELECT ..." + 变量`、`f"...{var}"` 含 SQL、`exec("SELECT...`、`WHERE x = '" + var`、`.format(...)` 含 SQL、`% "..." % (...)` 含 SQL 等。 +- **评级**:计数命中行数,0 → good,1-2 → warn,≥3 → fail。 +- **注意**:命中只是警告不是证据。前端 JSX/模板字符串含 SQL 字样易误报(如后端明明全部参数化绑定,报告仍可能报 1 处来自 `.tsx` 的"风险"),需逐一确认上下文,必要时跑 `EXPLAIN` 评估性能。 + +#### 5.3.2 `exception_coverage` — 异常分支覆盖 +- **收集方式**:用 10 条正则统计"异常/错误路径"行数(`try`、`except`、`catch(`、`raise`、`throw`、`if err != nil`、`if ... error`、`.catch(`、`else { return None` 等)。 +- **计算**:`异常行 / 总行 × 100%`。经验基线来自"每 2 条正常路径约有 1 条异常路径"。 +- **评级**:≥50% → good,30%-50% → warn,<30% → fail。 +- **注意**:阈值命名易误解——`warn_min=50` 实际是 good 的及格线,`good_min=30` 是 warn 的下限。该指标对 `?` 一元错误传播(Rust)、`Result` 链等"无显式异常关键字"的代码会低估,需人工补查。 + +#### 5.3.3 `redundancy_rate` — 代码冗余率 +- **收集方式**:将每行标准化为签名(去空白、数字→`N`、字符串→`"s"`),统计**在 ≥3 处出现相同签名**的行数。 +- **计算**:`重复行 / 总行 × 100%`。 +- **评级**:≤10% → good,10%-20% → warn,>20% → fail。 +- **注意**:签名长度 <24 字符的短行被忽略。重复的函数参数签名(如 `State(state)`/`Extension(claims)`)会高频命中,属结构性信号而非缺陷。 + +#### 5.3.4 `high_risk_density` — 高风险场景密度 +- **收集方式**:用 7 条正则标记"高关注行":并发(async/await/thread/mutex)、事务(transaction/commit/rollback)、原子性(atomic/race)、SQL 关键字、锁、缓存失效(cache/invalidate/evict)。 +- **计算**:`覆盖行 / 相关行 × 100%`——因所有相关行都被计入"覆盖",实际**恒为 100%**。无高风险行时返回 `na`(不适用),不计入整体评级。 +- **评级**:≥90% → good,≥70% → warn,其余 fail。 +- **重要**:这是**审查关注信号,不是正确性评分**——只提示"哪些行含并发/事务/安全模式需要人工验证",值高不表示代码好。 + +#### 5.3.5 `vulnerability_risk` — 漏洞风险 +- **收集方式**:用 6 条正则扫描 OWASP/密钥特征:硬编码 `password/api_key/secret/token`、`eval/exec(`、`subprocess(shell=True)`、`innerHTML/dangerouslySetInnerHTML/v-html`、``、`