📖 はじめに — 世代交代の裏で、枠の帳簿が偏っていた
前回の番外編は、GPT-5.6 sol への世代交代を当日中に測り切った記録だった。その監視項目の 3 つ目にこう書いた —「最上位ティアはサブスクリプション枠の消費が最速。実装委譲を連投する日は消費状況を見る習慣だけ持っておく」。実は同じ日、その「消費状況を見る習慣」が逆向きの発見をしていた。枯渇に向かっていたのは Codex 側ではなく、Claude 側だったのである。
アナリティクスの実測はこうだ。Claude Max は 5 時間ローリング枠がタイトに回り、週次でも Fable 36%・全モデル 26% を消費。一方 Codex Pro は遊休 90% 超、GPT-5.3-Codex-Spark に至っては別建て枠が遊休 100%。設計編以来の分担 — 実装 = Codex / 判断・テスト・レビュー = Claude — は品質の観点では正しく機能しているのに、枠の経済では釣り合っていない。買ってある能力が 9 割遊んでいて、買ってある能力の別の 1 つが逼迫している。
結果だけ先に書くと、この日 1 本のステアリングが起票 → レビュー → オーナー承認 → 実装 → 検証 → push まで同日で完走し、次の 3 つが入った。
| # | 効率化 | 中身 |
|---|---|---|
| 1 | 上流調査の Codex 前置 | ステアリング作成前の「材料集め」を read-only の Codex 調査レポートに置換(investigate.sh 新設) |
| 2 | --model 段別使い分け | 実装ヘルパにモデル指定を追加し、調査は軽量モデル・実装は既定、と段別に枠消費を最適化 |
| 3 | verifier のバッチ化 | 実装 N ユニットに対し Claude verifier の起動を 1 回に平準化(スクリプト変更ゼロ) |
ただし、この話の面白さは「Codex にもっと仕事を振りました」ではない。クロスファミリー検証には逆順禁止(Claude 実装 → Codex レビューの構造的禁止・実測 −8.6pt)という硬いルールがあり、「壁打ちの材料集めを Codex に出す」ことがこの禁止に触れるかどうかの解釈の正本が存在しなかった。この日の本当の仕事は、枠の付け替えではなく — ルールの境界線を確定させ、その境界の抜け穴まで塞いだことにある。
💸 動機 — 二大消費源は「読むこと」と「常駐すること」
Claude 枠の消費を分解すると、削れない部分と動かせる部分がはっきり分かれた。
削れないもの: 重要設計の Fable 5、ステアリング文書作成の Opus 4.8 xhigh、Phase 1 の Red テスト、そして verifier 本体。これらはTDD×ハーネス編・モデル戦略編で構造に固定した骨格であり、枠が苦しいからといって動かせば検証の独立性が壊れる。
動かせるものは 2 つあった。
- ステアリング作成時の生コード読み込み。壁打ちの材料集めで Opus が数百 KB のコードベースを読む — この時点ではまだ何の判断もしておらず、やっていることは「事実の収集」である
- 実装ユニットごとの verifier セッション起動。tdd-team は実装 1 ユニットごとに Claude verifier(3 ゲート)を spawn しており、細かいユニットの連投日は起動回数がそのまま枠に乗る
前者を「Codex が read-only で書いた事実レポート + Opus の spot-check」へ置換し、後者を「N ユニットまとめて 1 回」へ平準化する。Opus の仕事を判断に純化させ、読む仕事を遊休枠へ移す — 方針は 1 行で書ける。問題は、それがルール上許されるかだ。
⚖️ 解釈問題 —「調査」は逆順か
逆順禁止は常時ロードの運用ルールとして全ケース禁止の書き方になっている。ステアリングの材料集めを Codex に委譲する行為は、「Codex が Claude の領分に口を出す」ようにも見える。ここを曖昧なまま運用に入れると、便利さに引きずられて禁止の意味が溶けていく — 設計編で「逆順はスクリプトが構造拒否する」とまでした防御が、上流から浸食される。
そこでこの日、解釈を ADR として正本化した。核心は 1 文に要約できる。
逆順禁止が指すのは「Claude の実装物を Codex が採否確定する」方向である。read-only 調査は Claude の成果物が存在しない上流での事実収集であり、判断・採否は 100% Claude に残るため逆順に該当しない。
これで終わりなら簡単な話だが、レビューで面白いのはここからだった。「調査なら OK」という境界線には、提案語彙を 1 つも使わずに設計を誘導できる残余経路が 2 本あることを、設計レビューが特定したのだ。
残余経路 1: 調査に偽装した逆順
「作成中の design.md と実装の整合性を調査して」というクエリを Codex に投げたらどうなるか。返ってくるのは「X が記載されているが対応する実装が存在しない」という事実の列挙である。提案は 1 語もない。だがこれは機能的にはレビューと等価だ — Claude の成果物の欠陥を Codex が列挙し、Claude がそれに従って直すなら、採否の実権は事実上 Codex に移っている。
対策は運用規定で塞いだ: 調査クエリの対象は「既存コードベース・既存ドキュメントの事実」に限る。作成中のステアリング草稿・Claude の実装差分についての評価・レビュー依頼は、事実列挙の形をしていても禁止。クエリ語彙の機械 lint も検討したが、過剰検出とのトレードオフで今回は見送り、スキル手順への明記に留めた。
残余経路 2: 欠落バイアス
もう 1 本はさらに検出しづらい。調査レポートの記載内容は後述の機械検証(引用パス実在チェック)で正しさを担保できるが、Codex が拾わなかったファイルは誰にも見えない。「この 5 ファイルが該当します」というレポートが、実は 6 ファイル目を落としていたら — Opus はその 5 ファイルだけを見て設計し、選択バイアスは提案語彙ゼロで設計に混入する。
これは機械検出不能なので、Opus 側に検証義務を課す形で塞いだ。レポートの「該当ファイル一覧」を、最低 1 回の独立した Glob/Grep(対象領域のファイル列挙)と突合し、欠落があれば手動調査で補完する。つまり手動検索の「完全置換」ではなく「レポート + 軽量突合」の構図 — 読む量は 1 桁減るが、網羅性の最終責任は Claude 側に残る。
🔬 investigate.sh — 事実だけを通す配管
効率化 1 の実体は、実装編の implement.sh と対をなす新スクリプト investigate.sh だ。設計はすべて「事実は通し、判断は通さない」に向いている。
- read-only sandbox 固定。
--sandboxオプションの指定自体を呼出不備として拒否し、書込系の設定ミスを構造的に排除。レビュー待ちマーカーも生成しない(調査はレビュー対象ではない) - 6 セクション固定様式(該当ファイル一覧 / 現行実装の構造 / 依存関係 / 既存テスト範囲 / 関連 ADR 所在 / 未確認事項)。プロンプトテンプレートは「提案・評価・改善案・『すべき』の類は書かない。設計判断は下流の別担当が行う」を明示し、確認できなかったことは推測で埋めず §未確認事項へと強制する
- センチネル抽出。レポートは Codex stdout の
<!-- INVESTIGATION-REPORT-BEGIN/END -->間だけを採用する。read-only の Codex はファイルを書けないので stdout 経由が必然であり、同時にセンチネル外の出力 — 前置き・思考・自己評価・提案 — が構造的に遮蔽される。TDD×ハーネス編で handoff に使った自己評価遮蔽の応用だ - 機械フッター 2 本。レポート本文から引用パス表記を抽出して実在を検査し「N/M パス実在」を追記(ハルシネーションの一次防波堤)。加えて提案語彙(推奨・すべき・改善案・提案)の grep ヒット数を追記する — ADR 引用に正当に含まれ得るため hard fail にはせず、ヒット時は当該記述を無効として Opus が事実のみ採用する注意信号とした
実機だけが教えてくれた 2 つのバグ
fake codex を差し込んだ自作テストハーネスで全アサーションが緑になったあと、実機 E2E がテストでは再現しない実挙動を 2 つ暴いた。
- センチネルの部分一致がプロンプト echo で誤発火する。
codex execは出力にプロンプト全文を含むため、指示文中のセンチネル文言(1 行に BEGIN/END が並ぶ)に部分一致でマッチしてしまう → 判定を行完全一致に是正 - レポート本文が重複する。codex はストリーミング途中の出力と最終メッセージを二重に吐くことがあり、センチネルブロックが 2 回現れる → 最後の完全ブロックのみ採用に是正
どちらも fake では原理的に再現しない。前々回の番外編の「実測が有力仮説を殺す」と同型で、テスト緑 ≠ 機能が動くの教材がまた 1 つ増えた。以後の運用知見として「fake で緑になった直後に実機 1 回」を手順に足している。
🎛️ --model — 段別使い分けと「枠の逆流」防止
効率化 2 は一見ただの引数追加だが、2 つの設計判断が入っている。
1 つ目は、未ピン方針との両立。前回確立したとおり、実装の実効モデルは「未ピン = CLI 既定追従」を意図した方針として台帳に明文化してある。今回の --model はこれを覆す既定ピンではなく、呼出単位の override だ。未指定時の挙動(コマンド組立・exit code 意味論)は完全維持し、既存アサーションで後方互換を機械証明した。その上で、段別の推奨をモデル台帳に一表化した — 調査の標準は中位モデル、軽量な列挙は下位モデルか別建て枠の Spark(遊休 100% の枠から先に使う)、リポジトリ横断の大規模調査のみ最上位、実装は CLI 既定。オーナーの「Codex Pro にも制限はある」という指摘が、最上位一辺倒にしないこの表の直接の契機である。
2 つ目は、typo が枠を逆流させる穴。事前の実測で、存在しないモデル ID を -m に渡すと codex は exit 1(環境系失敗と同じコード)+「model is not supported」を返すと判明していた。現行の分岐では exit 1 → Claude implementer への fallback が発火する。つまりモデル ID の打ち間違い 1 つで、Codex へ移したはずの仕事が Claude 枠へ静かに逆流する。対策として、この文言シグネチャを検知したら exit 2(呼出不備 = fallback しない)へマップした。
ここにも設計レビューの貢献がある。初版は「文言があれば無条件で exit 2」だったが、design-reviewer が MUST 指摘で棄却した。無条件マップは (a) --model 未指定経路の「現行挙動の完全維持」という不変条件と自己矛盾する — 設定やプラン変更由来の not-supported は呼出側に修正手段がない環境系失敗で、fallback で前進させるのが正 — し、(b) codex が正常終了した run の出力にたまたま文言が含まれるだけで偽陽性になる。実際このステアリング自身が当該文言をドキュメントに書くので、Codex がそれを読む run で現実に起きる。最終仕様は「--model 指定時かつ codex 非 0 終了時に限り exit 2」— typo は必ずこの条件に落ちるので、目的は限定条件で完全に達成される。
📦 verifier バッチ化 — スクリプト変更ゼロで成立した理由
効率化 3 は当初、マーカーやゲートのスクリプト改修を覚悟していた。レビュー待ちマーカーはブランチ単位 1 ファイルを完全上書きする設計で、実装 2 回目の mark が 1 回目を消す。「バッチ化にはマーカーの複数保持が要るのでは」— が、ゲートの意味論を突合したら改修は 1 行も要らなかった。
TDD×ハーネス編の三層ゲートの解消側(resolve)は 4 つの検査を持つが、その全てが「最終状態」拘束だったからだ。
| ゲート | 検証内容 | N 回直列実行後も成立する理由 |
|---|---|---|
| 証跡照合 | 証跡 run-id == マーカー run-id | マーカーは上書きで最終 run の値になる → 証跡へマーカー値を転記すれば構成的に一致 |
| テストスタンプ | テスト checksum == 現在 tree | バッチ末尾にフルテストを 1 回流せば現在 tree と一致(回数無関係) |
| diff-sha | 証跡 diff-sha == 現在 working tree | 累積 tree の値がそのまま現在値 |
| reviewed-files | merge-base からの累積変更全ファイル | もともと累積の意味論 |
つまり「実装 N ユニットを直列で流してから verifier を 1 回起動する」運用は、ゲートから見れば「大きめの 1 実装」と区別がつかない。変更はオーケストレーション文書(tdd-team)の手順記述だけで済み、mark / resolve / diff-sha のスクリプトは凍結したまま — 代わりに、上書き挙動・旧 run-id 拒否といった「バッチが依存する現行挙動」を仕様固定テストで pin し、将来の変更で前提が壊れたら機械検知できるようにした。ゲートを設計した時点の「内容拘束」方針が、思わぬところで拡張性として配当を払った形である。
タダではない部分も正直に記録しておく。バッチ上限は N≤3 または累積 diff 約 400 行 — verifier の 1 回あたりレビュー品質を希釈させないための運用ガードだ。ユニットごとには build + 対象テストの軽量ゲートしか流さないため、ユニット k の変更が他ユニットのテストを壊す兄弟回帰はバッチ末尾のフルゲートまで検出されず、原因特定コストが N 倍になる(N≤3 が実質の緩和策)。バッチ中の git commit は禁止(証跡のアンカーを全ブリーフで一致させる)、同一 working tree での実装ヘルパ並列実行も禁止 — 書込み競合・テスト改ざんガードの誤検出・マーカー上書きレースの 3 点で決定的に危険なため、worktree 分離による真の並列化は「別ステアリング候補」として見送りをオーナー判断で確定した。read-only の investigate.sh だけは並列可である。
ついでに 1 つ、このステアリング起票時の教訓を。壁打ちの叩き台に使った対話 AI の案には「--model は設計済み・未実装」「マーカーが 2〜3 個溜まったら verifier 起動」など、リポジトリの実態と食い違う前提がいくつも混ざっていた。会話由来の数値・記憶由来の仕様をそのまま設計根拠にせず、決定ログに「採用しない」と明記して排除する — ステアリング文書化以来の規律が、ここでも手戻りを未然に止めている。
🧾 まとめ — 枠の経済もハーネス設計の一部である
起票から push まで同日。テストは 5 スイート 223 アサーション全緑(既存 138 の後方互換を保全)、文書レビュー 3 往復 + 設計レビュー 2 往復 + 実装検証で MUST 2・SHOULD 10・minor 8 を全処理。実機 E2E は軽量モデルと Spark の 2 回で、別建て枠のライブ検証を兼ねた。学びを 3 行に圧縮する。
- サブスク枠の非対称は、品質分担と同じ重さの設計変数である。 「実装だけ Codex」は品質の答えとしては正しくても、枠の経済では 9 割の遊休を放置していた。役割を動かさずに消費を動かす自由度 — 読む仕事の委譲・起動の平準化・段別モデル — は、探せばルールの内側にある
- ルールの境界を狭めるときは、解釈を ADR に正本化し、残余経路まで塞ぐ。 「read-only 調査は逆順非該当」という 1 行の解釈にも、調査に偽装した逆順と欠落バイアスという抜け穴が 2 本あった。境界線を引くだけなら誰でもできる — 境界線の抜け道を先に列挙して塞ぐのがレビューの仕事だ
- ゲートは「操作の回数」ではなく「最終状態」に拘束させる。 その設計を守っていたおかげで、verifier バッチ化はスクリプト変更ゼロ・手順書の改訂だけで成立した。拡張のコストは、拡張するときではなく最初の設計のときに決まっている
終章は「完成とは、自分の劣化を自分のデータで検出するループが閉じること」と書いた。本稿はその帳簿版だ — 消費の偏りを自分のアナリティクスで検出し、骨格を崩さずに配分を直す。世代交代(前回)とあわせて、モデルの進化にも枠の経済にも、同じエンジンのまま追従できることが確かめられた 1 日だった。そしてこの「同じエンジン」は、直後に cts-ec の外へ出ることになる — 4 プロジェクト共通ハーネスへの切り出しは次の番外編「ハーネスが単一プロジェクトを卒業する」に記録した。
📚 シリーズ記事(ステアリング駆動開発・実践編)
序章
第I部: 技術的負債ドメイン別の実録(総点検ガイド + 8 ドメイン・全 9 回)
- リファクタリング総点検ガイド — 7 つの観点と進め方
- DDD/SOLID/BC 編 — god class 一掃と境界の機械ガード
- SAGA 編 — 新アーキテクチャ挑戦と再発ゲート
- Atomic Design リファクタ編 — 47 page 新規移植
- Storybook × a11y 実機編
- テスト品質・網羅性編
- Python ジョブ群編
- パフォーマンス編
- セキュリティ編
第II部: 検証エンジン(クロスファミリー検証・全 6 回)
- 総論 — マルチ LLM の 2 系統と見取り図
- 裏取り編 — +18.1pt 論文の検証
- 設計編 — finder/verifier 分業と逆順禁止
- TDD×ハーネス編 — テスト保護と三層ゲート
- 実装編 — Claude Code の中から Codex を動かす
- モデル戦略編 — ティア割当と「買うか組むか」
終章
- クロスファミリー検証の最終型 —「正しく作る」から「自分で正しさを測り直す」へ — 検証エンジンに「計測」の層をはめ、自己修正ループを閉じる
番外編
- CI テスト 29 分 → 5.6 分 — 検証エンジンの平時運用実録 — 実測が有力仮説を殺し、退行前より速くなった 1 日
- GPT-5.6 sol 切替の当日実録 — もう一つのデフォルト追従 — CLI 更新が黙って替える finder と、当日中の再計測
- 遊休 90% の枠に仕事を振る — Codex 上流調査・段別モデル・verifier バッチ化(本記事)
- ハーネスが単一プロジェクトを卒業する — プラグイン化と二層配布 — 4 プロジェクト展開への切り出しと、version + SHA ピンによる非強制追従
- 69分で5リリース — Opus 5 当日対応が暴いた共通ハーネスの死角 — 新モデル対応を起点に、配布・文書・CI の回帰を二消費者で検出した 69 分