メインコンテンツへスキップ

第9回 自己検証を組み込む(hooksで検証を強制する)

Claudeが自分でテスト・lint・型チェックを確認してから見せる状態を作る。CLAUDE.mdの『お願い』と、hooksの『強制』の違い。

  • レッスン 10 / 22
  • 9分

このレッスンで

終わる頃には、次ができるようになります

  • CLAUDE.mdのお願いとhooksの強制の違いを説明できる
  • PostToolUseなどのhookで終了コード0と2を使い分けられる
  • サブエージェントレビューの指摘をcorrectnessと要件基準で絞り込める
成果物が必ず検証ゲートを通る仕組みの図
検証をお願いではなく、通過条件にする。

疲れていても、急いでいても、うっかりしていても、確実に検証が走る。そういう状態を、今回作る。

第8回で、2体目を立てた。worktreeで作業ツリーを分け、担当ファイルを割り振れば、2体が同じファイルを取り合う事故は防げる。だが体数が増えるほど、別の問題が出てくる。1体ずつ「テストは回した?型チェックは通った?」と聞いて回るのは、2体まではできても、5体・10体になると破綻する。

第7回で検証ループそのものは作った。テスト・ビルド・実行結果を確かめる仕組みは、もう手元にある。今回の課題は少し違う。その仕組みを、Claudeが自分から律儀に使うとは限らないという現実に、どう対処するかだ。


CLAUDE.mdは「お願い」、hookは「強制」

CLAUDE.mdに「必ずテストを実行してから報告してください」と書いておけば、たいていはその通りに動く。だが「たいてい」で止まる。

VoicesDOCUMENTATION

“Claude treats CLAUDE.md files and auto memory as context, not enforced configuration.”

筆者訳

ClaudeはCLAUDE.mdファイルや自動メモリを、強制される設定としてではなく、あくまで文脈として扱う。

Claude Code公式ドキュメントMemorycode.claude.com/docscode.claude.com/docs/en/memory.md

「文脈であって、強制設定ではない」。この一文が今回の出発点になる。CLAUDE.mdは、有能な同僚への申し送りメモに近い。読んでもらえることが前提で、絶対に守られる保証はない。

コンテキストが長くなったとき、途中で圧縮されたとき、あるいは単純に見落としたとき。CLAUDE.mdの「お願い」は、条件次第で読み飛ばされる。確実に守らせたいルールは、hookに移す。


hooksの仕組み:いつ・何を実行するか

hookは、ツール呼び出しやセッションの節目で決定的に実行されるコマンドだ。Claudeの判断を経由しない。だから守られなかった、が起きない。

PreToolUse

ツールを実行する直前。危険な操作をここで止められる

PostToolUse

ツール実行の直後。編集後にlint・型チェックを自動で走らせる

Stop

Claudeが応答を終えようとした瞬間。検証が済んでいなければ続行させる

SessionStart

セッション開始時。前提となる環境確認をここで固定する

SubagentStop

サブエージェントが終わろうとした瞬間。個々の担当分の検証に使える

主なhookイベント

hookの戻り値には意味がある。終了コード2はブロッキングエラー、0は成功。ここを取り違えると、意図せず処理を止め続けたり、逆に何もチェックしていないのに素通りさせたりする。

SourceDOCUMENTATION
Hooks:決定的に実行されるコマンド

イベントの種類、終了コードの扱い、設定ファイルでの書き方をまとめた公式ドキュメント。最初の1本を書く前に一読する価値がある。

Webcode.claude.com/docs
code.claude.com/docs/en/hooks.md

自己検証ループを作る:「見えている」と「動くと分かっている」

第7回で作った検証ループを、hookで自動起動に変える。Editツールが走ったら型チェックを、コミット前にはテストを。人間が「やって」と頼まなくても、実行された事実だけが残る。

VoicesBLOG / NEWSLETTER

“Testing turns a skill that seems to work into one you know works.”

筆者訳

テストをすることで、『動いているように見える』スキルが、『動くと分かっている』スキルに変わる。

Anthropic公式ブログSkills開発チームclaude.com/blog2026年3月3日claude.com/blog/improving-skill-creator-test-measure-and-refine-agent-skills

この指摘はもともとSkillsの品質について語られたものだが、自己検証全般に当てはまる。「動いているように見える」と「動くと分かっている」の間には、実行して確認したという1手順の差しかない。hooksは、その1手順を省略できなくする仕組みだ。

PostToolUseフックが自動でテストを走らせる例
$(Editツール実行後、hookが自動起動)npm test

FAIL test/upload.spec.ts(1 failing)。Claudeへの報告はブロックされました。

hookが強制するのは、テストやlintのような機械的な合否判定だ。もう一段別の視点からの確認を足すなら、作業を完了扱いにする前に、フレッシュなコンテキストのサブエージェントにdiffをレビューさせ、見落としを報告させるとよい。組み込みの /code-review スキルは、この型で動く。

VoicesDOCUMENTATION

“Before treating a task as done, have a subagent review the diff in a fresh context and report gaps.”

筆者訳

完了扱いにする前に、フレッシュなコンテキストのサブエージェントにdiffをレビューさせ、見落としを報告させる。

Claude Code公式ドキュメントBest Practicescode.claude.com/docscode.claude.com/docs/en/best-practices.md

実装したセッションのまま見直すと、書いた本人としての思い込みが残りやすい。コンテキストを切り替えたサブエージェントに見せることで、その思い込みを外して読める。

ただし、このレビューには注意が要る。欠陥を探せと頼まれたレビュアーは、仕事が健全なときでも、たいてい何かしら見つけてくる。

VoicesDOCUMENTATION

“A reviewer prompted to find gaps will usually report some, even when the work is sound, because that is what it was asked to do. Chasing every finding leads to over-engineering... Tell the reviewer to flag only gaps that affect correctness or the stated requirements, and treat the rest as optional.”

筆者訳

欠陥を探すよう頼まれたレビュアーは、それが役目である以上、仕事が健全なときでもたいてい何かを報告してくる。指摘を全部追いかければ、過剰な作り込みに向かう。correctness(正しく動くか)と明示された要件に影響する欠陥だけを拾うようレビュアーに伝え、それ以外は任意項目として扱う。

Claude Code公式ドキュメントBest Practicescode.claude.com/docscode.claude.com/docs/en/best-practices.md

見つかった指摘を全部拾おうとしないこと。correctnessと要件に効く指摘だけを採用し、残りは任意項目として扱う、という線引きを先にレビュアーへ伝えておく。


人間とAIに同じ品質バーを適用する

経験や肩書きに関係なく、同じ確認を通す。これが事故を減らす発想の核だ。

離陸前のパイロットのチェックリストを思い出してほしい。操縦士が新人でもベテランでも、チェックリストの項目は同じだけ読み上げる。

視点

チェックリストは信頼の代わりではない

ベテランのほうが間違えないから確認を省いていい、とはならない。むしろ慣れているほど確認を飛ばしたくなるからこそ、チェックリストは全員に等しく適用される。

hooksも同じだ。Claudeが優秀になったから確認は要らない、という理屈は成立しない。確認の有無は、能力の高さと関係のない話として設計する。

良いhook設計
  • 編集直後に型チェックを自動実行
  • 失敗したら報告そのものをブロックする
  • 何を確認したか、ログに残す
悪いhook設計
  • チェックを「参考情報」として表示するだけで止めない
  • 失敗しても終了コードを返さない
  • 範囲が広すぎて、正常な操作まで頻繁にブロックする

よくある誤解と罠

  • hookを入れれば検証ループは自動で万全になるという誤解。hookは「強制する手段」であって、何をチェックするかの中身は第7回の検証ループ設計がそのまま生きる
  • 終了コードの意味を取り違える。0と2を逆に書いてしまい、通ってほしい操作を止め続けたり、止めたい操作を素通りさせたりする
  • CLAUDE.mdに書けば十分だと思い込む。確実に守らせたいルールと、文脈として伝えれば足りるルールを、同じ場所に混ぜて書いてしまう
  • サブエージェントによるレビューの指摘は、全部拾わなければならないという思い込み。欠陥を探すよう頼まれたレビュアーは、仕事が健全でも何かしら見つけてくる。correctnessと要件に影響する指摘だけを拾い、残りは任意として扱う

セルフチェック

1. 公式ドキュメントが述べる、CLAUDE.mdの扱われ方は?

2. hookの終了コードについて正しいのは?

3. 「人間とAIに同じ品質バーを適用する」とはどういう考え方か?

4. 組み込みの `/code-review` のようなサブエージェントレビューについて、公式ドキュメントが注意を促しているのは?

明日のアクション

自分のリポジトリに、Editツール実行後に型チェックまたはlintを自動で走らせるPostToolUseフックを1つ設計してください。

実際に設定ファイルへ書き込む前に、まず紙かメモで「いつ・何を・失敗したらどうするか」を1行ずつ書き出すこと。終了コードの扱い(0/2)を必ず明記してください。

次は、体数が増えるほど重くなる承認プロンプトそのものを扱う。第10回、許可を設計する。

このレッスンは役に立ちましたか?