audit
무료プロジェクト監査。「監査して」「audit」「/audit」で発火。設計/UX/品質/テストなどの観点でコードベース全体を監査し、課題をissuesディレクトリに書き出す。実行ログで重複実行を防止。特定の差分・コミットのレビューには使わない(codex-review / cross-review を使う)。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Codex が設計・実装を担い、Claude が要件確定・成果物の検証・反復・commit/push を管理する。「codex に書かせて」「codex メインで実装」「codex-drive」で発火。大きめの機能・移植・プロトコル実装向け。
余剰トークンを厚く使う運用も選べる。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
起動したら最初に codex の枠を見る (
ratelimit -source codex -check。rc=1 のときの扱いはsubagent-model-tiering.mdの「枠の残量」)。
設計の壁打ちから実装まで codex を主役にし (設計 read-only / 実装 write 権限)、Claude は「指示・検証・観測・反復・commit」に徹するワークフロー。 codex-lead が「codex に設計をリードさせ Claude が実装」なのに対し、本 skill は設計壁打ちも実装も codex が担い、 Claude は orchestrator/verifier。新規ライブラリ・大きめ機能・プロトコル実装・大量移植など、コード量が多く codex トークンを積極消費したいタスク向け。
本文中の「実測根拠 (日付 / repo / issue / トークン数)」は意図的に残している。どのフェーズを削れて
どれを削れないかの判断は実測が根拠で、数字を落とすと「削減した」という無根拠な主張だけが残る
(perf-claims-need-measurement.md)。読み飛ばしてよいが、フェーズ構成を変えるときは必ず参照する。
トークン経済 (v3.0.0): codex は厚く・Claude は薄く。codex トークンは「独立した視点を増やす」方向に
積極消費する — spec 独立読解 2 本 + 相互照合 ([S])、設計案は独立 2 本 (厚い運用は 4 本、[D1]) + クロス批評 ([D1.5])、
方針が割れうる実装は競作 ([2p])、発見型レビュー 1〜3 観点 ([3.5])、敵対的レビューは攻め口別に並列で
未解決の不変条件を確認するまで ([3.6])、壊せなかった不変条件はテストで固定 ([3.7]) し、その検知力をミューテーションで
機械検証 ([3.8])。一方 Claude トークンは以下の 3 手で節約する:
codex-fanout) で 1 往復に畳む
(per-run の起動・tail の Bash 往復自体が Claude の消費源。同節参照)。-o は CLI が最終応答を保存する機能で、モデルのファイル編集とは別。設計本文・digest は
「本文全体を最終応答で返す。ファイル編集はしない」と指示し、read-only + -o で保存する。
-o の親ディレクトリは起動前に mkdir する。obaket 674 では本文が最終応答に載らず、
ファイル編集が拒否された。この 2 操作を区別して扱う。長文であることを理由に workspace-write へ上げない。
複数のファイルを実際に作る作業だけ、必要な書き込み権限を別途選ぶ。
設計スライス・spec・要件はプロンプトに長文で貼らず、<D>/design.<タスク名>.md 等の
ファイルパス + セクション名を指示して読ませる (Claude の出力トークンを長文 heredoc に使わない)。
定型部分は templates/ のテンプレートとのファイル連結で組み、Claude が書くのは brief 数行だけ。[3.8]) のような機械実行は
codex に worktree 内で回させ、Claude は結果表 + 抜き取り 1 件の追試で監査する。節約しないもの (硬い下限): commit ゲートの build/test/diff 精読 ([3]/[4])・採用した指摘の裏取り
なぞり ([3.55])・設計承認の Claude 視点 ([D3])。ここを digest で済ませると「無検閲 commit 禁止」
(subagent-model-tiering.md) が破れる。節約するのは検閲の入力の形 (生出力 → digest) であって、
検閲そのものではない。
既定は run の種類で 2 組 (下のモデル表が正本): 読む・判断する run (read-only / review。集約役を除く) は gpt-6.1-sol + effort high
(= sol-high)、書く run (danger-full-access) と集約役は gpt-6-luna + effort max (= luna-max)。
フェーズ・難易度でこの 2 組から外さず、品質の上積みは本数と観点の数で作る (ユーザー決定 2026-10-02、読む run の effort は 2026-10-03 に medium から high へ。それまでは全フェーズ luna-max)。
ユーザーが「品質全開で」と明示したときだけ v2 運用 (merger を挟まず Claude が生出力を全文精読) に切り替える。
| 主体 | 担当 |
|---|---|
codex (設計: codex exec -s read-only / 実装: codex exec -s danger-full-access。外せない環境は workspace-write) | 設計アウトライン・詳細設計のドラフト (壁打ち)、実ファイルの作成/編集、自分でプロジェクト標準の build/test を回して反復、spec 準拠の実装 |
| Claude (main agent) | タスクのスコープ分割 / codex への指示作文 / 設計・成果物の検閲 (設計レビューの 1 視点・build・test・diff 精読) / 観測駆動デバッグ (実行・ログ・CI で事実を集め、次の指示に翻訳) / commit & push / 次の一手の判断 |
Claude は重い実装を自分で書かない。ただし trivial な 1-2 行の確定的修正 (観測で原因が確定した typo・定数・オフセット) は
codex 往復より速いので Claude が直接やってよい (subagent-model-tiering.md の例外と同じ判断)。
codex の出力を無検閲で commit しない (subagent-model-tiering.md)。Claude が必ず build/test/diff を見てから commit。
レビューは「探す」ではなく「壊す」、壊せなかったものは「テストで固定し、テストの検知力まで機械検証する」:
実装者が codex なら、レビューも codex に任せた時点で同一モデルの相関盲点が残る。各マイルストーンは
発見型レビュー [3.5] → 裏取り [3.55] → 敵対的レビュー [3.6] (red team・未解決の不変条件に合う攻め口) →
テスト強化 [3.7] → ミューテーション検証 [3.8] の 5 段で commit ゲートを組む。
「指摘なし」は「正しい」ではなく「その攻め手では壊せなかった」、「テスト green」は「検知力がある」の
証明ではない、として扱う (作法の正本は codex-review スキル)。
トークンは「視点を増やす」ことに使う: 本 skill は codex トークンの積極消費が前提だが、効くのは
独立した視点が増える使い方 ([D1] の独立案・[2p] の競作・[3.6] の lens 別並列・[3.7] のテスト) であって、
同じ観点で本数や effort を増やすことではない (逓減する)。そして律速は Claude が読む digest の量で、
最終判断は委譲できない。本数を増やす前に「merger で 1 枚の digest に集約でき、その digest + spot check を
自分は精読できるか」を見る。集約を挟まず生出力を並べて読むのは、Claude トークンの浪費 (v3 の経済違反)。
主張は偽と仮定して裏を取る: codex の「実装済み」「検証済み」「テスト green」は主張であって証拠ではない。 diff・実行・外部基準 (spec の test vector / 実サーバ / CI) で反証を試みてから受け入れる。
codex に git commit させない。commit/push は Claude が行う (検閲後)。codex には「commit しない」と毎回明示。
要件は最初に固定する: 丸投げの依頼は [R] で「要件 + 受け入れ条件」のリストに言語化し、曖昧点は着手前に
まとめて質問する。完了判定は [7] でこのリストと照合する (暗黙解釈のまま走らない・黙って完了にしない)。
[R] の受け入れ条件に
「①待った事象が来なければ timeout して red ②cancel で解放 ③reset で drain」の 3 点を書く。
これは安全機構と同じ扱いで、後から敵対レビューに出させるものではない (実測 obaket 725:
F1〜F9 → G1〜G8 の 2 ラウンドで「waiter が hang して red にならない」「reset が waiter を drop する」が
どちらのラウンドにも出た)。書いていないと、緑は「壊れていない」ではなく「待ちが刺さって何も検査していない」になる。[R] と実装の指示に書く (nil を判定する async の helper を無条件に await しない。
actor の claim と accept の間に置かれた await token.runHook(...) は、未設定でも actor を離れて割り込みを許した。swift-smbee retro 111)構造投資の水準は「寿命と拡張予定」で決め、[R] で確定して全フェーズに伝搬する:
verify-design-intent-before-refactor.md)。買うのは
境界の明確さ・不変条件の明文化・変更の局所性 (次の変更が 1 箇所で済む形) であって、予測実装ではない。[2] の実装プロンプト・[3] の diff 精読基準まで一貫させる (フェーズごとに水準がブレるのが最悪 —
構造で設計して小手先で実装する、の逆転が起きる)。設計は承認ゲートを通す: 設計自由度のあるタスクは [D1]〜[D3] の壁打ちを経て、ユーザー承認後に実装へ入る。
設計自由度が低いタスク (spec 固定のプロトコル実装・大量移植等) は軽量パスに短縮してよいが、
D3 の敵対観点 1 本は軽量パスでも省略しない (D1 の軽量パス項が正本)。判断は一言明示する。
1 タスク = 1 検証可能なマイルストーンにスコープする。codex に「全部」を投げない (15 分制約・精度低下)。
観測駆動 (instrument-before-second-fix.md): 修正が外れたら次の blind fix を投げず、まず観測 (ログ/実行/CI) を増やして
事実を取り、それを codex への次の指示に翻訳する。CI でしか出ない移植/プロトコルバグはこの往復で 1 段ずつ潰す。
モデルはスキル側で明示する: -m <model> -c model_reasoning_effort=...。省略すると
~/.codex/config.toml の既定 (対話 TUI 側の都合で変わる) を拾い、実行ごとにモデルが変わってしまう。
effort も省かない (モデルだけ指定すると effort は config.toml の値になる。config.toml は対話用に sol + medium にしてあるので、書く run で effort を省くと luna が medium で走る)。
モデルと effort は run の種類で 2 組に分ける (ユーザー決定 2026-10-02):
| run | モデル + effort | フェーズ |
|---|---|---|
読む・判断する (-s read-only / codex exec review) | gpt-6.1-sol + high | [S] の 3 本・[D1]/[D1.5]/[D2]/[D3]・敗者剖検・[3.5]/[3.55]/[3.6]・[7] の敵対照合 |
書く (-s danger-full-access) と集約 | gpt-6-luna + max | [2]/[2p]・[3.7]・[3.8]・merger・変更マップ |
subagent-model-tiering.md の「重いモデルは短い高価値な run へ」)。
2026-08-26 に裁定役の 3 フェーズだけ sol-mid にして消費が重く同日中に廃止した経緯があるので、
sol の run を並べる前に codex の 5h 枠を見る (ratelimit -source codex -check)。high (ユーザー決定 2026-10-03)。特定のベンチマーク結果を
個別タスクの精度や ChatGPT の 5h 枠の消費に一般化しない。以前の DeepSWE の数値には
この文書でたどれる出典・測定条件が無いので、effort の禁止や残量見積もりの根拠から外す。
xhigh / max の優劣は対象タスクで比較して判断する。切り替えるならモデルが対応する値を確認し、
同じ受け入れ条件で採用指摘・差し戻し・所要時間・usage を記録する。印象だけで上げない。max だけ。low / medium / high / xhigh は使わない (sol の組と混ぜない)
(難易度の自己判定がブレて難所を低い effort で踏む事故を、固定で構造的に潰す)。[3.6] の 2400 と同じ扱い)。[2] の「モデルはマイルストーンの性質で振らない」)。
effort の比較は上の手順で行う。同じ失敗を繰り返す場合は、設定変更だけで解こうとせず forge / cross-review へ escalate する
(escalate-to-forge-after-failed-tries.md)。[3.6] が 1 ラウンド回して新規反証ゼロだが枯れたと思えないときは、lens を足す
(既存 lens の言い換えを増やさない)。escalate-to-forge-after-failed-tries.md)。[3] の build/test/diff 精読、
[3.8] のミューテーション検証は必須)。上げるのは codex 側の思考量だけで、
Claude 側の検証は減らさない。[R] で工程の厚さと予算 (本数・所要時間・レビュー上限) を記録する。
<D>。全フェーズ共通)本 skill が書くもの (要件・設計ファイル、プロンプト部品、manifest、codex の -o / stdout / rc、patch・status のスナップショット) は
すべて 1 つの dir <D> に置く。<D> は着手時に 1 回 skill-tmpdir codex-drive を打って得た絶対パス
(<本体 checkout>/tmp/codex-drive/<session-id>/。dotfiles の bin/skill-tmpdir) で、以降はリテラルで書く
(Bash の変数は次の呼び出しに残らない)。
[2]) が残らない。repo の外なので codex にも渡しにくいtmp/ 直下に置かない: 置き場が散ると後から run を突き合わせられず、掃除もできない (dotfiles issue 774)<literal-stamp>. や <タスク名> で一意にする (サブエージェントと共有される)[S] / [D1] / [D1.5] / [2p] / [3.5] / [3.55] / [3.6] 共通)本 skill の並列フェーズはすべてこの作法に従う。各フェーズで再定義しない。
codex-fanout) で 1 往復に畳むdotfiles の bin/codex-fanout (PATH に載っている)。read-only / review の並列 fan-out + merger を
driver 内で完結させ、Claude の Bash 往復を「起動 1 回 + digest 読み 1 回」にする。
1 本だけ起動するときは bin/codex-run (codex-fanout の薄い前面。manifest を書かずに済む):
codex-run -J -C <worktree> -l adv-behavior review <prompt-file>
作業ディレクトリは -C オプション (codex-run が cd する) で渡す。codex exec review 自体は
-C を受け付けないが、その差分は codex-run が吸収するので呼び出し側から見えない。
command codex / </dev/null / --ephemeral -o / stdout の保存 / rc の保存 / モデルと effort の固定も
codex-run 側で満たす。rc が 0 でも本文が空なら警告を出すので、成果物での判定がそのまま乗る。
-o を省くと ./tmp/codex-run/<stamp>-<label>/ に出る (cwd 基準。-C の影響を受けない)。本 skill では -o <D>/<literal-stamp>.<label> を渡す。
Go repo では codex の sandbox が go build / go test を走らせられないことがある (work dir / build cache を
$HOME 配下に作れず operation not permitted、goenv の version 不在。SnapTrim #251 で read-only lens が
ほぼ全本「テスト未実行・静的確認のみ」で返った)。Go を触るタスクでは 起動側で
GOCACHE=<worktree>/tmp/gocache GOTMPDIR=$(mktemp -d) GOFLAGS=-mod=mod を export してから
codex / codex-fanout を起動し、prompt にも同じ env を書く (GOTMPDIR は repo 外にする。repo 内にすると Go 1.26 の
t.TempDir() の親が repo になり、codex が TestMain に隔離コードを足して環境の都合が production テストに残る: obaket 719) (workspace-write なら worktree 内へ書ける。
read-only は依然走らないので、その lens の「未実行」は Claude が自分で実行して埋める)。
codex の「テストは sandbox で実行不可」は未検証の印であって、静的確認を実行結果と読まない。
Bash ツールの上限 (15 分) を超えうる起動は detach する: run_in_background の Bash は 15 分で
プロセスごと kill される (CODEX_FANOUT_TIMEOUT=2400 や長い workspace-write 実装と矛盾。2026-08-27 に
敵対 fanout と mutation 単発が同時に全滅した = obaket issues/620)。その場合は
(nohup codex-fanout … > log 2>&1; echo "rc=$?" > <outdir>.rc) > /dev/null 2>&1 & で起動し、
Monitor ツールで完了を待つ。待つのは driver が必ず書く runs.tsv (全 run の rc が揃うこと) であって、外側の <outdir>.rc
ではない (run 単位の成果物は全部揃ったのに外側 rc だけ書かれず永遠に待った例: obaket 696 項目 10)。
待機ループには deadline を置き、超えたら「判定不能」として報告する。プロセス不在かつ成果物無し = 死亡として扱う。
15 分以内に収まる起動は従来どおり run_in_background でよい。
自分の run を止めるときは PID か -o の出力パスで特定する (kill <pid> / pkill -f '<自分の -o パス>')。
pkill -f 'codex exec -s danger-full-access' のような pattern kill は同じマシンの別セッションの codex を巻き込む
(2026-09-05 obaket: 別セッションの pattern kill で実装 run が途中で死んだ。編集は残っていたので突き合わせで復旧したが、
kill された側からは「codex が壊れた」に見える)。
outdir / log / manifest は repo root からの絶対パスをリテラルで書く ($PWD 禁止。Bash の cwd は呼び出し間で
primary cwd に戻り、別 repo の tmp に出る: obaket 696 項目 1 / 715 項目 5)。
Claude がやるのは:
<D> に書く — 定型は ~/.claude/skills/codex-drive/templates/
(review-lens-header.md = lens 共通ヘッダ、merger.md = merger の既定指示) を使い、
Claude が書くのは lens の攻め口 + タスク固有の的の brief 数行だけ (トークン経済 2)label \t mode \t model \t effort \t 部品1,部品2,... [\t timeout_s]。部品は順に連結) を書く。
mode は ro | review の 2 値 (それぞれ codex exec -s read-only / codex exec review)。
下の例はコマンド形で書いてあるので、manifest には略号の方を書くこと。
末尾の timeout_s は任意で、その行だけ timeout を上書きする (省略時は CODEX_FANOUT_TIMEOUT)。
敵対レビュー系 lens は反証の構築に時間がかかり既定値で時間切れ (rc=124) になりやすい (dotfiles issue 150) ので
2400 を付ける ([3.6] が正本)-m)・outdir はすべて cwd 依存なので、各 Bash 呼び出しで
値を再計算するか、前回出力のリテラル絶対パスを使う。prompt part のパスにはカンマを入れない
(manifest は単純なカンマ分割)。codex-fanout -J <絶対パスの manifest> <絶対パスの outdir> を、
同じ呼び出しで必要なファイルを生成してから 1 回だけ run_in_background で起動 (2 本以下で merger 不要なら -M。
1 本だけの manifest は -m 明示が無い限り driver が merger を自動スキップする — 1 出力の digest は言い換えでしかない)
生成した manifest はその呼び出しで即実行する。manifest を残しておいて後で再実行すると、repo 移動・
別 worktree・別マシンで stale path になる (出典: 573-retro-codex-drive-541-2026-08-24.md)。<outdir>/digest.md を読む (原文へは digest の出典パスで跳ぶ)起動と同時に「待機中に自分がやる作業」を決める。 read-only フェーズは実測で
20〜40 分かかることがあり、その間 main agent が「待機中です」のターンを重ねるのは丸損
(1 ターンごとに会話全体を再送する)。起動した直後に、その codex の結果に依存しない作業を
1 つ選んで着手する — issue / commit message のドラフトを <D> に書く、自分でできる裏取り
(grep・件数の計測・ログの取得) を済ませる、次のフェーズのプロンプト部品を組む。
待ち自体は成果物ファイルの存在で張る (until [ -f <outdir>/runs.tsv ]。プロセスの存在で
待たない — verify-execution-not-just-exit-code.md)。
実測 2026-09-08 (swift-smbee 087): 待機中に自分で数えた「重複 25 行」が、
後から届いたレビュワーの計数 (別範囲) の誤りを弾く根拠になった。
runs.tsv の cause 列が usage_limit・要約が label:rc=N(利用上限) になる
(ratelimit -check が見ない枠。prompt や観点を直しても通らないので、再開の時刻を待って回し直す。検出の範囲は bin/codex-fanout の usage_limit_line)codex-fanout に -C は無く、各 run は driver を起動した cwd の木を読む。レビュー対象が worktree なら、同じ Bash 呼び出しで
cd <worktree の絶対パス> && codex-fanout … として起動し、prompt に書く対象のファイルも絶対パスにする (tmp/… や git show HEAD の
相対の指定は、起動した場所の木を指す。obaket retro 1112: 共有 checkout から起動し、codex が自分で worktree を探したので結果は使えたが、
探し当てる保証は無い)。1 本だけなら codex-run -C で足りる[2p]) は対象外 (worktree 分離が必要。[2p] の手順に従う)-J で JSONL を保存し、<label>.meta.json の完了状態・thread ID・usage・command_execution を確認する。
機械集約が必要なら -S <schema.json> を ro run に付ける (全行に同じ schema を使える manifest のみ)。
詳細は codex-review「自動化向けの出力」。merger は指摘 ID の対応を保持し、元 run の未確認状態を格上げしない。CODEX_FANOUT_TIMEOUT)・出力レイアウトの正本は bin/codex-fanout 冒頭の usage「2 本だから driver は大げさ」で素の codex exec を手で組まない。 2 本以下でも
codex-fanout -M か codex-run を使う (集約規約が言う「2 本以下は merger 不要」は
digest を挟むかどうかの話であって、起動を手組みしてよいという意味ではない)。
手組みに逃げると下の作法を毎回自分で再現することになり、その一つでも落とすと空振りする。
run_in_background: true)。1 つのシェルに複数行並べると直列実行になる。stamp="$(date ...)" を先の呼び出しで作って後続で
$stamp を参照すると空文字に化ける (worktree のパスに使っていると存在しないディレクトリを掴んで即死する)。
最初の呼び出しでパスを確定したら、以降の呼び出しにはリテラルの絶対パスを書く (値を会話に控えてから使う)。
driver に渡すパス (manifest / prompt 部品 / merger prompt / outdir) の扱いは
上の「既定: driver」の手順 3 が正本。ここでは繰り返さない。
この罠は [2p] の worktree 準備 (driver 対象外) でも踏むので、driver 有無に関わらず覚えておく。git log --grep は
候補を探すためだけに使い、複数一致を勝手に選ばない。実行中に rebase・編集が入ったら、
対象が変わったレビューを現行コードの合格根拠にせず、旧 SHA の指摘として扱って差分を再確認する。codex exec review はレビュー本文を -o に書かず
stdout にだけ出すことがある (正本: codex-review スキル「手順 4」)。| tail -40 だけで受けると本文前半を捨てるため、
重要な反証を読み落としたまま「指摘なし」と誤判定する。形は ... > "$log" 2>&1; tail -40 "$log" にし、
判断の入力は必ず保存したファイル (下記 merger 経由なら merger がその全文) にする。codex exec -s read-only・gpt-6-luna・max) に保存ログのファイルパス群を
渡して読ませ、1 枚の digest を作らせる — 指摘/案ごとに「出典ログパス・file:line・根本原因・発火条件・
重複マージの結果・severity」を構造化し、全数勘定を必須にする (「run X: N 件中 M 件採用、落とした分は
各 1 行の理由」+ 指摘ゼロの run の明記。merger の黙った取りこぼしを構造的に見えるようにする)。
merger に tail や抜粋を渡さない (本文が -o に出ない罠は、merger が保存ファイル全文を読むことで塞ぐ)。
Claude は digest を読んで採否し、採用する指摘・digest が曖昧/矛盾する項目だけ出典ログの原文へ跳ぶ。
merger 自体の起動は codex 消費 (経済 1)。driver 経由ならこの規約は templates/merger.md が実装済み。
2 本以下のフェーズは merger を挟まず Claude が直接読んでよい (集約のオーバーヘッドが逆転する)。codex-drive を回す前に、そのタスクが codex 実装に向いているかを Claude が評価する。向いていない領域を 無評価で codex に投げると、もっともらしく動かない/見た目が破綻したコードを量産し検証で空回りする。
[D1]〜[D3] で codex にやらせるが、
前提・制約・受け入れ条件・最終承認は人間/Claude が握る。実装を Claude に任せたい場合は codex-lead、多視点実装は forge)これらは「codex に任せない」ほどではないが、codex の自己申告/自己テストを信用せず Claude が外部基準で検証する。
以下はそのまま [3.6] 敵対的レビューで最初に攻める的になる (循環テスト・捏造 API・overclaim は「反証しにいけば落ちる」類の弱点)。
smb3 signing algorithms は当該版に存在せず無視された)。
設定キー/API は実環境・実ドキュメントで存在確認。--disable-sandbox 等で「通った」と報告しがち。
Claude は素の環境でビルド/テストし直す。[1] へ。[0] 適性評価 … 上記。苦手領域なら一度ユーザーに確認 (UI 等)
[R] 要件確定 … 依頼を「要件 + 受け入れ条件」リストに言語化し <D> へ保存。曖昧点はここでまとめて質問
[S] spec ダイジェスト … spec/プロトコル系のみ。codex 独立 2 本が spec を読解 → 第 3 の codex が相互照合 →
相違点と重要要件を Claude が原典で確認。digest は原典への索引になる
[D1] 設計アウトライン … codex 独立 2 本 (厚い運用は 4 本・read-only) が各々 1 案を作る。設計自由度が低ければ軽量パス (+ 敵対 1 本)
[D1.5] 設計クロス批評 … 各案を「書いていない」codex が批評 (破綻シナリオ・隠れコスト・要件乖離) → Claude が批評込みで統合
[D2] 設計詳細化 … 採用方針を codex が詳細設計に落とす (境界・データ構造・異常系・マイルストーン分割案)
[D3] 設計多角レビュー … codex 2並列 (1本は必ず敵対観点・read-only) + Claude 視点 → Claude 統合 → ユーザー承認ゲート
[1] スコープ確定 … 承認済み設計を基に Claude が「1 マイルストーン」を切り、受け入れ条件 (検証方法) を決める
[2] codex 実装 … codex exec -s danger-full-access に指示 (外せない環境は workspace-write)。codex がファイルを書きプロジェクト標準の build/test まで回す
方針が割れうるマイルストーンは既定で [2p] 競作 (別 worktree・勝者採用・敗者剖検は codex)
[3] 検証 (検閲) … Claude が build/test を自分で実行 + diff 精読。根拠なき断定・spec 取り違え・指示逸脱を弾く
[3.5] codex レビュー … マイルストーン green 直後。主要リスクに合う 1〜3 観点 (read-only・複数なら並列)
[3.55] 指摘の裏取り … 3.5/3.6 の指摘ごとに裏取り codex が再現手順を構築 (or「再現不能」判定)。
Claude は再現手順を 1 回なぞって採否を確定する (検閲の前処理)
[3.6] 敵対的レビュー … 「壊れている」前提の red team を攻め口別に並列。重要な指摘・不変条件・未確認範囲を照合して打ち止め
[3.7] テスト強化 … codex に「実装は触らず、この実装を落とすテスト」だけ書かせる
[3.8] ミューテーション検証 … 使い捨て worktree で codex が実装に現実的なバグを注入 → テストが検知するか機械確認。
検知漏れ = テストの穴として [3.7] に差し戻す。commit 直前の最終ゲート。
**ハーネスは手で組まず `bin/mutate-verify` を使う** (worktree の作成・未コミットの
持ち込み・baseline green・当たったか・誤ファイル・構文 (第 3 の結果)・zero execution・
red の帰属を強制。issue 408)
[4] commit & push … 自分の差分のみ commit (commit-policy)。push は必要時。**マイルストーンごとに issue の「進捗チェックポイント」節を更新して同時に commit する**
(採用設計の要点 / マイルストーン表と commit hash / 手順 / 再開方法。context 圧縮や別セッションからの再開はこの節が入口。
設計ファイルは `<D>` (gitignore。clean-tmp で消え、別マシンには無い) なので、再開に要る判断はここに残す。obaket 617 で圧縮 2 回を跨いで有効だった)
[5] 実地検証 (任意) … 実行 / 実機 / CI で動かす。失敗したら [6]
[6] 観測 → 次の指示 … blind fix しない。観測を増やし事実を取り、次の指示にする → [2] (設計前提の誤りなら D2/D3 へ)
[7] 要件照合 … [R] のリストと成果物を突き合わせ。codex 敵対照合 1 本を必須で先行させ、Claude が確定
各マイルストーンが green になったら次のマイルストーンへ。マイルストーン間で Claude が状況を要約し、必要なら人間に判断を仰ぐ。
<D>/design.<タスク名>.md の冒頭に書き出す (このファイルに D3 の確定設計も追記していく)。[1] で決める。pollUntil(timeout:) /
Task.sleep / 固定 deadline の実時間待ちを新規に書かない (事象待ち + hang guard の awaitOrFail)。実時間そのものを
検証する integration test は別に分けて明示する」を受け入れ条件の 1 行として書く。書かないと codex は repo で最も
多い形 (実時間 polling) を真似る — 実測 2026-09-12 obaket 781: 3 epic を並行させた 13 日で pollUntil が
315 → 402 に増え、増えた 81 箇所は別 epic が lint で「新規には使わない」と書いた形そのものだった
(~/dotfiles/_claude/rules/avoid-wall-clock-assertions.md)[7] の検収基準になる。要件が途中で変わったらこのファイルを更新する。RFC / MS-* / API 仕様が正解を決めるタスクでは、設計より前に spec の読解自体を多重化する。
spec の読み違いは最も高くつく失敗 (実装・テスト・レビューが全部同じ誤読の上に建つ) で、読解を 1 本に
しておくと [3.6] の循環テスト lens でも捕まらないことがある。独立読解 2 本の相違 = 読み違いの検出器。
codex exec -s read-only・gpt-6.1-sol・high・並列作法どおり) に、実装の存在を前提にせず
spec 該当節から抽出させる: 要件 (MUST/SHOULD の別)・不変条件・バイトレイアウト/状態機械・公式 test vector・
spec が曖昧な箇所 (解釈が割れる文)。2 本には互いの存在を伝えない。<D>/design.<タスク名>.md) に保存する。
digest は原典を引くための索引であり、正解の根拠は 原典・外部 vector・実サーバの契約 のままにする。
D1/実装/[3.7] には要件 ID と原典参照も渡す。新しい疑義が出たら digest と原典を再照合する。まず 設計自由度 を判定する:
[1] へ。
ただし D3 の敵対観点 1 本 (read-only・gpt-6.1-sol・high) だけは省略せず回す
(「設計をほぼ決める spec」の読み違い・前提崩れは軽量パスでこそ実装後に高くつく)。
「設計自由度が低いので軽量パス (+ 敵対 1 本) で進める」と明示する。上の「設計自由度が低い」軽量パスとは別に、タスク自体が小さいときは設計フェーズの codex を丸ごと省く。 判定は次の全部を満たすこと (1 つでも外れたら通常パス):
[S] と D1 の多重化はそこで効く)| フェーズ | 小タスク軽量パス |
|---|---|
[R] | 通常どおり要件ファイルを作る (観測事実と外部事実もここに書く。新規 run は前の履歴を持たず、継続 run も現行ファイルを読む) |
[S] / D1 / D1.5 / D2 | codex を回さない。Claude が D2 コントラクト形式 (採用アプローチ / 不変条件 / 失敗モード表 / テスト) の最小版を要件ファイルに書く |
| D3 | 敵対 1 本は省略しない (Claude の設計を Claude だけで閉じない)。指摘は採否表で仕分け |
[2] | 通常どおり codex 実装。テストも同じプロンプトで書かせる ([3.7] を分けない) |
[3] / [3.6] | 通常どおり。[3.6] は 1 ラウンド・lens 2 本まで (「指摘なし」で閉じない条件は同じ) |
[3.5] / [3.55] | 省略 ([3.6] に畳む。指摘 3 件以上なら裏取りは Claude が直接なぞる) |
[3.8] | Claude が直接変異を当てる (数本なら codex に回すより速い。worktree でなく cp 1 世代のバックアップで可) |
[7] | Claude 単独で照合してよい (codex 敵対照合を省略できる例外。下の [7] 節参照) |
実測根拠 (2026-08-28 swift-smbee、CI job の cache 修正 = production 40 行): D1 263k / D3 359k / 実装 158k /
[7] 193k tokens。設計と照合の codex だけで 80 万超を使ったが、D1 の設計は Claude の観測結果と同じ結論で、
[7] は cold/warm cache の文脈を持たず「未充足」と誤判定して Claude が CI ログで判定し直した。
一方 D3 敵対 (9 件中 4 件採用) と実装後の敵対 (6 件中 2 件採用) は実害を拾っており、削るのは案出しと照合、
残すのは反証。「小タスク軽量パスで進める (判定: 差分 N 行 / 受け入れ条件 = X)」と一言明示してから始める。
2 例目 (2026-08-31 obaket 661、UI 配線のバグ修正 = production 80 行): Claude 起草の D2 (Optional 意図 state 1 個) に対し
D3 敵対 1 本が「sheet 経由の対象を Delete 押下時に共有 selection から取ると reload で drift する」実経路を file:line で示し、
設計を 2 段 enum + Edit 時 snapshot の受け渡しへ変えた (実装後に見つけていたら signature 変更で 2 往復)。
実装後の敵対 2 lens も 9 件中 3 件採用。小タスクでも D3 敵対 1 本は削らないの実績。
案出しは「1 本に N 案出させる」のではなく「独立 N 本に 1 案ずつ出させる」。同一コンテキスト内で並べた複数案は
互いに相関し、最初に書いた案の周辺に寄る ([3.5] で警戒している同一モデルの相関盲点の設計版)。既定は 独立 2 本。厚い運用を明示されたときは 4 本。
各本に異なる出発点 (制約の優先順位) を与えると多様性が出る。分け方の例:
起動は「並列起動の作法」に従う (別 Bash 呼び出し・run_in_background・出力は一意パス・後続呼び出しに $stamp を
残さずリテラルで書く・stdout もファイルに保存)。
# 起動は codex-fanout driver が既定 (プロンプト部品を 4 案分書き、manifest で 1 回起動)。
# 以下は fallback の per-call 形。プロンプト内容の見本としてはどちらでも同じ。
# --- 案A (Bash 呼び出し 1・run_in_background)。案B〜案D も同形で別呼び出し・別パス ---
out="<D>/<literal-stamp>.designA.md"; log="$out.log"
command codex exec -s read-only -m gpt-6.1-sol -c model_reasoning_effort="high" \
--ephemeral -o "$out" </dev/null "$(cat <<'EOF'
<タスク>の設計壁打ち。コードは書かない (設計検討のみ)。
## 要件 / 制約
- <D>/design.<タスク名>.md の要件セクションを読むこと (貼らずに読ませる — トークン経済 2)
- <ファイルに無い補足だけ短く書く: 触ってよい範囲・依存方針 等>
## この案で最優先する軸
- <案 A なら「最短で動く」。他案の存在は伝えない (独立に考えさせる)>
## 出してほしいもの
- この軸で最良と考える設計 1 案 (構成・trade-off・リスク)
- この軸を優先したことで捨てたもの (何を犠牲にしたか)
- 確証が持てない前提は「未確認」と明示する (決め打ちしない)
EOF
)" > "$log" 2>&1; tail -40 "$log"
templates/merger.md) は指摘を集める形で、そのまま使うと digest が「各案のリスクの列挙」になり、
案の比較にならない (obaket retro 1040: 4 案の原文を全部読み直した)。D1 / D1.5 では上の構造を書いた merger prompt を -m で渡す。gpt-6.1-sol + high (モデル表)。[3] の乖離チェックが
「コントラクト項目ごとの検証」として機械的に回る形にする。-s read-only・sol・high)。出力先は別の一意パスに。[3.5] と同じ並列作法 (別 Bash 呼び出しで run_in_background・出力は別パス) で、直交する 2 観点の codex
レビューを並列起動する。ただしこの段階は diff が存在しないので codex exec review ではなく
codex exec -s read-only を使い、D2 の設計ドキュメントをプロンプトに含めて渡す。[6] で拾う)。[1] に進む。
独立したレビューは新規セッション、同じ実装担当への修正は session ID で継続する ([2])。
設計・受け入れ条件はセッション履歴だけに依存せずファイルにも残し、各 run が現行版を確認する。swift build / swift test)。-s danger-full-access (下の節) では素のコマンドがそのまま回るので、この確認は要らない。
着手前に確かめるのは本流だけでよい。[2p] の worktree と [3.8] の mutation worktree は
cwd・cache path・依存取得先・fixture 位置が変わるので、そのフェーズを実際に使うときに、
そのフェーズの開始時点で確認する (競作しないマイルストーンのために worktree を先に作らない)。[2] のプロンプトに必ず貼る。「失敗したときだけ書く」にすると
codex が素の swift test に戻って再び未検証コードを返す。codex が「実行できない」と報告したら
受け流さず、着手前の課題として扱う。instrument-before-second-fix.md)。macOS/SwiftPM なら、例えば
CLANG_MODULE_CACHE_PATH="$PWD/.build/mcache" swift test --disable-sandbox --cache-path .build/spm-cache。
GUI・実機・実サーバ・CI 認証など codex 内で完結しない検証は Phase 0/[5] に委譲し、代替経路と未検証範囲を着手前に固定する。
(出典: 573-retro-codex-drive-541-2026-08-24.md)-s danger-full-access (ユーザー決定 2026-09-13、dotfiles issue 369 案 0-b)。
-s workspace-write では make lint / make build / make test (xcodebuild) が SwiftPM / clang cache の書込拒否で
Error 74 になり走らず (obaket 598, 2026-08-27)、型エラー往復 2〜3 回 / マイルストーン (763)、走らない変異ループ
(650 M1)、sandbox 由来の偽赤 (613)、「xcodebuild を試みさせない」の縛り (617 M3) がすべてここから派生していた。
外すと codex が自分でプロジェクト標準の build/test を回して反復できる。
プロンプト・事後検閲・git worktree は sandbox と同等の隔離を提供しない。作業根外への
書き込み、認証情報へのアクセス、他プロセスへの操作を事後検閲で取り消せるとは考えない。
この既定は許可済みの信頼できるローカル repo での運用に限る。外部から持ち込まれたコード・
未信頼の build/test を扱うときは workspace-write または外側の隔離環境を選び、ビルド上の不足を先に診断する。
full access を選んだ場合も、次は編集事故の検出・軽減策として行う:
swift build を回すと、DerivedData と package graph が共有されてエラーではなく無限待ちになる
(no-concurrent-spm-build-during-xcodebuild.md、
7.5 時間停止の実例)。[2] のプロンプトに「xcodebuild は -derivedDataPath ./.derived を付ける」を書く (雛形は <<'EOF' で
クォートされているので $ROOT は展開されない。相対で書く)。.derived/ は .gitignore か .git/info/exclude に
入れる (入れないと untracked が [3] のスナップショット比較に混ざる)。
Makefile が固定パスで付けられない repo では、codex の run 中は Claude が本体で xcodebuild / swift build を回さない-C で渡した worktree / repo root の外は読むだけ)。
採用判定 [3] の前に 本体 checkout の git status --short が起動前スナップショットと同じこと、
worktree の git log -1 が起動前と同じ hash であることを確認する (sandbox が無いので、はみ出しは検閲でしか見えない)
$HOME 配下) まで確かめる。
作業根の外へ書く target は、作業根の中の出力先を指定できない限り使わせず、プロンプトで名指しして禁止する
(「外に書かない」の一般則だけではラッパーの既定値を止められない。obaket 1016: make -C macOS build が既定の DerivedData に書いた)git pull --ff-only を
試みる。ThumbnailThumb 542)。sandbox があった頃は失敗していたが、いまは成功するので検閲の項目に格上げ[3] で読む
(bin/tmux shim は非 TTY からの本番 kill を拒否するが、それ以外は無防備)swift build / swift test (上の cache フラグつき) まで、xcodebuild 系は Claude が
素の環境で回すと [2] のプロンプトに書く。codex の全体 swift test が赤を報告しても sandbox 由来の偽赤が
ありうる (613 で同日 2 回観測。素の環境では 0 failure) ので、赤も緑と同じく Claude の再実行で判定する。
codex に xcodebuild を試みさせないとプロンプトに書く (試みると Error 74 の往復で時間を溶かす。617 M3)。
codex に渡せる構文確認は swiftc -parse まで (型検査は依存モジュールが要り sandbox で組めない)。型 error は
Claude の make test で 1 往復として織り込む (542: memberwise init の引数順 1 件で passed 0 の往復)。
shared SPM を触るマイルストーンでは、実装プロンプトに**「返す前に cd shared && swift build --build-tests を通す」を
固定文で入れる** (sandbox で走るかは repo ごとに最初のマイルストーンで確かめてから固定する。issue 369 1-2)。
この環境では未実行の理由が sandbox 由来なので、[3.8] の実行ループも最初から Claude のハーネスで当てる
(変異 patch の生成だけ codex read-only に作らせる。codex に回しても typecheck だけで「成功」と書く: 650 M1)[2] のプロンプトに書くこと / [3] で見ること:
project.pbxproj は触らない (xcodegen が project.yml から生成する) — 書かないと codex が新規テストファイルを
pbxproj に手で登録する (obaket 686, 2026-09-01。再生成で上書きされるので実害は無いが diff がノイズになる)。
codex が書いた macOS target のテストは Claude が baseline 緑 + 変異 red を xcodebuild で確認するまで未検証扱い
(617 M5: codex 版の macOS テスト 2 本が baseline red / 変異検知が vacuous だった。macOS 側の変異は Claude が worktree で
xcodebuild -only-testing:<suite> を当てる)。
codex が Package.swift (依存の追加) を触ったら要約に明示させる (617 M5: test target の依存追加が要約に無く diff で気づいた)。
codex の要約に「未実行」「実行できなかった」がある成果物は、採用判定 ([3]) より先に Claude がその検証を回す
(645 M6c, 2026-09-03: 「macOS 側 xcodebuild は未実行」と明記された IA cancel test を、同ラウンドの shared 緑に
引っ張られて後回しにし、hang の発見が 1 ラウンド遅れた)# 最終応答・stdout・rc は **run 固有のパス** (<D>/<タスク>/。「出力の置き場」) に保存する。
# 後から「空振りだったのか遅れて完了したのか」を診断するため (2026-08-25 obaket 581 で証拠が残らなかった)。`</dev/null` 必須 (codex-review ルール)。
# 実装は書く run なので luna + effort **max** (モデル表)。
# ROOT は repo root の絶対パス。cwd はサブディレクトリに残っていることがあるので `-C "$ROOT"` を必ず付ける
# (Storage/ を cwd に起動され macOS/bin を書けず「対応できませんでした」で 30 分ロス: obaket 696 項目 1)。
ROOT="$(git rev-parse --show-toplevel)"
last_message="<D>/<タスク>/impl.out.md"; log="<D>/<タスク>/impl.log"; mkdir -p "<D>/<タスク>"
command codex exec -s danger-full-access -C "$ROOT" -m gpt-6-luna -c model_reasoning_effort="max" \
--json -o "$last_message" </dev/null "$(cat <<'EOF'
<タスク>。git 操作 (commit / pull / checkout / stash 等) はしない (人間が検証して commit する)。作業根 (この repo root) の外には書かない。
ファイルを書き、プロジェクト標準の build/test が green になるまで自分で反復すること。Swift プロジェクトなら swift build / swift test を使う。
最後の確認はテスト全体で行う (関係しそうな suite だけを選んで代用しない。応答の形や request の列は contract / golden の stub が別の suite で作っている)。
xcodebuild を回すときは -derivedDataPath ./.derived (repo root 直下) を付ける。
issue は起票しない。範囲外の発見は要約に書く (採番から push までは人間側が 1 手で行う)。
## ゴール / 受け入れ条件
- <1 マイルストーンの完了条件と検証方法>
## 承認済み設計 (このマイルストーンに関係するスライス)
- <D>/design.<タスク名>.md の「<セクション名>」を読んでから着手すること
(新規の実装 run は前フェーズの設計を知らない。継続 run も現行版を再確認する。貼らずにパス + セクション名で読ませる — トークン経済 2。
軽量パス (設計フェーズ省略) のときはこのセクションごと省略可)
## やること
- <具体的な実装項目。spec があれば節番号で参照>
## 制約
- <触らない領域 / 既存方針 / 依存方針 / Linux ビルド維持 等>
- 構造方針: <[R] の判定を貼る。長期運用なら「症状パッチ・特例分岐で凌がず前提を直す。ただし今使わない
抽象・設定可能化は足さない」/ 最小変更なら「既存構造に追従し、構造改修を持ち込まない」>
- production 型に **test 専用の状態・観測 API・barrier を足さない** (counter / waiter / 到達通知 /
停止用 seam)。interleaving を固定したいときはテスト側だけで観測できる形 (bounded yield + flag、
fake の注入、既存の internal 診断 counter) に留め、それでも固定できないなら「pin なし」として
要約に書く。判断基準は `_claude/rules/refuse-low-value-coverage.md` の「テスト困難 × 価値」表。
- テストに実時間待ちを新規に書かない (`pollUntil(timeout:)` / `Task.sleep` / `.sleep(for:)` / 固定 deadline)。
待つなら事象待ち (fake の waiter / `waitUntil*ForTesting`) + hang guard の `awaitOrFail`。実時間が検証対象そのもの
なら integration test として分け、理由コメントを直前行に置く。
- 確証が持てない点は決め打ちせず ⓥ コメントを残し保守的に実装する。
- (挙動を変えない作業のとき) 旧実装の不具合を見つけても直さず、要約の別項目に書く。「挙動を変えない」とだけ書くと直す方へ寄る (obaket retro 1062)。
- 他の AI / CLI (claude / codex 等) を呼ばない。指示にない長時間の検証 (test-load 等) を回さない。
終わったら、変更点・検証結果・未完部分を要約。
EOF
)" > "$log.events.jsonl" 2>"$log"; rc=$?; echo "rc=$rc" | tee "$log.rc"; tail -40 "$log"
実装 run は --ephemeral を外して --json を付け、thread.started.thread_id をその run の checkpoint に保存する。
独立レビュー・競作の各候補・テスト強化は引き続き別セッションにする。
同じ実装への修正は 明示 ID で codex exec resume <SESSION_ID> '<修正指示>' --json -o <新しい出力パス> を使う。
--last は並行セッションを誤って選ぶので使わない。resume も </dev/null、モデル・effort・一意なログ・timeout を付ける。
resume の実行ディレクトリは元の worktree にし、記録した sandbox 設定を明示して再指定する。
CLI 0.160.1 の resume は -s を持たないため -c sandbox_mode=read-only 等を使う。
対象 CLI の resume --help で受け付ける設定方法を確認する。継続時の設定を暗黙の継承に任せない。
継続前に元 run の終了を確認し、git diff と現行要件・設計ファイルを読むよう指示する。
rebase・他者の編集・設計変更があればその事実も渡す。session ID が失われた場合や前提が大きく変わった場合は、
checkpoint + 現行差分から新規 run を起こす。停止した run の編集を全ロスと決めつけない。
--json の command_execution / turn.completed / turn.failed / error と usage を保存する。
完了イベント・応答があっても実装の正しさは [3] の build/test/diff で検証する。
モデルはマイルストーンの性質で振らない (大原則のモデル振り分け): 機械的移植・boilerplate でも、
判断を含む実装・非自明な wire/protocol でも、一律 gpt-6-luna + max (モデル表の書く run)。
[3] の検閲で判定したマイルストーン
(「動くが筋が通っていない」/ 捏造 API / 同じ型エラーを 2 往復しても直らない、等) は、
そのマイルストーンだけ -m gpt-6.1-sol (effort は sol の high。モデル表) へ切り替えてよい
(ユーザー指示 2026-09-13、dotfiles issue 369 1-3。2026-09-30 に上振れ先を astra から gpt-6.1-sol へ変更 (ユーザー指示: コストが安いため)。probe 実測: codex-cli 0.159.1 で rc 0、応答 "GPT-6")。
切り替えはマイルストーン単位で、checkpoint に「M<n> は sol へ。理由: …」を 1 行残す (前後比較の材料)。
下げる方向 (541 の low) は依然禁止。capacity 死は luna と共通 (openai/codex #43398) なので回避策にはならない。
駄目だった質の判定材料は「[3] で差し戻した回数と種類」であって印象ではないsubagent-model-tiering.md の「1 本の重さも見る」。obaket 1003 で astra の run が 2 回とも実装の途中で枠切れになった)command codex プレフィックス / </dev/null / -o の作法は codex-review が正本。独立レビューの --ephemeral は [2] の継続実装には付けない。
-o は実行ログ全体ではなく最終応答 (--output-last-message) の保存先。標準出力/標準エラーは必要に応じて呼び出し側で保存する。
--full-auto は使わない。実装は -s danger-full-access を明示 (ユーザー決定 2026-09-13、issue 369。理由と
セットで守る項目は「1. スコープ確定」の sandbox 節)。外せない環境では -s workspace-write。review の -s read-only とは別。
大きいタスクは codex が時間内に終わらないことがある。プロンプトに「時間内に終わらなければ最小で動く形を優先し、 残りは TODO で残す」と書く。
codex の exit 0 を「実装した」の証拠にしない (空振りの検出)。実装フェーズの codex は、方針を述べただけで
exit 0・差分ゼロ・-o の出力ファイルも未作成のまま終了することがある (実測 2026-08-24)。成功終了なので
通知だけ見て次へ進むと「テストを足したつもり」で先へ進んでしまう。期待した成果物 (git status --short の
差分、または -o のファイル) が無い exit 0 は空振りとして扱い、再投げか Claude 直筆に切り替える。
🚨 判定は「差分ゼロ = 空振り」ではない (調査タスクや「変更不要」の結論では差分ゼロが正常)。
workspace-write の実装フェーズで、期待した成果物のパスに差分が無いときに限る。並行セッションの
差分と区別する必要があるなら [3.7] の pre/post スナップショットと同じ形を使う。
🚨 空振りと判定する前に、その run が終了していることを確認する。rc が確定する前に成果物の有無だけ見ると、
まだ走っている run を「空振り」と誤判定する。fanout なら runs.tsv の rc、単発なら $? を保存してから成果物を見る。
実害 (2026-08-25 obaket 581): 4 本を空振りと報告したが少なくとも 2 本は遅れて完了していた。
さらに、空振り判定後に Claude が書き直したテストを、遅れて完了した codex の出力が同じパスに
上書きし、commit されたのは codex 版だった (テスト名が同じで取り違えた)。誤判定のコストは
待ち直しではなく「codex が壊れている」という誤った因果を作ること。
🚨 判定できるように、出力先は run 固有のパス (<D>/<タスク>/) にする。-o と JSONL/stdout を scratchpad に出すと
再起動で消え、「空振りだったのか」を後から検証できない (581 で実際に残らなかった)。一般則は
verify-execution-not-just-exit-code.md の
「非同期・background の完了も『成果物』で判定する」節。
異常終了 (capacity 死・timeout・中断) も「全ロス」と決めつけない。書き込み権限の run (danger-full-access / workspace-write) は
死ぬ前に編集が途中まで、ときには全部残っている。実例 (2026-08-25 obaket 571): 632k tokens 消費後に
「Selected model is at capacity」で死んだ run は、突き合わせたら要求項目が全部完了していた。
再投げの前に git status --short と要求項目を突き合わせる (全ロス前提の再投げは二重編集を作る)。
起動し直すプロンプトには「再開の注意: まず git diff を読み、どこまで当たっているかを確かめてから続きを行う」を足す
(obaket retro 1076: クレジット切れで途中で死んだ run を 3 回この形で起動し直し、3 回とも二重に当てずに続きから終わった)。
上の空振り判定と同じ形で、違うのは向きだけ — あちらは「まだ走っている」を「壊れた」と読む誤り、
こちらは「異常終了した」を「何もしなかった」と読む誤り。
なお capacity で codex が使えない状態が続くなら、独立視点の agent で代替してよい
(2026-08-25 の実績: 敵対 round と [7] 検収を agent で代替し、どちらも実害を検出した)。
コマンド実行ツールの timeout は 900000ms。
同じマイルストーンを独立 2 本に実装させ、Claude が比較して勝者を採用する。1 本しか走らせないと「その 1 案が 最良か」を比較対象なしに判断することになる (レビューは「書かれたコードの粗探し」しかできず、「別の書き方なら そもそもこの問題が存在しない」には届かない)。競作は codex トークンを倍払って比較対象を買う手段。
適用条件 (満たすなら既定で競作する。満たさないなら通常の [2] 1 本):
起点は HEAD。開始時点の未コミット変更が今回の実装の前提になっているなら、競作を使わない
(または前提を先に commit してから競作する)。両候補は前提を見ずに実装するので、勝者を戻す段で初めて衝突する。
必ず別の git worktree で走らせる。同一 working tree に 2 本の書き込み run を当てると互いの編集を
上書きし合う。codex には -C <worktree> で作業根を渡す。
その repo に worktree を作るコマンドがあれば (例: my-products の bin/wt create。毎回新しい path + repo 直下の .wt-setup による
下準備)、detached で足りる用途 (実装 1 本・変異検証) ではそれを使う。下の例は branch を付ける競作用の手組み。
# --- 準備 (Bash 呼び出し 1)。パスは repo root からの絶対パスで確定し、出力された値を控える ---
root="$(git rev-parse --show-toplevel)"; stamp="$(date +%Y%m%d-%H%M%S).$$"
git worktree add -b "codex-drive/$stamp-a" "$root/../wt-$stamp-a" HEAD
git worktree add -b "codex-drive/$stamp-b" "$root/../wt-$stamp-b" HEAD
echo "A=$root/../wt-$stamp-a"; echo "B=$root/../wt-$stamp-b" # ← この 2 行を控える
$stamp は次の Bash 呼び出しに残らない。控えた絶対パスをリテラルで書くこと (「並列起動の作法」)。
../wt-* を cwd 基準で書くと、cwd が repo のサブディレクトリのとき repo 内部に worktree ができて
本流の untracked を汚す。上記のように repo root 基準の絶対パスにする。
# --- 案a (Bash 呼び出し 2・run_in_background)。案b も同形で別呼び出し・別 worktree ---
wt="/<控えた A の絶対パス>"; out="<D>/<literal-stamp>.implA.md"; log="$out.log"
command codex exec -s danger-full-access -C "$wt" -m gpt-6-luna \
-c model_reasoning_effort="max" --ephemeral -o "$out" </dev/null \
"<[2] と同じプロンプト>" > "$log" 2>&1; tail -40 "$log"
[D1]) と違い、ここで軸を分けると
「違う仕様のものが 2 つ」になり比較できない。振れ幅は codex 側の非決定性に任せる。[2] (codex) か trivial なら Claude 直接。merge / cherry-pick / 素の git diff はどれも取りこぼす。
git add -A で untracked を index に載せてから --cached --binary で patch 化し、本流に apply する。
適用前に必ず --check を通し、落ちたら強制適用しない。原因を git apply --check -v で切り分けて分岐する:
git apply -3 (3way) を試す。競合が残ったら手動で解消する[2] (単発・本流の作業ツリー) で
実装し直す。worktree は下記の手順で必ず片付けるwt="/<控えた勝者の絶対パス>"; patch="<D>/<literal-stamp>.winner.patch"
git -C "$wt" add -A
git -C "$wt" diff --cached --binary > "$patch"
git apply --check "$patch" && git apply "$patch" # --check が落ちたら適用しない
remove は拒否される。
git worktree remove --force を使い、-b で作ったブランチは別途 git branch -D する
(worktree remove はブランチを消さない)。放置しない (CLAUDE.md「並行作業者がいるときの worktree 退避」)。
削除は patch の適用と内容確認が済んでから行う (--force は未移送の成果物ごと消す)。git worktree remove --force "/<A の絶対パス>"; git worktree remove --force "/<B の絶対パス>"
git branch -D "codex-drive/<literal-stamp>-a" "codex-drive/<literal-stamp>-b"
git worktree list # 消えたことを確認する
[3] に入る。以降の検証・レビュー・commit は通常フローと同じで、commit は Claude が
自分が触ったパスを pathspec で明示して行う (commit-with-pathspec)。競作したことは commit message に一言残す。make build 相当) を回し、通ってから [3.5] / [3.6] を起動する。
レビュー fanout と並走させると型エラーを後から知り、「型エラーを抱えたままレビューに出した」往復が 1 回増える
(obaket 763 項目 4: マイルストーンごとに 2〜3 往復。issue 369 1-2)。型エラーはどの往復でも最終的に直るので、
先に潰しても質は変わらない — 減るのは往復だけ。macOS target を触るマイルストーンは薄く切り、この型検査を短くするswift build / swift test。
codex 環境の sandbox 差で codex 報告が --disable-sandbox 等になっていても、Claude は素の環境で確認する)。swift test が走らない環境では、codex の
変異検証は typecheck だけで「成功」と書かれる (実測 2026-09-05 obaket 650 M1: fix ×4 すべてで swift test は
一度も実行されておらず、Claude が当て直したら 1 本 hang・2 本 green だった)。変異検証は codex の報告を
数に入れず、Claude が [3.8] で必ず自分で当て直す。プロンプトには「実行できなかった検証は成功と書かない」を
入れてはあるが、報告の書き方は変わらないので、読む側で「実行ログの無い成功」を落とすForTests / Diagnostics /
waitFor… が付く stored property・actor・public/internal API、到達通知の counter、停止用 barrier)。
codex は「レビューで指摘された不変条件をテストで固定する」を最優先に解くので、production の
複雑性を上げる seam を躊躇なく足す。実測 (obaket 650 M1 fix3, 2026-09-05): 敵対レビューの
「テストが interleaving を強制していない」に対して production actor へ duplicateEndCleanupCount /
duplicateEndWaiters / waitForDuplicateEndCleanup() を追加してきた。次ラウンドで
「production に入った test 専用状態」として指摘され、fix4 でテスト側の bounded yield + flag へ置き換えた。
_claude/rules/refuse-low-value-coverage.md の「テストのために production へ seam を足して本番側の
複雑性を上げるなら、それはテスト困難の判定材料」と正面から衝突するので、差し戻す。
🚨 テストの失敗経路に、後始末を飛ばす early return が足されていないかも同じ位置で見る
(「待ちが失敗したら return」の guard が、Task の join・lease の終了・runtime の破棄を飛ばす)。
プロンプトで禁じても繰り返し足される (実測 obaket 806: 4 件。うち 3 件は diff 精読でしか見つからなかった)
🚨 既存ファイルを書き換えさせたら、削除されたコメント行を数え、理由 (なぜ / なぜしない) の消失を見る
(git diff -- <file> | grep -cE '^-\s*//' と ^\+\s*// を並べ、大きく減っていたら削除行を読む)。codex は書き換えのついでに
理由のコメントを要約・削除し、要約にはそれを書かない (実測 obaket 807: engine で削除 52 行に対し追加 29 行。issue 323 / 334 の理由が
消えていて差し戻した)。消えたものは list-masked-failure-modes-before-removing-guard.md の「統合・移設で comment を書き換えるとき」の扱いで戻させる
🚨 既存の分岐が投げるエラーの種類と、再試行の扱い (再試行する / しない) が変わっていないかを先に読む。codex は寄せる・整える
ついでにエラーの分類を変え、要約に書かない。テストがエラーの型しか見ていなければ素通りする (実測 obaket 1033: 再試行しない
capabilityLimit を再試行する transport に変え、ファイル全体の取得を最大 5 回繰り返す退行。diff 精読でだけ見つかった。
一般則は survey-receiver-guards-before-passing-new-values.md の「逆向きも同じ」)[3] の build/test が green になったマイルストーンごとに自動で実行する (green の前に起動しない — [3] の順序の項)。実装した codex とは別プロセスの
レビュアーとして、主要リスクに合う 1〜3 観点を選ぶ。複数なら重複を避けて並列で回す。
厚い運用は 3 観点。1 本で扱えない独立したリスクがあるときに観点を増やす。
ここは「問題を探す」発見型パスで、この後に [3.55] (裏取り) → [3.6] (壊す) → [3.7] (固定) →
[3.8] (テストの検知力検証) が続く 5 段構え。
[3] の Claude 精読もコントラクト照合をするが、
多数ファイル横断の依存方向・広域一貫性は codex の既知の弱点 ([0] の表) かつ diff 精読で追いにくいので、
レビュー側にも観点として明示的に持たせる。境界を定義していないタスク (機械的置換等) では充てなくてよい# 起動は codex-fanout driver が既定 (mode=review の 3 行 manifest で 1 回起動 → digest を読む)。
# 以下は fallback の per-call 形。パスはリテラルで書く ($stamp は次の呼び出しに残らない)。
# stdout も保存する ($log 群は merger に全文読ませる)。詳細は「並列起動の作法」。
# --- 観点A (Bash 呼び出し 1・run_in_background)。観点B・C も同形で別呼び出し・別パス ---
out="<D>/<literal-stamp>.reviewA.md"; log="$out.log"
command codex exec review -m gpt-6.1-sol -c model_reasoning_effort="high" \
--ephemeral -o "$out" </dev/null \
"<観点A の指示。file:line・理由・最小修正案を。要約/称賛不要>" > "$log" 2>&1; tail -40 "$log"
command codex / </dev/null / --ephemeral -o / --full-auto 禁止は codex-review スキルが正本。[3.55] の裏取りへ渡す。
Claude は digest + 裏取り結果で統合・検閲する (subagent-model-tiering.md)。生ログの原文へ跳ぶのは
採用する指摘と digest が曖昧な項目だけ。レビュー出力を無検閲で採用しない。[2] に戻す (既存の反復ループに合流)。green を維持したまま [3.6] へ。[3.5] / [3.6] が出した指摘リストを、採否判断の前に裏取り codex に前処理させる。従来は指摘の真偽確認が
丸ごと Claude の精読に乗っており、ここが本数を増やせない律速だった。裏取りを前置することで、Claude の検閲は
「指摘を一から検証する」から「構築済みの再現手順をなぞって確定する」に軽量化される。
gpt-6.1-sol・high) に指摘リストを渡し、各指摘について:
[3.6] の採否表の
「未確認」に残す。到達経路・契約違反をコードから確認できる場合は、その根拠も添えて採否する。[3.5] の指摘対応が終わり build/test が green に戻った状態で回す。
[3.5] が「問題を探す」レビューなのに対し、ここは 「壊す」ことを目的とした反証パス。
実装者が codex である以上、発見型レビューだけでは「codex が自分の書いたコードを自分の基準で見る」構図が残るため、
明示的に敵対側に立たせるフェーズを分けて置く。
プロンプトは codex-review スキルの「敵対的モード」テンプレートが正本。ここでは再定義せず、そのまま使う
(差分対象の選び方・実行作法も codex-review に従う。command codex / </dev/null / --ephemeral -o / --full-auto 禁止。
ただし出力先は本 skill の「出力の置き場」 (<D> の一意パス) に従う)。
1 本に全部の攻め口を投げず、攻め口 (lens) ごとに分けて並列で回す。「壊す条件を構築する」作業は攻め口ごとに
必要な思考が別物で、1 本に束ねると最初に見つけた 1 種類の周辺を掘って残りが浅くなる。[0] の「既知の弱点」表が
そのまま lens になる。タスクに合うものを 既定 1〜2 本、厚い運用は 2〜4 本選び、選んだ lens を一言明示してから起動する:
循環テスト: 追加されたテストは自作実装を自作テストで追認しているだけでないか。外部 test vector / 実サーバ / 別実装と照合されているか。落とせば「green だが実機で拒否される」を commit 前に捕まえられる
捏造 API / 設定キー: 参照している API・設定キー・オプションが対象バージョンに実在するか
overclaim: サマリ・コメント・コミットメッセージの「対応済み」「保証される」を 1 件ずつ反証する
別ターゲット: codex が動いた環境以外 (Linux / 別 toolchain / 別 OS バージョン) で壊れないか
境界 / 並行 / 順序: 境界値・空・巨大入力・再送・二重実行・部分失敗・再起動で不変条件を破れるか
マイルストーン境界: 前マイルストーンとの結合部・移行中の中途半端な状態で壊れないか
新規ファイルの欠落: 変更が新しいファイルを追加しているなら、「そのファイルが commit /
checkout / patch に含まれなかったら何が起きるか」を攻めさせる。git diff には出ないので
diff 精読では構造的に見えず、抜けると新規ファイルに依存する全経路が同時に死ぬ
(実測 2026-09-08 swift-smbee 076: 共有 init を 1 ファイルへ抽出した変更で、
それが untracked のままだと 5 workflow + ローカル smoke の全 launcher が停止する、を lens が P1 で拾った)
境界違反: D2 コントラクトの境界を破る経路を構築できるか — 依存方向を逆転させずにこの機能を拡張できない 箇所はないか / 別モジュールに割った責務がこの実装で漏れ出していて、次の変更が 2 箇所同時修正を強制されないか / 境界を跨いで内部表現 (型・生データ・状態) が露出していて、片側の変更が他方を黙って壊せないか
目的達成の反証 (リファクタ・改善系で特に効く): その変更が守ると称する目的を、変更後もなお silent に破れる残り経路を列挙させる (例: 「将来 case 追加で壊れない」が目的なら、実際に case を 足す開発者を演じて素通りする箇所を挙げる。実測: obaket 635 round 3 で最多の実害を出した lens)
モデルと effort の既定は読む run の gpt-6.1-sol + high (モデル表)。
未確認の重要な不変条件が残れば、それを攻める lens・実験・外部 oracle を追加する。
「新規指摘ゼロ」だけで閉じず、下の完了条件で判断する。effort の比較はモデル表の手順による。
各 lens は 別々の Bash 呼び出しで run_in_background: true・出力は別パス ([3.5] と同じ並列作法)。
[3.5] と同時に走らせない (3.5 の指摘を直した後のコードを攻めるため)。
manifest の各 lens 行に timeout 列 2400 を付ける (発見型レビューと違い、反証の構築は思考時間が
長く既定の 1200 秒で 時間切れ (当時の rc=143。今は 124) が頻発した — dotfiles issue 150 の実測。3〜4 回落ちて単発再実行では毎回完走)。
900 秒超なので起動は detach 形 (「並列起動の作法」の nohup + Monitor) にする。
🚨 codex-run で 1 本だけ起動するときも -t 2400 を明示する。codex-run は timeout を
CODEX_FANOUT_TIMEOUT の既定 (1200 秒) から取るので、付け忘れると 20 分待ってから 時間切れ (rc=124) で
本文ゼロになる (実測 2026-09-15 obaket 820 の D3: 32,062 行のログだけが残り、-t 2400 で
再実行して 1,426 秒で完走した)。上の manifest の記述は codex-fanout の列の話なので、
1 本だけのときに落としやすい。
# 起動は codex-fanout driver が既定 (lens ごとの brief + review-lens-header.md を連結する manifest)。
# --- fallback の per-call 形: lens ごとに別 Bash 呼び出し・run_in_background。パスは round と lens で一意にする ---
out="<D>/<literal-stamp>.r<N>-adv-<lens>.md"; log="$out.log"
command codex exec review -m gpt-6.1-sol -c model_reasoning_effort="high" \
--ephemeral -o "$out" </dev/null \
"<codex-review「敵対的モード」テンプレート全文 + この lens の攻め口だけを指定>" > "$log" 2>&1; tail -40 "$log"
打ち止めは「工程の厚さと完了条件」で決める: 1 ラウンド後に重要な指摘・不変条件・未確認範囲を照合する。 採用指摘を修正した場合は、その修正と回帰を再レビューする。未解決の重要項目があるときは、 そこに合う別 lens・実験を選ぶ。「新規ゼロが 2 周」は探索の記録に残してよいが、閉じるための必須回数にはしない。
<D>/design.<タスク名>.md) に追記して各ラウンドの統合検閲の直後に更新する
(<D> の外に台帳を置かない)。解消した項目は行を消さず「解消 (round N)」と記す — 消すと次ラウンドで
同じものが「新規」に見える。行番号では同定しない (修正のたびにズレる)。
file:line や言い回しが変わっただけの同一原因は既出、
前ラウンドで「未確認リスク」だったものに具体的な発火条件が付いたら新規として数える (格上げは発見であり、
既出扱いで捨てると最も価値のある反証を落とす)。[6] / D2・D3 に戻す、② 残リスクを明示して
ユーザーに判断を仰ぐ、のどちらかを選ぶ。4 ラウンド目は回さない (モグラ叩きにしない)。[2] に戻ったときの再開地点: [3] (build/test + diff 精読) は毎回必ず通す。
[3.5] の発見型レビューは再実行しない (同じ観点を毎ラウンド流すのはトークンを使うだけで視点が増えない)。
例外は修正がマイルストーンの構造を変えたとき (新規ファイル・境界の引き直し) で、そのときだけ [3.5] に戻る。採否の前に [3.55] の裏取りを通す (指摘 3 件以上のとき)。その上で codex-review「敵対的レビューの作法」の
仕分けに従う(敵対レビューほど無検閲採用が危険):
| 出力 | 扱い |
|---|---|
| 発火条件が具体的 → 再現またはコード・契約で裏取りできた | 修正対象。[2] に戻して構造的に直す (直したら次ラウンドで攻め直す) |
| 発火条件が具体的 → 再現できない | 到達経路・契約違反をコードでも確認する。確定できなければ未確認、到達不能などの反証があれば根拠つきで却下 |
| 未確認リスク (発火条件を示せない) | 修正しない。残リスクとして報告 / issue 化し、[6] の観測ポイント候補にする |
| 「起こりえないが念のため」提案 | 原則採らない。その入力の出所を示せた時だけ採る |
| 「壊せなかった」 | green の根拠にしない。重要な不変条件はテストで固定して初めて閉じる |
[3.6] の採用指摘を解消し、重要な不変条件の確認対象を整理した状態で、実装ではなくテストだけを書かせるフェーズを 1 本回す (この後 [3.8] で
テストの検知力を機械検証してから commit する)。
[3.6] の採否表は「壊せなかった = green の根拠にしない。重要な不変条件はテストで固定して初めて閉じる」と
している。その固定作業をやるのがここ。敵対的レビューは指摘を出して消えるが、テストはリポジトリに残って
次の変更でも同じ攻撃を自動で再実行する — 消費したトークンが恒久資産になる唯一のフェーズなので、
[3.6] を削ってでもここは通す価値がある。
[2] の仕事)。
ただし sandbox mode は prompt の禁止を強制しない (danger-full-access なら何も止めない) ので、内容スナップショットで検出する。
[2] の実装差分は未コミットのまま (M path) なので、パス一覧の比較では実装への追加編集を検出できない
(前後とも M path のまま)。前後の差分の中身を比べる:# 起動前 (上の起動コマンドと同じ Bash 呼び出しで)
git diff > "<D>/<literal-stamp>.pre.patch"
git status --porcelain --untracked-files=all > "<D>/<literal-stamp>.pre.status"
# 終了後
git diff > "<D>/<literal-stamp>.post.patch"
git status --porcelain --untracked-files=all > "<D>/<literal-stamp>.post.status"
diff -u "<...>.pre.patch" "<...>.post.patch" | head -200 # ← [3.7] が実際に足した変更
diff -u "<...>.pre.status" "<...>.post.status" # ← 新規ファイルの検出
[3.7] 実行中に並行セッションが触った可能性もあり、中身を見ずに checkout すると他人の作業を消す。git checkout -- <path> で HEAD に戻し、
pre.patch の当該パス分を git apply で再適用して起動前の状態に戻す (単に checkout すると
[2] の実装まで消える)。untracked の新規実装ファイルは checkout では消せないので、内容を確認して
削除する。[3.6] の探索ラウンドとは別のカウンタ
(あちらは敵対レビューのラウンド、こちらはテスト生成のラウンド)。混ぜて数えない。失敗は「要求した観点が揃わない」「テスト自体がコンパイルできない」「偽 green
(ミューテーションで落ちない)」だけを数える。追加テストが妥当で実装バグを見つけたため [2] に戻った回は、
テスト生成の成功なので数えない。テスト側の誤りを直させた回もカウントを進めない。これは、仕様・oracle・入力・
対象ファイル範囲が事前に確定していて量が限られる場合に限る「重い実装を Claude が書かない」の例外であり、
fixture / helper / mock / production コードは Claude が書かない。条件が未確定、外部 vector が無い、または未確認リスクが
多い場合はテストを書かせず [6] か設計へ戻す。[3.6] で「反証できなかった」と報告された不変条件 / [D3] の失敗モード表で「吸収する」と
宣言した経路 / 境界値・異常系・再実行。
「未確認リスク」は的に含めない。発火条件が示せない項目にはテストの入力も oracle も無く、codex が
契約を創作した mock テストになる (そしてそれが落ちて「実装のバグ」と誤判定される)。未確認リスクは
[6] の観測で契約が確定してから、改めてテストに昇格させる。grep -c '@Test' の実測値とテスト総数を貼らせる
(実測ではこれを書いた回だけ本数が揃った)。ただしこれは要求本数の取りこぼし検出であって、検知力の証明ではない
— parameterized test / 1 宣言に複数ケース / コメント内の文字列も数に入る。実装を落とせるかは [3.8] の
ミューテーションで別に確認する。本数と検知力を同じ指標として扱わない。max (モデル表の書く run)。「実装を落とす入力」を組み立てるのは構築作業で、
effort を落とすと常に真になる assert や壊せないヘルパーが出やすい (実測)。
モデルは gpt-6-luna。テストを自分で回させるので実装と同じ -s danger-full-access (外せない環境は workspace-write)。# 起動前スナップショット (上の pre.patch / pre.status) をこの呼び出しの冒頭で採る
out="<D>/<literal-stamp>.harden.md"; log="$out.log"
command codex exec -s danger-full-access -m gpt-6-luna -c model_reasoning_effort="max" \
--ephemeral -o "$out" </dev/null "$(cat <<'EOF'
このマイルストーンの実装を「落とす」テストを書く。git 操作 (commit / pull / checkout / stash 等) はしない。
## 絶対の制約
- **テストファイル以外は変更しない**。実装のバグを見つけても直さず、それを落とすテストとして書く
- 自作実装を自作テストで追認するだけの循環テストを書かない (自作 encode を自作 decode で往復させる形を含む)。
外部 test vector / spec の例 / 別実装 / 実サーバ応答との照合を優先し、照合先が無ければ片側の実装に
依存しない性質 (冪等・順序不変・境界での単調性・不変条件の保存) で書く
## 狙う的
- <[3.6] で「反証できなかった」不変条件・失敗モード表の吸収経路・境界/異常系。
発火条件を示せなかった「未確認リスク」は的に含めない>
## 出力
- 追加したテストと、それぞれが「何を破ろうとしているか」
- 実装のバグを示せた (= 落ちた) テストがあれば、それを最初に列挙する
EOF
)" > "$log" 2>&1; tail -40 "$log"
[2] に戻す。
テスト側が誤っていたら、そのテストを直すか捨てる — 正しい実装を誤ったテストに合わせない
(「テストを緩めて通さない」は、妥当なテストを甘くするなという意味であって、誤ったテストを守れではない)。refuse-low-value-coverage.md の判断軸)。
加えて ハング (無限待ち・タイムアウト無しのネットワーク待ち)・破壊的 teardown (共有リソースの削除)・
環境依存 (実機/GUI/時刻/ロケール) を持ち込んでいないか見る。CI を壊すのはたいていこの 3 つ。[3.7] がテスト差分を新たに足した以上、その差分は敵対レビューを通っていない。テストを追加したら [3.6] を 1 ラウンドだけ、追加テスト差分に絞って回す
(lens はテスト品質 = 循環テスト・偽 green・環境依存)。追加テストがゼロなら追い撃ちも不要。codex exec review は差分の選び方を自分で決めるため
「追加テストだけ」を渡せない ([2] で既に触ったテストファイルは以前の hunk が混ざる)。追い撃ちは
codex exec -s read-only にし、上で保存した pre/post の差 (= [3.7] が足した hunk) を
プロンプトに貼って対象を固定する。[2] に戻る。戻った後は [3] → [3.7] 再実行 → 追い撃ち、と巡回するが、
この巡回は最大 2 巡。2 巡しても新しい実装バグが出続けるなら、マイルストーンの切り方か設計前提を疑って
[6] / D2・D3 に戻す (通常 [3.6] の 3 ラウンド上限とは別枠で数える)。[3.6] を省略できるマイルストーン (機械的置換・rename のみ) と、
既存テストが受け入れ条件を完全に機械判定していて追加の的が無いとき。省略したら一言明示する。[3.7] で足したテスト (と既存テスト) が本当に実装の破壊を検知できるかを機械検証してから commit する。
「テストが green」は「テストに検知力がある」の証明にならない — 陽性対照なしの assert・空振りの検証は
書いた直後の自分でも見逃す (起源: 2026-07-30 の bench/fzf テストで「除外 assert が元データ不足で空振り」を
セルフレビューで検出した実例。人手のセルフレビューを機械化したのがこのフェーズ)。
git worktree add <path> HEAD + 未コミット実装を patch で持ち込む)。
本流でミューテーションしない: 変異の復元に git checkout を使うと未コミットの実装/修正ごと巻き戻す
(2026-07-29 に実際に起きた事故。worktree なら丸ごと捨てられるので復元事故が構造的に消える)。
worktree に patch を持ち込んだら baseline commit を作ってから注入させる。持ち込んだ直後の worktree でも
patch は未コミットなので、codex の git checkout -- . 復元が seam ごと消してテストがコンパイル不能になる
(obaket 696 項目 4)。-s danger-full-access・-C <worktree>・gpt-6-luna・max —
機械作業。トークン経済 3)。🚨 例外: sandbox を外せない環境で、その repo の swift test が sandbox で走らないと
1 度分かったら、以降のマイルストーンでは実行ループを codex に回さない。変異 patch の生成だけ codex read-only に
作らせ、適用 → テスト実行 → 復元は最初から Claude のハーネスで当てる (obaket 650 M1: max effort で 15〜40 分の
ループが typecheck だけで「全成功」を返し、Claude が全部当て直した。回させた分は丸ごと無駄。issue 369 1-1。
Claude 側の作業は増えるが、判定はどちらでも Claude の実行結果なので質は変わらない)。プロンプト: 「このマイルストーンの実装に、現実的なバグを 3〜5 個、1 個ずつ独立の
patch として作れ (境界の off-by-one・条件の反転・エラー処理の握りつぶし・early return の欠落など、
レビューで見逃しやすい類)。各 patch は git diff 形式で別ファイルに保存し、1 個ずつ適用 → テスト実行 →
git checkout -- . で復元を繰り返せ。テストファイルは触らない。出力は変異ごとの結果表:
patch ファイルパス / 変異の内容 1 行 / テストの生の終了コード / 落ちたテスト名 (検知漏れなら「検知されず」)」
git diff、-U3) で保存させる。-U0 / context 無しを使わせない。
context の無いハンクは git apply が照合できず、再適用すると意図しない位置に落ちる
(実測 2026-09-15 obaket 809: @@ -1080,0 +1080,5 @@ の挿入がファイル末尾の top level に入り
statements are not allowed at the top level でビルド不能になった)。codex 自身は context 照合の
apply_patch で当てるのでその run では正しい位置に入り、保存された成果物からだけ再現できない。
抜き取り追試が空振りするだけでなく、後から「codex が何を検証したのか」を誰も確認できなくなる[4] へ[3.7] に的として差し戻し
(「この patch を落とすテストを書け」— 的が具体的なので循環テストになりにくい)。テスト追加後に漏れた変異だけ再検証[3.7] を省略したマイルストーン (追加テストなし + 既存テストで受け入れ条件を完全機械判定)。
省略したら一言明示する。worktree は成否に関わらず必ず削除する。
後始末に stale な swiftpm-testing-helper の確認を含める: codex の swift test --disable-sandbox や worktree での mutation 実行が
helper プロセスを残す (obaket 674 項目 6: 5 個以上残留。無害だがリソースを食う)。pgrep -fl swiftpm-testing-helper で確認し、
自分が起動した scratch / worktree の path を持つものだけ kill する (他セッションの実行中 helper を巻き込まない)。
🚨 timeout N swift test で打ち切った run は、子の helper が必ず孤児になる (timeout は親しか殺さない)。変異ループの
各 run の直後に helper を刈る (実測 2026-09-05: 5 時間超の孤児 3 本が残った)timeout で rc=124) は「検知できなかった」ではなく
「テストが停止を失敗にできない」という別の穴。原因は大抵 2 つ: suite に .timeLimit が無い / await task.value が
外側の cancel に反応しない (unstructured Task の値待ちは time limit でも中断されない → cancel を転送する helper を通す)。
fake clock の「条件が来るまで待つ」observer も cancellation-aware にしておく。実測 2026-09-05 M1: 最初の hang は
time limit を付けても抜けず、この 2 点を直してから初めて red になったswift build が「Another instance of SwiftPM is already running ... waiting」を出したら待たない。lock を握って
いるのは大抵 read-only codex が sandbox で試した swift test --skip-build (hang する) か、前の変異 run の孤児。
ps -axo pid,etime,command | grep swift で見て kill する。実測 2026-09-05: 気づくまで 2 時間 53 分待ったgit add <path> (commit-policy)。並行する他作業/WIP を巻き込まない。[S] / [D1]〜[D3] で受け入れ条件が変わったら、設計ファイルだけでなく issue 本文にも移す。
設計ファイルは <D> にあり gitignore されるのでcommit されず、make clean-tmp で消え、別マシンには無い。issue に移し忘れると、
完了時のチェックリストが起票時の (古い) 条件だけになり、敵対レビューが足した条件が
誰にも検証されないまま done になる (実測 2026-09-07 obaket 740: D3 が足した 5 条件を設計ファイルに
だけ書き、done へ移す直前に気づいて移した)。移すのは条件そのものと、それが足された理由 1 行
(move-report-conclusions-to-issues.md)。grep -n 'tmp/' <issue> で
gitignore 配下への参照が無いか見る。codex は生出力のパスをそのまま
markdown リンクで書く。手元には実体があるのでリンク検査は通り、新品チェックアウトと
CI でだけ落ちる (実測 2026-09-15 obaket 809: tmp/809/mutations.md へのリンクが
check-doc-links を素通りしていた)。見つけたら中身を issue 本文へ転記してリンクを外す
(パスを tracked へ移すのではない — 同じものが 2 箇所になる)。
地の文での言及 (「原文は tmp/… にある」) はリンクではないので残してよい。gh run watch <id> --exit-status で結果を待つ。GUI/実機など自走確認が難しい検証は
スクショ・ログ・人間確認を受け入れ条件に含める。instrument-before-second-fix.md)。<D>/design.<タスク名>.md) を更新してから
実装に戻る。承認ゲートは初回限りではなく、設計が変わるたびに通す (黙って設計を変質させない)。[1] の分割時に落ちた要件はここでしか捕まらない)。[1] に戻して追加マイルストーンを切るか、ユーザーに判断を仰ぐ。<D>/design.<タスク名>.md) を削除してよい (ユーザーが「残して」と明示したら残す)。| skill | 主役 | 使う場面 |
|---|---|---|
| codex-drive (本 skill) | codex が設計壁打ち + 実装、Claude が検閲/観測/反復と承認ゲート運営 | コード量が多い実装・移植・プロトコル実装。codex トークンを積極消費し、Claude トークンは digest 検閲 + ファイル参照で節約 |
| codex-lead | codex が設計リード、Claude が実装 | 設計は codex に任せつつ実装の主役は Claude にしたい時 |
| forge | 専門家エージェント並行 + クロスレビュー | 高品質・多視点が要る実装/レビュー。バグ修正の自前試行が 1-2 回失敗した escalation 先 |
| codex-review / cross-review | レビューのみ | コードは変えない |
git diff、-U3) で保存させる (-U0 は再適用すると別の位置に落ちる)codex-run で敵対レビューを 1 本だけ回すときも -t 2400 を明示する (既定は 1200 秒で 時間切れ (rc=124) になる)grep -n 'tmp/' <issue> で gitignore 配下へのリンクを潰す[7] の codex を省き、D3 と [3.6] の敵対だけ残す$stamp 等のシェル変数を後続の Bash 呼び出しに持ち越す (空文字に化ける。リテラルで書く)codex exec review の stdout を保存せず tail の表示だけで「指摘なし」を判断する (本文が -o に出ないことがある。merger に tail や抜粋だけ渡すのも同罪)~/dotfiles/bin/codex-fanout — 並列起動 driver の実体 (manifest 形式・exit code・出力レイアウトの正本は冒頭 usage)。テンプレートは本 skill の templates/ (merger.md / review-lens-header.md)~/.claude/skills/codex-review/SKILL.md — command codex / </dev/null / --full-auto 禁止などコマンド作法の正本。敵対的レビュー ([3.6] / D3 の敵対観点) のテンプレートと指摘採否ルールもここが正本。検証フェーズのレビュー委譲先~/.claude/skills/codex-lead/SKILL.md — 設計は codex・実装は Claude の分担 (本 skill は設計も実装も codex)。D2 の設計コントラクト形式の正本 (1-5)~/dotfiles/_claude/rules/subagent-model-tiering.md — 下位主体の出力は main が必ず検閲~/dotfiles/_claude/rules/instrument-before-second-fix.md — 観測駆動デバッグ (本 skill の [6] の正本)~/dotfiles/_claude/rules/escalate-to-forge-after-failed-tries.md — 収束しない時の escalation아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
プロジェクト監査。「監査して」「audit」「/audit」で発火。設計/UX/品質/テストなどの観点でコードベース全体を監査し、課題をissuesディレクトリに書き出す。実行ログで重複実行を防止。特定の差分・コミットのレビューには使わない(codex-review / cross-review を使う)。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
AVFoundation (AVPlayer / AVPlayerLayer / AVPlayerItemVideoOutput / AVAsset) の落とし穴・文書化されていない実装挙動・debugging チェックリストを集約した reference skill。Swift / Objective-C で AVPlayer を使った動画再生 / seek / scrub / frame stepping を実装・debug するときに発火。VLCKit ではなく **AVFoundation 系** の問題に特化。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
このセッションで行った変更をコミットする。「コミットして」「commit」「/c」で発火。push はしない/クレデンシャルは混入させない。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
ディレクトリ・レイヤーごとに置いた CLAUDE.md と README.md が実体 (コード・コマンド・構成) とずれていないかを点検し、裏の取れた乖離だけを直す。引数で対象のディレクトリを任意に指定できる (省略時は repo 全体)。「CLAUDE.md を refresh して」「README が古くないか見て」「claude-md-refresh」「/claude-md-refresh」で発火。issues/ の更新漏れは issue-writeback / issue-sync の担当で、この skill は扱わない。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
タスク着手時に codex にリードしてもらうワークフロー。codex に設計/方針を主導(リード)させ、その方針に沿って Claude が実装し、実装後は codex で設計適合・実装正当性・敵対的(red team)の 3 観点でレビューする。余っている codex トークンを積極的に消費したい時に使う。「codexにリードしてもらって」「設計から codex に任せて」「タスクを codex 主導で」「codex-lead」「/codex-lead」で発火。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
codex exec review を基本に、必要なら codex exec を使ってコード変更のレビューを依頼し、指摘事項を報告する。通常 / 厳しめ (--strict) / 敵対的 (--adversarial、実装を壊しにいく red team) の 3 モードを持つ。「codexでレビューして」「codex-review」「/codex-review」「敵対的にレビューして」で発火。Codex 単体での単独レビュー用途。複数エージェント並行レビューは cross-review、差分ではなくコードベース全体の監査は audit を使う。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.