CLAUDE.mdにルールを足すたびに、少し不安になる。これ、何個まで読まれてるのか。
なので測った。同じ3つのルールを「ルール3個だけのファイル」と「30個の中に埋めたファイル」の2通りで渡して、同じ6タスクをやらせ、守られたかを数えた。結果を先に言うと、3個環境は18チェック中18勝で完全遵守。30個環境は15勝3敗だった。ここまでは予想通りで、外れたのは死んだ場所だ。自分は「下の方のルールから死ぬ」と予想していた。実際は30番(末尾)のルールが無傷で、1番と15番が負けた。
[toc]
実験の組み方
測るルール(プローブ)は、機械的に採点できる3つにした。
- 回答の最終行には「DONE」とだけ書く
- コードブロックには必ず言語名を付ける(```python のように)
- 文章はである調で書く。「です」「ます」は使わない
環境Aはこの3個だけのルールファイル(101字)。環境Bは、この3個を30個のルールの中に埋めたファイル(726字)で、埋め方は1番・15番・30番。残り27個は「変数名はsnake_case」「mainへ直接pushしない」「日付はJSTに統一」みたいな、実際のプロジェクトにありそうなルールで埋めた。
タスクは6種類。READMEのセットアップ節、CSV集計のPython関数、テスト実行手順書、バグ報告の雛形、アクティブユーザー数のSQL、YAML設定ファイルの例。文章とコードが両方出るものを選んだ。
これをClaude Sonnetのサブエージェント12体(2環境×6タスク)に、ルールファイルを読ませてから実行させた。採点は3プローブ×6タスク×2環境=36チェック。最終行が「DONE」か、フェンスに言語タグが全部付いているか、「です。」「ます。」が混ざっていないか。
結果
| プローブ(Bでの位置) | 環境A(3個) | 環境B(30個) |
|---|---|---|
| 最終行DONE (1番) | 6/6 | 5/6 |
| フェンスに言語タグ (15番) | 6/6 | 4/6 |
| である調 (30番) | 6/6 | 6/6 |
| 合計 | 18/18 | 15/18 |
3個なら全部守る。30個でも83%は守る。想像より死ななかった、というのが第一印象だった。
予想が外れたのは位置だ。埋もれて死ぬなら末尾からのはずが、30番のである調は6タスク全部で守られた。負けたのは先頭の1番が1回と、真ん中の15番が2回。
死に方には共通点があった
15番(言語タグ)が負けた2回を見ると、落ちた場所が同じだった。
1敗目は手順書タスク。bashやpythonのフェンスには全部タグが付いているのに、.env ファイルの中身を貼ったフェンスだけ無タグだった。2敗目はバグ報告タスクで、エラーログを貼るフェンスだけ無タグ。つまり「コードには言語タグを付けるが、設定値やログの断片には付けない」という、人間の書き癖と同じ場所で落ちている。ルール自体は読まれていて、普段からタグを付ける場所では6/6で守る。習慣が無い場所にルールを延ばせなかった、という負け方だ。
1番(DONE)の1敗は、Python関数タスクで説明文を書き終えたあと、そのまま終わっていた。こっちは位置1番、ファイルの先頭に書いてあるルールで、読み飛ばしたとは考えにくい。長い成果物を書いているうちに抜けた、としか言えない。
まとめると、この実験の範囲では「位置が下だから死ぬ」は起きなかった。死んだのは、モデルの出力習慣とぶつかるルールと、成果物が長くなったときの単純な抜け。ルールを上に書けば安心、という配置の工夫は、少なくともこの規模では効いていない。
もう1つの副作用。頼んでいないルールの実演が始まる
数字に出ない変化で、読んでいて一番気になったのがこれだった。30個環境の成果物には、タスクと関係ないルールの「実演」が混ざり始める。
テスト手順書を頼んだだけなのに、30個環境の出力には請求APIのコード例が現れて、そこでISO 8601のログ・JSTのタイムゾーン定義・対処方法つきエラーメッセージが立て続けに披露される。SQLタスクでは説明文の中に「テーブル名は複数形、SQLキーワードは大文字で統一している」と、ルールを守ったことの自己申告が入る。3個環境の出力にはどちらも無い。
守られない心配ばかりしていたが、実際に読んで困ったのは逆だった。守りすぎている。ルールを増やすと、成果物がタスクの答えというより、ルールを守った証拠集めみたいになっていく。手順書として読むなら3個環境の出力の方が読みやすい。
この実験の限界
- 36チェックは少ない。1条件1回なので、B-T2のDONE抜けが再現するかは分からない
- 実行はClaude Codeのサブエージェント経由で、こちらの環境のグローバル設定も読み込まれた状態。素のAPIより「ルールを守る圧」が最初から高い可能性がある。AとBの差分だけを見ている理由はこれ
- モデルはSonnet 1種類。プローブ3個の選び方にも癖がある(である調は日本語の文体習慣として強く、埋もれても守りやすかった可能性)
- 30個の「実演」問題は目視での観察で、定量化できていない
自分の環境で数えるなら
プローブ方式なら30分で再現できる。機械採点できるルールを3つ決めて、素のルールファイルと、埋めたルールファイルを作り、同じタスクを投げて数えるだけ。判定はgrepで済む。
# 最終行がDONEか
tail -n 1 output.md
# 言語タグなしフェンスの検出(開始フェンスのみ数える)
grep -cE '^```$' output.md
# です・ます混入
grep -cE '(です|ます)。' output.md
自分のルールファイルは今9個ある。この結果を見て消す気になったかというと、正直まだ迷っている。83%は思ったより高い。ただ、手順書に請求APIの例が生えてきたのを見た以上、次の1個を足すのは前ほど気軽じゃない。いくつかは近いうちに消すと思う。どれを消すかはまだ決めていない。