Зачем документация, если агент читает код напрямую

Контекстное окно на два миллиона токенов — не повод хоронить документацию. Без спецификации агент не отличит фичу от бага и запечатает ошибку тестом.

Зачем документация, если агент читает код напрямую

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

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

Почему код не заменяет спецификацию

Вывод «код — это Single Source of Truth» растёт из узкого взгляда на разработку: будто она сводится к написанию исходников. Если рассматривать SDLC только как этап написания исходников — и да, код кажется абсолютным источником правды. Но как только в инженерный процесс встроен автономный или полуавтономный агент, агент начинает выводить требования из реализации и затем проверять реализацию ею же.

Разница проста и она архитектурная. Исходный код описывает механику — то, как система работает прямо сейчас. Документация и спецификации описывают намерение, intent — то, как система должна работать и какие бизнес-ограничения она закрывает. Код отвечает на «как», спецификация отвечает на «зачем». Это два разных слоя, и второй из первого не выводится.

Когда агент проектирует решение, делает рефакторинг или пишет тесты, опираясь исключительно на код, он попадает в логическую ловушку. Если в коде лежит ошибка, неоптимальный костыль или скрытый баг — агент принимает это за намеренное поведение системы. Без внешнего источника контекста он физически не способен отделить фичу от бага. Всё, что написано, для него — эталон.

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

Постановка задачи: где агент ошибается из-за недостатка контекста

Разработка начинается не с коммита, а с постановки задачи. В нормальном процессе инженер читает тикет, сопоставляет его с архитектурой, задаёт уточняющие вопросы. Когда та же задача поступает агенту, его первая функция — не генерация pull request, а валидация требований. Он должен сначала понять, что ему разрешено, и только потом писать.

Если у агента нет базы знаний со спецификациями, ADR и бизнес-правилами — и на этой фазе начинаются сбои, которые выглядят как галлюцинации, а на деле являются нехваткой контекста.

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

Второе — конфликт с архитектурным замыслом. Агент предлагает рабочее, но чужеродное решение: добавляет прямой запрос к базе там, где по гайдлайну положено идти через шину событий. Локальная проверка проходит, но архитектурный инвариант нарушается.

Актуальная документация — OpenAPI, ADR, C4-модели или просто структурированный Markdown в репозитории — превращает первый шаг агента в предварительный аудит задачи. Он сверяет новое ТЗ с существующими Architecture Decision Records и бизнес-правилами. Нашёл конфликт — отклоняет задачу или запрашивает уточнение у архитектора до того, как переписаны сотни строк. Заодно документация подсказывает, какие модули затрагивает изменение: контекст локализуется, агент получает меньший и более релевантный контекст.

Как тесты закрепляют ошибочную реализацию

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

Дай агенту задачу покрыть модуль интеграционными тестами или проверить его после рефакторинга. И разверни два сценария рядом.

Сценарий без документации. Агент анализирует функцию calculate_discount(). В коде из-за ошибки прошлых разработчиков скидка при определённом условии начисляется дважды. Агент считает это нормальным поведением — так ведь написано в коде. Он пишет тест, который утверждает и запечатывает баг: assert calculate_discount() == double_discount. Тесты проходят. Система сломана, автоматика рапортует об идеальном покрытии.

Сценарий со спецификацией. Агент читает бизнес-требование: «Скидка не может превышать 15% и не суммируется с промокодами». Сравнивает требование с кодом calculate_discount(). Обнаруживает расхождение между намерением и реализацией. Дальше — либо локализует и чинит баг, либо генерирует падающий тест, подсвечивающий проблему инженеру.

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

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

Документация как машинно-проверяемый интерфейс

Чтобы всё это работало, документация обязана измениться. Водянистые Wiki-страницы, которые никто не открывал годами, бесполезны одинаково — и людям, и LLM. Барьером от ошибок становится не текст «для галочки», а три рабочих формы.

Executable specs — выполняемые спецификации. OpenAPI и Swagger, AsyncAPI, JSON Schema, Protobuf. Агент использует их как формальные ограничения: код не может выйти за границы схемы, он к ней притянут.

ADR — Architecture Decision Records. Короткие маркдаун-файлы прямо в репозитории, вроде docs/adr/0004-use-nats-for-messaging.md, объясняющие, почему принято то или иное решение. Именно это помогает агенту не нарушить принятое архитектурное решение, сломав фундаментальный паттерн: он видит не только правило, но и причину правила.

Living Documentation — живая документация, которую CI/CD валидирует так же строго, как код. Спецификация разошлась с API — сборка падает. Ровно тот же принцип работает и на слое поведения: eval-набор становится критерием релиза против решений, пригодных только для демонстрации, отсекая «на моей машине работает» до продакшна. Разложить это в реальном репозитории можно и без абстракций — цепочка specify → clarify → plan → tasks, каталог .specify/ с конституцией репозитория (шаблоны плюс память устойчивых решений) и отдельный eval-harness как обязательный критерий допуска к релизу. Публичные примеры такого каркаса лежат открыто: github.com/dobryakov/ytrader-bybit и github.com/dobryakov/eval-harness.

Стек валидации

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

Слой Что валидирует Фаза SDLC
Спецификация и ТЗ Намерение Постановка задач
Исходный код Реализацию Написание кода
Автотесты Поведение E2E / интеграция

Убери верхний слой — и нижние два начинают проверять сами себя, то есть не проверять соответствие реализации исходному намерению.

Кто в этой системе ставит задачу

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

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

Вопрос «зачем документация, если агент читает код» на самом деле звучит иначе: кто в этой системе ставит задачу — и по чему её потом можно проверить.

Leave a Reply

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