Files

274 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: project-review
description: Whole-project or single-feature code review (not diff-based) using graph-wide analysis and objective scoring
---
# Project Review
Review the entire codebase or a single feature/module, independent of the git diff. Two scopes, driven by the user's instruction:
- **whole-project**: "对项目代码进行全面审查", "全面审查", "整个项目" → review every source file in the graph.
- **feature**: "审查 <功能/模块> 的代码" (e.g. payment, auth) → review only the code related to the target.
**This skill is READ-ONLY.** Every finding is presented to the user for a manual fix decision. Never apply code changes, commit, or push.
## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="project review")`. Use `detail_level="minimal"` on all calls; escalate to `"standard"` only when a metric or finding needs evidence.
- **Whole-project deep-read is a sub-agent pipeline, not a main-context loop.** 主上下文不逐文件深读 500+ 文件;改为 Step 5.5 并行子代理分组深读。主上下文预算 ≤14 calls + N 子代理(见 Step 5.5)。
## Step 0 - Parse the scope
Read the user's instruction and set scope: whole-project (contains 全面/整个项目/所有/all) or feature + target (extract the feature/module keyword). Declare both in the report header.
> **快速参考**:审查 agent 的精简流程指引来自 `get_docs_section(section="project-review")`(引擎 `docs/LLM-OPTIMIZED-REFERENCE.md`),该文档已同步 review_data schema`reviewed_files` 数组、coverage 全字段透传含三件套字段、metrics 带 note、仅五客观指标)。完整 schema 以本 SKILL.md 与 `references/report-schema.md` 为准。
## Step 1 - Graph ready
1. Call `build_or_update_graph_tool()` to ensure the graph is current.
2. Call `get_minimal_context_tool(task="project review")` for stats and community overview.
## Step 2 - Architecture map
Call `get_architecture_overview_tool(detail_level="minimal")` and `list_communities_tool(detail_level="minimal")` to map the module structure.
## Step 3 - High-risk scan (whole-project)
Call `get_knowledge_gaps_tool()`, `get_hub_nodes_tool()`, `get_bridge_nodes_tool()`, `find_large_functions_tool()` and `get_surprising_connections_tool()` to locate hotspots, chokepoints, untested areas and odd coupling.
## Step 4 - Objective scoring
- whole-project: `score_review_tool(all_files=True)` scores every source file in the graph.
- feature: locate the target files with `semantic_search_nodes_tool(query=<target>)` and `query_graph_tool(pattern="children_of", target=<target>)`, then `score_review_tool(changed_files=<files>)` and `get_impact_radius_tool(changed_files=<files>)` for the blast radius.
- **指标集约束**:报告的 `metrics` 只透传 `score_review_tool` 返回的五个客观指标(`sql_risk` / `exception_coverage` / `redundancy_rate` / `high_risk_density` / `vulnerability_risk`)。**禁止**手工追加 `requirement_coverage` / `logic_alignment` / `llm_trust_boundary` / `shell_injection` / `enum_completeness` 等 LLM 判定指标;`review_data.llm_judged` 一律传空 `[]`
## Step 5 - Chain decomposition
Inspect the scored code across eight categories (interface, business, data, utility, error handling, security, performance, observability) and apply the gstack CRITICAL sub-pass (SQL & Data Safety, Race Conditions, LLM Output Trust Boundary, Shell Injection, Enum Completeness). Mark each ✅ / ⚠️ / —.
## Step 5.5 - 并行深读流水线(whole-project 强制,覆盖率达标的唯一可行路径)
> 引擎 v2.5.0 新增 `deep_read_plan_tool` / `save_coverage_index_tool``coverage_tool` 增加 `gate` / `include_prior`。主上下文无法逐文件深读 500+ 文件,必须用并行子代理分组深读,否则全库覆盖永远卡在 2-5%。覆盖率为**文件数口径**:已深读文件数 / 总文件数。
**目标**:全库覆盖 ≥85% **且** 高风险覆盖 ≥95%(双目标 `gate="both"`standard 档位)**且**每个深读文件通过三件套质量门禁(①单元完整性=100% ②行覆盖≥95% ③防伪抽验≤15次/轮,见 references/deep-read-pipeline.md §〇)。深读计划按风险权重贪心,85% 的全库计划会先选满全部高风险文件,天然同时逼近高风险 95%。
**流程**
```
a. 调 deep_read_plan_tool(gate="overall", target_coverage=85, include_prior=True)
→ 返回分组清单 groups[{name, weight, files[]}] + remaining_files
include_prior=True 自动排除上一轮已深读且未变更的文件,实现增量)
b. 按组并行派发 explore 子代理(每次 4-6 个并行,分多批)。
每个子代理深读该组**全部**文件,返回(**落盘到临时目录,勿回传大 JSON**):
- 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 证据的条目视为未深读**(该文件须重读)
prompt 模板见 references/deep-read-pipeline.md
⚠️ **禁止用 `DEEPREAD_CONFIRM: <路径|总行数|已读范围|单元数>` 单行摘要替代结构化 JSON**:
主代理必须拿到每文件的 `read_ranges`(分段数组)与 `semantic_units`(逐单元
{range,kind,name})并落盘,否则 coverage_tool 无法做行/单元门禁,报告会
"无行覆盖" 且引擎 fail-closed 会全部判缺口。子代理 prompt 必须直接复制
deep-read-pipeline.md §二 的模板,不得自创简化格式。
c. 每波子代理完成后跑三件套门禁(**B 阶段已落地,引擎原生支持**):
- 主代理首选:coverage_tool(deep_read_files=<verified_files>, gate="both+line",
file_read_ranges=<{rel:[[s,e]..]}>, file_semantic_units=<{rel:[{range,kind,name}]}>)
→ 引擎返回 line_coverage_pct / unit_coverage_pct / line_gap_files / unit_gap_files / unit_exempt_files
- 引擎不可用时的兜底:python skills/project-review/scripts/aggregate_deep_read.py <repo_root> <落盘目录>
- line_gap unit_gap → 补读队列;verified → 计入本轮 deep_read_files
d. 防伪抽验(**强制,每波必做,三件套③**):
- 每波子代理完成后立即执行,与 c 门禁同步;**每组抽 2 个文件、每文件抽 2-3 个语义单元**回读比对 note(每波 ≤40 次 read,全审查约 50-72 次分摊到各波)
- 回读:用 read 打开源文件对应 range,比对子代理上报的 semantic_units.note 是否与实际内容相符
- 结果落盘 `spot_check_<batch>.json`schemagroups_sampled / files_sampled / units_sampled / fake_read_found / groups_rereread / samples[{group,file,unit,range,note_match,in_read_ranges}]
- 抽到假读 → 该组重读并升级抽验率(同组改抽 2 文件×3 单元)
- ⚠️ 各波 spot_check 必须聚合后在 Step 8 注入 `review_data.spot_check`(顶层字段),否则报告渲染"未执行 🔴"且 verify-spot-check.ps1 exit 1
e. 主代理汇总全部 verified_files(去重)→
coverage_tool(deep_read_files=<verified_files>, gate="both+line", include_prior=True) 复算
include_prior 自动复用跨轮索引中 SHA 未变的文件及其 read_ranges
f. 未达标(文件数 <85%/<95% 或 行覆盖 <95% 或 单元有缺口)→
对 coverage 返回的 priority_deep_read_files / line_gap_files / unit_gap_files 补一轮 → 循环直至全达标
⚠️ **禁止降级**unit_gap_files 或 line_gap_files 非空时,**不得**改回 `gate="both"` 静默跳过三件套;
必须补轮重读至空,或显式在报告中标注"三件套未达标 🔴"并列出缺口文件。
g. G2:对 silent_files 抽 15% 深读(见 Step 7.5
h. 报告生成后:save_coverage_index_tool(deep_read_files=<verified_files>, file_read_ranges=<{rel:[[s,e]..]}>)
→ 写 .code-review-graph/coverage-index.jsonv2file + per-file SHA + rangesSHA 来自 nodes.file_hash
```
**约束**
- 子代理数量:whole-project 508 文件 ≈ 14-16 组(后端 6 组 / 前端 8 组,见 references/deep-read-pipeline.md 分组表)。
- 质量控制(三件套,必须全部通过才算深读):
- ① 单元完整性:`semantic_units` 与图谱单元差集 = 空(one-to-one 匹配,宽 range 不能冒充;**严格模式**Props interface / Type / 小函数也必须逐一列出)。巨型文件(**仅当**最大单元行占比>80%)豁免,按行覆盖校验。
- ② 行覆盖:`union(read_ranges)` / 真实行数 ≥95%(分母为真实文件行数,非图节点 line_end——后者有 ±1 偏差)。
- ③ 防伪抽验:主代理**每波必做**,每组抽 2 文件 × 2-3 单元,每波 ≤40 次 read;结果落盘 spot_check 并注入报告。引擎无法防假读,抽样是唯一手段。
- 每条 finding 必须带 `file:line` 证据。
- 若引擎工具 `deep_read_plan_tool` 不可用(旧版本),退化为:先 `coverage_tool``priority_deep_read_files` 手动分组派发。
- 增量语义:`include_prior=True` 时,变更文件(SHA 不同)自动失效需重读,防止"上轮读过"掩盖新代码。
> 🔒 **诚实声明(三件套③的防伪边界)**:防伪抽验的**真实性**(主代理是否真读了文件)引擎与脚本**均无法验证**——`verify-spot-check.ps1` 只能验证**声明完整性**(抽了、单元数>0、range 落在 read_ranges 内)。真实回读依赖主代理行为准则。此为引擎防伪能力的已知边界(deep-read-pipeline.md §〇)。
## Step 6 - Manual adjudication (READ-ONLY)
Present every finding with severity (🔴 blocker / 🟡 major / 🔵 minor), confidence (1-10), file:line and a proposed fix. Group by severity and ask the user per batch: fix / skip / self-fix. 🔴 blockers cannot be batch-skipped. **Do not modify code.**
## Step 7 - Acceptance gate
Any 🔴 blocker → verdict `❌ FAIL`. Classify each finding as Ready / Needs Fix / Unusable.
## Step 7.5 - 覆盖度自检(必须执行,防"审完了"由感觉决定)
`CODE_REVIEW_GUIDE_ZH.md` §3.5 的覆盖度保障机制,报告前完成三件事:
1. **深读名单完整性(G1**:确认名单外文件是"被评估过"而非"被忽略";未被任何信号点名的文件记入 **"未深读文件清单"**,在报告中显式列出。
2. **静默抽检(G2**:调用 `coverage_tool` 取返回的 `silent_files`(未被任何信号点名的文件),随机抽 **15%** 深读;发现 ≥1 major → 该文件升级全量深读,并同社区/同类追加抽检一轮。抽检记录附入报告(抽了几份 / 几个 major / 有无升级)。
3. **三件套质量门禁复核(G1.5**:报告前复核 Step 5.5 的三件套聚合结果——`line_gap_files unit_gap_files` 必须为空(已补读至空);`verified_files``coverage_tool``deep_read_files` 一致;防伪抽验记录(抽了几组/几个单元/有无假读)附入报告。
4. **覆盖度计算(G3**
- **whole-project**:调用 `coverage_tool(deep_read_files=<本轮实际深读文件>, gate="both+line")`,引擎自动计算**三重口径**(文件数口径 + 三件套质量口径):
- **全库覆盖** = `coverage_pct`(已深读文件数 / 全部源文件数)
- **高风险覆盖** = `high_risk_coverage_pct`(已深读高风险文件数 / 信号点名文件数)
- **双口径门禁(G3**`gate="both+line"``target_reached` 要求**全库 ≥85% 且 高风险 ≥95% 且 行覆盖 ≥95% 且 单元完整性无缺口**(标准档位,三件套 AND)。`gate="both"` 保持原语义(仅前两项)。`target_reached=false` → 报告顶部标 🔴 覆盖不足。
- **缺口信息**:返回值含 `remaining_files_to_target`(还差多少文件数)与 `priority_deep_read_files`(按风险权重降序的待深读文件)——据此驱动 Step 5.5 的补轮深读。
- **增量**`include_prior=True` 合并跨轮覆盖索引(.code-review-graph/coverage-index.json)中 SHA 未变的已深读文件。
- **feature(单功能)**:调用 `coverage_tool(deep_read_files=<本轮实际深读文件>, gate="line+unit", file_read_ranges=<ranges>, file_semantic_units=<units>)`——**只做行覆盖 ≥95% + 单元完整性无缺口**,**不做全库/高风险文件数覆盖检查**(引擎返回 `coverage_pct`/`high_risk_coverage_pct``null`,报告只渲染行/单元覆盖区块,不渲染全库/高风险行)。`target_reached=false`(行/单元未达标)→ **禁止生成报告**,执行补读闭环(见下)直至达标。
- ⚠️ **三件套数据必传(行覆盖非 0 的前提)**:feature 主上下文深读每个文件时,必须**边读边累积** `file_read_ranges={<rel>:[[s,e],...]}`(已读行区间)与 `file_semantic_units={<rel>:[{"range":[s,e],"kind","name"},...]}`(文件内语义单元),再传给 `coverage_tool`。**不传则 fail-closed 行覆盖=0%**,报告标"行覆盖 0%"且 `verify-line-coverage.ps1` exit 1 拦截。
- 🔁 **补读闭环(硬性,未达标禁止出报告)**:若 `target_reached=false`**不得生成报告**。必须对 `line_gap_files`/`unit_gap_files`/`missing_data_files` 列出的文件补读缺失行区间/语义单元,重跑 `coverage_tool`,直至 `target_reached=true`。无法读全的文件**移出** `deep_read_files`(line+unit 不看文件数,只保留真正读满 ≥95% 的文件)。报告生成后跑 `verify-line-coverage.ps1`exit 1 → 补读重新生成。
将覆盖度结果**完整透传**到 `review_data.coverage`(直接把 `coverage_tool` 返回值全部字段传入: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/overall_target/high_risk_target/gate/**line_coverage_pct/unit_coverage_pct/line_gap_files/unit_gap_files/unit_exempt_files/missing_data_files**/remaining_files_to_target/remaining_weight_to_target/priority_deep_read_files/uncovered_files/silent_files/note),不要手挑子集,否则计数字段渲染为 0/0 或 N/A。报告会自动渲染 `## 覆盖度` 区块(含行/单元覆盖)。**若 `line_coverage_pct` 为 null(未跑 both+line 或未传三件套),报告会显式标"行覆盖:未执行 🔴",且 verify-line-coverage.ps1 会 exit 1 拦截。** **feature 走 `gate="line+unit"` 时 `coverage_pct`/`high_risk_coverage_pct` 为 `null` 属正常,勿因 null 误判为失败;`reviewed_files` 必须传本轮深读文件数组,报告顶部以可折叠列表(details/summary)展示审查文件。**
**前置健康检查**:调用 `community_health_tool`,若 `needs_postprocess=true`nodes.community_id 归属率 <90%),先 `code-review-graph postprocess` 重建社区归属再计算,否则覆盖度失真。
## Step 7.6 - 覆盖度自检验证(必须执行,防"优化没生效")
> 当 `coverage_tool` / `community_health_tool` / `score_review_tool` / `dedupe_findings_tool` / `generate_report_tool` / `deep_read_plan_tool` / `save_coverage_index_tool` **任一工具不可用**,或报告缺 `## 覆盖度` 区块时,按本步骤自检。机制未生效时禁止用 CLI 兜底继续审查,先修复环境。详见 `docs/plans/review-coverage-guarantee-plan.md` 第八章。
1. **环境自检(阻断)**:确认可用工具含上述 7 件套;缺失 → 检查本地源码 `D:\code-review-graph\code-review-graph-main` 版本为 2.5.0`opencode.json``.mcp.json` 均指向 `.venv\Scripts\code-review-graph.exe`(非 `uv run`/`uvx`)。
2. **进程自检**`Get-Process code-review-graph, uv` 应无残留 serve/uv 进程;残留进程会锁 `.venv\Scripts\code-review-graph.exe`,导致 `uv run``os error 32` → MCP 起不来。清理:`taskkill /PID <pid> /T /F`
3. **引擎自检**`community_health_tool()` 应返回 `needs_postprocess=false``attribution_pct>=90``coverage_tool(deep_read_files=[...], gate="both+line", file_read_ranges=<ranges>, file_semantic_units=<units>)` 应返回 `coverage_pct`/`high_risk_coverage_pct`/`line_coverage_pct`/`unit_coverage_pct`/`line_gap_files`/`unit_gap_files`/`unit_exempt_files`/`target_reached`/`remaining_weight_to_target`/`priority_deep_read_files`/`uncovered_files`/`silent_files` 全字段;`deep_read_plan_tool` 应返回 `groups`/`planned_files`
4. **恢复路径**:杀残留进程 → `uv sync``D:\code-review-graph\code-review-graph-main`)修复 venv → 重启 opencode 新会话 → 重新执行本步骤 1-3 直到 PASS。
## Step 8 - Report
Call `generate_report_tool(review_data=<REQUIRED SCHEMA>)` to write `code-review-report.html` and `code-review-report.md` (default `format="both"`).
> **报告生成后(Step 8.6 命名自检通过后)必须执行**:
> `save_coverage_index_tool(deep_read_files=<本轮全量深读清单>, file_read_ranges=<{rel:[[s,e]..]}>)` —— 写跨轮覆盖索引 `.code-review-graph/coverage-index.json`v2file + per-file SHA + rangesSHA 来自 nodes.file_hash)。下一轮审查 `include_prior=True` 时自动复用未变更文件及其行区间,实现增量覆盖,多轮后增量归零即全覆盖。
### ⚠️ review_data 精确 Schema(必须严格遵循,否则报告只剩类别/位置)
工具在 `scoring.py::build_report_data` 中**只读取以下键**。用错键名/字段名会静默丢内容。
顶层键(均为可选项,但 `findings` 缺了就没有问题清单):
| 顶层键 | 值类型 | 说明 |
|---|---|---|
| `verdict` | `"PASS"` / `"FAIL"` | 结论 |
| `scope` | str | **只允许** `"whole-project"` / `"feature"` / `"change-level"`。❌ 禁止传功能名(如 `"evm"`)——verify 脚本按此判定是否检查行覆盖/抽验,传错会绕过门禁 |
| `tier` | str | 如 `"standard"` |
| `timestamp` | str | 如 `"2026-08-06T15:24:47"` |
| `files` | str | 审查文件列表(逗号分隔,兼容字段) |
| **`reviewed_files`** | **list[str]** | **本轮审查的文件数组**(如 `["server/src/api/evm_api.rs", ...]`;**也可传逗号分隔字符串,引擎会自动拆分**)。whole-project/feature 必传;报告顶部以可折叠列表(details/summary)展示,缺省时回退 `files` 逗号拆分 |
| `baseline` | str | git SHA |
| `quality_score` | int/float | 0-10 |
| `counts` | dict | 如 `{"blocker":0,"major":3,"minor":5}`MD 只读 `critical`/`informational` 键) |
| `metrics` | dict | `{指标名: {grade, value, note}}`**值必须是 dict****`note` 必传**(透传 `score_review_tool` 返回的 note/evidence,否则指标"说明"列为空)。❌ 传扁平标量(如 `"sql_risk": 3`)会被静默丢弃。**仅含五个客观指标**sql_risk/exception_coverage/redundancy_rate/high_risk_density/vulnerability_risk,见 Step 4 指标集约束);引擎会过滤 `blast_radius`/`objective_grade` 等非五指标键 |
| **`findings`** | **list[dict]** | **问题清单(必须用 `findings`,不能用 `issues`** |
| `manual_review` | list[str] | 人工复核项 |
| `llm_judged` | list[str] | 保留兼容字段,**一律置空 `[]`**,不再新增 LLM 判定指标 |
| `spot_check` | dict | **防伪抽验记录(顶层字段,非嵌 coverage)**。whole-project/feature 必传,否则报告渲染"防伪抽验:未执行 🔴"且 verify-spot-check.ps1 exit 1。schema`{groups_sampled, files_sampled, units_sampled, fake_read_found, groups_rereread, samples:[{group,file,unit,range,note_match,in_read_ranges}]}` |
| `summary` | str | 审查摘要 |
`findings` 每条**必须**的字段:
| 字段 | 说明 | 反例(会导致丢失) |
|---|---|---|
| `path` | 文件路径(与 `line` 合成 `location` | ❌ 传合并字符串 `location` |
| `line` | 行号(int,与 `path` 合成 `location` | ❌ 省略 `line` 导致无位置 |
| `message` | 问题描述(工具读 `summary``message` | ❌ 用 `title`/`detail` |
| `fix` | 修复建议 | ❌ 用 `title`/`detail` |
| `severity` | `"blocker"`/`"major"`/`"minor"` | |
| `category` | 如 `"business"`/`"security"` | |
| `confidence` | int 1-10 | |
### 完整示例(可直接替换占位复制)
```json
{"verdict": "PASS", "scope": "feature", "tier": "standard", "timestamp": "2026-08-06T15:24:47",
"files": "server/src/api/evm_api.rs, server/src/domain/evm.rs",
"reviewed_files": ["server/src/api/evm_api.rs", "server/src/domain/evm.rs"],
"baseline": "<sha>", "quality_score": 7.5,
"counts": {"blocker": 0, "major": 1, "minor": 0},
"metrics": {"sql_risk": {"value": 0, "grade": "good", "note": "全部参数化,无注入风险。"}},
"findings": [
{"path": "server/src/services/workflow_service.rs", "line": 111,
"severity": "major", "category": "business", "confidence": 8,
"message": "workflow 更新 completion_percentage 后未失效 EVM 缓存,5 分钟 TTL 内显示过期数据。",
"fix": "在 update_state 中调用 EvmService::invalidate_evm_cache(project_id, None)。"}
],
"manual_review": ["确认 list_evm_cases 无 data_scope 是否为有意设计"],
"summary": "发现 1 个 major。SQL 全部参数化无注入风险,无 blocker,结论 PASS。"}
```
**常见错误(自查清单):**
- ❌ 用 `issues` 键 → 工具只读 `findings`,结果 `问题清单(0`
- ❌ finding 用 `title`/`detail` → 工具读 `message`/`fix`,结果只剩类别+位置
- ❌ finding 直接传 `location` 字符串 → 工具由 `path`+`line` 合成,结果位置为空
- ❌ metrics 传扁平标量(`"sql_risk": 0`)→ 工具要求 `{grade, value, note}` dict
### Step 8.5 - 生成后自检(必须执行,防止空报告回归)
生成报告后**必须**打开生成的 `.md` 文件验证,全部通过才算完成:
1. `## 问题清单(N` 中 N == findings 数量(不是 0
2. 每条 issue 同时含**问题描述**、**位置**、**修复建议** 三要素(位置形如 `` `server/...:111` ``
3. **`## 客观指标` 表格存在且非空**(若传了 metrics)——若缺失,多为 `metrics` 值不是 `{grade, value, note}` dict(扁平标量被静默丢弃),需修正后重新生成
4. **`## 客观指标` 表恰好 5 行**`sql_risk` / `exception_coverage` / `redundancy_rate` / `high_risk_density` / `vulnerability_risk`)——出现其他指标名说明手工注入了 LLM 判定指标,违反 Step 4 指标集约束,需移除后重新生成
5. 若发现缺描述/缺修复建议/问题数=0 → 用上述 schema 修正 `review_data` 后**重新调用** `generate_report_tool` 覆盖,直到通过
### Step 8.6 - 报告命名自检(必须执行,防止报告落错位置/缺时间戳)
生成完成后,对仓库运行命名自检脚本(脚本独立于 code-review-graph CLI,任何版本可用):
```powershell
powershell -File "C:\Users\Administrator\.config\opencode\skills\project-review\verify-report.ps1" -Repo <repo_root>
```
- 退出码 **0** → 通过:所有报告都在 `docs/reviews/` 且文件名带 `-YYYY-MM-DD-HHMMSS` 后缀。
- 退出码 **1** → 存在根目录残留 `code-review-report.*`(漏传 `output_path` 的强信号)。用 `-Fix` 自动归档,或直接以正确 `output_path="docs/reviews/{name}-review-{YYYY-MM-DD-HHMMSS}"` **重新调用** `generate_report_tool` 覆盖,然后重跑脚本确认退出码 0。
- 脚本列出的 historic naming warnings 无需处理(仅提示),但**本次生成的报告**必须满足规范。
### Step 8.7 - 行级覆盖自检(必须执行,防止"无行覆盖还全绿")
生成完成后,对最新报告运行行覆盖自检脚本(独立于 code-review-graph CLI,任何版本可用):
```powershell
powershell -File "C:\Users\Administrator\.config\opencode\skills\project-review\verify-line-coverage.ps1" -Repo <repo_root>
```
- 退出码 **0** → 通过:whole-project/feature 报告含**行覆盖**字段且 ≥95%(三件套数据完整)。
- 退出码 **1** → 阻塞:报告覆盖度区块**没有行覆盖**(漏跑 `gate="both+line"`/`line+unit` 或漏传三件套)或行覆盖 <95%。必须补读(Step 7.5 补读闭环)后重新生成报告,再重跑,直到退出码 0。
- ⚠️ **scope 判定**:脚本只对 `change-level` 跳过;自定义 scope 值(如 `"evm"``"issues"`)只要报告含 `## 覆盖度` 区块,同样按行覆盖 ≥95% 检查——`scope` 传功能名不会绕过门禁。
### Step 8.8 - 防伪抽验自检(必须执行,防止"漏抽验还全绿")
whole-project / feature 审查**必须**执行防伪抽验(三件套③),并校验报告含抽验记录。生成完成后对最新报告运行:
```powershell
powershell -File "C:\Users\Administrator\.config\opencode\skills\project-review\verify-spot-check.ps1" -Repo <repo_root>
```
- 退出码 **0** → 通过:报告覆盖度区块含**防伪抽验**字段且单元数 >0(Step 5.5 抽验已执行并注入 `review_data.spot_check`)。
- 退出码 **1** → 阻塞:报告无防伪抽验字段,或渲染"未执行 🔴"。必须补抽验(Step 5.5 d+ 注入 `spot_check` + 重新生成报告后重跑,直到退出码 0。
- ⚠️ **scope 判定**:同 Step 8.7——只对 `change-level` 跳过;自定义 scope 值(如 `"evm"`)含 `## 覆盖度` 区块时同样检查抽验。
- **诚实声明**:该脚本只能验证抽验**声明完整性**(抽了、单元数>0),无法验证主代理是否真读了文件——真实回读依赖行为准则,此为引擎防伪能力的已知边界。
- **Step 8.6(命名)、Step 8.7(行覆盖)、Step 8.8(防伪抽验)三脚本必须全过**才算审查完成。
**Archive naming:** output the report to `docs/reviews/` with `output_path=<base>/{scope}-review-{YYYY-MM-DD-HHMMSS}` (e.g. `docs/reviews/evm-feature-review-2026-08-06-151522`) so the filename carries an exact timestamp and avoids overwriting same-day reviews. Scope value examples: `full-project` (whole project), `{feature}-feature` (feature), `pr-{branch}` (change-level). **不传 `output_path` 时工具默认写到仓库根目录 `code-review-report.*`——这是违规命名,必须在 Step 8.6 用 `verify-report.ps1` 检出并修复。**
更详细的字段对照和完整模板见 `references/report-schema.md`
## Output Format
`Project Review: N issues (X blocker, Y major, Z minor) — verdict: ✅ PASS / ❌ FAIL`. List each issue with severity, confidence, file:line, problem, and proposed fix.
## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="project review")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to `"standard"` when minimal is insufficient.
- **whole-project 深读是子代理流水线(Step 5.5),不是主上下文循环。** 主上下文预算 ≤14 tool calls;深读通过并行 explore 子代理(每次 4-6 个)完成,每个子代理返回 `deep_read 确认清单 + findings[]`(带 file:line 证据)。目标:每轮全库覆盖 ≥80% 且高风险 ≥80%gate="both"),并通过跨轮索引增量累积。