Pull Requestの頻出コメントをAIを用いて集計・ドキュメント化してレビュー改善を試みた

こんにちは。 Legalscape CVチームの梶です。

昨今ではAIコーディングで生産量が上がった分、コードレビューの改善が必要と言われています。 LegalscapeでもAIコーディングは盛んに行われており、品質を維持したままコードレビューを減らしたり効率を上げることは重要な課題の一つです。

Legalscapeでは大きなモノレポを運用しているのですが、今回はモノレポに蓄積した大量のPRコメントを活用してコードレビューを改善できないか挑戦してみました。

統計は全然専門ではないのですが施策の評価をするにあたってClaudeにビシバシ指導されながらなんとかやってみました。

TL;DR

  • コードレビューでは同じ指摘が人とPRを変えて繰り返される。そこで マージ済みPull RequestのレビューコメントをAI(LLM)で集計・要約し、頻出する実装観点を一枚のドキュメントにまとめて レビュー改善を試みた。
  • この取り組みではAIを二度使うことになった。
    • 一度目は「PRコメントを集計してドキュメントを作る」ため。
    • 二度目は「効果検証でPRコメントを観点分類する」ため。
  • 効果検証で最初に出た数字は approve(承認)までの時間が中央値 −73% という劇的なもの。
    • しかしその相関は PRの小粒化・Bot PR増加・既存トレンド・同日の別運用変更 でほぼ説明され、ドキュメントの独立した効果ではなかった。
  • 「測れていないだけ」か「効果が無い」かを切り分けるため、approve時間のような遠位指標ではなく、ドキュメント化した観点に沿ってPRコメントを分類する近位指標 を設計し、LLMで分類して検証した。それでも有意な効果は検出できなかった。
  • 一番の収穫は施策の是非ではなく、「PRコメント起点のドキュメント施策はこう測るべきだった」という測定の作法 だった。

取り組み: PRコメントの頻出事項をドキュメントにする

コードレビューでは「この領域ではここに気をつける」「このアンチパターンは過去に踏んだ」といった類似の実装観点をPRコメントで補足していました。これは知識共有としては機能していましたが、同じ指摘が人とPRを変えて何度も繰り返され、レビュアーの負担になっていました。

そこで、 PRコメントを一次データとしてAIで集計し、頻出事項をドキュメント化 しました。具体的には、

  1. マージ済みPRのレビューコメントをGitHubから大量に収集 (約16,000件)
  2. それを AI(LLM)で集計・要約 し、「複数PRで繰り返し出ている指摘」「重大度の高い単発の指摘」を抽出
  3. 抽出結果を 実装観点ドキュメント(リポジトリ内の VIEWPOINT.md)として整理
  4. VIEWPOINT.md を既存の AGENTS.mdREVIEW.md から参照するようにポインタを張る

ドキュメントの中身は、おおむね次の構成になりました。

  • 領域別の実装観点 : 認証・認可、API/データ層、フロントエンド、デザインシステム、ジョブ/バッチ、CI/インフラ
  • 避けるべき実装パターン(アンチパターン表) : 例外の握り潰し、N+1 クエリ、fail-open な認可ガード、useEffect での派生状態同期、タイムゾーン取り違え…をコード付きの表で列挙
  • プロジェクト固有の実装規約 / セキュリティ観点 / パフォーマンス観点

レビューの「進め方・ルール」を書いた REVIEW.md とは役割を分け、こちらは 「何を守るべきか」 に徹しました。さらに重要なのは メンテナンス運用 で、PRコメントを定期的に集約して、現場で実際に繰り返されている指摘だけをドキュメントに昇華させる ループにしたことです。

具体的には、メンテナンス指示用のドキュメントと集計用のドキュメントを VIEWPOINT.md とは別に用意して、集計用ドキュメントで一定の基準を超えたものだけを VIEWPOINT.md に昇格するようにしました。

このような構造です。

docs/
  ├── VIEWPOINT.md
  ├── maintenance-prompts/
  │  └── weekly/
  │     └── viewpoint.md
  └── generated/
     └── pr-review-observations.md

さらに、 「これでレビューは良くなったの?」 という検証を行いました。 導入からおよそ三週間経っています。このタイミングになったのは単純にブログを書くタイミングだったからです。


検証1: 魅力的すぎる最初の数字

ドキュメント導入日の前後で、マージ済みPRを数百件集めて比較しました。

指標は以下の二つです。まずは直感的に改善がわかりやすい指標としてこの二つを設定しました。

  • PRあたりの人間のレビューコメント数
  • 作成から初回approveまでの時間
指標 導入前 導入後 変化
人間コメント数/PR(平均) 3.68 2.67 −27%
approveまでの時間(中央値) 18.9h 5.1h −73%

approve時間が 約 3 分の 1。「頻出事項のドキュメント化でレビューが速くなった」とスライドに書きたくなる数字です。

しかし、これは本当に今回の施策の影響なのでしょうか?

なぜこの数字を信じてはいけないか

データの取り方を見直すと、すぐに 3 つの危うさが見えました。

  1. 打ち切りバイアス:「マージ済みPRだけ」を集めていた。導入後の直近で作られたPRは、まだマージされていない「遅いPR」が母集団から抜け、早くマージされたPRに偏る
  2. ウィンドウ*1長の不一致:導入前を長く・後を短く比べると、前期間にたまたま含まれる「荒れた高コメント週」が平均を吊り上げる。
  3. 既存トレンド:コメント数の中央値が下がり始めたのは、ドキュメント導入より 前の週から だった。

「導入前後で割って比べる」だけでは、ドキュメントの効果と無関係に進んでいた変化を区別できません。そこで交絡要因*2を順に潰していきました。


検証2: 4ステップで交絡を検証する:A → B → C → D

A. 「同じ日に何が起きていたか」を洗い出す

因果推論の前に、まず現場の歴史を調べました。コミット履歴をたどると、ドキュメント導入とまさに同じ日に、AIコードレビューの運用変更が別途入っていました。さらにAIレビューアーがPRをレビューする割合がその前後で大きく変動していました。

これは致命的です。「ドキュメント導入」と「AI レビュー運用変更」が同日に束ねられている ため、原理的にどちらの効果かを分離できません。

B. 中断時系列分析(ITS)+プラセボ

「もともと下がっていただけ」を否定するため、approve時間(対数)を時間トレンド込みで区分回帰し、導入日に段差があるか を検証しました。

  • 導入日の段差: 統計的に有意でない (トレンドの延長と区別できない)
  • 無関係な日付に偽の境界を置くプラセボでは、ある日付で偽陽性が出た(週末スパイクを拾った)

approve時間の系列は ノイズが大きく、導入日に明確な不連続はありませんでした

C. PRサイズで層別する ← これが本丸

ここで一番大きな交絡が見つかりました。導入前後で PRの中身そのものが激変 していました。

指標 導入前 導入後
PRの変更行数(中央値) 72 行 17 行
変更ファイル数(中央値) 4 2
Bot由来PRの割合 18% 28%

PRが小粒になり、依存更新Botなどの自動PRが増えていました。小さいPRは、どんなレビュー施策があろうと速く承認され、コメントも少ない です。サイズ別バケットで前後比較すると、生の大幅短縮はほとんど消えました。小さいPRではapprove時間はむしろ横ばい〜微増ですらありました。

D. 多変量回帰で「調整後の効果」を出す

最後に、approve時間(対数)を 導入フラグ+トレンド+変更行数+ファイル数+Bot 著者+週末 で回帰しました。

  • 支配的だったのは 変更行数(圧倒的に有意)と Bot 著者(自動マージで約 −98%)
  • ドキュメント導入フラグの係数は統計的に有意でなかった(点推定はわずかに正ですらあった)

結論は、

当初の「−73%」は実装観点のドキュメント化の因果効果ではない。PRの小粒化・Bot PRの増加という構成変化、既存の下降トレンド、同日の別運用変更で大部分が説明できる。


検証3: 「測れない」のか「効果が無い」のか

それで、有意な効果が出ない理由は

  1. そもそも統計が取れる環境ではない(測定の問題)
  2. ドキュメントが活用されていない(行動変容の問題)

のどちらなのでしょうか?

そこで、ドキュメントの目的に近い 近位指標 を設計しました。ここで再び PRコメントが測定の素材 になります。PRコメントの頻出事項からドキュメントを作りました。ならば、その後のPRコメントを同じ観点分類にかければ、「ドキュメント化した観点がレビューでどう変化したか」を直接測れる と考えました。

以下が検証項目です。

  1. 観点指摘密度 : VIEWPOINT.md に載っている観点に該当する指摘が、PRあたり何件出ているか
  2. ドキュメント済み指摘シェア : 「ドキュメント済み観点に当たる指摘」÷「実体のある指摘全体」。 ドキュメントに無い指摘を対照群に置いた差分の差分(DiD)
  3. 手戻り深さ : 指摘スレッドの往復回数・レビューラウンド数

項目2がポイントです。「全体のコメントが減った/PRが小さくなった」という、approve時間分析を壊した交絡に対し、 ドキュメント済み観点 vs それ以外の相対比 なら影響を受けにくいと考えられます。ドキュメントがレビューに浸透しているなら、

  • 実装者が観点を内面化して ドキュメント済みのアンチパターンを実装時点で先回り すれば、該当指摘は減る
  • あるいは(AI含む)レビュアーがドキュメントを使って より多く拾う ようになれば、該当指摘は増える

いずれにせよ「ドキュメント済みカテゴリ」の比が、対照群に対して動くはずです。

ドキュメントのタクソノミ*3でPRコメントをLLM分類する

最初にキーワードベースの決定的分類器を試しましたが、分類できたのは約10%。日本語・英語混在の自然なコメントには到底足りず、再現率 (recall) を確保するにはLLMでの分類が必須でした。

LLM分類器では以下のようにレスポンスを構造化しました

{
  "is_substantive": true,        // LGTM やステータス報告など非指摘を除外(分母)
  "categories": ["A3", "SEC"],   // ドキュメントの観点コード(0個以上, 多ラベル)
  "severity": "low|med|high",
  "is_novel_concern": false      // 実体ある指摘だがドキュメントに無い → 対照群
}

categories のenumは、ドキュメントのアンチパターン表(A1〜A21)+セキュリティ/パフォーマンス/領域別観点をそのままコード化したものです。つまり、 頻出事項ドキュメントがそのまま分類タクソノミ になります。

PRサイズ・著者・日時・スレッド往復数といった メタデータはコード側で JOIN します(LLM に出させない=出力トークン節約と精度維持)。

観点定義はプロンプトキャッシュに固定し、コメントをバッチで投げました。

実際の分類はコーディングエージェント自身(サブエージェント)を並列に走らせて行いました。検証を導入日±3週間のバランスウィンドウ(約 2,000 件)に絞り、それらを35バッチに分け各エージェントがバッチを読み込み → タクソノミで分類 → 結果をディスクに書き出すフローを1回の並列パスで完了し、その出力からコード集計で全指標を算出しました。

それでも、効果は検出できなかった

近位指標の結果(導入日を境にした前後比較、約 2,000 件のコメント)。

指標 導入前 導入後 判定
ドキュメント済み指摘シェア 82.1% 86.0% +4pt だが 非有意(z=1.48, p≈0.14)
ドキュメント済み指摘/PR 1.95 2.24 減るどころか微増
レビュースレッド深さ(中央値) 2 2 横ばい
往復ありスレッド率 60.9% 70.8% 手戻りはむしろ増

期待した「ドキュメント済みアンチパターンが 実装時点で先回りされ、レビューに現れなくなる 」という結果はどこにも出ていませんでした。指摘も手戻りも横ばい〜微増でした。

意義が大きいのは、 交絡に強い近位指標でも、遠位指標と同じく「効果なし」だった ことです。「効果はあるのに測れていなかった」のではなく、「この時点でドキュメントの行動への足跡が観測できない」というのが実態に近いことがわかりました。


ただし「ドキュメント化は無意味」とは限らない

調査の結果言えるのは「この観測ウィンドウでは有意な効果が検出できなかった」までで、以下の点に留保する必要があります。

  1. 観測ウィンドウが導入直後・数週間と短い : 実装者がドキュメントを内面化して挙動が変わるにはラグがある。先回り効果は数ヶ月スパンで遅れて出る可能性が高く、「早すぎて見えない」を排除できていない。
  2. 分類の偏り : 構造化された指摘への過剰なカテゴリ付与などがシェアを底上げしている恐れがある。実際、AI レビューアーのコメントはほぼ 100% が観点付与され、過剰付与の疑いがあった。
  3. 個別カテゴリは件数が疎で検出力不足 : 一部カテゴリは別の移行作業のノイズと交絡している。

したがって、 今回設計・検証した近位指標を、より長い期間の時系列として継続観測する とよさそうです。


持ち帰った教訓

今回の取り組みでは施策自体の良し悪し以上に、評価の作法を意識した導入・検証の重要性を痛感しました。

そこで得られた教訓は以下のようなものです。

  1. まず「対象の構成変化」を疑う : リードタイムやコメント数のような指標は、施策の効果よりも「作業単位(PR・タスク)のサイズや種類の分布」に支配されやすい。母集団の構成を揃えず、あるいは層別・調整せずに前後比較すると、ほぼミスリードする。
  2. 遠位指標と近位指標を区別する : 施策の効果は、その施策が直接触れる対象(=近位)に最初に現れる。リードタイムや満足度のような「手元にある便利な数字」は、効果から何段も離れた遠位指標であることが多い。施策の作用機序に最も近い指標を設計するのが先決。
  3. 「測れない」と「効果が無い」を切り分ける : 有意差が出ないとき、ノイズや交絡で隠れているのか or 本当に効果が無いのかは別問題。交絡に強い指標を一つ用意できればこの二つを切り分けられ、結論の確度が上がる。
  4. 変更を同時に束ねるな : 複数の介入を同じタイミングで入れると、どれが効いたのかは原理的に分離できなくなる。効果を後から評価したい施策は、他の変更から切り離してリリースする。
  5. 行動変容を伴う施策は、導入直後でなく継続トラッキングで評価する : 人の習慣や挙動が変わるにはラグがある。導入直後の一発の前後比較は、遅れて現れる効果を取りこぼす。時系列で追う前提で計測基盤を用意しておく。
  6. LLMは「これまで割に合わなかった測定」を現実的にする : 大量の非構造テキスト(コメント・ログ・チケット)を分類・集計して指標化する、といった作業は従来は人手のコストに見合わなかった。単一パス設計・プロンプトキャッシュ・バッチ並列で、こうした近位指標が安価に回せるようになった。測定対象の生成にも、測定そのものにもAIを使えるのは、評価設計の自由度を大きく広げる。

結果的に、劇的な数字に飛びつかず正体を確かめにいったことが今回の取り組みの価値に繋がったと思います。


さいごに

Legalscapeではエンジニア全方面で募集中です。AIを用いた開発の効率化に興味がある方、弊社に興味に湧いた方がいればぜひお気軽にご連絡ください

www.legalscape.jp

*1:分析対象のデータ範囲(区間)

*2:調べたい「原因」と「結果」の間に介入し、あたかも両者に関係があるかのように見せかけてしまう「第3の要因」

*3:大量のデータや情報を検索・整理しやすくするために、大分類・中分類・小分類のように木構造で分類する手法