08ed43385d
config 模块(glm_check_report_module_01_config.md)11 项 finding 修复: - H-config-1: Set(cfg) 用 mapstructure 重建 m.v,消除 Get/GetString/viper 视图分裂(C1) - M-config-1: 热重载回调独立 recover,panic 不杀 watcher、不阻断后续回调(C9) - M-config-2: DB SSL/TLS -- Postgres SSLMode(默认 prefer)+ MySQL TLS/TLSRootCA; database.ensureMySQLTLSRegistered 注册私有 CA 命名配置,fail-fast 不回退明文。 O-1 文档准确性修正:同名注册会覆盖 master,改为 per-host 不同名 + 自建 replica DSN 指引 - M-config-3: App.Shutdown closeResources 停 configManager watcher(C7) - M-config-4: Clone 切片/map 字段反射守卫测试 - M-config-5: WithConfig/WithConfigPath 全局可见性文档强化 - L-config-2: watchLoop 增 ctx 逃生通道,StopWatcher cancel+Close 双重退出 - L-config-3/4/5/6: Validate 连接池交叉校验、哨兵 errors.New、去冗余 TrimSpace、nil receiver 防御 含契约级回归测试(同源一致性/生命周期闭环/扩展点防御),-race/vet/build 全绿。 附 module 01 评审报告 + 全局结构图 + 扫描收敛协议。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.6 KiB
5.6 KiB
扫描收敛协议(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)"单列,但不计入、不阻塞、不计数:
- 风格 / 格式 / 命名:
fmt.Errorfvserrors.New、变量命名、注释措辞、import 顺序。 - "无害冗余" / 微优化:无热路径实测证据的重复调用、可选的零拷贝、可省的临时变量。
- 功能缺口 / 未实现能力:TLS 未加、交叉校验未加、某配置项未暴露--这些是 roadmap,不是 bug。归观察区。
- 已文档化的设计决策 / footgun:代码注释或 CLAUDE.md 已声明"刻意如此"的,不重挂。
- 不可达路径的防御性补丁:找不到真实 nil 调用方,就不报"缺 nil-check";找不到触发 panic 的输入,就不报"缺 recover"。防御性编码是好习惯,但不构成缺陷。
- 与红线有张力但场景"可接受":逐条对照开发纪律判定,若该场景被纪律明文豁免(如 watcher 的 for-range 关闭语义),不报。
- 维护性风险但当前无缺陷:Clone 手动列举字段今天工作正确、某 switch 缺 default 今天不会命中--只有当"未来扩展会漏"已造成当前可证缺陷时才报,否则不报。
3. 证伪门(计入前强制)
每条 finding 在写入交付前,reviewer 必须主动执行证伪:
- 写出触发路径(具体到调用链 / 输入 / 并发时序)。
- 尝试证伪:路径上有无 guard?调用方是否真实存在?是否已文档化?是否已是已知设计?是否其实有优雅降级?
- 裁定:证伪成功 → 丢弃或降级;证伪失败 → 计入。
只有证伪失败的 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:
- 只报 CRITICAL/HIGH,且每条必须给出可达触发路径,否则不报。
- 风格、冗余、功能缺口、已文档化设计、不可达防御、可接受场景、纯维护性风险--一律不报。
- 每条 finding 先尝试证伪;证伪成功的丢弃。
- 交付三段:真 bug 清单 / 观察区(非 bug)/ 证伪台账。
- 不重扫已加固模块,只扫本次改动 diff(除非报告头标注"首次/重构后")。
- 若你只能找到 MEDIUM/LOW,直接在证伪台账说明并结束,不要为凑数而上调。