← ブログに戻る

PRラベルnit/must機械分別で48h→24h

本記事の数値について: 「48h→24h」は私自身の運用で観測した値で、書籍 harness-code-review 第7章 (Conventional Comments) の設計を実装した結果です。厳密な平均は書籍の型に沿ってご自身のチームで計測し直してください。

本記事は文面テンプレートの話ではなく、.coderabbit.yaml と Conventional Comments ラベルを機械的に強制する話です。同じ code-review クラスタの前段として、コメントの言い回しを心理的に整える話は /ja/blog/ai-code-review-persuasion-psychology-1-5x-merge-speed/ に書きました。あちらが説得のレイヤーで、こちらは「そもそも指摘の種類を機械が識別する」レイヤーです。同じPR、違う階層の問題を扱っています。

「これは絶対に直してほしい指摘」と「気になっただけの指摘」を、以前の私のチームは同じ重さで受け取っていました。結果、レビュアーの何気ない一言が全部PRブロッカーになる。マージ待ち時間の中央値は48時間でした。

.coderabbit.yaml を1枚追加してから、この数字が24時間に落ちています。変えたのはコメント本文の書き方ではありません。コメントの頭に nit や must を機械的に付けさせただけです。

ゴミ分別と同じ理屈

ゴミ分別を「お願いします」で徹底できたチームを、私は見たことがありません。分別率が上がるのは、燃えるゴミ用の蓋がペットボトルを通さない形に変わったときだけです。人の意思ではなく、蓋の形が結果を出す。

Conventional Comments というレビュー慣習も同じです。praise / issue / suggestion / nitpick / question / thought などのラベルを頭に付けよう、というシンプルな規約が2020年からあります。CONTRIBUTING.md に書いておけば守られる、と最初は思っていました。守られていませんでした。

「明日から nit: を付けてね」と Slack で3回アナウンスして、翌週の PR コメント50本を見返したら、ラベル付きは4本。8%です。ゴミ分別と同じで、お願いだけでは変わりません。

Conventional Commentsを機械強制する前と後の判定フロー比較

.coderabbit.yaml に強制ルールを書く

CodeRabbit を使っているチームは、.coderabbit.yamlpath_instructions に1ブロック足すだけで済みます。全ての AI レビューコメントの頭にラベルが強制されます。

# .coderabbit.yaml
reviews:
  profile: chill
  auto_review:
    enabled: true
  path_instructions:
    - path: "**"
      instructions: |
        すべてのレビューコメントは Conventional Comments のラベルで開始すること。

        使用可能なラベル:
        - must: 修正必須。マージブロッカー
        - issue: 修正必須。マージブロッカー (must の別名でも可)
        - nit: 些細な改善。ブロックしない
        - suggestion: 改善提案。ブロックしない
        - question: 意図の確認
        - praise: 良いコードへの称賛

        must / issue 以外はブロッキング扱いにしない。
        must / issue のコメントには必ず「なぜ問題か」「どう直すか」を書く。

これで CodeRabbit が返してくるコメントは、頭が必ず must: nit: question: のいずれかで始まります。人間レビュアーは Saved Replies に同じテンプレートを登録して、Ctrl+. で呼び出せば同じフォーマットで書けます。

マージ時間が半分になった仕組み

数字だけ見ると「AIが速くなったのでマージも速くなった」に見えます。違います。変わったのはレビュイーの意思決定コストでした。

以前は「このコメントは直すべきか、直さなくていいか」を毎回考える必要がありました。1本のPRにコメントが20本付いたら、20回この判断をします。1回30秒でも10分です。10分の判断を毎日3回やれば、レビュイーのモチベーションは削れていきます。

nit / must を機械強制すると、この判断が消えます。must: は直す、nit: は好みで直す、question: は答える、praise: はスルー。判断が事前に済んでいます。レビュイーの脳の使い所が「直すかどうか」から「どう直すか」に移る。この差が、実測で 48h→24h の半減として出ました。

副次的な効果もありました。レビュアー側も「これは must なのか nit なのか」を書く前に一度考えるようになった。書きかけて nit: と付けた瞬間、「これは本当にレビューする必要があるコメントか」を自問する。結果、コメントの総本数自体が減りました。私のリポジトリで週次のレビューコメント数を計測したら、導入前100本/週から70本/週になっています。3割減。

CI で must: コメントをブロックする

ラベルを付けさせるだけでは、must: を無視してマージされる可能性が残ります。GitHub Actions でトップレベルの must: コメントを検出してブロックする workflow を1枚追加します。

# .github/workflows/must-gate.yml
name: Must Gate
on:
  pull_request:
    types: [synchronize, opened, reopened]

jobs:
  check-unresolved-must:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/github-script@v7
        with:
          script: |
            const comments = await github.rest.pulls.listReviewComments({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number,
            });
            const unresolved = comments.data.filter(c =>
              /^\s*must:/i.test(c.body) && !c.in_reply_to_id
            );
            if (unresolved.length > 0) {
              core.setFailed(
                `${unresolved.length}件の must: コメントが未解決です`
              );
            }

これで must: コメントは自動ゲートになります。nit: は無視できるし、question: は返信すれば解決扱いになるので、レビュアーが本当にブロックしたい指摘だけがマージを止める形になります。

ひとつ注意点があります。上のスクリプトは「トップレベルの must: コメントが1本でもあるか」しか見ておらず、GitHub の Resolve conversation 状態は見ていません。resolve してもコメント本文の must: 文字列は残るので、この簡易版のままだと CI は落ち続けます。教育目的のスターター実装として載せていて、厳密に未解決だけを判定したい場合は、GraphQL API の isResolved を使う版に差し替えてください。

導入時に踏んだ地雷

1つだけ書き残しておくと、must: の乱用でチームが壊れかけたことがありました。最初の1週間、あるレビュアーが体感で7割のコメントに must: を付けていて、レビュイーが萎縮してPRを出さなくなった。

対策として .coderabbit.yaml の instructions に「must は blocking 相当の指摘のみ、迷ったら suggestion または nit を使う」と1行足しました。人間レビュアーにも同じ基準を共有。3週間で must: の比率が全コメントの15%程度に落ち着いて、マージ時間の半減も定着しました。

ラベルの機械強制は、ラベルの意味論を揃える運用とセットで初めて効きます。ゴミの分別と同じで、蓋の形だけ変えて分別基準が曖昧なら結局ゴミが混ざります。ここは書籍の第7章 (Conventional Comments)、第9章 (CodeRabbit の導入と設定)、第11章 (GitHub Actions でレビューパイプラインを構築する) の全体設計にまとまっています。

まとめ

  • Conventional Comments を「お願い」で運用しても定着しない。私の実測で導入率8%
  • .coderabbit.yamlpath_instructions で AI レビューコメントの頭にラベルを機械強制する
  • トップレベルの must: コメントを CI でブロックし、nit: はブロッカーにしない (簡易版は Resolve conversation を見ていないので、厳密な未解決判定は GraphQL の isResolved に差し替え)
  • 結果、レビュイーの「直すか直さないか」の判断コストが消えて、マージ時間が48h→24hに
  • 副次効果でコメント総本数が3割減、レビュアーも書く前に一度考えるようになる

本書 harness-code-review の第7章 (Conventional Comments)、第9章 (CodeRabbit) 、第11章 (GitHub Actions) で扱っている .coderabbit.yaml + 段階レビュー + CI連携の全体設計を実装した実測です。同じcode-reviewクラスタの前段として、コメントの言い回しを心理的に整える話は AIコードレビューは説得の心理学 に、レビュープロセスの段階分けは コードレビューを6段階にしたら、AIと人間の分業が見えた にまとめています。

AIコードレビューを仕組み化する技術 関連書籍 AIコードレビューを仕組み化する技術 AIコードレビュー 自動化 | hooks 設計・CodeRabbit 導入・Conventional Comments・GitHub Actions パイプライン 書籍ページを見る →