← 一覧に戻る

plan-viewer フック修正計画 — 「そもそもフックが動いてなかった」問題を根本から直す

2026年3月7日 17:46 更新

一言でいうと

plan-viewer の自動チェック機能は実は一度も動いていなかった。承認メニューがフックを通らないのが原因。「実装の入り口」で止める方式に作り直す。

なぜこれが必要なのか

plan-viewer には「プランを承認する前に、非エンジニア向けHTMLを作りなさい」と自動で促す仕組み(hook = 特定操作の直前に別の処理を差し込む仕組み)がある。

しかし今回の調査で、この仕組みが一度も動いていなかったことが判明した。Claude Code のプラン承認メニュー(「Yes, and bypass permissions」等の選択肢)はフックのシステムを完全にスキップしていたため、チェックが一切かからずプランがそのまま実装に進んでいた。

放置すると、プランの内容がHTMLに変換されないまま実装が完了し、非エンジニアがプランの内容を確認できない。

何が起きていたのか

発見1: フックが一度も発火していなかった

tmux(ターミナルを分割してプログラムを動かせるツール)で Claude Code を3回テストし、デバッグ用のログも仕込んだ。結果、ログは完全に空。フックのスクリプトは一度も呼ばれていなかった。

原因は Claude Code のプラン承認メニュー。プランが完成すると「1. Yes, clear context / 2. Yes, and bypass permissions / ...」という選択肢が表示される。この選択肢を選んでプランモードを終了すると、内部的にフックを通らずに直接プランモードが解除される。これは GitHub Issue #15660 で報告されている既知の仕様。

発見2: プランモード中は Write が使えない

仮にフックが動いても、プランモード中は「ファイルに書き込むな」というAIへの指示が効いているため、HTMLを書けない。この指示はプログラム的なブロックではなく、AIへのテキスト指示(プロンプト)だけで制御されているが、AIはこの指示に忠実なので実質的に書けない。

発見3: 「プランモード終了」専用フックは未実装

理想的な解決策である「プランモード終了時フック」(PlanModeExited)は、GitHub Issue #20526 で提案されているが、2026年3月時点で未実装。

今までの設計(機能していなかった)

  • ExitPlanMode の「前」にチェック
  • 承認メニュー経由だとフック不発火
  • 実質ゼロ回動作

新しい設計

  • 「実装の入り口」でチェック
  • Write/Edit/Bash を全部ゲート
  • 承認メニューに依存しない

どう直すのか — Codex(GPT-5.4)と合意した設計

「プランモード終了」は検知できないので、プラン承認後に最初の実装ツール(ファイル書き込み・編集・コマンド実行)が呼ばれる瞬間をゲートにする。そこで「plan-viewer HTML をまだ書いてないよね?先にそっちを書いて」とブロックする。

3段構えの仕組み

1プランファイル書き込みを検知(PostToolUse:Write)
Claude がプランファイル(plans/ ディレクトリ内の .md ファイル)を書いた直後に自動で「フラグファイル」を作成する。フラグには「どのセッションで」「どのプランを」書いたかを記録する。これが「plan-viewer HTML 未生成」のマーカーになる。
2実装ツールをゲート(PreToolUse:Write|Edit|Bash)
フラグがある間は、plan-viewer 向けのファイル書き込み以外のすべての変更系ツールをブロックする(exit 2)。「まず plan-viewer HTML を書いてから実装して」というメッセージと一緒に止める。plan-viewer の HTML と index.html が両方更新されたらフラグを消す。
3最終安全弁(Stop hook)
Claude が応答を終了しようとした時に、フラグが残っていたらブロックする。万が一ステップ2をすり抜けた場合の保険。

Codex が指摘した重要ポイント

指摘対応
Write だけゲートでは Edit/Bash が素通りWrite|Edit|MultiEdit|Bash を全部ゲート
prompt フックだけでは弱いcommand フック(exit 2)でブロック + prompt は補助
タイムスタンプベースは壊れるsession_id + plan_hash でステート管理
異常終了でフラグが残るTTL(有効期限)で自動クリーンアップ

ポイント

調査の経緯: 最初は「プランモード中に Write が使えないデッドロック」が問題だと思っていた。しかし tmux での検証で「そもそもフックが発火していない」という、より根本的な問題が見つかった。

Codex との合意: Claude(Anthropic)と Codex(OpenAI GPT-5.4)の2つの AI で設計をクロスチェック。「実装の入り口をゲートにする」方針で一致した。

将来的な理想: Claude Code に PlanModeExited フック(Issue #20526)が実装されれば、もっとシンプルな設計にできる。今回の設計はそれまでのワークアラウンド。

見送った案: (A) prompt フックで plan mode の Write 制約を上書き → Codex が「権限レイヤーは上書きできない」と判定。(B) PostToolUse + Stop のみ → 「後追い承認」になり本質的でない。

📝 質問モード — テキストを選択してね
✓ 質問を送信しました