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
Sources