Как я написал dev-cycle для Codex и связал требования с тестами
Разработка часто начинается с заметок после встречи, переписки и пожеланий заказчика. В них могут остаться противоречия и открытые вопросы. Если не согласовать их до реализации, разработчик или ИИ-агент будет принимать решения по ходу работы. Позже бывает трудно восстановить, откуда взялось конкретное правило и каким тестом оно проверяется.
На связи Денис Москвин, Product-менеджер направлений «Кассы» и «Самозанятые» в Монете. Я разработал для Codex навык dev-cycle, в котором согласование требований встроено в процесс разработки, а договорённости связаны с моделью, задачами и тестами через постоянные идентификаторы. В статье покажу его работу на примере вымышленной гостиницы: от двух реплик о бронировании до реализации и приёмки. Разберу все 12 шагов и покажу, как проследить последствия изменения требования. Навык опубликован на GitHub под лицензией MIT.
1. Пользовательские истории
Небольшая гостиница подтверждает заявки с сайта вручную. На выбранную ночь в нужной гостю категории остался один свободный номер.
Гость. Хочу сразу после отправки заявки понять, закрепили ли за мной номер. Тогда я смогу покупать билеты.
Администратор. До проверки наличия номеров гостю показываем, что заявка получена. Бронь подтверждаю я. На последний свободный номер нельзя подтвердить две заявки на одну ночь.
Из реплик получаются две истории. Агент сохраняет источник и ожидаемый результат каждой, а в INDEX.md записывает вопрос Q-1 о том, какой статус гость увидит сразу после отправки. После согласования гость сразу видит заявку на рассмотрении. Бронь появляется после подтверждения администратором.
-
USRSTR-1. Подать заявку и видеть результат. Как гость, я хочу подать заявку на номер и видеть её статус, чтобы знать, могу ли покупать билеты. -
USRSTR-2. Подтвердить заявку при наличии свободного номера. Как администратор, я хочу подтверждать заявки при наличии свободных номеров, чтобы двум гостям не пообещали последний номер на одну ночь.
Чтобы увидеть первую паузу для согласования, передайте установленному навыку две исходные реплики из hotel-booking/meeting.md. Подойдёт запрос $dev-cycle stories Разбери эти реплики и покажи, какие решения ещё нужны.
2. Критерии приёмки и нефункциональные требования
Каждая история получает условия, по которым можно проверить результат. В гостиничном примере их четыре.
Критерий
Что проверяем
USRSTR-1/ACPT-1
При подаче система сразу возвращает номер заявки и статус «На рассмотрении».
USRSTR-1/ACPT-2
После подтверждения чтение по номеру заявки возвращает статус «Подтверждена».
USRSTR-2/ACPT-1
Администратор может подтвердить заявку при наличии свободного номера. Гость получает отказ, статус заявки сохраняется.
USRSTR-2/ACPT-2
При попытке подтвердить вторую заявку на ту же ночь система сообщает, что номеров больше нет. Первая заявка остаётся подтверждённой, вторая — на рассмотрении.
В последнем критерии важен статус обеих заявок после отказа. Сам отказ ещё не говорит, что система сохранила первую бронь и не изменила вторую заявку.
Сквозные требования, например ко времени ответа, получают свой номер NFR-N, источник и измеримый порог. В гостиничном примере «сразу» означает результат той же операции подачи. Числового требования ко времени ответа в исходных репликах нет. Риск подтвердить больше броней, чем есть номеров, записан как RISK-1 и связан с критерием USRSTR-2/ACPT-2.
3. Роли и кандидаты в агрегаты
Сначала выделяю действия из историй. Гость подаёт заявку и проверяет её статус. Администратор решает, подтвердить ли её. Это две роли с разными полномочиями, ROLE-1 и ROLE-2. Каждая ссылается на свою историю.
Кандидат в агрегаты появляется там, где у объекта есть собственная жизнь. Заявку создают, находят по номеру и подтверждают. Поэтому в roles-and-aggregates.md появляется кандидат AGGR-1 со ссылками на обе истории. Слово «подтверждение» пока обозначает действие над заявкой. Чтобы выделить его в самостоятельный объект, понадобилась бы история, в которой у подтверждения есть своя идентичность и поведение.
В учебном срезе моделируется одна ночь и одна категория. Наличие номера проверяется при подтверждении. Если в требованиях появится управление остатками по датам и категориям, я рассмотрю отдельный кандидат «Доступность категории на ночь». У такого объекта может быть своя идентичность — пара «категория, дата» — и собственные операции, например закрытие продаж на выбранную ночь.
4. Связи
В relations.md фиксирую, что связывает объекты, какова кратность и кто чем владеет. У связи есть идентификатор и ссылка на историю, которая её обосновывает. В примере REL-1 связывает гостя с подачей заявок, а REL-2 — администратора с их подтверждением. Обе связи имеют кратность «один ко многим». Один гость может подать несколько заявок, один администратор — подтвердить несколько заявок в пределах доступности.
Если добавить агрегат доступности, появится связь между двумя агрегатами. В сценарии на одну ночь каждая заявка относится к одной паре «категория, дата», а к такой паре могут относиться многие заявки. Это кратность связи, а лимит подтверждений задаётся отдельным правилом. Отдельно выясняю, что будет при удалении записи о доступности. Должна ли история заявок сохраниться? Ответ записываю рядом с кратностью и правилами владения.
5. Процессы и диаграммы последовательности
Истории описывают цели разных людей. Процесс связывает их действия в порядке, в котором они происходят. PROC-1 опирается на обе истории, роли и заявку. Триггер — гость отправляет заявку. На момент подтверждения заявка уже существует, а право на подтверждение есть у администратора.
В файле процесса записываю основной сценарий, альтернативы и отказы. Затем переношу взаимодействия на Mermaid-диаграмму sequenceDiagram. Участники берутся из модели. Ниже диаграмма основного сценария и отказа из-за отсутствия номеров.
Гость подаёт заявку и получает её номер и статус. Администратор подтверждает заявку при наличии номера. Иначе статус не меняется. Гость проверяет текущий статус по номеру заявки.
В текстовом сценарии есть ещё одна ветка. При попытке подтверждения со стороны гостя система возвращает отказ и сохраняет статус заявки. У процесса остаются ссылки на истории, из которых появились эти действия.
6. Состояния, атрибуты и проверка кандидатов
По критериям и процессу становится понятно, какие данные нужны объекту. У заявки AGGR-1 есть номер AGGR-1/ATTR-1 для поиска и статус AGGR-1/ATTR-2 для ответа гостю. В модели номер — целое положительное число, статус — одно из двух значений. Для атрибута навык просит указать тип, обязательность и источник. В этом случае номер назначается при подаче, а начальный статус задаётся при создании заявки.
На этом шаге возвращаюсь к кандидатам. Заявка — сущность с собственной идентичностью, и в примере она представляет агрегат из одной сущности. Состояния «На рассмотрении» и «Подтверждена» различимы снаружи и меняют доступные действия. Кандидат без собственных атрибутов возвращается на пересмотр. Границы агрегата проверяются отдельно по правилам, которые должны соблюдаться вместе. Например, лимит броней относится ко всем заявкам на одну категорию и ночь.
7. Жизненный цикл
Диаграмма последовательности показывает обмен между участниками. Жизненный цикл описывает, какие состояния может пройти одна заявка и по каким правилам.
При подаче заявка переходит в состояние «На рассмотрении». При подтверждении администратором при наличии номера заявка переходит в состояние «Подтверждена».
Переход AGGR-1/TR-1 создаёт заявку в начальном состоянии. У перехода AGGR-1/TR-2 есть инициатор, условие наличия номера и ссылки на критерии. Если номеров уже нет, заявка остаётся на рассмотрении. В таблице переходов это результат отказа. В этом срезе «Подтверждена» — терминальное состояние. На согласовании проверяю, что каждое состояние достижимо и у каждого нетерминального состояния есть выход. Скрипт проверяет ссылки на процессы и критерии, которыми обоснованы переходы.
8. Метрики
Для гостиницы MTR-1 — число подтверждённых заявок на выбранную ночь. Оно считается по статусу заявки, меняющемуся при переходе AGGR-1/TR-2. В этом примере администратор проверяет показатель после каждой попытки подтверждения, допустимый диапазон — от нуля до одной заявки.
Этот шаг помогает обнаружить недостающие данные до проектирования. Например, для метрики времени ожидания понадобятся моменты подачи и подтверждения. Тогда можно вернуться к атрибутам и переходам и решить, как их фиксировать.
9. Проектирование среза
Когда модель согласована, выбираю срез — набор историй, критериев и НФТ, которые команда реализует вместе. В примере срез booking включает обе истории. Решение DES-1 фиксирует хранение заявок в памяти и три операции — подать заявку, прочитать статус и подтвердить бронь. Альтернативой было постоянное хранилище с транзакцией. Для одной категории, одной ночи и последовательных вызовов достаточно памяти. В проекте указываю, где проверяется наличие номера и как проверить каждый критерий. Там же определяю, какие переходы должны порождать события и какие данные понадобятся для расчёта метрик.
10. Задачи
TASK-1 добавляет подачу заявки и чтение статуса. TASK-2 добавляет подтверждение и отказ, когда свободных номеров больше нет. Каждая задача ссылается на критерий или НФТ, а trace.py check проверяет обратное покрытие — дошёл ли каждый критерий среза до задачи. Так уже по списку задач видно, есть ли работа под каждый согласованный результат.
11. Реализация
После команды человека агент берёт задачи по порядку и отмечает каждую после успешного прогона её тестов. Навык предусматривает номер задачи в сообщении коммита и метку verifies: рядом с тестом. Вот проверка для TASK-2.
# verifies: USRSTR-2/ACPT-2def test_second_request_cannot_be_confirmed_when_no_rooms_remain(self): first, _ = self.booking.submit() second, _ = self.booking.submit() self.booking.confirm(first, is_admin=True) with self.assertRaises(RoomUnavailable): self.booking.confirm(second, is_admin=True) self.assertEqual(self.booking.status(first), "confirmed") self.assertEqual(self.booking.status(second), "pending")
Тест проверяет отказ и статус обеих заявок после него. Роль администратора здесь имитирует флаг is_admin.
12. Приёмка среза
Когда задачи закрыты, trace.py tests --slice booking сопоставляет критерии среза с проверками. Для гостиницы он находит четыре метки verifies:. Затем запускаю тесты и записываю фактический результат в acceptance.md. Если для критерия выбран другой метод, например демонстрация или осмотр, в приёмке фиксируются метод и результат проверки.
Что пересмотреть, если освободился второй номер
Допустим, на ту же ночь освободился второй номер той же категории. Теперь надо подтвердить первые две заявки и проверить отказ на третьей.
trace.py impact USRSTR-2/ACPT-2 находит шесть связанных элементов и строку с тестом. В список попадают переход, метрика, проектное решение, две задачи и риск превышения доступности. Задача подачи заявки попала туда через общее проектное решение. По ней достаточно проверить, затронуло ли изменение интерфейс подачи. Идентификатор критерия сохраняется, поэтому связи продолжают работать после уточнения его формулировки.
dev-cycle и AWS AI-DLC
Я сравнивал dev-cycle и AWS AI-DLC на практике. В таблице сопоставляю свои наблюдения с документацией dev-cycle v0.1.0 и AI-DLC Workflows v2.11.3 от AWS Labs. В Codex CLI AI-DLC запускается через $aidlc. AI-DLC на Codex CLI
Что сравниваю
🔵 dev-cycle
🟠 AWS AI-DLC
Устройство
Навык для Codex. Методика в SKILL.md и инструкциях к шагам, шаблоны для документов, trace.py для проверки связей.
Фреймворк с движком, CLI aidlc, оркестратором, хуками и журналом аудита. В комплекте 14 агентных ролей. Роли в AI-DLC
Охват
От заметок, интервью и транскриптов до реализации и приёмки среза.
От постановки цели до развёртывания, наблюдаемости и работы с инцидентами. В подходящих сценариях есть исследование рынка. Ideation · Operation
Маршрут
Задан порядок шагов 1–11 до реализации включительно. Затем приёмка среза, шаг 12. Можно запустить отдельный шаг или работать по срезам.
33 стадии в пяти фазах. В конкретный маршрут входят стадии, подходящие для выбранного масштаба работы. Протокол стадий
Задачи
Сервисы со сложной предметной областью, где нужно согласовать требования и правила поведения. Для мелких правок навык прямо рекомендует обычный режим работы.
От исправления бага до разработки продукта. Есть маршруты bugfix, poc, mvp и другие. Выбор маршрута
Модель предметной области
Роли и кандидаты в агрегаты, связи, процессы, состояния и атрибуты, жизненные циклы проходят отдельные согласования до проектирования среза.
Domain Design описывает границы компонентов, их зависимости и архитектурные решения (ADR). Functional Design уточняет сущности, связи, состояния и правила для каждой единицы работы, где этот этап нужен. Domain Design · Functional Design
Метрики
Отдельный шаг. Для метрики задаются формула на основе атрибутов и переходов, владелец и частота. Если данных не хватает, возвращаюсь к модели.
Метрики успеха задаются в Intent Capture. В Operation есть SLO и анализ стоимости. Intent Capture · Feedback & Optimization
Трассировка
Постоянные идентификаторы, ссылки на элементы предыдущих шагов, INDEX.md и метки verifies: в тестах. Перед каждой паузой trace.py check проверяет ссылки и покрытие по уже пройденным шагам.
traceability.json связывает критерии с правилами и файлами реализации на соответствующих стадиях. Движок проверяет покрытие между единицами работы и согласованность на границах фаз. Аудит фиксирует решения и одобрения. Проверки в Construction · Аудит
Открытые вопросы
Допущение получает пометку ‼ с номером вопроса. Обратный индекс связывает вопрос с элементами модели. answer Q-N показывает, что затронет ответ, перед правкой этих элементов.
Ответы и допущения подтверждаются на этапе согласования. В режиме strict движок предупреждает об изменении отслеживаемого документа завершённой стадии. Согласование и правки
Риски
Реестр RISK-N. Четыре варианта обработки — критерий, проектное решение, внешняя мера или принятие риска. Если риск закрыт критерием или решением, ссылки ставятся в обе стороны.
RAID-лог рисков, допущений, проблем и зависимостей в Feasibility, когда стадия входит в маршрут. В Delivery Planning риски учитываются при обосновании порядка поставки. Feasibility · Delivery Planning
Спецификации
StRS, SyRS и SRS собираются из модели по шаблонам, ориентированным на ISO/IEC/IEEE 29148. Идентификаторы требований сохраняются. Правила сборки
Свой набор артефактов по стадиям, в том числе requirements.md, stories.md и functional-spec.md. Каталог артефактов
Несколько моделей и репозиториев
Ссылка на элемент другой модели содержит её префикс. В целевой модели входящая зависимость записывается в разделе «На нас ссылаются».
Spaces и intents организуют работу, а результаты Reverse Engineering хранятся отдельно по репозиториям. В плане поставки есть карта внешних зависимостей. Хранение артефактов · План поставки
В задачах вроде бронирования мне полезны два свойства dev-cycle. Модель можно согласовать до выбора компонентов и хранения, а при изменении правила — найти по его номеру конкретный переход и строку теста. Когда в задачу входят CI, развёртывание и эксплуатация, у AI-DLC шире охват.
Как повторить пример
Скачайте и распакуйте архив с исходными репликами, моделью, кодом и тестами. Для запуска нужен Python 3.9 или новее. Выполните команды из каталога dev-cycle-hotel-example. Скачать пример бронирования гостиничного номера (ZIP)
python3 trace.py --model hotel-booking checkpython3 trace.py --model hotel-booking impact USRSTR-2/ACPT-2python3 trace.py --model hotel-booking tests --slice booking(cd hotel-booking && python3 -m unittest -v)
Проверка модели в примере не выявила расхождений. Все четыре теста прошли.
Если попробуете навык на своих заметках, расскажите, какие вопросы он поднял на первом шаге. Если агент пропустил важную развилку, оставьте обезличенный фрагмент обсуждения и вопрос, которого не хватило. Установка навыка · Обсуждение в Issues · Я в Телеграм
Источник: habr.com