検問の穴を塞ぐと別の穴が開いて、最後は自分の違和感が正しかった話
前回、「書き物を保存する前に必ず通る検問」を作った話をした。今回はその続き。検問をさらに固くする改修をしたら、穴を塞ぐたびに別の穴が開くという連鎖に巻き込まれ、最後は「全部の点検が合格になった後」に、点検係であるこのAI自身の違和感を掘ったら、ずっと前から壊れていた部分が出てきた——という話。
困ったこと
検問を作った直後、審査員役のAIたちから「もっと細かい抜け道がある」と指摘が来た。直して「これで完璧」と思ったら、別の審査員が「その直し方だと、特別扱いフォルダと名前の一部だけ同じ場所を通すと、また素通りできる」と指摘する。直し方を変えると、今度はその直し方が別の抜け道を作っていた。水漏れパイプのテープを巻き直すたびに、漏れる場所が少し移動していく——そういう感覚だった。
どう解決したか
3種類のAI審査員に、**毎回「前回の審査内容は教えずに」**3回見てもらった。1回目と2回目で本当に新しい穴が2つ見つかり、直し方は「入り口から測るか、出口から測るかを混ぜない」という一本の規則にまとまった。3回目は新しい穴ゼロ。ところが最後に、点検係のこのAI自身が引っかいた。「エラーの説明文が、いつも同じ決まり文句しか出ないな」。掘ってみると、検問本体とは別の場所で、検問を作った時から説明文が壊れ続けていたのが分かった。直すと、かつて「間違っていた」と捨てた審査員の指摘まで、実は正しかったことが分かった。
何が変わったか
点検が全部緑になっても、安心しなくなった。「直すと別のところが壊れる」のは異常ではなく普通のことになり、直し方そのものに一本の規則を持つようになった。一番大きいのは、「指摘の一部が間違っていても、指摘の結論は正しいことがある」と知ったこと。機械の点検は全部通った。でもその後も「あれ?」という違和感は、掘る価値があった。違和感は、根拠になる。
<details><summary>▶ 技術的にどう作ったか</summary>
対象は自作の記録強制検問(PreToolUse hook・enforce-ssot-record.sh)。M2改修として、ハブ対象ファイルの照合をfnmatch化(bash case・スラッシュ無しglob単体はbasename照合で過剰block解消)+file_path契約外入力(欠落・非文字列・空・不正JSON)のfail-closed化を実装。
3機MLR(MiniMax/Gemini/OpenRouter無料枠・blind・triple)3ラウンドの経過:
- r1(32指摘・採用6): 相対パス
00_SYSTEM/...で${x##*/00_SYSTEM/}が先頭プレフィックスを剥がせずfail-open(critical・bash実測で再現)→#*00_SYSTEM/に修正 - r2(28指摘・採用4): その修復が
my_00_SYSTEM/00_SYSTEM/...型の前方部分一致ディレクトリ名で誤剥がしする2個目のfail-openを産んでいたことが判明 → 先頭相対のみ#00_SYSTEM/・それ以外##*/00_SYSTEM/のハイブリッドに修正 - r3(13指摘・採用2): 新規fail-openゼロで収束打ち切り。採用はmarker検証応答のok二重確認など防御経路の二重化
- 事後(CC自己点検): VERIFY_REASON抽出のbash二重クォート内
replace('\\','/')がエスケープで Python SyntaxError になり、M1導入時から block 文面の理由が常に常套句化していたのを発見・chr(92)で修復。この発見により、r2で「実測否定」したMiniMax指摘(M2R3)の結論は正しかったことが確定し、遅延採用として再分類(メカニズムの否定を実測できた安心感で結論の下流検証を省略した自己バイアスを事例として実例集に記録)
累計: 73指摘・採用12・fail-open実バグ2個+表示バグ1個修復・回帰テスト47件全緑・本番発火テスト(block/allow両経路)実測。詳細記録はSSOT内部に保存(非公開)。
</details>