← Spec-driven development: the spec is the prompt
05 / 07 · 45 min

Iterating specs with agents

Where drift between spec and code comes from, the re-sync ritual with an auditor agent, and choosing between regeneration and a targeted patch.

Lesson content is currently available in Russian.

What you will learn

  • →Распознавать три источника drift: хотфиксы мимо спеки, самодеятельность агента, правки на ревью.
  • →Проводить re-sync: аудит расхождений спеки и кода силами агента с таблицей вердиктов.
  • →Выбирать между регенерацией модуля из спеки и точечной правкой по радиусу поражения.

Анатомия drift

Drift — накапливающееся расхождение между спекой и фактическим поведением кода. Он не случается одномоментно; он просачивается тремя типовыми путями.

Первый — хотфикс мимо спеки. Ночью упал экспорт на отчёте с эмодзи в названии колонки; дежурный за десять минут добавил санитизацию заголовков и выкатил. Поведение системы изменилось — спека об этом не знает. Через месяц агент, регенерируя модуль по спеке, честно уберёт санитизацию, и баг вернётся. Второй путь — самодеятельность агента. На этапе implement агент «улучшил» решение: добавил три ретрая с экспоненциальной задержкой, которых нет в контракте. Звучит безобидно, но теперь тайм-аут наружу — 40 секунд вместо описанных в спеке пяти, и об этом не знает ни спека, ни автор. Третий — правки на ревью: ревьюер попросил переименовать статус partial в incomplete в ответе API, автор поправил код и забыл спеку. Мелочь — пока другой агент не сгенерирует клиент этого API по спеке.

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

Агент-аудитор: ритуал re-sync

Хорошая новость: сверка спеки с кодом — идеальная работа для агента. Это чтение, сопоставление и отчёт — без права записи. Ритуал re-sync выглядит так: регулярно (перед началом новой итерации по фиче или раз в спринт) агент получает спеку и код и строит таблицу расхождений. Промпт-шаблон:

Прочитай specs/001-csv-export/spec.md и реализацию
в src/reports/export/. Построй таблицу расхождений
по трём категориям:
1) в спеке есть, в коде нет;
2) в коде есть, в спеке нет;
3) прямое противоречие (укажи строки и критерий).
Ничего не исправляй. По каждой строке — предложение:
обновить спеку или обновить код.

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

Результат ритуала — короткий PR: правки спеки одним коммитом, правки кода другим, каждая строка таблицы закрыта вердиктом. Полчаса в спринт против недели археологии, когда через полгода спеке перестанут верить. Спека, которой верят, — это спека, которую регулярно сверяют.

Изменение начинается со спеки

Re-sync лечит уже случившийся drift, но зрелый процесс предотвращает его: любое намеренное изменение поведения начинается с diff спеки. Заказчик просит «добавить в экспорт колонку с НДС» — первым артефактом становится не код, а правка spec.md: новый критерий AC-7 с форматом колонки, обновлённое ограничение совместимости со старыми выгрузками, помеченный на удаление устаревший пункт.

Этот порядок разворачивает знакомый конвейер в миниатюре: spec diff → обновление плана (появилась ли новая зависимость?) → новые задачи → implement. Для мелких правок конвейер сжимается до минут, но порядок сохраняется. Выгода конкретна: diff спеки — лучший формат обсуждения изменения. Три изменённые строки контракта ревьюятся за минуту и до того, как написан код; спор «а надо ли НДС отдельной колонкой или в сумме» происходит над спекой, где его цена — ноль строк переделки.

Версионирование при этом даёт git: тег или хеш коммита спеки фиксирует, какой контракт был в силе на момент релиза. Если API публичный, критические изменения критериев помечаются в спеке явно (breaking) — это сырьё для changelog и семантической версии. Антипаттерн, который этот порядок убивает: «сделаем быстренько, спеку допишем после ревью». После ревью правится код по замечаниям, спека забывается — и вы снова в первой секции этого урока.

Регенерация или точечная правка

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

Первая ось — радиус поражения изменения. Новая колонка в CSV — локальная правка: одна функция, один тест, регенерировать модуль ради этого странно. Изменение модели («экспорт становится асинхронным, с очередью и уведомлением») режет через весь модуль — точечные правки такого масштаба оставляют шрамы: мёртвые ветки, полуперенесённые абстракции, комментарии из прошлой жизни. Здесь регенерация из спеки даёт более чистый результат. Вторая ось — накопленный drift. Если модуль давно правился мимо спеки, регенерация уничтожит все незадокументированные фиксы — тот самый хотфикс с эмодзи. Правило безопасности: регенерировать можно только после re-sync, когда всё ценное из кода легализовано в спеке.

Перед регенерацией — три проверки: re-sync проведён и таблица закрыта; тесты по критериям (AC-N) зелёные до и обязаны быть зелёными после — они и есть сеть безопасности; регенерация идёт в отдельной ветке с полным diff-ревью, а не поверх рабочей. При соблюдении этих условий регенерация перестаёт быть азартной игрой: спека полная, тесты сторожат контракт, diff показывает цену. Именно к этому состоянию — «модуль можно перегенерировать в любой момент» — и стремится SDD: это операциональное определение того, что спека действительно является источником истины.

Practice

Re-sync на живом модуле

Возьмите модуль своего проекта, у которого есть спека или хотя бы её черновик из прошлых упражнений. Прогоните ритуал re-sync: дайте агенту спеку и код, получите таблицу расхождений по трём категориям, вынесите вердикт по каждой строке (обновить спеку / обновить код / обсудить) и оформите закрывающий PR с раздельными коммитами для спеки и кода.

Deliverable

Таблица расхождений с вердиктами по каждой строке и PR: коммит с правками спеки отдельно от коммита с правками кода.

Checkpoint

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

  • ✓ Первым шагом назван re-sync: хотфикс легализуется в спеке до любой регенерации.
  • ✓ Названы предохранители: зелёные тесты по критериям до и после, отдельная ветка, diff-ревью.
  • ✓ Объяснён выбор регенерации по радиусу поражения, а не по привычке.

Check yourself

Какой из сценариев — типичный источник drift?

01Какой из сценариев — типичный источник drift?

Почему в промпте агента-аудитора стоит запрет «ничего не исправляй»?

02Почему в промпте агента-аудитора стоит запрет «ничего не исправляй»?

Чем опасна регенерация модуля из спеки при накопленном drift?

03Чем опасна регенерация модуля из спеки при накопленном drift?

По какому главному признаку выбирают регенерацию вместо точечной правки?

04По какому главному признаку выбирают регенерацию вместо точечной правки?

Sources

Iterating specs with agents · Spec-driven development: the spec is the prompt · VORCL