用途
该技能用于对 HEAD 与用户指定固定点之间的 diff 进行双轴审查。固定点由用户提供,可以是提交 SHA、分支名、标签、main、HEAD~5 等。若用户未指定,技能会询问。
两个审查轴:
- 标准(Standards):代码是否符合本仓库中记录的编码标准。
- 规格(Spec):代码是否忠实实现了原始 issue / PRD / 规格。
两个轴作为并行子智能体运行,以免彼此污染上下文,然后由本技能汇总其发现。
该技能提示:issue tracker 应已提供;如果缺少 docs/agents/issue-tracker.md,需要运行 /setup-matt-pocock-skills。
主要能力与流程
1. 固定固定点
用户所说的固定点即为固定点——提交 SHA、分支名、标签、main、HEAD~5 等。如果未指定,则询问。
只捕获一次 diff 命令:git diff <fixed-point>...HEAD(三点,以便与合并基点比较)。同时通过 git log <fixed-point>..HEAD --oneline 记录提交列表。
继续之前,确认固定点可解析(git rev-parse <fixed-point>)且 diff 非空。错误的引用或空 diff 应在此处失败,而不是在两个并行子智能体内部失败。
2. 识别规格来源
按以下顺序查找原始规格:
- 提交消息中的 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。
除了仓库记录的内容外,标准轴始终携带以下坏味道基线——一组固定的 Fowler 代码坏味道(《重构》第 3 章),即使仓库没有任何记录也适用。两条规则约束它:
- 仓库覆盖。已记录的仓库标准始终优先;当仓库标准认可了基线会标记的内容时,抑制该坏味道。
- 始终是判断性调用。每个坏味道都是一个带标签的启发式(“possible Feature Envy”),从来不是硬性违规——并且,和这里的任何标准一样,跳过工具已经强制执行的任何内容。
每个坏味道的读法为“它是什么 → 如何修复”;将其与 diff 匹配:
- Mysterious Name —— 函数、变量或类型名称不能揭示其作用或持有内容。→ 重命名;如果没有诚实的名称,说明设计本身模糊。
- Duplicated Code —— 相同的逻辑形态在变更中出现于多个 hunk 或文件。→ 提取共享形态,两处都调用它。
- Feature Envy —— 一个方法访问另一个对象的数据多于自身数据。→ 将方法移动到它所羡慕的数据上。
- Data Clumps —— 同样的少数几个字段或参数总是结伴出现(一个想要诞生的类型)。→ 将它们捆绑为一个类型并传递该类型。
- Primitive Obsession —— 用原始类型或字符串代表应拥有自己类型的领域概念。→ 给该概念一个小类型。
- Repeated Switches —— 对同一类型的相同 switch/if 级联在变更中反复出现。→ 用多态替换,或两处共享一个映射。
- Shotgun Surgery —— 一次逻辑变更迫使 diff 中许多文件分散修改。→ 将一起变化的内容聚集到一个模块。
- Divergent Change —— 一个文件或模块因多个不相关原因被修改。→ 拆分,使每个模块只为一个原因变化。
- Speculative Generality —— 为规格并不存在的需求添加抽象、参数或钩子。→ 删除它;内联回去,直到出现真实需求。
- Message Chains —— 调用方不应依赖的长 a.b().c().d() 导航。→ 将遍历隐藏在第一个对象的一个方法后面。
- Middle Man —— 一个类或函数主要只是向下委托。→ 删除它,直接调用真实目标。
- Refused Bequest —— 子类或实现者忽略或覆盖了其继承的大部分内容。→ 放弃继承,使用组合。
4. 并行生成两个子智能体
发送一条消息,包含两个 Agent 工具调用。两者都使用通用子智能体。
标准子智能体提示词包含:
- 完整的 diff 命令和提交列表。
- 第 3 步找到的标准来源文件列表,以及第 3 步的坏味道基线全文粘贴——子智能体没有其他途径访问它。
- 简报:“按文件/hunk 报告相关处——(a) diff 违反已记录标准的所有位置:引用该标准(文件 + 规则);(b) 你发现的任何基线坏味道:命名并引用该 hunk。区分硬性违规与判断性调用——已记录标准的违反可以是硬性的,但基线坏味道始终是判断性调用,且已记录的仓库标准覆盖基线。跳过工具强制执行的任何内容。400 字以内。”
规格子智能体提示词包含:
- diff 命令和提交列表。
- 规格的路径或已获取内容。
- 简报:“报告:(a) 规格要求但缺失或部分实现的需求;(b) diff 中未被要求的行为(范围蔓延);(c) 看起来已实现但实现有误的需求。为每条发现引用规格行。400 字以内。”
如果规格缺失,跳过 Spec 子智能体并在最终报告中注明。
5. 汇总
在 ## Standards 和 ## Spec 标题下呈现两份报告,保持原文或轻度清理。不要合并或重新排序发现——两个轴是刻意分开的(见“为什么是两个轴”)。
最后以一行总结结束:每个轴的发现总数,以及每个轴内最严重的问题(如有)。不要在轴之间选出单一赢家——那正是分离所要防止的重新排序。
为什么是两个轴
一次变更可能通过一个轴而失败于另一个轴:
- 代码遵循所有标准但实现了错误的东西 → Standards 通过,Spec 失败。
- 代码完全按 issue 要求做了但破坏了项目约定 → Spec 通过,Standards 失败。
分开报告可防止一个轴掩盖另一个轴。