形骸化した学習ゲートをやめ、pre-commitでCodexのコードレビューを自動化した
朝いちばんに /procs を打った。
Claude Code のセッションを何本も開くので、dev サーバーと MCP サーバーが二重三重に立つ。
一覧が出たところで、そのまま Windows を再起動するつもりだったのを思い出した。 再起動すれば全部消えるので、その回は1本も止めずに終えた。
昼前にもう一度打った回では dev サーバーを3本止めている。 ただ、止めた直後に別のセッションが新しいのを立て始めていて、差し引きでは減っていない。
止めずに終えた朝の一覧の中で、learn-quiz の MCP サーバーが目に留まった。
スキップし続けた学習ゲートをどうするか
学習ゲートは、コミットの前にクイズへ合格しないと通れない仕組みとして入れてある。 ところが最近はずっとスキップ用の環境変数を付けて素通りしていた。 通していないのだから、止めるものは何もない。
無効化を決めた。 ただし消しはしない。 いつか有効化したくなる日が来ると思うので、quiz-server はリネームするだけにして実体は残させた。
そのうえで、前から欲しかったものを代わりに入れることにした。 コミットのたびに、その差分のコードレビューが自動で走ってほしい。
モデルは Codex 側の gpt-5.6-sol を指定し、reasoning effort は high にした。 手元の Codex CLI でそのモデルが使えるかを先に確認してもらってから、実装に入らせた。
critical と high の指摘が出たらコミットを止める。 medium と low は表示するだけで通す。 この線引きにした。
作ったゲートに、自分が11回止められた
出来上がったので .claude をコミットした。
通らない。
自分で入れたゲートが、自分のコミットに critical 3件と high 1件を出してきた。 どれも実在の穴だったので、1件ずつ直しては再コミットした。
4巡目の指摘が効いた。
レビュー用のコマンドをリポジトリ直下で実行しているので、その気になれば .env を読めてしまう、という内容だった。
正論なので隔離実行に作り替えさせた。
そのあとも毎回新しい穴が出てくるので、シェルでファイル一覧を回していた部分をやめ、Python 一本に寄せた。
次の巡で、コミットは通った。
通ってしまった、と書くほうが正しい。
差分の中に aws_secret_access_key という文字列が入っていたせいで、ゲートがこれを「機密を含む差分」と誤検出し、レビューそのものを飛ばして通していた。
検出パターンを詰め始めたら、今度は YAML の表記ゆれを延々と追う作業になった。 ここで打ち切った。
一連のやりとりに約1時間かかっている。 ゲート自身が自分のコミットを11回ブロックしたぶんである。 落ち着いてからの通常のコミットは、1回およそ50秒で終わっている。
自分で作った検査に自分が最初に引っかかる。 順番としては正しい。
除外リストが何を見ているか
顧客情報を含むリポジトリの差分は外部AIへ送れないので、除外リストを別ファイルで持たせてある。 中身を見たくなったので、フルパスを教えてもらったうえで Chrome の前面タブに開かせた。 19件が文字化けなく並んだ。
上から読んで、税務系のリポジトリ名が入っているのを確認した。 あのディレクトリ以下はまるごと税務系なので、これで大丈夫だろうと返した。
ところが判定はリポジトリのルート名だけを見ていて、置かれている場所は問わない作りだった。 「親ディレクトリごと除外されている」という読み方は、その時点までは成り立っていなかった。 目で1回追ったおかげで、穴が1つ出た。 修正してコミットし、push まで済ませた。
Skill ツールから呼べないスキルを呼ぼうとしていた
別の作業で codex:review を Skill ツールから呼んだら、disable-model-invocation で拒否された。
落ちているのかと思ったが、そうではない。
ユーザーが /codex:review と手で打つためのスキルなので、Claude 側からは起動できない。
仕様どおりの拒否だった。
引っかかったのは、別セッションでも同じ失敗を見ていたことだ。
同じスキルを、違うセッションが違う場面で呼ぼうとしている。
偶然ではないはずだと思って追わせたら、codex-review-doc スキルの説明文が、未コミット差分のレビューは /codex:review が担当すると案内していた。
呼べないものを毎回指していたのは、こちらの設定だった。
それなら、このスキル経由のレビューは実質的に機能していない。 codex プラグイン側を使う形に書き換えさせた。
ついでに運用方針もはっきりさせた。 計画を作ったら承認を待たずに実装まで進めてほしいし、実装したら Codex のレビューも勝手に受けてほしい。 一つずつ許可を取りに来るのをやめてほしい、という話である。
その直後のコミットが、またゲートに止められた。
今日書いた文言が、参照先の記述と食い違っていたためである。
「コミットしないときは codex-review-doc で回せ」と案内を足した一方で、当の codex-review-doc は「未コミット差分は対象外」と自分で断っている。
さらに critical として出たのは、自分のグローバルルールに抵触する手順を書いてしまっていた、という指摘だった。
顧客情報を外部AIに渡さない、.env を読まない、というルールの両方に引っかかっていた。
4回止められた。 4回目の指摘は「完全なシークレットスキャナーを必須にせよ」で、要求が上がり続ける形になっていた。 条件を足して安全にする方向をやめ、ファイル全体を外部AIへ送る例外経路そのものを削らせた。 もともと自分が頼んだ機能ではない。 「コミットしない場合はどうするか」を埋めようとして増やした穴だった。
消してよい検証データの見分け方
検証用に作った法人と、そこに入れた検証仕訳4本をどうするか決めた。
2021年の仕訳で、繰越利益剰余金2万9091円の根拠になっている。 消すと記事や実測メモのケースが再現できなくなるかが気になったが、その数値がメモに書いてあるなら消してよい。 キャッシュフローの論点からは外れているものだと思うので、なおさら残す理由はない。
一方、使い捨てのつもりで書いた検証スクリプトは、動くものができているので会計ソフトA用のディレクトリへ移す方針にした。 3本とも移してもらったうえで、置き場所は分けてある。
別セッションの置き土産を回収する
~/.claude に、別セッションでやったスキル棚卸しが未コミットのまま残っていた。
skills 配下の大量の移動と削除に、CLAUDE.md の変更が加わったものである。
そのまま2コミットに分けてコミットし、push させた。 そのあとに見つかった設定の不整合も直して、もう1コミット足した。 作業ツリーはクリーンになり、origin と同期した。
セッションを並行で回していると、こういう置き土産が出る。
朝いちで git status を見る習慣は、やはり要る。
トップのドラフト節を外し、全文モードにサイドバーを足す
午後は表示側にまわった。 dev サーバーをポート3200 で立ち上げさせて、トップページを開いた。
「ドラフト」節に並んでいる財務諸表のテキストとクイズの2件が、もう /lessons に入っているのではないかと思って調べさせた。 入っていなかった。 目次データに載っておらず、トップのドラフト節がサイト内で唯一の入口になっていた。
そこで2件を /lessons 側へドラフト扱いで移し、トップからは節ごと外した。 触ったのは2ファイルだけで、同じディレクトリに残っていた未追跡の memo は巻き込んでいない。
教材ページには「スライドで読む」と「全文を読む」の2モードがある。 全文側に切り替えると、左のセクション列が消えて、いま何章のどこを読んでいるのか分からなくなる。 右の目次も、その章の全部が出ていない。
左にはスライド側と同じ章一覧(現在章をハイライト)を、右には章全体の見出し目次を付けさせた。 ホストのコンポーネントが1本なので、所得税法の章だけでなく8冊すべての章に一度に効く。 描画、スクロール追従、章の移動、モバイル幅まで Chrome で確認させた。
並べて見ると、今度は右サイドバーの幅がモードで違うのが目についた。 スライド側のほうが広い。 狭いほうへ合わせる理由がないので、両モードの幅を実測させたうえで、全文側を260pxへ広げた。
このコミットは Codex のレビューを指摘ゼロで通った。 critical と high だけでなく、medium と low も出ていない。
今日の学び
- 通していないゲートは、ゲートではない。スキップが常態化した時点で、形だけ残った儀式になっている
- 自作の検査は、自分のコミットを11回止めてもらって初めて穴が見えた。作った直後に自分で通すのが、いちばん安いテストになる
- 「このディレクトリ以下は全部対象」のような思い込みは、実装が何を見ているかを1回読めば崩れる
- 指摘のたびに条件を足していくと、要求が際限なく上がる。守る条件が増え続けるなら、その仕組み自体を畳むほうが速い