Как валидировать проектные требования перед передачей ИИ-агенту

ИИ-агент читает требования буквально. Если в спецификации есть неопределённость, он галлюцинирует недостающий контекст и тратит бюджет на догадки. Качество входа становится качеством выхода — без амортизации.

Как валидировать проектные требования перед передачей ИИ-агенту

Живой разработчик получает тикет «ускорьте каталог» и идёт спрашивать. В курилке, в личку, на дейли. Он додумывает: знает, что каталог у нас на PostgreSQL, что прошлый раз сломались на импорте, что «ускорить» в этой компании значит p99, а не среднее. Половину требований он достраивает из доменного опыта команды, и никто этого не замечает.

ИИ-агент получает тот же тикет и, если в процессе нет шага уточнения, начинает писать код по буквальному тексту задачи.

Через три недели на ретро звучит «ИИ не тянет архитектуру». Это неправда. Он реализовал наиболее вероятную интерпретацию неполного описания.

Неопределённость расходует контекст и бюджет выполнения

Если в спецификации осталась неопределённость, противоречие или непокрытый сценарий, агент не останавливается и не спрашивает. Он выбирает один из вариантов — и строит на нём всё остальное. Некорректный код в этом раскладе ещё удачный исход: хуже, когда агент начинает галлюцинировать недостающий контекст и достраивать архитектуру вокруг выдуманного допущения.

Часть контекста и итераций тратится на восстановление незафиксированных предпосылок. Затем эти предположения попадают в код и начинают восприниматься как часть требования: сгенерированный код становится источником правды о требовании, которого никогда не существовало.

К этому добавляется разрыв между тикетом и мессенджерами. Формально требование лежит в Jira. Фактически половина смысла ведётся в трёх тредах Slack, куда агент не ходит. На код-ревью обсуждать становится нечего, кроме диффа: спорить о том, правильно ли решена задача, нельзя — задача не была сформулирована так, чтобы её можно было решить неправильно.

Три недели в сторону — это не сбой модели. Это следствие отсутствия проверки требований перед началом разработки.

Стандарты инженерии требований применимы и к работе с агентами

Инженерия требований разбиралась с этим задолго до появления агентов. ISO/IEC/IEEE 29148, пришедший на смену IEEE 830, сегодня считается основным международным стандартом в области требований; рядом стоят рекомендации BABOK. Промышленный ландшафт вокруг него — специализированные системы управления требованиями: ReqView, IBM Engineering Requirements Management DOORS Next, Siemens Polarion ALM, Jama Connect. Все они делают одно и то же базовое движение: хранят требование как отдельную сущность с идентификатором, связями и историей изменений.

В нерегулируемых командах такие практики часто воспринимались как избыточная документация. Пока требования читали люди, слабая формулировка компенсировалась разговором. Стандарт был страховкой.

При работе с агентом неявный контекст компенсируется хуже, если он не включён в промпт, спецификацию или доступные источники. Классические критерии качества требований получают новый практический смысл: они перестают быть документационной гигиеной и становятся спецификацией входа для системы, у которой нет доступа к неформальным командным обсуждениям.

Восемь критериев в оптике агента

Атомарность требования. Требование содержит одну законченную функцию или бизнес-правило. Комплексная формулировка — прямой источник ошибок: если попросить агента одновременно сделать регистрацию, отправку сообщений и блокировку аккаунта, возрастает риск, что агент пропустит деталь в одном из шагов или смешает логику разных компонентов. Разбиение на подзадачи снижает число зависимостей, которые агент должен удерживать одновременно.

Однозначность и ясность. «Быстрая загрузка» и «удобный интерфейс» в спецификации для агента недопустимы. Формулировку «загрузка должна быть быстрой» он интерпретирует на своё усмотрение — и это выливается в выбор неподходящих библиотек или отсутствие ограничений там, где они критичны. Вместо прилагательного — численная метрика, контракт взаимодействия или технический параметр: максимальное время отклика API на заданном перцентиле.

Проверяемость и тестируемость. Критерии приёмки дают агенту проверяемый способ подтвердить, что задача решена. Если требование описано как измеримый алгоритм с понятным результатом, агент может работать через тесты: сам написать проверку и сам прогнать код на соответствие. Измеримый критерий выглядит так: «выгрузка ≤ 15 минут для 50k SKU», «CSV в s3://…», «без PII». Неизмеримый выглядит как «выгрузка должна работать быстро и корректно».

Полнота. Агент не может надёжно учитывать ограничения и сценарии, которые не попали в доступный контекст. Если описан только позитивный сценарий нажатия кнопки, а сетевые ошибки, повторные клики, валидация и краевые случаи опущены — агент либо оставит эти зоны необработанными, либо напишет наивную реализацию. Для критичных сценариев нужно описать позитивные, ошибочные и граничные состояния. Для контроля полноты в организациях используют шаблоны спецификаций на базе 29148 — SRS, BRS и прочие, с обязательными разделами и атрибутами требований.

Непротиворечивость и согласованность. Взаимоисключающие указания в файлах правил, системных промптах и ТЗ часто приводят к наиболее заметным ошибкам: перезаписи решений, коллизиям и зацикливанию. Противоречивый контекст даёт перезапись кода по кругу и зацикливание: агент может поочерёдно следовать конфликтующим указаниям. Лечится централизованным хранением требований с версионированием и трассировкой изменений — этим занимаются корпоративные ALM-платформы, синхронизируя требования между аналитиками, архитекторами, разработчиками и тестировщиками.

Прослеживаемость. Агенту нужна связь между бизнес-целью, контрактами API, структурой базы и конкретными файлами репозитория. Чёткая идентификация требований помогает ему ориентироваться в проекте и не ломать смежные модули. Особенно важно это при нескольких агентах, работающих параллельно: если требование связано с пользовательской историей, архитектурным решением, тест-кейсами и коммитами, агент определяет область изменений и не разносит побочные эффекты по всему проекту.

Осуществимость и необходимость. Требование должно быть реализуемо в текущем стеке и архитектурных ограничениях. И оно должно быть нужно: избыточная функциональность, не работающая на бизнес-цель, замусоривает контекст и повышает риск ошибок. Лишнее требование увеличивает объём контекста и повышает риск ошибок в связанных задачах.

Входная проверка требований

Критерии не работают, если не встроены в процесс принятия тикета в разработку.

Тикет не идёт в разработку без цели, scope и проверяемых критериев приёмки — это clarify gate. Тикет возвращается на уточнение, если в нём нет цели, границ и проверяемых критериев. Механику я собирал на Jira: бот перехватывает тикет, задаёт уточняющие вопросы по осям — scope, акторы, данные, нефункциональные требования, зависимости, критерии приёмки — и не отпускает задачу в работу, пока ответы не закрывают эти оси. Код открыт: jira-clarify-bot — воспроизводимый след механики и контракт webhook'ов.

Качество уточнений зависит не только от шаблона вопросов, но и от доступного проектного контекста. Универсальный вопрос «Какие системы затронуты?» бесполезен — на него отвечают «ну, каталог и поиск», и неопределённость остаётся там же. Вопрос, основанный на проектном контексте, звучит иначе: «SLA витрины p99 200 ms — это жёсткое ограничение и для пакетной выгрузки тоже?» На такой вопрос нельзя ответить общими словами.

Разница между этими двумя вопросами — контекст проекта, разложенный по слоям. L1 — project bible, компактный документ о системе. L2 — корпус материалов проекта. L3 — граф Jira: связи задач, эпиков, прошлых решений. Из этих слоёв собирается context pack, на котором вопросы становятся конкретными.

С другой стороны барьера стоит спецификация фичи. Наивный подход к генерации кода часто сводится к одному крупному промпту: после нескольких итераций становится трудно понять структуру изменений, а откат обходится дороже. Spec-driven подход разворачивает порядок: сначала спецификация, потом план, потом контракты, и только потом код. Маркер [NEEDS CLARIFICATION] фиксирует место, где требуется уточнение, и не даёт заменить его неявным допущением: место, где неизвестно, обязано быть помечено, а не заполнено догадкой. Каталог contracts/ появляется до реализации. Отдельный шаг анализа гоняет петлю согласованности spec ↔ plan ↔ tasks — это превращает критерий непротиворечивости в автоматическую проверку. Инструментарий — spec-kit; как это выглядит на живом проекте, видно в ytrader-bybit.

Ответственность аналитики, архитектуры и QA

Валидация требований требует участия продукта, архитектуры и QA.

Аналитик и продукт закрывают неявные допущения. Задача — перевести бизнес-потребность в структурированный документ, где выписаны логические правила, бизнес-ограничения и пользовательские пути. Единые шаблоны и чек-листы на базе 29148 помогают выявить неоднозначности до передачи задачи в разработку.

Архитектурная проверка фиксирует границы модулей, данных и интерфейсов. Требования жёстко фиксируют границы модулей, схемы данных, паттерны проектирования и контракты интерфейсов. Для API это означает contract-first: сначала описание в OpenAPI, потом реализация. Линтер Spectral ловит неоднозначности и нарушения корпоративных правил оформления прямо в спецификации, до начала реализации; Prism проверяет соответствие реальных запросов и ответов контракту. Для автономно работающего агента отклонение от спецификации обнаруживается сразу, а не на приёмке.

QA переводит критерии приёмки и граничные условия в тест-кейсы, проверки контрактов и сценарии регрессии. На качественных требованиях исчерпывающий набор тест-кейсов может собрать и инженер, и сам агент — а дальше автоматически сверить реализацию с контрактами.

Где это ломается

Сам по себе гейт не гарантирует качество требований.

Галлюцинированные требования. Модель, уточняя спецификацию, охотно дописывает то, чего никто не просил, и формулирует это уверенно. Если уточнения принимаются без человеческого approve, в спецификации заводится фактура из ниоткуда — и её потом добросовестно реализуют.

Формальное согласование без проверки содержания. Ответы получены, оси закрыты, критерии приёмки записаны словами «система должна работать корректно». Гейт пройден, фальсифицируемости нет. Процесс считается пройденным, хотя требование остаётся непроверяемым.

Устаревший project bible. Context pack частично собирается из L1, и когда L1 отстал от системы на полгода, вопросы становятся уверенно неправильными. Вопрос, основанный на устаревшем SLA, может быть хуже универсального вопроса — он подтверждает несуществующее ограничение.

Дублирование уточнений. Бот спрашивает в тикете, команда параллельно обсуждает то же самое в Slack, и снова появляются две конкурирующие версии требования. Разрыв, который гейт закрывал, восстанавливается сбоку.

Со стороны спецификации набор ломающихся мест свой. Спецификация, написанная только для соблюдения процесса: файл написан, потому что положено, а код пишется от промпта. Drift после реализации: спецификация зафиксирована, реализация изменилась, а спецификация не была обновлена, и никто не синхронизировал. Слишком крупная функциональность, где спека честно описывает три месяца работы и перестаёт быть проверяемой. Контракты без версий. Двойная правда, когда одно и то же ограничение записано в спеке и в файле правил агента — по-разному. И избыточные накладные расходы: гонять полный цикл спецификации ради исправления опечатки — способ убить процесс на второй неделе.

Есть и общее ограничение. В публикациях по применению LLM к инженерии требований описывается, что LLM могут помогать находить отдельные нарушения критериев качества требований по 29148, но результат требует проверки человеком и предлагают улучшенные формулировки. Поэтому автоматическая предварительная проверка требований может быть полезной как вспомогательный шаг. Полезным, а не решённым. Модель, проверяющая требования, — участник процесса, а не его гарантия.

Минимальные шаги для внедрения

Заведите гейт на входе в разработку: тикет без цели, scope и фальсифицируемых критериев приёмки не берётся в работу. Это должно быть правилом процесса, а не рекомендацией. Проверяйте критерии на измеримость подстановкой числа: если вместо «быстро» нельзя написать «≤ 15 минут для 50k SKU», требование не готово.

Соберите контекст проекта в слои. Без project bible и корпуса материалов любые уточняющие вопросы будут общими, а общие вопросы дают общие ответы. Назначьте владельца L1 и фиксируйте дату последнего обновления по фактическому состоянию системы — протухший контекст опаснее его отсутствия.

Для API используйте contract-first как обязательное правило, кроме явно согласованных исключений. Спецификация до кода, линт спецификации до реализации, проверка реализации на соответствие контракту. Агенту нужен контракт как единственный источник правды об интерфейсе, иначе агент может сгенерировать интерфейс, не совпадающий с ожиданиями системы.

Для фич — спека до кода, с явными маркерами [NEEDS CLARIFICATION] там, где неизвестно. Резать фичу до размера, при котором спека остаётся проверяемой. И хранить каждое ограничение в одном авторитетном источнике: одно ограничение живёт в одном месте, иначе агент будет исполнять оба варианта по очереди.

На ретро сначала проверяйте качество входных требований, а уже потом обсуждайте ограничения модели. Пока входные требования не проходят через барьер, разговор о том, тянет ли ИИ архитектуру, — обсуждение не приведёт к управляемому улучшению процесса.

Требования всегда определяли результат. Просто раньше между плохим требованием и плохим кодом стоял человек, который молча закрывал разрыв собой. При передаче задачи агенту этот человеческий буфер уменьшается или исчезает. Нефиксированные допущения агент заменит собственной интерпретацией — и эта интерпретация может не совпасть с ожиданиями команды.

Leave a Reply

Your email address will not be published. Required fields are marked *