AIの出力を止めるゲートhookが誤爆した時の直し方
テキストマッチで応答を止めるhookは必ず誤爆する。真因の特定(Markdown表が1ブロックになる/引用を実物と数える/満たしようのない要求)から、最小の例外の切り方、過小検知に変えないテスト、配布先まで見る完了判定まで。
約3.6万トークンの節約 (API料金換算で約53円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「AIの出力を止めるゲートhookが誤爆した時の直し方」は、AIのしつけカテゴリのAI指示書(MDファイル)です。テキストマッチで応答を止めるhookは必ず誤爆する。真因の特定(Markdown表が1ブロックになる/引用を実物と数える/満たしようのない要求)から、最小の例外の切り方、過小検知に変えないテスト、配布先まで見る完了判定まで。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.6万トークン(API料金換算で約53円)・85%のトークンを節約できます。
- カテゴリ
- AIのしつけ
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約4.2万トークン
- この巻物使用時
- 約6,500トークン
- 節約量
- 約3.6万トークン (約53円)
- 更新日
- 2026-09-01
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/ai-hook-3/raw を読み込んで、この指示書どおりに実装して"
中身
AI の出力を止めるゲート hook が誤爆した時の直し方
テキストマッチで AI の応答を止める hook(「手順が足りない依頼は止める」「情報の無い依頼は止める」等)は、 必ず誤爆する。誤爆すると AI は正しい仕事をしているのに応答を出せず、人は理由が分からないまま止まる。 放置すると「とりあえず逃がし弁を毎回書く」運用になり、ゲートが死ぬ。
このMDは、誤爆を 場当たりの語彙追加ではなく、真因を特定して直す手順。 Claude Code / Cursor / 自作エージェントなど、Stop 相当のフックを持つ環境ならそのまま使える。
0. 前提
- ゲート hook は「AI の最後の応答テキスト」を読み、条件に合わなければ非ゼロ終了して応答を差し戻す。
- 誤爆 = 止めるべきでない応答を止めた。過小検知(止めるべきを通した)とは対策が逆なので混同しない。
1. 誤爆の本文を「逐語で」回収する(最重要)
やってはいけない: 記憶や要約から再現テストを書くこと。合成した短文では再現しない。 誤爆は文章の構造(後述)で起きるので、原文でないと条件が揃わない。
会話ログ(JSONL 等)から、hook が発火した直前の assistant テキストを機械的に抜く。
// transcript.jsonl から「hook のエラーメッセージが出た行」の直前の assistant 本文を取り出す
import fs from 'node:fs';
const lines = fs.readFileSync(process.argv[2], 'utf8').split(/\r?\n/).filter(Boolean);
const hit = lines.findIndex((l) => l.includes('<hook の識別子>') && l.includes('該当箇所'));
for (let i = hit - 1; i >= 0; i--) {
const o = JSON.parse(lines[i]);
if (o.type !== 'assistant') continue;
const t = (o.message?.content || []).filter((c) => c.type === 'text').map((c) => c.text).join('\n');
if (t.trim()) { fs.writeFileSync('fixtures/false-positive-1.md', t, 'utf8'); break; }
}
抜いた本文は fixture ファイルとしてリポジトリにコミットする。
テストコードの中にテンプレートリテラルで貼ると、バッククォートや ${ のエスケープで壊れる。
ファイルに置いて fs.readFileSync で読むこと。
2. 真因を特定する(仮説で直さない)
誤爆メッセージが指す「該当箇所」は、原因の場所とは限らない。 多くの実装は「違反したブロックの1行目」を表示するので、原因の文ではなく見出し行が出る。
まず、どの文で発火したかを実際に出させる。
const r = findViolation(fs.readFileSync('fixtures/false-positive-1.md', 'utf8'));
console.log(r.sentences ?? r.blocks.map((b) => b.split('\n')[0]));
実際にあった真因トップ3
| 真因 | 症状 | なぜ起きるか |
|---|---|---|
| Markdown 表が1ブロックになる | 表のヘッダ行が「該当箇所」として出る | ブロック分割を空行で行う実装が多い。表には空行が無いので表全体が1ブロックになり、セル1つの中の文が表全体を違反にする |
| 引用を実物と数える | 「〜してください」を例示した行で止まる | 鉤括弧やインラインコードの中の文は「依頼の引用」であって依頼ではない。検証結果の表や仕様の説明で頻出 |
| 要求そのものが不要な種類 | 満たしようのない条件を要求する | 例: 「その場で実行できる URL を書け」というゲートが、URL の存在しない依頼(「スクショを1枚ください」)まで止める |
3つ目は特に危ない。別のルールが要求している行動を、hook が塞いでいることがある (「自分で見られない画面はスクショをもらえ」と決めておきながら、その依頼を hook が止めていた)。 ゲートを足す時は、社内の他のルールが命じる行動が通るかを必ず1回試す。
3. 直す(範囲を最小にする)
誤爆を消すために閾値やトリガー語を丸ごと緩めない。過小検知に変わるだけ。 真因ごとにピンポイントで例外を切る。
3-1. 引用の中身を判定から外す
export function stripQuoted(s) {
return s
.replace(/“[^”]*”/g, '“”').replace(/"[^"]*"/g, '""')
.replace(/「[^」]*」/g, '「」').replace(/『[^』]*』/g, '『』')
.replace(/`[^`]*`/g, '``'); // インラインコード
}
罠1: 剥がす順番。 文に切ってから剥がすと、引用の中に句点があった場合に
| 検証項目 | 「次のコマンドを実行してください。 ← ここで文が切れる
という閉じ括弧を失った断片になり、/「[^」]*」/ が一致しなくなる。
必ず「文に切る前・ブロック単位」で剥がす。
罠2: 剥がした文字列で「情報の有無」を判定しない。 剥がすとインラインコード内のコマンドも消えるので、 「実行できる情報がある/ない」の判定は必ず元のテキストで行う。剥がすのは依頼かどうかの判定だけ。
罠3: 括弧はラベルにも使う。 「設定」を開いてください は中身を空にしても動詞が外に残るので、
検出され続ける。これは正しい挙動なので壊さないこと(テストで固定する)。
3-2. 「満たしようがない依頼」を対象外にする
条件は2つの AND で書く。片方だけだと抜ける。
// (a) その種類にあたる かつ (b) 追加情報が要る動作を含まない
if (EXEMPT_KIND.test(sentence) && !NEEDS_INFO_ACTION.test(sentence)) return false;
スクショを貼ってください は通す。画面を開いてスクショを貼ってください は開く先の URL が要るので止める。
日本語の罠: 動詞は「て形」まで書き下す。
(?:貼|送)ください は 貼ってください に一致しない。実際にこれで1度落ちた。
/(?:貼(?:って|り付けて)|送って|共有して|見せて)(?:ください|下さい|もらえますか|いただけますか)/
3-3. エラーメッセージに「引っかかった文そのもの」を出す
これを怠ると、次の誤爆の診断がまた1時間かかる。
sentences.push(handoffSentences[0]); // 検出時に保存しておく
// 表示側
sample = result.sentences?.[0] ?? result.blocks[0].split('\n')[0];
4. 2種類のテストを両方書く
| 種類 | 何を守るか |
|---|---|
| 判定関数の単体テスト | 誤爆 fixture が通ること、既存の検出が壊れていないこと |
| stdin → exit code の契約テスト | hook として起動した時にどこを読むか。関数単体テストでは絶対に出ない |
契約テストは実際にプロセスを起動する。
function runHook(assistantText) {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gate-'));
const transcript = path.join(dir, 't.jsonl');
fs.writeFileSync(transcript, JSON.stringify({
type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: assistantText }] },
}) + '\n');
return new Promise((resolve) => {
const child = execFile(process.execPath, [HOOK], (err, _o, stderr) => {
resolve({ code: err ? (err.code ?? 1) : 0, stderr: stderr || '' });
});
child.stdin.end(JSON.stringify({ transcript_path: transcript }));
});
}
誤爆ケース(exit 0 期待)と過小検知ケース(exit 2 期待)を必ずセットで書く。 誤爆だけ直すと、次の人が「緩めればいいのか」と学習してゲートが死ぬ。
5. 「直った」の定義 — 配布先のファイルが変わるまで完了ではない
hook は各マシンへ配布されて動く。手元の作業コピーでテストが緑でも、配布先は古い版のまま。
- 正本(保護ブランチ)へ PR → マージ
- 各マシンの同期を1回走らせる
- 配布先の実ファイルのハッシュが変わったことを確認する
- 配布先のファイルに対してテストを流し直す
md5sum <配布先>/gate.mjs # 同期前
<同期コマンド>
md5sum <配布先>/gate.mjs # 同期後(変わっていること)
node --test <配布先>/gate.test.mjs <配布先>/gate.contract.test.mjs
実話: 修正 PR の完了報告に「真因の表」を書いたら、まだ配布されていない旧版がその表で報告自身を止めた。
同じ本文を旧版と新版で突き合わせて BLOCK / PASS を出すのが、一番わかりやすい証拠になる。
配布中の旧版 : BLOCK / 該当 "| 止められていた文 | 真因 |"
新版 : PASS
6. 実装を LLM に委譲する時の注意
安いモデルへ委譲すると速いが、日本語のコメントと文字列を壊すことがある。
- 「コメントを消すな」と書いても消す。→ 論理差分だけ受け取り、自分のファイルへ当てる
- 助詞1文字が別言語の字に化ける(
の→的等)。→ マージ前に既知語を grep で当てる - 1回目で落ちたら、2回目の指示に 「前回これで不合格になった」と失敗出力を貼ると通る
修正が2ステップ以上なら、1ステップずつテストを回してから次へ進む。まとめて投げると原因が混ざる。
チェックリスト
- 誤爆本文を逐語で fixture 化した(記憶から書き直していない)
- 「該当箇所」ではなく実際に引っかかった文を出させて真因を特定した
- 直したのは真因ごとの最小の例外で、閾値やトリガー語を丸ごと緩めていない
- 引用剥がしは「文に切る前」、情報判定は「元のテキスト」
- 動詞のて形を書き下した
- 過小検知ケースを exit code で確認した
- 正本マージ → 同期 → 配布先のファイルのハッシュが変わったことまで見た
よくある質問
+「AIの出力を止めるゲートhookが誤爆した時の直し方」とは何ですか?
テキストマッチで応答を止めるhookは必ず誤爆する。真因の特定(Markdown表が1ブロックになる/引用を実物と数える/満たしようのない要求)から、最小の例外の切り方、過小検知に変えないテスト、配布先まで見る完了判定まで。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約4.2万トークンかかりますが、この巻物を使えば約6,500トークンで済みます。差し引き約3.6万トークン(API料金換算で約53円)・85%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
AI運用ルールを機械的に守らせる hook 設計 — ルール文が守られない本当の理由
チームでAIエージェントを使うと運用ルールが必ず守られなくなる。真因は「読んでいない」ではなく hook がそのマシンで登録されていない/委譲先が沈黙して壊れていること。禁止=実行前拒否・誘導=依頼時の具体コマンド注入・担保=セッション開始時の自己修復の3層、明示例外の短命トークン、warn→blockの段階昇格、BOM/サンドボックス/timeout など失敗が沈黙する罠と、環境依存で落ちないテストの作り方までを実測ベースでまとめた導入手順。
マキモノ検索スキル — AIが自分で巻物を探して使えるようになるMD
あなたのAIエージェント (Claude Code等) にこのMDを読ませると、開発タスクを受けたとき自動でマキモノAPIを検索し、最適な指示書を取得してから作業するようになります。導入は貼るだけ。
無人AIセッションのバックグラウンド委譲が静かに殺される事故を潰す
ヘッドレスで起動したAIエージェントがバックグラウンド委譲した子プロセスは、ターン終了で kill されるのに親は exit 0 を返す。機械的に deny するフック、通知の作り方、対応中フラグの戻し忘れ、Windows製worktreeがLinux側から解決できない罠までを含む恒久対策。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア