Критерий: диаграмма заводится, если структура граф или автомат, а проза вынуждена его пересказывать. Где структура таблица соответствий — чек-лист синка, профили ревью, коды выхода — не заводится: дублировала бы таблицу и разошлась с ней. tasks: жизненный цикл записи по индексам — состояния это где числится строка, файл items/ не двигается ни на одном переходе. session: четыре шага сессии; текст говорил «это зависимость, а не список», но зависимости не показывал — теперь на рёбрах написано, что ломается. sprint.md: исходы задачи в спринте плюс два ребра, где порядок нарушается молча — урожай до sprint close и блокер в обход исходов. task-pipeline: одиннадцать шагов с развилкой «тривиальная» и досрочным исходом «крупнее задачи». promote.md: храповик находка → конвенция → правило → удаление, с обратным ребром; обязательность третьего шага теперь видна как ребро. calibration.md: счётчик retune до drop — таблица вердиктов его выразить не может, автомат может. README: граф вызовов между плагинами; односторонность зависимости pipeline → pm видна сразу. Все девять блоков прогнаны через mermaid-cli. README-схема и автомат калибровки переверстаны после просмотра: subgraph'ы ломали раскладку, self-loop наезжал подписями. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
260 lines
21 KiB
Markdown
260 lines
21 KiB
Markdown
---
|
||
name: session
|
||
description: Ритуал между спринтами и ведение самого спринта: разбор накопившихся вопросов, разбор прошедшего спринта про процесс, переоценка задач порциями, выбор цели и набор нового спринта с заморозкой. Плюс правила по ходу спринта — что врывается в замороженный набор, чем вопрос отличается от блокера, когда задача выходит из спринта, что считается сделанным и что идёт в доклад. Использовать, когда просят закрыть или начать спринт, собрать набор, разобрать вопросы, провести груминг/переоценку/ретроспективу, решить «что делать дальше» или доложить итоги. Формат и содержимое задач — скилл tasks.
|
||
---
|
||
|
||
# Сессия между спринтами
|
||
|
||
Работа идёт спринтами: **набор задач под одну цель, замороженный до конца
|
||
спринта**. Между спринтами — одна сессия из четырёх шагов. Этот скилл владеет
|
||
**ритуалом**: как сессия проводится и как спринт ведётся. Форматом и содержимым
|
||
задач владеет скилл `tasks`, выполнением задачи — пайплайн проекта.
|
||
|
||
## Почему не Scrum
|
||
|
||
Терминология близка — спринт, груминг, определение готовности, ретроспектива, —
|
||
и это удобно: не нужно изобретать слова. Но добрая половина Scrum существует
|
||
ради синхронизации людей, которых здесь нет.
|
||
|
||
**Не берём:** тайм-бокс (спринт ограничен объёмом, а не временем), velocity и
|
||
оценки в очках, ежедневный стендап (стендап — это и есть диалог), планирование
|
||
отдельно от груминга (владелец беклога один), роль скрам-мастера.
|
||
|
||
**Берём:** цель спринта, заморозку набора, определение готовности, груминг —
|
||
каждое потому, что снимает решение, которое иначе принимается заново каждый раз.
|
||
**Ретроспективу берём содержанием, но не отдельным ритуалом:** она шаг той же
|
||
сессии. Процесс личный, синхронизировать некого, а отдельная встреча ради трёх
|
||
вопросов — та самая плата ритуалом без выгоды.
|
||
|
||
## Роли
|
||
|
||
**Человек** выбирает цель спринта, разбирает вопросы, держит право на
|
||
необратимое и на истину в самих данных.
|
||
|
||
**Агент — оркестрация.** Он собирает набор под названную цель, ставит задачи,
|
||
принимает отчёты и докладывает. Кто именно делает задачу — исполнитель, сабагент,
|
||
пайплайн — дело проекта; сессия про это не знает и знать не должна.
|
||
|
||
## Единицы
|
||
|
||
- **Цель** — то, ради чего набирается спринт. Файл `[goal]`, перечисленный в
|
||
`PLAN.md`. Цель постоянна: живёт, пока живёт направление.
|
||
- **Задача** — то, что мерджится целиком и даёт видимую пользу.
|
||
- **Вопрос** — решение человека. Не останавливает начатую работу, но **блокирует
|
||
взятие** задачи в спринт. Живёт внутри файла задачи разделом «Вопросы» и тегом
|
||
`question`.
|
||
- **Блокер** — состояние, когда спринт не может продолжаться **ни одной**
|
||
задачей.
|
||
- **Спринт** — набор задач под одну цель, замороженный до его конца.
|
||
|
||
## Вопрос, блокер, необратимое
|
||
|
||
| | Что это | Когда спрашиваем | Что останавливает |
|
||
| --- | --- | --- | --- |
|
||
| **Вопрос** | решение человека | на сессии, пачкой | взятие задачи в спринт |
|
||
| **Блокер** | спринт не может продолжаться ни одной задачей | немедленно | всё |
|
||
|
||
Право на **необратимое** — третье и отдельное: что именно необратимо, называет
|
||
`CLAUDE.md` проекта, и спрашивается оно всегда, независимо от спринта.
|
||
|
||
**Блокер определяется исходом, а не одновременностью.** Встали разом или
|
||
высыпались из спринта по одной — если продолжать нечем, это блокер: спринт
|
||
распускается (`sprint close --dissolve --reason …`), человек спрашивается
|
||
немедленно. Иначе спринт, из которого задачи вышли поштучно, выглядел бы штатно
|
||
завершённым, а вопросы тихо ждали бы сессии.
|
||
|
||
**Отличать вопрос от застревания.** Правило про остаток принадлежит управлению
|
||
задачами: оно решает, **сделана задача или вышла**, а это исход планирования, не
|
||
исполнения. **Ниже канонический текст; пайплайн проекта на него ссылается, а не
|
||
пересказывает** — два экземпляра одного правила разъезжаются, и разъезжаются
|
||
незаметно, потому что расхождение видно только на редком входе.
|
||
|
||
> Есть остаток, который доводится без ответа, — задача продолжается, вопрос
|
||
> записывается в файл. Остатка нет — задача выходит из спринта.
|
||
|
||
С двумя оговорками, без которых тест ошибается:
|
||
|
||
> **Остаток, который материализует нерешённое** — записывает в хранилище,
|
||
> журнал, витрину **или наружу** состояние, зависящее от неотвеченного вопроса,
|
||
> — **не остаток**. Решение поднимается до начала записи: откатить запись
|
||
> дороже, чем подождать ответ, а иногда невозможно. «Наружу» — часть правила, а
|
||
> не пример: выкладка, публикация и отправка данных третьей стороне не
|
||
> откатываются тем более.
|
||
|
||
> **Пол для остатка:** остаток, из которого пропала польза, названная в «зачем», —
|
||
> это не сделанная задача, а вышедшая из спринта.
|
||
|
||
## Заморозка набора
|
||
|
||
**Цель одна.** Набор служит ей; задача, не служащая цели, в спринт не попадает,
|
||
даже если взять удобно (`sprint take` это и запрещает). **Задача с открытым
|
||
вопросом в набор не берётся.**
|
||
|
||
**Новая работа падает в беклог, а не в идущий спринт.** Решение «врываться или
|
||
отложить» принимается один раз правилом, а не заново каждый раз. Врывается
|
||
только два класса:
|
||
|
||
1. **Необратимый ущерб** — потеря, порча или утечка данных: то, что не чинится
|
||
доделкой потом.
|
||
2. **Сломан общий станок** — красная проверка, на которой стоит определение
|
||
готовности **всех** задач набора. Это не новая работа, а починка того, на чём
|
||
делается вся остальная.
|
||
|
||
Что в проекте считается необратимым ущербом и что — общим станком, называет
|
||
`CLAUDE.md` проекта. Не названо — спрашиваем человека, а не решаем сами.
|
||
|
||
**Конец спринта** — когда каждая задача набора либо сделана, либо вышла с
|
||
записанной причиной. Не «все сделаны»: иначе одна застрявшая задача держит
|
||
спринт бесконечно. Пустой набор закрывается `sprint close` — скрипт не даст
|
||
закрыть непустой.
|
||
|
||
Ведение спринта целиком — исходы задачи, определение готовности, приёмка,
|
||
доклад — [references/sprint.md](references/sprint.md).
|
||
|
||
## Сессия: четыре шага в этом порядке
|
||
|
||
Это зависимость, а не список.
|
||
|
||
1. **Разбор вопросов.**
|
||
2. **Разбор прошедшего спринта — про процесс, а не про задачи.**
|
||
3. **Переоценка задач** порциями.
|
||
4. **Выбор цели и набор спринта.** Цель называет человек, набор собирает агент и
|
||
показывает **до старта работ**.
|
||
|
||
Рёбра подписаны тем, что ломается при их нарушении:
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
check["tasks.py check (+ --fix)<br/>результат — строкой в доклад"]
|
||
s1["1. Разбор вопросов<br/>пачкой, не больше трёх за раз"]
|
||
s2["2. Разбор прошедшего спринта<br/>про процесс → docs/review.md"]
|
||
s3["3. Переоценка задач порциями"]
|
||
s4["4. Цель называет человек,<br/>набор собирает агент"]
|
||
sprint["спринт: набор заморожен"]
|
||
|
||
check --> s1
|
||
s1 --> s2
|
||
s2 --> s3
|
||
s1 -->|"неотвеченный вопрос → переоценка вслепую"| s3
|
||
s3 -->|"без переоценки набор берётся из протухшего"| s4
|
||
s4 --> sprint
|
||
```
|
||
|
||
Процедура каждого шага, размер и отбор порции, храповик на залежавшихся, формат
|
||
интерактива и доклад — [references/cadence.md](references/cadence.md).
|
||
|
||
## Инструмент
|
||
|
||
Тот же `tasks.py`, что у скилла `tasks` — оба скилла в одном плагине, путь
|
||
общий: `tk="$CLAUDE_PLUGIN_ROOT/skills/tasks/scripts/tasks.py"`. Сессии нужны
|
||
прежде всего:
|
||
|
||
```
|
||
python3 $tk check --dir D # с этого начинается любая сессия
|
||
python3 $tk list --dir D --questions # шаг 1: что накопилось
|
||
python3 $tk list --dir D --tag sprint:<слаг> # шаг 3: урожай спринта, первая порция
|
||
python3 $tk list --dir D --stale # шаг 3: дальше по залежалости
|
||
python3 $tk list --dir D --goal <слаг> # шаг 4: кандидаты под названную цель
|
||
python3 $tk sprint start --dir D --goal <слаг> # шаг 4: заводит и слаг спринта
|
||
python3 $tk sprint take --dir D <слаг> … # шаг 4: набор
|
||
python3 $tk sprint close --dir D # конец спринта; --dissolve при блокере
|
||
python3 $tk reopen <слаг> --dir D --reason … # приёмка не сошлась после закрытия
|
||
```
|
||
|
||
`D` — каталог задач проекта, по канону всегда `docs/tasks`; `--dir` передаётся
|
||
явно каждой командой. Вызов из чужого контекста описан в скилле `tasks`
|
||
(«Переносимость»). **Коды выхода** — там же: 1 это дрейф в беклоге, 3 это
|
||
«каталога нет», и ветвиться на них надо по-разному.
|
||
|
||
**Слаг спринта заводит `sprint start`** (по умолчанию — дата) и пишет его в
|
||
`SPRINT.md`; всё заведённое **при открытом спринте** помечается `sprint:<слаг>`
|
||
автоматически. Поэтому «первая порция — урожай прошедшего спринта» работает без
|
||
чьей-либо памяти — но ровно до команды `sprint close`, которая `SPRINT.md`
|
||
очищает. Отсюда порядок: **урожай заводится до закрытия, слаг для сессии берётся
|
||
из отчёта `sprint close`** ([references/sprint.md](references/sprint.md)).
|
||
|
||
Правки задач делаются мутациями (`edit`, `move`, `close`), а не редактором:
|
||
руками правится только тело файла. Это правило скилла `tasks`, здесь оно не
|
||
пересказывается.
|
||
|
||
## Стимулы, которые процесс создаёт
|
||
|
||
Правило, которое можно обойти в свою пользу, будет обойдено.
|
||
|
||
**Приёмщик и исполнитель здесь совпадают, и это надо назвать вслух.** Задачу
|
||
закрывает и двигает по индексам агент-оркестратор — тот же, кто её и сделал.
|
||
Прежде границу держала механика: моста между плагинами не было, и закрыть задачу
|
||
пайплайн физически не мог. Теперь мост есть, и защита у трёх обходов ниже —
|
||
**только текстовая**. Опоры, которые остались настоящими:
|
||
|
||
- **независимый отчёт ревью** — артефакт, написанный не исполнителем; по нему
|
||
сверяют состав прогона и урожай. Где он лежит, знает пайплайн проекта; при
|
||
конвейере `av-dev-pipeline` это отчёт триажа в
|
||
`openspec/changes/archive/<id>/review/` (до архивации — `changes/<id>/review/`);
|
||
- **`SPRINT.md` под git** — `git log -p` показывает, что и когда было закрыто.
|
||
Работает, только если закрытие **закоммичено**: удаление файла задачи и правка
|
||
индекса, оставшиеся в рабочем дереве, никакой истории не образуют;
|
||
- **`reopen <слаг> --reason`** — закрытие не окончательно. Приёмка человеком на
|
||
сессии его отменяет, и это штатная операция, а не скандал.
|
||
|
||
Известные обходы:
|
||
|
||
- **Скрыть блокер** — он останавливает всё и выглядит как провал исполнителя.
|
||
Защита: тест про остаток плюс прямая запись, что **объявление блокера
|
||
неудачей не считается**.
|
||
- **Не записать вопрос** на задаче-кандидате, чтобы не вычеркнуть её из
|
||
ближайшего набора. Защита: вопросы кандидатов разбираются на той же сессии
|
||
**вне очереди порции**.
|
||
- **Занизить критерии приёмки**, раз они пол. Защита ослаблена: правит их тот же,
|
||
кто по ним отчитывается. Остаётся требование, что расхождение критериев с
|
||
сутью — **дефект критериев, о котором сообщают, а не молча дорабатывают**, и
|
||
переоценка на сессии, где критерии видит человек.
|
||
- **Сжать задачу до остатка** и отчитаться «сделана». Защита ослаблена там же.
|
||
Пол для остатка — польза, названная в «зачем»; проверяет его человек при приёмке,
|
||
и `reopen` — его инструмент.
|
||
- **Занизить урожай** — не заводить найденное по ходу. Защита: поимённая сверка
|
||
с **сохранённым независимым отчётом**, а не с прозой исполнителя. Каждая
|
||
отложенная находка имеет либо слаг, либо строку «не заведена: причина».
|
||
Нулевой урожай при непустом отчёте виден сразу.
|
||
|
||
**Проект без конвейера ревью — независимого отчёта нет, и это надо сказать, а не
|
||
обойти молча.** Задачи делались руками или чужим пайплайном, сверять урожай не с
|
||
чем: остаётся проза исполнителя, то есть тот же взгляд, что и у автора. Тогда
|
||
защита от занижения урожая **снята**, и доклад спринта обязан нести строку «урожай
|
||
сверялся с отчётом исполнителя — независимого отчёта в проекте нет». Дальше это
|
||
решение человека: завести конвейер, принимать выборочной перепроверкой или
|
||
согласиться с ценой. Молчание здесь хуже любого из трёх исходов.
|
||
|
||
Стимулы внутри пайплайна задачи (занизить требования к проверке, пропустить
|
||
проход) принадлежат ему и защищены там же.
|
||
|
||
## Слоты проекта
|
||
|
||
Сессия не знает ни языка, ни сборки, ни CI. Часть проектного отвечает
|
||
[канон](../canon/references/canon.md) структурой: разбор процесса (шаг 2) живёт
|
||
в `docs/review.md`, оракулы и «чем краснеет безусловно» — в семантике гейта в
|
||
`CLAUDE.md`. Остальное проект **дописывает в `CLAUDE.md`**:
|
||
|
||
1. **Пайплайн задачи** — чем задача выполняется и что входит в его определение
|
||
готовности. Сессия требует только форму: пайплайн пройден + критерии приёмки
|
||
проверены поимённо.
|
||
2. **Общий станок** — какая проверка, покраснев, врывается в замороженный
|
||
спринт.
|
||
3. **Необратимое** — что спрашивается у человека всегда (тот же слот, что у
|
||
скилла `tasks`; дом один).
|
||
4. **Ориентир по размеру спринта**, если он замерялся. Умолчание — 5–8 задач, и
|
||
это **ориентир, а не закон**.
|
||
|
||
Слота «куда копируются критерии приёмки» здесь нет намеренно: на него отвечает
|
||
**пайплайн проекта**, перенося их в описание изменения при его заведении. Проект
|
||
без пайплайна называет своё место сам, в слоте 1.
|
||
|
||
Числа проекта (сколько задач в спринте, сколько времени на задачу, каков прирост
|
||
беклога) — предмет шага 2, а не константы этого скилла.
|
||
|
||
## Чего этот скилл не делает
|
||
|
||
Не пишет код и не выполняет задачи. Не заводит и не переоформляет задачи сам по
|
||
себе — формат и содержимое ведёт `tasks` (сессия зовёт его операции). Не решает
|
||
за человека, какая цель следующая. Не двигает набор идущего спринта.
|