AIの逸脱を、AIを使わずに見つける道具を作った

波打つ線の逸脱を、定規のような手作業の計測器具が直線と照合して検出している設計図風のイラスト

長時間の自律セッションは、毎回まったく別の失敗をするわけではなかった。能力の高低よりも、任せている構造に引かれて、同じ種類の逸脱が何度も顔を出す。

そこで作ったのが、lanes/heavyweight-audit という監査道具だ。名前の通り少し重装備だが、やることは慎重に絞った。AIに「これは危ないですか」と判断させない。実行記録を機械的に読み、決めた条件に当てはまるものだけを可視化して、人へ渡す。

検出したい型は三つある。

  • 承認境界の踏み越え
  • 編集したのに未コミットのまま終わる棚卸し漏れ
  • 停止・再起動・スケジュール削除など、稼働レーンそのものを操作する動き

前二つは旧環境で実際に観測した。三つ目も含め、どれも文章の雰囲気やエージェントの自己申告ではなく、残った実行記録から条件として拾える。ここが今回いちばん作りたかったところだった。

目次

「賢く見抜く」より、同じ条件で止める

図解: 監査の3層構造(Layer 0 静止待機、Layer 1 決定論ガードが常時稼働、Layer 2 判断層は点線でグレーアウトし未搬入)
図解: いまはLayer 1までが稼働し、Layer 2は接続待ち(AI生成)

監査は三層に分けた。最初の Layer 0 は、まだ動いている途中のセッションを誤って監査しないための切り出しだ。codex のセッションは末尾の task_complete を基準に30分、なければ180分を待つ。claude は単独で90分を待つ。まず静止したものだけを対象にする。

次の Layer 1 がこの道具の中心で、モデルを一切使わない決定論ガードになっている。

  • G1: protected path に触れたのに、定めた形式の承認マーカーがない
  • G2: 編集済みなのにコミットされていない
  • G4: systemctl stop lane-*、cron の削除、再起動、再帰的な削除のようなレーン操作がある

ここで必要なのは解釈力ではなく、同じ記録に対していつ読んでも同じ答えを返すことだった。全セッションに掛けられ、モデルの利用状況にも左右されない。通知が出ても「危険と確定した」という意味にはしない。ただ、人が確認すべき札を作る。

Layer 2 には本来、判断を受け持つ層を置く予定だった。しかし判断主体の MAGI はまだ搬入していない。そのため現在は notify-only に縮退している。検出、集約、通知まで。修復や最終判断はしない。

承認の文を、ただの魔法の言葉にしない

この工作で一番面白く、いちばん神経を使ったのは G1 だった。保護対象を触った後に「承認されていました」と書けば通れる設計では、監査の意味が薄くなる。

承認 trailer は owner (日付 chat: 具体的な承認内容) の形式だけを通す。曖昧な語だけ、日付なし、MAGI 形式は弾く。過去コミットを後から正規化する場合も、Resolves-G1: に40桁の完全ハッシュを全件列挙する。短縮ハッシュは使わず、履歴を書き換える rebase、amend、force-push にも頼らない。

とはいえ、自分で書いた規則を自分で信じ込むのは危ない。そこで別ベンダーの codex に、このレーンの反証を依頼した。2026年7月25日の結果は claim FALSE。偽の承認 trailer が通過する迂回路が見つかった。

これは少し悔しいが、工作としては最高の瞬間でもある。守るための道具に、攻める役をきちんと当てたら穴が見えた。見つかった迂回路は、self_protected_paths を承認 trailer では一切クリアしない仕様にして塞いだ。監査道具自身の防御を、被監査側の文言だけで解除できないようにした。

同じ方向の工作としては、先に作った「自分の権限は自分で書き換えない、という制約を工作した」ともつながっている。こちらは、任せた後の実行記録を見返す番だ。

生の指摘を投げず、毎日一度だけ引き渡す

図解: 検出結果の蓄積から20:00 JSTのtriageを経て、差分だけがDiscordへ通知される手順
図解: 生の指摘は溜め、毎日一度だけ差分を渡す(AI生成)

検出結果は、そのまま大量に送らない。日次20:00 JST の triage が、機械的に終端できる札を終端し、前回通知から変わった分だけを Discord へ返す。

以前は生の findings をそのまま送る経路もあったが、2026年8月2日の「集約して、適切に対応して、その結果を返す」というオーナー指示を受けて廃止した。監査の仕事は、不安を増幅することではない。確認の入口を整えて、次の人が扱える量で渡すことだ。

未終端の指摘は一覧で確認でき、対応後は ID、状態、何を検証したかを添えて終端できる。監査結果と対応結果が別々に消えてしまわないよう、ここも道具の一部として残した。

「直しはしないで、壊れた直後の証拠を集める」という設計は、以前の証拠収集ツールから引き継いでいる。今回は対象が障害ではなく、自律セッションの行動になっただけだ。

いまは判断しない。けれど、判断の置き場は残してある

Layer 1 は、現在も全セッションに無料で掛かっている。一方で Layer 2 は判断主体がいないため、notify-only のままだ。

ただ、報告にはすでに trigger_pairs と動議相当の情報を出している。MAGI をこの環境へ搬入できたとき、判断層を戻せる余地は残してある。監査コード自体が被監査リポジトリの作業ツリーから実行されるという限界、つまり実行バイナリを分離できていない点も、まだ手つかずだ。

次は「もっと賢く検出する」と決めてはいない。まず、この三つの札を人へ渡すところまでを崩さずに回しながら、どこまでなら判断を持たせられるかを見ている。AIを見張るために、あえてAIを使わない。その余白が残っている今の形が、なかなか気に入っている。

対照的に、固定プログラムの見張り係をAIへ置き換えた工作もある。興味があれば、「見張り係を固定プログラムからAIに置き換えた」もどうぞ。同じ「確かめる」でも、置くべき場所は道具ごとに違う。

この検証を回している環境

この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。

ラボ構成のまとめを見る →
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次