- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель; - буквенные метки решений заменены сквозными Р1–Р234, следствия получили префикс С при прежних номерах: схема букв выродилась до пятибуквенных и сломалась — `АЕАКЛ` была занята и темой 53, и темой 65; - 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер означал тему, а слово стояло «решение», формулировка исправлена.
69 lines
5.4 KiB
Markdown
69 lines
5.4 KiB
Markdown
# 6. Поддержание документов по ходу разработки (2026-08-03)
|
||
|
||
## Что было
|
||
|
||
Гейт healthlog **уже изобрёл нужный механизм** для одного документа —
|
||
`scripts/gate.py:177-181`: миграция изменена, а `docs/database.md` нет → `FAIL`.
|
||
Документ канона сверяется с кодом красным гейтом, а не напоминанием.
|
||
|
||
Против этого — прямое доказательство, что́ не работает: у `adr/` был список
|
||
триггеров прозой («выбор технологии, структурные решения, дорогой откат,
|
||
намеренный отказ»), и он дал **6 записей на 43 изменения**. Прозаический триггер,
|
||
который некому проверить, не срабатывает.
|
||
|
||
Механизируемы три документа из десяти: `database.md` (миграция), `architecture.md`
|
||
(capability в `openspec/specs/` без упоминания в обзоре), `tasks/` (`tasks.py
|
||
check`). Плюс `openspec/specs/` вливает `opsx:archive`.
|
||
|
||
## Решено
|
||
|
||
**Р21. Принуждённое отрицание в докладе шага синка.** Шаг обязан назвать
|
||
**каждый** документ канона: обновлён — чем, либо «не требуется, потому что…».
|
||
Нетронутые группируются одной строкой с общей причиной.
|
||
|
||
*Причина:* это тот же приём, что «границы покрытия» в отчёте ревью и «пустой
|
||
пункт называется пустым» в каноне — и единственный, о котором в этом репозитории
|
||
есть данные, что он работает. Отличить «не написал» от «написал, что не
|
||
требуется» можно только тогда, когда отрицание обязательно.
|
||
|
||
**Триггер ADR, окончательная формулировка.** Запись заводится, когда верно одно
|
||
из трёх: **дорогой откат** (переделка стоит дороже переписывания одного файла);
|
||
**намеренный отказ** от очевидного подхода; **пересмотр прежнего решения** — тогда
|
||
у старой записи обязателен статус «заменено на». Не заводится для рутины и для
|
||
того, что видно из кода и `git log`. Источник — архивный `design.md`: ADR его
|
||
цитирует и на него ссылается, а не пересказывает.
|
||
|
||
**Р22. `docs.py check` обязателен в гейте проекта.** Скилл `canon` при адаптации
|
||
добавляет шаг и печатает это в отчёте.
|
||
|
||
*Причина:* гейт — единственный общий станок, который нельзя пропустить. Проверка,
|
||
которую зовёт агент, может быть не позвана; прецедент в самом healthlog уже есть.
|
||
|
||
Сверка «миграция изменена — `database.md` нет» **обобщается**: путь миграций
|
||
проекта записывается в `docs/.pm.json` рядом с версией канона, и `docs.py` делает
|
||
эту проверку сам, а не каждый проект заново.
|
||
|
||
**Р23. Остаток чистки помечается маркером и считается числом.** Неразобранный
|
||
раздел получает `<!-- канон: поведение → openspec/specs/<capability> -->`,
|
||
`docs.py` считает маркеры и печатает остаток. Закрывается порциями, как
|
||
переоценка задач.
|
||
|
||
**Маркеры гейт не красят.** Это долг, а не отказ: покрасневший гейт на первом
|
||
маркере сделал бы постепенный переезд невозможным, а разовый — обязательным.
|
||
Число печатается и убывает на глазах.
|
||
|
||
## Что из этого следует
|
||
|
||
**С28. Шаг 9 `task-pipeline` переписывается** из четырёх пунктов прозой в
|
||
построчный доклад по документам канона.
|
||
|
||
**С29. `promote.md`, шаг 3, переписывается:** «вычеркнуть пункт из брифа,
|
||
правило переезжает в перечень механизированного в разделе `## Карта`» → перечень
|
||
механизированного живёт в `conventions/README.md`. Брифа нет.
|
||
|
||
**С30. `docs/.pm.json` держит не только версию канона**, но и пути, нужные
|
||
проверкам: каталог миграций — как минимум.
|
||
|
||
**С31. `docs.py check` получает две сверки с кодом**, а не только раскладку:
|
||
миграции ↔ `database.md`, capability ↔ упоминание в `architecture.md`.
|