Files
dev-skills/av-dev/skills/task-groom/references/portions.md
T
av de12a4d8a3 слияние: три плагина стали одним av-dev, скиллы получили префиксы
Каталоги, агенты и общие дома переехали в av-dev/; скиллы названы по прежнему
плагину — doc-*, task-*, code-*, с двумя смысловыми именами вместо тавтологии:
doc-sync вместо docs, task-track вместо tasks. Манифесты сведены к двум
плагинам. Пространства имён вызовов и пути внутри дерева переписаны машинно;
проза, которая называет прежние плагины отдельными, идёт следующим шагом.
2026-08-13 10:10:51 +03:00

164 lines
14 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.
# Порции, разбор и расстановка
Процедура шагов 2–4 груминга. Рамка и правила — [SKILL.md](../SKILL.md).
Начинается всё с `tasks.py check``check --fix`, если дрейф накопился) —
результат идёт строкой в доклад.
## Шаг 2. Разбор вопросов
`tasks.py list --questions` — всё, что накопилось. Порядок по каждому вопросу:
1. **Проверь, не отвечен ли он уже** — решением, документом, соседним
изменением, самим ходом сделанной с тех пор работы. Отвеченный вопрос не
выносится человеку: это самая частая находка и она не требует ничьего
решения.
2. **Сформулируй развилку** с вариантами и последствием каждого, рекомендация —
первым вариантом.
3. **Вынеси пачкой** через `AskUserQuestion`, не больше трёх за раз.
4. **Запиши ответ в тело задачи, опустоши раздел «Вопросы»**, сними тег
(`edit <slug> --rm-tag question`), **перепиши «зачем»**: «Решено: …» на вопрос
«почему это лежит в беклоге» уже не отвечает. Опустошение раздела — не
уборка, а условие взятия: правило и причина в скилле `tasks`,
[references/task-format.md](../../tasks/references/task-format.md).
**Вопросы на верхних строках очереди разбираются вне очереди порции** — здесь
же, даже если сама задача в порцию переоценки не попала. Иначе правило «задача с
открытым вопросом в работу не берётся» создаёт стимул вопрос не записывать, лишь
бы не вычеркнуть задачу из ближайшей работы.
## Шаг 3. Что перестало быть важным
Цель — выкинуть то, что перестало быть задачей, и вернуть остальному честное
состояние. Не «пересмотреть всё», а «пересмотреть порцию до конца».
### Порция и правило остановки
- **5–8 задач за порцию.** Размер обоснован усталостью, а не пропускной
способностью, и менять его не надо — **надо брать несколько порций**.
- **Отбор порций по порядку:**
1. **свежее** — заведённое с прошлого груминга: оно ещё не проходило ни одной
проверки на нужность. Свежесть меряется git'ом, как и залежалость, — датой
появления файла в истории;
2. дальше **по залежалости**`list --stale`;
3. по потребности — одна секция целиком, один тег (партия ревью), одна цель
(`--goal`), список от человека.
- **Останавливайся на границе порции**, даже если «ещё чуть-чуть осталось».
Между порциями — промежуточный доклад.
### Что делать с каждой задачей
Сперва то, что не требует ничьего решения:
1. **Проверь, не сделано ли уже.** Задача, реализованная попутно в соседнем
изменении, — самая частая находка. Смотри код, документацию, историю коммитов
по ключевым словам. Удаление «как реализованной» деструктивно и без следа
`REJECTED.md` реализованные не пишутся), поэтому порог улики жёсткий:
`close <slug> --implemented` только имея **конкретный коммит или строку
документа**, закрывающие задачу, и ссылка идёт в доклад. Есть лишь косвенные
признаки — не удаляй сам, вынеси в пачку вопросов. Сделана частично → задача
сжимается до остатка: тело правишь редактором, заголовок и «зачем» — через
`edit`.
2. **Проверь, не отменена ли решением.** Документ, ADR или архивное изменение
мог закрыть вопрос иначе — тогда `close <slug> --reason "<ссылка на
решение>"`. Задача закрывается не только коммитом.
3. **Проверь пересечения.** Две задачи об одном — содержимое в одну, вторую
`close <slug> --reason "слита с <другой-слаг>"`. Смотри **шире порции**:
интейк дедуплицирует новое против существующего, но никогда не пересматривает
уже лежащее, и две задачи с одной причиной могут лежать рядом месяцами.
4. **Пере-кластеризуй по общей причине.** Несколько задач, оказавшихся симптомами
одного дефекта, сливаются в одну — это находка, которую интейк дать не мог.
5. **Гигиена полей** — протухшее «зачем», вопрос в прозе, снятый ответ, свойство
репозитория в рамках, предписание процесса в теле, тип, разошедшийся с
задачей, границы вместо реализации в разделе «Затрагивает». Список и правила —
в скилле `tasks`. **Груминг — то самое место, где беклог добирает тип и
разделы его схемы:** требовать их на входе значило бы выгонять в заметки то,
что должно лежать задачей, а к взятию в работу они уже обязательны (`ready`).
Блок здоровья `check` печатает, сколько записей готово к взятию, — по этому
числу и видно, добрал ли груминг.
Гигиена — **побочный продукт, а не предмет**. Тридцать полей вместо трёх
решений о важности означают, что груминг не состоялся.
Затем — то, что решает человек:
6. **Жива ли она вообще.** Контекст мог измениться: ушла зависимость, отпал
сценарий, обошли иначе. Здесь и звучит вопрос, выкидывать ли.
7. **Та ли цель — и нужна ли она вообще.** `feature`, которой не находится цель,
— кандидат на выход: новая возможность вне цели это возможность, которой никто
не заказывал. Операционной задаче (`fix`, `chore`, `research`) цель не нужна,
и выдумывать её здесь не надо.
**Отменяется и сама цель** — когда замысел оказался неверен, а не когда
задача выбрала не ту. Тогда порция расширяется до всех задач этой цели: каждую
либо закрыть своей причиной, либо перевесить на другую цель, и только потом
закрыть цель. Порядок и почему он такой —
[task-goal.md](../../tasks/references/task-goal.md#отменённая-цель--сперва-задачи-потом-цель).
8. **Задача ли это по-прежнему.** Не проходит `ready` по существу, а не по
недописанным разделам → `edit <slug> --type research` и опустошённый раздел
«Вопрос», то есть сырьё; дальше штурм. Разрослась → это несколько задач под
той же целью, дальше декомпозиция.
9. **Не подешевела ли она.** Сделанная с прошлого раза работа меняет цену
**других** задач: рядом с только что тронутым кодом та же работа стоит меньше.
Это довод и на шаге 4 — задача, внезапно подешевевшая, поднимается в очереди
не потому, что стала важнее, а потому, что окно открыто.
### Храповик на залежавшихся
Сильно залежавшаяся задача — сигнал сама по себе: её либо ни разу не собирались
делать, либо нечем взять. Измеряй наблюдаемым — датой последней правки из git
(`list --stale` ставит такие первыми); счётчик «сколько грумингов пережила»
нигде не хранится.
Задача из верхних строк `--stale`, которую и этот заход оставляет без изменений,
**либо двигается (меняет цель, поднимается в очереди, уходит с причиной), либо
остаётся с явно записанной причиной**, почему её держим (`move <slug> --reason
…` — без `--section` секция берётся текущая). Молчаливое «оставить как есть» на
давно неподвижной задаче — это решение не принимать решение; запись причины
превращает его в осознанное и не даёт тому же вопросу всплыть на следующем
груминге.
## Шаг 4. Что важно сейчас — расстановка
Разбирается **верх очереди**, а не весь беклог: первые три-пять строк каждой
секции. Ниже пятой строки порядок всё равно перестаёт что-либо значить.
1. **Покажи текущий верх**`list --index backlog`, по секциям, в том порядке,
в каком строки лежат. Плюс состояние проекта из роадмапа: секция `Готово`
отвечает на «где мы», `Запланировано` — на «куда шли».
2. **Спрашивай сравнением, а не оценкой.** «Что из этих двух делают раньше»
имеет проверяемый ответ, «насколько важна эта задача» — нет. Веди попарно и
сверху: что первое, что после него.
3. **Двигай командой, с причиной**`move <slug> --after <другой> --reason …`
или `move <slug> --first --reason …`. Довод берётся из перечня в
[SKILL.md](../SKILL.md#приоритет-как-его-расставляют): сломано сейчас,
разблокирует остальное, дешевеет от сделанного, дорожает от ожидания,
названная цель.
4. **Проверь верх на готовность**`tasks.py ready <слаг> …` по первым строкам.
Задача, стоящая первой и не проходящая `ready`, — это очередь, которая врёт:
взять её нельзя. Либо дописывается здесь же, либо уступает место.
Пример одной итерации:
> **Верх секции «Игра», сейчас в таком порядке:**
> `board-render-once` · `draw-before-full-board` · `move-parse-strict`
>
> 1. Что делаем первым?
> - `draw-before-full-board` *(рекомендую)* — ничья объявляется на неполном
> поле: игра врёт о результате, это сломано сейчас
> - `board-render-once` — печать поля дублируется; мешает всякой правке
> отрисовки, то есть разблокирует остальное
> - оставить как есть
> 2. `move-parse-strict` — третьей или выше?
> - Оставить третьей *(рекомендую)* — ошибка ввода видна игроку сразу
> - Поднять второй: тот же разбор трогает `board-render-once`, окно открыто
Каждый вариант несёт причину — ту самую, что уедет в `--reason`.
## Что делать, если разбирать нечего
Беклог пуст или в нём три задачи и все живые — груминг кончается за минуту, и
это законный исход. Скажи строкой: очередь такая-то, сдвигать нечего. Придумывать
работу, чтобы груминг «состоялся», — ровно тот ритуал без выгоды, от которого
процесс избавлялся.