AIDive

Claude Code Verify Поставил PASS Сломанному Коду

AIDive · Опубликовано

Кодинг-агентыИИ-модели

Сам себя оценил: 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-сессии и скрытые тесты, которые проверяют только то, что заявлено в запросе. На более сложной работе цифры изменятся.

Источники

Частые вопросы

Ловит ли /verify в Claude Code баги?
Не всегда, когда та же модель проверяет собственную работу. В бенчмарке из 116 сессий `/verify` вернул PASS в 24 из 24 запусков, включая изменение Haiku 4.5, не выполнившее заявленное требование; запущенный Opus 5.5 на том же изменении, он вернул FAIL 3 из 3.
Стоит ли использовать /verify в Claude Code вместе с Opus?
На понятных запросах — нет. На Opus 5.5 это подняло стоимость задачи с $0.39 до $0.96 (в 2,5 раза) и время с 75 до 125 с, не изменив ни одного из 12 результатов, потому что чистый Opus уже сам запускал набор тестов в 11 из 12 запусков.
Что лучше использовать для верификации в Claude Code — skill или Stop hook?
Stop hook — для всего, что может проверить скрипт. Claude открывал verification skill лишь в 10 из 24 сессий (Opus — 8 из 12, Sonnet — 2 из 6, Haiku — 0 из 6), тогда как Stop hook запускается каждый раз, когда агент пытается завершить работу; он обошёлся примерно на 20% дороже на Opus.
Что такое Stop hook в Claude Code?
Скрипт, который Claude Code запускает каждый раз, когда агент пытается завершить работу. Он может отказать в остановке с JSON-решением block и указанием причины, отправляя агента обратно к работе; он проверяет только то, что тестирует сам скрипт.
Может ли более сильная модель проверять код более слабой в Claude Code?
Да. `/verify` от Opus 5.5, подключённый как Stop hook, заставил Haiku 4.5 исправить пропущенный случай в 3 из 3 запусков. Это дорого обошлось: каждый запуск упирался в лимит 60 ходов и в среднем стоил $1.36 против $0.76 за написание функции одним Opus.
Почему ИИ-модель пропускает баги в собственном коде?
Её проверка тестирует только те случаи, о которых она уже подумала. Haiku проверил перенос одного пользователя на email другого, но ни разу — одно обновление, затрагивающее несколько документов, поэтому собственный `/verify` отметил проверенный случай и написал PASS, хотя скрытый тест провалился.

Похожие видео