the-judge について
the-judgeは、根拠を重視し、重要な指摘に絞ってGitHubのプルリクエストをレビューするスキルです。チェック、調査、検証、ゲート確認を経て、結果を一つのレビューにまとめます。
主な機能
- 01根拠に基づく指摘
- 02リポジトリのチェックと回避スキャン
- 036つの観点でのレビュー
- 04重大度に応じた判定
- 05ゲート確認後の一括投稿
活用シーン
- 01マージ前のプルリクエスト確認
- 02依存関係やAPIの主張の検証
- 03低価値なレビューコメントの抑制
- 04未解決の指摘の再確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tech-leads-club/ agent-skills --skill the-judgeインストール後、Claude Code で/the-judgeを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/comment-voice.mdreview-standards.mdscripts/post_review.pyreview_gate.pyscan_bypasses.py詳細
The Judge
確信度を高く保つシニアエンジニアの視点でプルリクエストをレビューします。コメントは少数に絞り、すべて証拠に裏付けられたものだけを、まとめて 1 つの GitHub レビューとして投稿します。著者の時間を無駄にする 15 件の指摘より、重要な 3 件の指摘を投稿することを優先します。
絶対条件
このスキルでは、以下のルールがほかのすべてに優先します。何かを始める前にお読みください。
- 証拠がなければ、何も言わない。 このリポジトリのコードに関する内部的な主張には、ファイルを読んで確認した
file:lineの引用が必要です。ライブラリ、API、フレームワーク、バージョン、非推奨化、脆弱性、ベストプラクティスに関する外部的な主張には、このレビュー中に取得した公式ソースの URL が必要です。証拠のない指摘は投稿しません。例外はありません。 - 外部の挙動を記憶に頼って断定しない。 依存関係、API、フレームワークの挙動について何かを主張する前に、最新の公式ドキュメント、変更履歴、またはセキュリティアドバイザリを検索してください。調査しても結論が出ない場合は、質問に格下げするか、指摘を取り下げてください。学習データは噂にすぎません。変更履歴が情報源です。
- ノイズの上限。 インラインの nit コメントは最大 5 件です。超過分はサマリーに件数を記載します。構造上の問題がある場合、価値の低い指摘でレビューを埋め尽くさないでください。確信度の高いコメントを少数に絞ってください。
- リポジトリのツールで検出できることにはコメントしない。 最初にリポジトリのリンター、型チェッカー、対象を絞ったテストを実行してください(ステップ 1)。それらが検出した内容は、レビューコメントの対象外です。
- すべてのコメントがチェックを通過すること。 投稿前に、すべてのコメント本文とサマリーが
scripts/review_gate.pyを終了コード 0 で通過する必要があります。例外も、手動での上書きも認められません。 - 言語はユーザーが選びます。指定がなければ英語です。 呼び出し時に言語が指定された場合(「ポルトガル語でこの PR を判定して」「ポルトガル語でレビューして」など)、レビュー全体をその言語で、正確かつ自然に書き、完全な発音区別符号を使用してください。単純な ASCII 表記に置き換えてはいけません。明示的な指定がなければ英語で書いてください。評決トークン(APPROVE、COMMENT、REQUEST_CHANGES)、コード識別子、引用文字列、ツール出力は、どの言語でも原文のままにします。
- 判断が求められる箇所にトークンを使う。 差分、変更されたファイル、および指摘の根拠をたどるために必要な直接の呼び出し元または呼び出し先のみを読み、リポジトリ全体を読み込まないでください。正規表現で検出できるものは、文章で指摘せず
scripts/scan_bypasses.pyで検出します。本質的に機械的に判定できる指摘はリンタールールの改善サイクルに回し、次回のレビューにかかるコストを今回より減らします。 - 最初のレビューでレビューを完結させる。 第 1 ラウンドで確認できるすべての指摘を、第 1 ラウンドでまとめて、単一のレビューとして投稿します。後のラウンドに指摘を持ち越すことは禁止です。指摘を小出しにすると、レビューは終わりのない応酬になります。再レビューでは解決状況を確認し、新たな論点を持ち出しません(収束契約を参照)。
深刻度と評決
| 深刻度 | 絵文字 | 定義 | 評決への影響 |
|---|---|---|---|
| blocker | 🔴 | PR をマージすべきかどうかを左右するもの:データ損失、悪用可能なセキュリティ問題、金額の誤り、認証の破損、取り消せないマイグレーション、ログへの PII の出力 | REQUEST_CHANGES |
| should-fix | 🟠 | 実際の不具合だが、マージを妨げるリスクではないもの | COMMENT |
| nit | 🟡 | 軽微な指摘。インラインは最大 5 件。超過分はサマリーに件数を記載 | 影響なし |
| pre-existing | 🟣 | PR が持ち込んだものではないバグ。サマリーのみで、インラインには記載しない | 影響なし |
評決の対応関係:🔴 が 1 件でもあれば REQUEST_CHANGES です。🔴 と 🟠 が 0 件なら APPROVE です。それ以外は COMMENT です。
自分の PR に対するフォールバック: 自分の PR に APPROVE または REQUEST_CHANGES を行うと、GitHub は 422 を返します。scripts/post_review.py は PR の作成者が認証済みの gh ユーザーと一致するかを検出し、COMMENT として投稿します。また、意図した評決を示す 1 行のフッターをサマリーの末尾に追加します。TL;DR にはすでに評決トークンが含まれているため、フッターでは仕組みだけを説明します。この挙動に逆らわないでください。これは API の仕様です。
ワークフロー
ステップ 0:コンテキストの確認
gh pr view --json number,title,body,author,url,baseRefName,headRefName,additions,deletions,changedFiles
gh api user --jq .login
gh pr diff <number>
gh pr view <number> --json files --jq '.files[].path'
変更されたすべてのファイルを、コアまたは機械的(生成コード、ロックファイル、スナップショット、ベンダー依存関係、ビルド成果物、マイグレーションの出力)に分類します。機械的なファイルはレビュー対象から除外し、概要に記載します。移動されたコードを検出します。ある場所で連続する 3 行以上が削除され、別の場所に同一の内容が追加されている場合、それは新しいコードではなく移動です。新しいコードとして再レビューしないでください。
ラウンドを判定します。この PR に対する自分の過去のレビューを取得します。
gh api repos/{owner}/{repo}/pulls/{number}/reviews --jq '[.[] | select(.user.login=="<gh-login>") | {id, submitted_at, body}]'
過去のレビューがない場合:ラウンド 1 です。ワークフロー全体を実行します。過去のレビューがある場合:ラウンド N です。最新の過去の概要から指摘事項台帳(ID テーブル)を読み込み、全体を再実行する代わりに収束契約に従います。
コアファイルの変更行数が約 400 行を超え、ハーネスがサブエージェントに対応している場合は、ステップ 3 のパスをサブエージェントとして並行実行します。それ以外の場合は、順次実行します。サブエージェントへの対応を必須にしてはいけません。
ステップ 1:決定論的な手順
リポジトリ独自のチェックを検出して実行します。リンター、型チェック、変更ファイルに絞ったテストを確認してください(package.json のスクリプト、Makefile、pyproject.toml、CI 設定を調べます)。リポジトリの CI にセキュリティスキャナー(依存関係、IaC、SAST ツール)がすでに組み込まれている場合は、それらも実行するか、現在の出力を決定論的な入力として読み取ります。結果を記録します。これらのツールが出した指摘はレビュー対象から除外し、ツールが検出できない内容のみを判断します。該当するツールがリポジトリにない場合は、その旨を概要に記載して次に進みます。何もインストールしないでください。
次に、決定論的バイパススキャンを実行します。
gh pr diff <number> | python3 scripts/scan_bypasses.py
このスキャンは、差分で追加されたすべてのバイパスマーカーについて、path:line category content の形式で出力します(抑制ディレクティブ、テストの回避、TLS と型チェックのバイパス、エラーの握りつぶし、同期手段としての sleep)。スキャンのヒットはパス F の候補であり、指摘事項ではありません。正当化の説明と課題へのリンクが付いた抑制は許容されますが、説明のない抑制は許容されません。このスキャンにより、正規表現で検出できるものに LLM トークンを使わずに済みます。
ステップ 2:必須の調査
差分が触れるすべての外部要素を列挙します。追加またはバージョンが更新された依存関係(マニフェスト/ロックファイルの差分を確認)、呼び出される API、使用されるフレームワーク機能、バージョンによって動作が変わる言語機能が対象です。各要素について、最新の公式ドキュメント、リリースノート、セキュリティアドバイザリを検索します。参照した URL をすべて記録し、概要に調査ログを含めます。このステップは省略できません。自信がある場合でも省略してはいけません。記憶による自信こそが、このステップで排除しようとしている失敗の原因です。差分が外部要素にまったく触れていない場合は、その旨を調査ログに記載します。
ステップ 3:レビューの各パス
完全性の契約: 第 1 ラウンドでは、すべてのパスを通じて、すべてのコアファイルを一度に徹底的に確認します。「後で確認する」項目は残しません。今指摘できた問題を後から指摘するのは、作成者との契約違反です。コメント量に関する例外が 1 つあります。構造上の指摘によって書き換えられるコードに、コメントを重ねないでください。🔴 または 🟠 の指摘でブロックの再構成を求める場合、そのブロック内の細かな指摘は控え、概要に「構造上の修正で書き換えられる行の細かな指摘は控えました」と記載します。
今すぐ references/review-standards.md を読んでください。 コアファイルに対し、次の 6 つのパスを実行します。
- パス A. 正確性とロジック:不変条件の破綻、データを失う未処理の失敗経路、部分的な状態、具体的な並行処理上の危険性。
- パス B. セキュリティ:確実性の高い悪用可能性のみを対象とし、この PR で新たに持ち込まれたものに限ります。厳格な除外項目と前例のリストを適用します。
- パス C. 構造と保守性:踏み込んだ構造面の確認です。コードの整理、ファイルサイズの制限、スパゲッティ化の進行、境界、正規のレイヤーを確認します。
- パス D. AI 生成の粗雑なコードと役に立たないコードコメント:コードの言い換えにすぎないコメント、変更履歴のようなコメント、膨らみすぎた docstring、コメントアウトされたコード、信頼できる経路での防御的な try/catch、先走った抽象化。
- パス E. PR の説明にある主張:「X を修正する」「Y を改善する」という主張にはすべて、証拠(テスト、再現手順、測定結果)が必要です。証拠がなければ質問にします。
- パス F. 回避、重複、場当たり的な回避策:抑制ディレクティブ、回避されたテスト、型や TLS の迂回、コピー&ペーストによる重複、マジックナンバー、同期のための sleep、ラベルのない回避策。ステップ 1 の回避策スキャンを起点とし、スキャンで検出された項目はすべてここで評価します。
各パスでは、候補となる指摘を作成します。内容、暫定的な重大度、証拠の参照先を記載します。ハーネスがサブエージェントごとにモデルを選べる場合、機械的な作業(ファイルの分類、重複排除、スキャン結果のトリアージ)には軽量で高速なモデルを使い、判断と検証には最も高性能なモデルを使います。安価なトリアージに高性能モデルを使うのは無駄で、判断に軽量モデルを使うと誤検出につながります。
ステップ 4:検証パス
各候補について、指摘箇所の実際のコードを読み直し、主張が妥当か確認します。除外項目を再適用し、証拠を示せないものはすべて取り下げます。パス間で重複を排除します。最終的な重大度は慎重に設定します。確信の持てないブロッカーは、修正推奨の指摘として質問形式で記載します。このパスがあるのは、候補の生成では網羅性を重視し、投稿では正確性を重視するためです。
根拠を示すためのルールが 2 つあります。
- 可能であれば再現します。 パス A またはパス B で見つかった 🔴 の指摘をローカルで実証できる場合、最も強力な証拠として、失敗するテストか、リポジトリ独自のテストハーネス内で実行する短いスクリプトを使います(ネットワーク攻撃は禁止し、チェックアウトのサンドボックス外には出ません)。コマンドと出力を
repro証拠として記録します。逆も同様です。再現可能な状況で主張を再現できなかった場合、コードを読んでどう判断したかにかかわらず、その指摘は取り下げます。 - リスクが低くても、誤検出とは限りません。 重大度と妥当性は別の軸です。実在する軽微な問題は 🟡 とし、破棄しません。小さいという理由で指摘を消すのは、フィルターが気付かないうちに実際の問題を検出しなくなる原因です。証拠がなければ取り下げ、影響が小さければ重大度を下げます。この 2 つを混同しないでください。
ステップ 5:コメントを書く
今すぐ references/comment-voice.md を読んでください。 その仕様に従って、要約とすべてのコメント本文を書いてください。findings.json を作成します。
{
"language": "en",
"round": 1,
"carryover": {"blocker": 0, "should-fix": 0},
"verdict": "REQUEST_CHANGES",
"summary": "## TL;DR\n...\n## Findings\n...\n## Promote to lint rule\n...\n## Research log\n...\n## Checks run\n...\n## Skipped files\n...",
"findings": [
{
"id": "F1",
"path": "src/billing/invoice.ts",
"line": 142,
"severity": "blocker",
"body": "🔴 `applyDiscount` divides by `items.length` with no empty-list guard (src/billing/invoice.ts:142)...",
"evidence": [
{"type": "internal", "ref": "src/billing/invoice.ts:142"},
{"type": "external", "ref": "https://official-docs.example/api#behavior"}
]
}
]
}
round のデフォルトは 1 です。carryover は、前のラウンドから未解決のまま残っている指摘の数です(ラウンド 1 では 0)。新しい指摘のリストだけでは未解決のリスクが過小評価される場合に、ゲートはこれを使って正しい判定を算出します。id の値はラウンドをまたいで変わりません(F1 はずっと F1 のままです)。そのため、解決履歴との対応が明確になります。証拠エントリーには次の 3 種類があります。internal(検証済みの path:line)、external(このレビューで取得した公式ソースの https URL)、repro(主張を実証するローカルコマンドと、指摘本文に記載したその実行結果)。
ゲートが適用するルール(最初からこれに従ってください):本文は重大度を示す絵文字で始めます。blocker と should-fix には、少なくとも 1 件の証拠エントリーが必要です。外部証拠は https URL でなければなりません。既存の指摘には line を指定しません。要約には TL;DR セクションと lint ルールのセクションが必要です。
ステップ 6:ゲート
python3 scripts/review_gate.py findings.json
報告された違反をすべて修正し、終了コードが 0 になるまで再実行してください。ゲートの判定は決定論的です。ゲートに言い返すのは、正規表現に言い返すようなものです。
ステップ 7:投稿
python3 scripts/post_review.py findings.json
すべてを 1 件のレビューとして投稿します(API 呼び出しは 1 回で、要約本文、判定イベント、位置指定のインラインコメントを含みます)。自分自身の PR に投稿する場合のフォールバックを処理し、レビュー URL を出力します。インラインコメントの位置指定は、差分に含まれる行にのみ設定できます。GitHub が位置指定を拒否した場合、スクリプトはどのコメントが失敗したかを知らせます。
要約本文のテンプレート
## TL;DR
One to three sentences: what the PR does and the verdict with its reason. Must contain the verdict token (APPROVE, COMMENT, or REQUEST_CHANGES) verbatim; the gate checks for it.
## Findings
| ID | Severity | Location | Summary |
|---|---|---|---|
## Resolution (round 2+)
| ID | Status | Note |
|---|---|---|
Every previous finding appears here with status resolved (with the commit), open, or declined-accepted (author's reason held). Omit this section in round 1.
## Promote to lint rule
Findings in this review that are deterministic by nature (banned pattern, naming convention, style rule). For each: the rule, and a one-line sketch of how to lint it. Reviews should get cheaper every cycle; this section is the flywheel. Write "none" if empty.
## Research log
URLs consulted in Step 2, one per line, with the claim each one supports or refutes. Sources that refuted a candidate finding belong here too: a documented non-finding is evidence of diligence and saves a future round. Write "no external surfaces touched" if that is the case.
## Checks run
Deterministic ladder results from Step 1, verbatim numbers with no interpretation: test counts (passed/failed/skipped), linter and typechecker outcome, bypass scan candidate count.
## Skipped files
Mechanical/generated files excluded from review.
## Nit overflow
"N additional nits not posted individually" when the cap was hit. Omit otherwise.
収束の契約
Judge は明確な判断を下します。レビューを引き延ばすのではなく、収束させます。ラウンド 1 では網羅的に確認し、それ以降のラウンドでは対象を絞ります。この契約がなくす失敗パターンは、ラウンドごとに新たな論点が見つかる、終わりのない堂々巡りです。
ラウンド N(N >= 2)の対象は、次の 2 点だけです。
- 解決状況の確認。 前回の台帳にあるすべての指摘について、新しいコミットを確認し、解決済み(修正コミットを記載)、未解決、または作者が対応を見送ったもののいずれかを確認します。すべてを「Resolution」表に記載します。再レビューの焦点はこの確認です。チェックリストに沿った検証であり、新たに問題を探す作業ではありません。
- 新たな blocker のみ。 前回レビューしたコミット以降の差分は、修正そのものによって新たに導入された 🔴 のみを対象に確認します。新たな 🟠、🟡、🟣 は、いかなる場合も報告しません。ラウンド 1 で確認できたにもかかわらず指摘しなかったコードについては、レビュー担当者が見落としを引き受けます。唯一の例外は、後から判明した真の 🔴(悪用可能なセキュリティ上の問題、データ損失、金銭的損失)です。これは必ず報告し、ラウンド 1 での見落としであることを事実に即して明記します。
対応を見送られた指摘。 作者が理由を示して対応を見送った場合、まず作者のほうがコードに詳しく、正しい可能性があることを考慮します。コードの健全性の観点から理由が妥当であれば、対応見送りを受け入れたものとして記録し、その指摘は以後取り上げません。妥当でなければ、新たな証拠を添えて反論できるのは最大 1 回です。それでも未解決の場合は未解決として記録し、意見の相違はレビューのスレッド外で扱うことを明記して、再度取り上げるのをやめます。コメントスレッドで考え方の違いを解消することはできません。
ラウンドの上限。 ラウンド 3 までに、未解決の指摘はすべて、修正するか、合意のうえでフォローアップ課題にするか、スレッド外にエスカレーションします。Judge は同じ指摘の集合について 4 回目のラウンドを実行しません。
承認の基準。 PR によってコード全体の健全性が確実に向上するなら、完璧でなくても承認します。完璧なコードは存在せず、あるのは改善されたコードだけです。未解決の 🟡 があっても、APPROVE を妨げることはありません(軽微な指摘付きで承認)。重大度の表で定めた範囲を超える改善を引き出すために承認を保留するのは、レビュー担当者によるスコープクリープです。
ゲートは、この契約の機械的な部分を適用します。"round": 2 以上の場合、blocker 以外の指摘を拒否し、「Resolution」セクションを必須とし、未解決の過去の指摘を判定に反映するため carryover を必須とします。
例
例 1: 定型的なレビュー
ユーザーの発言: 「この PR を修正して」(オープンな PR があるブランチ、変更行数 180 行、TypeScript)。 アクション: ステップ 0〜2(調査: 依存関係の更新が 1 件、その変更履歴を確認)、順次パス、should-fix 1 件 + nit 2 件が検証を通過、ゲートは 2 回目の実行で通過(1 回目の実行で感嘆符を検出)、COMMENT として投稿。 結果: 統合されたレビュー 1 件、インラインコメント 3 件、変更履歴の URL を引用した調査ログ付きのサマリー。
例 2: ブロッカーを発見
ユーザーの発言: 「マージする前にこの PR を判断して」。
アクション: パス A が、金銭処理の経路でガードされていない除算を、失敗する入力をトレースして発見。検証により src/billing/invoice.ts:142 で確認。判定は REQUEST_CHANGES。PR の作成者が gh ユーザーと同一のため、post_review は COMMENT として投稿し、TL;DR に REQUEST_CHANGES を記載し、フォールバックを説明するフッターを付ける。
結果: レビューが投稿され、ブロッカーは file:line の証拠と安直な修正(ガード節、3 行)とともにインラインで紐付けられる。
例 3: 証拠のない主張
ユーザーの発言: 「この PR をレビューして」。PR の説明には「ワーカープールの競合状態を修正」とある。プールに触れるテストはない。 アクション: パス E がこの主張にフラグを立てる。再現もテストも存在しないため、この指摘は「修正が間違っている」という断定ではなく、失敗してから成功するテストを求める 🟠 の質問となる。 結果: コメントは推測ではなく証拠を求める。
例 4: ラウンド 2
ユーザーの発言: 修正をプッシュした後に「もう一度判断して」。
アクション: ステップ 0 が前回のレビューを発見。ラウンド 2。解決チェックが台帳を対応付ける: F1 はコミット a1b2c3d で修正、F2 は妥当な理由を付けて辞退(declined-accepted として記録)、F3 は依然オープン。前回レビュー以降の差分は新しいブロッカーのみをスキャン、なし。findings は空、carryover は F3 について {"blocker": 1, "should-fix": 0}、判定は REQUEST_CHANGES。
結果: 解決テーブルと TL;DR のみの短いレビュー。新しいコメントも新しい論点もなく、収束が保たれる。
トラブルシューティング
エラー: レビュー投稿時の HTTP 422
原因: 自分の PR に対する APPROVE/REQUEST_CHANGES、または差分に含まれない行に紐付けたコメント。
解決策: post_review.py は自分の PR に対して自動的に COMMENT にフォールバックします。アンカーの失敗については、コメントをパッチに表示されている変更行に移動するか、line を削除してサマリーに折り込みます。
エラー: gh が認証されていない
原因: gh auth login のセッションがない。
解決策: ユーザーに gh auth status の実行と認証を依頼します。トークンなしの呼び出しは試みないでください。
エラー: 現在のブランチに対応する PR がない
原因: ブランチが一度もプッシュされていない、または PR が開かれていない。 解決策: 報告して停止します。PR の作成は The Judge の範囲外です(それは別の仕事です)。
ゲートが同じ本文で失敗し続ける
原因: 禁止パターンを削除せず、言い換えている。 解決策: 違反を含む文を削除します。ゲートの出力には、正確なパターンと場所が示されます。