mcpField
R
review-diff

review-diff

github.com/jimwellerテスト・品質19 回インストール
リポジトリ

review-diff について

review-diff は、Claude Code と Codex 向けのコードレビュー用スキルです。main に対するコミット済み変更と作業ツリーの差分を、9 つの観点でレビューし、スクリプトで指摘を集約、順位付け、検証します。

主な機能

  1. 01main に対する全変更のレビュー
  2. 029 つの観点で並行レビュー
  3. 03失敗したレビューの確認と再依頼
  4. 04スクリプトによる集約、統合、順位付け、検証

活用シーン

  1. 01マージ前のコミット済み・未コミット変更の確認
  2. 02アーキテクチャ、セキュリティ、テスト面の問題確認
  3. 03review-tickets での後続作業向けレビュー結果の作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jimweller/clanker-code-review-plugin --skill review-diff

インストール後、Claude Code で/review-diffを入力して読み込まれたか確認します。

詳細

STARTER_CHARACTER = ⚡

差分レビュー

main との差分を、サブエージェントごとに1つ、9つの観点からすべてレビューします。9つの領域の指摘事項は、その後、review-deep で使用されるものと同じ、スクリプトによる集約、統合、順位付け、独立した判定による検証のチェーンにかけられます。引数はありません。

Claude Code(このプラグイン経由)と Codex で利用できます。OpenCode と Hermes Agent では、名前を指定したレビュアータイプにサブエージェントをディスパッチできないため、名前を示して事前チェックに失敗します。

このスキルは context: fork を実行し、プロンプトに答えるユーザーがいない状態でサブエージェントとしてディスパッチされます。スコープ、コスト、モデルの使用量を確認するために、ディスパッチ前に決して一時停止しないでください。差分はそのままの状態でレビューします。

ステップ 1:事前チェック

実行環境を判定します。Claude Code では、HARNESS=claude とし、PLUGIN_ROOT はこのプラグインのルート(この SKILL.md から2つ上のディレクトリ)です。Codex では、HARNESS=codex とします。9つの Codex レビュアーエージェントはプラグイン内ではなく固定パスにあるため、PLUGIN_ROOT は適用されません。

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 は、このスキルに必要なすべてのツール、エージェントファイル、参照先をチェックします(origin/main または main が解決されることも含みます)。各チェックにつき PASS または FAIL の行を1つ出力し、FAIL があれば終了コード 1 で終了します。成功時には、$LABEL-<area>.md の元となるレビュアー名である LABEL と、9つのサブエージェントタイプの名前空間プレフィックスである AGENT_PREFIX も出力します。Claude Code では clanker-code-review:、Codex では空です。$S ガードは、プラグインまたはスキルのインストールが不完全、あるいは破損している場合を検出します。

ステップ 2:ベースを解決する

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.
# 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"

ステップ 3:差分を収集する

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 がないため、マージベースから作業ツリーまでの差分が対象になります。コミット済み、ステージ済み、未ステージの変更は、すべて1つの差分に含まれます。--find-renames は、純粋な名前変更が空の差分にならないよう、両方のパスを含む R<score> エントリとして名前変更を表示します。git status --porcelain は、変更、追加、削除、名前変更、コピー、未追跡のすべてのエントリを示す正確な一覧です。差分として表現されない未追跡ファイルは、ls-files --others で検出します。.gitignore に一致するファイルは除外されます。

5つのシグナル(コミットログ、差分統計、差分、ステータス、未追跡ファイル一覧)がすべて空の場合は、ここで停止します。No changes against main と報告して終了します。

ステップ 4:実行を開始する

python3 "$S/init_run.py" --kind diff --base "$BASE" "$PROJECT_ROOT" "$PROJECT_ROOT" "$PROJECT_ROOT/.llmtmp/review-diff"

RUN_DIR と COMMIT を出力します。RUN_DIR はリポジトリの外部にある ${XDG_CACHE_HOME:-~/.cache}/review-diff/<repo>-<commit12> です。作業ツリーがクリーンな場合、COMMIT は HEAD です。作業ツリーに変更がある場合、init_run.py は作業ツリーのスナップショットを HEAD の上に未参照コミットとして作成します。そのため、レビュアー、後述の git diff、スクリプトによるチェーンの判定者は、すべて同じ未コミットの編集内容を確認できます。run.json には kind: diff、base: $BASE、ticket_label: review-diff が設定されます。

ステップ 5:入力を作成する

変更セット全体を1つのファイルに書き込みます。レビュアーには Read がありますが Bash はないため、自分で git を実行できません。差分を9つのプロンプトに渡すと、オーケストレーターの出力に差分が9回分必要になります。1回だけ書き込み、各レビュアーがそれを読むようにすれば、必要なのは1回分です。

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" は、作業ツリーを対象とする以前の git diff "$BASE" を置き換えます。レビュアーは、スクリプトによるチェーンの判定者が後でチェックアウトして検証する内容と完全に同じものを確認する必要があります。作業ツリーに変更がある場合はスナップショット、ない場合は HEAD である $COMMIT が、その固定された基準点です。未追跡ファイルは差分として表現されないため、行番号を付けて内容全体を追加します。

rm -rf ではなく、mkdir -p の後に find -delete を使います。一部の dotfiles セットアップのように、PATH 上の safe-rm シムがパスをゴミ箱に移動し、-f を指定していても存在しないパスに対してゼロ以外の終了コードを返す場合、初回実行時に消去処理が失敗するためです。

ステップ 6:台帳を作成する

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 を実行します。そのため、名前変更は新しいパスが1回だけ示され、削除は除外されます。レビュアーは partition.py の構成要素ではなく、直接 $INPUT を参照します。実際に構成要素を読み取るのは、report.py のカバレッジセクションです。

ステップ 7:9 人のレビュアーを並列にディスパッチする

run_in_background: false を指定して、9 つの Agent 呼び出しを1 つのツールブロック内ですべて実行します。

サブエージェントは、デフォルトでバックグラウンド実行されます。バックグラウンドでの一斉ディスパッチでは、結果が後続のターンで返されるため、ステップ 8 では統合するものが見つかりません。同じターン内で並列実行し、レポートを作成できるのは、1 つのブロック内で同期的にディスパッチした場合です。

エージェントタイプ領域
${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-solidSOLID
${AGENT_PREFIX}reviewer-testingテスト

実行のたびに、9 つすべてをディスパッチします。変更されたファイルに応じて、視点を省略してはいけません。

すべてのプロンプトは完全に同一です。<INPUT> と <PROJECT_ROOT> を置き換えて、次の内容を送信します。

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."

ブリーフを意図的に短くしています。重大度、引用形式、出力形式、担当範囲の規律はすべてエージェント定義に記載されているため、そこを 1 か所編集すれば、すべての呼び出し元に反映されます。

repomix を詰め込まないでください。入力ファイルに必要なものがすべて含まれています。

ステップ 8:確認して再ディスパッチする

python3 "$S/check_reviews.py" "$RUN_DIR" "$LABEL"

領域ごとに PASS または FAIL の行を 1 つ出力し、次のいずれかに該当する場合は終了コード 1 で終了します。ファイルが存在しない、H2 がない、指摘事項がなく、内容が厳密に No findings. でもない、または normalize.FULL にも normalize.BARE にも一致しない箇条書きが含まれている。よくある原因は 2 つです。エージェントが一時的な API エラーで停止して何も書き込まなかった場合、またはフックによって $INPUT の読み取りを阻止され、代わりに拒否のメッセージを書き込んだ場合です。失敗した各領域のエージェントを、ステップ 7 と同じプロンプトで 1 回だけ再ディスパッチし、その後 check_reviews.py をもう一度実行します。2 回目も失敗した場合は、ステップ 9 で未レビューとして報告し、それ以上は再試行しません。

エージェント定義を編集しても、すでに実行中のセッションには影響しません。Claude Code はエージェントファイルの追加や削除を検出しますが、セッションが使用するのは起動時に読み込んだ内容のままです。また、(dotbot がインストールするような)シンボリックリンク経由で読み込んだ定義は、編集しても再読み込みされません。レビュアーを変更した後は、セッションを再起動してください。

ステップ 9:スクリプト化された一連の処理を実行し、報告する

各モデルのステージは、バックグラウンドの Bash 呼び出しとして実行します。すべての呼び出しが完了すると、その呼び出しのプールから制御が戻り、完了通知が続行の合図になります。実行中のステージを sleep でポーリングしてはいけません。ステージコマンド自体をバックグラウンド呼び出しとして実行してください。nohup や末尾の & でデタッチしてはいけません。また、tail -f | grep -m1 でログ行を待ってはいけません。tail は次に出力があるまで終了しないため、ログに最後の行が書き込まれると、呼び出しはタイムアウトまでハングします。

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"

差分の範囲は通常小さいため、Medium の重大度の問題も検証できます。verify.py に --floor Medium を渡すと(python3 "$S/verify.py" "$RUN_DIR" --floor Medium)、デフォルトの Critical/High より対象範囲を広げられます。

report.md の件数、確認済みの問題、RUN_DIR をオペレーターに報告します。実行ディレクトリは review-tickets スキルへの有効な入力で、チケットラベルは review-diff です。

テスト

review-deep の「Tests」セクションを参照してください。このプラグインのリポジトリのルートにある同じ evals/ が、このスキルの事前確認層向けの unit/preflight を含め、ここにあるすべてのスキルを対象としています。

コメント