# Сессия: четыре шага Одна сессия между спринтами. Порядок шагов — **зависимость, а не список**: переоценивать задачи, не разобрав вопросы, значит переоценивать вслепую; набирать спринт, не переоценив, значит набирать из протухшего. Начинается сессия с `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. Разбор прошедшего спринта — про процесс, а не про задачи Не «что мы сделали» (это доклад спринта, он уже был), а: - **что сломалось в процессе и почему не поймали** — промах, доехавший до конца; - **что оказалось дороже, чем выглядело при заведении** — не число, а сам факт и причина: чего не было видно в постановке; - **какие правила не сработали или сработали не так** — в том числе правила этого плагина. Замеров процесс не ведёт намеренно: оценки в очках и velocity не взяты («[Почему не Scrum](../SKILL.md#почему-не-scrum)»), а спринт ограничен объёмом, а не временем — сравнивать «сколько заняло» не с чем. Разбор здесь качественный, и это не упущение. **Артефакт обязателен.** Вывод, оставшийся в контексте сессии, не существует: следующая сессия его не увидит. Дом у него один и известен из канона — **`docs/review.md`**: вывод про конвейер и про то, что перестали проверять, идёт в раздел настройки, вывод про воспроизведённый дефект — в журнал. Решение с долгим следом — в `docs/adr/`. Отдельным ритуалом ретроспектива не выделяется: процесс личный, синхронизировать некого. **Здесь же зовутся оба судьи документов** — на весь канон разом, а не на пачку, отобранную работой: - **`doc-consistency`** — согласованность документов между собой и с openspec: факт в двух домах, прямое противоречие, поведение в `architecture.md` вместо спек, ADR без парного статуса при замене, число без провенанса; - **`doc-code-drift`** — сверка с кодом по закрытому перечню фактов: имя основной ветки, команды, пути, внешние зависимости поимённо, настройки с числовым значением, единые точки проекта, capability. Раз в спринт, а не чаще, и причина в цене: оба на `opus`, а второй ещё и читает репозиторий. Но и не реже — **спринт это ровно то, что двигает код и документы**: переименованная цель сборки, ушедшая зависимость, второй способ делать то, что обзор объявил единственным; факт, дописанный в `architecture.md`, уже живущий в `CLAUDE.md`. Протухшее и раздвоившееся неотличимо от свежего, и по нему принимают решения, пока кто-нибудь не наткнётся. **Пачка — весь канон, и это не расточительство, а охват.** Отбор пачки работой оставлял без присмотра ровно то, чего работа не касалась: правка, отменившая решение, живёт в одном документе, а парный статус нужен в другом. Канон мал, раз в спринт он читается целиком. Находки обоих — обычный материал переоценки: строка на замену идёт в документ сразу, работа больше чем на абзац становится задачей типа `chore`. **Позвал — скажи в докладе, кого именно позвал, и приложи границы покрытия**; не позвал — скажи и это, иначе доклад читается как «сверено». ## Шаг 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`. **Переоценка — то самое место, где беклог добирает тип и разделы его схемы:** требовать их на входе значило бы выгонять в заметки то, что должно лежать задачей, а к взятию в спринт они уже обязательны. Сколько записей готово к взятию, печатает блок здоровья `check`, — по этому числу и видно, добрала переоценка или нет. Затем — то, что решает пользователь: 6. **Жива ли она вообще.** Контекст мог измениться: ушла зависимость, отпал сценарий, обошли иначе. Здесь и звучит вопрос о выкидывании. 7. **Та ли цель — и нужна ли она вообще.** Приоритетов нет, и «повысить» нечего — вместо повышения **смена цели** (`edit --goal <другой>`) или включение в ближайший набор. `feature`, которой не находится цель, — кандидат на выход: новая возможность вне цели это возможность, которой никто не заказывал. Операционной задаче (`fix`, `chore`, `research`) цель не нужна, и выдумывать её здесь не надо. **Отменяется и сама цель** — когда замысел оказался неверен, а не когда задача выбрала не ту. Тогда порция расширяется до всех задач этой цели: каждую либо закрыть своей причиной, либо перевесить на другую цель, и только потом закрыть цель. Порядок и почему он такой — [task-goal.md](../../tasks/references/task-goal.md#отменённая-цель--сперва-задачи-потом-цель). Здесь этому и место: отмена цели это разбор её задач, а разбор задач — этот шаг. 8. **Задача ли это по-прежнему.** Не проходит тест «готова к взятию» → `edit --type research` и опустошённый раздел «Вопрос», то есть сырьё; дальше штурм. Разрослась → это несколько задач под той же целью, дальше декомпозиция. 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` — вынести распознавание в сервис-спутник > - Понизить до сырья (`--type research`) *(рекомендую)* — не проходит тест «готова к взятию» > - Оставить задачей Каждый вариант несёт причину — ту самую, что уедет в `--reason`. Ответы применяй сразу и, если в порции осталось ещё, следующей итерацией показывай следующие ≤3. ## Шаг 4. Выбор цели и набор спринта 1. **Покажи состояние проекта**: секцию `Готово` (что приложение уже умеет — это половина ответа на «где мы»), затем `Запланировано` с обоснованием очереди, `Направления`, и по каждой цели-кандидату — сколько под ней задач без открытых вопросов (`list --goal <слаг>`). Цель без готовых задач набором не станет: её сперва надо декомпозировать. 2. **Цель называет человек.** Это продуктовое решение, а не механика: агент предлагает и объясняет, но не выбирает. 3. **Набор собирает агент** — `sprint start --goal <слаг>`, затем `sprint take …`. Скрипт не даст взять цель, задачу с чужой целью, с открытым вопросом, без типа и **без разделов, которых требует её тип** (у `fix` это в том числе `Воспроизведение`, у `research` — `Вопрос` и `Куда ляжет ответ`, и сырьё поэтому не берётся вовсе). Задача без цели (`fix`, `chore`, `research`) берётся свободно — операционная работа входит в набор помимо его цели. 4. **Набор показывается человеку до старта работ.** Показ — это и есть момент заморозки: после него набор не двигается. **В показе называется состав по типам** — три `fix` и ни одной `feature` под целью развития это разговор про цель, а не про набор, и увидеть его надо до заморозки, а не в докладе по итогам. Здесь же последний дешёвый момент заметить **разнородную задачу**: раздел «Затрагивает» показывает границы до того, как заведено предложение об изменении. Строка, которая одна тянет задачу на ступень выше остального перечня, — кандидат на разрез (шов — в `tasks`, `references/split.md`). Замеченная здесь, она стоит одного `edit`; замеченная на ревью — выброшенного предложения. 5. Задача, которой для взятия не хватает только разделов её типа, дописывается здесь же — критерии с оракулами, перечень границ, шаги воспроизведения. Но если для этого нужен ответ человека, это вопрос, и задача в набор не идёт. **Размер — ориентир, а не закон:** 5–8 задач. Можно взять больше, можно меньше — набор под цель важнее круглого числа; одна крупная задача спринтом тоже бывает. ## Доклад сессии - Что просмотрено: N из M, сколько порций, по какому признаку отобраны. - Вопросы: разобрано N, из них отвечено без человека N, снято тегов N. - Разбор процесса: что записано и куда. - Сверка документов с кодом: звался ли `doc-code-drift`, что проверено из названного, что разошлось. - Изменения списком: удалено как реализованное (со ссылками), ушло без реализации (с причинами), понижено до сырья, слито, сменило тип или цель. - Новый спринт: цель, набор со слагами, дата, состав по типам. - **Границы покрытия**: сколько задач не трогали и какие именно секции, теги или цели остались — иначе доклад читается как «беклог разобран». - `tasks.py check` после правок — результат строкой.