Spec-first, spec-anchored или spec-as-source: сколько должна жить спецификация

Spec-first, spec-anchored и spec-as-source — три модели отношений между спецификацией и кодом после начала реализации. Они отвечают не на вопрос «нужна ли спека», а на более практичный: какой артефакт остаётся источником истины, когда продукт меняется.
В spec-first спецификация ведёт к первой реализации, а затем главным становится код. В spec-anchored спека и код развиваются вместе. В spec-as-source спецификация остаётся первичным артефактом, из которого генерируется значимая часть реализации.
Эти модели описаны в документации GitHub Spec Kit. Выбор влияет на review, документацию, генерацию кода и стоимость drift. Практический контекст самого подхода разобран в статье о spec-driven development, а граница между процессом и готовой основой проекта — в сравнении GitHub Spec Kit и Application Skeleton.
Spec-first: спецификация как стартовый контракт
В модели spec-first команда сначала фиксирует ожидаемое поведение и план, затем реализует фичу. После выпуска код становится основным источником истины, а исходная спека сохраняет исторический контекст решения.
Модель подходит, если:
- фича небольшая и имеет ограниченный срок жизни;
- код и тесты достаточно ясно выражают текущее поведение;
- продукт быстро исследует направление;
- поддержка не требует отдельного нормативного документа;
- спецификацию дорого синхронизировать с частыми мелкими изменениями.
Главный риск — воспринимать старую spec как актуальную. Если документ остаётся рядом с проектом, его статус должен быть явным: implemented, superseded или historical. Иначе следующий агент выберет красивое описание вместо реального поведения.
Spec-anchored: спека как долговечный ориентир
В spec-anchored код и спецификация остаются связанными после релиза. Изменение наблюдаемого поведения требует обновить оба артефакта. Спека объясняет контракт и цель, тесты доказывают часть поведения, код реализует его.
Эта модель полезна для:
- core user journeys;
- публичных API и интеграционных контрактов;
- прав доступа и security boundaries;
- бизнес-правил, которые трудно восстановить по implementation details;
- продукта с передачей между разработчиками или агентами;
- функций, по которым принимаются продуктовые решения.
Spec-anchored не означает, что каждая строка кода описывается в prose. Спека держит наблюдаемый контракт: входы, результаты, ошибки, исключения и acceptance criteria. Названия локальных функций и мелкий refactoring остаются в коде.
Главный риск — drift. Он снижается процессом: review проверяет spec-conformance, Definition of Done требует actualisation, а pull request связывает изменение с конкретным разделом контракта.
Spec-as-source: спецификация генерирует систему
В spec-as-source изменение начинается в формальном описании, а код или другие артефакты генерируются из него. Знакомые примеры принципа — OpenAPI для клиента и server stubs, schema для типов и validators, declarative infrastructure для состояния окружения.
Модель оправдана, когда:
- формат достаточно строгий для машинной обработки;
- несколько потребителей должны получить согласованные артефакты;
- ручная синхронизация регулярно создаёт ошибки;
- генератор стабилен и является частью build;
- generated output не редактируется вручную.
Свободный Markdown редко становится полным spec-as-source: в нём слишком много семантики, которую нельзя однозначно превратить в код. Практичнее комбинировать уровни: продуктовая spec остаётся spec-anchored, а OpenAPI или schema работает как source для конкретного технического контракта.
Почему «одна модель на весь репозиторий» неудобна
Разные артефакты имеют разную цену рассинхронизации. Для disposable experiment достаточно spec-first. Контракт авторизации лучше держать spec-anchored. API types можно генерировать из schema.
Полезнее выбрать модель по типу решения:
- Feature intent: spec-first для эксперимента, spec-anchored для core flow.
- API shape: spec-anchored или spec-as-source.
- Database schema: migrations и schema-код как executable source, ADR для причин нетривиального решения.
- UI details: design tokens и компоненты являются source; feature spec фиксирует состояния и доступность.
- Operations: runbook spec-anchored, infrastructure definition — spec-as-source там, где это поддерживает платформа.
Как выбрать модель до начала фичи
Ответьте на пять вопросов.
Кто будет читать контракт после релиза?
Если никто, кроме автора одноразового эксперимента, spec-first может быть достаточным. Если контракт нужен support, QA, следующему агенту или внешнему интегратору, он должен оставаться актуальным.
Можно ли восстановить намерение по тестам и коду?
Тест доказывает конкретный пример, но не всегда объясняет, почему исключение разрешено. Чем больше скрытого продуктового контекста, тем полезнее spec-anchored.
Сколько потребителей у одного формата?
Если schema должна одновременно кормить frontend types, backend validation и документацию, генерация снижает drift. Один потребитель не всегда оправдывает собственный генератор.
Как обнаруживается рассинхронизация?
Если ответ «на встрече или после бага», процесс слабый. Нужна проверка в review, CI или генерации. Spec-anchored без actualisation быстро превращается в spec-first с неясным статусом.
Как отменяется решение?
У документа должен быть lifecycle: active, implemented, superseded, archived. Новая spec ссылается на заменённую, а не переписывает историю так, будто старого контракта не существовало.
Минимальный процесс actualisation
Для spec-anchored фичи достаточно короткого обязательного цикла:
- Перед реализацией зафиксировать наблюдаемое поведение и открытые вопросы.
- В plan назвать файлы, tests и docs, которые изменятся.
- При discovery обновить spec до продолжения реализации, если изменился контракт.
- В review сравнить diff не только с tasks, но и с acceptance criteria.
- После зелёных gates обновить status и связанные docs.
- При замене контракта отметить superseded и дать ссылку на новый.
Это дешевле, чем поддерживать параллельную документацию «на всякий случай», и надёжнее, чем надеяться, что следующий разработчик восстановит намерение по коммитам.
Итог
Spec-first оптимизирует старт и сохраняет исторический контекст. Spec-anchored сохраняет долговечный продуктовый контракт. Spec-as-source устраняет ручную синхронизацию там, где формальное описание может надёжно генерировать артефакты.
Хорошая система использует все три модели осознанно и всегда показывает статус документа. Нужен процесс спецификаций, который не превращается в архив устаревшего Markdown? Опишите текущий workflow — можно определить модель для каждого типа контрактов и добавить actualisation в quality gates.