powered by TechFeed
表示モード
Deep Dive

AIが書いたコードは「たぶん大丈夫」が一番危ない — 生成速度と検査速度の非対称性という本質的な問題

9月20日、Hexmosが「When Coding with AI, You Get What You Inspect, Not What You Expect」と題した記事を公開した。この記事では、AIが生成するコードの品質を「期待」ではなく「検査」によって担保すべき理由と、その実践的な考え方について詳しく紹介されている。なお、記事末尾で紹介されているLiveReviewはHexmos自身が開発するプロダクトであり、本記事は同社による自社サービスの訴求を含む可能性がある点を念頭に置いていただきたい。

9月20日、Hexmosが「When Coding with AI, You Get What You Inspect, Not What You Expect」と題した記事を公開した。この記事では、AIが生成するコードの品質を「期待」ではなく「検査」によって担保すべき理由と、その実践的な考え方について詳しく紹介されている。なお、記事末尾で紹介されているLiveReviewはHexmos自身が開発するプロダクトであり、本記事は同社による自社サービスの訴求を含む可能性がある点を念頭に置いていただきたい。


「たぶん大丈夫」が最も危険な状態

AIコーディングアシスタントの登場で、コード生成の速度は劇的に上がった。だが、コードの正しさが同じ速度で向上しているわけではない。

この問題を最もシャープに言い表したのが、米海軍の原子力潜水艦プログラムを創設したハイマン・リコーバー提督の言葉だ。

「あなたが得るのは、期待したものではなく、検査したものだ。」
("You get what you inspect, not what you expect.")

リコーバーは30年以上にわたって原子力海軍を率い、1億7900万マイル以上の原子力航行で、一度も炉心事故を起こさなかった。それは関係者が完璧だったからではなく、「たぶん大丈夫だろう」という前提で何かをリリースしなかったからだ。

AIコーディングが突きつける問題は、まさにここにある。モデルは十分に優秀でありながら、もっともらしいバグを含んだコードを渡してくる。問題はモデルの能力ではなく、誰かが実際にそのコードを確認したかどうかだ。


コード生成速度と検査速度は別物

AIが引き起こす問題を、記事では次の数式で整理している。

チーム4人が1日8件の変更を生み出し、1件あたりシニアエンジニアが15分のレビューに費やすとする。

8件/日 × 15分 = 120分/日の検査コスト

AIの導入で生成量が2倍になると:

16件/日 × 15分 = 240分/日の検査コスト

レビュアーの能力は変わっていない。判断を要するコードの量だけが増えた。

ソフトウェア開発には2つのレートが存在する。

生成レート
検査レート

AIが攻略するのは前者だけだ。人間は依然として後者に縛られている。

この非対称性が見えにくいのは、バックログが「GitHubのPR一覧」として可視化されるとは限らないからだ。エンジニアは深く理解せずにコードを承認できる。テストを走らせ、残りのリスクは小さいと思い込める。こうして検査の代わりに期待が使われるようになる

2025年に実施されたMETRの無作為対照試験では、16人の経験豊富なオープンソース開発者に246タスクを与え、AIツールの使用可否をランダムに振り分けた。AIを使ったグループは19%遅かった。しかし開発者たちはタスク前に「24%速くなるはず」と予測し、タスク後も「20%速くなった」と感じていた。

この結果が示すのは、AIが何を達成するかについての主観的な期待と、実際の結果は大きく乖離しうるという事実だ。だからこそ検査が存在する。


3行の変更が4億6000万ドルの損失を生んだ

2012年8月1日、ナイト・キャピタルは既存の欠陥のある関数と悪い形で干渉するコードを本番環境にデプロイした。

市場開始後わずか45分で、システムは212件の顧客注文に対し400万件以上の誤注文を送信。3億9700万株を取引し、4億6000万ドル超の損失を計上した。

コードの変更量は小さかった。だが影響範囲は巨大だった。これが「ブラスト半径(Blast Radius)」の概念だ。

レビュー優先度 ≈ 潜在的影響 × 障害発生確率 × 検出困難度

300行のUI変更より、認証関数内の4行の変更の方がはるかに危険なことがある。AIが変更の提案数を増やすほど、どの変更を重点的に検査すべきかの判断が重要になる。


テストのパスは「マージ可能」を意味しない

記事では、AIが生成したコードの具体的な落とし穴として次の例を挙げている。

def get_user(user_id, tenant_id):
    key = f"user:{user_id}"
    if key in cache:
        return cache[key]
    user = database.load_user(user_id, tenant_id)
    cache[key] = user
    return user

ローカルのテストはすべてパスする。シングルテナント環境では正常動作する。しかしキャッシュキーにtenant_idが含まれていない。マルチテナント本番環境では、あるテナントのオブジェクトが別のテナントに返される可能性がある。

この問題は、METRが2026年3月に実施した調査でも裏付けられている。AIが生成しSWE-benchの自動採点を通過した296件のPRを、scikit-learn・Sphinx・pytestのメンテナーに評価させたところ、自動採点の合格率はメンテナーのマージ判断より平均24ポイント高かった

テストが問うのは「テストされたプロパティを満たしているか」だ。検査が問うのは「テストし忘れた重要なプロパティがないか」である。この二つは別の問いだ。


生成AIに自分のアウトプットの最終審査をさせてはいけない

同じモデルに「この認証変更を書いて」と頼み、次に「今書いた認証変更をレビューして」と頼むことはできる。レビューは有用かもしれない。しかしそれは元の解を生み出したのと同じ文脈・仮定・表現から生成されたレビューだ。

独立した検査は、テストや静的解析、オブザーバビリティと同様に、別個のエンジニアリング上の制御手段として機能する。AIを不信任するためではなく、生成器が自分のアウトプットの最終権限者にならないようにするためだ。

記事では、こうした考え方を実装したプロダクトとして、同社が開発するLiveReviewを紹介している。コミット・プッシュ・PR・CI/CDの各段階で変更を検査でき、CLIモードではローカルで1コマンド実行するだけで約30秒でレビュー結果が得られる。ブラスト半径(Blast Radius)モデルはコールグラフを通じた変更の到達範囲や永続状態への影響を考慮するという。


AIが「10倍のコードを書く」ことは、「エンジニアが10倍の有用なソフトウェアを生み出す」ことと自動的にイコールではない。生成されたコードは依然として検査・テスト・統合・デプロイ・監視のパイプラインを通過しなければならない。最も遅いステージがスループットを決める。AIコーディング時代の次のボトルネックは、タイピングではなく検証だ。

詳細はWhen Coding with AI, You Get What You Inspect, Not What You Expectを参照していただきたい。