review-changes 是 afu-it/safe-code 项目中的一个代码审查技能,用于审查工作区、分支或 PR 的变更。其核心设计是使用两个互不合并的审查维度:Standards(仓库规范加代码坏味道基线)和 Spec(变更是否实现当前规格)。两个维度分别评估,代码可能通过其中一个而失败于另一个,合并两者会让一个维度掩盖另一个维度的问题。
输入方面,该技能支持多种变更范围:无参数时比较工作区与默认 diff 基线;传入文件或函数时审查该目标及其影响;传入分支时与 main/master 比较;传入 PR 编号时审查已检出的 PR 分支或本地 diff。它读取 .safe-code/context/code-standards.md 获取文档化的仓库规范,以及 .safe-code/context/feature-specs/<NN>-*.md 中状态为 in-progress 的 active spec(或用户指定的 spec)。在代码图索引就绪时(需先运行 codegraph sync),可使用 codegraph impact <symbol> 评估高风险变更、codegraph callers <symbol> 检查变更的签名、codegraph affected <changed files> 查明 diff 触达的测试。没有代码图时,回退到 git diff、rg 和直接读取,仅对变更或高影响文件读取完整源码。
Standards 维度检查变更是否遵循文档化规范,并避免坏味道基线。坏味道基线来自 Fowler,始终对照 diff 携带,包括:Mysterious Name、Duplicated Code、Feature Envy、Data Clumps、Primitive Obsession、Repeated Switches、Shotgun Surgery、Divergent Change、Speculative Generality、Message Chains、Middle Man、Refused Bequest。另外还有两个结构坏味道:纯辅助函数位于重型模块中会把该模块拖入每个导入者(应移到叶子模块);两个分支检查同一状态且条件几乎相同,会留下间隙。绑定规则包括:文档化的仓库规范始终覆盖基线;每个坏味道都是带标签的判断(例如可能的 Feature Envy),绝不是硬性违规;跳过工具(lint、type-check、formatter)已强制执行的任何内容。
该维度还列出应拒绝的测试形态:实现耦合(mock 内部协作者或通过侧通道断言,特征是重构时行为未变但测试失败);同义反复(断言用与代码相同的方式重新计算期望值,因而按构造通过;期望值必须来自独立来源,如已知良好的字面量、演算示例或规格);横向切片(先写所有测试再写所有实现,验证的是想象的行为);子串匹配(contains("valid") 也会在 "invalid" 上通过,或格式化变更时失败;应断言精确值或结构);仅模拟(假计时器或 jsdom 可能隐藏仅真实运行时才有的 bug,应要求至少一个真实运行时探测)。
证据检查包括:性能主张(如 faster、lighter)需要同条件下测量的变更前基线,否则标记为假设;更少行数不是性能证据。多个路径共享的设置变更(超时、池大小、重试次数)需要针对每个路径的时间预算用真实延迟检查,而不仅仅是触发变更的路径。只有项目在 code-standards.md 中声明分层时,才允许按变更大小调整测试深度;绝不能自行选择较轻层级,短审查压缩的是报告而非验证。
Spec 维度仅在存在 active spec 时启用,否则报告 Spec: no active spec。它检查:缺失(规格中有需求但变更未对应实现)、范围蔓延(变更没有对应需求,可能是预重构,标注即可)、实现错误(需求已处理但行为与规格的 Design / Verify When Done 不同)、重复造轮子(规格或变更新增模块、表或测试框架,而现有事物已完成大部分工作,应指出已有实现)。
输出格式为三个部分。Standards 部分列出严重程度、路径:行号、问题、影响、修复,并给出最严重问题一行或 none。Spec 部分列出 missing | creep | wrong | reinvention、需求或变更、细节,并给出最严重问题一行或 no active spec。Summary 部分包含风险(低、中、高)、影响范围(文件/函数/流程)、已检查测试(命令或图覆盖)、待解决问题或 none。发现项先列,在每个维度内按严重程度排序,绝不跨维度重新排序。只报告可操作的发现。