Files

175 lines
8.6 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.
# generate_report_tool 入参 Schema(权威参考)
> 依据 `code-review-graph` 源码 `code_review_graph/scoring.py::build_report_data`
> 与 `render_markdown_report` 反推的精确约定。**任何偏离都会导致报告静默丢内容。**
## 1. 顶层键
工具从 `review_data` dict 中只读取以下键(`scoring.py:620-633`):
| 键 | 类型 | 默认值 | 作用 |
|---|---|---|---|
| `scope` | str | `"change-level"` | 审查范围 |
| `tier` | str | `"standard"` | 审查档位 |
| `timestamp` | str | `""` | 生成时间 |
| `files` | str | `""` | 审查文件(逗号分隔字符串,兼容字段) |
| `reviewed_files` | list[str] | `[]` | 本轮审查文件数组;报告顶部以可折叠列表(details/summary)展示,缺省回退 `files` |
| `baseline` | str | `"generic"` | git 基线 SHA |
| `verdict` | str | `"❌ FAIL"` | 结论,`"PASS"``"FAIL"` |
| `quality_score` | int/float | `None` | PR 质量分 |
| `counts` | dict | `{}` | 严重度统计 |
| `metrics` | dict | `{}` | 客观指标(值必须是 dict) |
| **`findings`** | **list[dict]** | `[]` | **问题清单** |
| `manual_review` | list[str] | `[]` | 人工复核项 |
| `llm_judged` | list[str] | `[]` | 保留兼容字段,**一律置空**;不再新增 LLM 判定指标 |
| `summary` | str | `""` | 摘要(仅 HTML 渲染) |
## 2. findings 条目字段(scoring.py:645-658
工具对每条 finding 做如下映射:
```python
data["issues"].append({
"severity": f.get("severity", "minor"),
"category": f.get("category", ""),
"message": f.get("summary", f.get("message", "")), # summary 优先,其次 message
"location": f"{f.get('path','')}:{f.get('line','')}" # 仅当 line 非空
if f.get("line") else str(f.get("path","")),
"confidence": f.get("confidence"),
"fix": f.get("fix", ""),
})
```
| 字段 | 说明 | 若不传会怎样 |
|---|---|---|
| `path` | 文件路径 | 与 `line` 合成 `location`;仅传 path 也可显示路径 |
| `line` | 行号 | **line 为空则 location 只有 path**(无 `:行号` |
| `message` | 问题描述 | 缺失 → 报告只剩类别/位置 |
| `summary` | 问题描述(优先级高于 message) | 同上 |
| `fix` | 修复建议 | 缺失 → 无修复建议段 |
| `severity` | `blocker`/`major`/`minor`(也接受 `critical`/`warn`/`informational` | 默认 `minor` |
| `category` | 如 `business`/`security`/`data` 等 | 默认空 |
| `confidence` | int 1-10 | 缺失则不显示置信度 |
## 3. metrics 结构(scoring.py:636-643
`metrics` 的值必须是 **dict**,每项支持 `grade`/`value`/`note`/`evidence`。**`note` 必传**(透传 `score_review_tool` 返回的 note/evidence),否则报告"说明"列为空。
```json
"metrics": {
"sql_risk": {"value": 0, "grade": "good", "note": "全部参数化查询,无注入风险。"},
"exception_coverage": {"value": 0, "grade": "fail", "note": "Rust Result 误报。"}
}
```
MD 报告显示标签来自硬编码映射:`sql_risk`→SQL 注入风险、`exception_coverage`→异常分支覆盖、`redundancy_rate`→代码冗余率、`high_risk_density`→高风险场景密度、`vulnerability_risk`→漏洞风险。其他指标名直接显示原名。**指标表应仅含上述五个客观指标**(指标集约束见 SKILL.md Step 4),禁止手工注入 `requirement_coverage`/`logic_alignment`/`llm_trust_boundary`/`shell_injection`/`enum_completeness` 等 LLM 判定指标;**也不要混入 `blast_radius`/`objective_grade` 等键——`build_report_data` 会按五指标白名单过滤,非五指标键一律丢弃。**
## 4. counts 说明(scoring.py:727-732
MD 报告的问题统计行只读 `counts.critical``counts.informational`
```python
f"- **问题统计**{counts.get('critical', 0)} 严重 · {counts.get('informational', 0)} 次要"
```
因此若想统计正确,`counts` 需用 `critical`/`informational` 键(或将 major/minor 数量合入)。
## 4b. coverage 字段(Step 7.5 G3,引擎 v2.5.0
`review_data.coverage` 直接透传 `coverage_tool` 返回值**全部字段**(不要手挑子集,否则计数字段渲染 0/0 或 N/A):
| 字段 | 说明 |
|---|---|
| `coverage_pct` | 全库覆盖(已深读文件数 / 全部源文件数,**文件数口径**);`gate="line+unit"`feature)时为 `None` |
| `high_risk_coverage_pct` | 高风险覆盖(已深读高风险文件数 / 信号点名文件数,文件数口径);`gate="line+unit"`feature)时为 `None` |
| `grade` | good/warn/fail |
| `deep_read_count` / `total_files` | 已深读数 / 总源文件数 |
| `high_risk_total_files` / `high_risk_deep_count` | 高风险文件数 / 已深读高风险数 |
| `deep_read_weight` / `total_weight` | 已深读权重 / 总权重(兼容保留,仅用于排序参考) |
| `target_reached` / `target` | 门禁结果 / 高风险目标值(gate="both" 时需全库 ≥85% 且 高风险 ≥95% 才 Truestandard=85/95 |
| `overall_target` / `high_risk_target` | 双目标值:全库 85% / 高风险 95%(报告据此分别显示) |
| `gate` | 门禁口径(high_risk/overall/both/both+line/line+unit |
| `remaining_files_to_target` | 距全库目标还差多少文件数(**驱动补轮的主字段**) |
| `remaining_weight_to_target` | 距目标还差多少权重(兼容保留) |
| `priority_deep_read_files` | 按风险权重降序的待深读文件(`[{path, weight}]` |
| `uncovered_files` | 未深读文件清单(G1 |
| `silent_files` | 静默文件清单(G2 抽检源) |
| `note` | 引擎口径说明 |
> 增量:`coverage_tool(include_prior=True)` 合并跨轮索引 `.code-review-graph/coverage-index.json`
> 中 SHA 未变的已深读文件。报告后必须 `save_coverage_index_tool` 写索引供下轮复用。
### 4b-1. feature(单功能)审查:`gate="line+unit"`
feature 覆盖度门禁**只保留行级覆盖 + 单元覆盖**,不做全库/高风险文件数覆盖检查:
```json
"coverage": {
"gate": "line+unit",
"coverage_pct": null,
"high_risk_coverage_pct": null,
"line_coverage_pct": 100.0,
"unit_coverage_pct": 100.0,
"line_gap_files": [],
"unit_gap_files": [],
"target_reached": true
}
```
- `coverage_pct` / `high_risk_coverage_pct``null` 是**预期行为**(不做文件数覆盖检查),勿误判失败。
- `target_reached` 只由行覆盖 ≥95% + 单元完整性无缺口决定。
- 报告 `## 覆盖度` 区块只渲染行/单元覆盖与状态行,不渲染全库/高风险行。
- 必须同时传 `reviewed_files`(本轮深读文件数组),报告顶部以可折叠列表展示。
## 5. 完整可复制模板
```json
{
"verdict": "PASS",
"scope": "feature",
"target": "EVM",
"tier": "standard",
"timestamp": "2026-08-06T15:24:47",
"files": "server/src/api/evm_api.rs, server/src/services/evm_service.rs",
"baseline": "f4235d00008a0de651ad8988adc1bca27ede1fb2",
"quality_score": 7.5,
"counts": {"blocker": 0, "major": 3, "minor": 5},
"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": "progressive 模式下 EV 计算依赖 workflow_states.completion_percentage,更新后未失效 EVM 缓存,5 分钟 TTL 内显示过期数据。",
"fix": "在 update_state / create_state / delete_state 中调用 EvmService::invalidate_evm_cache(project_id, None)。"
}
],
"manual_review": [
"list_evm_cases 无 data_scope 是否为有意设计(需产品/权限负责人确认)"
],
"summary": "发现 3 个 major 与 5 个 minor。SQL 全部参数化无注入风险,无 blocker,结论 PASS。"
}
```
## 6. 错误用法 → 现象对照表
| 错误用法 | 代码示例 | 现象 |
|---|---|---|
| 用 `issues` 键 | `{"issues": [...]}` | `问题清单(0`,条目全丢 |
| finding 用 `title`/`detail` | `{"title": "...", "detail": "..."}` | 只剩类别+位置,描述/修复为空 |
| 传合并 `location` | `{"location": "a.rs:5"}` | 位置为空(工具只认 path+line |
| metrics 传扁平标量 | `"sql_risk": 0` | 指标表空(要求 dict |
| `counts` 用 major/minor | `{"counts":{"major":3}}` | MD 统计行显示 0 严重·0 次要 |
## 7. 生成后自检清单(Step 8.5
生成报告后必须打开 `.md` 验证:
- [ ] `## 问题清单(N`N == findings 条数,且 > 0
- [ ] 每条 issue 同时含描述 + 位置(`` `path:line` ``+ 修复建议
- [ ] 若任一缺失 → 修正 `review_data` 字段后重新调用 `generate_report_tool` 覆盖