SEN PRODUCT BLOG

千株式会社のプロダクト開発メンバーによるブログ

AIでPRレビューコメントからコーディングガイドラインを自動更新する

はじめに

はじめまして、千株式会社でエンジニアをしています、 daitasuです!

昨今、ハーネスエンジニアリングが話題になっており、skills、hooks、orchestration、rules などなど、様々な企業で事例が出てきています。

そんな中、私が現在所属しているデザインシステムを構築している開発チームでは、AIによるSelf-improve として、

PRのレビューコメントをもとにコーディングガイドラインを自動更新する」仕組みを取り入れています。

今日はその取組みについてご紹介します。

課題

AI による開発で、私たちのチームでは、Codex、Claude Code、Gemini Code assist、Cursor 等様々なツールを用いています。

これらのskill はシンボリックリンクで参照されるようになっているのですが、コーディングガイドラインとしては docs/ 配下にまとめているものを参照しています。

.
├── AGENTS.md                          # AI エージェント共通指示
├── CLAUDE.md -> AGENTS.md       # Claude Code 用(シンボリックリンク)
│
├── .agents/skills/                    # 共有スキル定義(実体はここに集約)
│   ├── commit/
│   ├── frontend-expert/
│   ├── review-pr/
│   ├── ・・・
│   └── typescript-expert/
│
├── .claude/
│   └── skills/                        # Claude Code 用スキル(→ .agents/skills/* へのシンボリックリンク)
│       ├── typescript-expert -> ../../.agents/skills/typescript-expert
│       ├── review-pr -> ../../.agents/skills/review-pr
│       └── ・・・
│
├── .codex/
│   └── AGENTS.md                      # OpenAI Codex 用プロジェクト指示
│
├── .gemini/
│   ├── config.yaml                    # Gemini Code Assistant 設定
│   └── styleguide.md                  # Gemini Code Review 用スタイルガイド
│
└── docs/
    └── coding-guide/                  # コーディングガイドライン(全ツール共通で参照)
        ├── frontend.md                # フロントエンドガイドライン
        ├── ・・・                      # 各種ガイドライン

各AIツールはコーディングガイドラインを参照して実装をしています。

私たちのチームは、プロジェクトとしての立ち上げ期なこともあり、開発を進めていく中で変更したい項目が出てきたり、AIの精度上プロジェクトルールとして追加したい項目が増えたり、と見えてくるものもありました。

その都度人の手で改修を加えていくのも手ではありますが、AIによって自動でルールを更新させて、自動で精度向上に繋がっていく基盤を構築したかった ため、Gemini API を用いた自動更新の仕組みを作成しました。

やったこと

Github Action の構築

私たちの開発では、基本的には gemini-code-assistClaude Code の skill によってAIレビューを挟んでいます。

とはいえ、設計思想であったり、ドメイン知識であったり、AI のルール不足による方向性のズレ、といった点は最後に人間がレビューをしています。

今回は、PRがマージされたタイミング人間が指摘したPRのレビューコメントを見て、改修の必要性があればAIがコーディングガイドラインを自動修正したPRを立てる というものを作りました。

name: Review Feedback to Guidelines

on:
  pull_request:
    types: [closed]
    branches: [main]

jobs:
  analyze-and-improve:
    name: Analyze review comments & improve guidelines
    # マージされた PR のみ(close しただけの PR はスキップ)
    if: github.event.pull_request.merged == true && !startsWith(github.event.pull_request.head.ref, 'docs/review-feedback-')
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      contents: write
      pull-requests: write

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          ref: main

      - name: Setup pnpm
        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4

      - name: Setup Node.js
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
        with:
          node-version-file: .node-version
          cache: pnpm

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Analyze review comments
        id: analyze
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GOOGLE_GENERATIVE_AI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
          REPO_OWNER: ${{ github.repository_owner }}
          REPO_NAME: ${{ github.event.repository.name }}
        run: node .github/scripts/analyze-review-feedback/index.ts

      - name: Create Pull Request
        if: steps.analyze.outputs.has_updates == 'true'
        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          branch: docs/review-feedback-${{ github.event.pull_request.number }}
          delete-branch: true
          title: "docs: レビューフィードバックからガイドライン更新 (#${{ github.event.pull_request.number }})"
          body: |
            ## Summary

            PR #${{ github.event.pull_request.number }} (${{ github.event.pull_request.title }}) のレビューコメントを解析し、以下のガイドラインを改善しました。

            ${{ steps.analyze.outputs.summary }}

            ## 元 PR

            ${{ github.event.pull_request.html_url }}

            ## 注意

            - この PR は自動生成されています。内容を確認してからマージしてください。
            - 不要な変更が含まれている場合は、該当部分を revert してください。

            ---
            Generated by [Review Feedback Action](.github/workflows/review-feedback.yml)
          labels: docs,automated
          assignees: ${{ github.event.pull_request.user.login }}
          reviewers: ${{ github.event.pull_request.user.login }}
          commit-message: "docs: レビューフィードバックからガイドライン更新 (#${{ github.event.pull_request.number }})"

仕組み上は至ってシンプルで、マージされたPRのレビュー内容をGithub API で取得して、Gemini に咀嚼して改修案を立ててもらう。

その後、 peter-evans/create-pull-request を用いてPR を作成する、という流れになってます。

PR コメントを読み取り、整形、Gemini の解析をかける

CI の run: node .github/scripts/analyze-review-feedback/index.ts の部分は、PRから拾ったレビューコメントを整形してGeminiに送るスクリプトを組んでいます。

愚直に文字列整形をしてるのが大半なので、詳細は割愛しますが、主に下記の流れを取っています。

  1. Github API からレビューコメントを取得
  2. コメントを整形
  3. 現在のガイドラインを一通り読み取る
  4. Gemini API でコメントを解析
  5. ガイドラインファイルを更新
  6. 修正のサマリーを出力(CIに返却して利用するため)

Gemini API による解析

取得したレビューコメントは、下記のようにしてGemini API でAI解析にかけています。

import { generateText, Output } from "ai";
import { google } from "@ai-sdk/google";
import { z } from "zod/v4";

export const TARGET_FILES = [
  {
    path: "docs/coding-guide/frontend.md",
    description:
      "フロントエンド(React / TailwindCSS / テスト)のコーディングガイドライン",
  },
  // ・・・ 
  // いくつかのコーディングガイドやプロジェクトルールファイルを参照
  {
    path: ".claude/skills/review-pr/SKILL.md",
    description:
      "Claude Code の PR レビュースキル定義(レビュー観点・ラベル体系・手順)",
  },
  {
    path: ".gemini/styleguide.md",
    description:
      "Gemini Code Review 用スタイルガイド(コーディング規約サマリー)",
  },
] as const;

const paths = TARGET_FILES.map((f) => f.path);
if (paths.length === 0) {
  throw new Error("TARGET_FILES cannot be empty.");
}
const VALID_PATHS: [string, ...string[]] = [paths[0], ...paths.slice(1)];

const guidelineUpdateSchema = z.object({
  path: z.enum(VALID_PATHS).describe("更新対象のファイルパス"),
  updatedContent: z.string().describe("改善を反映したファイルの完全な内容"),
  summary: z.string().describe("何をどう変えたかの要約(日本語)"),
});

export type GuidelineUpdate = z.infer<typeof guidelineUpdateSchema>;

type FormattedComment = {
  author: string | undefined;
  path: string | undefined;
  line: number | undefined;
  body: string | undefined;
  diff_hunk: string | undefined;
};

type FormattedReview = {
  author: string | undefined;
  state: string | undefined;
  body: string | undefined;
};

// --------------------------------------------------------------------
// Gemini による解析
// --------------------------------------------------------------------

export const analyzeReviewComments = async (
  prNumber: string,
  formattedComments: FormattedComment[],
  formattedReviews: FormattedReview[],
  currentFiles: Record<string, string>,
): Promise<GuidelineUpdate[]> => {
  const guidelineContext = Object.entries(currentFiles)
    .map(([path, content]) => `### ${path}\n\`\`\`markdown\n${content}\n\`\`\``)
    .join("\n\n");

  const { output: updates } = await generateText({
    model: google("gemini-2.5-flash"),
    output: Output.array({ element: guidelineUpdateSchema }),
    system: `あなたはコードレビューのフィードバックからコーディングガイドラインを改善する専門家です。

以下の原則に従ってください:
- レビューコメントから、ガイドラインに反映すべき**汎用的な知見**のみを抽出する
- 特定の PR にしか当てはまらないコメント(個別のバグ修正指示など)は無視する
- 既にガイドラインに記載済みの内容と重複する追加は行わない
- 変更は最小限に留め、既存の構造・フォーマットを維持する
- 変更がない場合は、空配列を返す`,
    prompt: `## PR #${prNumber} のレビューコメント

### インラインコメント
${JSON.stringify(formattedComments, null, 2)}

### レビューボディ
${JSON.stringify(formattedReviews, null, 2)}

## 現在のガイドラインファイル

${guidelineContext}

## タスク

上記のレビューコメントを分析し、ガイドラインに反映すべき汎用的な知見を特定してください。
改善が必要なファイルのみ配列に含めてください。
すべてのファイルで改善が不要な場合は空配列を返してください。`,
  });

  return updates ?? [];
};

結果

これにより、PRをマージした際に、必要に応じて下記のようなPRが自動で立てられるようになりました。

運用してみてどうか

実際に運用してみて、中々初回作って以降更新がされにくいコーディングガイドや CLAUDE.md.gemini/styleguide.md などのルールファイルが適宜成長していくようになり、AI 開発における心理的安全性が高まりました。

まだ立ち上げて 1, 2か月程度のプロジェクトで運用を回してみたので、もっとドメイン知識が複雑なプロジェクトやコーディングガイドが煩雑になっている既存サービスなどで運用を回すと、副次的な改善効果がより見えるようになるかもしれません。

課題感

いくつか課題があります。

  • 生成されるPR の精度が低い時がある
    • ルールファイル上の意図していない example コード例を削除
    • 必要以上に詳細に内容を書き込んでしまう
    • (ひどい時は)frontmatter を抹消するケースがあった
  • 生成された PR 上で修正がある場合、その修正もAI にしてほしい
    • 現状は修正したい場合は人の手が介在している

今回は社内の状況などを加味して Gemini API で構築しましたが、Claude Code Action に変更してモデルを変えてみるなど、まだこの自動修正の精度を上げるために模索する必要があります。

また、生成されたPR に修正を入れたい際も、レビューしたらAI が修正してくれる、という状況まで持っていく、のを次のステップとしたいです。

まとめ

AI 開発での生産性をより加速させていくうえで、こうした AI 自身に ルールを更新させて、ガードレールを自動強化する仕組みは、運用が進むほど効果が出ていくはずなので、Self improve の仕組みをチームでもっと作っていければと思ってます。

弊社、千株式会社では、ハーネスエンジニアリングで事業とプロダクトを加速させるエンジニアを引き続き募集しています!

sencorp.co.jp