Понятия записаны, словарь согласован — теперь их можно превратить в главный рабочий артефакт продукт-инженера: документ, по которому агент строит, а вы принимаете результат.
Соблазн этот шаг пропустить велик: срез в голове ясный, агент умный — почему не описать задачу в двух фразах? Потому что недостающее агент достроит сам, и достроит не из вашего продукта, а из среднего по всему, что видел. Вы говорите «сделай оформление заказа» — он решает, что такое заказ, какие поля обязательны, что происходит при повторном нажатии, куда уходят деньги при сбое. Каждое решение по отдельности разумно. Но разумно вообще — не разумно для вашего среза.
Результат узнаваемый: приезжает код, который выглядит убедительно, компилируется, даже покрыт тестами — и делает не то. Не грубо не то, а на пару шагов в сторону: границы шире, чем вы хотели; поведение на краю не такое; наружу торчит не тот контракт. Замечаете вы это не на приёмке, а через две недели, когда строите следующий срез поверх. Причём чем мощнее агент, тем правдоподобнее выходит «не то»: размытость задачи не компенсируется умом исполнителя, она им усиливается.
Спека — это модель понятий с обязательствами
Посмотрите, из чего состоит хорошая спецификация функциональности:
- Сущности и их атрибуты — понятия модели: заказ, позиция, платёж.
- Состояния и переходы — жизненный цикл:
draft → placed → paid → shipped, «изcancelledпереходов нет». - Команды — что можно сделать: «оформить заказ», «отменить», «оплатить» — с предусловиями («оплатить можно только
placed»). - События — что происходит в результате: «заказ оформлен», «платёж получен» — то, на что реагируют другие части системы.
- Инварианты — правила, которые не нарушаются никогда: «сумма позиций равна сумме заказа», «у заказа ровно один клиент».
- Критерии приёмки — проверяемые сценарии: дано → когда → тогда.
Первые пять пунктов — ровно элементы модели домена (объекты, состояния, события, связи, правила), только с обязательствами: спека не просто описывает понятия, она фиксирует, что система про них гарантирует. Поэтому попытка «написать спеку» без модели понятий и проваливается — нечего разворачивать. Получается пересказ пожеланий, где агенту всё равно приходится угадывать, что такое «заказ» и можно ли оплатить отменённый.
Порядок работы такой: понятия и связи → состояния (запрещённые переходы важнее разрешённых) → команды и события в едином словаре (CancelOrder и OrderCancelled, а не синонимы по настроению) → инварианты → критерии приёмки. На выходе — документ на несколько страниц, где нет ни слова про фреймворки и таблицы: только домен. Техника добавляется отдельным разделом и не смешивается с моделью — мы уже видели, что бывает при смешивании.
Контракт среза: рабочая единица
Спека описывает область целиком, а работа идёт срезами — кусками продукта, каждый из которых решает настоящую проблему пользователя и проверяет гипотезу минимальными силами (про то, как резать до такого среза, — в приоритизации наименьшего среза).
Один срез разворачивается в короткий контракт. Это не техническое задание на сто страниц, а четыре вещи, зафиксированные словами настолько точно, чтобы по ним можно было и собрать, и потом проверить.
1. Границы — что входит и что не входит. Самая недооценённая часть. Вы явно перечисляете, что в срез входит, и отдельным списком — что в него сознательно не входит. «Оплата картой — да; сохранённые карты, рассрочка, возврат — нет, не в этом срезе». Список «не входит» дороже списка «входит»: именно туда агент залезает по умолчанию, достраивая правдоподобное.
2. Сценарий словами пользователя. Один случай использования, описанный так, как его проживает человек, а не как исполняет система: «покупатель нажимает „оплатить", видит подтверждение, деньги списываются один раз». Не «контроллер принимает POST и вызывает сервис». Если сценарий не формулируется одной внятной фразой — срез ещё не дорезан.
3. Интерфейс — вход, выход, ошибки, повторный вызов. Не реализация, а сигнатура: что операция принимает, что возвращает, какими ошибками отвечает и что происходит при повторе. Идемпотентность фиксируется именно здесь, на уровне контракта, а не «разберёмся в коде»: повторный вызов с тем же ключом даёт тот же результат, а не второе списание. Это граница, которую видят соседние куски продукта, — её нельзя оставлять агенту на усмотрение.
4. Критерии приёмки — проверяемые. Не «работает корректно», а перечень утверждений, каждое из которых проверяется «да/нет». «При повторе с тем же ключом второго списания нет». «При недоступном шлюзе заказ остаётся неоплаченным, пользователь видит понятную ошибку». Если критерий нельзя проверить — это не критерий, а пожелание, и агент его тихо проигнорирует.
Как это выглядит
Контракт короткий и вне языка: ремесло агент знает сам, ваше дело — задать рамку.
UseCase: Оплатить заказ
Границы:
входит — оплата картой одного заказа, разовое списание
не входит — сохранённые карты, рассрочка, частичная оплата, возврат
Сценарий:
Покупатель подтверждает оплату заказа в статусе «ожидает оплаты»
и получает подтверждение; деньги списываются ровно один раз.
Интерфейс:
вход — идентификатор заказа, ключ идемпотентности
выход — статус заказа, ссылка на платёж
ошибки — заказ не найден; заказ уже оплачен; шлюз недоступен
повтор — тот же ключ возвращает первый результат, второго списания нет
Критерии приёмки:
1. Успешная оплата переводит заказ в «оплачен» и возвращает ссылку.
2. Повтор с тем же ключом не списывает второй раз.
3. Недоступный шлюз оставляет заказ «ожидает оплаты», ошибка понятна.
4. Оплата уже оплаченного заказа отклоняется и не списывает.
Двадцать строк. Но по ним агент собирает предсказуемо: границы не дают расползтись, сценарий держит смысл, интерфейс фиксирует стык, критерии дают чем закончить.
Почему это работает
Три причины, и все три — про то, чего размытая задача не даёт.
Контракт проверяем. Инварианты и критерии приёмки — это готовые тесты, и приёмка результата превращается из «вроде похоже» в прогон сценариев. Написан контракт один раз, а работает дважды: как задание на входе и как основание приёмки на выходе.
Он устраняет угадывание. Агент не решает сам, можно ли оплатить отменённый заказ, — это записано. Чем меньше свободы в смысле, тем больше пользы от скорости агента: свобода остаётся там, где она уместна, — в реализации.
Он переживает сессии. Контекст сессии исчезает, документ остаётся. Следующая сессия — или другой агент, или вы через месяц — стартует от того же текста, и три сессии дают одно решение, а не три.
И ещё одно, менее очевидное: контракт — это не лишний этап между «придумал» и «собрал», а перевод. Слева от него продуктовый язык: проблема, ценность, гипотеза. Справа — язык сборки: команда, интерфейс, обработка ошибок. Без контракта переход всё равно происходит — просто внутри агента, молча, по его усмотрению. Вы отдаёте продуктовое решение тому, кто не знает вашего продукта.
Дальше эта дисциплина масштабируется: контракт на срез — рабочая единица, набор контрактов — модель сервиса. По этому принципу устроена методология Use Case Pattern, на которой стоит весь этот сайт: спецификация живёт рядом с кодом, исполняется агентом и проверяется на каждом изменении.
Коротко
- Размытая задача даёт правдоподобное «не то», и чем мощнее агент, тем лучше оно замаскировано.
- Спека = модель понятий с обязательствами: сущности, состояния, команды, события, инварианты + критерии приёмки.
- Порядок: понятия → состояния (запрещённое важнее разрешённого) → команды и события в едином словаре → инварианты → критерии приёмки. Домен отдельно, техника отдельно.
- Рабочая единица — контракт на один срез: границы (в том числе «не входит»), сценарий словами пользователя, интерфейс (вход, выход, ошибки, повтор), проверяемые критерии.
- Список «не входит» дороже списка «входит»: именно туда агент достраивает лишнее.
- Контракт проверяем (критерии = тесты), устраняет угадывание (инварианты не интерпретируются) и переживает сессии.
- Написан один раз — работает дважды: как задание на входе и как основание приёмки на выходе.
Что почитать дальше
- Язык домена — откуда берутся понятия, которые разворачиваются в контракт.
- Приёмка результата ИИ — как критерии превращаются в проверку.
- Наименьший ценный срез — как дорезать задачу до одной линии ценности.
- Use Case Pattern — методология, где такие контракты живут рядом с кодом.