Agent Dev 101

Модуль 16 · Урок 16.8

Урок 16.8. Концепции: персистентность спек, сложные фичи, spec of specs

На этой странице
  1. Зачем это нужно
  2. Основная идея
  3. Модели хранения спецификаций
  4. Сложные фичи
  5. Spec of specs: процедура
  6. Практика
  7. Краткое резюме
  8. Вопросы для самопроверки
  9. Что дальше
  10. Источники

Зачем это нужно

Процессы (уроки 16.3-16.7) отвечают на вопрос «какие команды запускать». Остаются два практических вопроса, на которые документация отвечает концептуальными страницами:

  • что происходит со спеками потом? SDD-процесс порождает spec.md, plan.md, tasks.md - но требования меняются, и Spec Kit сознательно не предписывает, как команда сохраняет и мутирует артефакты после этого;
  • что делать с большими фичами? Длинные фичи часто проходят specify/plan/tasks гладко и разваливаются на /speckit.implement - модель теряет план, игнорирует задачи, галлюцинирует.

Третья страница - «spec of specs» - дает систематический ответ на крайний случай второго вопроса: декомпозицию эпика в дорожную карту независимых спек.

Основная идея

Документация фиксирует три именованные модели хранения спек (flow-back, flow-forward, living spec) - команда выбирает модель явно, ни одна не является дефолтом или требованием Spec Kit. Для больших фич - лестница из четырех стратегий по нарастанию overhead: ограничить охват задач, делегировать саб-агентам, скомбинировать, разложить фичу на меньшие спеки.

Модели хранения спецификаций

Spec Kit намеренно оставляет командам контроль над судьбой spec.md, plan.md и tasks.md после смены требований. Тулкит дает повторяемый workflow, но не навязывает стратегию сопровождения артефактов. Страница называет три распространенные модели, чтобы выбор стал явным.

Два отдельных вопроса

У спек-ориентированной разработки есть временной вопрос: как долго спецификация должна иметь значение? Обзор SDD-инструментализации Мартина Фаулера frames этот жизненный цикл тремя уровнями:

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

Spec Kit поднимает второй вопрос: что происходит с набором артефактов при смене требований? Его и описывают модели ниже - стратегии мутации.

Flow-back spec

Все артефакты - spec.md, plan.md, tasks.md и реализация - могут информировать друг друга. Правки могут начинаться в любом артефакте: разработчик обновляет tasks.md в ходе реализации, ревизует plan.md после технического открытия, корректирует spec.md после продуктового уточнения. Команда вручную reconcil-ит набор, чтобы итоговая история проекта сходилась.

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

Главный риск - молчаливое расхождение: если нижние артефакты меняются без отражения решения в spec.md, будущие контрибьюторы не знают, какому артефакту верить.

Flow-forward spec

Каталог каждой завершенной фичи остается исторической записью. Завершенные артефакты неизменяемы; при смене требований создается новый каталог фичи, а старый остается полезным для аудита, сравнения и объяснения, как проект пришел к текущему состоянию.

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

Главный trade-off - дублирование: связанные решения расползаются по нескольким каталогам, нужны привычки именования, линковки и ревью, чтобы происхождение читалось легко.

Living spec

spec.md - контракт, остальные артефакты - производные. Команда сначала обновляет spec.md, затем регенерирует или ревизует plan.md и tasks.md из источника. План и задачи ценны, но считаются одноразовыми производными, а не постоянными источниками правды.

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

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

Выбор модели

Модель - командная конвенция, не настройка CLI. Проект может использовать разные модели в разных областях - пока контрибьюторы знают, какая где действует.

Модель Правило мутации Лучше всего Осторожно с
Flow-back spec править любой артефакт, затем сводить быстрая итерация, тесная коллаборация молчаливый дрейф артефактов
Flow-forward spec новые требования - новый каталог фичи аудит-след, историческая ясность дублированный/фрагментированный контекст
Living spec править spec.md; производные регенерировать спека как контракт потеря обоснований в регенерированных файлах

Если модель еще не выбрана, ответьте на два вопроса:

  1. Каталоги завершенных фич - исторические записи или редактируемые рабочие области?
  2. spec.md - единственный источник правды, или plan.md и tasks.md могут быть равноправными источниками?

Когда ответы ясны - задокументируйте конвенцию в конституции проекта или командном онбординге, чтобы будущие контрибьюторы знали, как обрабатывать изменения.

Сложные фичи

Большая или сложная фича часто проходит /speckit.specify, /speckit.plan, /speckit.tasks гладко и деградирует на реализации. Посреди длинного /speckit.implement агент начинает терять план, игнорировать задачи, галлюцинировать - обычно прямо перед или после триггера компакции контекста.

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

/speckit.implement принимает свободный ввод, который агент обязан учесть перед продолжением, - значит, скопировать прогон можно без изменений тулинга.

Вариант 1: ограничить задачи на вызов

Вместо прогона по всем задачам скажите остановиться раньше:

text
/speckit.implement only execute tasks T001-T010, then stop and report progress

или скопируйте фазой:

text
/speckit.implement only execute the Setup phase, then stop

Выполненные задачи помечаются [X] в tasks.md, поэтому следующий вызов продолжит с места остановки. Так каждый прогон остается в пределах контекста.

Вариант 2: саб-агенты

Если ваш coding-агент поддерживает саб-агентов (например, GitHub Copilot CLI или расширение Copilot для VS Code), поручите /speckit.implement делегировать отдельные задачи:

text
/speckit.implement delegate each parallel [P] task to a sub-agent

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

Вариант 3: комбинировать

Для очень больших фич объедините скопирование и делегирование:

text
/speckit.implement execute only the Core phase, delegate [P] tasks to sub-agents

Вариант 4: декомпозиция в меньшие спеки

Когда даже одна фаза переполняет контекст, разбейте фичу на независимо специфицируемые под-фичи. Каждая получает собственные spec.md, plan.md, tasks.md и проходит собственный цикл specify/plan/tasks/implement.

Это подход «spec of specs»: первый проход разбивает массивную фичу на меньшие самодостаточные спеки, каждая из которых реализуется без перегрузки модели. Добавляет больше всего overhead - бережите его для фич, которые иначе не удержать.

Что выбрать

Подход Лучше для
Ограничить N задач или фазой любой агент; проще всего; саб-агенты не нужны
Делегирование саб-агентам агенты с поддержкой саб-агентов; максимум параллелизма
Скопирование + делегирование большие фичи на агентах с саб-агентами; баланс обоих
Декомпозиция в меньшие спеки когда даже одна фаза переполняет контекст

В большинстве случаев простейшее решение - ограничить охват задач на прогон. К делегированию переходите, когда агент его поддерживает и нужен параллелизм; к декомпозиции - только когда одна фаза все еще не влезает в один прогон.

Spec of specs: процедура

Когда фича слишком велика для единственного цикла /speckit.specify -> /speckit.plan -> /speckit.tasks -> /speckit.implement без потери моделью нити посреди реализации, разбейте ее в roadmap меньших, независимо специфицируемых под-фич. Один предварительный проход декомпозирует массивную фичу в самодостаточные спеки; каждая проходит собственный цикл.

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

Проход roadmap

До любой под-спеки - один проход декомпозиции, дающий roadmap. Это легковесный планировочный разговор с агентом, не полная спека:

  1. Сформулируйте фицу целиком. Опишите эпик в одном-двух предложениях, чтобы агент видел всю картину.
  2. Найдите независимые слайсы. Пусть агент предложит небольшой набор под-фич, каждая delivers целостный кусок эпика и специфицируется сама по себе. Цельтесь в слайсы, независимые по тестируемости: реализация одного должна оставлять что-то демонстрируемое.
  3. Проведите границы. Для каждого слайса - строка намерения и явная граница охвата: что входит, что отложено в соседний слайс. Резкие границы удерживают каждую под-спеку в пределах контекста.
  4. Упорядочьте по зависимостям. Отметьте, какие слайсы зависят от других; пререквизиты - раньше. Независимые слайсы можно строить в любом порядке; для параллельной стройки используйте отдельные worktree, чтобы у каждого прогона было изолированное состояние активной фичи.
  5. Запишите roadmap. Зафиксируйте слайсы в durable-файле дорожной карты (ниже), чтобы каждая будущая под-спека могла ссылаться на него.

Roadmap намеренно мелкая: она называет и упорядочивает под-фичи, но не проектирует их. Дизайн случится, когда каждый слайс пройдет собственный /speckit.specify.

Артефакт roadmap

Roadmap - обычный Markdown-файл, который вы авторите и держите под версионным контролем; за ним нет специального тулинга. Кладите туда, где его найдут под-спеки:

  • для эпика в рамках фичи: specs/<epic-slug>/roadmap.md;
  • для крупного сквозного эпика: верхнеуровневый ROADMAP.md.

Каждая запись несет стабильный ID (якорь для будущего линкинга), имя, намерение, границу охвата, зависимости, статус и - когда под-спека существует - ссылку на нее. Минимальный шаблон:

markdown
# Roadmap: <epic name>

<One or two sentences: what the epic is and why it is being decomposed.>

**Status legend**: planned · in-progress · done

| ID | Sub-feature | Intent | Scope boundary | Depends on | Status | Sub-spec |
|----|-------------|--------|----------------|-----------|--------|----------|
| R1 | <name>      | <one line> | <in / deferred> | —      | planned | — |
| R2 | <name>      | <one line> | <in / deferred> | R1     | planned | — |
| R3 | <name>      | <one line> | <in / deferred> | R1     | planned | — |

Колонку ID держите неизменной с момента, как на запись ссылается под-спека, - это якорь трассируемости. Заполняйте Sub-spec путемми к каталогам под-фич по мере создания и обновляйте Status по мере продвижения.

Спецификация каждой под-фичи

С roadmap в руках работайте по записям по одной, обычным флоу Spec Kit:

  1. Возьмите следующую запись, чьи зависимости уже done (или отсутствуют).
  2. Запустите /speckit.specify только для этого слайса, описывая лишь его намерение и границу из записи roadmap. Слайс ограничен - его спека, план и задачи остаются в контекстном окне.
  3. Прогоните /speckit.plan, /speckit.tasks, /speckit.implement для слайса как обычно.
  4. Пометите запись done и переходите к следующей.

Каждый слайс - полная независимая фича Spec Kit со своими spec.md/plan.md/tasks.md. Roadmap - то, что связывает их вместе.

Линковка под-спек к roadmap

Чтобы охват и намерение не дрейфовали между прогонами, каждая под-спека ссылается на свою запись roadmap, и roadmap ссылается обратно - простая, greppable, двунаправленная конвенция:

  • Под-спека -> roadmap. В spec.md под-фичи назовите родительский roadmap и ID записи в строке Input:

    markdown
    **Input**: Parent roadmap: `specs/<epic>/roadmap.md` → entry **R3**. <feature description>
    
  • Roadmap -> под-спека. В таблице roadmap проставьте в Sub-spec каталог под-фичи, например specs/<epic>-part-3/.

Оба направления - обычный текст: любой под-спекой можно проследить к ее месту в эпике (и найти соседей) быстрым поиском - без тулинга и схем метаданных.

Синхронизация roadmap и под-спек

Roadmap - живой документ. По мере узнавания нового держите его и под-спеки согласованными:

  • Сначала roadmap, затем reconcil. Когда охват смещается, обновите запись roadmap, затем затронутые под-спеки. Roadmap - источник правды о разбиении эпика.
  • Уважайте зависимости и порядок. Если слайс зависит от другого - стройте пререквизит первым и скрестите ссылки зависимой под-спеки, чтобы отношение было видно с обеих сторон.
  • Рекурсия, когда слайс все еще велик. Если под-фича не специфицируется за цикл - дайте ей собственный roadmap и декомпозируйте глубже; тот же подход работает уровнем ниже. Рекурсия добавляет overhead - углубляйтесь ровно настолько, насколько требует проблема контекста.

Разобранный пример

Эпик - «self-service billing portal»: клиенты смотрят инвойсы, управляют способами оплаты и меняют планы без поддержки. Слишком велик для одного цикла; roadmap-проход разбивает его на три слайса.

specs/billing-portal/roadmap.md:

markdown
# Roadmap: Self-service billing portal

Let customers view invoices, manage payment methods, and change plans without
contacting support. Too large for one cycle, so it is split into independent slices.

**Status legend**: planned · in-progress · done

| ID | Sub-feature        | Intent                                   | Scope boundary                              | Depends on | Status  | Sub-spec |
|----|--------------------|------------------------------------------|---------------------------------------------|-----------|---------|----------|
| R1 | Invoice history    | Customers view and download past invoices | Read-only; no payment actions               | —         | done    | specs/billing-invoices/ |
| R2 | Payment methods    | Add, remove, and set a default card       | No plan changes; assumes invoices exist     | R1        | in-progress | specs/billing-payment-methods/ |
| R3 | Plan changes       | Upgrade/downgrade the subscription plan   | Uses R2's default payment method            | R1, R2    | planned | — |

Каждый слайс специфицируется сам по себе. Например, spec.md под-фичи R2 открывается обратной ссылкой:

markdown
# Feature Specification: Billing — payment methods

**Input**: Parent roadmap: `specs/billing-portal/roadmap.md` → entry **R2**.
Let customers add, remove, and set a default payment method in the billing portal.

Читатель трассирует R2 к roadmap, видит зависимость от R1 (уже done) и что R3 ждет ее. Стройка R1 -> R2 -> R3 держит каждый прогон малым, а roadmap сохраняет форму всего эпика.

Автоматизация (опционально)

Если хочется автоматизировать фиксацию roadmap и проверки консистентности, community-расширение Spec Roadmap исследует это направление. Это стороннее расширение и оно не обязательно - ручной конвенции выше достаточно самой по себе.

Практика

  1. Определите модель хранения спек для своего проекта: ответьте на два вопроса выбора и впишите конвенцию в конституцию проекта (/speckit.constitution).
  2. Возьмите большую фичу из бэклога и примените лестницу стратегий: сначала ограничение задач, затем - при необходимости - делегирование. Зафиксируйте, на какой ступени качество реализации перестало деградировать.
  3. Для эпика, который не удерживается даже пофазно, сделайте проход roadmap: напишите таблицу с границами слайсов и зависимостями, затем специфицируйте первый слайс с обратной ссылкой Input.

Краткое резюме

Три концептуальные страницы связывают процессы Spec Kit с реальной эксплуатацией. Модели хранения (flow-back - править все и сводить; flow-forward - новые требования в новый каталог; living spec - править спеку, производные регенерировать) - командная конвенция, не настройка CLI. Для больших фич - лестница по нарастанию overhead: ограничить охват прогона, делегировать саб-агентам, скомбинировать, декомпозировать в roadmap независимых спек с двунаправленной текстовой линковкой.

Главное из урока:

  • Spec Kit не предписывает модель мутации артефактов - выбор фиксируется явно, лучше в конституции;
  • деградация длинных прогонов - это контекстное окно; лечение - скопировать прогон свободным аргументом /speckit.implement;
  • выполненные задачи [X] в tasks.md - механизм возобновления между прогонами;
  • roadmap - обычный Markdown под версионным контролем: ID записи - якорь трассируемости, границы слайсов держат спеки малыми;
  • рекурсивная декомпозиция допустима, но каждый уровень добавляет overhead.

Вопросы для самопроверки

  1. Чем временной вопрос (spec-first / spec-anchored / spec-as-source) отличается от вопроса стратегии мутации артефактов? К какой оси относятся три модели урока?
  2. Назовите главный риск flow-back и главный trade-off flow-forward. Для какой команды living spec - естественный выбор?
  3. Опишите симптомы деградации длинного /speckit.implement и их причину. Почему симптомы возникают около компакции контекста?
  4. Как работает возобновление между ограниченными прогонами реализации? Что в tasks.md это обеспечивает?
  5. Перечислите пять шагов прохода roadmap. Почему roadmap не проектирует слайсы?
  6. Как устроена двусторонняя линковка под-спек и roadmap? Почему достаточно обычного текста без метаданных?

Что дальше

Процессы и концепции агента закрыты. Урок 16.9 переключается на терминальную сторону: справочник core-команд CLI specify, экспериментального MCP-сервера и аутентификации для приватных каталогов.

Источники

Обновлено 03.10.2026