code-review

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Two-axis review of the diff between
HEAD
and a fixed point the user supplies:
  • Standards — does the code conform to this repo's documented coding standards?
  • Spec — does the code faithfully implement the originating issue / spec?
Both axes run as parallel sub-agents so they don't pollute each other's context, then this skill aggregates their findings.
The issue tracker should have been provided to you — run
/setup-matt-pocock-skills
if
docs/agents/issue-tracker.md
is missing.
HEAD
与用户指定的固定节点之间的代码差异进行双维度审查:
  • 标准维度——代码是否符合本仓库已文档化的编码标准?
  • 需求维度——代码是否忠实地实现了原始需求/规格说明书的内容?
两个维度的审查由并行子Agent运行,避免互相干扰上下文,之后由本Skill汇总审查结果。
系统应已为你提供issue tracker——如果缺少
docs/agents/issue-tracker.md
,请运行
/setup-matt-pocock-skills

Process

流程

1. Pin the fixed point

1. 确定固定节点

Whatever the user said is the fixed point — a commit SHA, branch name, tag,
main
,
HEAD~5
, etc. If they didn't specify one, ask for it.
Capture the diff command once:
git diff <fixed-point>...HEAD
(three-dot, so the comparison is against the merge-base). Also note the list of commits via
git log <fixed-point>..HEAD --oneline
.
Before going further, confirm the fixed point resolves (
git rev-parse <fixed-point>
) and the diff is non-empty. A bad ref or empty diff should fail here — not inside two parallel sub-agents.
用户提及的任何内容都可作为固定节点——commit SHA、分支名称、tag、
main
HEAD~5
等。如果用户未指定,需向其询问。
记录一次差异命令:
git diff <fixed-point>...HEAD
(三个点,表示基于merge-base进行对比)。同时通过
git log <fixed-point>..HEAD --oneline
记录提交列表。
在继续下一步前,确认固定节点可解析(运行
git rev-parse <fixed-point>
)且差异内容非空。无效引用或空差异应在此处终止流程——不要进入并行子Agent的运行环节。

2. Identify the spec source

2. 确定需求来源

Look for the originating spec, in this order:
  1. Issue references in the commit messages (
    #123
    ,
    Closes #45
    , GitLab
    !67
    , etc.) — fetch via the workflow in
    docs/agents/issue-tracker.md
    .
  2. A path the user passed as an argument.
  3. A spec file under
    docs/
    ,
    specs/
    , or
    .scratch/
    matching the branch name or feature.
  4. If nothing is found, ask the user where the spec is. If they say there isn't one, the Spec sub-agent will skip and report "no spec available".
按以下顺序查找原始需求:
  1. 提交信息中的issue引用(如
    #123
    Closes #45
    、GitLab的
    !67
    等)——通过
    docs/agents/issue-tracker.md
    中的工作流获取。
  2. 用户作为参数传入的路径。
  3. docs/
    specs/
    .scratch/
    目录下与分支名称或功能匹配的需求文件。
  4. 如果未找到任何内容,询问用户需求所在位置。若用户表示没有需求,需求维度的子Agent将跳过审查,并报告“无可用需求”。

3. Identify the standards sources

3. 确定标准来源

Anything in the repo that documents how code should be written, such as
CODING_STANDARDS.md
or
CONTRIBUTING.md
.
On top of whatever the repo documents, the Standards axis always carries the smell baseline below — a fixed set of Fowler code smells (Refactoring, ch.3) that applies even when a repo documents nothing. Two rules bind it:
  • The repo overrides. A documented repo standard always wins; where it endorses something the baseline would flag, suppress the smell.
  • Always a judgement call. Each smell is a labelled heuristic ("possible Feature Envy"), never a hard violation — and, like any standard here, skip anything tooling already enforces.
Each smell reads what it ishow to fix; match it against the diff:
  • Mysterious Name — a function, variable, or type whose name doesn't reveal what it does or holds. → rename it; if no honest name comes, the design's murky.
  • Duplicated Code — the same logic shape appears in more than one hunk or file in the change. → extract the shared shape, call it from both.
  • Feature Envy — a method that reaches into another object's data more than its own. → move the method onto the data it envies.
  • Data Clumps — the same few fields or params keep travelling together (a type wanting to be born). → bundle them into one type, pass that.
  • Primitive Obsession — a primitive or string standing in for a domain concept that deserves its own type. → give the concept its own small type.
  • Repeated Switches — the same
    switch
    /
    if
    -cascade on the same type recurs across the change. → replace with polymorphism, or one map both sites share.
  • Shotgun Surgery — one logical change forces scattered edits across many files in the diff. → gather what changes together into one module.
  • Divergent Change — one file or module is edited for several unrelated reasons. → split so each module changes for one reason.
  • Speculative Generality — abstraction, parameters, or hooks added for needs the spec doesn't have. → delete it; inline back until a real need shows.
  • Message Chains — long
    a.b().c().d()
    navigation the caller shouldn't depend on. → hide the walk behind one method on the first object.
  • Middle Man — a class or function that mostly just delegates onward. → cut it, call the real target direct.
  • Refused Bequest — a subclass or implementer that ignores or overrides most of what it inherits. → drop the inheritance, use composition.
仓库中所有记录代码编写规范的文件,例如
CODING_STANDARDS.md
CONTRIBUTING.md
除了仓库中已文档化的标准外,标准维度始终遵循以下代码异味基准——这是一组固定的Fowler代码异味(来自《Refactoring》第3章),即使仓库没有任何文档化标准也适用。该基准遵循两条规则:
  • 仓库标准优先:仓库中已文档化的标准始终优先;如果仓库标准认可某一内容,而基准将其标记为异味,则忽略该异味。
  • 始终需主观判断:每个异味都是带标签的启发式判断(如“可能存在Feature Envy”),而非硬性违规——并且,与这里的任何标准一样,跳过已由工具强制执行的内容。
每个异味都包含“是什么”→“如何修复”的说明,需与代码差异进行匹配:
  • Mysterious Name(晦涩命名)——函数、变量或类型的名称无法体现其功能或用途。→ 重命名;如果找不到合适的名称,说明设计存在模糊性。
  • Duplicated Code(重复代码)——相同的逻辑结构出现在变更中的多个代码块或文件中。→ 提取共享逻辑,在两处调用该逻辑。
  • Feature Envy(特性羡慕)——某个方法更多地访问其他对象的数据,而非自身数据。→ 将该方法移至它所访问的数据所属的对象中。
  • Data Clumps(数据泥团)——相同的几个字段或参数总是一起出现(意味着需要创建一个新类型)。→ 将它们打包成一个类型,传递该类型。
  • Primitive Obsession(原始类型痴迷)——使用原始类型或字符串来代表本应拥有独立类型的领域概念。→ 为该概念创建一个独立的小型类型。
  • Repeated Switches(重复分支)——针对同一类型的相同
    switch
    /
    if
    分支结构在变更中多次出现。→ 用多态替换,或使用一个两处共享的映射。
  • Shotgun Surgery(霰弹式修改)——一项逻辑变更需要对差异中的多个文件进行零散修改。→ 将相关变更整合到一个模块中。
  • Divergent Change(发散式修改)——一个文件或模块因多个不相关的原因被修改。→ 拆分该模块,使每个模块仅因一个原因变更。
  • Speculative Generality(过度抽象)——为需求中不存在的场景添加了抽象、参数或钩子。→ 删除这些内容;直到有实际需求时再重新添加。
  • Message Chains(消息链)——过长的
    a.b().c().d()
    链式调用,调用者不应依赖这种导航方式。→ 在第一个对象上添加一个方法,隐藏链式调用过程。
  • Middle Man(中间人)——某个类或函数主要仅负责转发调用。→ 删除它,直接调用实际目标。
  • Refused Bequest(拒绝继承)——子类或实现类忽略或覆盖了大部分继承的内容。→ 放弃继承,使用组合。

4. Spawn both sub-agents in parallel

4. 并行启动两个子Agent

Standards sub-agent prompt — include:
  • The full diff command and commit list.
  • The list of standards-source files you found in step 3, plus the smell baseline from step 3 pasted in full — the sub-agent has no other access to it.
  • The brief: "Report — per file/hunk where relevant — (a) every place the diff violates a documented standard: cite the standard (file + the rule); and (b) any baseline smell you spot: name it and quote the hunk. Distinguish hard violations from judgement calls — documented-standard breaches can be hard, but baseline smells are always judgement calls, and a documented repo standard overrides the baseline. Skip anything tooling enforces. Under 400 words."
Spec sub-agent prompt — include:
  • The diff command and commit list.
  • The path or fetched contents of the spec.
  • The brief: "Report: (a) requirements the spec asked for that are missing or partial; (b) behaviour in the diff that wasn't asked for (scope creep); (c) requirements that look implemented but where the implementation looks wrong. Quote the spec line for each finding. Under 400 words."
If the spec is missing, skip the Spec sub-agent and note this in the final report.
标准维度子Agent提示词——需包含:
  • 完整的差异命令和提交列表。
  • 步骤3中找到的标准源文件列表,加上步骤3中的代码异味基准完整内容——子Agent无法访问其他外部内容。
  • 任务说明:“报告——针对相关的文件/代码块——(a) 差异中所有违反已文档化标准的位置:引用标准(文件+规则);(b) 你发现的任何基准异味:命名异味并引用代码块。区分硬性违规与主观判断——违反已文档化标准属于硬性违规,但基准异味始终是主观判断,且仓库已文档化的标准优先于基准。跳过已由工具强制执行的内容。报告字数不超过400字。”
需求维度子Agent提示词——需包含:
  • 差异命令和提交列表。
  • 需求文件的路径或获取到的内容。
  • 任务说明:“报告:(a) 需求中要求但未实现或部分实现的内容;(b) 差异中存在但未在需求中提及的行为(范围蔓延);(c) 看似已实现但存在错误的需求。每个发现需引用需求中的对应行。报告字数不超过400字。”
如果缺少需求文件,跳过需求维度子Agent,并在最终报告中注明这一点。

5. Aggregate

5. 汇总结果

Present the two reports under
## Standards
and
## Spec
headings, verbatim or lightly cleaned. Do not merge or rerank findings — the two axes are deliberately separate (see Why two axes).
End with a one-line summary: total findings per axis, and the worst issue within each axis (if any). Don't pick a single winner across axes — that's the reranking the separation exists to prevent.
将两份报告分别放在
## 标准维度
## 需求维度
标题下,可直接使用原文或稍作整理。不要合并或重新排序发现的问题——两个维度是刻意分开的(参见“为什么采用双维度”)。
最后添加一行总结:每个维度的问题总数,以及每个维度中最严重的问题(如果存在)。不要在两个维度中选出一个“最严重”——这正是分开两个维度所要避免的重新排序行为。

Why two axes

为什么采用双维度

A change can pass one axis and fail the other:
  • Code that follows every standard but implements the wrong thing → Standards pass, Spec fail.
  • Code that does exactly what the issue asked but breaks the project's conventions → Spec pass, Standards fail.
Reporting them separately stops one axis from masking the other.
一项代码变更可能通过其中一个维度的审查,但未通过另一个:
  • 代码遵循所有标准,但实现了错误的功能 → 标准维度通过,需求维度未通过
  • 代码完全符合需求,但违反了项目约定 → 需求维度通过,标准维度未通过
分开报告两个维度的结果,可以避免一个维度的结果掩盖另一个维度的问题。