Files
dev-skills/decisions/31-pm-coverage-product-review.md
T
av bf6a173115 журнал решений: разложен по теме на файл, метки решений стали номерами
- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель;
- буквенные метки решений заменены сквозными Р1–Р234, следствия получили
  префикс С при прежних номерах: схема букв выродилась до пятибуквенных и
  сломалась — `АЕАКЛ` была занята и темой 53, и темой 65;
- 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер
  означал тему, а слово стояло «решение», формулировка исправлена.
2026-08-13 12:40:56 +03:00

13 KiB
Raw Blame History

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.

С119. Частота вызова агента выводится из того, что он ищет. Судья расхождений между документами бессмысленен там, где документ один; значит его место не на задаче, а на наборе задач. Цена вызова подтвердила вывод, но не она его дала.

С120. Запрет обязан называть выход. close верно не давал осиротить задачи, но текст отказа перечислял препятствия и молчал о ходе. Проверка без названного следующего шага — половина работы: она защищает данные и бросает человека.

С121. Признак вместо порога там, где счётчик пришлось бы вести руками. «Набор перестал быть твоим» проверяется в момент вопроса и ничего не требует хранить; «прошло N недель» требует учёта, который никто не ведёт, и всё равно кончается решением человека.

С122. Версионирование без единого переехавшего проекта — не журнал миграций, а история правок. Довод за схлопывание был верен по факту и отвергнут по принципу: обкатка на живых проектах и проверяет, работает ли механизм. Схлопнуть значило бы не прогнать его ни разу и оставить вопрос открытым.

С123. Проверка версии не есть проверка миграции. Число в .pm.json двигает тот же проход, что делал шаги, — и двигает независимо от того, все ли сделаны. Механической проверки существа нет; там, где её нет, ставится судья, а не отметка.