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 фичи достаточно короткого обязательного цикла:

  1. Перед реализацией зафиксировать наблюдаемое поведение и открытые вопросы.
  2. В plan назвать файлы, tests и docs, которые изменятся.
  3. При discovery обновить spec до продолжения реализации, если изменился контракт.
  4. В review сравнить diff не только с tasks, но и с acceptance criteria.
  5. После зелёных gates обновить status и связанные docs.
  6. При замене контракта отметить superseded и дать ссылку на новый.

Это дешевле, чем поддерживать параллельную документацию «на всякий случай», и надёжнее, чем надеяться, что следующий разработчик восстановит намерение по коммитам.

Итог

Spec-first оптимизирует старт и сохраняет исторический контекст. Spec-anchored сохраняет долговечный продуктовый контракт. Spec-as-source устраняет ручную синхронизацию там, где формальное описание может надёжно генерировать артефакты.

Хорошая система использует все три модели осознанно и всегда показывает статус документа. Нужен процесс спецификаций, который не превращается в архив устаревшего Markdown? Опишите текущий workflow — можно определить модель для каждого типа контрактов и добавить actualisation в quality gates.

Есть похожая задача?

Опишите её — предложим решение и оценку. Бесплатно.