Files
xlgo-core/scan_protocol.md
2026-07-14 10:24:10 +08:00

91 lines
5.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.
# 扫描收敛协议(review discipline
> 本文件是 CLAUDE.md「开发纪律」的姊妹篇。开发纪律管"怎么写代码",本协议管"怎么审代码"。
> 起源:多轮大模型全局复审非收敛--每换一个 reviewer 就重新生成一批 nits/功能建议/风格偏好,finding 数永不归零,压迫感持续累积却无关真实质量。本协议把复审收敛到"只产出严重问题"。
## 0. 一句话原则
**只报可达、真实、严重的缺陷。功能正常、质量良好、无 bug 的代码不报。低于 HIGH 一律不报。**
## 1. 栅栏:只报 CRITICAL 与 HIGH
仅当缺陷**同时**满足以下三条才计入交付:
- **可达**:存在真实调用路径触发(必须给出路径:哪条调用链、什么输入、什么并发时序)。纸上推演"理论上如果有人这么调"不算,必须有真实调用方或合理下游用法。
- **是缺陷,非设计**:不是已文档化的设计取舍,不是功能缺口,不是已知 footgun。
- **严重**:达到 CRITICAL 或 HIGH。
级别定义:
- **CRITICAL**:正常使用下可触发的 数据损坏 / 安全突破 / 死锁 / panic / 资源泄漏。
- **HIGH**:真实(不必常见)路径下的 契约违反 / 并发竞态 / 生命周期泄漏 / 安全弱点,且无优雅降级。
低于 HIGH(MEDIUM/LOW)**默认不报**。若某条 MEDIUM 实际后果严重(如静默停摆),应在证伪后上调为 HIGH 再报,而不是以 MEDIUM 身份进清单。
## 2. 吹毛求疵禁区(明确不报)
以下一律**不作为 finding**。可在交付末尾"观察区(非 bug)"单列,但**不计入、不阻塞、不计数**:
1. **风格 / 格式 / 命名**:`fmt.Errorf` vs `errors.New`、变量命名、注释措辞、import 顺序。
2. **"无害冗余" / 微优化**:无热路径实测证据的重复调用、可选的零拷贝、可省的临时变量。
3. **功能缺口 / 未实现能力**:TLS 未加、交叉校验未加、某配置项未暴露--这些是 **roadmap**,不是 bug。归观察区。
4. **已文档化的设计决策 / footgun**:代码注释或 CLAUDE.md 已声明"刻意如此"的,不重挂。
5. **不可达路径的防御性补丁**:找不到真实 nil 调用方,就不报"缺 nil-check";找不到触发 panic 的输入,就不报"缺 recover"。防御性编码是好习惯,但不构成缺陷。
6. **与红线有张力但场景"可接受"**:逐条对照开发纪律判定,若该场景被纪律明文豁免(如 watcher 的 for-range 关闭语义),不报。
7. **维护性风险但当前无缺陷**:Clone 手动列举字段今天工作正确、某 switch 缺 default 今天不会命中--只有当"未来扩展会漏"已造成**当前**可证缺陷时才报,否则不报。
## 3. 证伪门(计入前强制)
每条 finding 在写入交付前,reviewer 必须主动执行证伪:
1. **写出触发路径**(具体到调用链 / 输入 / 并发时序)。
2. **尝试证伪**:路径上有无 guard?调用方是否真实存在?是否已文档化?是否已是已知设计?是否其实有优雅降级?
3. **裁定**:证伪成功 → 丢弃或降级;证伪失败 → 计入。
只有**证伪失败**的 finding 进入交付清单。证伪成功的进入"证伪台账"(见 §5),透明留痕但不制造压迫。
## 4. 范围规则(防重新生成噪声)
非收敛的头号成因是"对已加固模块反复全量重扫"--每个新 reviewer 都会重新生成一批 §2 禁区项。规则:
- **默认扫 diff**:自上次绿灯复审以来的变更,不扫全模块。
- **已加固模块不重扫**,除非本次改动了它。模块是否"已加固"以最近一份"达标"总评为准。
- **全模块扫描**只在"首次复审"或"大重构后"做,且必须在报告头标注"首次 / 重构后重审"。
- **换 reviewer 不算重扫理由**:同一模块换模型复审前,先确认自上次复审有无改动;无改动则拒绝重扫。
## 5. 输出格式
交付物只含三段,严格物理分隔:
### 5.1 真 bug 清单(仅 CRITICAL/HIGH,证伪失败)
每条:
- 标题
- `file:line`(源码唯一证据)
- 触发路径(可达性证明)
- 为何是缺陷(违反哪条契约 / 红线)
- 修复方向(一两句,不展开实现)
### 5.2 观察区(非 bug,不计入,不阻塞)
功能缺口 / roadmap 建议 / 可选增强。明确标注"非 bug"。用户可忽略。
### 5.3 证伪台账(透明留痕)
列出本轮考虑过但丢弃的条目及丢弃理由(落入 §2 哪一条 / 证伪成功)。让用户看到"审过了但拒绝计入",避免"是不是漏审了"的疑虑。
**明确不输出**:风格 nits、"无害冗余"、防御性补丁建议、纯维护性担忧。
## 6. 成功度量(避免把不可达目标绑在自己身上)
-**证伪后剩余的真实 CRITICAL/HIGH 数** -- 可归零,这是唯一硬指标。
-**是否出现新 bug 类别** -- 已收敛的类别(多视图状态 / 公开生命周期 / 用户扩展点 / 间接层吞错)再出现同类的实例,属"扫尾",不属"新问题"。
-**原始 finding 条数** -- 永不归零,不作度量。任何用"finding 条数下降"衡量进步的做法都是错的。
## 7. 给 reviewer 的硬约束(可直接喂入 prompt)
> 你在审查 xlgo 框架代码。遵守 `scan_protocol.md`:
> 1. 只报 CRITICAL/HIGH,且每条必须给出可达触发路径,否则不报。
> 2. 风格、冗余、功能缺口、已文档化设计、不可达防御、可接受场景、纯维护性风险--一律不报。
> 3. 每条 finding 先尝试证伪;证伪成功的丢弃。
> 4. 交付三段:真 bug 清单 / 观察区(非 bug)/ 证伪台账。
> 5. 不重扫已加固模块,只扫本次改动 diff(除非报告头标注"首次/重构后")。
> 6. 若你只能找到 MEDIUM/LOW,直接在证伪台账说明并结束,不要为凑数而上调。