Как собрать семантику проекта для кодового агента: четыре файла вместо Confluence

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

Главное
  • Для небольшого репозитория достаточно четырёх файлов: index.md, domain.md, contracts.md и спецификации активной фичи
  • domain.md хранит термины и инварианты, например правило «отклонённая попытка не расходует квоту»
  • В PR достаточно двух правил: изменился публичный API — обнови contracts.md, изменился инвариант — обнови domain.md и тест
Схема структуры agent-context из четырёх файлов рядом с кодом проекта
Фото: Хабр: ИИ

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

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

Это не обязательно проблема модели. Автор материала формулирует так: она дала агенту код, но не дала намерение. Решение — обзорный вариант практики Spec-Driven Development (SDD) для небольшого репозитория. Не RAG, не корпоративная база знаний, а четыре коротких файла, которые помогают агенту понять проект до первого изменения.

Что такое семантика проекта

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

Это похоже на SDD, но в уменьшенном масштабе. Документация GitHub Spec Kit описывает SDD как процесс, в котором намерение фиксируется до реализации и уточняется в несколько шагов. Копировать весь workflow не нужно: для маленького проекта достаточно сделать намерение доступным агенту и связать его с тестами.

Минимальный набор файлов

Рядом с кодом предлагается положить структуру agent-context/ с файлами index.md, domain.md, contracts.md и папкой features/ со спецификациями. У каждого файла одна работа: index.md ведёт от типа задачи к исходникам, domain.md хранит термины и инварианты, contracts.md фиксирует то, что видит внешний вызывающий код, а features/*.md описывает границы и критерии готовности фичи.

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

Пример из domain.md: недельный лимит считается на пользователя, а не на API-ключ и не на IP-адрес; отклонённая из-за лимита попытка не расходует квоту; неделя начинается в понедельник в 00:00 UTC. Эти три строки полезнее для агента, чем ещё один пересказ app/limits.py. Первая задаёт границу агрегации, вторая — поведение на отказе, третья — правило времени. Все три должны быть проверяемы тестами.

Как собрать контекст за вечер

Начинать с генерации документации моделью не стоит — иначе быстро получится аккуратный пересказ package-lock.json. Автор советует посмотреть пять вещей: точку входа и дерево модулей, файл зависимостей и команду запуска тестов, публичный API или CLI, две-три показательные интеграционные проверки и последнюю нетривиальную фичу в истории изменений.

Из них можно собрать навигацию, имена модулей и внешний контракт. Но смысл правила «отказ не расходует квоту» из кода надёжно не извлекается — его должна записать та, кто знает предметную область. Фильтр простой: если предложение можно без потери восстановить из исходника, не копируйте его в agent-context, дайте путь к модулю в index.md. Если после рефакторинга утверждение всё ещё обязано быть верным, ему место в domain.md или в спецификации фичи.

Как этим пользуется агент

Весь репозиторий в первый запрос отправлять не нужно. Агенту дают короткий маршрут: перед изменением прочитать agent-context/index.md; для задачи про лимиты прочитать domain.md, contracts.md и features/weekly-limit.md, затем открыть названные там исходники и тесты. Сначала сопоставить каждый критерий готовности с тестом, а публичный контракт не менять без обновления contracts.md.

Польза не в волшебном промпте. Маршрут заставляет сначала прочитать правила, а потом ограничивает поиск нужной частью репозитория. Если агент предлагает поменять тип результата, он видит, что это уже не локальная правка.

Что автоматизировать, а что нет

Для маленького проекта достаточно двух правил в PR: изменился публичный API — обновите contracts.md; появился или изменился инвариант — обновите domain.md и тест. Автоматизировать имеет смысл только очевидное, например сравнение сгенерированного OpenAPI с закоммиченной схемой. CI, который требует переписать документацию после переименования переменной, превратит контекст в ритуал, который все обходят стороной.

Спецификацию разовой фичи после merge можно удалить. Если в ней остался постоянный инвариант, его переносят в domain.md или contracts.md. Spec Kit тоже не предписывает единую судьбу артефактам спецификации после изменения требований.

Где подход заканчивается

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

Здесь можно смотреть в сторону OpenViking — контекстной базы для агентов, которая объединяет знания, память и skills в виртуальной файловой системе. В ней агент сначала читает короткий abstract каталога, затем overview и только потом исходные материалы. Идея близка к index.md, но масштаб другой: вместо четырёх файлов появляются сервер, индексация и отдельный слой хранения контекста.

Для pet-проекта ставить OpenViking только ради того, чтобы агент нашёл два теста, автор не советует. Но когда контекст живёт дольше одной фичи, у агента есть память между сессиями, а источников уже много, такая система становится осмысленным следующим шагом. Начинать с RAG, графа зависимостей и автономного оркестратора необязательно: сначала стоит ответить на вопрос, сможет ли новый человек за десять минут понять, что прочитать перед изменением лимита.

Для профиТехнические детали: архитектура, цифры, ссылки

Структура agent-context/ в мини-примере:

  • index.md — маршрутизация от типа задачи к исходникам и тестам;
  • domain.md — термины и инварианты без деталей реализации;
  • contracts.md — внешне наблюдаемое поведение без внутренних классов и SQL;
  • features/weekly-limit.md — границы и критерии готовности активной фичи.

Инварианты из примера domain.md: лимит считается на пользователя, а не на API-ключ или IP; отклонённая попытка не расходует квоту; неделя начинается в понедельник в 00:00 UTC.

Автоматизация в PR: обновление contracts.md при изменении публичного API, обновление domain.md и теста при изменении инварианта. Для CI подходит сравнение сгенерированного OpenAPI с закоммиченной схемой.

Ссылки из материала: GitHub Spec Kit (What is Spec-Driven Development?, Development notes), OpenViking (Context Database).

Вопросы и ответы

Сколько файлов нужно для семантики проекта?
Для небольшого репозитория достаточно четырёх: index.md, domain.md, contracts.md и спецификации активной фичи в features/.
Что хранить в domain.md?
Только термины и инварианты, которые должны пережить рефакторинг, без деталей реализации.
Когда стоит переходить на OpenViking?
Когда контекст живёт дольше одной фичи, у агента есть память между сессиями, а источников уже много.