Сам себя оценил: PASS
Встроенная проверка Claude Code, /verify, поставила PASS сломанной функции. Таков результат бенчмарка из 116 сессий Claude Code на реальном репозитории, где каждое «готово» потом оценивалось приёмочными тестами, которых агент никогда не видел.
Борис Черни, создатель Claude Code, называет верификацию самым важным, что вы можете ей дать. Встроенная проверка запускается по требованию начиная с Claude Code v2.1.215: либо вы вводите /verify, либо она не срабатывает вовсе. В этом бенчмарке она поставила PASS в 24 запусках из 24, и в одном из них была выпущена сломанная функция. Что на самом деле поймало баг — рассказано ниже, вместе с настройкой, которая обошлась в два с половиной раза дороже и ничего не изменила.
Тест: 116 прогонов, тесты, которых не видели
Ложное «готово» — это сессия, которая завершается заявлением, что работа сделана, хотя скрытый приёмочный тест или собственный набор тестов репозитория не проходит. Бенчмарк измеряет, как часто это происходит при шести настройках верификации.
Сомнение, которое всё это запустило, пришло из собственного трекера задач Claude Code: issue #96416, заведённая 2026-09-23, описывает ревью, которое перечислило 19 замечаний, проверило 5 из них и всё равно заключило «accept as is».
| Параметр | Значение |
|---|---|
| Репозиторий | msiemens/tinydb (документная база данных на Python), коммит 18d73a1 |
| Набор тестов репозитория | 226 тестов |
| Заявки на функции | 6, в каждой по 5 требований |
| Скрытые приёмочные тесты | по одному на каждое требование, написаны до любого запуска, никогда не показывались агенту |
| Модели | Opus 5.5, Sonnet 5, Haiku 4.5 |
| Claude Code | 2.1.283, headless (claude -p), лимит 60 ходов |
| Сессии | 112 запусков задач + 4 межмодельных запуска /verify = 116 |
| Затраты | $66.29 в API-эквиваленте |
Шесть настроек — от чистого Claude Code (только запрос) до второй модели, проверяющей работу в момент остановки:
| Настройка | Что добавляется |
|---|---|
| A plain | ничего |
| B /verify | встроенный /verify, введённый вторым ходом |
| C verify skill | project skill, написанный по методике Anthropic |
| D Stop hook | скрипт, блокирующий остановку, пока набор тестов красный, и требующий доказательство по каждому требованию |
| E tests first | правило в CLAUDE.md: падающий тест на каждое требование до написания кода |
| F Opus verifier | Stop hook, запускающий /verify с Opus поверх изменения |
Понятные запросы к хорошо покрытой тестами библиотеке — это лёгкий случай. Чистый Opus 5.5 правильно справился во всех 12 своих запусках и в 11 из них сам запускал набор тестов, прежде чем сказать, что готово.
Встроенный /verify: всегда PASS, в 2,5 раза дороже
/verify — это skill верификации, который поставляется вместе с Claude Code. Он прогоняет изменение, читает diff и пошагово выносит вердикт. Начиная с v2.1.215 он вызывается только пользователем, поэтому в бенчмарке его вводили после каждой задачи вторым ходом.
Он вынес вердикт PASS в 24 запусках из 24 по всем трём моделям, включая сломанное изменение от Haiku. На Opus 5.5 он не изменил ни одного результата и обошёлся в 2,5 раза дороже:
| Opus 5.5, на задачу | Plain | С /verify |
|---|---|---|
| Стоимость | $0.39 | $0.96 |
| Время выполнения | 75 с | 125 с |
| Изменённые результаты | 0 из 12 |
Справедливости ради, /verify нашёл один настоящий баг: в одной задаче Opus он отметил проблему reuse-after-close, которая уже была в библиотеке и не была вызвана проверяемым изменением. На работе, которая и так была правильной, это дорогое второе мнение.
Skill или hook: что легче пропустить
Skill — это markdown-процедура, которую Claude может открыть, если сочтёт её уместной. В посте Anthropic о циклах верификации описан рецепт из шести шагов: выбрать ручную проверку, которую вы делаете чаще всего, сначала попробовать встроенный /verify, описать процедуру простым языком, превратить её в skill, затем вызвать её на новой задаче и итерировать. Skill бенчмарка, verify-change, был построен именно так и предписывает Claude доказывать каждое требование на реальном коде, прежде чем сказать, что готово.
Skill — это лишь предложение, и Claude сам решает, открывать его или нет:
| Модель | Сессии, открывшие skill |
|---|---|
| Opus 5.5 | 8 из 12 |
| Sonnet 5 | 2 из 6 |
| Haiku 4.5 | 0 из 6 |
| Всего | 10 из 24 |
Единственное ложное «готово» от Sonnet случилось в сессии, где skill так и не открылся: она завершилась с двумя проваленными собственными новыми тестами.
Stop hook — это скрипт, который Claude Code запускает каждый раз, когда агент пытается завершить работу. Он может отказать в остановке и вернуть агента с указанием причины. Hook из бенчмарка запускает набор тестов, блокирует остановку, пока тесты красные, и при первой попытке остановиться требует по одной строке доказательства на каждое требование. Он срабатывал в каждой сессии. На Opus он обошёлся на 20% дороже — $0.47 против $0.39 за задачу (94 с против 75 с). В этом бенчмарке он ни разу не застал набор тестов красным в момент остановки, поэтому ловить было нечего: hook срабатывает всегда, но проверяет только то, что вы велели ему проверять.
Слепое пятно: 11 из 11 пропущено
Провалившаяся задача требовала уникальных полей в таблице: два пользователя не могут иметь один и тот же email, и любое обновление, после которого два документа получат одинаковое уникальное значение, должно вызывать DuplicateKeyError.
Haiku 4.5 протестировал перенос одного пользователя на email другого пользователя, и это было корректно отклонено. Но он ни разу не протестировал одно обновление, которое затрагивает сразу несколько документов и записывает во все них один и тот же новый email. Этот случай проходил без ошибки в 11 сессиях Haiku из 11, в каждой настройке с той же моделью: plain, /verify, skill, Stop hook и tests first.
Собственный /verify Haiku отметил галочкой тот случай, который он проверил, и написал PASS. Скрытый тест выдал DID NOT RAISE DuplicateKeyError. Sonnet 5, которого попросили прогнать /verify на том же изменении, тоже вернул PASS. И Opus, и Sonnet сами написали эту функцию правильно, так что это один случай — одна модель на одной задаче, — но проверка, написанная той же моделью, разделяет её слепое пятно.
Внешняя проверка: Opus говорит FAIL
Тот же /verify на том же изменении Haiku, запущенный Opus 5.5, вернул FAIL в 3 запусках из 3, каждый раз называя пропущенный случай: одно обновление, затрагивающее несколько документов, записывает во все них одно и то же значение без ошибки. Поймала это другая модель — не автор и не собственная проверка автора.
Подключённый как Stop hook (настройка F), Opus проверяет работу Haiku каждый раз, когда Haiku пытается завершить работу. Результаты:
| T6, на запуск | Haiku + проверка Opus | Opus 5.5 в одиночку |
|---|---|---|
| Баг исправлен / ложное «готово» | исправлен в 3 из 3 | 0 ложных «готово» |
| Ходы | лимит 60 ходов достигнут в каждом запуске | |
| Стоимость | $1.36 с учётом проверяющего | $0.76 |
Внешняя проверка работает. На этой задаче она обошлась дороже, чем если бы более сильная модель написала функцию сама.
Что взять на вооружение и что это стоит
Хватит позволять модели, написавшей изменение, быть единственной, кто его проверяет.
| Правило | Почему | Стоимость на этом бенчмарке |
|---|---|---|
| Держите Stop hook для всего, что может проверить скрипт | он срабатывает в каждой сессии | около 20% дороже на Opus |
| Настоящая проверка должна приходить извне автора: более сильная модель на выходе или собственные тесты, написанные по запросу | та же модель пропустила свой баг 11 раз из 11 | $1.36 за задачу для связки Haiku + проверка Opus |
На понятном запросе с Opus не вводите /verify |
0 изменённых результатов | стоимость ×2,5, 125 с против 75 с |
Ограничения: одна небольшая библиотека, шесть понятных запросов, от одного до трёх запусков на ячейку, headless-сессии и скрытые тесты, которые проверяют только то, что заявлено в запросе. На более сложной работе цифры изменятся.
AIDive