Files
dev-skills/av-dev-pm/skills/session/references/sprint.md
T
avandClaude Opus 5 bd1ea6d6b1 старшинство диаграмм объявлено, рендер проверяется скриптом
Диаграмма и проза вокруг неё описывают один факт — это второй дом, и
разойтись они могут молча: то самое, против чего написан copies.py.
Механической сверки здесь нет, дословного соответствия между текстом и
графом не существует, поэтому работает объявление. В review-pipeline
старший граф — он и есть алгоритм планировщика, проза объясняет рёбра;
в остальных местах старшая проза, диаграмма там сводка; в calibration.md
старшая таблица вердиктов, схема добавляет к ней только счётчик.

Объявление стоит у каждой диаграммы строкой в месте, а не общим правилом
в README: скилл читают целиком, README — нет. В task-batch добавлена
оговорка про соседний скилл — два вызова с разным старшинством рядом это
место, где легко ошибиться.

scripts/diagrams.py вынимает все mermaid-блоки и рендерит каждый через
mmdc или npx @mermaid-js/mermaid-cli. Коды выхода — общий словарь; нет
рендерера — код 3, а не молчаливый успех. Chromium с --no-sandbox:
без флага падает на «No usable sandbox», причина в докстроке. Проверены
обе ветки: 11 диаграмм в 9 файлах зелено, сломанный блок даёт точное
место с текстом ошибки парсера и код 1.

README: раздел «Проверка диаграмм» рядом с проверкой копий — что ловит,
чего не ловит и почему не в гейте. DECISIONS 63 и 64.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 20:41:42 +03:00

187 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ведение спринта
Спринт — набор задач под одну цель, замороженный до его конца. Здесь то, что
происходит **внутри** спринта: как задача заканчивается, что считается сделанным,
кто принимает и что идёт в доклад. Как спринт набирается — шаг 4 в
[cadence.md](cadence.md).
## Наблюдаемые исходы задачи
Как они достигаются — дело пайплайна проекта. Сессия знает только исход и его
след.
- **Сделана** — по определению готовности ниже. `close <slug> --implemented`:
файл и строка удаляются, следом остаётся коммит. **Закрывает агент-оркестратор
последним шагом пайплайна, после коммита; приёмка человеком идёт позже и
отменяется `reopen`** — см. «Кто и когда закрывает».
- **Вышла из спринта** — `sprint drop <slug> --reason …`: возвращается в беклог
с вопросом в файле и **без живого незакоммиченного предложения** — иначе при
следующем взятии оно столкнётся с новым. Наработки, которые жалко терять,
переезжают в тело задачи текстом.
- **Переросла в эпик** — распознаётся **до того, как под неё заведено
предложение об изменении**, иначе его придётся выбрасывать. Помечается
`[epic]`, выходит из набора, уходит на декомпозицию; спринт продолжается
остальными, части в замороженный набор не добавляются.
- **Отменена решением по ходу** — `close <slug> --reason "<ссылка на решение>"`
прямо из спринта. Это редкий, но законный исход, и он называется в докладе.
**Конец спринта** — когда по каждой задаче набора наступил один из исходов. Не
«все сделаны»: иначе одна застрявшая задача держит спринт бесконечно. Затем
`sprint close`.
```mermaid
flowchart TD
take["sprint take — задача в наборе"]
done["сделана<br/>close --implemented"]
out["вышла<br/>sprint drop --reason"]
epic["переросла в эпик<br/>распознаётся до заведения change"]
cancel["отменена решением по ходу<br/>close --reason"]
all{"по каждой задаче набора<br/>наступил исход?"}
harvest["урожай заводится интейком tasks"]
close["sprint close"]
dissolve["sprint close --dissolve --reason<br/>недоделанное — в беклог"]
take --> done
take --> out
take --> epic
take --> cancel
done --> all
out --> all
epic --> all
cancel --> all
all -->|да| harvest
harvest -->|"тег sprint: ставится, пока SPRINT.md не очищен"| close
take -->|"продолжать нечем ни одной задачей — блокер"| dissolve
done -->|"приёмка не сошлась: reopen --reason"| take
```
Два ребра на схеме — те, где порядок обязателен и нарушается молча: **урожай до
`sprint close`** (после команды автотег уже не поставится) и **блокер в обход
исходов** (спринт распускается, а не ждёт).
Схема — **сводка**: определение готовности и правила приёмки ниже, и при
расхождении прав текст.
**Урожай заводится при закрытии спринта, а не при закрытии задачи.** Это
обязанность закрывающего: пройти по спискам находок от исполнителей и завести
недостающее интейком скилла `tasks` — с дедупликацией и картой человеку. Заводимое
метится тегом спринта само (`sprint:<слаг>`), поэтому первая порция следующей
сессии поднимается одной командой `list --tag sprint:<слаг>`. Спринт, закрытый
без этого шага, оставляет находки жить в отчётах — то есть нигде.
**Порядок здесь обязателен: урожай заводится ДО команды `sprint close`.**
Автотег ставится по слагу из `SPRINT.md`, а `sprint close` этот файл очищает;
заведённое после команды остаётся без тега и в первую порцию следующей сессии
не попадёт — молча, потому что пустой `list --tag` выглядит как «урожая не
было». Если так уже вышло, тег ставится руками: `add … --tag sprint:<слаг>`,
слаг берётся из отчёта `sprint close`.
**Провал спринта.** Сработал блокер — спринт распускается (`sprint close
--dissolve --reason …`), недоделанное возвращается в беклог, новый набор
делается после ответа человека. Спринт не «ждёт»: ждать может человек, а
замороженный набор, который нельзя двигать, только мешает.
## Определение готовности
Задача засчитывается сделанной, когда верно **всё**:
1. **Пайплайн задачи пройден до конца** — со своим определением готовности, за
которое отвечает проект: проверки, состав ревью, документация, коммит. Здесь
оно не пересказывается и не подменяется — **форма фиксирована, содержание
даёт `CLAUDE.md` проекта**. Пайплайна нет, задача сделана руками — условие
читается как «проверки проекта зелёные и изменение влито».
2. **Критерии приёмки проверены поимённо** — каждый со своим оракулом, исход по
каждому назван. Это единственное, что добавляет управление задачами: пайплайн
отвечает «сделано по правилам», критерии — «сделано то, что заказывали».
3. **Находки по ходу отданы списком** — исполнитель обязан их **назвать**
(каждую, с пометкой «заведена / не заведена: причина»), но **не обязан
заводить**: заведение интерактивно, оно требует дедупликации против беклога и
кладбища и решений человека. Обязанность **завести урожай** — на закрытии
спринта, ниже. Так автономный исполнитель не оказывается одновременно обязан
завести задачи и не вправе это сделать в одиночку.
### Кто и когда закрывает
**Задачу закрывает агент-оркестратор — тот же, кто её и сделал**, последним шагом
пайплайна, после коммита. Порядок:
1. пайплайн доводит задачу до коммита;
2. **после коммита** зовёт `Skill av-dev-pm:tasks` и закрывает задачу
(`close <slug> --implemented`); строка уходит из `SPRINT.md`;
3. **докладывает исход и по каждому критерию — оракул и наблюдаемый исход.**
Это доклад приёмщику, а не отметка «принято».
**Приёмщик и исполнитель здесь совпадают, и это принято сознательно** — цена
названа в `SKILL.md`, раздел «Стимулы». Поэтому закрытие **не окончательно**, а
доклад по критериям — не формальность: он единственное, по чему приёмка вообще
возможна.
**Порядок «коммит, потом закрытие» обязателен.** Закрытие удаляет файл задачи;
упавший коммит после закрытия оставил бы задачу закрытой без единого следа
работы.
**Само закрытие тоже коммитится, отдельным коммитом.** Удаление файла задачи и
правка индекса — правки в рабочем дереве; пока они не в истории, `SPRINT.md`
ничего не показывает, а `reopen` восстанавливает текст из `HEAD` в узком окне,
которое закончится первым посторонним коммитом. Сообщение про учёт, а не про
работу: `закрыта задача <slug>`.
**Дорога назад существует и обязана быть названа.** Человек на сессии сверил
критерии, и приёмка не сошлась — `tasks.py reopen <slug> --reason "приёмка не
сошлась: …"`:
файл восстанавливается из истории git, строка возвращается в набор идущего
спринта (или в беклог, если спринта нет), строка кладбища снимается. Тело
восстанавливается **на момент удаления** — всё, что было дописано позже, живёт
только в коммите задачи, и это называется в докладе.
### Кто и по чему принимает
Три условия, без которых пункт про критерии не исполняется никем:
1. **Критерии переживают файл задачи.** Файл удаляется при закрытии, поэтому
критерии копируются туда, где их увидит приёмщик. Куда именно — **отвечает
пайплайн проекта, а не слот в `CLAUDE.md`**: он переносит их в `tasks.md`
изменения на шаге заведения change. Проект без пайплайна называет своё место
сам.
2. **Принимает человек на сессии, а не отдельный агент.** Декорреляция
исполнителя и приёмщика в момент закрытия **снята** (решение о снятии и его
цена — в `SKILL.md`, «Стимулы»). Опоры остались три: **сохранённый независимый
отчёт ревью** (при конвейере `av-dev-pipeline` — отчёт триажа в
`openspec/changes/archive/<id>/review/`, до архивации — `changes/<id>/review/`),
`SPRINT.md` под git и `reopen`. Переоценка на сессии и есть момент, когда
критерии видит не исполнитель. **Конвейера ревью в проекте нет — первой опоры
нет тоже**, и это называется строкой доклада, а не обходится молча
(`SKILL.md`, «Стимулы»).
3. **Расхождение — дефект критериев.** Приёмщик правит критерии и возвращает
задачу исполнителю **в этом же спринте**: ответ есть, остаток есть, по тесту
про остаток это не выход из спринта.
## Что врывается в замороженный набор
Только два класса — правило и его обоснование в SKILL.md. Здесь механика:
- вторжение **не добавляет** задачу в набор: `SPRINT.md` остаётся набором под
цель. Внеплановая работа делается и называется в докладе отдельной строкой
«внеплановое: что и почему»;
- если внеплановое требует больше пары часов, честнее распустить спринт, чем
делать вид, что набор соблюдается;
- всё остальное падает в беклог через обычный интейк и ждёт сессии.
## Доклад в конце спринта
Проверяемые якоря, а не пересказ:
- **Цель спринта** и по каждой задаче набора: **хеш коммита**, дословный исход
проверок проекта, **исход по каждому критерию приёмки**.
- **Какие развилки решались** и чем обоснованы.
- **Урожай:** сколько задач заведено, какие вопросы накопились, что вышло из
спринта и почему, что было внеплановым.
- **Поимённая сверка урожая** с независимыми отчётами ревью: каждая отложенная
находка имеет либо слаг, либо строку «не заведена: причина». Нулевой урожай при
непустом отчёте — сигнал, а не благополучие. **Отчётов нет** (проект без
конвейера ревью) — сверять не с чем, и строка доклада говорит именно это, а не
«сверено».
- **Созрела ли порция для сессии.** Решение звать — человека, напоминание —
обязанность агента: `⌈урожай / 8⌉` порций.
- **Границы покрытия** сжатой строкой: что в этом спринте не проверялось вовсе.