TL;DR
- Anthropic 自身の推奨は考え方として正しい。フィードバックループを持つモデルは、より良い成果物を出す。問題は、そのループを誰が回すかだ。116 回の実行で、組み込みの
/verifyは 24 回中 24 回 PASS を返した。明示された要件を壊す変更に対しても同じだった。 - 自分の変更を自分で確認するモデルは、同じ盲点を共有する。Haiku 4.5 は、同一モデルのすべてのセットアップで、同じ unique-field のケースを 11 回中 11 回見落とした。Haiku 自身の
/verifyも、誤ったケースの横にチェックマークを付けた。 - Opus 5.5 では、
/verifyのコストは 2.5 倍($0.96 対 $0.39)で、結果は何も変わらなかった。素の Opus は 12 回中 12 回正解し、そのうち 11 回で自分からテストスイートを実行した。 - プロジェクトの skill はモデルにとって任意だ。24 回中 10 回しか発動せず、Haiku では 6 回中 0 回だった。Stop hook は毎回発動し、Opus ではコストが約 20% 増えた。
- 機能したチェックは、作者の外側から来た。同じ
/verifyを Opus で実行すると、Haiku の変更に対して 3 回中 3 回 FAIL を返し、バグを名指しした。これを Stop hook として組み込むと、Haiku は 3 回中 3 回バグを直した。コストは 1 タスクあたり $1.36 で、Opus が単独で書く場合の $0.76 と比較できる。 - 真似するならこの形だ。決定的な部分には Stop hook、判断が要る部分には作者ではない verifier、仕様が明確な作業の Opus では
/verifyを使わない。
What the measurements say
Anthropic の主張: "If Claude has that feedback loop, it will 2-3x the quality of the final result." s4 ブログはこれを 5 ステップの導入手順にしている。最も繰り返す手動チェックを選ぶ、組み込みの /verify を試す、手順を平易な英語で skill に書く、それを決定的にする、CI に移す、の順だ。s1 v2.1.215 以降、"Claude no longer runs the /verify and /code-review skills on its own; invoke them with /verify or /code-review when you want them." s3
現場の報告は、検証したと主張されながら実行されていないケースに集中している。Issue #96416 は、懸念 19 件のうち 5 件しか検証していないのに "accept as-is" を出したレビュー判定だ。s6 Issue #97039 は、チェックリストを読み込んでいたのに、部分的なチェックだけで "held up" と主張した例だ。s7 "build passes" と "production-ready" は別の水準で、見逃しのたびに 2-3 回の再プロンプトが発生する。s8
私たちのベンチは、エージェントが一度も見ない隠し受け入れテストで、すべての "done" を採点した。タスク実行 112 回 + モデル間 /verify 実行 4 回 = 116 回、API 換算コストは $66.29 だった。誤った "done" は 112 回中 12 回。そのうち 11 回はセットアップ A から E のすべてでの T6 の Haiku、1 回は skill セットアップでの T6 の Sonnet で、自分で書いた新しいテストが落ちていたのに skill が発動しなかった。s1
組み込みの /verify は、3 モデル合計 24 回中 24 回で Verdict: PASS と言った(23 回はパース可能、1 回はラベルなしの pass)。Haiku の壊れた T6 も含む。Opus では、素の実行の $0.39 に対し $0.96(2.5 倍)、75 s に対し 125 s かかり、結果は何も変えなかった。s3
5 ステップの手順どおりに書いたプロジェクト skill が呼ばれたのは 24 回中 10 回だった。Opus 8/12、Sonnet 2/6、Haiku 0/6。Stop hook は毎回発動し、Opus では $0.39 に対して $0.47(+20 %)だった。s19
盲点は 1 つの要件、T6 の req 4 だ。複数の一致ドキュメントに同じ unique な値を与える単一の update は、DuplicateKeyError を送出しなければならない。Haiku は、すべてのセットアップ(plain、/verify、skill、hook、tests first)で 11 回中 11 回見落とした。Haiku 自身の /verify は "update one doc onto another's email" を確認しただけで、1 回の update が複数のドキュメントに当たるケースは試さなかった。テストファーストのルールも効かなかった。3/3 が req 4 を見落とし、1 回は req 3 まで壊した。s1
同じ Haiku の変更を、別のモデルで /verify した結果: Sonnet は PASS(1/1)、Opus は FAIL 3/3 で、毎回同じケース、つまり 1 回の update が同じ値を複数のドキュメントに書くケースを名指しした。1 回のチェックは $0.39 から $0.47 だった。Haiku への Stop hook として(セットアップ F)、Opus の verifier はバグを 3 回中 3 回直させた。3 回とも修正中に 60 ターンの上限に達し、verifier を含む T6 1 回の平均は $1.36 だった。Opus が T6 を単独で書いた場合は $0.76 で、誤った "done" は 0 だった。s19
Measurements
ハーネス: Claude Code 2.1.283 headless(claude -p)、分離した config dir、タスクごとに同じプロンプト、60 ターン上限。リポジトリ: msiemens/tinydb @ 18d73a1(Python、テスト 226 件)。機能要望 T1 から T6 の 6 件で、それぞれ明示された要件が 5 つ(T5 は 6 つ)。隠し受け入れテストは要件ごとに 1 つで、エージェントには一切見せず、すべての実行を採点する。リポジトリ自身のスイートも実行する。誤った "done" とは、隠しテストまたはリポジトリのスイートが失敗しているのに完了を主張して終わった実行のこと。
セットアップ: A plain(要望のみ)、B /verify(A のあと、2 ターン目で組み込みの /verify)、C verify skill(5 ステップの手順どおりに書いた、モデルが呼び出せるプロジェクト skill)、D Stop hook(prove-it.py: スイートが赤の間は停止をブロックし、最初の停止では要件ごとに証拠 1 行を求めてブロックする)、E tests first(CLAUDE.md のルール: コードの前に要件ごとに落ちるテストを書く)、F Opus verifier hook(変更に対して claude -p /verify --model opus を実行し、PASS 以外の verdict ならブロック、最大 2 ラウンド)。
| model | setup | runs | false done | avg cost | avg turns | avg wall |
|---|---|---|---|---|---|---|
| Opus 5.5 | A plain | 12 | 0 | $0.39 | 16.6 | 75 s |
| Opus 5.5 | B /verify | 12 | 0 | $0.96 | 22.3 | 125 s |
| Opus 5.5 | C skill | 12 | 0 | $0.43 | 19.5 | 80 s |
| Opus 5.5 | D hook | 12 | 0 | $0.47 | 19.8 | 94 s |
| Opus 5.5 | E tests first | 2 (T6) | 0 | $0.64 | 18.5 | 129 s |
| Sonnet 5 | A | 7 | 0 | $0.44 | 24.0 | 112 s |
| Sonnet 5 | B | 6 | 0 | $1.18 | 36.3 | 210 s |
| Sonnet 5 | C | 7 | 1 | $0.48 | 25.7 | 136 s |
| Sonnet 5 | D | 6 | 0 | $0.53 | 27.0 | 157 s |
| Haiku 4.5 | A | 8 | 3 | $0.34 | 35.4 | 172 s |
| Haiku 4.5 | B | 6 | 1 | $0.68 | 43.3 | 217 s |
| Haiku 4.5 | C | 6 | 1 | $0.26 | 28.2 | 124 s |
| Haiku 4.5 | D | 8 | 3 | $0.37 | 38.9 | 179 s |
| Haiku 4.5 | E | 3 (T6) | 3 | $0.41 | 38.3 | 186 s |
| Haiku 4.5 | F Opus verifier | 3 (T6) | 0 | $1.36 verifier 込み | 61 (cap) | 457 s |
| Sonnet 5 | F | 1 (T6) | 0 | $2.30 verifier 込み | 50 | 512 s |
制約: リポジトリは 1 つ(小さく、テストが充実した Python ライブラリ)、仕様が明確な要望は 6 件、各セルの繰り返しは 1 から 3 回、headless 実行。隠しテストは、要望に書かれたことだけを検証する。
Do this Monday
- モデルの "done" を読む前に、明示された要件ごとに受け入れテストを自分で 1 つ書く。ベンチの隠しテストは、同一モデルのどのチェックも見逃したものを捕まえた。
- テストスイートを実行し、赤の間は block decision を返す Stop hook を追加する。毎回発動する。skill は発動しない。
- タスクの最初の停止に、要件ごとに証拠 1 行を要求する(
prove-it.pyのパターン)。文章ではなく、コマンドとその出力で。 - 判断が要るチェックは、その変更を書いていないモデルに回す。diff に対して
claude -p /verify --model opusを実行し、PASS 以外ならブロック、上限は 2 ラウンド。 - 仕様が明確な要望の Opus 5.5 では、習慣で
/verifyを打つのをやめる。コストは 2.5 倍で、12 回の実行で何も変わらなかった。テストのない領域や、既存バグの調査のために取っておく。 - コスト削減のために Haiku 4.5 へ委任するなら、verifier の予算を見込む。Opus hook 付きで 1 タスク $1.36、Opus が単独で書けば $0.76。
- 失敗した修正のリトライをすべて ledger に記録し、同じものが繰り返されたらループを止める。ブロックする hook が、同じ誤ったパッチでトークンを燃やさないようにするため。
- 要件を、複数行のケースの観点で読み直す。"one update that matches several documents" は、Haiku の 11 回中 11 回が一度も試さなかったケースの形だ。
Go further
- 5 ステップの手順と、手動チェックから CI ゲートまでの成熟度のはしご。hook がローカルで動くようになったら、決定的な部分が属するのは上の段(CI と PR のゲート)だ。s1
- Stop hook の仕様: reason 付きの block decision はターンをモデルに差し戻す。自作のゲートを書く前に、exit code と JSON contract を読むこと。s19
- Groundtruth は、チェックが通るまでターンの終了を拒否する Stop hook だ。この考え方の決定的な版で、参照実装として読める。s5
- regressionledger はコスト側の話だ。同じ失敗した修正を再試行するループを止める hook で、実行が 60 ターンの上限に達したとき、私たちの Stop hook に欠けていた部品だ。s10
Sources
- Building verification loops in Claude Code with skills, Anthropic blog. 読む理由: ベンチの skill セットアップの土台になった 5 ステップの手順とはしご。
- Building verification loops in Claude Code, official Claude channel. 読む理由:
/verifyが初回に何をするかを 3 分で。使い続けるか決める前に。 - Claude Code CHANGELOG, GitHub. 読む理由: v2.1.215 で
/verifyがユーザー呼び出しのみになった。実行される頻度が変わる。 - Boris Cherny: give Claude a way to verify its work, X. 読む理由: "2-3x the quality" という主張の正確な文言。
- Groundtruth, GitHub. 読む理由: ゼロから書く代わりにコピーできる、動作する Stop hook ゲート。
- Issue #96416, GitHub. 読む理由: 懸念 19 件のうち 5 件しか検証せずに承認したレビュー判定の、日付付きトランスクリプト。
- Issue #97039, GitHub. 読む理由: 2 日後に、チェックリストを読み込んだ状態で起きた同じ失敗。チェックリストでは解決しない。
- AI coding agents can verify some of their work now, dev.to. 読む理由: "build passes" と "production-ready" の差を最も明快に述べた記事。
- Saguaro, GitHub. 読む理由: ループ内レビューと PR レベルのレビューをめぐる議論。コメント欄に反論がある。
- regressionledger, GitHub. 読む理由: ブロックする hook が生むリトライコストの問題と、それを抑える一つの方法。
- SPICE simulation to oscilloscope to verification with Claude Code, personal blog. 読む理由: オラクルが物理的な計測器である検証ループ。
- Hooks reference, code.claude.com. 読む理由: Stop hook が守るべき block decision の contract。
FAQ
組み込みの /verify はバグを捕まえるか?
このベンチでは捕まえなかった。Opus 5.5、Sonnet 5、Haiku 4.5 の 24 回中 24 回で PASS を返し、明示された要件を壊した Haiku の変更も含まれる。唯一の有用な発見は、変更とは無関係な、既存の upstream のバグだった。
なぜ強い verifier が弱い書き手の助けになるのか?
Haiku 自身のチェックは、すでに思いついていたケースを試しただけだった。Opus は同じ変更と同じ /verify で、1 回の update が複数のドキュメントに当たるケースを試し、3 回中 3 回 FAIL と言った。Sonnet は PASS と言った。verifier は、作者が見なかったケースを見る必要がある。
Haiku を Opus で検証するのと、Opus で書くのではどちらが安いか?
Opus で書くほうが安い。Haiku に付けた Opus verifier hook は T6 1 回あたり平均 $1.36 で、毎回 60 ターンの上限に達した。Opus が T6 を単独で書いた場合は平均 $0.76 で、誤った "done" は 0 だった。
AIDive