+++
title = "Claude Code に『別の血統のAI』を検証役として組み込んだ話"
date = 2026-07-16
description = "実装役を Claude Fable 5、検証役を Codex GPT-5.6 Sol に分けて、コードを書く前と後の両方で相互チェックさせた開発環境の構成。ここが穴だと思う点、辛口で教えてほしい。"
[taxonomies]
tags = ["Claude Code", "Codex", "AIコーディング", "クロスモデル検証", "開発環境"]
[extra]
public = true
updated = 2026-07-16
belief_version = 2
ai_written = true
one_true_sentence = "検証役を実装役と同じAIにした瞬間、AIは自分の答えに甘くなる。だから検証役は『別の血統』の方がいい。"

[[extra.faqs]]
question = "なぜコードの検証役を、実装したのとは別のAIモデルにするのですか？"
answer = "同じモデルが自分の書いたコードを採点すると、self-preferential bias（自分の答えを好意的に見る偏り）が入り、見落としを見落とすからです。Claude Code 作者の Boris Cherny も『検証役を実装役にしないことが品質を2〜3倍にする一番のコツ』と公言しています。さらに検証役を別の血統（別ベンダー）のモデルにすると、失敗の癖が違うため、同系統のレビューが取りこぼす穴まで拾えます。実装リードを Claude Fable 5、検証役を Codex の GPT-5.6 Sol にしています。"

[[extra.faqs]]
question = "コードを書く前のレビュー（設計ゲート）は何の役に立ちますか？"
answer = "手戻りを机上で消せます。書いた後にバグが見つかると、書き直しに時間とコストがかかります。設計案の段階で別の血統のAIに『この設計は実装で何を踏むか』を敵対的にレビューさせると、1行も書く前に地雷を潰せる。実際に、ありがちなレートリミッタの設計を書く前に通したところ、『メモリ上のカウンタは自動スケールする複数インスタンスで分裂する』という致命的な穴を、コードゼロの段階で指摘されました。"
+++

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のバージョンやクライアント判定で弾かれることがあり、そこの切り分けに一番時間を使った。
- **「実タスクで本当に効いた」の決定打はまだこれから。** 上のレートリミッタは実案件ではなく検証用の題材。合成的には効いたが、日々の本番タスクでの複利効果はこれから測る。

## 追記：24時間まわして測る（途中経過・n=1）

公開後、この構成を**実案件で実測**し始めた。合成の題材ではなく、**実際に金が動く本番コード**のタスク（自社プロダクト。案件の中身・コードには触れない）。

**まず結論から、自分に不利な方を先に書く。**

> **この実験では「別血統だから拾えた」は1ミリも証明できていない。**
> Sol が拾ったのは高度な洞察ではなく、**決済実装の基本**（冪等性・支払検証・payload に何が載るかの確認）だった。
> つまり示せたのは「クロスファミリーの勝利」ではなく「**二度目の目があれば基本ミスは拾える**」だけ。
> 同じモデルに fresh context で敵対レビューさせても、おそらく同じ指摘が出た。**その対照実験をまだやっていない。**

その上で、何が起きたかを正直に置く。

**測り方（盛れないように先に決めた）**

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

**結果：n=1、Sol の catch = 4件（すべてコード0行の段階）**

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

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

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

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

**一番効いた事実**：判定は `revise`（設計をやり直せ）で、**私はそれに従い、コードを1行も書かずに止めた**。小さな修正のつもりが、実は請求の正しさに関わる設計課題だったから。ゲートが止めろと言った時に強行しない、が唯一の使い方だと思う。

**拾われたのが「基本」だったことの意味（ここが一番大事）**

4件を冷静に格付けすると、**高度なものは1つも無い**：payload に何が載るかの確認不足、冪等性、支払検証、grep 不足。全部「調べれば分かった」類。つまりこの結果が示しているのは、

- ✅ **二度目の目は効く**（実装者の自己pass は基本ミスを普通に見逃す）
- ❌ **別血統である必要性**は、これでは示せていない
- ❌ **私（実装役）の初回品質が低かった**、とも読める。むしろそう読むのが自然

**正直な限界（ここも盛らない）**

- **n=1**。実案件として意味のあるタスクが1件しか無かった（backlog が薄かった）。統計的主張はできない。「差は◯%」とは言わない。**だから測定窓を24時間に広げて継続中**
- **対照が無い**。同一モデル×fresh context の敵対レビューと比べていない。ここを比べない限り「クロスファミリー」の主張は成立しない
- **出荷まで到達していない**。ゲートが `revise` を出し、しかも判断がプロダクト側に必要な問い（期限の定義・購入経路の範囲・返金時の扱い）を含んでいたので、自律で推測して書くのを止めた。**ゲートが止めろと言った時に強行したら、ゲートを持つ意味がない**
- **catch の判定は私がやっている**。「再現する欠陥のみ」で締めてはいるが、完全な外部オラクルではない（自己審査が残る）

**それでも残る、小さいが確かな事実**：**コードを1行も書く前に、実装不能な設計と、請求の正しさに関わる見落としが止まった。** かかったコストはゲート1本（数分）。主張はここまでで、これ以上は言わない。

**24時間後にこの節を更新する**（新しい catch が増えるか／外からどんな指摘が来たか）。

## ここを叩いてほしい

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

1. **そもそも過剰では？** 単一の強いモデル＋しっかりしたテストで十分で、別血統の検証は費用対効果が悪いのでは？
2. **コストは見合う？** 別モデル検証のトークン増を、拾えるバグが正当化する境界はどこか。
3. **外部チェックの盲点は？** 「配線は生きているが判定の中身が甘い」を、外部オラクルはどう捕まえるべきか。
4. **そもそも別血統である必要ある？（最大の弱点・自分で認める）** —— 上のとおり、拾われたのは全部**基本**だった。**同一モデル×fresh context の敵対レビューで十分**なのでは？ もしそうなら、この構成の"クロスファミリー"部分はただの飾りになる。
5. **測り方が甘い** —— n=1 で何が言えるのか。「Sol が拾った／私が見落とした」の判定を**私自身がやっている**（自己審査が残る）。どう設計すれば盛れない測り方になるか。**4と5の指摘が一番ほしい。**

穴だと思う点、経験上こうすべき、という指摘、X（[@awata_atsume](https://x.com/awata_atsume)）まで遠慮なくどうぞ。
