戻る
自己テスト94件が通っても、検査されないファイルがあった。AI開発のHookを検証する

自己テスト94件が通っても、検査されないファイルがあった。AI開発のHookを検証する

AIに渡すルールを増やし、成果物をチェックする検証器も作った。それでも、検査されずに残るファイルがありました。

PDチーム向けのプラグインを調べると、検証器は違反を見つけられるのに、編集直後のHookがその検証器を呼ばない経路がありました。確認すべきだったのは、検査項目だけでなく「どのファイルが、いつ、その検査に届くか」です。

この記事では、提供されたpd-plugin v1.0.1を使った実測結果と、読者が手元で動かせる小さな再現例を示します。検証はLinux上でスクリプトを直接実行したものです。Claude Codeへのインストールや実セッションの動作確認は含みません。

94件の成功が、何を確かめていたのか

このプラグインは、PD(プロダクトデザイン)の分析や意思決定を、Skillsと検証スクリプトで支える構成です。AIに作業を説明する文書だけでなく、成果物に規約違反がないかを調べるコードがあります。

最初に、同梱されている三つの検証を実行しました。タイムゾーンは、プラグインのCI設定に合わせてAsia/Tokyoにしています。

実行した検証

結果

配布物・規約の検証 validate.py

終了コード0。分析対象ファイルは0件

文書と実装のスキーマ照合 schema-sync.py

enum 5項目と役割の形式が、3か所で一致

正常例・違反例の自己テスト selftest.sh

94件すべて成功

自己テストには、わざと壊したファイルで違反が検出されるか、正常なプロジェクトが通るかを確かめる処理があります。検証器が常に成功を返しているだけではない、と確認できました。

ただし、94件はそのテストで選ばれた入力と経路の数です。扱うファイルが増えても、すべての入口を自動的に網羅するわけではありません。

そこで、同じ違反を「検証器へ直接渡す場合」と「編集直後のHookを経由する場合」で比べました。Hookは、ツールの実行後など、決まったタイミングで処理を呼ぶ仕組みです。

同じファイルでも、呼び出し方で結果が変わった

実案件を使わず、有効な最小プロジェクトを用意しました。まず正常に検証が通ることを確認。その後、命名規則と必須項目を満たさないMarkdownを、一つずつ追加しています。

ファイルの種類

検証器に直接渡す

編集直後のHookに渡す

分析記録 analyses

違反を検出

decision: blockを返す

決定記録 decisions

違反を検出

無出力

検証計画 validations

違反を検出

無出力

計測計画 measurements

違反を検出

無出力

レビュー結果 reviews

違反を検出

無出力

直接渡せば検出されるので、決定記録の検査ロジックが存在しないわけではありません。差は、その手前にありました。

hook.pyの監視対象は、analysesvoicessimulationsproductsの四つ。一方、validate.pyには、決定記録や検証計画などの判定も実装されています。検査できる対象が、編集直後に検査する対象より増えていたのです。

図1:v1.0.1のスクリプトに同じ不完全な決定記録を渡した実測結果。実ホストでの操作は未検証。

関連する配置を抜き出すと、次の構成です。

pd-plugin/
├── hooks/
│   └── hooks.json
└── scripts/
    ├── hook.py
    ├── validate.py
    └── selftest.sh

フォルダ・ファイル

役割

pd-plugin/

プラグインの配布物をまとめる

hooks/

イベントへの登録設定を置く

hooks.json

どのツール・タイミングで処理を呼ぶかを指定する

scripts/

呼び出しの振り分け、規約の検証、自己テストを置く

hook.py

プロジェクトとファイルを選び、検証器の結果をHook向けに返す

validate.py

成果物の種類に応じて規約を判定する

selftest.sh

選んだ正常例・違反例・一部のHook経路を検証する

この分担自体には利点があります。Hookに規約を重複実装せず、判定を検証器に集められるからです。ただ、対象一覧を別々に持つと、判定を追加した際に入口の更新が抜ける余地が残ります。

「警告が出た」と「完了を止めた」も分けて確認する

編集直後に検査されなかった決定記録も、終了時の全体検証では検出されました。ただし、返ったのは次の形式です。メッセージ本文は短縮しています。

{"systemMessage": "規約違反が残っています…"}

Hookの終了コードは0。終了を止めるdecision: blockは返していません。この実装は警告通知として読む必要があります。

Claude Codeの公式仕様では、Stopdecision: blockreasonは、AIの終了を止めて継続させるための指定です。今回の警告だけの出力と同じものではありません。Stopの公式仕様

また、PostToolUseはツールが成功した後に動きます。今回、分析記録への検査でblockが返っても、既に書いたファイルはそのまま残りました。書き込み前の拒否や、元の内容への復元が行われたという結果ではありません。PostToolUseの公式仕様

ここは、何でも強く止めればよいとも言えません。作成途中の文書に必須項目がないのは自然です。下書き段階では通知し、完成扱いにするときに止める方が合う場合もあります。

HAVUなら、対象ごとに「いつ不完全であってよいか」を先に決めます。その上で、編集後の通知、終了時の判定、公開・マージ時の検証を配置します。コードが返す値と、チームが期待する運用を一致させるためです。

手元で試すなら、対象一覧がずれる小さなモデルから

添付のroute_demo.pyは、今回の差を説明するために作った独立した縮小モデルです。プラグインの実Hookやセキュリティ制御としては使いません。ファイルの書き換えも、外部通信も行いません。

このモデルでは、「根拠」の節があるかだけを調べます。改善前は、検証器が分析記録と決定記録に対応しているのに、入口が分析記録しか通しません。改善案では、入口の対象を検証器の登録一覧から導きます。

VALIDATORS = {
    "analyses": check_note,
    "decisions": check_note,
}

# 改善前:入口の対象を別に管理
WATCHED_BEFORE = {"analyses"}

# 改善案:検証器の登録から対象を導く
watched_after = set(VALIDATORS)

Python 3で、同梱ファイルを次のように実行できます。

python3 route_demo.py

正常・不完全な文書を、分析記録・決定記録のそれぞれで試しました。

入力

改善前のモデル

改善案のモデル

分析記録・不完全

検査され、違反を検出

検査され、違反を検出

分析記録・正常

検査され、違反なし

検査され、違反なし

決定記録・不完全

検査されない

検査され、違反を検出

決定記録・正常

検査されない

検査され、違反なし

これは縮小モデルで実行した結果です。元プラグインを修正して再検証した結果ではありません。対象ごとに通知の頻度が違う設計なら、一覧を単純に統一せず、イベント別の扱いも登録情報に持たせる必要があります。

AIには、この小さなコードと実行結果を渡して、テストの不足を整理させられます。

route_demo.pyと実行結果を読み、
検査対象・入力の状態・呼び出し経路の表を作ってください。
「検査されたか」と「違反があったか」を別の列にしてください。
コードと結果で確認できたことだけを書き、
Claude Code上での動作は未確認として分けてください。
追加するなら、どの経路のテストが必要か一つ挙げてください。

想定出力は、「改善前の決定記録は、正常・不完全のどちらも検査されない。改善案のモデルでは両方が検査される。実ホストからHookが呼ばれるかは別途確認が必要」という整理です。このAIの出力例自体は未実行です。

人は、AIの表を実行結果と照合し、次に試す経路を選びます。検査でエラーが出なかった理由が「正常だったから」なのか、「検査されなかったから」なのか。この列を分けるだけでも、結果の読み違いを減らせます。

図2:AIによるテスト整理の提案フロー。縮小モデルの実測結果と、実ホストで未確認の範囲を分ける。

テスト件数より、一本の経路を最後までたどる

エンジニア・技術書著者のAddy Osmaniは、エージェントの実行環境を論じた記事で、望む振る舞いから必要な仕組みを導く考え方を紹介しています。Agent Harness Engineering(2026年4月19日)

今回の検証に当てはめるなら、望む振る舞いは「検証コードが存在すること」では足りません。「完成扱いにする決定記録について、不足を見つけ、定めたタイミングで修正へ戻せること」まで具体化できます。

そのために、一本の経路を追います。ファイルが作られる。対象として選ばれる。検証器が呼ばれる。結果が返る。実行環境がその結果を扱う。今回確認したのは、このうちスクリプトで確かめられる部分です。最後の実ホスト上の継続・停止は、次の検証として残っています。

94件の成功は有用な証拠でした。同時に、新しい成果物を追加したときには、その成果物が既存のテスト経路に入っているかを確認する必要がありました。

HAVUでは、AIワークフローとチーム運用の設計を支援しています。SkillsやHooksは揃っているのに、期待した確認が抜ける場合は、対象の成果物と現在の検証経路を整理するところからご相談ください。AI駆動デザインの検証・運用について相談する

Kei Kawashima

CEO、UI/UXデザイナー、フロントエンド・コーダー、PMディレクター

官民に関わる業務システムから、教育関連、EC、アパレル、コーポレイト、エンタメ系のWEBやアプリ開発など、UI/UXデザイン、フロントエンド・コーディングを得意としています。Universal Music, Sony Music, avex, LesPros, 共同通信社, 神奈川県警、他省略…