| name | code-review |
| description | 从两个轴向审查某个固定点(commit、branch、tag 或 merge-base)以来的变更——Standards(代码是否遵循本仓库记录的编码规范?)和 Spec(代码是否符合源起的 issue/PRD 的要求?)。在并行子智能体中运行两项审查,并把它们并排报告。当用户想审查一个分支、一个 PR、进行中的变更,或要求 "review since X" 时使用。 |
对 HEAD 与用户提供的某个固定点之间的 diff 进行双轴审查:
- Standards — 代码是否符合本仓库记录的编码规范?
- Spec — 代码是否忠实实现了源起的 issue / PRD / 规格?
两个轴向都作为 并行子智能体 运行,以免互相污染上下文,然后由本技能汇总它们的发现。
问题追踪器应该已经提供给你了——如果 docs/agents/issue-tracker.md 缺失,运行 /setup-matt-pocock-skills。
流程
1. 钉住固定点
用户所说的就是固定点——一个 commit SHA、branch 名、tag、main、HEAD~5 等等。如果他们没指定,就问。
一次性确定 diff 命令:git diff <fixed-point>...HEAD(三点,因此比较是针对 merge-base 的)。同时通过 git log <fixed-point>..HEAD --oneline 记下 commit 列表。
在继续之前,确认固定点能解析(git rev-parse <fixed-point>)且 diff 非空。坏的 ref 或空 diff 应该在这里失败——而不是在两个并行子智能体内部。
2. 确定规格来源
按以下顺序寻找源起的规格:
- commit 消息中的 issue 引用(
#123、Closes #45、GitLab !67 等等)——通过 docs/agents/issue-tracker.md 中的工作流获取。
- 用户作为参数传入的路径。
docs/、specs/ 或 .scratch/ 下与分支名或功能匹配的 PRD/规格文件。
- 如果什么都没找到,问用户规格在哪里。如果他们说没有,Spec 子智能体将跳过并报告 "no spec available"。
3. 确定规范来源
仓库中任何记录代码应如何编写的东西,例如 CODING_STANDARDS.md 或 CONTRIBUTING.md。
在仓库所记录的东西之上,Standards 轴始终携带下面的 坏味道基线——一组固定的 Fowler 代码坏味道(Refactoring, ch.3),即使仓库什么都没记录也适用。有两条规则约束它:
- 仓库优先。 记录在案的仓库规范始终获胜;当它认可某个基线本会标记的东西时,压制该坏味道。
- 始终是判断题。 每个坏味道都是一个带标签的启发式("possible Feature Envy"),从不是硬性违规——而且,像这里的任何规范一样,凡是工具已经强制执行的都跳过。
每个坏味道读作 它是什么 → 如何修;把它对照 diff:
- Mysterious Name — 一个函数、变量或类型,其名字没有揭示它做什么或持有什么。→ 重命名它;如果找不到诚实的名字,说明设计混浊。
- Duplicated Code — 同样形态的逻辑出现在此次变更的多个 hunk 或文件中。→ 抽取共享的形态,从两处调用它。
- Feature Envy — 一个方法访问另一个对象的数据多过访问自己的。→ 把该方法搬到它所艳羡的数据上。
- Data Clumps — 同样的几个字段或参数总是结伴出现(一个想要诞生的类型)。→ 把它们打包成一个类型,传那个。
- Primitive Obsession — 一个原始类型或字符串充当一个本该有自己类型的领域概念。→ 给这个概念它自己的小类型。
- Repeated Switches — 同样的
switch/if 级联针对同一类型在此次变更中反复出现。→ 用多态替换,或用两处共享的一张 map。
- Shotgun Surgery — 一处逻辑变更迫使 diff 中许多文件里散落的编辑。→ 把一起变化的东西聚拢到一个模块里。
- Divergent Change — 一个文件或模块因几个不相关的原因被编辑。→ 拆分,使每个模块因一个原因而变化。
- Speculative Generality — 为规格并不具备的需求而添加的抽象、参数或钩子。→ 删掉它;内联回去,直到出现真正的需求。
- Message Chains — 调用方本不该依赖的长串
a.b().c().d() 导航。→ 把这趟游走藏在第一个对象上的一个方法后面。
- Middle Man — 一个大部分只是往下委托的类或函数。→ 砍掉它,直接调用真正的目标。
- Refused Bequest — 一个子类或实现者忽略或覆盖了它所继承的大部分。→ 放弃继承,改用组合。
4. 并行派生两个子智能体
用单条消息发出两个 Agent 工具调用。两个都用 general-purpose 子智能体。
Standards 子智能体提示词 — 包含:
- 完整的 diff 命令和 commit 列表。
- 你在第 3 步中找到的规范来源文件列表,外加第 3 步的坏味道基线 完整粘贴进去——子智能体没有其他途径访问它。
- 任务简述:"报告——在相关处按文件/hunk——(a)diff 违反某项记录在案规范的每一处:引用该规范(文件 + 规则);以及(b)你发现的任何基线坏味道:命名它并引用该 hunk。区分硬性违规与判断题——记录在案规范的违反可以是硬性的,但基线坏味道始终是判断题,且记录在案的仓库规范覆盖基线。凡工具强制执行的都跳过。不超过 400 词。"
Spec 子智能体提示词 — 包含:
- diff 命令和 commit 列表。
- 规格的路径或已获取的内容。
- 任务简述:"报告:(a)规格所要求但缺失或部分实现的需求;(b)diff 中并未被要求的行为(范围蔓延);(c)看似已实现但实现看起来有误的需求。为每个发现引用规格中的那一行。不超过 400 词。"
如果规格缺失,跳过 Spec 子智能体,并在最终报告中说明这一点。
5. 汇总
把两份报告放在 ## Standards 和 ## Spec 标题下呈现,逐字照录或略作清理。不要 合并或重新排列各项发现——这两个轴向是刻意分开的(见 为什么是两个轴向)。
以一行摘要结尾:每个轴向的发现总数,以及 每个轴向内 最严重的问题(如有)。不要跨轴向挑一个总冠军——那正是这种分离要防止的重排。
为什么是两个轴向
一个变更可以通过一个轴向而在另一个上失败:
- 遵循了每一项规范但实现了错误的东西的代码 → Standards 通过,Spec 失败。
- 完全做了 issue 所要求的、却破坏了项目约定的代码 → Spec 通过,Standards 失败。
分开报告能阻止一个轴向掩盖另一个。