AIコードレビュー「棚卸し」のススメ
最新記事はこちら
CodexSDKを使ってサブエージェントを独自実装する手法を解説しています。
AI にコードレビューを投げると、ありがたいことに山ほどレビューコメントが返ってくる。
しかし、実際に運用してみると、その中には直さなくても良さそうな細かい指摘や、そもそもレビュー内容自体が誤っているコメントが紛れ込み、PR のコメント欄があっという間にカオスな状態になることも珍しくない。
結局のところ、一つひとつについて「この指摘は妥当か?」「今すぐ対応すべきか?」を目で追いながら判断していくことになり、レビューが増えたわりに仕分け作業だけが重くのしかかってくる。
そこで発想を変え、まずは PR についたレビューコメントをすべて洗い出し、その一つひとつについて妥当性や対応方針(対応するべきか、保留でよいか、無視してよいか)を AI に一次判定させることにした。
AI にレビューコメントそのものを棚卸しさせ、結果を一覧表として出力させるイメージである。その一覧をそのまま信用して修正対応を一括で任せてもいいし、人間がざっと眺めてから本当に手を入れるべき指摘だけを選び直してもいい。
今回の仕組みを使うと、だいたい次のような「レビュー棚卸し」の結果が得られるはずだ。
---
1. **位置**: src/features/todo/TodoList.tsx (line 42)
**要旨**: items が null の場合に例外が発生しうる
**種別**: bug
**判定**: MUST_FIX
**理由**: 実行時例外を招くため、このPRの範囲で必ず修正すべきです。
---
2. **位置**: src/features/todo/TodoItem.tsx (line 15)
**要旨**: コンポーネント名とファイル名の不一致
**種別**: style
**判定**: SHOULD_CONSIDER
**理由**: 動作には影響しませんが、既存の命名ルールと揃えた方が保守性が高まります。
---
実際にはレビューの数だけ、このブロックが連続して並ぶイメージである。
これの何が良いのか
今回はこの出力を得るための指示をカスタムコマンド化した。後ほど原文を見せるが、コマンドで実行したいことはシンプルだ。
- AI が付けたレビューコメントを一度すべて洗い出す
- 各コメントについて「優先的に直すべきか/余裕があれば検討か/無視してよいか」を判定させる
- その結果を一覧で眺めて、一気に対応する
という流れを作ることが目的である。
一個一個のコメントに対して
- 「このレビューどおりに修正して」
- 「これは無視していい?」
- 「この指摘、そもそも間違っていない?」
のように会話ベースで処理していくのは、さすがに手間が大きい。
そこでまずは「棚卸し」と「優先度付け」だけを AI に任せて、その結果を見ながら人間が動く、という仕組みを目指している。
ghコマンドまわりで困っていたこと
また、今回わざわざカスタムコマンド化したのにはもう一つ理由がある。
Codexのようなエージェントに対して「GitHub のレビューコメント確認して」と雑に指示すると、素直に gh pr comment 系を使ってしまうことが多い。
しかし、これでは PRのレビューコメントがうまく取得できないケース が発生する。
欲しいのは Issue コメントではなく、次のような情報である。
- PRにぶら下がっている「レビューコメント」
- できれば「未解決のスレッド」だけ
そのため、今回のプロンプトでは最初から「コメントは gh comment ではなく gh api 系で取りにいく」という指示を加えている。これによってPRレビューコメントをAIエージェントに取得させることが可能になる。
セッションを分ける前提の設計
今回作成したプロンプトはPRレビューの解析とリストアップでタスクを完了させるような設計になっている。一覧表をファイルとして書き出す提案もしているので、そのタスクでセッションを閉じることも可能だ。こうした背景として、Anthropicの公式記事でも紹介されていた次の考え方を参考にしている。
リサーチ・計画・実装を分離する
各フェーズで新しいセッションを開始し、
文脈全体を引きずらず、要約した結論だけを次に渡す
これはかなり納得感がある。調査、計画、実装といった形で役割ごとにセッションを分け、成果だけをドキュメントとして次に渡していくほうが、コンテキスト管理の観点でも効率的であり、モデルの力を引き出す上では重要な考え方になってくるだろう。
セッションの分け方について参考にした記事はこちら
プロンプトの概要
プロンプト内部で行っていることをざっくり書くと、次のような流れになる。
-
対象PRを一つ特定する
- PR番号やURLを尋ねる
- 指定がなければcurrentブランチから自動検出してもよい
-
GitHub GraphQL API(
reviewThreadsなど)経由で
未解決のレビューコメントだけ を取得する- どうしても絞り込めない場合は「未解決のみを判定できなかったため、全コメントを対象にする」と宣言してから処理する
-
PRのタイトル・本文・diffを読み、
このPRが何を目的とした変更なのか を把握する- 仕様変更なのか、バグ修正なのか、リファクタなのか、といった前提を理解させる
-
各レビューコメントについて、次の情報を付けて一覧化する
- 位置(ファイル名+おおよその行)
- 要旨(何を指摘しているか)
- 種別(bug / spec / perf / security / test / style / 好み など)
- 判定(
MUST_FIX/SHOULD_CONSIDER/CAN_IGNORE) - 理由(1〜3 行)
特に今回はPRの目的・スコープを理解したうえで判定させるために、PRの本文を考慮することも指示に入れている。コードの内容だけではどうしても背景を把握できないことがあるので、PR本文含め「何の目的の実装か」を意識させるようにしている。
カスタムコマンドの全文はこちら(ご自由にお使いください)
カスタムコマンドの全文
---
name: review-comment-analysis
description: 現在のPRの未解決レビューコメントを分析し、修正要否を判断する
---
あなたは、このリポジトリのコードレビューアとして動作する。
## 目的
- 対象PRに付いている「未解決レビューコメント」を収集する。
- 各コメントが妥当かどうか、修正すべきかどうかを評価した一覧を作成する。
- **このコマンドではコード修正やファイル編集は一切行わない(読む・分析のみ)。**
## 前提
- 必要に応じて `gh` コマンドや GitHub API(REST / GraphQL)を利用して、対象PRとレビューコメントを取得してよい。
- **対象PRのタイトル・本文・diff を読み、どのような実装/変更を行おうとしているのかを把握したうえでレビューすること。**
- PRの目的・前提条件・スコープを理解したうえで、各コメントがその意図と整合しているかも判断材料に含める。
- 評価の際は、可能な範囲で「指摘対象コード」や「プロジェクトの方針・既存の書き方」も確認して判断すること。
## 会話開始時のフロー
1. 最初の応答では、**対象PRを特定するための短い質問を1つだけ**行うこと(長い前置きは不要)。
- 例:
`対象にするPRを教えてください。PR番号、PRのURL、または「現在のブランチのPR」のいずれかを指定してください。特に指定がなければ、現在のブランチからPRを自動で探します。`
2. ユーザーの回答に応じて対象PRを決める:
- PR番号またはURLが指定された場合: それを対象PRとして扱う。
- 「現在のブランチ」「current」等と指定された場合:
- `gh pr view` や `gh pr list --head <current-branch>` などを使って、現在のブランチに紐づくPRを探す。
- 特に指定がない/曖昧な場合:
- 現在のブランチからPRを自動で探してよい。
3. 現在のブランチに紐づくPRが見つからない、または情報不足でPRを特定できない場合:
- その旨を簡潔に伝え、処理を終了する(無理に推測しない)。
## レビューコメントの取得と絞り込み
- 可能であれば、GraphQL の `reviewThreads` 等を用いて、
**「未解決コメント(`isResolved == false` のスレッド)」のみに絞る。**
- 未解決かどうかの判定が技術的に難しい場合は、次のように宣言してから全コメントを対象とする:
- `未解決コメントのみを判定できなかったため、このPRの全レビューコメントを対象に分析します。`
## 分析で行うこと
対象PRを特定しレビューコメント一覧を取得したら、次の手順で分析する:
1. まず PR のタイトル・本文・diff を読み、**このPRが何を目的とした変更なのか**を把握する。
- 仕様変更なのか、バグ修正なのか、リファクタリングなのか等を理解したうえで、レビューコメントの妥当性を評価する。
2. 次に、未解決コメント(もしくは全コメント)を走査し、各コメントについて以下の情報をまとめる:
- **位置**: ファイル名と大まかな位置(行番号やハンク情報など、わかる範囲で)
- **要旨**: コメントが何を指摘しているか
- **種別**: `bug` / `spec` / `perf` / `security` / `test` / `style` / `好み` など、適切だと思う分類
- **判定**: `MUST_FIX` / `SHOULD_CONSIDER` / `CAN_IGNORE` のいずれか
- **理由**: なぜその判定にしたかを 1〜3 文で説明する
- 可能であれば、PR本文で説明されている目的や前提、既存の設計/コーディングスタイルとの整合性にも言及する。
3. 上記の情報を、**以下のフォーマットで一覧として出力する。**
### 一覧の出力フォーマット
- 各コメントごとに、`---` で囲まれたブロックを 1 つ出力する。
- コメントごとに、**1 から始まる連番**を付ける(`1.`, `2.`, `3.` …)。
- 各ブロックは、以下のフォーマットにできるだけ忠実に従うこと(太字ラベル・改行位置も含めて守る):
---
1. **位置**: src/features/todo/TodoList.tsx (line 42)
**要旨**: nullチェックが不足している可能性がある
**種別**: bug
**判定**: MUST_FIX
**理由**: items が null の場合に実行時例外が発生する。
ガード節を追加すべき。
---
* 一覧本体を出力するメッセージでは、原則として上記フォーマットのブロックを連続して並べる。
* ただし、**一覧をすべて出力し終えた直後に続けて 1〜2 行の案内文(ファイル保存案内)を付けることは許可する。**
## 一覧出力後のファイル保存案内
* 一覧の全ブロックを出力し終えた直後に、**必ず**次のような趣旨の案内を付けること:
`必要であれば、この一覧をローカルファイル(例: review-decisions.md)として出力することもできます。保存したい場合はファイル名を指定してください。`
* `review-decisions.md` というデフォルト名を例として示してよいが、
**ユーザーから明示的な指示があるまでは、実際にファイルを作成・編集しないこと。**
* ユーザーがファイル名や保存を指示した場合のみ、ファイル出力に関する具体的な手順やコマンド例を提案する。
## 禁止事項・注意事項
* このコマンドの実行中は、**コードの修正やリポジトリ内ファイルの編集は一切行わないこと。**
* 提案に留めるのはよいが、実際の変更はユーザーの明示的な指示があるまで行わない。
* PR やコメントの情報が不十分で判断が難しい場合は、無理に決めつけず、
* その旨を「理由」に明記したうえで、最も妥当と思われる判定を選ぶか、
* どうしても判定不能な場合は、そのコメントについては「情報不足で判定困難」であることをはっきり示す。
どう使うと効果的か
このプロンプトは、Codexで使う前提で作っている。
ただ、GitHub CLIのコマンドをちゃんと扱えるエージェントであれば、他のツールでも問題なく流用できるはずだ。
やっていること自体はかなり地味だが、
- AIレビューの量が増えてきて、仕分けに疲れてきた
- 「とりあえず全部読む」運用から一歩抜け出したい
- セッションを役割ごとに分けて、AI との付き合い方を整理したい
といった感覚が少しでもあれば、
「AIのレビューをレビューするレイヤー」を一段挟んでみる価値はあると思う。
レビューコメントの質そのものをどう高めるか、という話とは別に、
降ってきたレビューをどうさばくかというレイヤーを AI に任せていく。
今回のスラッシュコマンドは、そのための一つの具体例である。
似たような課題感を持っている人のところで、少しでも役に立てばうれしい。
こちらの記事もぜひ!
Discussion