🚄

全PRの83%をAIレビューだけでマージできるようにした

に公開2

はじめに

カウシェでは、PRの83%が人間のコードレビューを経ずに自動でマージされています。
GitHub Actions上で動くAIレビュー(Claude Code Action)がPRを自動でApproveし、CIが通ればそのまま自動マージされる仕組みです。
本記事では、レビュールールを毎晩自動改善する仕組みを作ることで、自分たちの運用で許容できるレベルまでAIレビューの精度を引き上げた話を書きます。

これが成り立つ前提

カウシェはtoCのECプラットフォームで、バックエンド・フロントエンド・モバイルを1つのモノレポで開発しています。
決済や認証など不可逆な領域は人間がレビューしていますが、それ以外は万一バグが出ても迅速にロールバックや修正デプロイで対応できるので、auto-mergeという選択肢が取りやすい環境です。
その上で、83%の自動マージはAIレビューの精度だけで成り立っているわけではなく、以下の前提があります。

コード品質の担保

  • テスト
    • バックエンドでは原則としてE2Eテストを書いています
    • gRPCエンドポイントごとに正常系・異常系をステータスコード別に検証していて、テストと実装は原則セットで出します
    • AIレビューがバグを見逃しても、E2Eテストやlintを含むCIパイプラインで検出される確率が高い構成です
  • Design Doc
    • 機能開発の前にDesign Docを書きます
    • L1(メモレベル)からL4(アーキテクチャレベル)まで粒度別のテンプレートが用意されていて、実装の前に設計方針を揃えています
    • AIに実装させる際も、このDesign Docをもとに実装方針を決めています
  • 開発方針の明文化
    • バックエンドのコーディング規約、テストポリシー、API設計ガイドラインをLiving Docとして維持しています
    • レイヤー構造(handler/usecase/domain)、命名規約、エラーハンドリング方針などが明文化されていて、AIレビューはこれらを読み込んで準拠性をチェックします

速度と品質を並列で回すカルチャー

カウシェではできるだけ早く本番に反映させてユーザーに価値を届けたいと考えています。
コード品質は重視していますが、即座に対応が必要でない改善点のためにマージを止めることはしません。改善は別PRで追いかけます。

AIレビューでマージをブロックしない運用にするために、事前にこのカルチャーを浸透させました。
機能開発とは別に、コード品質の改善だけを目的としたPRを日常的に出す文化です。
技術的負債を見つけたらその場で直しますし、AIレビューの改善提案もすぐ別PRで拾います。

加えて、AIレビューが出した改善提案(SUGGESTIONと呼んでいます)が放置されないための仕組みもあります。

AIレビューは過去に出した指摘が未対応のまま残っている場合、次のPRのレビュー時に改めて指摘します。
同じ開発者が同じカテゴリの指摘を繰り返し受けている場合は、過去のPRを引用して重点的にチェックします。

カルチャーだけに頼らず、仕組みとしてもフォローアップが回るようにしています。

AIレビューの構築

チームがこれまで蓄積してきたレビューの知見をAIに読み込める状態にするところから始めました。

  • サービスごとにレビュー設定ファイルを用意して、以下のような内容を構造化しています
    • レビュー判定ルール
      • PRの変更内容に応じて「AIレビューのみでの承認でOK」「人間のレビュー必須」「念のため人間が確認(auto-mergeは止めて人間にエスカレーション)」を振り分ける条件
    • コードの危険度マップ
      • コードベースの領域ごとに「壊れたときにどれだけ困るか」をcritical/high/medium/lowで定義
      • たとえば決済フローはcritical、補助機能はlow
    • DBの危険度マップ
      • テーブルごとのデータサイズと、DDL変更時の注意事項
    • ドメイン知識
      • コードだけ読んでもわからない背景情報
      • 例えば、連携先SaaSのAPIの非公式な挙動や、過去のインシデントから得た教訓など
  • リポジトリ作成以降の過去のPRを全件収集・分析して、レビューコメントのパターンをナレッジベースに反映

3人の専門家による並列レビュー

AIレビューは1つのAIがdiffを見て判断するのではなく、3人の専門家ペルソナに並列でレビューを依頼して結果を統合する構造です。

  • シニアGoエンジニア: コード品質、規約準拠、テストカバレッジ
  • シニアアーキテクト: 設計の整合性、セキュリティ(認証バイパス、情報漏洩、インジェクション等)、ドメイン知識との照合
  • GCP専門家: DBクエリの効率、インフラへの影響、非同期処理の冪等性

各専門家はdiffだけでなく、変更内容に応じて以下の文脈を選択的に読み込んだ上でレビューします。

  • レビュー設定ファイル
    • 危険度マップ、ドメイン知識
  • コーディングガイドライン
    • サービスごとに用意しているアーキテクチャ説明、ディレクトリ構造、命名規約、テスト方針をまとめたファイル
  • サービス横断パターン集
    • DBトランザクションの制約やAPI規約など、サービスをまたいで適用できる知見をまとめたファイル
  • 検出ルール(レビュー設定ファイルとは別に管理)
    • 後述する自動改善ループが過去の見逃しから自動生成したルール
  • 開発者プロファイル
    • PRの作者の過去の実績
    • 経験豊富な開発者にはSUGGESTIONを減らし、特定のカテゴリで繰り返し指摘がある開発者にはそのカテゴリを重点チェックする
    • Approve/Rejectの判定基準自体は開発者によって変わりません。変わるのはSUGGESTIONの量だけです
  • PR本文、コメント、実装計画
    • 作成者の補足コメントや過去のAIレビューコメントも読みます
    • たとえば一度Rejectされた後に「実装の都合上ここは今のまま許容して、後続のPRで変更します」とコメントすれば、再レビュー時にその文脈を踏まえて判断します
    • 実装計画がリンクされていれば、段階的実装の中間状態を許容します

たとえばサービス横断パターン集は全文読み込みではなく、エラーハンドリングの変更なら該当セクションのみ、DBスキーマ変更ならDBのセクションのみを読みます。

各専門家の指摘はBUGとSUGGESTIONに分類された後、トリアージされます。
diffの変更に根拠がない指摘の除外、前回のレビューと矛盾する指摘の検出、曖昧な指摘の除外を行ってから最終判定に使います。

AIレビューのみでのauto-mergeを実現するためにやったこと

構築したAIレビューを運用していく中で、auto-mergeに耐えるレベルにするには「AIがどこまで判断するか」と「ルールの鮮度をどう保つか」の2つを解決する必要がありました。

判定原則とAI/人間の役割分担

まず判定原則として「却下すべき理由がないならApprove」を入れました。

  • マージをブロックするのは、そのまま本番環境に出してはいけない問題や、コードベースの保守性を著しく損なう変更のみ
    • ランタイムエラー、データ不整合、セキュリティ脆弱性、トランザクション境界の誤り等
  • それ以外はSUGGESTION(改善提案)としてコメントに残すが、マージはブロックしない
    • 品質はカルチャーとSUGGESTIONフォローの仕組みで担保しています

次に、AIに判断させる範囲と人間がオーナーシップを持つ範囲を分けました。
不可逆な変更や手戻りコストの高い領域は、AIの判定結果にかかわらず人間レビューにエスカレーションしています。

  • DBスキーマ変更、Proto定義の変更: ロールバックが難しい、クライアント互換性に影響
  • Terraform変更: plan結果を人間が確認してからapply
  • 認証・決済フロー: AIレビューでもセキュリティチェックは行っていますが、auto-mergeはせず人間が最終判断する
  • 実装計画、Design Doc: 実装の方向性を決めるものなので人間が握る
  • AIが判断しきれないケース(大規模なアーキテクチャ変更、複数サービスにまたがる変更)

日常的なサービス開発PR(機能追加、リファクタリング、テスト追加など)はAIレビューに任せています。
83%の自動マージは、この判定原則と領域分けを適用した上での数字です。

ルールの鮮度をどう保つか

auto-mergeを実現するために解決すべきもう1つの課題が、レビューに使うルールの鮮度でした。

  • コードベースは毎日変わるのに、レビュー設定ファイルが追従しない
  • 使われないルールがコンテキストウィンドウを食いつぶして、必要なルールの精度を下げる
  • 新機能が入るたびにレビュー観点も変わるのに、人間がルールを追加するまでAIは追いつけない

ナレッジを手動メンテし続けるのは厳しいと感じていました。
そこで、ナレッジの追加・削除・修正を自動化する仕組みを作りました。
計測・発見・改善・統合・監査の5つの役割をそれぞれ別のエージェントに担わせて、毎晩ループで回しています。

各エージェントはClaude Code Actionで動いています。

  • Measure: 直近のPR統計(承認率、誤判定数、ルールごとの発火率、開発者ごとの実績)を集計する
  • Explore: リポジトリやインフラを巡回して、数字だけでは見えないボトルネックや未知のパターンを探す
  • Improve: MeasureとExploreの出力を読んで、検出ルールやパターン集を実際に編集する
  • Reflect: 3つのエージェントの出力を横断的に読んで、翌日の優先順位を決める。各エージェントは翌日このファイルから自分への指示を読む
  • Audit: 全エージェントの変更を検証して、改善が逆効果になっていないかをチェックする

各エージェントは毎回新しいセッションで動くので、前回の判断を覚えていません。
そこで思考ジャーナル(前回の判断記録)を書かせて、実行のたびにそれを読んでから動くようにしています。
たとえばMeasureが「ある指標が悪化した → でも前回サンプル数が激減していた → 統計的ノイズだ」と判断できるのは、前回のジャーナルに書いてあるからです。
プロンプトの冒頭で「前回のジャーナルを読んでから判断しろ」と指示することで、毎回の実行に連続性を持たせています。
クリストファー・ノーラン監督の映画『メメント』のように、前回の自分が残したメモとナレッジファイルを頼りに判断する構造です。

カウシェではAIレビューとは別に、AIレビューの検出漏れを補完する目的で外部のレビューツールも並行して動かしています。
実際に、AIが見逃したバグを外部ツールが検出したケースがありました。
翌日Measureがこの見逃しを記録し、Improveが類似の見逃し数件を横断分析して検出ルールを自動生成しました。
このルールが後日別のPRで発火して、正しく機能することも確認されています。
こうしたルールが数十件生成されていて、今も増え続けています。

一方で使われないルールは自動で整理されます。
Measureがルールごとの発火数(レビューで参照された回数)と効果数(判定の改善に寄与した回数)を追跡していて、効果スコア(効果数÷発火数)が低いルールはImproveがアーカイブします。
ルール数には上限を設けていて、超過した場合も効果スコアが低い順に整理されます。

安全面では、エージェントごとに書き込み可能なファイルを制限しています。
MeasureがImproveのルールを書き換えたり、Improveが計測データを改竄したりすることは構造的にできません。
また、同じ夜のループの最後にAuditが全エージェントの変更を検証して、問題があればエスカレーションします。

再現するなら

  • Step 1: 前提を整える
    • E2Eテスト・コーディング規約・CIパイプラインが先に必要です
    • レビュー設定ファイルは最初から完璧に書く必要はありませんが、最低限コーディング規約と、コードベースのどの領域が危険か(決済フローはcritical、補助機能はlow等)の危険度マップは必要です。これがないとAIはすべての変更を同じ優先度で扱ってしまいます
  • Step 2: まずレビューコメントから始める
    • いきなり自動マージではなく、AIのレビューコメントをPRに付けるところから始めます
    • 最初の数週間はコメント投稿のみにして、AIの判定がどの程度正確かを確認します。内部的にはApprove/Rejectの判定を出しますが、GitHub上ではコメントに留めて自動マージは有効にしません
    • 判定原則は最初から「却下すべき理由がないならApprove」にしておくのがおすすめです
    • 主観的な理由でRejectが頻発すると、開発者にとってAIの指摘がノイズになり、本当に重要な指摘も含めて読まれなくなるリスクがあります
    • auto-approve/auto-mergeへの切り替えは、次のステップで述べる計測指標(誤判定数と見逃し率)が十分低く安定してきたタイミングで判断します
  • Step 3: 計測と改善の循環を回す
    • 以下の指標を定期的に集計して、ルールの追加・削除に使います
      • 承認率: AIがApproveしたPRの割合
      • 誤判定数: AIと人間の判断が食い違ったPRの件数(AIがApproveしたが人間がRejectした、またはAIがRejectしたが人間がoverrideしてマージした)
      • 見逃し数: AIがApproveしたがマージ後にバグが発覚したPRの件数
    • この数字がないとルール変更が良い方向に効いたのか判断できず、感覚での運用になります
    • 計測と改善は別のエージェントに分けるのが大事です。同じエージェントにやらせると自分の改善効果を自分で計測する構造になります

おわりに

4ヶ月ほど運用してみて学んだのは、AIレビューの質は何を見つけるかではなくて、何を見ないかで決まるということです。指摘を絞ったら、本当に対応すべきものだけが残りました。そしてその「何を見ないか」の判断を毎晩自動で更新し続けるのがこの仕組みです。

コードレビューにはチームの共通理解を揃える役割もあります。
人間が見ている17%はDBスキーマや設計判断、アーキテクチャ変更で、チームの方向性に関わるPRはちゃんと人間を通しています。
設計方針の共有はDesign Docのレビューで実装前にやっています。
定型的なPRのレビューから解放された分、こういう判断に時間を使えるようになりました。

AIが検出できるのはルール化できるパターンに限られていて、設計のトレードオフやビジネス上の妥当性の判断は人間にしかできません。
この境界をどこに置くかは今も試行錯誤していますが、人間が本当に頭を使うべきレビューに集中できる状態を作れたのは大きな前進だと思っています。

カウシェ Tech Blog

Discussion

myztmyzt

残り17%はどんなことをしているのかが気になります!

a-thuga-thug

人間が見ている残り17%ですが、だいたい以下をやってます!

DBスキーマの変更
設計判断(Design Docもgithubで管理している)
アーキテクチャ変更や共通ライブラリなど、影響範囲が大きい変更
認証・決済フローなどのcritical領域の変更
複数サービスにまたがる変更
チームでの開発施策の方向性に大きく関わる変更(例えばドメインモデリングやコアロジック周りなど)