はじめに
生成 AI がコーディングをするだけでなく、そのコードレビューすらも AI に任せるケースが増えています。
しかし、現状だと AI が行ったレビューそのものを人間がレビューするという「レビューのレビュー疲れ」が起きつつあります。
この問題を解決するため、私が愛用している Claude Code の /pr-review-toolkit:review-pr が出力するレビューコメントに対して、「この指摘は今すぐ直すべき」「これは後回しでいい」「これはそもそも対応不要」という仕分け作業を自動化する skill を作りました。本記事ではその設計と判断基準について紹介します。
見ようによっては
/pr-review-toolkit:review-prに対する文句のように見えかねませんがその意図は全くありません。むしろ、私自身このプラグインには大変お世話になっており、顔見知りにはオススメさえしているほど愛用しているプラグインです。
TL;DR
-
フローチャートを用いて、レビューコメントを「すぐ対応」「issue 化」「棄却」に自動仕分けする skill を作りました。
- このフローチャートは、「そもそも対応する価値があるか?」「価値があるとして、この PR で直すべきか?」「後回しにするなら、どれくらい急ぐか?」という 3つの Step から成り立っています。
- この各 Step に対して、私の感覚に合う仕分けをしてもらうために数値や自然言語を用いて作った判断基準を設定しました。
- その判断基準を達成しているかをみるために、既存の変更内容との関連度合いおよびメリット・デメリット・変更コスト・放置コストのような判断軸に焦点を当てるようにしました。
フローチャートについて
この skill を作るにあたり、まず自分が 「AI のコメントを読んだ後どういうことを考え・行動をとっているか?」を整理しました。
整理の結果、AI レビューの仕分けは以下のようなフローチャートを用いて表現できそうだと考えました
判断基準と判断軸について
次に、各 Step で使う判断基準と判断軸を定義します。
ここではこの 2つの言葉を以下のように定義しています
- 判断基準: フローチャートの各 Step における合否のライン。「メリット > 0 か?」のような分岐条件を指します
- 判断軸: フローチャートの各 Step で合否を算出するための評価軸。今ある変更に関連があるか?メリットはあるか?のような判断基準を満たすかどうかを確認するための評価軸を指します
定義をするために、再度自分が 「AI のコメントを読んだ後どういうことを考え・行動をとっているか?」を整理しました。
整理した結果、この skill 全体を通して以下の 5観点を判断軸としました。
- 既存の変更との関連度合い
- PR のレビューを、今の PR にまとめるかまとめないかを判定するために使います。関連度合いを定量的に表現しきれなかったので、AI に丸投げしています
- メリット
- プロダクトが良くなる要素全てを指します
- ここの「良い」が曖昧さを含んでいるため、「どういう状況をよしとするか」は別途表にまとめています
- 「良い」にも良さの大小があると思っていて、それらも後述する表にまとめています
- プロダクトが良くなる要素全てを指します
- デメリット
- プロダクトが悪化する要素全てを指します
- ここの「悪化する」という言葉も曖昧さを含んでいるため、詳細は別途表にまとめています。
- プロダクトが悪化する要素全てを指します
- 変更コスト
- 変更によるプロダクトへの影響範囲を指します。ソースコードの行数や作業工数の観点ではなく、プロダクトの内部実装の観点で影響範囲のみを変更コストとします
- 例えば、「1 ファイル内の local 変数の命名変更」はそのファイル内のみで完結しますが、処理の共通化を行うリファクタリングはモジュールへの影響があったり、DDD でいう interface の修正は別モジュールにも影響が及ぶ事象です
- ソースコードの行数はその多さ少なさによってプロダクトへの影響を適切に表現しきれなかったのでやめました
- 作業工数(ソースコードを書き換える量)は、私がコードを書くことはほぼほぼないため常に一定であるという前提に立ちました
- 変更によるプロダクトへの影響範囲を指します。ソースコードの行数や作業工数の観点ではなく、プロダクトの内部実装の観点で影響範囲のみを変更コストとします
- 放置コスト
- 今対応しないことで将来発生するであろう追加の損失を指します
- 「共通して使いまわされる関数シグネチャの変更は、修正が遅くなればなるほど依存先が増えてしまい修正箇所が増える」といった事象を指します
- 今対応しないことで将来発生するであろう追加の損失を指します
判断軸の構成要素について
上記の判断軸の表現だと曖昧な部分もあったので、それを AI に自分好みに推測させるようにするために一部の判断軸を構成する項目の定義とそれらの重み付け(スコアの定義づけ)を行いました。
メリットについて
「AI の指摘が以下の表のどのカテゴリに該当するか」で点数が決まるようにしました。
一旦考えやすさを優先して、「単一選択」「最大 10点」「大きい数値ほどメリットが大きい」としています。
| カテゴリ | スコア | 判定基準 |
|---|---|---|
| バグ(Critical) | 10 | データ破損、サービス停止、本番クラッシュ、未定義動作を引き起こす |
| バグ(Major) | 8 | 機能不全、誤った値を返す、操作完了不能 |
| バグ(Minor) | 3 | 表示崩れ、レイアウト乱れ、コンソールへの無害なエラー出力 |
| セキュリティ(Critical) | 10 | 認証・認可の欠陥、インジェクション、情報漏洩 |
| セキュリティ(Advisory) | 8 | セキュリティヘッダー欠損、HTTPS 非強制など、即座に悪用されないが放置すべきでないもの |
| パフォーマンス改善(効果大) | 8 | アルゴリズム計算量の改善(O(n²)→O(n)等)、N+1 クエリの修正、ボトルネックの除去 |
| パフォーマンス改善(効果小) | 4 | 不要な処理の除去、キャッシュ追加、定数的な高速化 |
| 保守性・可読性向上 | 7 | 責務分離、命名改善(コードの意図が変わる命名変更)、複雑度の低減(本質的な設計改善に限る)、略語展開、typo 修正(コードの意図を正しく伝えるために必要な変更) |
| スタイルの統一 | 0 | フォーマット、lint / formatter で自動検出・修正できる違反。CI の lint チェックで対応すべきため棄却対象 |
| メリットなし | 0 | メリットが見当たらないものをここに指定する |
仮にここに該当しないものがあった場合、 skill の改善対象としたいので別途報告してもらうようにしています
デメリットについて
デメリットは「対応した結果プロダクト品質が毀損される事柄」としました。
こちらも考えやすさを優先して、「単一選択」「最大 10点」「大きい数値ほどデメリットが大きい」としています。
| カテゴリ | スコア | 判定基準 |
|---|---|---|
| 品質を毀損しない | 0 | 変更後もプロダクトの品質特性は維持される |
| テスタビリティ・可観測性が低下 | 2 | ログ・メトリクス・テストカバレッジが失われる |
| パフォーマンスが劣化 | 5 | 改善のつもりが逆効果、別の性能指標が悪化する |
| 後方互換性を破壊 | 10 | 既存ユーザーの動作が壊れる |
| セキュリティ境界が弱まる | 10 | 認証・認可・暗号化の担保が緩くなる |
変更コストについて
上述の通り「変更の影響範囲」のみを対象とします。
こちらも「単一選択」「最大 10点」「大きい数値ほどデメリットが大きい」としていますが、メリットやデメリットの 10点と比べた時にこの項目の重要度が低くなるため現在 9点が最高得点になっています
| カテゴリ | スコア | 判定基準 |
|---|---|---|
| 自己完結する変更 | 1 | 今の PR の変更箇所のみで完結。他のコード・振る舞い・契約に影響しない |
| 同一モジュール内で波及 | 3 | 同じモジュール内の他の関数の振る舞いが変わる。呼び出し元の入出力は不変 |
| 他モジュールへ波及 | 6 | モジュール境界を越えて振る舞いが変わる。ただし外部公開されていない内部の話 |
| 外部インターフェースへ波及 | 9 | 他サービスや外部クライアントが依存する契約(API・イベント・スキーマ)が変わる |
放置コストについて
実装を後回しにする場合の追加損失を、2つの観点で定義しました。
それぞれの観点から 1つずつ当てはまるものを探します。
コード硬直化コスト
時間経過で修正範囲が広がるかをみています。
| レベル | スコア | 判定基準 |
|---|---|---|
| 最高 | 10 | 公開 APIへの指摘。外部が依存するため、後回しでの修正が困難になる |
| 高 | 7 | 共通モジュールへの指摘。プロダクト内部で依存先が増え続け、修正対象が増大する |
| 中 | 4 | 同じパターンがコピーされ、意図せず修正対象が増大する |
| 低 | 0 | 局所的な問題。放置しても修正範囲は変わらない |
コンテキスト喪失コスト
時間経過で issue の内容を再度理解するのが面倒かをみています。
AI が解釈するのでそれほど重要視はしていませんが、将来 token の消費量を気にしたくなりそうだったので先んじて導入しております。
| レベル | スコア | 判定基準 |
|---|---|---|
| 高 | 3 | 設計意図の理解が必要。時間が経つとコンテキストを失い、再理解コストが大きい |
| 中 | 2 | ある程度の再理解は必要だが、コードを読めば思い出せる |
| 低 | 0 | 局所的な変更で済み、コンテキスト不要 |
各 Step における判断基準と判断軸の使われ方について
各判断軸で考慮したい事柄が出揃ったので、ここでは各 Step がどういう判断基準を持つかをみていきます
Step 1: メリットがあるか?
メリットが少しでもありそうなレビューコメントは遅かれ早かれ対応したいので「棄却」しません。
Step2 で「すぐ対応」か「issue 化」の判断がしたいので後続に処理を渡します
Step 2: この PR で対応すべきか?
ここでは PR のスコープを過度に広げすぎないようにするため、以下の 2つの条件を両方とも満たすかどうかで判断します。
-
条件1: 今ある修正内容とどれくらい関連しているか
— 数値化するのが難しかったのと、AI の感覚とそれほどズレがなかったのでこちらで明確に定義していません -
条件2: メリットがデメリットと変更コストを上回るか
— 「メリット から デメリット と 変更コスト の値を引いた数値が 0 より大きいか」で判断します。デメリットや変更コストが大きすぎる場合は私が実装方針を再検討したいため、issue 化する方針にしています
Step 3: issue 化するなら、どれくらいの優先度にするか?
この skill を使っているリポジトリには、issue に priority-7(急ぎ対応する) ~ priority-1(基本やらない) というラベルをつけて管理しているため、どのラベルがふさわしいかを決める必要があります。
そのため「メリット から デメリット と 変更コスト を引いたものに 放置コスト を足した数値」と priority の対応表を作り、それに合うラベルをつけるようにしています。
| priority スコア | priority |
|---|---|
| 20 以上 |
priority-7(全ての開発を止めてでも対応したい) |
| 16〜19 |
priority-6(甚大な被害は出ていないが、なるはやで対応したい) |
| 12〜15 |
priority-5(それなりに効果があるので対応したい) |
| 8〜11 |
priority-4(急がないが対応したい) |
| 4〜7 |
priority-3(時間があればやる) |
| 0〜3 |
priority-2(多分やらない) |
| -1 以下 |
priority-1(基本やらない) |
完成図
実際の具体例
実際のレビューコメントがフローチャートをどう通過するか、10 のサンプルを表にまとめました。
(結果がいい感じにバラけている PR がなかったので実際の出力とは異なる点はご容赦ください)
| # | コメント概要 | メリット | デメリット | 変更コスト | diff 関連 | 放置コスト | 判定 | priority |
|---|---|---|---|---|---|---|---|---|
| 1 | 認証バイパスの脆弱性 | 10 | 0 | 1 | Yes | - | すぐ対応 | - |
| 2 | 変数名の typo | 7 | 0 | 1 | Yes | - | すぐ対応 | - |
| 3 | N+1 クエリ | 8 | 0 | 3 | Yes | - | すぐ対応 | - |
| 4 | 共通モジュール分割 | 7 | 0 | 6 | No | 10 | issue 化 | 4 |
| 5 | API 日付フォーマット統一 | 7 | 10 | 9 | No | 10 | issue 化 | 1 |
| 6 | console.log 残存 | 3 | 0 | 1 | Yes | - | すぐ対応 | - |
| 7 | 例外の握りつぶし | 8 | 0 | 3 | No | 2 | issue 化 | 3 |
| 8 | コメント追加提案 | 0 | - | - | - | - | 棄却 | - |
| 9 | キャッシュ導入 | 4 | 5 | 3 | Yes | 2 | issue 化 | 1 |
| 10 | 感想コメント | 0 | - | - | - | - | 棄却 | - |
結論
この skill により、AI が生成したコードのレビューを人間が確認する工数がなくなりました。スコアの重みや閾値など、一旦さまざまな点を割り切った設計にしていますが、今のところ使い勝手は良いです。
改善したものがあればまた追記しようと思います。