review-diff

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
<!-- markdownlint-disable-file MD041 -->
STARTER_CHARACTER = ⚡
<!-- markdownlint-disable-file MD041 -->
STARTER_CHARACTER = ⚡

Diff Review

差异审查

Review everything that differs from
main
across 9 perspectives, each by one subagent. The nine areas' findings then run through the same scripted collate, merge, rank, and isolated-judge verification chain review-deep uses. No arguments.
Available on Claude Code (through this plugin) and Codex. Fails preflight by name on OpenCode and Hermes Agent, neither of which can dispatch a subagent to a named reviewer type.
This skill runs
context: fork
, dispatched as a subagent with no user present to answer a prompt. Never pause before dispatch to confirm scope, cost, or model spend; the diff is whatever it is.
从 9 个维度审查相对于
main
的所有差异,每个维度由一个 subagent 负责。随后,9 个领域的结果将经过与 review-deep 相同的脚本化汇总、合并、排序和隔离 judge 验证链处理。无需参数。
可通过 Claude Code(经由此插件)和 Codex 使用。在 OpenCode 和 Hermes Agent 上会按名称在 preflight 阶段失败,因为二者都无法将 subagent 派发给指定类型的 reviewer。
此 skill 以
context: fork
运行,作为 subagent 被派发,期间没有用户可回答提示词。派发前绝不暂停以确认范围、成本或模型消耗;审查对象就是当前 diff。

Step 1: Preflight

第 1 步:Preflight

Determine your harness. In Claude Code,
HARNESS=claude
and
PLUGIN_ROOT
is this plugin's root, two directories up from this SKILL.md. In Codex,
HARNESS=codex
;
PLUGIN_ROOT
does not apply there, since the nine Codex reviewer agents live at a fixed path, not inside a plugin.
bash
S="${CLAUDE_SKILL_DIR}/../review-deep/scripts"   # replace ${CLAUDE_SKILL_DIR} with this SKILL.md's own directory on a non-Claude harness
[ -f "$S/init_run.py" ] || { echo "scripts not found at $S"; exit 1; }
HARNESS=claude
PLUGIN_ROOT="$(cd "${CLAUDE_SKILL_DIR}/../.." && pwd)"

OUT=$(python3 "$S/preflight.py" --tier diff --harness "$HARNESS" --plugin-root "$PLUGIN_ROOT")
STATUS=$?
echo "$OUT"
[ "$STATUS" -eq 0 ] || exit 1
LABEL=$(echo "$OUT" | sed -n 's/^LABEL=//p')
AGENT_PREFIX=$(echo "$OUT" | sed -n 's/^AGENT_PREFIX=//p')
preflight.py
checks every tool, agent file, and ref this skill needs (including that
origin/main
or
main
resolves), prints one
PASS
or
FAIL
line per check, and exits 1 on any
FAIL
. On success it also prints
LABEL
(the reviewer source name behind
$LABEL-<area>.md
) and
AGENT_PREFIX
(the namespace prefix for the nine subagent types;
clanker-code-review:
in Claude Code, empty in Codex). The
$S
guard catches a partial or corrupted plugin or skill install.
确定 harness。在 Claude Code 中,
HARNESS=claude
,
PLUGIN_ROOT
是此插件的根目录,即从该
SKILL.md
向上两级。在 Codex 中,
HARNESS=codex
;
PLUGIN_ROOT
不适用,因为九个 Codex reviewer agent 位于固定路径,而不是插件内部。
bash
S="${CLAUDE_SKILL_DIR}/../review-deep/scripts"   # replace ${CLAUDE_SKILL_DIR} with this SKILL.md's own directory on a non-Claude harness
[ -f "$S/init_run.py" ] || { echo "scripts not found at $S"; exit 1; }
HARNESS=claude
PLUGIN_ROOT="$(cd "${CLAUDE_SKILL_DIR}/../.." && pwd)"

OUT=$(python3 "$S/preflight.py" --tier diff --harness "$HARNESS" --plugin-root "$PLUGIN_ROOT")
STATUS=$?
echo "$OUT"
[ "$STATUS" -eq 0 ] || exit 1
LABEL=$(echo "$OUT" | sed -n 's/^LABEL=//p')
AGENT_PREFIX=$(echo "$OUT" | sed -n 's/^AGENT_PREFIX=//p')
preflight.py
检查此 skill 所需的每个工具、agent 文件和 ref(包括
origin/main
或
main
能否解析),每项检查打印一行
PASS
或
FAIL
,任何
FAIL
都以 1 退出。成功时还会打印
LABEL
(
$LABEL-<area>.md
背后的 reviewer 来源名称)和
AGENT_PREFIX
(九种 subagent 类型的命名空间前缀;在 Claude Code 中为
clanker-code-review:
,在 Codex 中为空)。
$S
守卫可捕获插件或 skill 的部分安装或损坏安装。

Step 2: Resolve the Base

第 2 步:解析基准

bash
PROJECT_ROOT=$(git rev-parse --show-toplevel)

BASE_REF=$(git rev-parse --verify --quiet origin/main || git rev-parse --verify --quiet main)
if [ -z "$BASE_REF" ]; then
  echo "No main branch found (tried origin/main and main)"
  exit 1
fi

BASE=$(git merge-base HEAD "$BASE_REF")
bash
PROJECT_ROOT=$(git rev-parse --show-toplevel)

BASE_REF=$(git rev-parse --verify --quiet origin/main || git rev-parse --verify --quiet main)
if [ -z "$BASE_REF" ]; then
  echo "No main branch found (tried origin/main and main)"
  exit 1
fi

BASE=$(git merge-base HEAD "$BASE_REF")

On main itself the merge base is HEAD, which would hide committed work.

On main itself the merge base is HEAD, which would hide committed work.

Fall back to the previous commit so the branch tip is still under review.

Fall back to the previous commit so the branch tip is still under review.

if [ "$BASE" = "$(git rev-parse HEAD)" ]; then BASE=$(git rev-parse --verify --quiet HEAD~1 || echo "$BASE") fi
echo "BASE=$BASE"
undefined
if [ "$BASE" = "$(git rev-parse HEAD)" ]; then BASE=$(git rev-parse --verify --quiet HEAD~1 || echo "$BASE") fi
echo "BASE=$BASE"
undefined

Step 3: Collect the Delta

第 3 步:收集差异

bash
git log --oneline "${BASE}"..HEAD
git diff "${BASE}" --find-renames --stat
git diff "${BASE}" --find-renames
git status --porcelain
git ls-files --others --exclude-standard
git diff "$BASE"
carries no
..HEAD
, so it spans the merge base through the working tree. Committed, staged, and unstaged changes all land in one diff.
--find-renames
surfaces renames as
R<score>
entries with both paths so a pure rename does not collapse into an empty diff.
git status --porcelain
is the authoritative list of every modified, added, deleted, renamed, copied, and untracked entry.
ls-files --others
surfaces untracked files, which have no diff representation. Files matching
.gitignore
are excluded.
Stop when all five signals are empty (the commit log, the diffstat, the diff, the status, and the untracked list). Report
No changes against main
and stop.
bash
git log --oneline "${BASE}"..HEAD
git diff "${BASE}" --find-renames --stat
git diff "${BASE}" --find-renames
git status --porcelain
git ls-files --others --exclude-standard
git diff "$BASE"
不带
..HEAD
,因此其范围从 merge base 贯穿 working tree。已提交、已暂存和未暂存的更改都包含在一个 diff 中。
--find-renames
会将重命名显示为
R<score>
条目并同时列出两个路径,因此纯重命名不会缩减为空白 diff。
git status --porcelain
是所有已修改、新增、删除、重命名、复制和未跟踪条目的权威列表。
ls-files --others
会显示没有 diff 表示形式的未跟踪文件。匹配
.gitignore
的文件会被排除。
当五个信号全部为空时停止,即 commit log、diffstat、diff、status 和未跟踪文件列表均为空。报告
No changes against main
并停止。

Step 4: Start the Run

第 4 步:启动运行

bash
python3 "$S/init_run.py" --kind diff --base "$BASE" "$PROJECT_ROOT" "$PROJECT_ROOT" "$PROJECT_ROOT/.llmtmp/review-diff"
Prints
RUN_DIR
and
COMMIT
.
RUN_DIR
is
${XDG_CACHE_HOME:-~/.cache}/review-diff/<repo>-<commit12>
, outside the repository. On a clean working tree
COMMIT
is HEAD. On a dirty one,
init_run.py
snapshots the working tree into an unreferenced commit over HEAD, so the reviewers, the
git diff
below, and the scripted chain's judges all see the exact same uncommitted edits.
run.json
carries
kind: diff
,
base: $BASE
, and
ticket_label: review-diff
.
bash
python3 "$S/init_run.py" --kind diff --base "$BASE" "$PROJECT_ROOT" "$PROJECT_ROOT" "$PROJECT_ROOT/.llmtmp/review-diff"
init_run.py
会打印
RUN_DIR
和
COMMIT
。
RUN_DIR
位于
${XDG_CACHE_HOME:-~/.cache}/review-diff/<repo>-<commit12>
,在仓库之外。working tree 干净时,
COMMIT
为 HEAD。存在未提交更改时,
init_run.py
会在 HEAD 之上将 working tree 快照为无引用 commit,因此 reviewers、后续的
git diff
以及脚本链的 judges 都能看到完全相同的未提交编辑。
run.json
记录
kind: diff
、
base: $BASE
和
ticket_label: review-diff
。

Step 5: Materialize the Input

第 5 步:物化输入

Write the whole change set to one file. Reviewers hold
Read
but no
Bash
, so they cannot run git themselves. Passing the diff through nine prompts costs nine copies of it in orchestrator output; writing it once and having each reviewer read it costs one.
bash
STATE_DIR="$PROJECT_ROOT/.llmtmp/review-diff"
mkdir -p "$STATE_DIR"
find "$STATE_DIR" -mindepth 1 -delete
INPUT="$STATE_DIR/input.md"

{
  echo "# Change set vs merge-base ${BASE}, reviewed at commit ${COMMIT}"
  echo; echo "## Commits"; git log --oneline "${BASE}"..HEAD
  echo; echo "## Status"; git status --porcelain
  echo; echo "## Diffstat"; git diff "${BASE}" "${COMMIT}" --find-renames --stat
  echo; echo "## Diff"; git diff "${BASE}" "${COMMIT}" --find-renames
} > "$INPUT"

for f in $(git ls-files --others --exclude-standard); do
  { echo; echo "## Untracked file: $f"; cat -n "$f"; } >> "$INPUT"
done

wc -c "$INPUT"
git diff "$BASE" "$COMMIT"
replaces the old
git diff "$BASE"
against the working tree: reviewers must see exactly what the scripted chain's judges will later check out and verify, and
$COMMIT
(a snapshot when the tree is dirty, HEAD otherwise) is that same, fixed point. Untracked files carry no diff representation, so their full contents are appended with line numbers.
mkdir -p
then
find -delete
rather than
rm -rf
. A
safe-rm
shim on
PATH
(as in some dotfiles setups) moves paths to Trash and exits non-zero on a missing path even under
-f
, which breaks the wipe on a first run.
将整个变更集写入一个文件。Reviewer 拥有
Read
但没有
Bash
,因此无法自行运行 git。将 diff 通过九个提示词传递会在 orchestrator 输出中产生九份副本;只写一次并让每个 reviewer 读取则只需一份。
bash
STATE_DIR="$PROJECT_ROOT/.llmtmp/review-diff"
mkdir -p "$STATE_DIR"
find "$STATE_DIR" -mindepth 1 -delete
INPUT="$STATE_DIR/input.md"

{
  echo "# Change set vs merge-base ${BASE}, reviewed at commit ${COMMIT}"
  echo; echo "## Commits"; git log --oneline "${BASE}"..HEAD
  echo; echo "## Status"; git status --porcelain
  echo; echo "## Diffstat"; git diff "${BASE}" "$COMMIT" --find-renames --stat
  echo; echo "## Diff"; git diff "${BASE}" "$COMMIT" --find-renames
} > "$INPUT"

for f in $(git ls-files --others --exclude-standard); do
  { echo; echo "## Untracked file: $f"; cat -n "$f"; } >> "$INPUT"
done

wc -c "$INPUT"
git diff "$BASE" "$COMMIT"
取代了原先针对 working tree 的
git diff "$BASE"
:reviewers 必须看到与脚本链 judges 后续检出并验证的内容完全一致,而
$COMMIT
(working tree 脏时为快照,否则为 HEAD)正是同一个固定点。未跟踪文件没有 diff 表示形式,因此其完整内容会带行号追加。
使用
mkdir -p
后接
find -delete
,而不是
rm -rf
。某些 dotfiles 配置中
PATH
上的
safe-rm
shim 会将路径移至 Trash,并在路径不存在时即使使用
-f
也会返回非零状态,从而导致首次运行时清理失败。

Step 6: Build the Ledger

第 6 步:构建台账

bash
python3 "$S/ledger.py" "$STATE_DIR" --diff "$PROJECT_ROOT" "$BASE" "$COMMIT"
python3 "$S/partition.py" "$STATE_DIR"
ledger.py --diff
runs
git diff --name-only --no-renames --diff-filter=d
between
$BASE
and
$COMMIT
, so a rename gives its new path once and a deletion is dropped. The reviewers work from
$INPUT
directly, not from
partition.py
's components;
report.py
's coverage section is what actually reads them.
bash
python3 "$S/ledger.py" "$STATE_DIR" --diff "$PROJECT_ROOT" "$BASE" "$COMMIT"
python3 "$S/partition.py" "$STATE_DIR"
ledger.py --diff
在
$BASE
与
$COMMIT
之间运行
git diff --name-only --no-renames --diff-filter=d
,因此重命名只以新路径出现一次,删除项则被丢弃。Reviewers 直接基于
$INPUT
工作,而不是使用
partition.py
的组件;实际读取这些组件的是
report.py
的 coverage 部分。

Step 7: Dispatch 9 Reviewers in Parallel

第 7 步:并行派发 9 个 Reviewer

Issue all 9 Agent calls in a single tool block with
run_in_background: false
.
Subagents default to running in the background. A backgrounded fan-out delivers its results in later turns, so Step 8 would find nothing to consolidate. Synchronous dispatch in one block is what makes the fleet parallel and the report possible in this turn.
Agent typeArea
${AGENT_PREFIX}reviewer-architecture
architecture
${AGENT_PREFIX}reviewer-correctness
correctness
${AGENT_PREFIX}reviewer-data
data
${AGENT_PREFIX}reviewer-ops
ops
${AGENT_PREFIX}reviewer-performance
performance
${AGENT_PREFIX}reviewer-quality
quality
${AGENT_PREFIX}reviewer-security
security
${AGENT_PREFIX}reviewer-solid
solid
${AGENT_PREFIX}reviewer-testing
testing
Dispatch all 9 every run. Do not skip a perspective based on which files changed.
Every prompt is identical apart from nothing. Send this, with
<INPUT>
and
<PROJECT_ROOT>
substituted:
text
Read <INPUT>. It holds the commit log, porcelain status, diffstat, full diff
against the merge-base with main, and the full contents of every untracked
file. That is the complete change set under review.

The project root is <PROJECT_ROOT>. Every path in the diff is relative to it.
Open any file you need in that tree to confirm a finding and to confirm the
line number you cite.

Audit this change set. Apply the Ownership table in your instructions: report
only defect classes you own, and stay silent on the rest.

Write your findings to <STATE_DIR>/<LABEL>-<area>.md. Use an H2 header
followed by findings or exactly "No findings."
The brief stays short on purpose. Severity, citation format, output shape, and lane discipline all live in the agent definitions, so one edit there changes every caller.
Do not pack repomix. The input file holds everything.
在单个 tool block 中发出全部 9 次 Agent 调用,并设置
run_in_background: false
。
Subagent 默认在后台运行。后台 fan-out 会在后续轮次才返回结果,因此第 8 步将找不到可汇总的内容。在一个 block 中同步派发,才能让这组任务并行执行,并在本轮生成报告。
Agent type领域
${AGENT_PREFIX}reviewer-architecture
架构
${AGENT_PREFIX}reviewer-correctness
正确性
${AGENT_PREFIX}reviewer-data
数据
${AGENT_PREFIX}reviewer-ops
运维
${AGENT_PREFIX}reviewer-performance
性能
${AGENT_PREFIX}reviewer-quality
质量
${AGENT_PREFIX}reviewer-security
安全
${AGENT_PREFIX}reviewer-solid
SOLID
${AGENT_PREFIX}reviewer-testing
测试
每次运行都要派发全部 9 个。不要因为某些文件未发生变化而跳过任何维度。
所有提示词都完全相同,没有任何差异。发送以下提示词,其中
<INPUT>
和
<PROJECT_ROOT>
已替换:
text
Read <INPUT>. It holds the commit log, porcelain status, diffstat, full diff
against the merge-base with main, and the full contents of every untracked
file. That is the complete change set under review.

The project root is <PROJECT_ROOT>. Every path in the diff is relative to it.
Open any file you need in that tree to confirm a finding and to confirm the
line number you cite.

Audit this change set. Apply the Ownership table in your instructions: report
only defect classes you own, and stay silent on the rest.

Write your findings to <STATE_DIR>/<LABEL>-<area>.md. Use an H2 header
followed by findings or exactly "No findings."
提示词有意保持简短。严重程度、引用格式、输出结构和 lane 约束均定义在 agent definitions 中,因此只需修改一处即可影响所有调用方。
不要打包 repomix。输入文件包含全部内容。

Step 8: Check and Re-dispatch

第 8 步:检查并重新派发

bash
python3 "$S/check_reviews.py" "$RUN_DIR" "$LABEL"
Prints one
PASS
or
FAIL
line per area and exits 1 when any fails: the file is missing, has no H2, has no finding and is not exactly
No findings.
, or holds a bullet that parses as neither
normalize.FULL
nor
normalize.BARE
. Two causes are common here: the agent died on a transient API error and wrote nothing, or a hook blocked its read of
$INPUT
and it wrote a refusal instead. Re-dispatch each failing area's agent once, using the same prompt as Step 7, then run
check_reviews.py
again. A second failure is reported as not reviewed in Step 9, not retried further.
Editing an agent definition does not affect a session already running. Claude Code detects agent files being added or removed, but a session keeps the body it loaded at startup, and a definition reached through a symlink (as dotbot installs them) is not re-read on edit. Restart the session after changing a reviewer.
bash
python3 "$S/check_reviews.py" "$RUN_DIR" "$LABEL"
每个领域打印一行
PASS
或
FAIL
,任一失败即以 1 退出:文件缺失、没有 H2、没有 finding 且并非恰好为
No findings.
,或者包含无法解析为
normalize.FULL
或
normalize.BARE
的 bullet。常见原因有两个:agent 因临时 API 错误退出且没有写入任何内容;或者某个 hook 阻止其读取
$INPUT
,导致它写入拒绝信息。使用与第 7 步相同的提示词,为每个失败领域重新派发一次 agent,然后再次运行
check_reviews.py
。第二次失败会在第 9 步中报告为未审查,不再继续重试。
编辑 agent definition 不会影响已在运行的 session。Claude Code 可以检测到 agent 文件的新增或删除,但 session 会保留启动时加载的正文,而通过 symlink 访问的 definition(例如 dotbot 的安装方式)在编辑后不会重新读取。修改 reviewer 后需重启 session。

Step 9: Run the Scripted Chain and Report

第 9 步:运行脚本链并生成报告

Run each model stage as a background Bash call; its pool returns when every call has finished, and the completion notification is the signal to continue. Never poll a running stage with
sleep
. Run the stage command itself as the background call. Never detach it with
nohup
or a trailing
&
, and never wait on a log line with
tail -f | grep -m1
.
tail
exits only when it next writes, so the call hangs until its timeout once the log gets its last line.
bash
python3 "$S/checkout.py" "$RUN_DIR"
python3 "$S/normalize.py" "$RUN_DIR"
python3 "$S/collate.py" "$RUN_DIR"         # one model call per component, background
uv run --with scikit-learn --with scipy --with numpy python "$S/windows.py" "$RUN_DIR"
python3 "$S/merge.py" "$RUN_DIR"           # one model call per similarity window, background
python3 "$S/rank.py" "$RUN_DIR"
python3 "$S/verify.py" "$RUN_DIR"          # one model call per Critical or High issue, background
python3 "$S/report.py" "$RUN_DIR"
A diff's scope is usually small enough to afford verifying Medium-severity issues too: pass
--floor Medium
to
verify.py
(
python3 "$S/verify.py" "$RUN_DIR" --floor Medium
) to widen it past the Critical/High default.
Report the counts from
report.md
, the confirmed issues, and
RUN_DIR
to the operator. The run directory is valid input to the review-tickets skill, with ticket label
review-diff
.
将每个 model stage 作为后台 Bash 调用运行;其 pool 会在所有调用完成后返回,而完成通知才是继续执行的信号。绝不要用
sleep
轮询正在运行的 stage。应将 stage 命令本身作为后台调用运行。绝不要用
nohup
或末尾的
&
将其分离,也绝不要通过
tail -f | grep -m1
等待某一行日志。
tail
只有在下一次写入时才会退出,因此日志写完最后一行后,调用会一直挂起直到超时。
bash
python3 "$S/checkout.py" "$RUN_DIR"
python3 "$S/normalize.py" "$RUN_DIR"
python3 "$S/collate.py" "$RUN_DIR"         # one model call per component, background
uv run --with scikit-learn --with scipy --with numpy python "$S/windows.py" "$RUN_DIR"
python3 "$S/merge.py" "$RUN_DIR"           # one model call per similarity window, background
python3 "$S/rank.py" "$RUN_DIR"
python3 "$S/verify.py" "$RUN_DIR"          # one model call per Critical or High issue, background
python3 "$S/report.py" "$RUN_DIR"
Diff 的范围通常足够小,因此也可以验证 Medium 严重程度的问题:向
verify.py
传入
--floor Medium
(
python3 "$S/verify.py" "$RUN_DIR" --floor Medium
),将验证范围扩展到 Critical/High 默认级别之外。
向操作者报告
report.md
中的计数、已确认的问题以及
RUN_DIR
。该 run directory 是 review-tickets skill 的有效输入,ticket label 为
review-diff
。

Tests

测试

See review-deep's Tests section. The same
evals/
at the root of this plugin's repository covers every skill here, including
unit/preflight
for this skill's preflight tier.
见 review-deep 的 Tests 部分。此插件仓库根目录下的同一套
evals/
覆盖这里的所有 skill,包括此 skill 的 preflight tier 对应的
unit/preflight
。