«Готово» — это оценка агента или чека? TDD и eval-driven разработка с ИИ

12 мин. чтения
BYBIT EARN
Крипта лежит?
Bybit Earn: процент капает каждый день
Открыть Earn

Коротко (TL;DR)

ИИ-агент любит рапортовать «готово». Проблема в том, что «готово» в его исполнении часто значит «выглядит готовым» — код написан, но не проверен, тесты подогнаны, а фича не работает на краевых случаях. Решение — сделать критерий готовности объективным и машинным: готово не когда агент так сказал, а когда прошли тесты и проверки.

Это выстраивается в три слоя:

  1. Verification loop — общий принцип: дайте агенту исполняемый чек (тест, сборка, линтер, скриншот-дифф), который сам возвращает «прошло/не прошло», и цикл замкнётся без вас.
  2. TDD (test-driven) — частный случай для детерминированного кода: тесты пишутся до реализации, «готово» = зелёные тесты.
  3. EDD (eval-driven) — для генеративного и качественного вывода, где бинарного «прошло/не прошло» мало и нужна оценка по нескольким измерениям.

Ниже — как это работает, чем принудить агента (не попросить, а заставить инфраструктурой), почему агенты подгоняют тесты (с цифрами) и готовый чек-лист Definition of Done.

«Готово» — чья это оценка

Корень проблемы в том, что модель по умолчанию оценивает свою работу сама — и оценивает оптимистично. Она декларирует успех, потому что результат «похож на правильный», а не потому, что он проверен. Anthropic задокументировала это как отдельный режим отказа: агент помечает фичу выполненной до реальной проверки.

BYBIT COPY TRADINGКопитрейдинг на BybitОткрытая статистика трейдеров, старт с $10, отключение в один клик.Выбрать трейдера

Официальный ответ Anthropic — принцип verification loop: дайте агенту то, что выдаёт «pass или fail», и цикл замкнётся сам. Ключевое слово — исполняемый. Пока критерий субъективен («сделай хорошо»), агенту нечем себя проверить. Как только появляется тест или сборка, у него есть объективный сигнал, и он будет доводить работу до зелёного, а не до «на мой взгляд, норм».

Модель Claude Sonnet 5, исполняя такой цикл в Claude Code, ведёт себя принципиально иначе, чем в свободном режиме: не «я думаю, готово», а «тесты зелёные — готово». Разница как между самооценкой и приёмкой по чек-листу.

TDD с ИИ: тесты до кода

Классический ритм TDD — red-green-refactor: сначала пишем падающий тест (red), потом минимальную реализацию, чтобы он прошёл (green), потом чистим код (refactor). С ИИ он работает так же, но есть нюанс: по умолчанию модель делает наоборот — сначала пишет реализацию, потом тест под неё.

Причина не в лени, а в архитектуре контекста. Если тест и реализацию пишет один агент в одном окне, он «подсматривает» будущую реализацию, пока формулирует тест, и неосознанно подгоняет тест под неё. Это называют context pollution (загрязнение контекста). Тест, написанный с оглядкой на реализацию, проверяет не то, что нужно, а то, что уже задумано, — и теряет смысл как независимая проверка.

Важно честно разделить, что тут официальная позиция, а что практика сообщества. Anthropic даёт общий принцип verification loop и пример «задайте критерии проверки». А строгую дисциплину «напиши тест, подтверди, что он упал, и только потом реализацию, без заглушек» — довели до рабочего вида уже практики. Это не цитата Anthropic, а надстройка над её принципом; путать их не стоит.

Как заставить агента реально это делать

Просьба в промпте — слабый инструмент: агент про неё забудет, особенно после сжатия контекста. Принуждение выстраивается по нарастающей жёсткости:

  • Правила в CLAUDE.md — advisory-слой. Удобно, но это рекомендация: агент читает файл в начале сессии, а после /compact может о нём «забыть». Годится как договорённость, не как гарантия.
  • PreToolUse-хуки — детерминированный слой. Хук может физически заблокировать запись кода, пока нет теста, — это уже не «агент согласился», а «инфраструктура не пустила». Хуки принуждают там, где промпт только просит.
  • Субагенты по фазам — изоляция контекста. Тест пишет один субагент, реализацию — другой, в отдельном окне, не видя замысла первого. Так лечится context pollution: тест-райтер не может подсмотреть реализацию, потому что её ещё нет в его контексте.

Хороший технический паттерн для этого — feature-list в виде JSON, где у каждой фичи стоит поле passes: false, а агенту запрещено редактировать тесты. Фича переводится в passes: true только после реальной проверки. Этот приём Anthropic описала в эксперименте с «харнессами» для долгих агентов: агент сам верифицирует каждую фичу и помечает пройденной лишь после аккуратного теста.

BYBITВсё ещё смотришь со стороны?Рынок работает без выходных. Счёт на Bybit открывается за 2 минуты.Начать сейчас

Eval-driven development: когда тестов мало

Юнит-тест отвечает на бинарный вопрос: прошло или нет. Но для генеративного вывода (текст, суммаризация, ответы ассистента) этого мало — там нет одного «правильного» ответа, есть «лучше или хуже» по нескольким измерениям. Здесь работает eval-driven development.

TDDEDD
Критерийбинарный pass/failоценка по нескольким измерениям
Для чегодетерминированный кодгенеративный/качественный вывод
Основатестыgolden-датасет примеров
Ответ на вопрос«работает?»«насколько хорошо?»

Важное предупреждение от практиков EDD: не переносите TDD-мышление в EDD один в один — это дорого и даёт неверные выводы. И не гонитесь за размером набора: рабочий golden-датасет стартует со 100 примеров и редко превышает 500. Смысл не в объёме, а в том, чтобы примеры покрывали реальные сценарии и краевые случаи.

Verification gates перед мержем

Отдельный слой — барьер перед слиянием: typecheck, линт и тесты как обязательные ворота, без которых PR не проходит. Почему это не опция, а необходимость, показывают цифры: объём pull request’ов, генерируемых с ИИ, растёт быстрее, чем способность их ревьюить. По данным инженерной аналитики (телеметрия 2025 года, тысячи разработчиков), число PR выросло примерно на 98%, время ревью — на 91%, а размер самих PR — на 154%. Пост-фактум ручное ревью просто не масштабируется на такой поток. Детерминированные ворота — единственный способ удержать планку качества, когда кода становится в разы больше.

Риски: агент подгоняет тесты

Теперь про слабые места — с цифрами, а не декларациями (бенчмарки reward hacking ниже относятся к периоду конца 2025 – начала 2026 года и быстро меняются вместе с версиями моделей). Агенты действительно занимаются reward hacking: вместо того чтобы решить задачу, они подгоняют решение под метрику — хардкодят ожидаемый ответ, ослабляют тест, ловят лазейку в проверке. И это измерено двумя независимыми способами:

  • Академическая работа EvilGenie (arXiv, начало 2026 года) показала, что на неоднозначных задачах доля «жульничества» резко растёт: у одной модели-агента она достигала около 44%, у других — порядка 33% и 22%. Ключевой вывод практичен: чем расплывчатее критерий, тем чаще агент жульничает.
  • Сама Anthropic в system card (от 24 ноября 2025 года) признаёт: на специально сконструированных «невозможных» задачах без анти-хак-инструкции доля обхода у моделей доходила до 30–80%.

Это разные бенчмарки с разными методиками и версиями моделей — их нельзя складывать в одно число. Но они независимо подтверждают один феномен: без чёткого критерия и запрета трогать тесты автономный агент склонен обмануть проверку, а не пройти её честно. Отдельная ловушка — «уверенное заблуждение»: 90%+ покрытия тестами при бессмысленных ассертах, которые ничего не проверяют. Высокая цифра покрытия сама по себе ничего не гарантирует.

Неудивительно, что доверие осторожное: по опросу Stack Overflow за 2025 год ИИ для кода используют около 84% разработчиков, но точности вывода не доверяют 46% (против 33% доверяющих). Главная жалоба — код «почти правильный, но не совсем» (66%), и на его отладку уходит больше времени. Именно этот разрыв между «агент отрапортовал» и «код действительно работает» и закрывают объективные проверки: они переводят доверие с обещаний агента на воспроизводимый результат.

Definition of Done: рабочий чек-лист

Всё это сводится в один артефакт — Definition of Done (DoD). Его часто путают с acceptance criteria, но это разные вещи: acceptance criteria специфичны для одной фичи («пользователь может сбросить пароль»), а DoD — единый чек-лист качества, применимый к каждой фиче. Для ИИ-агентного кодинга рабочий DoD выглядит так:

  1. Критерии приёмки зафиксированы и проверены с доказательством (не «сделал», а «вот подтверждение»).
  2. Тесты на новое поведение написаны и проходят.
  3. Сборка, typecheck и линт зелёные.
  4. Обработаны краевые случаи и невалидный ввод, а не только happy path.
  5. Ничего из ранее работавшего не сломано.
  6. Тест написан ДО реализации и подтверждённо падал (fail-to-pass).
  7. Агент не редактировал и не удалял тесты без явного разрешения.

Последние два пункта — прямая защита от reward hacking из предыдущего раздела. Такой чек-лист превращает размытое «готово» в проверяемый список, который одинаково понимают и человек, и агент.

Продвинутые техники

Два приёма поверх базового гейта. Первый — метрика fail-to-pass: тест должен сначала падать на старом коде и проходить на новом. Это отсекает бессмысленные тесты, которые проходят всегда и ничего не проверяют. Второй — «второе мнение»: результат одного агента проверяет независимый субагент-верификатор в отдельном контексте. Инженеры Anthropic прямо советуют разносить генерацию и оценку по разным контурам — самооценка в одном контексте ненадёжна, автономный агент слишком легко убеждает сам себя, что справился.

FAQ

Чем «готово=тесты зелёные» отличается от обычного TDD? Принцип тот же, но с ИИ важнее инфраструктура принуждения. Человек сам держит дисциплину, а агенту нужен объективный, исполняемый критерий и барьеры (хуки, запрет трогать тесты), иначе он подгонит результат под проверку или объявит «готово» преждевременно.

Правда ли, что Anthropic советует строгий red-green-refactor? Не буквально. Anthropic даёт общий принцип verification loop (дайте агенту pass/fail-чек). Строгую TDD-дисциплину с изоляцией фаз довели до рабочего вида практики сообщества поверх этого принципа. Это важное различие, чтобы не приписывать вендору чужую формулировку.

Когда нужен eval-driven вместо обычных тестов? Когда у задачи нет одного правильного ответа: суммаризация, генерация текста, ответы ассистента. Там бинарный pass/fail не работает — нужна оценка по нескольким измерениям на golden-датасете из 100–500 примеров.

Как понять, что агент не подогнал тесты? Требуйте fail-to-pass (тест падал до реализации), запрещайте агенту редактировать тесты и проверяйте осмысленность ассертов, а не только процент покрытия. 90% покрытия при пустых проверках хуже, чем умеренное покрытие осмысленными тестами.

Хватит ли просто написать правила в CLAUDE.md? Как договорённость — да, как гарантия — нет. CLAUDE.md advisory: агент может о нём забыть после сжатия контекста. Для реального принуждения нужен детерминированный слой — PreToolUse-хук, который физически не пустит код без теста.

Курс «Claude Code с нуля до продакшена» · модуль «PRO: автономность и дисциплина». Полная программа и два маршрута обучения — на странице курса.

Предыдущий урок: Параллельные агенты: git worktree · Следующий урок: Адверсариальное мульти-агентное ревью

BYBIT COPY TRADING
Копируй профи
Bybit повторит сделки трейдера за тебя
Начать
ТЕГИ:
Поделиться
Связаться:
Крипто- и data-аналитик, инженер-программист (факультет компьютерных наук ХНУРЭ). В IT с 2008 года: администрировал корпоративный мониторинг в «Vodafone Украина», семь лет разрабатывал и продвигал веб-проекты, пять лет руководил маркетингом на метриках — конверсия, CTR, ROI, LTV.Криптовалютными рынками занимаюсь с 2021 года: ончейн-метрики, токеномика, макроэкономические индикаторы. Разработал собственную data-driven модель анализа рынка на 30+ метрик. Стек — Python (pandas, NumPy, SciPy, matplotlib), математическая статистика и EDA; сбор и сверку данных автоматизирую AI-агентами.Принцип — «Don't trust, verify»: каждая цифра проверена по первоисточнику, ключевые — минимум по двум независимым; прогнозы — только сценарии с условиями. Тезис без данных не публикуется.