| name | code-review |
| description | 从用户指定的固定点(commit、branch、tag 或 merge-base)开始,从两个维度审查代码变更:Standards 检查代码是否遵守仓库记录的编码规范,Spec 检查实现是否符合原始 Issue、PRD 或规格。两个审查由并行子 Agent 分别完成,再并列汇报。适用于用户希望审查分支、PR、开发中的改动,或要求“审查自 X 以来的变更”时。 |
对 HEAD 与用户提供的固定点之间的差异进行双维度审查:
- Standards——代码是否符合仓库中记录的编码规范?
- Spec——代码是否忠实实现了原始 Issue、PRD 或规格?
两个维度由并行子 Agent分别执行,避免彼此污染上下文;随后由本 Skill 汇总结果。
Issue 跟踪器应当已经配置。如果缺少 docs/agents/issue-tracker.md,请运行 /setup-matt-pocock-skills。
流程
1. 固定比较点
用户提供的内容就是固定点,可以是 commit SHA、分支名、tag、main、HEAD~5 等。用户未指定时,向其询问。
只确定一次 diff 命令:git diff <fixed-point>...HEAD。这里使用三点语法,使比较以 merge-base 为基准。同时通过 git log <fixed-point>..HEAD --oneline 记录提交列表。
继续前先确认固定点能够解析(git rev-parse <fixed-point>),并且 diff 不为空。无效引用或空 diff 应在这里立即失败,不能等到两个并行子 Agent 内部才暴露。
2. 确定规格来源
按以下顺序寻找原始规格:
- Commit 信息中的 Issue 引用,例如
#123、Closes #45、GitLab !67。按照 docs/agents/issue-tracker.md 中的流程获取内容。
- 用户通过参数传入的路径。
docs/、specs/ 或 .scratch/ 下与分支名称或功能匹配的 PRD / 规格文件。
- 仍未找到时,询问用户规格在哪里。用户明确表示没有规格时,Spec 子 Agent 跳过审查,并报告“没有可用规格”。
3. 确定规范来源
找出仓库中所有说明代码应该如何编写的文档,例如 CODING_STANDARDS.md 或 CONTRIBUTING.md。
除仓库自身文档外,Standards 维度始终携带下方的代码坏味道基线。这是一组固定的 Fowler 代码坏味道(《重构》第 3 章),即使仓库没有记录任何规范也适用。它受两条规则约束:
- 仓库规范优先。 已记录的仓库规范始终具有更高优先级。仓库明确认可某种写法时,即使基线会标记它,也应抑制该提示。
- 始终属于判断性意见。 每种坏味道都必须标记为启发式判断,例如“可能存在 Feature Envy”,绝不能当作硬性违规。与其他规范相同,已经由工具自动执行的事项应跳过。
每条坏味道按“它是什么 → 如何修复”的形式描述。将它们与 diff 对照:
- Mysterious Name——函数、变量或类型的名称无法说明它做什么或保存什么。→ 重命名;如果无法找到诚实准确的名字,说明设计本身仍然模糊。
- Duplicated Code——本次变更的多个区块或文件中出现相同逻辑结构。→ 提取共享结构,由两处共同调用。
- Feature Envy——某个方法访问另一个对象的数据多于自身数据。→ 将方法移动到它所依恋的数据对象上。
- Data Clumps——同一组字段或参数总是结伴出现,暗示一个新类型应当诞生。→ 将它们组合成一个类型,并传递该类型。
- Primitive Obsession——使用 primitive 或字符串代替一个值得拥有独立类型的领域概念。→ 为该概念建立一个小型专用类型。
- Repeated Switches——本次变更中多次对同一种类型重复使用相同的
switch 或 if 级联。→ 使用多态替代,或让两处共享同一张映射表。
- Shotgun Surgery——一项逻辑变更迫使 diff 在许多文件中分散修改。→ 将共同变化的内容聚集到一个模块中。
- Divergent Change——同一个文件或模块因为多个互不相关的原因被修改。→ 拆分模块,使每个模块只因一种原因变化。
- Speculative Generality——为规格中不存在的需求增加抽象、参数或扩展钩子。→ 删除;在真实需求出现前,将其内联回去。
- Message Chains——调用方依赖很长的
a.b().c().d() 导航链。→ 在第一个对象上提供一个方法,把整段遍历隐藏在内部。
- Middle Man——类或函数的大部分工作只是把调用继续转发。→ 删除中间层,直接调用真正目标。
- Refused Bequest——子类或实现者忽略或覆盖了继承内容中的大部分能力。→ 放弃继承,改用组合。
4. 并行启动两个子 Agent
在一条消息中发出两次 Agent 工具调用。两者都使用 general-purpose 子 Agent。
Standards 子 Agent 提示词应包含:
- 完整 diff 命令和 commit 列表。
- 第 3 步找到的规范来源文件列表,以及第 3 步的完整代码坏味道基线。子 Agent 无法通过其他途径访问这份基线。
- 任务说明:“按相关文件或 diff 区块报告:(a) 所有违反已记录规范的位置,并引用对应规范(文件及规则);(b) 发现的任何基线坏味道,写明名称并引用对应区块。区分硬性违规和判断性意见:违反已记录规范可以属于硬性违规,基线坏味道始终只是判断性意见;仓库中记录的规范优先于基线。跳过已经由工具执行的事项。控制在 400 词以内。”
Spec 子 Agent 提示词应包含:
- diff 命令和 commit 列表。
- 规格文件路径或已获取的规格内容。
- 任务说明:“报告:(a) 规格要求但缺失或只完成一部分的内容;(b) diff 中未经要求的行为,即范围蔓延;(c) 表面上已经实现、但实现方式看起来错误的要求。每项发现都引用对应规格原文。控制在 400 词以内。”
缺少规格时,跳过 Spec 子 Agent,并在最终报告中注明。
5. 汇总
分别在 ## Standards 和 ## Spec 标题下呈现两份报告,可以原样使用,也可以做轻微文字清理。不要合并发现,也不要重新排序;两个维度有意保持独立,原因参见“为什么分成两个维度”。
结尾添加一行总结:分别写出每个维度的发现总数,以及该维度内最严重的问题(如果存在)。不要从两个维度中再选出一个共同的“最严重问题”;这样做会重新混合本应分离的判断。
为什么分成两个维度
一项变更可能通过其中一个维度,却在另一个维度失败:
- 代码遵守所有规范,却实现了错误内容 → Standards 通过,Spec 失败。
- 代码准确实现了 Issue 要求,却破坏项目约定 → Spec 通过,Standards 失败。
分开报告可以防止其中一个维度掩盖另一个维度的问题。