Перейти к содержимому
Программа SDDSDD.1 Идея SDD

Что такое разработка через спецификации

Почему ИИ-агенту для кода нужен продуманный план, что такое SDD и спецификация, три уровня подхода по Биргитте Бёккелер (spec-first, spec-anchored, spec-as-source), что в SDD нового по сравнению с требованиями, BDD и model-driven development, когда он окупается — и как устроена программа.

УРОКsdd/sdd-1-idea/01-what-is-sdd.mdx1 ч 30 минУрок 1 из 2
После урока вы сможете
  • Объяснить, что ломается при «вайб-кодинге» с агентом и какую задачу решает разработка через спецификации
  • Отличить спецификацию от плана и задач и узнавать уровни spec-first, spec-anchored и spec-as-source на примерах
  • Сравнить SDD с классическими требованиями, BDD и model-driven development и назвать, что в нём действительно нового
  • Решить для конкретной задачи, нужен ли ей полный процесс SDD, лёгкая спецификация или достаточно хорошего промпта

Автор курса описывает идею этой программы так: «суть идеи в том, чтобы хорошенько пошевелить мозгами на этапе планирования, родить тонну md-файлов, а затем скормить их агенту и спокойно идти пить кофе, пока Claude перемалывает ваши спеки в рабочий код».

В этой фразе сразу и сила подхода, и его ловушки. Сила — в первой половине: продумать задачу до того, как агент написал первую строку, дешевле, чем переписывать его код. Ловушки — во второй. «Тонна» markdown-файлов, которую никто не перечитывает, — это не план, а макулатура. А кофе можно пить спокойно только тогда, когда вы заранее знаете, как проверите результат: агент не обязан делать то, что написано в спецификации, — он делает то, что счёл правдоподобным.

Разработка через спецификацииразработка через спецификации (SDD)EN Spec-Driven DevelopmentПодход к работе с ИИ-агентами для кода: сначала продумать задачу и записать её в спецификации (что и зачем, затем план и задачи), а код получать из них и проверять по ним. (Spec-Driven Development, SDD) — способ работать с ИИ-агентом для кодаИИ-агент для кодаEN AI coding agentПрограмма, в которой языковая модель в цикле читает и правит файлы проекта, запускает команды и тесты и сама решает, что делать дальше: Claude Code, GitHub Copilot, Cursor, Codex и др. как инженер: сначала договориться с собой, командой и агентом, что и зачем строим, потом — как, и только потом писать код, который проверяется по этим договорённостям. За программу вы научитесь писать спецификации, которые агент понимает однозначно, пользоваться инструментами Spec Kit и OpenSpec и проверять, что код действительно соответствует замыслу. Этот урок — вход: что такое SDD, откуда он взялся, какие у него уровни, когда он окупается и как устроена программа.

В начале 2025 года Андрей Карпатый назвал вайб-кодингомвайб-кодингEN vibe codingВыражение Андрея Карпатого (2025): писать программу в разговоре с ИИ — попросил, получил, поправил, — почти не вчитываясь в код и не фиксируя требований. Годится для прототипов, опасен для систем с правилами. (vibe coding) стиль, в котором программу пишут в разговоре с ИИ: попросил — получил — поправил — снова попросил, почти не вчитываясь в код. Для прототипа на выходные это прекрасно. Для системы, у которой есть бизнес-правила и которая будет жить годами, — нет.

Возьмём сквозной пример программ DDD и SDD — онлайн-школу (подробно она описана в уроке DDD.1.1). Попросим агента одной фразой: «Сделай на Python запись студентов на курсы с отменой и возвратом денег». Типичный результат выглядит примерно так — у вашего агента детали будут другими, но характер тот же:

from datetime import datetime
class Order: # «заказ», хотя в школе говорят «запись на поток»
def __init__(self, user_id, course_id, price):
self.user_id = user_id
self.course_id = course_id # запись на курс, а не на поток с датой старта
self.price = price # рубли числом с плавающей точкой
self.status = "active"
self.created_at = datetime.now() # время внутри модели — не протестировать
class CourseManager:
def __init__(self):
self.orders = []
def enroll(self, user_id, course_id, price):
order = Order(user_id, course_id, price) # ни вместимости, ни проверки повторной записи
self.orders.append(order)
return order
def cancel(self, order, course_start):
self.orders.remove(order) # запись удалена — история пропала
days_left = (course_start - datetime.now()).days
return order.price if days_left > 7 else order.price * 0.5 # откуда 50%?

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

Что решил агентКак на самом деле в школеПочему так вышло
записываются на курсзаписываются на конкретный поток с датой старта и вместимостьюв промпте не было слова «поток»
мест сколько угодноне больше вместимости потокаправило не названо
записаться дважды можнонельзяправило не названо
возврат, если осталось больше 7 целых сутокполный возврат при отмене за 7 суток и более (7 × 24 часа), позже — без возврата«неделю» каждый понимает по-своему
при поздней отмене — 50%возврата нетагент заполнил пробел «разумным» значением
отмена удаляет записьзапись получает статус «отменена»так короче
деньги — float в рубляхцелое число копеек и валютатак чаще пишут в интернете
время — datetime.now() внутривремя передаётся параметром, чтобы тесты были детерминированытак чаще пишут в интернете

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

Дальше начинается цикл «поправь». Вы пишете «записывают на поток, а не на курс», потом «нет, возврата 50% не бывает», потом «не удаляй запись». Каждое исправление живёт в истории чата. В новой сессии, у коллеги или у другого агента этой истории нет, и решения приходится принимать заново — иногда иначе. Создатели OpenSpec формулируют это прямо: агенты мощные, но непредсказуемые, когда требования живут только в истории чата.

Что ломается без плана, если собрать в один список:

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

СпецификацияспецификацияEN specification (spec)Документ на естественном языке о том, что должна делать система и зачем: цель, требования, сценарии, границы. Описывает поведение, а не реализацию. В SDD — главный артефакт, из которого выводятся план, задачи и код. — это документ на естественном языке о том, что должна делать система и зачем: цель, пользователи, требования, сценарии, границы, открытые вопросы. Она описывает поведение, наблюдаемое снаружи, а не реализацию: в ней нет имён библиотек и схем таблиц. Для онлайн-школы это, например, «при отмене записи за 7 суток и более до старта потока студенту возвращается полная стоимость» — и сценарий с конкретными датами, по которому это проверяется.

В SDD спецификация становится главным артефактом, а код — производным от неё. Манифест Spec Kit называет это «инверсией власти»: десятилетиями документы служили коду — их писали и выбрасывали, когда начиналась «настоящая работа»; в SDD код служит спецификации. Звучит как лозунг, но практический смысл простой: если код и спецификация расходятся, по умолчанию неправ код (или спецификацию надо осознанно поменять — сначала её, потом код).

Почти все инструменты SDD разделяют три слоя, хотя называют их по-разному:

СлойВопросЧто в нёмПример для школы
Спецификациячто и зачем?цель, истории, требования, сценарии, «вне рамок», открытые вопросы«запись закрывается в момент старта потока»; сценарий с Глебом, который опоздал
Планкак?архитектура, стек и обоснование, модель данных, контракты, решенияагрегат «Поток» (Cohort), статусы EnrollmentStatus, исключение EnrollmentClosed
Задачив каком порядке?маленькие проверяемые шаги со ссылками на требования«T-003: запрет записи после старта; требования: REQ-004»

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

flowchart LR
I["Идея<br/>одна фраза"] --> S["Спецификация<br/>что и зачем"]
S --> Q["Уточнения<br/>вопросы агента<br/>и эксперта"]
Q --> S
S --> P["План<br/>как"]
P --> T["Задачи<br/>маленькие шаги"]
T --> C["Реализация<br/>агентом"]
C --> V["Проверка<br/>тесты из сценариев,<br/>ревью диффа"]
V -->|"расхождение"| S
V -->|"готово"| D["Принято"]
Цикл SDD: от идеи через спецификацию, план и задачи к коду, который проверяется по сценариям спецификации

Обратите внимание на две обратные стрелки. Уточнения возвращают нас к спецификации до кода — это самое дешёвое место для исправлений. Проверка возвращает к спецификации после кода: если тест по сценарию упал, разбираемся, кто неправ — код или спецификация. Spec Kit, например, предлагает цикл команд constitution → specify → plan → tasks → implement → converge, где последний шаг сверяет реализацию со спецификацией, планом и задачами и дописывает задачи на то, что упущено. OpenSpec — предложение изменения, реализацию и архивирование. Детали инструментов — в модуле SDD.3.

Слово «спецификация» сейчас используют очень по-разному, и споры об SDD часто идут потому, что люди имеют в виду разное. Самая ясная классификация — в статье Биргитты Бёккелер (Thoughtworks) «Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl», опубликованной в 2025 году в серии «Exploring Generative AI» на сайте Мартина Фаулера. Бёккелер предлагает различать уровни по тому, как долго живёт спецификация и кто правит код.

1. сначала спецификациясначала спецификация (spec-first)EN spec-firstПервый уровень SDD по Биргитте Бёккелер: продуманную спецификацию пишут до кода и используют для текущей задачи. Что с ней будет после реализации, не оговаривается.. Продуманную спецификацию пишут до кода и используют для текущей задачи. После реализации её могут выбросить или просто перестать обновлять. Пример: вы написали specs/003-enrollment/spec.md, агент реализовал запись на поток, код принят. Через полгода нужен перенос записи на другой поток — вы пишете новую спецификацию, а старая лежит в папке как исторический документ и постепенно расходится с кодом. Это уже огромный шаг вперёд по сравнению с вайб-кодингом: агент работал по продуманному плану.

2. спецификация как якорьспецификация как якорь (spec-anchored)EN spec-anchoredВторой уровень SDD по Бёккелер: спецификацию сохраняют после реализации и развивают вместе с функцией — изменения сначала вносятся в спецификацию, потом в код.. Спецификацию сохраняют после реализации и используют для дальнейших изменений той же функции. Изменение начинается с правки спецификации, а код и тесты следуют за ней. Пример: в репозитории живёт specs/enrollment/spec.md — актуальное описание правил записи. Чтобы добавить перенос записи, сначала описывают изменение требований (что добавлено, что изменено), согласуют его, затем реализуют и обновляют основную спецификацию. Требования и сценарии имеют идентификаторы, тесты ссылаются на сценарии, и по спецификации всегда можно понять, как система работает сейчас.

3. спецификация как исходникспецификация как исходник (spec-as-source)EN spec-as-sourceТретий уровень SDD по Бёккелер: человек правит только спецификацию, а код целиком генерируется из неё и вручную не редактируется.. Человек правит только спецификацию — она единственный исходник, а код целиком генерируется из неё и вручную не редактируется. Пример: файл enrollment.spec.md превращается в enrollment.py с пометкой «сгенерировано из спецификации, не редактировать»; чтобы исправить ошибку, правят спецификацию и генерируют код заново. Пример инструмента, который движется в эту сторону, по описанию Бёккелер, — Tessl.

spec-firstspec-anchoredspec-as-source
Когда пишут спецификациюдо кодадо кода и при каждом изменениивсегда; код руками не пишут
Что живёт дольшекодкод и спецификация вместеспецификация
Кто правит кодагент и людиагент и люди, после спецификациитолько генератор
Цена дисциплинынизкаясредняя: спецификацию надо поддерживатьвысокая: вся логика должна быть в тексте
Главный рискспецификация устареваетспецификация и код незаметно расходятсянедетерминированная генерация, негибкость

Уровни — не оценки «плохо, лучше, отлично». Это разные договорённости, и у каждого своя цена. Интересно, что сам Spec Kit в документации (страница о моделях жизни спецификации) ссылается на эту классификацию и сознательно оставляет выбор команде: держать ли папку каждой функции как исторический документ или обновлять спецификацию как живой контракт. Мы в программе будем учиться работать в основном на уровнях spec-first и spec-anchored — они применимы уже сегодня с любым агентом.

Что здесь нового: требования, BDD, model-driven development

Заголовок раздела «Что здесь нового: требования, BDD, model-driven development»

Идея «сначала описать, потом построить» старше большинства из нас. Полезно понимать, что SDD берёт у предшественников и чем от них отличается.

Документы требований. Ещё в 1990-х существовали стандарты оформления требований к программам (например, IEEE 830 о спецификации требований, 1998). Слабое место классики — документ пишут один раз в начале, потом он устаревает, а код живёт своей жизнью. SDD наследует отсюда структуру: требования с идентификаторами, критерии приёмки, нефункциональные требования, границы.

BDD и спецификация на примерах. разработка через поведениеразработка через поведение (BDD)EN Behavior-Driven DevelopmentПрактика, которую предложил Дэн Норт в середине 2000-х: описывать поведение системы примерами «Дано / Когда / Тогда» на языке бизнеса и превращать их в автоматические тесты (инструмент Cucumber, язык Gherkin). (Behavior-Driven Development) Дэна Норта и спецификация на примерахспецификация на примерахEN specification by exampleСпособ описывать правила конкретными примерами с числами и ожидаемым результатом вместо общих фраз (книга Гойко Аджича, 2011). Примеры вскрывают неясности и затем становятся тестами. Гойко Аджича предложили описывать поведение конкретными сценариями «Дано / Когда / Тогда», которые сразу становятся автоматическими тестами. Это прямой предок критериев приёмки в SDD; сценарии мы разберём в уроке SDD.2.1. Родственная практика — разработка через тестированиеразработка через тестирование (TDD)EN Test-Driven DevelopmentПрактика Кента Бека: сначала падающий тест, потом минимальный код, чтобы он прошёл, потом рефакторинг («красный — зелёный — рефакторинг»). Тесты становятся исполняемой спецификацией.: сначала тест, потом код.

Model-driven development. разработка на основе моделейразработка на основе моделей (MDD)EN Model-Driven DevelopmentПодход, популярный в 1990–2000-х: систему описывают моделями (обычно UML), а код генерируют из них; известный вариант — Model Driven Architecture (MDA) консорциума OMG. Широко не прижился: модели оказались не проще кода, а генераторы — негибкими. обещала то же, что spec-as-source: описываем систему моделями (обычно UML), код генерируется. Широко подход не прижился: модели оказались не проще кода, генераторы — негибкими, а правки в сгенерированном коде терялись при следующей генерации. Бёккелер прямо проводит эту параллель и задаётся вопросом, не получим ли мы в spec-as-source недостатки обоих миров: негибкость MDD и недетерминизм языковых моделей.

Что действительно нового:

БылоВ SDD
«компилятор» понимал только строгий формальный язык (UML, DSL)агент понимает естественный язык, примеры и даже нечёткие формулировки
генерация детерминирована: одна модель — один кодгенерация недетерминирована: одна спецификация — разный код при каждом запуске
писать код было дорого, документы — «лишняя работа»код стал дешёвым; дорогими стали решение, что строить, и проверка
документ читает человекспецификацию читает и человек, и агент: это одновременно документ и промпт

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

Вернёмся к «кофе». Чтобы спокойно уйти от компьютера, пока агент работает, нужны три вещи: продуманная спецификация, план, который вы прочитали, и автоматическая проверка, которая скажет, что получилось. Посмотрим трезво, что SDD даёт, а чего не даёт.

Что даёт.

  • Дешёвые ошибки. Неясность, найденная в спецификации, стоит пять минут разговора. Та же неясность в коде, который уже ушёл пользователям, — инцидент и переделка.
  • Контекст для агента. Решения записаны в файлах репозитория, и их читает любой агент в любой сессии.
  • Предмет для ревью до кода. Эксперт подтверждает правила, разработчик — план; спорят о смысле, а не о строчках.
  • Определение «готово». Сценарии из спецификации становятся приёмочными тестами.
  • Параллельная работа. Хорошо нарезанные задачи можно отдать нескольким агентам или людям.

Чего не даёт — и об этом важно знать с первого дня.

  • Ложное чувство контроля. Подробная спецификация создаёт ощущение, что всё учтено. Но агент может пропустить пункт, переосмыслить его или сделать «больше, чем просили». Бёккелер пишет об этом прямо: шаблоны и чек-листы не гарантировали, что агент в её опытах будет следовать всем инструкциям.
  • Многословие. Шаблоны поощряют длинные документы. Длинную спецификацию не читает человек — и хуже использует агент: важное тонет в контексте. Ревьюить десять markdown-файлов бывает тяжелее, чем сам код.
  • Недетерминизм. Дважды запущенная генерация по одной спецификации даст разный код. Значит, проверка нужна каждый раз, а не один раз «на процесс».
  • Один процесс на всё. Полный цикл для исправления опечатки — стрельба из пушки по воробьям.
  • Ошибка в спецификации размножается быстрее. Агент добросовестно реализует неверное правило во всех местах сразу.
  • Дрейф. Код правят в обход спецификации, и через месяц непонятно, какому документу верить.

Отсюда рабочая версия девиза программы: пошевелить мозгами на этапе планирования — обязательно; markdown-файлов — ровно столько, сколько вы и агент действительно прочитаете; кофе — да, но с возвращением к тестам и диффу.

flowchart LR
H1["Человек:<br/>спецификация<br/>и ответы на вопросы"] --> A1["Агент:<br/>план"]
A1 --> H2["Человек:<br/>ревью плана"]
H2 --> A2["Агент:<br/>реализация по задачам<br/>и тесты"]
A2 -.->|"здесь можно пить кофе"| A2
A2 --> H3["Человек:<br/>отчёт тестов,<br/>ревью диффа"]
H3 -->|"расхождение"| H1
Где в SDD работает человек: спецификация, ревью плана, проверка результата. Кофе — только на шаге реализации

Когда SDD окупается, а когда это бюрократия

Заголовок раздела «Когда SDD окупается, а когда это бюрократия»

Создатели OpenSpec называют свой принцип «постепенной строгостью» (progressive rigor): по умолчанию — лёгкая спецификация из коротких требований, границ и нескольких проверок; полная — только для рискованных изменений: между командами, в контрактах, миграциях, безопасности. Это хороший ориентир для любого инструмента.

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

Простая проверка: если задачу можно объяснить одной фразой и проверить глазами за минуту, спецификация не нужна. Если в задаче есть правила с числами, статусы, сроки или она займёт больше одной сессии агента — нужна.

Подробно инструменты разобраны в модуле SDD.3; здесь — только чтобы узнавать названия. Имена команд и папок — по README и документации репозиториев, проверено в октябре 2026 года; инструменты меняются быстро, сверяйтесь с источником.

ИнструментЧто этоКак устроен процесс
Spec Kit (github/spec-kit, MIT)набор шаблонов и команд для разных агентов; CLI specifyконституция проекта один раз (/speckit.constitution), затем для каждой функции /speckit.specify → /speckit.plan → /speckit.tasks → /speckit.implement → /speckit.converge; артефакты spec.md, plan.md, tasks.md. В режиме навыков команды пишутся через дефис: /speckit-specify
OpenSpec (Fission-AI/OpenSpec, MIT)лёгкий слой спецификаций, рассчитанный и на существующие проекты; CLI openspecактуальные спецификации в openspec/specs/, каждое изменение — папка в openspec/changes/ (proposal.md, specs/, design.md, tasks.md); команды /opsx:propose, /opsx:apply, /opsx:archive
Kiro (AWS)агентная среда разработки со спецификациями: IDE, CLI, веб- и мобильный клиенттребования, проектные решения и задачи; steering-файлы с соглашениями проекта
Свой процесспапка specs/, шаблоны, файл памяти проектато же самое вручную — это урок SDD.3.3

Обратите внимание: все инструменты сходятся на одном и том же скелете — спецификация, план, задачи, проверка. Выучив скелет, вы сможете работать с любым из них и даже без них.

Программа рассчитана примерно на 34 часа: четыре модуля, две домашние работы с автотестами и уровнями Simple, Medium, Strong и Boss — как в основном курсе (как устроены домашние работы, вы знаете по уроку 0.1.3).

flowchart LR
M1["SDD.1<br/>Идея SDD"] --> M2["SDD.2<br/>Как писать<br/>спецификации"]
M2 --> M3["SDD.3<br/>Инструменты:<br/>Spec Kit, OpenSpec"]
M3 --> M4["SDD.4<br/>Практика<br/>и качество"]
M2 --> H1["ДЗ sdd-hw01-spec<br/>пакет спецификаций"]
M4 --> H2["ДЗ sdd-hw02-implement<br/>реализация с агентом"]
D["Программа DDD:<br/>модули DDD.1–DDD.2"] -.->|"язык и правила<br/>для спецификаций"| M2
Четыре модуля программы SDD, две домашние работы и вход из программы DDD
МодульЧасовЧто в нёмЧто появится в онлайн-школе
SDD.1 Идея SDD6что такое SDD; как работает агент и его контекстфайл памяти проекта с глоссарием и правилами
SDD.2 Как писать спецификации10требования и критерии приёмки; план, модель данных и контракты; задачи и конституция проектаспецификация записи на поток; ДЗ sdd-hw01-spec — пакет спецификаций фичи «Перенос записи на другой поток»
SDD.3 Инструменты SDD8Spec Kit; OpenSpec; обзор остальных и свой процесста же функция, проведённая через Spec Kit и через OpenSpec
SDD.4 Практика и качество10полный цикл с агентом; проверка, тесты и ревью; подводные камни и критика; выпускной проектДЗ sdd-hw02-implement — реализация «Выдачи сертификатов» с агентом по готовым спецификациям

Вторая программа курса — DDD, предметно-ориентированное проектирование. Программы дополняют друг друга. SDD отвечает на вопрос, как передать замысел агенту и проверить результат. DDD — на вопрос, что записать: какие в системе понятия, как они называются, какие правила нельзя нарушать и где проходят границы. Глоссарий школы из урока DDD.1.2 — готовый словарь для требований, правила Набора — готовые критерии приёмки, а границы контекстов — готовый скелет плана. Поэтому до модуля SDD.2 желательно пройти модули DDD.1–DDD.2; дальше программы можно идти параллельно.

  • Python, классы, модули, исключения и pytest — ступень 0 основного курса; урок 0.2.3 о классах и @dataclass пригодится в практиках.
  • Git и терминал — урок 0.1.1: агент работает в репозитории, а коммит после каждой задачи — главная страховка.
  • Доступ к любому ИИ-агенту для кода: Claude Code, GitHub Copilot, Cursor, Codex или аналог. Примеры в программе чаще даны для Claude Code, но идеи переносятся на любой агент.
  • Желательно — урок 8.3.1 об агентном цикле: он объясняет, как агент устроен изнутри.

Проведите эксперимент «промпт против спецификации» с вашим агентом. Он займёт около часа и покажет разницу лучше любых слов.

Шаг 1. Вайб-кодинг. Создайте пустую папку, выполните git init и дайте агенту одну фразу: «Сделай на Python запись студентов на курсы с отменой и возвратом денег». Закоммитьте результат и ответьте на вопросы: как названы классы? Есть ли поток с датой старта и вместимостью? Можно ли записаться дважды? Сколько вернут при отмене ровно за 7 суток до старта и через минуту после этого момента? Деньги — float или целые копейки? Откуда берётся текущее время? Что происходит с записью при отмене? Есть ли тесты? Посчитайте, сколько решений о продукте агент принял сам.

Шаг 2. Спецификация. Откатитесь к пустому репозиторию (новая ветка от первого коммита) и положите файл specs/enrollment/spec.md. Это сокращённая спецификация; полный формат разберём в уроке SDD.2.1.

# Спецификация: запись на поток
## Контекст
Онлайн-школа продаёт курсы потоками. У потока есть дата старта, вместимость и цена.
Студент записывается на поток; запись ожидает оплаты, после оплаты подтверждается.
Числа (7 суток) — условия учебного примера.
## Требования
- **REQ-001**: Когда студент записывается на поток со свободными местами, система должна создать запись со статусом «ожидает оплаты».
- **REQ-002**: Если свободных мест на потоке нет, то система должна отказать в записи (NoFreeSeats).
- **REQ-003**: Если у студента уже есть действующая запись на этот поток («ожидает оплаты» или «подтверждена»), то система должна отказать в повторной записи (AlreadyEnrolled).
- **REQ-004**: Если студент записывается в момент старта потока или позже, то система должна отказать в записи (EnrollmentClosed).
- **REQ-005**: Когда студент отменяет запись за 7 суток (7 × 24 часа) или более до старта потока, система должна вернуть полную стоимость.
- **REQ-006**: Когда студент отменяет запись позже, система должна отменить запись без возврата.
## Сценарии
По одному на требование, с датами: старт потока 2 ноября 2026 года в 10:00, вместимость 2, цена 30 000 руб.
Например, SC-005: Анна отменяет запись 26 октября в 10:00 (ровно за 7 суток) — возврат 30 000 руб.;
SC-006: Анна отменяет запись 26 октября в 10:01 — возврат 0.
## Вне рамок
Оплата, лист ожидания, уведомления.
## Открытые вопросы
- [УТОЧНИТЬ] Поток перенесли на другую дату — что с записями и правилом 7 суток? До ответа эксперта агент это не реализует.
## Интерфейс (для тестов; вообще это часть плана — урок SDD.2.2)
Модуль enrollment.py: Cohort(capacity, starts_at, price) — цена в копейках;
cohort.enroll(student_id, now) -> Enrollment с полями id и status (EnrollmentStatus.PENDING_PAYMENT, CONFIRMED, CANCELLED);
cohort.cancel(enrollment_id, now) -> сумма возврата в копейках; cohort.free_seats() -> int;
исключения NoFreeSeats, AlreadyEnrolled, EnrollmentClosed. Время передаётся параметром now, datetime.now() не используем.
Отменённая запись место не занимает.

Затем дайте агенту промпт в два захода. Первый — без кода:

Прочитай specs/enrollment/spec.md. Код пока не пиши. Перечисли, что в спецификации тебе неясно
или допускает два толкования, и задай мне не больше пяти вопросов. Ничего не додумывай сам.

Ответьте на вопросы (и, если ответ меняет правила, допишите его в спецификацию). Второй заход:

Реализуй specs/enrollment/spec.md в enrollment.py строго по разделу «Интерфейс».
Не добавляй ничего из раздела «Вне рамок». Когда закончишь, запусти python -m pytest -v tests/
и покажи результат. Если тест падает, исправляй код, а не тест.

Шаг 3. Приёмочные тесты. Положите в tests/test_acceptance.py тесты по сценариям — до того, как агент начнёт писать код. Имя каждого теста начинается с ID сценария: так видно, какое правило проверяется.

"""Приёмочные тесты из specs/enrollment/spec.md: один тест — один сценарий SC-…"""
from datetime import datetime, timedelta
import pytest
from enrollment import AlreadyEnrolled, Cohort, EnrollmentClosed, EnrollmentStatus, NoFreeSeats
STARTS_AT = datetime(2026, 11, 2, 10, 0) # старт потока «Python для аналитиков»
PRICE = 3_000_000 # 30 000 руб. в копейках
def new_cohort(capacity=2):
return Cohort(capacity=capacity, starts_at=STARTS_AT, price=PRICE)
def test_sc_001_enroll_with_free_seat():
cohort = new_cohort()
enrollment = cohort.enroll("anna", now=datetime(2026, 10, 1, 10, 0))
assert enrollment.status == EnrollmentStatus.PENDING_PAYMENT
assert cohort.free_seats() == 1
def test_sc_002_no_free_seats():
cohort = new_cohort()
cohort.enroll("anna", now=datetime(2026, 10, 1, 10, 0))
cohort.enroll("boris", now=datetime(2026, 10, 1, 11, 0))
with pytest.raises(NoFreeSeats):
cohort.enroll("vera", now=datetime(2026, 10, 1, 12, 0))
def test_sc_003_enroll_twice():
cohort = new_cohort()
cohort.enroll("anna", now=datetime(2026, 10, 1, 10, 0))
with pytest.raises(AlreadyEnrolled):
cohort.enroll("anna", now=datetime(2026, 10, 2, 10, 0))
def test_sc_004_enrollment_closed_at_start():
with pytest.raises(EnrollmentClosed):
new_cohort().enroll("gleb", now=STARTS_AT)
def test_sc_005_full_refund_exactly_7_days_before():
cohort = new_cohort()
enrollment = cohort.enroll("anna", now=datetime(2026, 10, 1, 10, 0))
refund = cohort.cancel(enrollment.id, now=STARTS_AT - timedelta(days=7))
assert refund == PRICE
assert cohort.free_seats() == 2
def test_sc_006_no_refund_later():
cohort = new_cohort()
enrollment = cohort.enroll("anna", now=datetime(2026, 10, 1, 10, 0))
refund = cohort.cancel(enrollment.id, now=STARTS_AT - timedelta(days=7) + timedelta(minutes=1))
assert refund == 0

Если реализация соответствует спецификации, вывод python -m pytest -v tests/ будет таким:

tests/test_acceptance.py::test_sc_001_enroll_with_free_seat PASSED [ 16%]
tests/test_acceptance.py::test_sc_002_no_free_seats PASSED [ 33%]
tests/test_acceptance.py::test_sc_003_enroll_twice PASSED [ 50%]
tests/test_acceptance.py::test_sc_004_enrollment_closed_at_start PASSED [ 66%]
tests/test_acceptance.py::test_sc_005_full_refund_exactly_7_days_before PASSED [ 83%]
tests/test_acceptance.py::test_sc_006_no_refund_later PASSED [100%]
============================== 6 passed in 0.01s ===============================

А если агент всё-таки решил, что «7 суток» — это «больше семи целых дней» ((starts_at - now).days > 7), сценарий на границе это поймает. Вот сокращённый вывод короткого режима python -m pytest -q tests/ (без трассировки ошибки):

....F. [100%]
FAILED tests/test_acceptance.py::test_sc_005_full_refund_exactly_7_days_before
1 failed, 5 passed in 0.01s

Шаг 4. Сравнение. Заполните таблицу для обеих веток: сколько решений о продукте агент принял сам; сколько сценариев проходит (тесты из шага 3 можно запустить и против кода из шага 1 — скорее всего, они даже не импортируются); сколько сообщений «поправь» вы написали; сколько минут ушло. Сохраните таблицу: в уроке SDD.4.1 вы повторите эксперимент на полном цикле и сравните.

Проверь себя6 вопросов
1 Команда пишет specs/enrollment/spec.md, агент реализует по нему запись на поток. Через месяц, чтобы добавить перенос записи, команда сначала описывает изменение требований, согласует его, реализует и обновляет спецификацию. Какой это уровень SDD по Бёккелер?
2 Что относится к спецификации, а не к плану? Выберите все верные варианты.Можно выбрать несколько ответов
3 Агент получил подробную спецификацию с шаблонами и чек-листами. Что из этого верно?
4 Для какой задачи полный цикл SDD (спецификация, план, задачи) скорее всего избыточен?
5 Чем SDD с ИИ-агентами принципиально отличается от model-driven development 2000-х?
6 Как называется стиль «попросил ИИ — получил — поправил», почти без чтения кода и без записанных требований? (по-русски)
  • Без плана агент заполняет пробелы самыми вероятными вариантами и молча принимает решения о продукте, а исправления живут в истории чата и теряются между сессиями.
  • SDD делает спецификацию главным артефактом: сначала что и зачем, потом как (план), потом задачи, а код проверяется по сценариям спецификации.
  • Бёккелер различает три уровня: spec-first, spec-anchored и spec-as-source — по тому, сколько живёт спецификация и кто правит код. Прочитайте её статью целиком.
  • SDD продолжает требования, BDD и TDD; от model-driven development его отличает «генератор», который понимает естественный язык, но недетерминирован.
  • Сила подхода — дешёвые ошибки, контекст для агента и определение «готово». Ограничения — многословие, ложное чувство контроля, недетерминизм и дрейф. Пейте кофе, но возвращайтесь к тестам и диффу.

Дальше: урок SDD.1.2 — как устроен ИИ-агент для кода, что такое его контекст и почему он «забывает», как файлы памяти проекта, режим планирования и субагенты помогают держать его на рельсах и как не открыть агенту дорогу к секретам.