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 / PRD / 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
与用户指定的固定节点之间的差异进行双维度审查:
  • 标准维度——代码是否符合本仓库的文档化编码标准?
  • 需求维度——代码是否忠实地实现了发起变更的需求工单/PRD/规格说明?
这两个维度由并行sub-agent运行,避免互相干扰上下文,之后由本skill汇总它们的审查结果。
应已为你提供问题追踪器——如果缺少
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、分支名、标签、
main
HEAD~5
等。若用户未指定,请询问具体节点。
一次性记录diff命令:
git diff <fixed-point>...HEAD
(三个点,表示基于合并基准进行对比)。同时通过
git log <fixed-point>..HEAD --oneline
记录提交列表。
在继续下一步前,确认固定节点可解析(执行
git rev-parse <fixed-point>
)且diff非空。若引用无效或diff为空,应在此步骤终止,而非进入两个并行sub-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 PRD/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. 提交消息中的需求引用(如
    #123
    Closes #45
    、GitLab的
    !67
    等)——通过
    docs/agents/issue-tracker.md
    中的流程获取详情。
  2. 用户作为参数传入的路径。
  3. docs/
    specs/
    .scratch/
    目录下与分支名或功能匹配的PRD/规格文件。
  4. 若未找到任何内容,请询问用户需求文档位置。若用户表示无需求文档,则需求维度的sub-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代码异味规则(出自《重构》第3章),即使仓库未制定任何标准也适用。该基准遵循两个规则:
  • 仓库标准优先:文档化的仓库标准始终优先级更高;若仓库标准认可某一内容,而基准将其标记为异味,则忽略该异味提示。
  • 始终需主观判断:每个异味都是带有标签的启发式判断(如“疑似特性依恋”),绝非硬性违规——且与本流程中的所有标准一样,跳过任何已由工具强制执行的规则。
每个异味包含“定义”→“修复方案”,需与diff内容匹配:
  • 模糊命名——函数、变量或类型的名称无法清晰体现其功能或用途。→ 重命名;若无法给出准确名称,则说明设计存在模糊性。
  • 重复代码——相同逻辑结构出现在变更中的多个代码块或文件中。→ 提取共享逻辑,在两处调用该逻辑。
  • 特性依恋——某个方法对其他对象数据的访问频次高于自身数据。→ 将该方法移至它所依赖的对象中。
  • 数据聚合——相同的几个字段或参数频繁一起出现(意味着需要创建一个新类型)。→ 将它们打包为一个类型,传递该类型实例。
  • 原始类型痴迷——用原始类型或字符串代表本应拥有独立类型的领域概念。→ 为该概念创建专属的小型类型。
  • 重复分支判断——针对同一类型的相同
    switch
    /
    if
    分支结构在变更中多次出现。→ 用多态替代,或使用两处共享的映射表。
  • 霰弹式修改——一项逻辑变更需要对diff中的多个文件进行零散修改。→ 将相关修改整合到一个模块中。
  • 发散式修改——单个文件或模块因多个不相关原因被修改。→ 拆分模块,使每个模块仅因单一原因变更。
  • 过度抽象——为需求文档中未提及的需求添加抽象层、参数或钩子。→ 删除该抽象;在实际需求出现前,保持代码内联。
  • 消息链——调用者依赖
    a.b().c().d()
    这类长链式导航。→ 在第一个对象中封装导航逻辑,提供单个方法供调用。
  • 中间层——某个类或函数主要仅负责转发调用。→ 移除该中间层,直接调用实际目标。
  • 拒绝继承——子类或实现类忽略或重写了大部分继承的内容。→ 放弃继承,改用组合方式。

4. Spawn both sub-agents in parallel

4. 并行启动两个sub-agent

Send a single message with two
Agent
tool calls. Use the
general-purpose
subagent for both.
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
工具调用的单条消息,两者均使用
general-purpose
子代理。
标准维度sub-agent提示词——需包含:
  • 完整的diff命令和提交列表。
  • 步骤3中找到的所有标准源文件,加上步骤3中的代码异味基准完整内容——sub-agent无法访问其他外部资源。
  • 任务说明:“按文件/代码块(如需)报告:(a) diff中所有违反文档化标准的位置:引用标准(文件+规则内容);(b) 发现的任何基准异味:命名异味并引用对应代码块。区分硬性违规与主观判断——违反文档化标准属于硬性违规,但基准异味始终是主观判断,且仓库文档化标准优先于基准。跳过任何工具已强制执行的内容。字数控制在400字以内。”
需求维度sub-agent提示词——需包含:
  • diff命令和提交列表。
  • 需求文档的路径或获取到的内容。
  • 任务说明:“报告:(a) 需求文档要求但未实现或未完全实现的内容;(b) diff中存在但需求文档未提及的行为(范围蔓延);(c) 看似已实现但存在错误的需求内容。每条发现需引用需求文档对应行。字数控制在400字以内。”
若缺少需求文档,则跳过需求维度sub-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.
一项变更可能通过其中一个维度但未通过另一个:
  • 完全符合标准但实现内容错误的代码 → 标准维度通过,需求维度未通过
  • 完全符合需求工单要求但违反项目约定的代码 → 需求维度通过,标准维度未通过
分开报告可避免一个维度的结果掩盖另一个维度的问题。