- sprint.md прямо запрещал шаг, который пайплайн теперь делает: раздел «кто и когда закрывает» переписан под снятую границу приёмки - закрытие задачи стало шагом 11, после коммита: раньше упавший коммит оставил бы задачу закрытой без следа работы - контракт close --implemented больше не обещает состоявшуюся приёмку - слот «куда копируются критерии приёмки» убран из session: на него отвечает пайплайн, а канон его не заводил - research/ в таблице ролей вернул adversary; журнал версий поднимает CLAUDE.md целиком, а не тремя пунктами из восьми - TODO и REMAINING перестали занижать: коммитов одиннадцать, переписок три
135 lines
12 KiB
Markdown
135 lines
12 KiB
Markdown
# Ведение спринта
|
||
|
||
Спринт — набор задач под одну цель, замороженный до его конца. Здесь то, что
|
||
происходит **внутри** спринта: как задача заканчивается, что считается сделанным,
|
||
кто принимает и что идёт в доклад. Как спринт набирается — шаг 4 в
|
||
[cadence.md](cadence.md).
|
||
|
||
## Наблюдаемые исходы задачи
|
||
|
||
Как они достигаются — дело пайплайна проекта. Сессия знает только исход и его
|
||
след.
|
||
|
||
- **Сделана** — по определению готовности ниже. `close <slug> --implemented`:
|
||
файл и строка удаляются, следом остаётся коммит. **Закрывает владелец спринта
|
||
и только после вердикта приёмки** — см. «Кто и когда закрывает».
|
||
- **Вышла из спринта** — `sprint drop <slug> --reason …`: возвращается в беклог
|
||
с вопросом в файле и **без живого незакоммиченного предложения** — иначе при
|
||
следующем взятии оно столкнётся с новым. Наработки, которые жалко терять,
|
||
переезжают в тело задачи текстом.
|
||
- **Переросла в эпик** — распознаётся **до того, как под неё заведено
|
||
предложение об изменении**, иначе его придётся выбрасывать. Помечается
|
||
`[epic]`, выходит из набора, уходит на декомпозицию; спринт продолжается
|
||
остальными, части в замороженный набор не добавляются.
|
||
- **Отменена решением по ходу** — `close <slug> --reason "<ссылка на решение>"`
|
||
прямо из спринта. Это редкий, но законный исход, и он называется в докладе.
|
||
|
||
**Конец спринта** — когда по каждой задаче набора наступил один из исходов. Не
|
||
«все сделаны»: иначе одна застрявшая задача держит спринт бесконечно. Затем
|
||
`sprint close`.
|
||
|
||
**Урожай заводится при закрытии спринта, а не при закрытии задачи.** Это
|
||
обязанность закрывающего: пройти по спискам находок от исполнителей и завести
|
||
недостающее интейком скилла `tasks` — с дедупликацией и картой человеку. Заводимое
|
||
метится тегом спринта само (`sprint:<слаг>`), поэтому первая порция следующей
|
||
сессии поднимается одной командой `list --tag sprint:<слаг>`. Спринт, закрытый
|
||
без этого шага, оставляет находки жить в отчётах — то есть нигде.
|
||
|
||
**Провал спринта.** Сработал блокер — спринт распускается (`sprint close
|
||
--dissolve --reason …`), недоделанное возвращается в беклог, новый набор
|
||
делается после ответа человека. Спринт не «ждёт»: ждать может человек, а
|
||
замороженный набор, который нельзя двигать, только мешает.
|
||
|
||
## Определение готовности
|
||
|
||
Задача засчитывается сделанной, когда верно **всё**:
|
||
|
||
1. **Пайплайн задачи пройден до конца** — со своим определением готовности, за
|
||
которое отвечает проект: проверки, состав ревью, документация, коммит. Здесь
|
||
оно не пересказывается и не подменяется — **форма фиксирована, содержание
|
||
даёт `CLAUDE.md` проекта**. Пайплайна нет, задача сделана руками — условие
|
||
читается как «проверки проекта зелёные и изменение влито».
|
||
2. **Критерии приёмки проверены поимённо** — каждый со своим оракулом, исход по
|
||
каждому назван. Это единственное, что добавляет управление задачами: пайплайн
|
||
отвечает «сделано по правилам», критерии — «сделано то, что заказывали».
|
||
3. **Находки по ходу отданы списком** — исполнитель обязан их **назвать**
|
||
(каждую, с пометкой «заведена / не заведена: причина»), но **не обязан
|
||
заводить**: заведение интерактивно, оно требует дедупликации против беклога и
|
||
кладбища и решений человека. Обязанность **завести урожай** — на закрытии
|
||
спринта, ниже. Так автономный исполнитель не оказывается одновременно обязан
|
||
завести задачи и не вправе это сделать в одиночку.
|
||
|
||
### Кто и когда закрывает
|
||
|
||
**Задачу закрывает агент-оркестратор — тот же, кто её и сделал**, последним шагом
|
||
пайплайна, после коммита. Порядок:
|
||
|
||
1. пайплайн доводит задачу до коммита;
|
||
2. **после коммита** зовёт `Skill av-dev-pm:tasks` и закрывает задачу
|
||
(`close <slug> --implemented`); строка уходит из `SPRINT.md`;
|
||
3. **докладывает исход и по каждому критерию — оракул и наблюдаемый исход.**
|
||
Это доклад приёмщику, а не отметка «принято».
|
||
|
||
**Приёмщик и исполнитель здесь совпадают, и это принято сознательно** — цена
|
||
названа в `SKILL.md`, раздел «Стимулы». Поэтому закрытие **не окончательно**, а
|
||
доклад по критериям — не формальность: он единственное, по чему приёмка вообще
|
||
возможна.
|
||
|
||
**Порядок «коммит, потом закрытие» обязателен.** Закрытие удаляет файл задачи;
|
||
упавший коммит после закрытия оставил бы задачу закрытой без единого следа
|
||
работы.
|
||
|
||
**Дорога назад существует и обязана быть названа.** Человек на сессии сверил
|
||
критерии, и приёмка не сошлась — `tasks.py reopen <slug> --reason "приёмка не
|
||
сошлась: …"`:
|
||
файл восстанавливается из истории git, строка возвращается в набор идущего
|
||
спринта (или в беклог, если спринта нет), строка кладбища снимается. Тело
|
||
восстанавливается **на момент удаления** — всё, что было дописано позже, живёт
|
||
только в коммите задачи, и это называется в докладе.
|
||
|
||
### Кто и по чему принимает
|
||
|
||
Три условия, без которых пункт про критерии не исполняется никем:
|
||
|
||
1. **Критерии переживают файл задачи.** Файл удаляется при закрытии, поэтому
|
||
критерии копируются туда, где их увидит приёмщик. Куда именно — **отвечает
|
||
пайплайн проекта, а не слот в `CLAUDE.md`**: он переносит их в `tasks.md`
|
||
изменения на шаге заведения change. Проект без пайплайна называет своё место
|
||
сам.
|
||
2. **Принимает человек на сессии, а не отдельный агент.** Декорреляция
|
||
исполнителя и приёмщика в момент закрытия **снята** (решение о снятии и его
|
||
цена — в `SKILL.md`, «Стимулы»). Опоры остались три: сохранённый отчёт триажа
|
||
в `openspec/changes/<id>/review/` — независимый артефакт, `SPRINT.md` под git
|
||
и `reopen`. Переоценка на сессии и есть момент, когда критерии видит не
|
||
исполнитель.
|
||
3. **Расхождение — дефект критериев.** Приёмщик правит критерии и возвращает
|
||
задачу исполнителю **в этом же спринте**: ответ есть, остаток есть, по тесту
|
||
про остаток это не выход из спринта.
|
||
|
||
## Что врывается в замороженный набор
|
||
|
||
Только два класса — правило и его обоснование в SKILL.md. Здесь механика:
|
||
|
||
- вторжение **не добавляет** задачу в набор: `SPRINT.md` остаётся набором под
|
||
цель. Внеплановая работа делается и называется в докладе отдельной строкой
|
||
«внеплановое: что и почему»;
|
||
- если внеплановое требует больше пары часов, честнее распустить спринт, чем
|
||
делать вид, что набор соблюдается;
|
||
- всё остальное падает в беклог через обычный интейк и ждёт сессии.
|
||
|
||
## Доклад в конце спринта
|
||
|
||
Проверяемые якоря, а не пересказ:
|
||
|
||
- **Цель спринта** и по каждой задаче набора: **хеш коммита**, дословный исход
|
||
проверок проекта, **исход по каждому критерию приёмки**.
|
||
- **Какие развилки решались** и чем обоснованы.
|
||
- **Урожай:** сколько задач заведено, какие вопросы накопились, что вышло из
|
||
спринта и почему, что было внеплановым.
|
||
- **Поимённая сверка урожая** с отчётами ревью: каждая отложенная находка имеет
|
||
либо слаг, либо строку «не заведена: причина». Нулевой урожай при непустом
|
||
отчёте — сигнал, а не благополучие.
|
||
- **Созрела ли порция для сессии.** Решение звать — человека, напоминание —
|
||
обязанность агента: `⌈урожай / 8⌉` порций.
|
||
- **Границы покрытия** сжатой строкой: что в этом спринте не проверялось вовсе.
|