对 HEAD 与用户指定的固定点之间差异进行双轴审查:
- 标准:代码是否符合此仓库文档化的编码标准?
- 规范:代码是否忠实地实现了原始议题/规范?
两个轴作为并行子代理运行,以避免污染彼此上下文,然后此技能汇总它们的发现。
议题跟踪器应已提供给您。如果没有,请告诉用户运行 /setup-matt-pocock-skills。
流程
1. 锁定固定点
无论用户说固定点是什么(提交 SHA、分支名、标签、main、HEAD~5 等)。如果用户没有指定,请询问。
捕获 diff 命令一次:git diff <固定点>...HEAD(三个点,以便与合并基础进行比较)。同时通过 git log <固定点>..HEAD --oneline 记录提交列表。
在继续之前,确认固定点可解析(git rev-parse <固定点>)并且 diff 非空。错误的引用或空的 diff 应在此处失败,而不是在两个并行子代理内部。
2. 识别规范来源
按此顺序查找原始规范:
- 提交消息中的议题引用(
#123、Closes #45、GitLab!67等),通过跟踪器文档中的工作流获取。 - 用户作为参数传递的路径。
- 与分支名或功能匹配的
docs/、specs/或.scratch/下的规范文件。 - 如果未找到,请询问用户规范在哪里。如果用户说没有规范,则规范子代理将跳过并报告“无可用规范”。
3. 识别标准来源
搜索仓库中所有记录代码书写方式的文件。当存在 CODING_STANDARDS.md 或 CONTRIBUTING.md 时,它们必须在列表中。
除了仓库记录的内容之外,标准轴始终携带下面的坏味基准:一组来自 Fowler 《重构》第 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. 汇总
在两个标题 ## 标准 和 ## 规范 下呈现两份报告,逐字逐句或稍加清理。不要合并或重新排列发现,因为这两个轴是故意分开的(参见为什么是两个轴)。
以一行摘要结尾:每个轴发现总数,以及每个轴内最严重的问题(如果有)。不要在轴之间选择单一获胜者:分离正是为了防止这种重新排序。
为什么是两个轴
一个变更可能通过一个轴但无法通过另一个轴:
- 遵循所有标准但实现了错误功能的代码→标准通过,规范失败。
- 完全按照议题要求编写但违反了项目约定的代码→规范通过,标准失败。
分别报告它们可以防止一个轴掩盖另一个轴。