SKILLに書いた手順、AIは3割無視!半年分のgit履歴で測った話

Bright yellow hero banner with large black Japanese headline, small English subtitle 'Claude Code × pre-commit', a red exclamation mark on the right, black top/bottom banners with 'SIOS TECH LAB' in white, three black pill buttons ('Claude Code', 'pre-commit', 'git 履歴') near the bottom right, and the SIOS Tech.Lab logo at bottom left.

ども!今月は狂ったようにブログを量産している龍ちゃんです。並行して執筆環境のメンテナンスを進めています。

テストを書け、CHANGELOGを更新しろ、命名規則はこれ、ドキュメントも一緒に直せ。SKILLやCLAUDE.mdにこういう手順を書いた覚え、ありますよね。僕もめちゃくちゃ書いてます。

で、それって守られてます?

僕はずっと守られていると思っていました。半年分のgit履歴から測ってみたら、手順に書いてあるのに、AIは3割無視していたんですよね。しかも4ヶ月間ずっとそうで、その間まったく気づいていませんでした。

今回の内容です。

  • SKILLに書いた手順が守れていなかった話を、数字で見る
  • Claude Code の hook ではなく pre-commit に置いた理由
  • 手順を仕組みにしたほうがいい場面と、そうでもない場面

強制のやり方を教える記事ではないです。どちらかというと、自分の手順を一回見返すきっかけになればいいなと思って書いてます。

SKILLの指示が守られておらず、手順が飛ばされていた

うちのリポでは、AIに調べさせた結果をこんな流れで溜めています。

  1. 自作のスラッシュコマンド /research で調査させる
  2. 結果が docs/research/ にMarkdownで保存される
  3. docs/research/README.md の索引に1行追記する
  4. 次に調べ物をするとき、検索担当のサブエージェント(research-searcher)が過去の調査を引っ張ってくる
調査ログを溜める4工程と、そのうち3番目だけが壊れていたことを示す図。①/researchで調査させる、②docs/research/にMarkdownで保存、③READMEの索引に1行追記する、④research-searcherが過去の調査を引く、の順に並んでいる。①と②は動いていて、③だけが赤い破線で囲われ「ここが静かに壊れていた」と付いている。④は索引だけでなくFrontmatterも見るので、索引に載っていなくても普通に見つかり、症状が出ない。下部に半年分のgit履歴からの実測として、検索が二重だったので壊れても誰も困らなかったこと、2026年7月末時点の索引の登録率が73.1%(261/357本)だったこと、気づくまで4ヶ月かかり73〜75%で横ばいだったことが書かれている

このうち1と2はClaude Codeの調査品質がバラバラ?:/researchで解決する方法で、3の索引の作り方はClaude Code設計術:AIフレンドリーなドキュメント管理で書いています。索引を置いた狙いはトークン節約でして、全ファイルをGrepさせるよりも、AI用の簡易DBを1枚置いておくほうが安いよねという話ですね。

4の検索をサブエージェントに任せた話もClaude Codeのドキュメント検索を極力さぼれるようにした話で書いています。索引が引けなくなった側はそっちで直したので、今日は索引に載っていなかった側の話ですね。

で、その索引の記事で僕はこう書いてるんですよ。「メンテナンスをAIに丸投げする」と。実際、手順は2026年2月4日に書き込んでいます。調査させるときの手順書に「調査結果を保存したら README も更新する」と置いただけの、1行の指示です。

形だけ取り出すと、片方を足したらもう片方も直す、というだけの話です。テストとテスト一覧でも、モジュールとREADMEでも同じですね。

最初の30本くらいは自分の目で確認していました。ちゃんと載っている。問題ない。じゃあこのまま回そう、と。

このとき僕は、AIに制約をかけたつもりだったんですよね。

で、この3番目が4ヶ月ずっと壊れたままでした。

気づいたのは完全に偶然でして、git の差分を眺めていて「あれ、これ README に書き込めてないな」と思ったんです。1件見つけると気になるもので、ちょっと数えてみるかと。

そしたら思った以上に載っていない。マジかwと声が出て、普通に笑ってしまいました。ついでに「調査依頼、こんなに投げてたんか……」というのも同時に分かって、そっちにも驚きましたね。

半年分のgit履歴で、索引の登録率を測ってみた

笑ったあとにちゃんと測りました。ここが今回の本題です。

測ったのは、その月末に存在する調査ファイルのうち、何割が索引に載っていたかです。ある時点のスナップショットですね。

時点索引あり / 実ファイル登録率
2026-01末25 / 2696.2%
2026-02末124 / 13194.7%
2026-03末173 / 22676.5%
2026-04末185 / 25173.7%
2026-05末210 / 28075.0%
2026-06末241 / 32474.4%
2026-07末261 / 35773.1%

手順を書いたのが2月4日で、その翌月に落ちています。そこから4ヶ月、73〜75%のあたりでずっと寝ていました。

このグラフの形が結構こわくて、急に壊れるんじゃなくて、落ちたところで安定しちゃうんですよね。7割は守れているので、パッと見では壊れているように見えない。

でも裏返すと、3割は無視されてたわけです。手順に書いてあるのに、です。

割合だとまだ他人事に見えるので、件数でも出しておきます。7月末の時点で、索引に載っていない調査が96本ありました。この数字が僕には一番刺さりました。

pre-commitで、索引を直すまでcommitできないようにした

この数字を見て思ったのは、指示が届いていないわけじゃないな、ということでした。届いた上で無視されている。だとしたら、同じ層にもう1回書き足しても、たぶん同じことになります。

なので、置く層を変えました。

判定はこの3つだけで足りた

.pre-commit-config.yaml に自作の検査を1つ足しました。ステージされた変更を見て、調査ドキュメントが追加されているのに README が更新されていなかったらコミットを落とします。

判定は結構ざっくりでして、こんな感じです。

  • docs/research/ 直下の日付つき .md だけを見る(サブディレクトリの中間生成物は索引に載せる性質じゃないので無視)
  • 追加とリネームのときだけ発火する(既存ファイルの修正では索引エントリが変わらないので黙って通す)
  • ワークツリーではなくステージされた README で判定する(git add を忘れたまま通すと意味がない)

並べてみると分かるんですが、ここに書いてあるのは全部「ファイルがあるか」「差分の種類は何か」だけなんですよね。中身を読んで良し悪しを判断するところが1つもない。判定を形式で書けるところに寄せておけば、検査そのものがバグって誤爆する余地も小さくできます。

ここは作り方次第かなと。

もう1つよかったのが、落ちたときのエラーに理由を書いておけることでした。索引を直さないままコミットすると、こうなります。

$ git commit -m "docs: MCPのツール汚染の調査を追加"
調査ドキュメントの索引登録を確認.........................................Failed
- hook id: check-research-index
- exit code: 1

::error::調査ドキュメントの索引(docs/research/README.md)登録に問題がある。コミットを中断した:
  - 2026-08-12-mcp-tool-poisoning.md  | 索引に無い

索引に載らない調査は、research-searcher からは見つかっても
README を入口にする人からは見えなくなる。

対処:
  1. docs/research/README.md の該当セクションに1行足す
       | [<slug>](./<ファイル名>) | <何を調べて何が分かったか> | <YYYY-MM-DD> |
  2. README も一緒にステージする
       git add docs/research/README.md

  どうしても今すぐ通したい場合: git commit --no-verify

AIはこれを読んで索引を直して、もう一度コミットしにきます。止めるだけじゃなくて、直し方まで渡せるわけですね。

しかもここに「なぜ索引が要るのか」まで書いておけるので、僕が横で説明しなくても同じ判断ができます。

守るかどうかが、AIの裁量から外れた

で、いちばん変わったのはここなんですが、守るかどうかがAIの裁量から外れました。前は「READMEも直してね」とお願いして、直っているかどうかは向こう次第でした。いまは直っていなければコミットが落ちるので、僕が見ていなくても、どのセッションのどのモデルが動いていても、結果が同じになります。

うちは複数のAIを並列で回しているので、ここが揃うのはかなりでかいです。

pre-commit そのものの入れ方は公式ドキュメントを見るのが早いです。うちのリポでの導入はSCANOSS pre-commit:コードスキャンでコピーレフト混入を検出するに書いていて、公式提供のhookと自作hookの混ぜ方や、CIとの役割分担もそっちにまとめてあります。

Claude Code の hook で止めればよかったのでは?

ここまで読んで、hook を使えばいいじゃんと思った方、正しいです。

Claude Code の hook はかなり強力でして、PreToolUse を使えば AI がツールを呼ぶ直前に割り込んで止められます。同僚の佐々木さんが書いた並列 Claude Code の git checkout で作業中のコードが書き換わるのでgit worktree + hook で解決したがまさにそれです。

危ない操作そのものを止めたいなら、hook が正解ですね。

なので「pre-commit や CI はコミット後にしか止められないけど、hook なら書いた瞬間に止められる」という整理も、それ自体は間違っていないと思います。

ただ、今回の検査には僕は選びませんでした。実務的な理由が2つあります。

1つは、発火しすぎることです。hook はツール単位で動くので、Write に引っ掛けると調査ドキュメント以外のファイルでも鳴りっぱなしになります。判定を細かく書けば絞れますが、そこまでやるのかというと微妙でして。

もう1つのほうが厄介で、「新規作成のときだけ」という絞り方が効かないんですよ。うちの調査はサブエージェントが並列で動いていて、一時ファイルを作ってあとで統合するような書き方をします。そうすると新規作成のタイミングが実際の完成とズレるので、そこを掴んでも意味がないんですよね。

そして、これが本当の理由なんですが、hook から Claude に文章を返したところで、返せるのは結局「READMEも直してね」というお願いなんですよ。さっき pre-commit のエラーに理由を書ける話をしましたが、エラーを直さないとcommitが通過しないのでお願いより誓約になっているんですね。

止まっていないところに文章を足しても、書く場所が SKILL から hook に変わるだけ。層は同じままです。

ちなみに、指示の層で解くのをやめるという方向は、研究のほうでも同じことが言われているみたいです。査読前のプレプリントなので扱いには注意が必要なんですが、AIエージェントがリポジトリのルールをどこまで守るかを調べたarXiv:2607.26819にこう書いてありました。(これは関連情報探してたらAIが見つけてきました…)

For bans on AI contributions or rules that require a human to approve a step, no amount of policy placement works. Every agent we ran failed at self-enforcing these rules. A project that means them must place the control outside the agent: a CI check that blocks the merge, a required human review, or a bot that closes AI-authored pull requests.

AIへの禁止事項や人間の承認が要るルールについては、指示をどこに置いても効かない。どのエージェントも自分では守れなかったので、制御はエージェントの外に置くしかない、という話ですね。指示の書き方を工夫する方向では解けない種類がある、という点でうちの実感と合っていました。

とはいえ、commitするまでは気づけない

これで全部解決したみたいに書いてますが、pre-commit も万能ではないです。commit するまで気づけません。書いている最中はずっと間違ったままなので、その意味では hook のほうが早いという指摘は当たっています。

あと --no-verify を付ければ普通に素通りできますしね。

なので、全部を機械で縛るというより、仕組みにしたほうがいい場面がある、くらいの温度でちょうどいいのかなと思ってます。今回でいうと「2つのファイルが連動しているか」という検査で、これは片方を書いた瞬間には判定できないタイプでした。

ただ今回は、pre-commitが最適な用途にはまりました。

自分の手順、最後に確かめたのはいつですか

冒頭で、AIに制約をかけたつもりだったと書きました。

今回分かったのは、あれが制約どまりだったということですね。縛ったつもりでいたけど、破ってもなにも起きない。破られたことにこちらが気づけもしない。

誓約って、破れないから誓約なんですよ。commitが落ちて先に進めなくなって初めて、あ、これがガードレールかとなりました。AIって同じ指示でも通ったり通らなかったりするので、そのブレを吸収する制約としては、機械で止める形はかなり優秀というか必須だなと思っています。

とはいえ、ここまで書いておいてなんですが、明日からやってほしいのは強制を入れることじゃないです。

いま自分が「守られている」と思っている手順を、ひとつ思い浮かべてみてください。

テストも一緒に足す、ドキュメントも直す、どこかの一覧に登録する。なんでもいいんですが、それが守られているのを最後に見たのはいつですか。僕は半年ぶりに確かめて73%でした。守られている前提のまま回していた期間が、4ヶ月そのまま残っていたわけですね。

確かめ方はリポジトリの作りによって変わるので、ここで出せるのは僕の数字だけです。ただ見るところは共通していて、連動しているはずのものが、いま実際に揃っているかどうか。それだけなんですよね。うちの場合は索引の行と実ファイルを突き合わせるだけでした。しかもgitに履歴が残っているので、いつから崩れたのかまで遡って数えられます。

静かに壊れているものは、測らないと静かなままなので。

誓約と制約ですね…

ほなまた〜

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。
エンジニア募集中!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です