# 扫描收敛协议(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,直接在证伪台账说明并结束,不要为凑数而上调。