175 lines
8.6 KiB
Markdown
175 lines
8.6 KiB
Markdown
# 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% 才 True;standard=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` 覆盖
|