对 HEAD 与用户给出的固定点之间的 diff 做双轴评审:
- 规范:代码是否符合本仓库已记录的编码规范?
- 规格符合:代码是否忠实实现了最初那个议题/规格说明?
两条轴都作为并行子代理运行,这样它们不会污染彼此的上下文;最后由本技能汇总它们的发现。
议题跟踪器的信息本应已经提供给你。如果 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. 找到规格说明的来源
按下面的顺序寻找最初那份规格说明:
- 提交信息里的议题引用(
#123、Closes #45、GitLab 的!67等等),通过docs/agents/issue-tracker.md里的工作流取回。 - 用户作为参数传进来的路径。
docs/、specs/或.scratch/下与分支名或功能相匹配的规格说明文件。- 如果什么都没找到,就问用户规格说明在哪里。如果用户说没有,规格符合子代理会跳过,并报告「没有可用的规格说明」。
3. 找到规范来源
仓库里任何记录代码该怎么写的东西,例如 CODING_STANDARDS.md 或 CONTRIBUTING.md。
在仓库自己记录的一切之上,规范这一轴始终带着下面这份坏味道基线:一组固定的 Fowler 代码坏味道(Refactoring 第 3 章),即使仓库什么都没记录,它也照样适用。有两条规则约束它:
- 仓库优先。 仓库里已记录的规范永远胜出;当它认可了基线会点出来的某种做法时,就把那条坏味道压下去。
- 永远是判断题。 每条坏味道都是一个带标签的启发式提示(例如「可能是依恋情结」),绝不是硬性违规。和这里任何规范一样,跳过工具已经在强制检查的东西。
每条坏味道都按它是什么 → 怎么修来读,再拿它和 diff 对照:
- 神秘命名:函数、变量或类型的名字没有透露它是做什么的、装的是什么。→ 重命名它;如果实在想不出诚实的名字,那说明设计本身就不清楚。
- 重复代码:同一种逻辑形状在这次改动的多个改动块或文件里出现。→ 把共用的形状抽出来,两边都调用它。
- 依恋情结:一个方法伸进别的对象的数据里,比用它自己的数据还多。→ 把这个方法搬到它所依恋的那份数据上去。
- 数据泥团:同样那几个字段或参数总是结伴出现(一个想要诞生的类型)。→ 把它们捆成一个类型,传这个类型。
- 基本类型偏执:用一个基本类型或字符串顶替一个本该有自己的类型的领域概念。→ 给这个概念一个自己的小类型。
- 重复的 switch:对同一类型写出的同一串
switch/if级联在这次改动里反复出现。→ 换成多态,或者换成两处共用的一个映射表。 - 霰弹式修改:一次逻辑上的改动迫使你在 diff 的许多文件里零散地改。→ 把总是一起变的东西收进一个模块。
- 发散式变化:一个文件或模块因为几个互不相关的原因被修改。→ 拆开,让每个模块只为一个原因而变。
- 夸夸其谈通用性:为了规格说明里并不存在的需要而添的抽象、参数或钩子。→ 删掉它;先内联回去,等真实的需要出现。
- 过长的消息链:一长串
a.b().c().d()式的导航,调用方不该依赖它。→ 把这趟游走藏到第一个对象上的一个方法后面。 - 中间人:一个类或函数基本只是在往下转发。→ 砍掉它,直接调用真正的目标。
- 被拒绝的遗赠:一个子类或实现者忽略或覆盖了它继承来的大部分东西。→ 丢掉继承,改用组合。
4. 并行起两个子代理
规范子代理的提示词应包含:
- 完整的 diff 命令和提交列表。
- 你在第 3 步找到的规范来源文件清单,再加上第 3 步那份坏味道基线的全文粘贴(子代理没有别的途径拿到它)。
- 交给它的任务说明:「按文件/改动块分别报告(在相关的地方):(a)diff 中每一处违反已记录规范的地方:引用那条规范(文件 + 规则);(b)你发现的任何基线坏味道:说出它的名字并引用那段改动。区分硬性违规和需要判断的地方:违反已记录规范可以是硬性的,但基线坏味道永远属于需要判断的地方,而且仓库里已记录的规范优先于基线。跳过任何工具已经在强制检查的东西。400 词以内。」
规格符合子代理的提示词应包含:
- diff 命令和提交列表。
- 规格说明的路径或已取回的内容。
- 交给它的任务说明:「报告:(a)规格说明要求了、但缺失或只做了一部分的需求;(b)diff 里没有要求过的行为(范围蔓延);(c)看起来实现了、但实现方式看起来有误的需求。每一条发现都引用规格说明里的原句。400 词以内。」
如果规格说明缺失,就跳过规格符合子代理,并在最终报告里注明这一点。
5. 汇总
把两份报告分别放在 ## Standards 和 ## Spec 标题下面呈现,原文照录或稍作清理。不要合并或重新排序发现的问题,因为两条轴是刻意分开的(见为什么是两条轴)。
最后用一行总结收尾:每条轴上的发现总数,以及每条轴内部最严重的问题(如果有的话)。不要在两条轴之间挑出唯一的赢家:那正是这种分离要防的重新排序。
为什么是两条轴
一次改动可以通过一条轴,却在另一条轴上不及格:
- 代码遵守了每一条规范,但实现的东西是错的 → 规范:通过;规格符合:不及格。
- 代码完全按议题要求的做了,但破坏了项目的约定 → 规格符合:通过;规范:不及格。
分开报告,能防止一条轴掩盖另一条。


