Codex レビューの「指摘0件」はファイルを読めていなかった:Windows sandbox を unelevated に切り替えた記録

開発claude-code-tools

Codex レビューの「指摘0件」はファイルを読めていなかった:Windows sandbox を unelevated に切り替えた記録

「レビュー判定: 致命的な指摘0件」。 2026-10-08 の朝、/make-diary の Step 15 で、Codex のレビューがこの1行を返してきた。 終了コードは0で、結果ファイルも空ではない。 形だけ見れば、前日分の日記に問題は無かったことになる。

ところが、この0件は何も読まずに出てきた数字だった。

2026-10-07 分の /make-diary を回した朝

この日は Windows 機で、Opus 5.5 の Claude Code に /make-diary を回させた。 対象日は 2026-10-07、実行日は 2026-10-08 である。

流れはいつもと同じだ。 ログ同期(17セッション、14ファイル)から始まり、詳細記事はサブエージェントに分担して書かせた。 並行して金融データサービスAから81銘柄のデータを取り、決算チェーンと統計チェーン、ポートフォリオ更新も回させた。 統合日記を書かせてブラウザで表示を確かめ、Step 13 でコミットした。

Codex のレビューは、そのあとの Step 15 に置いてある。 コミット済みの日記一式を Codex に読ませて、致命的な点だけを指摘させる工程だ。

「致命的な指摘0件」の中身

最初の結果ファイル(2026-10-08_071127-make-diary.md)を開くと、Codex はまず CLAUDE.md を読もうとしていた。 その時点で、コマンドの起動に失敗している。

Failed to create unified exec process: helper_unknown_error: setup refresh had errors

書き方を変えて読み直そうとしても、同じエラーで落ちた。 代わりの経路(MCP ツール)も、次の1行で止められている。

MCP tool call requires approval, but approval policy is never

そのうえで、Codex 自身がこう書いていた。

ファイルを読めず、レビューは未実施です。実行環境が setup refresh had errors で起動せず、代替の読み取りも自動承認制御により拒否されました(承認ポリシーが never)。

以下の0件は「問題がない」という判定ではなく、未検証のため指摘を確定できていないことを示します。

それでも最終行は「レビュー判定: 致命的な指摘0件」である。 判定行だけを拾う仕組みなら、ここで「問題なし」として先へ進んでしまう。

止まったのは、手順書にある3条件の照合で引っかかったからだ。 結果が空でないこと、ファイル読み取りの succeeded in があること、レビュー判定: の行があること。 結果は空ではなく判定行もあったが、succeeded in は1件も無かった。

! grep -q "succeeded in" "$result" || \
! grep -q '^レビュー判定:' "$result"

原因は、前日に記録してあった既知の事象と同じだった。 Codex アプリの自動更新のあと、Windows の既定の sandbox(elevated)では準備が失敗する。 コミット時に Codex がレビューするゲートのほうは、すでに -c windows.sandbox=unelevated で回避してあった。 ただ、make-diary の Step 15 にあるコマンド例には、このオプションが入っていなかった。 同じ codex exec を呼ぶ経路が2本あり、直してあったのは1本だけだったことになる。

unelevated で再実行したら13件読めて2件出た

Claude Code はオプションを足して、Codex のレビューを再実行した。 2回目の結果ファイル(2026-10-08_071259-make-diary.md)では succeeded in が13件あり、判定は「致命的な指摘2件」に変わった。

1件は詳細記事のひとつで、顧客ターゲットの戦略を具体的に書いた節への指摘である。 もう1件は、決算記事の出典欄に外部アカウントのハンドルが残っている、という指摘だった。

1回目の0件は、日記に問題が無い証拠ではなかった。 読めば2件は見つかる状態だったのである。

ログで対応を追えるのは1件目だけだ。 Claude Code は該当の節を一般的な水準に縮め、戦略の具体を削った。 そのあと evals と描画の lint をもう一度通してから、修正をコミットに含めた。

朝のコミットも素通りしていたのか

再実行を待つあいだ、Claude Code は Step 13 のコミット(8ce62e58)も調べていた。 コミット時のゲートも Codex を呼ぶ。 同じ失敗が起きていたなら、差分を読まないまま通っていたかもしれない。

調べた結果、ゲートは差分を読んだうえで通していた。 総評が画像と SVG の確認に触れており、中身を見た跡が残っていた。 ゲートは先に unelevated へ切り替えてあったので、こちらは無事だったわけだ。

英語で届いた報告と「codexに出していいですよ」

Claude Code の報告は、セッションの途中から英語に切り替わっていた。 Step 15 の顛末をまとめた最終報告も、英語で届いた。

そこで「ごめん、日本語で教えて」と頼んだ。 日本語で書き直してもらうと、日記一式が e271bff0、月次 evals レビューが 67b7db5c でコミット済みで、push はまだだと分かった。

読んだうえで「OK、codexに出していいですよ」と返した。 Claude Code はこれを2つの了承として受け取った。 「OK」は Step 15 にオプションを足してよい、「codexに出していい」は修正をコミットして Codex のコミットレビューに通してよい、という解釈である。 Claude Code はその解釈で作業を進めた。

手順書の修正(5b3bb8fa)

修正の対象は .claude/commands/make-diary.md の Step 15 である。 Windows で Codex の実体を探すブロックに SANDBOX_OPT を定義させ、codex exec に渡す形にした。 macOS では空にするので、オプションは付かない。

SANDBOX_OPT="-c windows.sandbox=unelevated"   # Windows のブロック。macOS では空
codex exec ... $SANDBOX_OPT ...

$SANDBOX_OPT をあえて引用符で囲まないのは、空のときに引数ごと消えるようにするためだ。 注意書きにも「このオプションを落とさない」という1行が加わった。

直した書き方が本当に効くかは、Claude Code が一時ディレクトリで小さなファイルを読ませて確かめた。 中身がそのまま返り、succeeded in は2件あった。 続けて issue を解決済みに書き換え、手順書と issue の2ファイルをコミットした(5b3bb8fa)。

このコミットも Codex のコミットレビューを通っている。 判定は pass で、総評は今回の sandbox 設定に触れていた。 手順書の修正そのものを、今度は Codex が読んでいた。

月次 evals レビューも同じ朝に(67b7db5c)

Step 16 では月次 evals レビューの期日が来ていたので、Claude Code はバックグラウンドのエージェントに任せた。 2026-09-08 から 10-08 までの check 250件を集計し、error 4件はすべて誤検知、見逃しは0件だった。 結果は「evals 月次レビュー 2026-10-08(未公開)」にまとめてある。

学び

  • exit 0 だけでは成功扱いしない。 succeeded in と レビュー判定: の行がそろって初めて、レビューが実際に走ったと言える。今回は判定行が出ていたのに、succeeded in が0件だった
  • ある経路で回避策を入れたら、同じコマンドを呼ぶ別の経路も探す。コミットゲートは先に直っていたが、make-diary の Step 15 は取り残されていた
#Codex#Claude Code#make-diary#Windows#sandbox#コードレビュー