Files
dev-skills/av-dev-pm/skills/session/references/cadence.md
T
avandClaude Opus 5 47a2f3de63 язык скиллов av-dev-pm: проход упрощения пятью агентами и разбор находок
Эксперимент: по сабагенту на каждый скилл av-dev-pm, задача — переписать текст
более простыми словами, но только там, где уверен и без потери смысла и
точности. Нормой служил устав языка самого проекта, language.md, включая его
раздел «Порог правки»: правка без нарушенного правила не делается.

36 правок в двенадцати файлах, +64/-63 — почти строго замена, а не
переписывание. Правили залог (пассив с названным деятелем в творительном),
отглагольные существительные, параллельность перечней, канцелярит «является»,
пару garden-path и одно двойное отрицание. Контракт не задет нигде: в диффе нет
изменённых строк-заголовков, а код-спаны встречаются ровно парой минус-плюс,
то есть ни имя, ни флаг, ни путь не переписаны.

Отчёты «что рассматривал и не тронул» вышли длиннее отчётов о правках у всех
пятерых, и это главный результат прогона. Самый частый повод остановиться —
слово, живущее в четырёх файлах: конфляция, интейк, провенанс, непоймание.
Правка в одном месте развела бы словарь, а править все — уже не упрощение
текста скилла, а сквозной проход по репозиторию. Второй повод — формулировка,
дословно повторённая в соседнем плагине: декорреляция, материализация
нерешённого, «при расхождении прав текст».

Шестой агент проверил все 36 правок и нашёл четыре.

Перестановка слов в task-research.md развела формулу с её домом: «число без
источника проход ревью обязан читать как условие» стоит в canon.md и в уставе
doc-consistency, который прямо ссылается на канон как на источник. Откачено —
это ровно тот класс расхождения, который сам doc-consistency и ловит.

«Держит H1, мету и индекс в согласии» — управление требует дополнения, а
language.md в разделе англицизмов прямо оговаривает: русский аналог звучит
коряво — остаётся термин. Взят третий вариант, «согласованными».

В skeletons.md «правка тянет запись, и она называет» — местоимение указывает
на два женских существительных сразу. Стало «и запись называет».

Четвёртая находка не откачена: правка в init/SKILL.md хорошая, но развела
конструкцию с близнецом в canon/SKILL.md — выровнена вторая половина.

Побочно найдена старая логическая инверсия в DECISIONS.md, решение U:
«становится неотличимым, только если отрицание обязательно» — смысл вывернут,
в docs/SKILL.md и во второй записи журнала он правильный. Починено.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 14:49:03 +03:00

265 lines
24 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.
# Сессия: четыре шага
Одна сессия между спринтами. Порядок шагов — **зависимость, а не список**:
переоценивать задачи, не разобрав вопросы, значит переоценивать вслепую; набирать
спринт, не переоценив, значит набирать из протухшего.
Начинается сессия с `tasks.py check``check --fix`, если дрейф накопился) —
результат идёт строкой в доклад.
## Шаг 1. Разбор вопросов
`tasks.py list --questions` — всё, что накопилось. Вопрос это решение человека,
и разбирается он **пачкой**, а не по одному, как только возник: по одному —
это дёрганье, пачкой — это сессия.
Порядок по каждому вопросу:
1. **Проверь, не отвечен ли он уже** — решением, документом, соседним
изменением, самим ходом прошедшего спринта. Отвеченный вопрос не выносится
человеку: это самая частая находка и она не требует ничьего решения.
2. **Сформулируй развилку** с вариантами и последствием каждого, рекомендация —
первым вариантом.
3. **Вынеси пачкой** через `AskUserQuestion`, не больше трёх за раз.
4. **Запиши ответ в тело задачи, опустоши раздел «Вопросы»**, сними тег
(`edit <slug> --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 <slug> --implemented` только имея **конкретный коммит или строку
документа**, закрывающие задачу, и ссылка идёт в доклад. Есть лишь косвенные
признаки — не удаляй сам, вынеси в пачку вопросов. Сделана частично → задача
сжимается до остатка: тело правишь редактором, заголовок и «зачем» — через
`edit`.
2. **Проверь, не отменена ли решением.** Документ, ADR или архивное изменение
мог закрыть вопрос иначе — тогда `close <slug> --reason "<ссылка на
решение>"`. Задача закрывается не только коммитом.
3. **Проверь пересечения.** Две задачи об одном — содержимое в одну, вторую
`close <slug> --reason "слита с <другой-слаг>"`. Смотри **шире порции**:
интейк дедуплицирует новое против существующего, но никогда не
пересматривает уже лежащее, и две задачи с одной причиной могут лежать рядом
месяцами.
4. **Пере-кластеризуй по общей причине.** Несколько задач, оказавшихся симптомами
одного дефекта, сливаются в одну — это находка, которую интейк дать не мог.
5. **Гигиена полей** — протухшее «зачем», вопрос в прозе, снятый ответ, свойство
репозитория в рамках, предписание процесса в теле, тип, разошедшийся с
задачей, границы вместо реализации в разделе «Затрагивает». Список и правила —
в скилле `tasks`. **Переоценка — то самое место, где беклог добирает тип и
разделы его схемы:** требовать их на входе значило бы выгонять в заметки то,
что должно лежать задачей, а к взятию в спринт они уже обязательны. Блок
здоровья `check` печатает, сколько записей готово к взятию, — по этому числу
и видно, добрала переоценка или нет.
Затем — то, что решает пользователь:
6. **Жива ли она вообще.** Контекст мог измениться: ушла зависимость, отпал
сценарий, обошли иначе. Здесь и звучит вопрос, выкидывать ли.
7. **Та ли цель — и нужна ли она вообще.** Приоритетов нет, и «повысить» нечего
— вместо повышения задача **меняет цель** (`edit <slug> --goal <другой>`) или
входит в ближайший набор. `feature`, которой не находится цель, — кандидат
на выход: новая возможность вне цели это возможность, которой никто не
заказывал. Операционной задаче (`fix`, `chore`, `research`) цель не нужна, и
выдумывать её здесь не надо.
**Отменяется и сама цель** — когда замысел оказался неверен, а не когда
задача выбрала не ту. Тогда порция расширяется до всех задач этой цели: каждую
либо закрыть своей причиной, либо перевесить на другую цель, и только потом
закрыть цель. Порядок и почему он такой —
[task-goal.md](../../tasks/references/task-goal.md#отменённая-цель--сперва-задачи-потом-цель).
Здесь этому и место: отмена цели это разбор её задач, а разбор задач — этот
шаг.
8. **Задача ли это по-прежнему.** Не проходит тест «готова к взятию» → `edit
<slug> --type research` и опустошённый раздел «Вопрос», то есть сырьё; дальше
штурм. Разрослась → это несколько задач под той же целью, дальше
декомпозиция.
9. **Переоценка по пройденному.** Прошедший спринт показывает, чего на самом
деле стоит такая работа. Это меняет цену **других** задач, и именно здесь
применяется: задача, оказавшаяся заметно дороже, чем думалось, при прежней
пользе — кандидат на выход. Судит человек по тому, что помнит о прошедшем
спринте; замеров процесс не ведёт и оценок не хранит.
### Храповик на залежавшихся
Сильно залежавшаяся задача — сигнал сама по себе: её либо ни разу не собирались
делать, либо нечем взять. Измеряй наблюдаемым — датой последней правки из git
(`list --stale` ставит такие первыми); счётчик «сколько сессий пережила» нигде
не хранится.
Задача из верхних строк `--stale`, которую и этот заход оставляет без изменений,
**либо двигается (меняет цель, идёт в набор, уходит с причиной), либо остаётся с
явно записанной причиной**, почему её держим (`move <slug> --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` после правок — результат строкой.