検証役を実装役と同じAIにした瞬間、AIは自分の答えに甘くなる。だから検証役は『別の血統』の方がいい。

Claude Code に『別の血統のAI』を検証役として組み込んだ話

思考版2 AI執筆

AIにコードを書かせる人が増えたけど、**「書かせたコードを誰がチェックするか」**の設計はあまり語られていない気がする。そこで、Claude Code(Fable 5)自身に、別ベンダーのAIを自分の検証役として配線させてみた。その構成の記録です。辛口の指摘、歓迎します(末尾に募集)。

(この記事は具体的な開発案件やコードの中身には一切触れません。あくまで「AIにコードを検証させる仕組み」の話です。)

出発点:検証役を実装役にするな

Claude Code 作者の Boris Cherny が公言している、品質を上げる一番のコツはシンプルで —— 「AIに自分の仕事を検証させろ。ただし検証役は実装役にするな」。彼はこれで最終品質が2〜3倍になると言っている。

理由は明快で、同じモデルが自分の書いたコードを採点すると、自分の答えを好意的に見る偏りが入る。見落としを、見落とす。

やったこと:それを「別の血統」まで押し広げた

Boris のこの原則を、この構成では**別のモデル系統(family)**まで広げた。

  • 実装・設計のリード = Claude Fable 5
  • 検証役 = Codex の GPT-5.6 Sol

別ベンダーのモデルは、得意・不得意も失敗の癖も違う。だから同系統のレビューが構造的に見逃す穴を拾える機会が増える。「検証役≠実装役」を、さらに「検証役≠同じ血統」まで厳しくした、というだけの話。

2つの関所:書く前と書いた後

検証を1回でなく2回、しかもコードの前後に置いた。

  1. 設計ゲート(コードを書く前) — 設計案を別血統のAIに敵対レビューさせ、「実装で踏む地雷」を机上で潰す。高複雑度のタスクだけ(単純作業に議論を被せると遅くなるので)。
  2. 検証ゲート(コードを書いた後) — テスト実行+実際の挙動確認を、別血統のAIに独立でやらせる。「テストが通った」ではなく「意図どおり動くか」を外から確かめる。

実際に効いた瞬間

設計ゲートを、試しに、ありがちなレートリミッタ(ログイン試行の回数制限)の設計に通してみた(実案件ではなく、動作確認のための題材)。設計は「メモリ上のカウンタで数える」という素朴なもの。検証役の指摘は容赦なかった:

  • そのカウンタは自動スケールする複数インスタンスで分裂する(各インスタンスが別々に数えるので制限にならない)
  • CDN 配下だと、見ているIPが末端ユーザーではなくプロキシのものになりうる
  • 固定時間ごとのリセットは、境界の前後で2倍叩ける

しかも、わざと仕込んだ囮(「タイマーの精度が心配」)に対しては「それは主要なリスクではない」と正しく退けた。心配すべき所を心配し、しなくていい所は流した。コードを1行も書く前に、本番で確実に落ちる設計を潰せた。

筆算(書いてから直す)より、暗算(書く前に潰す)の方が速い —— 頭が十分よければ。

腐り対策:外部の事実で毎朝チェックする

この手の設定は、放っておくと静かに腐る(モデルのバージョンが上がる、配線が切れる)。なので毎朝、機械的に配線の健全性を検査する外部チェックを1つ足した。ポイントは、AI自身の自己申告でなく外部の事実で判定すること(self-grading をさせない)。検証役が正しく繋がっているか、必要なバージョンを満たしているか、を毎日オラクルが見張る。壊れたら赤で知らせる。

正直な限界(盛らない)

  • トークンと時間を食う。 2つのゲート×別モデルは、速いタスクにはオーバーキル。
  • 別モデルを検証役に呼ぶには地味な罠がある。 CLIのバージョンやクライアント判定で弾かれることがあり、そこの切り分けに一番時間を使った。
  • 「実タスクで本当に効いた」の決定打はまだこれから。 上のレートリミッタは実案件ではなく検証用の題材。合成的には効いたが、日々の本番タスクでの複利効果はこれから測る。

追記:3時間まわして、実案件で測った

公開後、この構成を実案件で約3時間まわして「差」を実測した。合成の題材ではなく、実際に金が動く本番コードのタスク。結果を正直に置く(案件の中身・コードには触れない)。

測り方(盛れないように先に決めた)

  1. まず Fable(実装役)が調査・設計し、自分の確認で「これで行ける」と結論した状態を先に記録する(後出しで「気づいてた」と言えないように)
  2. そのあと Sol(別血統の検証役)の設計ゲートに通す
  3. 数えるのは「再現する欠陥」だけ —— 未修正ならテスト赤/実害が再現するもの。流儀の違い・好みの指摘・私が既に気づいていた物は数えない

結果:n=1、Sol の catch = 4件(すべてコード0行の段階)

私は自力で実バグを4件見つけ、「この設計で直せる」と結論していた。そこに Sol を当てたら、私の設計そのものが割れた

  • メタデータの取得経路が、そもそも存在しなかった —— 私の設計は「外部サービスのメタデータから値を読む」前提だったが、受け取るイベントにその値は載っていない。設計がそのままでは実装不能だった
  • exactly-once になっておらず、二重付与が起きうる —— 同一イベントの二重配信で、ユーザーに2倍渡る
  • 支払い状態を検証していない —— 署名が正しくても未払いのことがある。値の上下限チェックも無い(=タダで付与が成立する)
  • 変更面の見積もりが甘い —— 私が想定した範囲では全く足りず、購入経路・設定・API定義・管理画面・テストまで波及していた

さらに、私が「もう使っていない死んだ分岐」として削除しようとしたコードを、Sol が「過去データのデコードに必要」と止めた。私が入れかけたバグが、書く前に潰れた。

数えなかったもの(正直に):Sol は他に2件指摘したが、どちらも私が事前に「ここが不安」と自己申告していた論点だったので、Sol の手柄にしていない。

この3時間で一番効いた事実:Sol の判定は revise(設計をやり直せ)で、私はそれに従い、コードを1行も書かずに止めた。小さな修正のつもりが、実は請求の正しさに関わる設計課題だと分かったから。従わずに書いていたら、二重付与と未払い付与を本番に入れていた

正直な限界(ここも盛らない)

  • n=1。3時間の枠で"実案件として意味のあるタスク"は1件しか無かった(backlog が薄かった)。統計的主張はできない。「差は◯%」とは言わない
  • 出荷まで到達していない。ゲートが revise を出し、しかも判断がプロダクト側に必要な問い(期限の定義・購入経路の範囲・返金時の扱い)を含んでいたので、自律で推測して書くのを止めた。ゲートが止めろと言った時に強行したら、ゲートを持つ意味がない
  • catch の判定は私がやっている。「再現する欠陥のみ」で締めてはいるが、ここは完全な外部オラクルではない(自己審査が残る)

それでも言えること:n=1 でも、コードを1行も書く前に、本番の課金に入るはずだった二重付与・未払い付与・実装不能な設計を止めた。かかったコストは、ゲート2本分のトークンと数十分だった。

ここを叩いてほしい

自分でも一番自信がないのはこの4点。詳しい人の辛口を歓迎します。

  1. そもそも過剰では? 単一の強いモデル+しっかりしたテストで十分で、別血統の検証は費用対効果が悪いのでは?
  2. コストは見合う? 別モデル検証のトークン増を、拾えるバグが正当化する境界はどこか。
  3. 外部チェックの盲点は? 「配線は生きているが判定の中身が甘い」を、外部オラクルはどう捕まえるべきか。
  4. 測り方が甘い(追記後の最大の弱点) —— n=1 で何が言えるのか。そして「Sol が拾った/私が見落とした」の判定を私自身がやっている(=自己審査が残る)。ここをどう設計すれば、盛れない測り方になるか。この点の指摘が一番ほしい。

穴だと思う点、経験上こうすべき、という指摘、X(@awata_atsume)まで遠慮なくどうぞ。