補足: 本記事は AI(Claude)が私の最初のメモと着想をもとに仕上げたものです。
前回の「待つのは一つだけ」は、一つのことを認めて終わっていた。モデルが八段すべてを守りきる保証は出せない。だから次にやることはルールを増やすことではなく、どれだけ守られているかを測ることだ、と。
今回はその測定から得たことを書く。結論を先に言うと、点数をつけるのは簡単で、難しいのは分母を決めることだ。 分母を三度直し、点数は 11% から 24% まで上がった。その間、モデルの振る舞いは一度も変わっていない。
どのルールにも、セッションの記録の中に見つけられる痕跡がある。ゲートのブロックが書かれたか、審査の判決行が現れたか、テスト実行の結果が error を返したか。だから測り方はこうなる——すべてのセッションの記録を引き出し、区間に切り、区間ごとに問う。「このルールはここで発火すべきだったか。発火したか」。
分子は「発火した」区間の数、分母は「発火すべきだった」区間の数だ。分子はまず間違えない。痕跡は痕跡だからだ。落とし穴はすべて分母にある。
最初の版は、何かしら手を動かした区間をすべて「審査対象となる」分母に数えていた。よく見ると、163 の区間は git commit、mkdir、install.sh、tee の類しか走らせていない——分母の三割を占め、遵守率は 1% だった。
1% で当然だ。それらの区間には審査する作品がない。ルールはそもそもそこで発火するはずのものではなかった。外したところ、遵守率は 11% から 15% に動いた。
雑音を取り除いてもまだ何かがおかしい。審査対象の 390 の区間のうち 58 で、判決行は区間の中にはある——ただし最後の編集の後にはない。
追っていくと、区間の境界が間違っていた。隣り合う二つの仕事が一つの区間に畳まれている。一つ目は完了し、審査され、判決が書かれた。続いて二つ目が編集を始め、審査なしで終わった。一つの区間として読めば、最後の編集の後に判決はないから、落第と採点される。
だがこの読みはまったく逆さまだ。審査を受けた一つ目が減点され、審査を受けていない二つ目は同じ区間に隠れて、一度も数えられていない。
直し方は「判決が書かれた瞬間に区間を閉じる」。これで遵守率は 15% から 24% に動いた。
三つの数字を並べてみる。
| 分母 | 遵守率 | モデルの振る舞い |
|---|---|---|
| コマンドのみの区間を含める | 11% | — |
| コマンドのみの区間を外す | 15% | 変わらず |
| 判決が書かれた時点で区間を閉じる | 24% | やはり変わらず |
毎回、分母が真に近づいただけで、規律が良くなったわけではない。これがこの記事の背骨だ。「エージェントの遵守率」という数字を見たら、まずその分母が誰で、いつ変えられたかを問うこと。 分母の履歴を持たない点数は、先月と比べられない。
二つ目の落とし穴は分母の話ではない。誰が誰を採点しているか、の話だ。
ルールはこう書いてある。審査で指摘が出たらまず直す。直してから完了報告を書き、最後の行に Compliance Review: PASS と記す。ルール自体は正しい。だが測定が読むのがその行なら、結果は 100% にしかなりえない——その行を書くのは、審査される側であるメインの流れ自身であり、メインの流れは自分が通ったと思えるまで書かないからだ。
だから判決は、審査者自身の記録から読むしかない。派遣された、読み取り専用の、メインの流れと記憶を共有しないエージェントが実際に何を言ったか。メインの行は主張であり、審査者の記録が証拠だ。
同じ落とし穴は、ゲートの受入率にも姿を変えて現れる。ゲートが止まって人を待つとき、ユーザーはいくつかの選択肢から一つを選んで答える。「一つ選んだ」を常に「計画を受け入れた」と数えるなら、計画がどれほど雑でも、分母の十分の一は構造的に 100% に張り付く。
判定を二つの層に分けた。構造的な判定は tool_result の error フラグだけを読み、出力文字列はいっさい解析しない——だから書式の変更で壊れることはない。頼もしく聞こえる。
そこへ前回の落とし穴が戻ってきた。今度は数字を携えて。
flutter analyze 2>&1 | tail -6
set -o pipefail がなければ、shell が返すのは tail の終了ステータスだ。記録を横断して見ると、pipe を通した lint 実行の 99% が「クリーン」を返していた。linter が何を捕まえていようがだ。これらを通過と数えるわけにはいかない。「測定不能」という別枠を設け、その行の下に印字し、どちら側にも数えないことにした。
同じ行から、小さいものもいくつか出てきた。
command -v による探査が分母に紛れ込み、どれも「失敗」していた。理由はただ、その機械にツールが入っていなかったこと。tsc を裸の単語で照合すると、grep -n tsc file も型検査として数えられ、しかも grep の終了ステータスを借りて通過を捏造する。構造的とは「モデルの読みに頼らない」という意味であって、「間違えない」という意味ではない。
三つ目の落とし穴は、測定が確信を持てないときにどうするか、だ。私の答えは、どちら側にも数えず、別に記録すること。
abandoned として記録する。沈黙は計画への判決ではない。データを捨てるのは痛い。だが一つの誤った帰属は、行全体の数字を間違った方向へ傾ける。しかもそれは見えない。
前述の通り、判定は二層ある。構造的な層は終了ステータスを読む。発見的な層は記録の一区間をモデルに渡して意図を判断させる(セッションとターン単位でキャッシュし、二度は訊かない)。
二つの信頼度は大きく違う。だから見出しの数字は二つに分けて出し、一つの平均で確からしさを装うことはしない。さらにモデル別——Opus、Sonnet、Fable をそれぞれ一列——にも切っている。「モデルはルールを忘れる」はもともとモデルについての主張であって、混ぜてしまえば差が見えなくなるからだ。

2026-08-31 時点のダッシュボード。各行の下の小さな文字が、分母から外されたものだ。コンプライアンス審査の行は、本記事を書く時点で 37% まで来ている。
先に三つ。
エージェントが規律を守っているかを知りたいなら、まず点数を見ないこと。先に三つ問う。この点数の分母は誰か、誰が誰を採点しているか、分からないときそれはどうするか。三つとも答えが出て初めて、その数字は意味を持ちはじめる。