敵対的コードレビュー(Breaker × Judge)
あなたはこのスキルの実行責任者として、Breaker(反例生成器)と Judge(裁定者)を組み合わせて敵対的レビューを行う。 役割は明確に分離する:
- Breaker(あなた= Claude Opus 4.7): コードを「読む」のではなく「壊す」。反例・攻撃シナリオ・不変条件違反を生成し、可能な限り failing テストとして実行する。
- Judge(Codex gpt-5.4、
codex:rescue経由): Breaker の指摘を「真の欠陥 / 仕様未定 / 低優先度 / ノイズ」に分類し、修正コストと見合うかを裁定する。
評価関数を意図的にずらしている点が肝。指摘件数ではなく、本当の欠陥を見逃さないことと false positive を抑えること の両立を狙う。
引数の解析
$ARGUMENTS を以下のルールで解析する:
-pがある場合 →-pより後の部分を{重点観点}として保持する(Breaker persona に追加注入する)--test <cmd>がある場合 → 以降の1トークンを{テストコマンド}として保持する(自動検出より優先)--claude-judgeがある場合 →{claude judge}= true を立て、該当トークンを除去する(「## claude-judge モード」参照)- 残りの最初の位置引数を
{対象}として解析する
{対象} の判別順
| 判定 | 解釈 | 書き出しモード |
|---|---|---|
| 省略 | 未コミット変更 + 現在ブランチ vs main を対象にする |
現在ブランチに open PR が 1 件 → 有効 |
| 存在するファイル/ディレクトリパス | そのパス配下の変更のみ | 無効(PR に紐付かない) |
| 数字のみ | GitHub PR 番号として扱う(GitHub MCP ツールで diff を取得) | 有効 |
<ref>..<ref> を含む |
commit 範囲の diff | 無効(PR に紐付かない) |
ローカル or origin/ で解決できるブランチ名 |
そのブランチ vs main の差分 |
そのブランチに open PR が 1 件 → 有効 |
| 上記いずれでもない | AskUserQuestion で解釈を確認する |
解釈に応じて再判定 |
複数 PR / 0 件 / GitHub MCP 未接続などの失敗ケースの挙動は ## PR 書き出しモード の「フォールバック」を参照。
例:
/code-reviewer-adversarial— 現在の未コミット変更を対象/code-reviewer-adversarial 42— PR #42/code-reviewer-adversarial main..HEAD— 現在ブランチの全コミット/code-reviewer-adversarial src/api/ -p N+1— 特定パス + 重点観点/code-reviewer-adversarial --test "pnpm test" feature/add-foo— テストコマンド明示 + ブランチ指定
フロー
Phase 0 — 前提把握
引数解析(上記ルール)で
{対象},{テストコマンド},{重点観点}を確定変更範囲の取得 —
{対象}に応じてgit diff/ GitHub MCP の PR diff を取得し、変更ファイル・行・hunk を特定(大きい PR ではレスポンスから diff テキストと変更ファイルリストのみ保持し、メタデータは Breaker/Judge の材料として必要な範囲に絞る)書き出しモード判定 —
{対象}が PR に紐付き得るケース(省略 / ブランチ名 / PR 番号)では、mcp__plugin_github_github__list_pull_requestsで open PR を確認して書き出しモードの有効/無効を確定する。省略時の現在ブランチはgit rev-parse --abbrev-ref HEADで取得する(詳細は## PR 書き出しモード)仕様・設計の確認 — 関連 Issue / ADR / 要件ドキュメント / 会話コンテキストの設計意図を突き合わせる
テストランナーの確定:
{テストコマンド}が明示されていればそれを使う- なければ
bash ${CLAUDE_SKILL_DIR}/assets/detect-test-runner.shで自動検出 - 検出できなければ AskUserQuestion でユーザーに確認
- 確認で「不要」「わからない」等が返った場合は テスト記述のみモード(Phase 1 で反例テスト "生成" はするが "実行" はスキップ)にフォールバック
ゲート出力 — ここまでの確定値を1ブロックで表示し、ユーザーが確認できるようにする。フォーマットは以下:
対象: <対象の識別子>(PR 対象なら "PR #N \"タイトル\"" を併記) テストコマンド: <確定値 or "記述のみモード"> 重点観点: <指定があれば記載、なければ "(指定なし)"> 書き出しモード: <有効(投稿先: PR #N "タイトル")| 無効(理由: ...)>
Phase 1 — Breaker(反例生成器)
Breaker は3つの persona を順に切り替えて実行する(persona 定義は assets/breaker-personas.md):
- Security persona — 認可逸脱・インジェクション・秘密情報漏洩・TOCTOU・Confused Deputy
- Performance persona — N+1・境界外入力・競合・メモリリーク・タイムアウト・移行性能
- Specification persona — 仕様未充足・契約違反(入出力・事前事後条件)・後方互換性破壊・移行失敗
各 persona で以下の手順を実行する:
- 反例アイデアの列挙 — そのレンズで「壊れそうな入力・状態・呼び出し順序」を列挙する
- 反例テストの生成 — 最小反例を failing テストコードとして書く(言語・フレームワークは Phase 0 で確定した
{テストコマンド}に合わせる) - テストの実行 —
{テストコマンド}で生成したテストを実行するfailしたものは「検証済み反例」として採用passしたものは「仮説は外れた」として破棄(Breaker のノイズを自己フィルタする)- テスト記述のみモードではこの手順をスキップ
- 7フィールド形式で整形 —
[references/output-schema.md](references/output-schema.md)のスキーマに従い、1指摘を1レコードとして書き下す
全 persona に横断するルール:
{重点観点}が指定されていれば、各 persona の手順 1(列挙)に追加注入して優先度を上げる- そのレンズで反例が 1 件も出せなかった persona は、「検出 0 件」を明記して報告書に残す(Judge 側での監査性を保つため、空欄にせず 0 件と書く)
全 persona 終了後、Breaker は persona 単位の指摘リストをそのまま並べた Breaker 報告書 を作成する。同根の指摘が複数 persona から出た場合はタイトルに (Security+Specification) のような persona 注記だけを付け、重複統合・ノイズ除外・カテゴリ分類は Judge に委ねる(共犯化回避のため、Breaker 側で分類判断を先取りしない)。テストコードは一時領域に残し、Judge が参照可能にする。
Breaker に課す制約(ノイズ防止):
- 反証不能な指摘(「〜かもしれない」の感想)は 確信度 Low で出す。Judge がノイズとして切る想定
- 推測に頼る指摘には
[UNVERIFIED]タグを付け、実行で確認できなかったことを明記する - 「良いコード」「可読性」系は出さない(このスキルの対象外。
/code-reviewerに委ねる)
Phase 2 — Judge(裁定者)
codex:rescue スキルを呼び出し、Codex に裁定させる。呼び出しテンプレートは assets/judge-prompt.md を参照。
Judge への入力:
- 変更 diff(Phase 0 で取得)
- 仕様・設計意図の要約
- Breaker 報告書(全7フィールドの指摘リスト)
- 生成された反例テストコード(およびその実行結果)
Judge は各指摘を次の4カテゴリに分類する:
| カテゴリ | 意味 | 最終出力への扱い |
|---|---|---|
| 真の欠陥 | 仕様違反・セキュリティリスク・性能問題として妥当で、修正価値あり | 最終出力に含める |
| 仕様未定 | 仕様が曖昧で、Breaker が勝手な前提を置いている | 「仕様確認が必要」として分離 |
| 低優先度 | 妥当だが重大度が低く、修正コストに見合わない | サマリに件数のみ |
| ノイズ | 反証不能・誤解・的外れ | 最終出力から除外(件数のみ報告) |
Judge には 分類理由 と 修正コスト見積(S/M/L) を必ず付けさせる。Judge が独断で「低優先度」「ノイズ」と切ったものは、理由を読めば妥当性が検証できる形にする。
Judge 利用不能時のフォールバック
Codex(codex:rescue)が Judge として使えないケース:
- 呼び出し不能 —
codex:rescueが呼び出せない環境(Codex CLI 未設定・ネットワーク断・サブエージェント内実行など) - 復旧不能なハング — 呼び出し済みの裁定が返らず(silent death)、assets/judge-prompt.md の「運用ノート」に従った復旧(cancel →
--resume再投入)を 2 回試みても完了しない(ハング時は即フォールバックせず、必ず先に復旧を試みる)
分岐:
- Workflow 利用可 → claude-judge モードに自動でフォールバックする(「## claude-judge モード」)。独立 Opus の Breaker × Judge で裁定するため、
codex:rescue未設定の環境でもレビューを完遂できる。ただしこれは別系統モデルの独立ではなくコンテキスト隔離 + 役割分離であるため、認証 / 認可 / 決済 / スキーマ / 外部 API などの重要変更では実 Codex での再実行を推奨する旨を 1 行明示する。フォールバック前に、Phase 1(codex-judge の Breaker)が変更セットに残した.breaker-probe.を含む反例テストを取り除く({テストコマンド}が確定していると claude-judge の Breaker がそれらを再実行し、Phase 1 由来の failing テストを自身の検証済み反例〔verified: fail〕として誤帰属・二重計上するため) - Workflow も不能 → Phase 2 で停止し、Phase 3 を出力しない。次の 2 点をユーザーに提示して終了する:
- Breaker 報告書(Phase 1 の成果物をそのまま)
- 完成した Judge 呼び出し用 task 文字列(
assets/judge-prompt.mdに従って埋めたもの) ユーザーが別セッションで codex:rescue を呼ぶか、環境を整えて再実行することを案内する。
いずれの場合も Claude 自身(メインセッション)が Judge 裁定を模擬・代行してはならない(共犯化を回避するため、別系統モデルまたは隔離エージェントによる独立裁定が本スキルの核)。
Workflow も不能で停止したケースでは書き出しモードも自動的に無効化する。Breaker 単独結果を PR に投稿すると共犯化回避の原則が崩れるため、投稿ゲート(Phase 4)まで到達させない(claude-judge にフォールバックできた場合は Judge 裁定が得られるため書き出しモードは有効なまま)。
Phase 3 — 最終出力
Judge の裁定結果をもとに、次の構造で出力する:
## Adversarial Review 結果
### サマリ
- 対象: <対象の識別子>
- 真の欠陥: N 件 / 仕様未定: N 件 / 低優先度: N 件(詳細省略) / ノイズ: N 件(除外)
- テスト実行: <実行済み / 記述のみ>
- Judge: Codex (via codex:rescue)
### 🚫 真の欠陥
(7フィールド形式、Judge 分類理由つき)
### ❓ 仕様未定
(確認が必要な前提と、Breaker が置いた仮定)
### 📉 低優先度(件数のみ)
- N 件: <1行タイトル羅列>
### 🔇 ノイズ(除外理由のみ)
- N 件: <1行タイトル + 除外理由>
### 💡 修正推奨の順序
Judge の修正コスト(S/M/L)と重大度から、着手順序の提案を添える
各「真の欠陥」は references/output-schema.md の7フィールドで表示する。重大度・確信度の基準は references/severity-rubric.md を参照。
Phase 4 — PR 投稿ゲート
書き出しモードが 有効 の場合に限り、Phase 3 の最終出力を PR へ投稿する。無効なら Phase 3 の出力後にスキルを終了する。Phase 2 のフォールバック(Judge 利用不能)で Phase 3 を出さなかった場合もここには到達しない。
フロー・投稿ツール・本文テンプレート・確認ゲート UX・フォールバックは ## PR 書き出しモード に従う。
claude-judge モード(--claude-judge / Codex 不在時の自動フォールバック)
{claude judge} = true のとき、または Codex が使えず Workflow が使えるとき(「Judge 利用不能時のフォールバック」)、Phase 1(Breaker)と Phase 2(Judge)を Workflow で起動する独立 Opus エージェント 2 体に置き換える。Judge も別系統モデル(Codex)ではなく独立 Opus になるため、独立性はコンテキスト隔離 + 役割分離で担保する(別系統モデルの独立性はない → 認証 / 認可 / 決済 / スキーマ / 外部 API などの重要変更では実 Codex =デフォルトの codex-judge を推奨)。
- 単発(ループ・収束判定は持たない。このスキルはループスキルではない)。references/agent-orchestration.md の雛形(
cra-claude-judge)を起動する:- Breaker(独立 Opus / effort max) — Phase 0 で確定した
{対象}/ diff の取り方 /{テストコマンド}/{重点観点}をargs({ target, diffBase, testCmd, focus, startedAt }。startedAtは起動直前にTZ=Asia/Tokyo date '+%Y-%m-%d %H:%M:%S'で実測した開始日時)で渡す。攻撃観点・反例テスト(.breaker-probe.命名)の規律はプロンプトに内蔵(smart-issue-resolve 雛形 B の breakerPrompt からの移植) - Judge(独立 Opus・バッチ並列 + miss-finder 分離) — Breaker の反例を ≤4 件/バッチに分割し、フラット
parallelで並列に裁定する(各バッチ effort high・evidence 限定照合・4 カテゴリ〔真の欠陥 / 仕様未定 / 低優先度 / ノイズ〕・防御基準は雛形 B と同一)。Breaker 見落としの独立探索は miss-finder(別の独立 Opus / effort max・diff スコープ) が並列で担い、同じ 4 分類基準で自己分類する。一部バッチ失敗はjudgeDegraded(未裁定の反例が残る)、miss-finder 失敗はmissSearchFailed(独立探索のみ喪失・より軽い劣化)で返る
- Breaker(独立 Opus / effort max) — Phase 0 で確定した
- Phase 0(前提把握・テストランナー確定・ゲート出力)、Phase 3(最終出力)、Phase 4(PR 投稿ゲート)は codex-judge と共通で再利用する。Workflow 返却の
items(真の欠陥 / 仕様未定)・dismissed(低優先度 / ノイズの件数)を Phase 3 の構造に整形する。Phase 3 サマリの「Judge:」欄はCodex (via codex:rescue)の代わりに独立 Opus エージェント(コンテキスト隔離・バッチ並列 + miss-finder)と記す。judgeDegraded: trueは未裁定の反例が残る旨を Phase 3 出力に明記し PR 投稿ゲート前にユーザーへ確認、missSearchFailed: trueはその旨を Phase 3 出力に明記する - Phase 3 の出力・Phase 4 の投稿の前に、
.breaker-probe.を含む反例テストが変更セットに残っていれば取り除く(単発レビューの使い捨て。回帰テスト化するかは呼び出し元の判断) {claude judge}を明示せず Codex が利用可能なら、デフォルトは codex-judge(別系統モデルの独立性を優先)- Workflow の
agent()がnull(ユーザースキップ / 終端エラー)を返した場合は 1 回だけresumeFromRunIdで再開を試み、それでも失敗なら「Judge 利用不能時のフォールバック」の停止ケース(Workflow も不能)と同様に扱う
共犯化の回避: claude-judge でも Breaker と Judge は別々の fresh エージェント(互いに相手の思考を持たない)。メインセッションがどちらかを模擬・代行しない。
同期ノート
claude-judge モードの Breaker / Judge プロンプト(攻撃観点・4 分類裁定基準)は smart-issue-resolve references/agent-orchestration.md の雛形 B(sir-claude-review-set)の breakerPrompt / judgeBatchPrompt からの移植である。攻撃観点・裁定基準を変更するときは CLAUDE.md「スキル改修時の注意」の同期対象(smart-issue-resolve 雛形 B/C・smart-issue-plan sip-plan-review-set・code-reviewer の隔離モード)と揃える。Judge のバッチ並列化 + miss-finder 分離は cra 固有の構造変更(Issue #107。裁定基準の内容は不変のため resolve/plan への内容同期は不要)。Breaker はレンズ分割しない(resolve/plan の雛形 B/sip とは意図的に非対称 — 単発レビューはラウンド往復が無く、Breaker 1 本の全観点走査を維持する)。雛形のエージェントプロンプト・スキーマ description は英語、出力(指摘内容・log()・カテゴリ enum 値)は日本語で記述する(Issue #122。同期時も英語表現のまま揃える)。Opus 役のプロンプト末尾には共通の英語抑制ノート RESTRAINT_NOTE(サブエージェント起動禁止・手順外の追加検証禁止・スコープ維持・出力簡潔化。Opus 5 プロンプトガイド準拠)を TAIL_NOTE の直前に付す(同期対象 4 スキルで共通)。
PR 書き出しモード
Phase 4 で Phase 3 の最終出力を PR へ投稿する際の仕様。
投稿ツール
mcp__plugin_github_github__pull_request_review_writeを使用するmethod: "create"owner,repo:git remote get-url originからパース(HTTPS:https://github.com/foo/bar.git/ SSH:git@github.com:foo/bar.gitどちらもowner=foo,repo=bar。末尾の.gitは任意)pull_number: 対象 PR 番号event: "COMMENT"(approve / request_changes は人間レビュアーの判断に残す)body: 下記テンプレートに従って生成した markdowncomments: [](行コメントは使わない)
- PR 検出は
mcp__plugin_github_github__list_pull_requestsをowner,repo(上記と同様に origin から取得),head: <branch>,state: "open"で呼ぶ(Phase 0 の対象判別で実施)。現在ブランチはgit rev-parse --abbrev-ref HEADで取得する
投稿本文テンプレート
<!-- claude-code-review:code-reviewer-adversarial -->
> 🤖 Generated by `/code-reviewer-adversarial` — <ISO8601 タイムスタンプ>
## Adversarial Review 結果
{Phase 3 の最終出力をそのままコピーして貼る。サマリ / 🚫 真の欠陥 / ❓ 仕様未定 / 📉 低優先度 / 🔇 ノイズ / 💡 修正推奨の順序}
---
_このレビューは Claude Code スキル `/code-reviewer-adversarial` が生成しました。approve / request_changes 判断は含みません。_
- 識別マーカー
<!-- claude-code-review:code-reviewer-adversarial -->は必ず先頭に入れる(HTML コメントなので PR 表示上は不可視) - ローカル表示と PR 投稿は同じ本文を使い回す(二重生成しない)
確認ゲート
投稿前に必ず AskUserQuestion で以下を出す:
- 質問文:
"PR #<番号> にこのレビュー内容を投稿しますか?(投稿先: <PR タイトル>)" - 選択肢:
[投稿する]/[投稿しない]/[本文を修正してから投稿]
「本文を修正してから投稿」を選んだ場合、ユーザーに修正指示を求め、本文を再生成して再度確認ゲートに戻る。修正ループは最大 3 回、超えたら投稿を中止する。
成功・切り詰めの表示
- 成功:
✅ レビューを投稿しました: <Review URL>を 1 行表示 - 本文が 65,536 文字を超える場合: 反例テストコード等を
<details>で折りたたむ、もしくは末尾を切り詰めて「以降は省略(ローカル出力を参照)」と明記する。切り詰めが発生したら⚠️ 本文が長すぎたため末尾を切り詰めました。完全版はローカル出力を参照してくださいを併記する
フォールバック
| ケース | 挙動 |
|---|---|
| GitHub MCP ツール未接続 | 書き出しモード無効化。Phase 0 ゲート出力に理由を明示し、レビュー処理は通常実行 |
| 対象ブランチの open PR が 0 件(引数省略時) | 書き出しモード無効化。エラーにしない |
| 対象ブランチの open PR が複数 | AskUserQuestion で PR 番号を選ばせる(「書き出し不要」選択肢も出す) |
| 指定 PR 番号が存在しない / アクセス権なし | 書き出しモード無効化し理由を明示、レビュー処理は続行 |
| Judge(Phase 2)利用不能 | 書き出しモード自動無効化(詳細: Phase 2 の #### Judge 利用不能時のフォールバック を参照) |
| 投稿権限 403 等 | 失敗メッセージを 1 行表示、ローカル出力は残す |
| API 一時エラー | 1 回だけリトライ、再失敗で諦めて手動投稿を案内 |
| 確認ゲートで「投稿しない」 | 正常終了、ローカル出力のみ |
| 修正ループ 3 回超 | 投稿中止、最後の本文をローカルに残す |
原則: PR 書き出しが失敗してもレビュー処理自体は止めない。エラーメッセージは 1〜2 行でチャットに出し、追加の AskUserQuestion は出さない。
やらないこと
- 実装の書き直し(最小反例と修正案までに留める)
- 可読性・命名レベルの指摘(
/code-reviewerの役割) - 感想・一般論(反証可能な指摘のみ)
- Builder(実装者)との対話ループ(このスキルの入力は実装済みコードのみ。対話は呼び出し元の責務)
原則
- 壊すレビューに寄せる: 読むレビューではない。反例が出ない指摘は弱く扱う
- 共犯化を避ける: Breaker(Claude)と Judge(Codex)は別系統モデル。両者が同意した指摘を優先する
- ゲーム化を防ぐ: Judge の好みに合わせてコードを書く方向に最適化されないよう、裁定基準は固定スキーマで運用する
- 仕様の不在は自覚する: 仕様が曖昧なら「仕様未定」として分離し、無理に欠陥判定しない
使い分け
- 通常レビュー・コミット前セルフレビュー →
/code-reviewer - 重要変更(認証 / 認可 / 決済 / スキーマ / 外部 API)・最終ゲート・高コスト領域 →
/code-reviewer-adversarial
通常フローの「最終ステップで Codex レビュー」は、このスキルを使う場合 Judge 呼び出しが相当する。別途追加の Codex レビューは不要。