AI сгенерировал код. Почему до готового продукта ещё далеко
AI сгенерировал код. Почему до готового продукта ещё далеко
Сегодня получить работающий фрагмент кода стало проще. Можно описать задачу, получить реализацию, запустить сборку и через несколько минут увидеть новый экран или успешный ответ API.
Именно в этот момент возникает опасная иллюзия: раз функция работает, значит продукт почти готов.
На практике между «код выполняется» и «версию можно передать заказчику» находится отдельный инженерный контур. В него входят проверка требований, интеграций и негативных сценариев, воспроизводимая сборка, установка на чистой машине, контроль состава поставки и фиксация результатов проверок.
Я столкнулся с этим при разработке локального enterprise-продукта для QA. AI-инструменты действительно ускоряли реализацию отдельных функций. Но чем ближе проект подходил к состоянию коробочной поставки, тем меньше пользы было от ещё одной быстро созданной возможности и тем больше значения получали воспроизводимость, проверяемость и приёмка.
Эта статья не о том, что AI пишет плохой код. Генерация кода и принятие продукта просто решают разные задачи.
Что на самом деле подтверждает 200 OK
Представим, что новый endpoint возвращает 200 OK, страница открывается, а контейнер имеет статус healthy. Это подтверждает, что реализация выполнилась в конкретном окружении и в проверенном сценарии. Но из успешного ответа ещё не следует, что функция соответствует исходному требованию, не нарушает соседние сценарии и предсказуемо ведёт себя при ошибках.
Мы также ничего не узнали о воспроизводимости сборки. Неизвестно, запустится ли тот же комплект на чистой машине, не зависит ли он от старого состояния базы данных или локально установленной библиотеки. Успешный запуск на машине разработчика нередко говорит лишь о том, что продукт работает на машине разработчика.
Отдельный вопрос — что именно войдёт в поставку. В исходном коде может не быть секретов, но старый конфигурационный файл окажется в staging-каталоге, тестовые данные попадут во frontend bundle, а журнал с токеном — в evidence-архив. Проверка исходников и проверка готового пакета — не одно и то же.
Для внутреннего прототипа такой неопределённости иногда можно не придавать большого значения. Для банковской, финтех- или другой enterprise-среды этого недостаточно. Продукт становится готовым к приёмке не тогда, когда автор уверен, что всё работает, а когда заявленный результат можно независимо повторить и проверить.
Почему AI усиливает иллюзию готовности
AI особенно хорошо справляется с локальными задачами, у которых есть понятный вход и ожидаемый выход. Создать обработчик API, добавить форму, написать SQL-запрос, собрать Dockerfile или исправить конкретную ошибку — всё это можно достаточно точно описать в одном запросе.
Продукт, однако, состоит не только из таких задач. Между компонентами существуют контракты, состояния и ограничения, которые редко помещаются в один prompt.
Рассмотрим импорт файла лицензии. Форма может выглядеть исправной, принимать файл и показывать сообщение об успехе. Но настоящее поведение функции определяется не только этим экраном. Нужно понять, кто является источником истины для статуса лицензии, что произойдёт при повторном импорте, как система отреагирует на повреждённую подпись и сохранит ли доступ к ранее созданным данным после истечения лицензии. Не менее важно проверить, не остаётся ли содержимое файла в браузере или логах, фиксируется ли операция в журнале аудита и одинаково ли ведут себя UI и API.
Каждый компонент по отдельности способен работать корректно, а ошибка при этом будет находиться на границе между компонентами или в состоянии, которое не встретилось в основном сценарии.
Есть и другая причина. Модель выполняет сформулированную задачу. Если попросить её «добавить кнопку экспорта», она, скорее всего, добавит кнопку. Но такая формулировка ничего не говорит о разграничении доступа, формате имени файла, детерминированности порядка данных, работе через реальный reverse proxy и отсутствии чужих данных в выгрузке. Проблема здесь не в модели, а в неполном определении готовности.
Когда версию действительно можно принимать
Под готовым к приёмке продуктом я не имею в виду систему без дефектов. Таких систем не существует. Речь идёт о версии с определёнными границами: известно, какие функции в неё входят, какие ограничения остаются и какие сценарии сознательно не поддерживаются. Если разработчик и заказчик проверяют разные представления о составе версии, честная приёмка невозможна.
Затем каждое критическое утверждение о продукте переводится в наблюдаемую проверку. Если заявлено, что система устанавливается офлайн, работает без внешней сети, ограничивает доступ при недействительной лицензии или не содержит приватных ключей, наличие соответствующего кода ещё ничего не доказывает. Нужен запуск на конкретном артефакте в заданных условиях.
Результат должен быть воспроизводимым. Другой инженер берёт тот же комплект, выполняет описанные действия и получает сопоставимое поведение. Для коробочного продукта это означает как минимум чистую установку, первый запуск, прохождение основного сценария и корректное удаление.
Наконец, от проверки должны остаться доказательства. Фраза «всё проверено» не позволяет установить, что именно запускалось и на какой сборке. Хэш передаваемого файла, журнал установки, HTTP-запрос и ответ, запись аудита, manifest состава поставки и отчёт сканирования связывают вывод с конкретной версией. Evidence не устраняет доверие полностью, но делает его предмет понятным.
Одна функция от генерации до приёмки
Удобнее всего показать этот процесс на обычной задаче — экспорте чек-листа. В исходном виде постановка звучит просто: «добавить экспорт чек-листа». Для генерации кода этого достаточно, для приёмки — нет.
Сначала задача превращается в наблюдаемый результат. Авторизованный пользователь должен экспортировать чек-лист активного проекта в PDF, DOCX и XLSX. Сервер обязан вернуть корректные Content-Type и Content-Disposition, экспорт объекта другого проекта должен быть запрещён, а полученные файлы — открываться стандартными приложениями. Новые внешние сервисы в поставке появиться не должны.
Такое описание сразу меняет работу с AI. Модель получает не только просьбу написать код, но и границы допустимого изменения. Можно отдельно запретить изменение схемы авторизации, добавление нового сервиса и перестройку соседних страниц. Чем меньше и точнее diff, тем легче проверить его фактическое воздействие.
После генерации источником истины становится не объяснение модели, а сам diff. Нужно увидеть, какие файлы изменились, появились ли новые зависимости и не затронуты ли публичные контракты. Важно проверить, не добавлены ли fallback-значения, тестовые ключи или временная диагностика, а также не отключена ли существующая проверка ради прохождения успешного сценария. Объяснение может звучать убедительно и при этом не совпадать с реализацией.
Затем запускается основной сценарий: пользователь открывает свой проект, выбирает чек-лист и получает файл. Но один успешный экспорт подтверждает только happy path. Следующая серия проверок направлена на предсказуемый отказ. Запрос выполняется без авторизации, с идентификатором объекта другого проекта, с пустыми данными и при недоступности одной из зависимостей. Отдельно проверяется повтор операции: он не должен оставлять частично записанное состояние, дублировать данные или раскрывать детали исключения.
На этом функция работает, но поставка ещё не проверена. Приложение пересобирается, после чего исследуется уже результат сборки. Именно здесь можно обнаружить значение переменной окружения во frontend bundle, тестовый fixture в архиве или лишний каталог, захваченный упаковочным скриптом. Если используются контейнеры, проверять приходится и экспортированные образы: удалённый из текущего слоя файл способен сохраниться в предыдущем слое.
Следующий рубеж — чистая машина или эквивалентное изолированное окружение. На ней нет старых образов, кэшей, сохранённых credentials, вручную созданных каталогов и локальных зависимостей. Если установка проходит только после устного пояснения автора или ручного копирования файла, перед нами ещё не готовая коробочная поставка.
После выполнения сценария сохраняются результаты. Хороший evidence позволяет установить, что проверялось, на каком артефакте, в каких условиях, каким способом и с каким итогом. Один файл PASS.txt этого не обеспечивает. Нужна связь с версией поставки, её хэшем, сценарием и сырым журналом выполнения.
При этом evidence сам становится частью передаваемого комплекта. Его тоже нужно проверить на пароли, токены, приватные ключи, персональные данные и лишние внутренние пути. Доказательство проверки не должно создавать новую утечку.
Короткая матрица перед передачей версии
Полноценную стратегию качества нельзя заменить одной таблицей. Но перед передачей кандидата она помогает быстро увидеть, где утверждение о готовности пока держится только на уверенности команды.
Область | Вопрос | Что подтверждает результат |
|---|---|---|
Границы версии | Понятно ли, что реализовано и что не поддерживается? | Scope, acceptance criteria, known limitations |
Реализация | Просмотрены ли фактические изменения и зависимости? | Зафиксированный diff и review |
Поведение | Проверены ли основной сценарий и ожидаемые отказы? | Результаты функциональных и негативных тестов |
Интеграции | Проверено ли поведение через реальные контракты? | HTTP-, DB- или event-evidence |
Поставка | Воспроизводятся ли сборка и установка на чистой машине? | Build log и clean install report |
Состав и безопасность | Известно ли, что передаётся, и проверен ли пакет на секреты и лишние файлы? | Manifest, SHA-256 и scan report |
Главная особенность этой матрицы в том, что ответ «да» без подтверждающего артефакта не считается полным ответом.
Может ли AI проверить собственный результат
AI полезен и на стороне проверки. Он способен провести предварительный review, предложить негативные сценарии, найти несогласованности, разобрать логи, подготовить тестовые команды и сравнить реализацию с критериями приёмки. Он также помогает собрать черновик отчёта из уже полученных результатов.
Но окончательный вывод должен опираться на наблюдаемое состояние системы. Если одна и та же модель написала код, придумала тест, интерпретировала его результат и объявила PASS, независимость такого контроля ограничена.
Это не означает, что для каждого AI-generated commit нужен отдельный отдел проверки. Разделение можно обеспечить инженерными средствами. Тест выполняется через публичный интерфейс, состояние сверяется с базой данных или журналом событий, команды запускаются в чистом окружении, а сырые результаты сохраняются до составления вывода. В такой схеме AI помогает анализировать доказательства, но не подменяет их собственным описанием.
Особенно важны детерминированные проверки. Хэш либо совпал, либо нет. Запрещённый запрос либо вернул ожидаемый статус, либо прошёл. Чистая установка либо завершилась по документированной инструкции, либо потребовала незаявленного действия. Чем меньше итог зависит от свободной интерпретации, тем надёжнее приёмка.
Как изменилось моё понимание прогресса
В начале разработки главным признаком движения было количество работающих возможностей. Новый экран, endpoint или экспорт выглядели как законченный результат. По мере подготовки реальной поставки фокус сместился.
Стало важнее понимать, какая сборка является текущим кандидатом, чем она отличается от предыдущей и какие проверки выполнены именно на ней. Пришлось отдельно сопоставлять файлы в evidence с фактически передаваемым комплектом, проверять установку без устных пояснений и искать в итоговых артефактах следы разработки, которых не должно быть у заказчика.
После этого новая функция перестала считаться завершённой сразу после появления в UI. Теперь её путь выглядит так: требование превращается в критерий приёмки, затем выполняется ограниченное изменение, просматривается diff, проверяются успешные и негативные сценарии, пересобирается продукт, исследуется итоговый артефакт, выполняется чистая установка и только после этого принимается решение по версии.
AI остаётся внутри этой цепочки и ускоряет несколько её этапов. Он помогает быстрее перейти от требования к реализации, быстрее увидеть подозрительное изменение и быстрее подготовить проверки. Но саму цепочку он не отменяет.
Вывод
AI существенно сократил расстояние от идеи до работающего кода. Расстояние от работающего кода до продукта, готового к приёмке, осталось инженерной задачей.
Для прототипа бывает достаточно показать функцию. Для enterprise-поставки необходимо определить границы версии, проверить критические утверждения на конкретном артефакте, воспроизвести результат в чистом окружении и сохранить доказательства.
Поэтому после вопроса «работает ли код?» стоит задать второй: «Какое утверждение о продукте мы сейчас доказали и на каком артефакте?»
Если конкретного ответа нет, перед нами ещё не принятый продукт, а рабочая версия, которой предстоит пройти инженерную приёмку.