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