журнал решений: разложен по теме на файл, метки решений стали номерами

- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель;
- буквенные метки решений заменены сквозными Р1–Р234, следствия получили
  префикс С при прежних номерах: схема букв выродилась до пятибуквенных и
  сломалась — `АЕАКЛ` была занята и темой 53, и темой 65;
- 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер
  означал тему, а слово стояло «решение», формулировка исправлена.
This commit is contained in:
av
2026-08-13 12:40:56 +03:00
parent b411d4edb8
commit bf6a173115
72 changed files with 4253 additions and 4053 deletions
+126
View File
@@ -0,0 +1,126 @@
# 31. Ревизия покрытия `av-dev-pm` продакт-оптикой (2026-08-05)
Сабагент в роли продакт-менеджера оценил покрытие жизненного цикла личного
проекта (один человек, недели-месяцы) скиллами и агентами `av-dev-pm`. Скоуп
сужен по ходу разбора: деплой и разбор инцидентов на проде делаются вручную,
скиллов под них не заводим. Осталось планирование, разработка и доработка.
**Р126. Шаг 2 сессии требовал чисел, которых процесс отказался собирать
решением.** `cadence.md` делал обязанностью пересмотр «ориентира по размеру
спринта, прироста беклога на закрытую задачу, времени на задачу» и «сколько
заняли задачи **против ожидания**» — с обоснованием «иначе обязанность висит
ничья». Данных под это нет: у записи нет дат заведения, взятия и закрытия,
`close --implemented` удаляет файл, `sprint close` очищает `SPRINT.md`. Хуже
того, «против ожидания» и «время на задачу» требуют оценки и тайм-бокса, а
`session/SKILL.md` в «Почему не Scrum» их прямо не берёт: пункт противоречил
решению, стоящему через файл от него.
Исход — **выкинуть, а не подпереть данными**. На практике числа не
пересматривались ни разу, и заводить под них учёт дат значило бы обслуживать
обязанность, которой никто не брал. Осталось качественное: что сломалось в
процессе, что оказалось дороже, чем выглядело при заведении, какие правила не
сработали. Шаг 3 пункт 9 переименован из «переоценки по измеренному» в
«переоценку по пройденному», судит человек по памяти о спринте. Рядом записано,
что замеров нет **намеренно** — иначе следующий читатель заведёт их обратно как
недостающие.
**Р127. `doc-consistency` переехал с каждого синка на сессию, к
`doc-code-drift`.** Агент на `opus` зовётся шагом 9 пайплайна, то есть на каждой
задаче: 5–8 opus-проходов за спринт по документам, которые за спринт меняются на
несколько абзацев. Обоснование в каноне («сверка текста с текстом дёшева») верно
относительно второго агента, но не в абсолюте на одиночке.
Довод сильнее денег: **расхождение между двумя документами по определению
требует двух документов**, а на большинстве задач синк правит один. И пачка,
отбираемая работой, не видит того, чего работа не касалась, — а расхождение живёт
ровно там: правка отменяет решение в одном документе, парный статус нужен в
другом. Это был открытый вопрос `REMAINING` про охват ADR при пересмотре; переезд
его закрыл. Цена — потеря привязки находки к задаче, которая её породила: по теме
29 именно эта привязка дала пять самых точных находок. Принято сознательно.
**Р128. Отмена цели получила порядок, но не флаг.** `close` запрещал закрыть
цель с живыми задачами, а что делать с этими задачами, не говорил нигде: шаг 3
сессии знал только «та ли цель», `task-goal.md` описывал одно достижение, а
`session/SKILL.md` вдобавок утверждал «цель постоянна». Человек получал отказ с
перечнем и никакой подсказки.
Порядок записан: сперва задачи поштучно (`close --reason` своей причиной либо
`edit --goal` на другую цель), потом сама цель через `close --reason` в
`REJECTED.md`, а не в `Готово` — отменённая цель не умеет ничего. Флаг
`--cascade` отвергнут: отмена цели редка и дорога, и поштучный разбор здесь не
церемония, а единственный момент, когда видно, что из задач переживёт цель.
Каскад превратил бы его в один Enter. **Причина у каждой задачи своя**: «цель
отменена» это пересказ команды, в `REJECTED.md` от него нет пользы через квартал.
Место процедуры — переоценка на сессии, а не отдельный заход: отмена цели **и
есть** разбор всех её задач, а разбор задач — шаг 3.
**Р129. У брошенного спринта появился второй законный исход, без порога.**
`--dissolve` во всех текстах был привязан к блокеру, и скрипт отказывал словами
«роспуск объясняется блокером». Вернувшийся к набору, который стоял месяц, не
имел законного хода: двигать нельзя (заморозка), распускать не по чему. Теперь
роспуск объясняется блокером **или тем, что набор протух**.
Порога в неделях сознательно нет — это тот же класс, что выкинутые числа шага 2:
счётчик простоя пришлось бы вести руками, а решает всё равно человек. Признак не
срок, а **что набор перестал быть твоим**: перечитываешь, зачем эти задачи вместе
— он протух. Туда же добавлена точка входа «вернулся, а спринт открыт»: `check`,
`SPRINT.md`, развилка продолжать/распустить. Середины у развилки нет намеренно —
«доделаю пару штук и решу» это работа по набору, которого ты не понимаешь.
**Р130. Журнал канона прогоняется как есть, а проверка исхода поручена судьям.**
Схлопнуть записи 3 и 4 в один переход «с 2 на 4» отвергнуто: журнал описывает не
только *что сделать*, но и порядок, в котором это делалось, и слитая запись
экономит один проход ценой невоспроизводимости остальных. Оба живых проекта
пройдут 2→3→4 по записям.
Взамен появилась проверка исхода: **шагом 6 `adopt` и шагом 6 `upgrade` зовутся
оба судьи документов**. Это прямой ответ на открытый вопрос REMAINING «как
проверять, что канон не разошёлся с проектами после `upgrade`»: `check` сверяет
**число** в `.pm.json` с версией скрипта и про существо записи не знает ничего.
Проект несёт `"canon": 4` и может не иметь того, чего требовала любая из
пройденных версий — записи применяются руками, а ручной проход по трём записям
подряд ровно то место, где половина шага делается и забывается.
У `adopt` добавка другого рода: там судьи ловят не недоделанную миграцию, а
последствия переноса — факт, растащенный по двум домам, поведение, осевшее в
`architecture.md`, ADR, оторванный от своего `design.md`. Им передаётся
объявленное переходное состояние из шага 5, иначе честная строка в незаполненном
слоте вернётся находкой.
## Что из этого следует
**С117. Обязанность без источника данных отменяют, а не механизируют.** Первый
позыв — дать шагу данные (дописать даты, сводку спринта). Но обязанность, не
исполнявшуюся ни разу, дешевле снять: механизация под неё производит учёт,
который надо вести, ради разбора, который не делается.
**С118. Требование, противоречащее решению через файл от него, — не мелочь, а
признак копии.** «Против ожидания» пережило решение «не берём оценки», потому
что стояло в другом документе. Обратный обход по решению «что мы не берём» нашёл
бы это сразу — тот же приём, что и следствие
[С109](29-doc-consistency-trial.md).
**С119. Частота вызова агента выводится из того, что он ищет.** Судья
расхождений **между** документами бессмысленен там, где документ один; значит
его место не на задаче, а на наборе задач. Цена вызова подтвердила вывод, но не
она его дала.
**С120. Запрет обязан называть выход.** `close` верно не давал осиротить задачи,
но текст отказа перечислял препятствия и молчал о ходе. Проверка без названного
следующего шага — половина работы: она защищает данные и бросает человека.
**С121. Признак вместо порога там, где счётчик пришлось бы вести руками.**
«Набор перестал быть твоим» проверяется в момент вопроса и ничего не требует
хранить; «прошло N недель» требует учёта, который никто не ведёт, и всё равно
кончается решением человека.
**С122. Версионирование без единого переехавшего проекта — не журнал миграций, а
история правок.** Довод за схлопывание был верен по факту и отвергнут по
принципу: обкатка на живых проектах и проверяет, работает ли механизм. Схлопнуть
значило бы не прогнать его ни разу и оставить вопрос открытым.
**С123. Проверка версии не есть проверка миграции.** Число в `.pm.json` двигает
тот же проход, что делал шаги, — и двигает независимо от того, все ли сделаны.
Механической проверки существа нет; там, где её нет, ставится судья, а не
отметка.