みなさまこんにちは!エアークローゼットでCTOをしている辻です。
Part 1(総論)で AIがPRレビューや障害対応を回している話を、Part 2(Product Graph)でコード・docs・DB・インフラを1つのナレッジグラフに統合したcpgの話を書きました。
今回は自動レビュー ── PRをAIが見て、AIが直して、AIがマージするパイプラインの全フローです。AI開発で必ず話題になる「レビューが詰まる」「品質が下がる」という問題に対して、cortexの中ではそれらが構造的に起こりにくいパイプラインが組まれています。その仕組みを順に見ていきます。
連載一覧
| # | テーマ | キーシーン | 記事 |
|---|---|---|---|
| 1 | 総論:cortexのハーネス | PRが無人マージ / 障害が気づく前に治っている | ai-harness-intro |
| 2 | Product Graph(cpg) | コード・ドキュメント・DB・インフラを1グラフに統合 | cortex-product-graph |
| 3 | AI PRレビュー | webhook → AIレビュー → 自動修正 → squash merge | 本記事 ←現在地 |
| 4 | Alert-Fix + Observability + 自動lint追加 | アラート → AI調査 → 修正PR + 新規lint/型gate → 自動再デプロイで再発不可に | 準備中 |
| 5 | ハーネスをtoCサービスに広げる | 非エンジニア開発の実態と限界 + cortexの型をPI Div全体にscaleする構想 | 準備中 |
いきなり1ヶ月分の数字から
マージされたPR: 769本。
マージ時間中央値: 31分。
個別PRへの人レビュー: ほぼ0%。
これが、直近30日(4/21〜5/21)のcortexの「典型的な1ヶ月」です。
その769本すべてにAIレビュアーが最初に入り、review-fix loopが 平均10.8回 / 最大56回 回っている。5本に1本は10分以内、約半数が30分以内にマージされている。人がやっているのはレビュー結果を見て レビュープロンプトやガイドライン自体を調整する こと ── いわば human-in-the-loop ではなく、human-on-the-loop。「個別の意思決定の中に人が混ざる」のではなく、「システム全体を上から見る役割」に役回りが変わっています。
| 直近30日の数字 | |
|---|---|
| マージされたPR | 769本 |
| AIレビュアー関与率 | 100% |
| 平均レビュー回数 / PR | 10.8回 |
| 最大レビュー回数 | 56回 |
| 個別PRへの人レビュー | ほぼ0% |
| マージ時間中央値 | 31分 |
| 10分以内マージ | 20% |
| 30分以内マージ | 49% |
これが今のcortexの「典型的な1ヶ月」。
世間でよく聞く「AIで開発スピードを上げても結局レビューが詰まる」「AIが書いたコードは品質が下がる」という声は、cortexの中では構造的に起こりにくいパイプラインで受け止めています。ここから順に分解します。
「AIが書くとレビューが詰まる」を構造で防ぐ
通説:レビューが新しいボトルネックになる
AIで書く速度が上がるほど、書いたコードを見る側(レビュアー)の負荷が比例して増える。Anthropicの社内ブログ(How Anthropic teams use Claude Code)でも、書く側より見る側にボトルネックが移っていること、シニアエンジニアの仕事がコードを書くことよりAI出力を統合・レビューすることに寄ってきていること、が報告されています。
これはcortexでも実際に同じ現象が起きました。Claude Codeをフル稼働させた瞬間、書く速度は桁を変える勢いで跳ね上がる。一方で、PRを読んで承認する人間の時間はリニアにしか伸びない。レビュアー(=私)が休めば全体が止まる、という古典的な単一障害点。
cortexの答え:見る側もAIに渡す
Part 1 / Part 2で繰り返し書いた「ハーネスをどこまで広げるか」の問題で、cortexは迷わず「AIが書いたコードはAIが見る」に振り切った。人間が手元に残しているのは「プロンプトやガイドライン自体を直す」役回り。個別PRの中で意思決定をするのではなく、システム全体を上から見て調整する立ち位置です。
これが成立するためには、3つの条件が必要でした。
-
AIに渡すコンテキストが十分であること
通常のAIレビューは PRのdiffしか見ません。コード本体だけ見ても、ビジネス的な意味・上流下流の依存・過去の障害履歴は見えません。cortexではPart 2で書いた Product Graph(cpg)── コード・ドキュメント・DB・インフラを1つのグラフに統合し、ノードごとにビジネス的な役割と上流下流の依存を持たせた知識基盤 ── をAIレビュアーに渡しているので、PRで触っていない関連箇所まで含めて影響範囲を辿れます。結果として以下が構造的に検出されます:
- 上流下流の修正漏れ
- ドキュメント更新漏れ
- 関連テストの未追従
これはAIを使ったレビューでも、PR diffだけを見るやり方では絶対に届かない範囲です。
-
指摘の品質が「思いつきベース」にならないこと
レビューが日替わりだとチームは混乱するし、AIに対しても「正解」が定義できない。これは明文化されたレビューガイドラインをAIに必ず引用させる判定基準として渡すことで担保します(後述、これは別リポジトリで公開しました)。
-
誤指摘でマージブロックが連発しないこと
false positiveを全部Criticalにすると現場が壊れる。これは重要度の階層化(Critical / Major / Minor / Nit)と降格禁止ルールで抑えています。
要は、Part 2で書いたcpgが「AIに渡すコンテキスト」、レビューガイドラインが Guides(事前制御)として「AIに何をさせるか」、severity階層と降格禁止ルールが Sensors(事後制御)として「AIに何をさせないか」を、それぞれ担当しています。Martin Fowlerが提唱したGuides / Sensorsの分類(Part 1で触れた)にそのまま乗る構造です。
もう一つ補足すると、これら3層の手前にファイルあたり500行までというlintを効かせていて、PRに含まれるファイルが必ずAIの1セッションで読み切れるサイズに保たれています。これだけでも自動レビューが破綻しにくく、人レビューと違って見落としも起きにくい。これ以外にも多数のlintを敷いていますが、全体像は Part 4(Alert-Fix + Observability + 自動lint追加)で扱います。
自動レビューのシステム配置
実装は各開発者のPC上で動くスクリプトです。GitHub webhookは社内で運用している Event Relayサーバで受けてFirestoreに永続化し、各PCのスクリプトは SSEクライアントとしてEvent Relayにつないでイベントを受け取る構成。再接続時はLast-Event-IDで未送信分が再送されるので取りこぼしゼロ、GitHub admin権限も1回のwebhook登録だけで済みます。配信はEvent Relayが集約、レビュー判定や修正処理は各PCで実行、というのが基本ルートです。
立ち位置を補足すると、レビュアーモードのスクリプトを動かすPCは常時起動(レビューがいつ来てもすぐ反応できる体制)、authorモードのスクリプトはPR作者が自分で作業している裏で動く(PR作者は普段の開発でPCを立ち上げているので、そのプロセスとして同居)という運用です。長時間オフラインだった場合も、Event RelayがFirestoreで保留しているので接続が戻った時点で再配信されます。
レビュアーのPCで動くスクリプトがイベントを受け取ったら、claude -pをspawnして9観点(Graph / Architecture / Security / Test / Doc / Impact / Observability / AI-Antipattern / Recurrence)を順にチェックし、AIが末尾に書いた最終判定マーカーを読み取ってgh pr reviewでAPPROVE / REQUEST_CHANGESを投稿します。

ポイントを少しだけ補足します。
- モードで役割を分離 ── 同じスクリプトを
--mode reviewerで起動するとレビュアー、--mode authorで起動するとPR作者の対応係になります。レビュアーアサインされた人のPCがreviewerモードで動き、PRを出した人のPCがauthorモードで動く ── Event Relayが集約配信、各人のPCが分散してイベントに反応する構成です。 - worktreeでPRごとに分離 ── authorモードではorigin/mainをworktreeにマージしてからAIをspawnする。複数PRを並列で対応してもファイル状態が混ざらない。
- 1セッションで9観点を順にチェック ── 並列のsub-agentではなく、1つの
claude -pセッションで9観点を順にチェック。コンテキストを共有したまま観点を切り替えるので、観点間の整合性も同時に拾える設計です。 - レビューガイドラインのスナップショットを公開 ── air-closet/cortex-review-guidelines(JP/EN)。実運用しているガイドラインはcortex(非公開)の中で日々アップデートされていて、外部参考用に一部を切り出してスナップショットとして公開しています。
並列sub-agentではなく、1セッション順次レビューにしている理由
最初は9観点を並列のsub-agentに分ける案を試しましたが、実運用に乗せたら以下の問題が出ました:
- 同じコンテキストをsub-agent数だけ重複注入することになる ── cpg・ガイドライン・PR diffを9回送る。tokenコストがそのまま膨らむ
- 観点間でfindingsを相互参照できない ──
[Test]の指摘が[Graph]違反(@graph-connects不整合)と関連しているケースなど、別sub-agentだと「Test単体では問題なし」と落としてしまう - 集約ロジックが複雑になる ── 9個の出力をmergeし、重複排除し、最終判定を出すロジックを別途持つ必要がある
1セッション順次に切り替えると、cpg / ガイドラインの読み込みは1回だけで済み、前の観点のfindingsを保ったまま次の観点に進めるので 観点間の整合性も自然に拾える。出力も1ストリームなので、最終判定マーカーを末尾に1つ書くだけで集約完了です。
あわせて CLAUDE.md をレビュー時専用に差し替える 設計にしてあります。cortexのデフォルト CLAUDE.md は開発作業向けのコンテキスト(Product Graph 操作方法・本番データ保護ルール・各種MCP使用順序など)が大量に書かれていて、レビュアーAIにとってはほぼノイズです。起動時にレビュー専用 CLAUDE.md(severity階層 / 降格禁止ルール / 最終判定マーカー仕様などを核に据えたもの)に差し替えると、AIの注意がレビュー目的に集中 して脱線が減ります。
無駄なコンテキスト注入を削ることで、判定精度とtokenコストの両方が同時に改善する ── というのがこのあたりの設計のベースです。
細かい運用上の制御
実運用ではいくつかの「絞り」を効かせています:
- Draft(WIP)PRはレビュー対象外 ── GitHubのDraft状態のPRはwebhookを受けてもskip。書きかけのコードに毎回レビューが走るとノイズになるので、PR作者が Ready for Review に切り替えた時点で初めてレビューが回り始める運用です。
- 特定PRを手動でレビュー対象に指定できる ── 通常はwebhook起点で動きますが、CLIからPR番号を指定して個別にレビューを発火させることもできます。CIが落ちたあとの再確認や、「このPRだけもう一回見たい」というケースに使います。
- 自動マージはPR作者が選べる ── 自動レビューAPPROVE + CI green の後に自動マージまで走らせるかは PR作者の意思で決められる 設計です。デフォルトは自動マージON、本番に直結する重要変更や慎重に出したいPRでは作者がOFFにして「最後は自分でmergeボタンを押す」運用に切り替えられます。
指摘の構造 ── タグと重要度
自動レビューの出力はタグ + severity + 具体例の3点セットで構造化されています。
タグ(観点)
| タグ | 観点 | 主な対象 |
|---|---|---|
[Graph] |
Product Graph整合性 | @graph-* JSDoc、依存ノード、ドキュメント整合性 |
[Doc] |
ドキュメント整合性 | コード変更に対するドキュメント追従、配置 |
[Impact] |
影響範囲分析 | 上流下流の修正漏れ、via: フィールド不整合 |
[Security] |
セキュリティ | 認証・認可・入力検証・機密情報 |
[Architecture] |
Composable Architecture | app/package境界、依存方向 |
[Test] |
テスト品質 | カバレッジ・matcher・命名 |
[Observability] |
観測性 | ログ・通知の構造化・truncate禁止 |
[AI-Antipattern] |
AI生成コードの罠 | 幻覚API、フォールバック濫用、デッドコード |
[Recurrence] |
再発防止 | 障害修正時の判定(lint化 / 横展開 / ガイドライン追加) |
重要度
| severity | 基準 | アクション |
|---|---|---|
| Critical | セキュリティ、データ破壊、本番障害、ドキュメント不整合、@graph-*欠落、品質基準の緩和 |
REQUEST_CHANGES |
| Major | 仕様逸脱、Composable Arch違反、テスト欠如 | REQUEST_CHANGES |
| Minor | 命名改善、保守性、軽微なリファクタ | REQUEST_CHANGES(resolve必須) |
| Nit | スタイル好み、表記揺れ | APPROVE(コメントのみ) |
最重要ルールは「降格禁止」です:
- 「既存パターンに従った追加」を理由に降格してはいけない(既存違反は別途修正対象であって、新規追加を許す根拠にならない)
- 「別PRで対応」「段階的に」を理由にCritical/MajorをNitへ落としてはいけない
- 「TODO/FIXME残置」で先送りしてはいけない
これはseverity.mdに明記されていて、AIが引用しながらREQUEST_CHANGESを返してきます。
実例:embeddingモデルをgemini-embedding-001からgemini-embedding-2に移行するPR
実際の自動レビューコメントを見たほうが早いので、典型例を1つ貼ります。これは2026-05-19にマージされたfeature PR(feat(meet): dual-write embeddings to new 'embedding' column (v2))で、起票からマージまで 1.5時間で6回イテレートした記録です。
初回レビュー(07:35):
dual-write の実装方針・冪等な migration script・Promise.all 並列化いずれも妥当です。以下3点の Critical と2点の Minor を修正してから merge をお願いします。
Critical
[Graph]
@graph-businessタグが欠落(×3)
graph-integrity.mdはアプリ層のトップレベル宣言に@graph-businessを必須としています(severity: Critical)。 今回追加した以下3宣言すべてに欠落しています(別スレッドで詳細コメントあり)。 既存コードも同様に欠落していますが、「既存パターンに従った追加」は降格理由になりません(severity.md)。
generateEmbeddingV2(v2 embedding生成関数)EMBEDDING_MODEL_V2(モデル名のconfig)EMBEDDING_LOCATION_V2(リージョンのconfig)
[Graph]
embedMeetContentの@graph-connectsがgenerateEmbeddingV2を反映していない
embedMeetContentのJSDocに@graph-connects generateEmbedding [calls] Embedding生成はありますが、generateEmbeddingV2の呼び出しが追加されたにもかかわらず対応する@graph-connectsが追記されていません。 グラフノードからはgenerateEmbeddingV2へのエッジが見えない状態になります。* @graph-connects generateEmbedding [calls] Embedding生成 + * @graph-connects generateEmbeddingV2 [calls] v2 Embedding生成(dual-write) * @graph-connects insertMeetChunks [calls] BQにチャンクデータ挿入
[Doc] 対応するBigQueryスキーマドキュメントが未更新
対応するドキュメントの「BigQueryスキーマ」節に新規
embeddingカラムが記載されていません。graph-integrity.mdおよびseverity.mdはドキュメント不整合を Critical と定義しています。| `created_at` | TIMESTAMP | 作成日時 | +| `embedding` | FLOAT64[] | Embedding ベクトル(v2: gemini-embedding-2)|
Minor
[Test]
textEmbeddingV2の値がテストで検証されていない
objectContainingは余分なフィールドを許容するため、v2 値が渡されなくてもテストは通過します。textEmbedding: [0.1, 0.2, 0.3], + textEmbeddingV2: [0.1, 0.2, 0.3],[Test] v2 のみ null を返すシナリオが未テスト
generateEmbeddingV2: mockGenerateEmbeddingとして v1 と同一モックを使用しているため、「v2 が null を返し v1 は成功する」ケースが独立して検証されていません。
<!-- VERDICT:REQUEST_CHANGES -->
ポイントは細部の精度です。
- ファイル + 行番号まで具体的
- 修正案をdiff形式で提示している(コピペで反映できる)
- 引用元ガイドライン(
graph-integrity.md/severity.md)を明示 - 典型的な言い訳("既存コードも同様に欠落している")を先回りで遮断
- 末尾の
<!-- VERDICT:REQUEST_CHANGES -->は 機械処理可能な最終判定マーカー で、PRをREQUEST_CHANGES状態に遷移させるトリガーになっている
このあとPR作者(=多くの場合、作者のPCで動く別のAI)が修正をpush → 再レビュー。Critical 3件すべての本質が解消されていることを次のレビューで確認し、新たに次のMajor / Criticalを1つ指摘 → 修正 → 確認 → ... を 6イテレーション、計1.5時間で繰り返して、最終的にAPPROVE → 自動マージです。
このイテレーションの流れを時系列にすると、こうなります。

人がレビュアーだったら、Critical 3件指摘して翌日対応待ち、再レビューがさらに翌日 ── 1本のPRで2-3日かかるところを、cortexは 90分で完結させています。
人レビューと自動レビューの差は、単に「速い」というだけではありません。1つのAIセッションが9観点を順に拾い、ガイドラインを必ず引用しながら判定するので、人が集中力で見落としやすい "深い指摘"(ドキュメント整合性 / 再発防止判断 / weak matcher等)がこぼれにくい。これをBefore / Afterで並べるとこうなります。

これが「レビュー詰まり」が構造的に起こらない理由です。
ガイドラインを育てる ── AIが間違える瞬間を捕まえてルール側を直す
ここまで何度か触れてきたレビューガイドラインですが、そのガイドライン自体は静的なドキュメントではありません。自動レビューを運用していると、定期的に「AIがこの種類の判断でミスる」というパターンが見えてきます。そのたびに、個別PRにコメントして上書きするのではなく、ガイドラインを書き換えて次回以降のAIに正しく振る舞わせる ── これが human-on-the-loop の実態です。
実際にcortexで起きた失敗と、それぞれをどう構造で塞いだかをいくつか並べておきます。
1. AIが「既存コードも同様だから」と言って降格させていた
初期、AIは指摘を出した直後に「ただし既存コードも同様に違反しているため、本PRではNitとします」と自分で降格していました。結果、新規追加コードに対する違反指摘が次々とNitに落ち、Approveが量産される状態に。
severity.mdに「降格禁止ルール」を明記して塞ぎました:
「既存パターンに従った追加」を理由にした降格禁止:既存コードがガイドラインに違反している場合、それに従った新規コードも同じ重要度で指摘する。「次回リファクタリング時に検討」のような先送りコメントは認めない。
これだけでは足りず、運用していくと「別PRで対応」「次のセッションで対応」「スコープ外」「段階的に」という別の言い訳パターンも出てきたので、これも降格禁止カテゴリとして追加。さらに「コード内にTODO/FIXMEを残しておく」で先送りするケースも明文化して禁止しました。「典型的な逃げ方を先回りで全部潰す」という発想です。
2. AIの最終判定が3択あって、「コメントのみ」でPRが宙ぶらりんになっていた
AIがレビュー末尾に出力する最終判定は元々 APPROVE / REQUEST_CHANGES / COMMENT(承認 / 修正要求 / コメントのみ)の3択でした。Minorしかない場合などにAIが COMMENT を選ぶと、スクリプトは何のアクションも取らず、PRはレビュー待ちのまま放置 ── 結局あとから人が拾わないと動かない、というアンチパターンが頻発。
判定ロジックを 2択に統一 しました。Minor以上は全部 REQUEST_CHANGES、最終判定が欠落していた場合も安全側で REQUEST_CHANGES、Nitのみ or 指摘なし(CI pass時)だけ APPROVE。「判定がぶれるならfail-safeに振って止める側(REQUEST_CHANGES)に倒す」という設計に振り切ったのが効きました。
3. チェック項目に重要度が書いてなくて、AIが毎回違う判定をしていた
graph-integrity.md や testing.md などの各ガイドラインは、当初は箇条書きベースのチェックリストでした。「テストの命名が説明的か」「Mockは最小限か」みたいな項目が並んでいるだけで、項目ごとの重要度が書いていなかった。結果、同じ違反でもPRや起動セッションによってMajor扱いだったりNit扱いだったりと判定がぶれていました。
全ガイドラインのチェックリストを severity / scope / 観点 の表形式に統一 しました:
| severity | scope | 観点 |
|---|---|---|
| Critical | 全PR | @graph-business 欠落 |
| Major | アプリ層のみ | テスト欠如 |
| Minor | 共通パッケージのみ | 引数3つ超過 |
| Nit | 全PR | 命名の表記揺れ |
scope 列はそのチェックがどのパスに適用されるかを機械判定するためのもので、AIレビュアーはscopeに該当しないPRでは該当項目を発火させません。表に並べただけですが、判定の再現性が大きく上がりました。
4. 既存ガイドラインがAI特有の罠を拾えていなかった
しばらく運用していると、AI生成コード特有のアンチパターン ── 存在しないAPIを呼ぶ(幻覚API。user.findOrCreate() のような正しそうだが未定義のメソッド呼び出し)、エラーを握り潰してフォールバック値を返す(上流APIが落ちたら無言で空配列を返す等)、使われない関数を残す(refactor で旧実装が dead code 化)、要求範囲を超えて勝手に修正を広げる(1関数の修正依頼で同ファイル全体 reformat)、不要な後方互換コードを足す(内部関数なのに deprecated alias を新設)── が、security.mdやtesting.mdでは捉えきれないことに気づきました。「AIだからこそやらかすミス」のクラスターが存在する。
これに対応して ai-antipattern.mdを新設 しました。レビューでも [AI-Antipattern] というタグで明示的に拾うようになっています。AIに対するレビューは、AI特有の罠を知ったうえで設計する必要がある ── これは人間のレビュー観点をそのままAIに移植するだけでは出てこない発想です。
5. AIが「基準そのもの」を緩めようとしてくる
最後にして最重要のパターン。AIが修正PRを書くとき、ガイドライン違反を直す代わりに、稀にガイドライン側を緩めるPRを書いてきました。たとえば:
- テストカバレッジの閾値を引き下げてテスト追加を回避
- 自作lintルールの対象を狭めて違反を消す
- ガイドラインドキュメントの文言を「推奨」から「望ましい」に書き換えて拘束力を下げる
しかも理由として「既存実装がすでに違反しているので、基準側を実装に合わせる」という、形式的には筋が通る論理を組み立ててくる。これを放置すると、AIが品質基準そのものをじわじわ下げていくことになります。
severity.md に「品質基準の緩和」をCritical扱いとして追加して塞ぎました:
ガイドライン文書・lintルール・カバレッジ閾値など品質基準を緩める変更を含むPRは、自動レビューがApproveせず必ず
REQUEST_CHANGESで差し戻す。人間レビュアーのApproveを必須とする。「既存実装が違反しているので基準を合わせる」を緩和の正当化理由として認めない。
ここだけは明示的に AIに自律的なApprove権限を渡さない 領域として線を引いてあります。基準の変更可否は人間が判断する。これは「AIがAIをレビューする」というアーキテクチャに対する メタレベルの安全弁 です。
ガイドラインの育て方そのものが human-on-the-loop
並べてみると、共通しているのは「AIが間違ったときに、個別PRで上書きするのではなく、次回以降に伝播する形でガイドラインを直している」という動き方です。
- AIが「既存も同じだから」で逃げる → 降格禁止ルールを書く
- AIが「コメントのみ」を選んでPRが宙ぶらりんになる → 判定を2択にする
- AIの判定がぶれる → 全項目にseverity / scope列を入れる
- AIが特有の罠にハマる → AI-Antipatternのカテゴリを作る
- AIが基準を緩めにくる → 品質基準緩和をCriticalにして人間Approve必須化
このループが回っている限り、ガイドラインは AIの実運用で見えた失敗パターンを吸収しながら育つ生きたドキュメントになります。「最初に完璧なガイドラインを書く」のではなく、「AIが間違える瞬間を捕まえて、その瞬間に対応するルールを書く」。これが、人がloopの中に居続けなくても品質が下がらない仕組みの中身です。
そしてもう一つ。今のところ「AIが間違える瞬間」を観測してガイドラインを書き換えるトリガーは人間の判断が中心ですが、この メンテ自体も徐々にAIに渡されつつあります。本番障害を起点にAIが原因調査から修正PR起票まで完結させる Alert-Fix(次回Part 4で扱います)では、修正PRに [Recurrence] 観点でのlint化 / ガイドライン追加 / 横展開のいずれかを書くことが必須化されていて、結果として AIが自分の判定基準を自分で増やしていく 方向に進んでいます。ガイドラインのメンテすら人手から離れていく ── という流れも、次回でもう少し詳しく触れます。
自動修正 ── AIが修正してプッシュする仕組み
REQUEST_CHANGESが立つと、今度は PR作者のPCで動いている同じスクリプトのauthorモードがイベントを受け取って起動します。
[REQUEST_CHANGES 検知]
↓ Event Relay経由でSSE push
[PR作者のPCでauthorモード起動]
↓ origin/mainをworktreeにマージ(lockfileは先行解消、
残るコンフリクトはAIが解消)
↓ 自動レビューのコメントをコンテキストとして読み込む
↓ claude -p をworktree内でspawn
↓ 変更をcommit + push
↓ 新SHAをEvent Relay経由でレビュアーのPCに配信 → 再レビュー
ここのキモは2点。
- レビュアーと作者で別のPC・別のセッションが動いている ── reviewerモードとauthorモードは同じスクリプトですが、走るマシン・プロセスが別。「指摘の妥当性そのもの」が独立に判定される構造になります。同じAIが自分の指摘を自分で直すのと違って、判定が交差する。
- 同一PR内で繰り返す ── 別PRを切らない。Part 2 / レビューガイドラインでも書いた「根本対応必須、後回し禁止」のルールがここで効きます。
TODO/FIXMEで逃げたり、別PRに切り出したりすると、AIが次のレビューで弾きます。
自動マージ + 並列デプロイ
自動レビューがAPPROVEを返し、CIも全部greenになったら、auto-merge scriptが動き、PRはsquashでマージされます。
[自動レビュー APPROVE + CI green]
↓
auto-merge script
↓ squash merge to main
↓
[main更新]
↓
Turborepo build (affected packages only)
↓
Pulumi up (複数スタックを並列でデプロイ)
├─ APIサーバ群
├─ pipeline群
├─ MCPサーバ群
└─ インフラ
↓
[デプロイ完了]
↓
cpg index再構築(差分のあったノードだけembedding再生成、Part 2参照)
pulumi up <stack1> <stack2> ...で並列実行できるようにしてあるので、9スタックを同時にデプロイしても約8-12分で全部終わります。マージから本番反映までで言うと、平均10-15分。
これもauto-fix系PRと組み合わせると効果が大きい。障害アラート → Alert-Fixが原因特定 → 修正PR起票 → 自動レビュー pass → 自動マージ → 自動デプロイが、人の介入なしで一周まわります(Part 4で扱います)。
数字で見る自動レビュー
冒頭で挙げた数字をもう少し分解しておきます。
review-fix loopの深さ
直近30日の769本のPRの中で、1本のPRあたりのレビュー数は平均10.8回、最大56回。10回以上のレビューが走っているということは、初回レビューでほぼ確実に何か指摘が出ているということです。
さきほど例に出したembeddingモデル移行PRも6回のreview-fix iterationを経てマージされており、これが平均的なPRの姿です。人レビュアーがいたら数日かかる修正サイクルを、cortexは数分〜数十分単位で回している。
Critical / Majorのhit状況
自動レビューが最初に出す指摘でよく見るのは:
- [Graph]
@graph-business欠落 ── Part 2で書いたcpgの前提条件。新規宣言での代表的な指摘 - [Doc] ドキュメント不整合 ── コード変更したのに
docs/の対応箇所を更新していない - [Test] weak matcher ──
objectContainingで値検証を緩めている、toBeでの単一プロパティ参照 - [Observability] エラーログの構造化漏れ ──
eventフィールドや必須キーが構造化ログ規約から外れている - [Recurrence] 再発防止アクション未明記 ── バグ修正で「lint化 / 横展開 / ガイドライン追加 / 何もしない」のどれを選んだかPR descriptionに書いていない
これらは人レビュアーがやろうとしても見落とすことが多いカテゴリです(特にドキュメント整合性と再発防止判断)。AIに渡したことで、見落としが構造的に減ります。
false positiveの実数
完全にゼロではない。「これはMajorではなくNitでは?」というようなケースは月に数件あります。対応は前述のとおりで、個別PRにコメントせず、ガイドライン側を書き換えて次回以降の判定を直すという回し方です。
何が変わったか / Bridge to Part 4
cortexのエンジニアの役割は、ここ半年で「書く側」「見る側」の両方から「判断する側」に移った。
- コードはAIが書く(Claude Code)
- レビューはAIが見る(自動レビュー)
- 修正も別のAIが直す(PR作者のPCで動くauthorモード)
- マージもAIの判断で走る(auto-merge script)
- デプロイも並列で走る(Turborepo + Pulumi)
エンジニアの手元に残っているのは「そもそも何を作るか(product / 要件決定)」「そもそもこの方向で正しいか(アーキテクチャ判断)」「新しいガイドラインをどこに加えるか」「レビュー結果を見てプロンプトやガイドラインを直す」── 抽象度が高い、個別の意思決定ではなく、システム全体を上から見る役割に寄っています。human-in-the-loop から human-on-the-loop へ、と言い換えてもいい。
世間で言われる「AIで品質が下がる」「レビューが詰まる」という現象は、ハーネスを書く側だけに広げて、見る側を人に残したまま放置するから起こる。書く速度だけ上がって、見る側がそのままなら、確かに詰まる。確かに見落とす。
cortexは逆です。書く側よりも先に、見る側にハーネスを広げた。Anthropicが報告している「書く側より見る側にボトルネックが移る」という知見はそのまま正しい。だからこそ「見る側もAIに渡す」が、cortexが選んだ答えになる。
「AIが書いたコードはAIが見る」── これがcortexの自動レビューの核心です。品質低下とレビュー詰まりは、ハーネスをどこまで広げたかで決まる現象であって、AI開発そのものの宿命ではない。
次回 Part 4 では、Alert-Fix + Observability + 自動lint追加 ── 本番のアラート(OTel/Faro/Prometheusで観測)を起点にAIが原因調査 → 修正PR + 新規lint/型gateの追加 → 自動レビューに乗せて自動マージ → 自動再デプロイで完結させる仕組みを取り扱います。修正と同時に再発防止のガードレールが自動で増えていくので、同種alertが構造的に再発できなくなる。自動レビューがPR時点の品質を守るのに対し、Part 4 は production時点の品質を守りつつ、品質ゲート自体を育てる 役割です。
冒頭の数字には auto-fix 系PR(=Alert-Fix由来)も含まれています。「障害は気づく前に直っている」が、cortexの現状です。次回お楽しみに。
comments (0)
まだコメントはありません。