🪓

PRの切り方を変えたらAIが急に賢くなった

に公開

「このPR、+1,200行なんですけど、今日中にレビューお願いできますか?」

Slackの通知を見て、正直フリーズした。

差分を開く。ファイル数32。変更行数1,247。コミットは1つ。メッセージは「feat: implement user dashboard」。

——スクロールしても、スクロールしても、終わらない。

はじめに

AI搭載のコーディングエージェントが当たり前になって、コードの「生成速度」は爆発的に上がった。でも、それと同じくらいのスピードで、PRのレビューが破綻し始めている。

最近、Hacker Newsで「GitHub "Lines Viewed" extension」——AIが生成した長大なPRをレビューするとき、進捗バーを表示して正気を保つための拡張機能——が話題になっていた。

たぶん、多くの人はこう考えている。「AIが大量にコード書くんだから、レビューも効率化しなきゃ」と。

でも僕は、逆のことに気づいた。問題はレビューの仕方じゃない。PRの切り方が壊れている。そして、それを直したら、AIの出力品質まで上がった。

なぜAIのPRは膨れ上がるのか

原因はシンプルだ。AIエージェントに「ダッシュボード機能を作って」と指示すると、AIは律儀に全部やろうとする。

APIルート、コンポーネント、状態管理、テスト、スタイリング——人間なら「まずAPIから」「次にUI」と自然に分割するところを、AIは一気通貫で仕上げてくる。

僕のチームでも、Claude Codeを導入してから同じことが起きた。

# ある日のPR一覧
PR #142: feat: implement notification system (+2,834 lines)
PR #143: fix: typo in README (+1 line)
PR #144: feat: add analytics dashboard (+1,891 lines)

1行の修正と2,000行の機能追加が同じ「1 PR」として並んでいる。レビュワーは#143だけ秒速でApproveして、#142と#144は「後で見ます」のまま3日放置される。

具体的に何が辛いかというと、こういうことだ。

// PR #142 の差分の一部(通知システム)
// ファイル: src/notifications/NotificationProvider.tsx
export const NotificationProvider: React.FC<Props> = ({ children }) => {
  const [notifications, setNotifications] = useState<Notification[]>([]);
  const ws = useRef<WebSocket | null>(null);

  useEffect(() => {
    ws.current = new WebSocket(process.env.NEXT_PUBLIC_WS_URL!);
    ws.current.onmessage = (event) => {
      const data = JSON.parse(event.data);
      setNotifications(prev => [...prev, data]);
    };
    return () => ws.current?.close();
  }, []);
  // ... さらに200行続く

WebSocket接続、状態管理、UIコンポーネント、トースト表示、既読管理——全部が1つのPRに入っている。レビュワーは「WebSocketの接続処理は正しいか」と「トーストのアニメーションは適切か」を同時に判断しなきゃいけない。認知負荷が高すぎる。

世間の反応

この問題に対して、大きく2つの派閥がある。

「レビューツール派」 は言う。「AIが書いたコードはAIにレビューさせればいい。LLMベースのレビューボットを入れろ」と。実際、GitHub Copilot PRレビューやCodeRabbitのようなツールは急速に普及している。

「人間がちゃんと読め派」 は言う。「自動生成だろうが手書きだろうが、マージする前に人間が全行読むべきだ。それがプロの責任だ」と。

——正直、どっちも正論なんだけど、ピンとこなかった。

AIレビューは便利だけど、「このWebSocket接続、うちのインフラ構成的に大丈夫?」みたいな文脈依存の判断はできない。かといって、2,000行を毎回人間が精読するのは、現実的に持続しない。

どちらのアプローチも、「巨大なPRが飛んでくること」を前提にしている。でも、その前提自体がおかしいんじゃないか?

PRの粒度を人間が設計する

僕が試したのは、AIに「何を作るか」を指示する前に、「PRをどう切るか」を先に設計するというアプローチだ。

具体的にはこうする。

# 通知システムの実装計画

## PR 1: WebSocket接続の基盤(目安: 200行以内)
- WebSocketクライアントのセットアップ
- 接続・切断・再接続のハンドリング
- テスト

## PR 2: 通知データモデルとストア(目安: 150行以内)
- 通知の型定義
- 状態管理(zustand or context)
- テスト

## PR 3: 通知UIコンポーネント(目安: 250行以内)
- トースト表示
- 通知一覧パネル
- 既読/未読の切り替え

## PR 4: 統合と結合テスト(目安: 200行以内)
- PR 1-3の結合
- E2Eテスト

これをClaude Codeに渡す前に作っておく。そして、PR単位でタスクを投げる。

# 悪い例
claude "通知システムを実装して"

# 良い例
claude "WebSocket接続の基盤を実装して。スコープはこのドキュメントのPR 1の範囲に限定して"

ポイントは「目安: 200行以内」のような制約を明示すること。AIは制約があると、不思議なくらいスコープを守ってくれる。逆に制約がないと、「ついでにこれも」と際限なく広げてくる。

obra/superpowersのようなagentic skillsフレームワークでも、タスクを小さなスキル単位に分割する設計思想がある。AIエージェントに長大なタスクを丸投げするのではなく、スキル(=小さな責務)の組み合わせとして構造化する。PRの粒度設計もまったく同じ発想だ。

気づき——AIの出力品質が上がった

面白かったのは、PRの粒度を人間が設計するようにしたら、レビューが楽になっただけじゃなく、AIの出力品質自体が上がったことだ。

理由はたぶんシンプルで、スコープが狭いほうがAIは正確に動く。

「通知システム全体を作って」だと、AIは全体の整合性を取ろうとして、あちこちで中途半端な実装をする。WebSocketの接続処理に微妙なバグがあっても、UI側の実装に注力しているときには気づかない。

でも「WebSocket接続の基盤だけ作って。接続・切断・再接続のハンドリングとテストを含めて」と言うと、AIはその狭いスコープに集中する。エッジケースまで丁寧に拾ってくれる。テストのカバレッジも自然と高くなる。

つまり、こういうことだ。

PRの粒度設計は、レビュワーのためだけじゃなく、AIのためでもある。

制約はAIの敵じゃない。制約はAIの集中力だ。

これはZennで話題になっていた「Agent Teams+Skillsでエージェント3体と1週間働いた」という記事でも触れられていた。複数のエージェントを協調させるとき、各エージェントのスコープを明確に区切ることが、全体の品質を左右する。1体に全部やらせるより、責務を分割したほうが結果がいい。PRも同じだ。

結論

AIがコードを書く時代に、人間がやるべきことは「レビューを速くすること」じゃない。

「何を1つのPRにするか」を設計することだ。

レビューツールを入れるのもいい。AIレビューボットも便利だ。でもその前に、PRが1,000行を超えている時点で、何かが壊れている。

PRの粒度は、AIへの指示の粒度であり、思考の粒度だ。

次にAIに「これ作って」と言う前に、5分だけ立ち止まって、PRの分割計画を書いてみてほしい。たぶん、レビューも、AIの出力も、チームの速度も——全部変わる。

参考

Discussion