Зелёный билд, не та задача: соглашение для Java-команд с ИИ-агентами
Grok и GPT спорят: 12% контекста или враньё про зелёные тесты
Автор из Explyt пересказывает вебинар Сергея Поспелова от 28 сентября о том, как командам на Java работать с ИИ-агентами в JetBrains IDE. Разбираются три способа потерять полдня: расплывчатая задача, переполненный чат с несколькими тикетами и слепое доверие отчёту агента «все тесты проходят». Решение — писать спецификацию вместе с агентом, сначала фиксировать тесты по критериям приёмки, а проверку делать программой или вторым агентом с чистым контекстом. Материал не привязан к конкретному агенту и содержит пример спецификации и JUnit-тестов для Spring Boot-сервиса. Порядок работы меняется: тесты пишутся до кода.
Материал основан на вебинаре 28 сентября и написан для Java-разработчиков, которые уже используют ИИ-агентов. Автор работает в Explyt, делающей ИИ-агента для IDE от JetBrains, а текст пересказывает выступление её сотрудника Сергея Поспелова, из которого убрано всё, что имеет смысл только внутри одного продукта. Главная мысль: качество работы агента зависит от того, насколько он понимает проект и насколько точно понимает задачу, и эти половины описывают отдельными документами. Свежий чат уже тратит около двенадцати процентов окна контекста на системный промпт, список инструментов и файл AGENTS.md из репозитория. Где-то между пятьюдесятью и восемьюдесятью пятью процентами использования ответы ухудшаются, а на девяноста девяти модель перестаёт отвечать. Все три ошибки ниже — способы впустую истратить это окно. Первая — недоописанная задача. Просьба «добавь тесты» превращается в юнит-тесты для одного класса, хотя нужен был сквозной сценарий оформления заказа. Агент не соврал, он заполнил пробел самым вероятным прочтением. Лечится на стороне человека: назвать класс и слой, дать ссылку на задачу и держать конвенции проекта в AGENTS.md. Вторая — переполненный чат: одна сессия на три часа и несколько несвязанных тикетов. К четвёртому тикету агент применяет шаблон из первого к коду из третьего, и дифф выглядит правдоподобно. Помогает один чат на задачу, дробление большой задачи и сжатие чата только тогда, когда нужная часть точно переживёт его. Третья — доверие к отчёту агента. Он пишет «все тесты проходят, реализация готова», ревьюер кивает, а через неделю баг оказывается в продакшене. Агенты щедро оценивают свою работу, поэтому проверять должна программа — тесты, линтер, сборка — или второй агент со свежим контекстом, желательно модель другого вендора. Формулировка со слайда: код выглядел правильно, и агент звучал уверенно, но оба утверждения говорят о подаче, а не о поведении. Отсюда переход к спецификации. Документ о проекте — это AGENTS.md в корне репозитория: команды сборки, структура модулей, конвенции тестов, то есть всё, что верно для любой задачи. Документ о задаче — спека, и писать её самому не обязательно: агент в режиме планирования читает код, задаёт вопросы и готовит черновик, который вы правите и утверждаете. В статье приведён пример для Spring Boot-сервиса с ограничением частоты запросов: контекст, цель, требования, раздел «вне области», дизайн, критерии приёмки в виде чекбоксов и план. Раздел «вне области» мешает агенту построить распределённый лимитер просто потому, что он может. Дальше порядок фиксирован: агент пишет тесты, вы их утверждаете, агент пишет код, агент прогоняет тесты и повторяет, пока они не позеленеют. Каждый пункт критериев приёмки превращается в тест, и тесты существуют раньше реализации. В примере они написаны на JUnit с MockMvc под Spring Boot 3.3, с заглушками контроллера и фильтров. Отмечается практическая деталь: @WebMvcTest регистрирует только контроллер и то, что вы явно импортируете, поэтому оба фильтра и привязка свойств указываются вручную, а без @EnableConfigurationProperties контекст не загрузится, так как фильтру нечего внедрять в конструктор. Свойство с лимитом на уровне класса снижает порог до трёх, чтобы класс целиком проверял переопределение настройки, а циклы оставались короткими и медленный CI не успевал пополнить корзину токенов. Правила описаны так, чтобы работать с любым агентом, который у команды уже установлен.