роадмап — состояние проекта, а не очередь работ

Основной инструмент владельца отвечал на половину своего вопроса. Оценка идёт
по поведению: что приложение уже может и чего ещё не может, — а close
--implemented удалял у достигнутой цели и файл, и строку, так что роадмап по
построению показывал только «что осталось». Свидетельство лежало в самом
роадмапе healthlog: секция «Что уже пройдено» на двадцать строк прозы, руками,
с припиской «Эти звенья целями не заведены: закрытая цель записи не оставляет».

Теперь строка с датой переезжает в секцию достигнутого, файл удаляется
по-прежнему. Вторым домом поведения это не делает: нормативное поведение живёт
в openspec/specs, роадмап отвечает, когда и в каком порядке оно появилось.
Ссылки на файл в строке нет — файла больше нет, форма как в REJECTED.md.

Цель стала возможностью приложения, задача — шагом к ней:
- заголовок цели отвечает на «что приложение будет уметь»; свойство поведения
  («сообщает о своём состоянии», «исход не зависит от порядка») — тоже
  возможность и переформулировки не требует;
- «Завершение» — списком, а не абзацем: задача ссылается на его строку, и это
  новая защита от «отрефакторить X» вместо прежнего «наблюдаемо снаружи».
  Заодно видно обратное: строка, к которой не относится ни одна задача, —
  незакрытая часть возможности;
- работа над инструментом и процессом на этот вопрос не отвечает и живёт в
  отдельной секции.

Цель обязательна не у всякой задачи. Прежнее «иначе она не попадёт ни в один
спринт» было угрозой, а не аргументом, и заставляло операционную работу
выдумывать себе направление. Граница по роду: feature без цели не бывает, fix,
chore и research живут без неё и входят в набор помимо цели спринта.

Тип [epic] упразднён: зонтиком стала цель, а слишком крупный шаг дробится под
ней. Ноль употреблений на 97 записей двух живых проектов.

Секции роадмапа — умеет / строим / направления / станок, четыре вместо двух;
имена приняты как временные и запаркованы (TODO 7). Имя секции достигнутого
знает скрипт — docs/.pm.json, ключ tasks.achieved_section. reopen цели снимает
строку достигнутого, круг проверен вживую.

Всё дописано в версию 3 канона: она ещё нигде не выкачена. DECISIONS 19,
YYY–ГГГ и следствия 78–81.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-08-04 17:43:55 +03:00
co-authored by Claude Opus 5
parent 5bf599a767
commit e847bfa0ea
13 changed files with 453 additions and 136 deletions
+18 -17
View File
@@ -1,7 +1,7 @@
# Декомпозиция и мозговой штурм
Обе операции превращают одну запись в несколько (или в ноль). Разница во входе:
декомпозиция дробит **готовую задачу или эпик**, штурм прорабатывает **идею**,
декомпозиция дробит **слишком крупную задачу**, штурм прорабатывает **идею**,
которая ещё не задача.
## Тест декомпозиции
@@ -11,10 +11,11 @@
1. **Мерджатся независимо.** Часть Б не требует, чтобы часть А была уже влита.
Есть порядок «сперва А, потом Б, иначе не собрать» → это не декомпозиция, а
план реализации: шаги остаются **внутри одного файла**.
2. **Каждая даёт видимую пользу.** Часть, полезная только в комплекте с другой,
— не самостоятельная задача. Пользу проверяй тестом «готова к взятию»
(task-format): что станет наблюдаемо иначе именно от этой части и какие у неё
собственные критерии приёмки.
2. **Каждая — самостоятельный шаг.** Часть, осмысленная только в комплекте с
другой, — не задача. Проверяй тестом «готова к взятию» (task-format): какую
строку «Завершения» цели двигает **именно эта часть** и какие у неё
собственные критерии приёмки. У операционных частей (`fix`, `chore`,
`research`) цели может не быть — тогда достаточно собственных критериев.
Не проходит хотя бы одно — **не дроби**. Ложная декомпозиция плодит файлы,
которые нельзя взять поодиночке, и переоценка потом склеивает их обратно.
@@ -55,21 +56,21 @@
`REJECTED.md` здесь — не «выкинули», а именно тот след, что переживает запись:
через квартал вопрос «куда делась задача X» отвечается строкой со ссылками на
наследников, а не археологией git;
- родитель осмыслен как зонтик → `edit <slug> --type epic`, тело — ссылки на
задачи-части, своих шагов у него нет. **Эпик не берётся в спринт** и живёт
ровно до тех пор, пока не закрыта последняя часть.
- родитель осмыслен как **возможность**, а не как шаг → это цель. Тип на месте
не меняется (цель живёт в другом индексе): заводится `[goal]` в `ROADMAP.md`,
части получают `--goal <новый слаг>`, родитель закрывается с причиной-ссылкой.
Зонтик, который перестал быть временным и описывает направление, а не работу, —
это уже **цель**, а не эпик. Тип на месте не меняется (цель живёт в другом
индексе): заводится `[goal]` в `ROADMAP.md`, задачи получают `--goal <новый слаг>`,
эпик закрывается с причиной-ссылкой.
**Промежуточного зонтика между целью и задачей нет.** Тип `[epic]` упразднён:
роль зонтика играет цель, а слишком крупный шаг дробится на шаги помельче под
той же целью. Если частям нужен общий заголовок — значит у них общая
возможность, и её надо назвать целью, а не заводить временный тип.
## Когда декомпозиция случается посреди спринта
Задача, которая **переросла в эпик**, распознаётся до того, как под неё заведено
предложение об изменении: иначе его придётся выбрасывать. Она помечается
`[epic]`, выходит из набора (`sprint drop … --reason "переросла в эпик"`), уходит
на декомпозицию, а спринт продолжается остальными. Части заводятся сразу, но в
Задача, которая **оказалась крупнее задачи**, распознаётся до того, как под неё
заведено предложение об изменении: иначе его придётся выбрасывать. Она выходит
из набора (`sprint drop … --reason "крупнее задачи"`), уходит на декомпозицию, а
спринт продолжается остальными. Части заводятся сразу под той же целью, но в
текущий набор **не добавляются** — набор заморожен.
## Мозговой штурм идеи
@@ -100,7 +101,7 @@ Applicative-штурм («перечисли задачи, следующие и
- Идея/задача на входе, выбранная рамка (для штурма), задачи-наследники со
слагами, целями и секциями.
- Судьба родителя: удалён / стал эпиком / стал целью / выкинут с причиной.
- Судьба родителя: удалён / стал целью / выкинут с причиной.
- `tasks.py check` после правок.
- Границы покрытия: какие постановки рассмотрены и какие сознательно отброшены —
чтобы штурм не пришлось повторять с нуля.