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

- 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
+51
View File
@@ -0,0 +1,51 @@
# 10. Ревью готовых плагинов двумя проходами (2026-08-03)
## Что было
Два независимых сабагента `fable` — по одному на `av-dev-pm` и `av-dev-pipeline`.
**20 находок, из них две найдены обоими независимо.** Прошлые три круга ревью
шли по одному проходу на всё; два прохода с разными предметами дали и больший
урожай, и перекрёстное подтверждение самого дорогого дефекта.
## Что оказалось сломано по существу
**Р36. Перестановка закрытия за коммит (решение из [темы
8](08-rollout-order.md)) сломала `reopen` и батч — и это нашли оба прохода.**
`close --implemented` печатает «дорога назад: файл восстанавливается из git», а
`reopen` искал **коммит удаления**, которого в новом порядке ещё нет: шаг 11
идёт последним, и учёт остаётся незакоммиченным. Проверено прогоном: `reopen`
отказывал кодом 2 на свежезакрытой задаче — то есть в самом вероятном своём
применении. Тем же грязным деревом ломался `task-batch`: `git rebase` и `git
worktree remove` отказывают, и **каждая успешно закрывшая задачу ветка** уезжала
бы в провалившиеся.
Починено с обеих сторон: `reopen` берёт текст из `HEAD`, если коммита удаления
нет, а шаг 11 обязан **коммитить учёт вторым коммитом** — иначе закрытие не
доезжает до основной ветки и опора «`SPRINT.md` под git» остаётся словами.
**Р37. Канонический пример `docs/.pm.json` убивал `tasks.py`.** `canon.md`,
`skeletons.md`, `tasks/SKILL.md` и `adopt.md` показывали ключ `tasks.sections`,
которого скрипт не знает: `_validate_config` отвергает неизвестные ключи кодом 3
на **любой** команде. Проект, заведённый по канону дословно, остался бы без
работы с задачами целиком — а `docs.py check` при этом печатал «канон соблюдён»,
потому что чужой код 3 уходит в «не проверялось». Секции живут в заголовках `##`
индекса и второго дома не получают.
## Что из этого следует
**С44. Класс находок тот же, что и в прошлые три круга: стыки.** Не новый код, а
место, где один файл ссылается на другой. `sprint.md` в пункте «Сделана» всё ещё
отсылал к порядку, который сам же тремя экранами ниже отменил; три остатка «шаг
9а» несли **предкоммитную** позицию закрытия; путь отчёта триажа не переживал
`opsx:archive`, хотя по нему сверяют полноту ревью четверо.
**С45. Инструкция, которую нельзя выполнить, выглядит как выполненная.** Ответ
на вопрос по документированной процедуре (снять тег) оставлял задачу
незабираемой, потому что судит **раздел**, а не тег; `canon adopt` требовал
гнать `docs.py check` «до отсутствия дрейфа», недостижимого без нарушения
запрета сочинять цели; урожай спринта, заведённый после `sprint close`, терял
автотег молча.
**С46. Два прохода по разным предметам дороже одного, но не вдвое.** Перекрытие
оказалось ровно в одной находке из двадцати — той самой, что подтвердилась
дважды. Практика остаётся: ревью на плагин, а не одно на репозиторий.