# Сессия: четыре шага Одна сессия между спринтами. Порядок шагов — **зависимость, а не список**: переоценивать задачи, не разобрав вопросы, значит переоценивать вслепую; набирать спринт, не переоценив, значит набирать из протухшего. Начинается сессия с `tasks.py check` (и `check --fix`, если дрейф накопился) — результат идёт строкой в доклад. ## Шаг 1. Разбор вопросов `tasks.py list --questions` — всё, что накопилось. Вопрос это решение человека, и разбирается он **пачкой**, а не по одному в момент возникновения: по одному — это дёрганье, пачкой — это сессия. Порядок по каждому вопросу: 1. **Проверь, не отвечен ли он уже** — решением, документом, соседним изменением, самим ходом прошедшего спринта. Отвеченный вопрос не выносится человеку: это самая частая находка и она не требует ничьего решения. 2. **Сформулируй развилку** с вариантами и последствием каждого, рекомендация — первым вариантом. 3. **Вынеси пачкой** через `AskUserQuestion`, не больше трёх за раз. 4. **Ответ записывается в тело задачи, раздел «Вопросы» опустошается**, тег снимается `edit --rm-tag question`, **«зачем» переписывается**: «Решено: …» на вопрос «почему это лежит в беклоге» уже не отвечает. Опустошение раздела — не уборка, а условие взятия: правило и причина в скилле `tasks`, [references/task-format.md](../../tasks/references/task-format.md). **Вопросы на задачах-кандидатах разбираются вне очереди порции** — здесь же, на этой сессии, даже если сама задача в порцию переоценки не попала. Иначе правило «задача с открытым вопросом в набор не берётся» создаёт стимул вопрос не записывать, лишь бы не вычеркнуть задачу из ближайшего спринта. ## Шаг 2. Разбор прошедшего спринта — про процесс, а не про задачи Не «что мы сделали» (это доклад спринта, он уже был), а: - **что сломалось в процессе и почему не поймали** — промах, доехавший до конца; - **сколько на самом деле заняли задачи** против ожидания; - **какие правила не сработали или сработали не так** — в том числе правила этого плагина; - **какие числа пора пересмотреть** — ориентир по размеру спринта, прирост беклога на одну закрытую задачу, время на задачу. Эта обязанность иначе висит ничья: числа, помеченные как «первый замер», не пересматриваются никогда, если их не пересматривает конкретный шаг. **Артефакт обязателен.** Вывод, оставшийся в контексте сессии, не существует: следующая сессия его не увидит. Дом у него один и известен из канона — **`docs/review.md`**: вывод про конвейер и про то, что перестали проверять, идёт в раздел настройки, вывод про воспроизведённый дефект — в журнал. Решение с долгим следом — в `docs/adr/`. Отдельным ритуалом ретроспектива не выделяется: процесс личный, синхронизировать некого. ## Шаг 3. Переоценка задач Цель — выкинуть то, что перестало быть задачей, и вернуть остальному честное состояние. Не «пересмотреть всё», а «пересмотреть порцию до конца». ### Порция и правило остановки Тридцать задач за один заход — это усталость и штамповка: последние десять получат «оставить» не потому, что живы, а потому, что сессия затянулась. - **5–8 задач за порцию.** Размер обоснован усталостью, а не пропускной способностью, и менять его не надо — **надо брать несколько порций за сессию**. - **Сколько порций:** не меньше `⌈урожай прошедшего спринта / 8⌉`. Урожай — это задачи, заведённые за спринт; при урожае в 15 это две-три порции. - **Отбор порций по порядку:** 1. **урожай спринта** — `list --tag sprint:<слаг>`: свежезаведённое ещё не проходило ни одной проверки на нужность. Тег на задачах проставлен автоматически при заведении — руками не метят и не вспоминают. **Слаг берётся из отчёта `sprint close`, а не из `SPRINT.md`:** сессия идёт после закрытия, а закрытие этот файл очищает; 2. дальше **по залежалости** — `list --stale`; 3. по потребности — одна секция целиком, один тег (партия ревью), одна цель (`--goal`), список от пользователя. - **Останавливайся на границе порции**, даже если «ещё чуть-чуть осталось». Между порциями — промежуточный доклад. ### Что делать с каждой задачей Сперва то, что не требует ничьего решения: 1. **Проверь, не сделано ли уже.** Задача, реализованная попутно в соседнем изменении, — самая частая находка. Смотри код, документацию, историю коммитов по ключевым словам. Удаление «как реализованной» деструктивно и без следа (в `REJECTED.md` реализованные не пишутся), поэтому порог улики жёсткий: `close --implemented` только имея **конкретный коммит или строку документа**, закрывающие задачу, и ссылка идёт в доклад. Есть лишь косвенные признаки — не удаляй сам, вынеси в пачку вопросов. Сделана частично → задача сжимается до остатка: тело правишь редактором, заголовок и «зачем» — через `edit`. 2. **Проверь, не отменена ли решением.** Документ, ADR или архивное изменение мог закрыть вопрос иначе — тогда `close --reason "<ссылка на решение>"`. Задача закрывается не только коммитом. 3. **Проверь пересечения.** Две задачи об одном — содержимое в одну, вторую `close --reason "слита с <другой-слаг>"`. Смотри **шире порции**: интейк дедуплицирует новое против существующего, но никогда не пересматривает уже лежащее, и две задачи с одной причиной могут лежать рядом месяцами. 4. **Пере-кластеризуй по общей причине.** Несколько задач, оказавшихся симптомами одного дефекта, сливаются в одну — это находка, которую интейк дать не мог. 5. **Гигиена полей** — протухшее «зачем», вопрос в прозе, снятый ответ, свойство репозитория в рамках, предписание процесса в теле, род работы, разошедшийся с задачей, границы вместо реализации в разделе «Затрагивает». Список и правила — в скилле `tasks`. **Переоценка — то самое место, где беклог добирает род работы и границы:** требовать их на входе значило бы выгонять в заметки то, что должно лежать задачей, а к взятию в спринт они уже обязательны. Затем — то, что решает пользователь: 6. **Жива ли она вообще.** Контекст мог измениться: ушла зависимость, отпал сценарий, обошли иначе. Здесь и звучит вопрос о выкидывании. 7. **Та ли цель — и нужна ли она вообще.** Приоритетов нет, и «повысить» нечего — вместо повышения **смена цели** (`edit --goal <другой>`) или включение в ближайший набор. `feature`, которой не находится цель, — кандидат на выход: новая возможность вне цели это возможность, которой никто не заказывал. Операционной задаче (`fix`, `chore`, `research`) цель не нужна, и выдумывать её здесь не надо. 8. **Задача ли это по-прежнему.** Не проходит тест «готова к взятию» → `edit --type idea`, дальше штурм. Разрослась → это несколько задач под той же целью, дальше декомпозиция. 9. **Переоценка по измеренному.** Спринт производит числа — сколько на самом деле стоит такая работа, что оказалось дороже ожидания. Эти числа меняют цену **других** задач, и именно здесь это применяется: задача, чья цена выросла втрое, а польза осталась прежней, — кандидат на выход. ### Храповик на залежавшихся Сильно залежавшаяся задача — сигнал сама по себе: её либо ни разу не собирались делать, либо нечем взять. Измеряй наблюдаемым — датой последней правки из git (`list --stale` ставит такие первыми); счётчик «сколько сессий пережила» нигде не хранится. Задача из верхних строк `--stale`, которую и этот заход оставляет без изменений, **либо двигается (меняет цель, идёт в набор, уходит с причиной), либо остаётся с явно записанной причиной**, почему её держим (`move --section <та же> --reason …`). Молчаливое «оставить как есть» на давно неподвижной задаче — это решение не принимать решение; запись причины превращает его в осознанное и не даёт тому же вопросу всплыть на следующей сессии. ### Интерактив - Вопросы — через `AskUserQuestion`, **не больше трёх за раз**. Порция в 5–8 задач обычно даёт больше трёх суждений — тогда веди несколько итераций по ≤3, а не по одному на задачу и не одним перегруженным запросом. - К каждому варианту — **предварительное суждение, рекомендация первым вариантом**: «предлагаю выкинуть, потому что …». Пользователю дешевле возразить, чем судить с нуля. - Всё, что решается фактом (сделано / отменено / дублируется), решай сам и показывай списком в докладе, а не выноси в вопросы. Пример одной итерации — три залежавшихся задачи, механику по ним уже разобрали: > **Переоценка: 3 залежавшихся (порция по `--stale`)** > > 1. `versii-kachestvo-repaki` — версии и качество одного тайтла > - Выкинуть *(рекомендую)* — помечена «не боль», за полгода ни разу не возникла > - Оставить под целью `nadyozhnost-razdach` > - Перевести под цель `kachestvo-mediateki` — там она первая в очереди > 2. `backup-sqlite` — бэкап базы > - Оставить под текущей целью *(рекомендую)* — не сработала, но риск реальный > - Взять в ближайший набор — без бэкапа ретеншн опасен > - Выкинуть > 3. `guessit-sputnik` — вынести распознавание в сервис-спутник > - Понизить до `[idea]` *(рекомендую)* — не проходит тест «готова к взятию» > - Оставить задачей Каждый вариант несёт причину — ту самую, что уедет в `--reason`. Ответы применяй сразу и, если в порции осталось ещё, следующей итерацией показывай следующие ≤3. ## Шаг 4. Выбор цели и набор спринта 1. **Покажи состояние проекта**: секцию `Готово` (что приложение уже умеет — это половина ответа на «где мы»), затем `Запланировано` с обоснованием очереди, `Направления`, и по каждой цели-кандидату — сколько под ней задач без открытых вопросов (`list --goal <слаг>`). Цель без готовых задач набором не станет: её сперва надо декомпозировать. 2. **Цель называет человек.** Это продуктовое решение, а не механика: агент предлагает и объясняет, но не выбирает. 3. **Набор собирает агент** — `sprint start --goal <слаг>`, затем `sprint take …`. Скрипт не даст взять цель, идею, задачу с чужой целью, с открытым вопросом, без критериев приёмки, без рода работы или без раздела «Затрагивает». Задача без цели вовсе (`fix`, `chore`, `research`) берётся свободно — операционная работа входит в набор помимо его цели. 4. **Набор показывается человеку до старта работ.** Показ — это и есть момент заморозки: после него набор не двигается. **В показе называется состав по роду работы** — три `fix` и ни одной `feature` под целью развития это разговор про цель, а не про набор, и увидеть его надо до заморозки, а не в докладе по итогам. Здесь же последний дешёвый момент заметить **разнородную задачу**: раздел «Затрагивает» показывает границы до того, как заведено предложение об изменении. Строка, которая одна тянет задачу на ступень выше остального перечня, — кандидат на разрез (шов — в `tasks`, `references/split.md`). Замеченная здесь, она стоит одного `edit`; замеченная на ревью — выброшенного предложения. 5. Задача, которой для взятия не хватает только критериев приёмки, границ или рода, дописывается здесь же — 2–5 утверждений с оракулами, перечень затрагиваемых границ, `--kind`. Но если для этого нужен ответ человека, это вопрос, и задача в набор не идёт. **Размер — ориентир, а не закон:** 5–8 задач. Можно взять больше, можно меньше — набор под цель важнее круглого числа; одна крупная задача спринтом тоже бывает. ## Доклад сессии - Что просмотрено: N из M, сколько порций, по какому признаку отобраны. - Вопросы: разобрано N, из них отвечено без человека N, снято тегов N. - Разбор процесса: что записано и куда. - Изменения списком: удалено как реализованное (со ссылками), ушло без реализации (с причинами), понижено до идей, слито, сменило цель. - Новый спринт: цель, набор со слагами, дата, состав по роду работы. - **Границы покрытия**: сколько задач не трогали и какие именно секции, теги или цели остались — иначе доклад читается как «беклог разобран». - `tasks.py check` после правок — результат строкой.