ENECHANGE Developer Blog

ENECHANGE開発者ブログ

人間によるレビュー指摘を蓄積してAIコードレビューの精度を高める

はじめに

弊社の開発では ClaudeCode をはじめとした AI エージェントによるPRコードレビューを利用するのが日常になっていますが、商用製品としてのクオリティを担保するためにも必ずマージ前に人間によるレビューも行っています。

しばらくこの運用を続けていると 複数PRに渡り人間が何度も同じ種類の指摘をしている という問題が顕在化してきました。

例えば以下のような指摘が頻繁にあがっています。

  • 責務の分離・配置:「この処理は呼び出し元ではなく処理側で自己完結させるべき」「定型コンテンツは別ファイルに切り出すべき」といった、コンポーネント間の役割の境界に関する指摘
  • 実装品質:「同一リソースへの重複アクセスを避ける」「同一リソースへの操作を冪等に設計する」「使用したリソースは必ずクリーンアップする」といった実装の堅牢性に関する指摘
  • ドキュメントの明確さ:「前提条件や操作対象を明示してほしい」「具体的なコード例をドキュメントに含めてほしい」「新機能を追加したら利用方法も記載してほしい」といった記述スタイルに関する指摘

中には CLAUDE.md に記載のポイントも含まれておりエージェントによるレビュー時も考慮されているはずですが、同じ指摘が繰り返される状況が続いていました。

そこで、過去の人間レビューコメントからレビュー観点を抽出し、蓄積して AI レビューで活用する仕組みを作りました。

この記事では、その仕組みの設計と実装について紹介します。

仕組みの全体像

PRマージ後から次回のレビューまでの流れは以下のとおりです。

PRマージ
  ↓
人間レビューコメントから観点を自動抽出
  ↓
レビュー観点の追加・更新をするPRを作成、マージ
  ↓
以降のPRレビュー時に AI が観点を参照

AI レビューを行うエージェントは観点ファイルを読み込み、人間目線の観点を考慮しながらコードを評価します。

このファイルはリポジトリにコミットして管理するため、チームメンバー全員で観点を共有でき、変更履歴もバージョン管理の中に残ります。

観点ファイルの管理

YAML フォーマット

PRレビューから抽出した観点は yaml ファイルで構造的に管理しています。基本的な構造は以下のとおりです。

version: 1

insights:
  - id: "insight-{3桁連番}"
    category: "{カテゴリ}"         # design / security / performance / testing / style
    severity: "{重要度}"           # CRITICAL / WARNING / INFO
    title: "{観点を一言で表すタイトル}"
    guideline: |
      {望ましい実装方針}
    anti_pattern: |
      {問題のある実装パターンの例}
    good_pattern: |
      {望ましい実装パターンの例}
    scope:
      - "{適用対象のファイルパス(グロブ形式)}"
    status: active                 # active / retired
    frequency: {指摘された累計回数}
    last_seen: "{最後に確認された日付 YYYY-MM-DD}"
    added_from_pr: {最初に抽出・追加されたPR番号}
    evidence:
      - pr: {コメントが投稿されたPR番号}
        comment_url: "{コメントへの URL}"
        summary: "{コメント内容の要約}"

観点の記述ルール

観点の追加・更新時に意識しているルールをいくつか紹介します。

抽象度を適切に保つ

「PR #42 でこの変数名が悪かった」のような個別事例をそのまま記録するのではなく、再発する可能性のある観点として抽象化しています。

ただし抽象化しすぎると「コードの品質を高める」のような意味のない観点になってしまうため、guidelineanti_pattern / good_pattern で具体的な判断基準を示すようにしています。

重複の扱い

新しいレビューコメントを追加する際は、既存の観点と意味的に類似していないかをまず確認します。

類似する観点があれば新規追加ではなく frequency のカウントアップと evidence への追記に留めます。

表現や用語が異なっていても「根本的に同じ欠陥・懸念を指しているか」を判断の軸にしています。

新しいコメントが既存観点より広い範囲をカバーしている場合は scope の見直しも行います。

不要になった観点の退役

観点が不要になった場合は削除するのではなく status: retired に変更し無効化します。

「なぜこの観点を外したか」の経緯を残すために退役の理由(retired_reason)・退役を決定したPR(retired_from_pr)・退役日(retired_at)もあわせて記録するようにしています。

メンテナンスワークフロー

PRマージ後:観点の抽出と追加

PRマージ後にエージェントに指示を出すと、以下の処理が自動で行われます。

flowchart TD
    A[PRマージ] --> B[全コメントを取得]
    B --> C[Bot・AI・指摘内容のないコメントを除外]
    C --> D{既存 insight と意味照合}
    D -- 類似あり active --> E[frequency++ / last_seen 更新 / evidence 追記]
    D -- 類似あり retired --> F[スキップ]
    D -- 類似なし --> G[新規 insight 草稿を生成]
    E --> H[review-insights PRを作成]
    G --> H
    H --> マージして次回以降のレビューから活用

作成された review-insights PRには変更内容(追加した観点・更新した頻度・元コメントの抜粋)が記載されるため、チームメンバーがレビューして問題なければマージします。

観点の却下:[REJECT] によるリプライ

エージェントが insight に基づくレビューコメントを投稿した際、その観点が「このリポジトリでは意図的に許容している」「過剰な観点だった」と判断した場合は、エージェントのレビューコメントに対して [REJECT] で始まるリプライを返します。

[REJECT] このリポジトリではパフォーマンスより可読性を優先しているため許容している

このリプライを検知すると、対象の insight を退役させるPRが自動で作成されます。

PR本文には退役対象の観点・退役理由・元コメントへの参照が含まれるため、退役の判断をチームで確認した上でマージできます。

今後の展望

この仕組みを導入した現時点は「insight を記録し始めた」フェーズです。以下、さらに発展させていきたいことを紹介します。

頻度データの活用

frequency フィールドはPRをまたいで自動的に積み上がっていくため、運用を続けると「どの観点が最も繰り返されているか」がデータとして見えてきます。

頻度が高い観点はチーム、エージェントの盲点になりやすい領域を示しており、コードベースの構造的な問題を把握するヒントになる可能性があります。

CLAUDE.md / rules への昇格

frequency が積み上がり「これはプロジェクトの不変のルール」と判断できる観点は、insight のまま管理し続けるより CLAUDE.md や rules に昇格させる方が効果的であると期待できます。

insight のままだと「実装→レビューで検知→修正」のフローが必要になりますが、CLAUDE.md / rules に昇格すれば実装段階で防げるようになります。

「insight で蓄積 → 頻度を観察 → 成熟した観点を CLAUDE.md / rules に昇格 → insight を retired」というサイクルを回すことで、AI との協働の品質が継続的に向上していく状態を目指しています。

おわりに

人間レビュアーが繰り返す指摘をエージェントに「教える」という発想で作ったこの仕組みは、運用を続けることで観点ファイルが自然に育っていきます。

どの観点を採用するか・どの観点を退役させるかをPR経由で決めていくプロセス自体が、チームのレビュー基準を言語化していく機会にもなっている点も、導入してみてよかった点の一つです。

ENECHANGE で働きませんか

ENECHANGE では、AI 時代の開発体験を支える技術選定から一緒に取り組んでくれる仲間を募集しています。ぜひ 採用情報 をご覧ください。