обвязка: модель копий переписана под один маркер и манифест

- именованные регионы `<!-- local:имя -->` заменены на единственный
  `<!-- conv:local -->`: всё ниже него принадлежит репозиторию, всё выше
  пересобирается, поэтому имени-которое-можно-осиротить больше нет
- лок-файла и `origin_hash` в шапке нет — «что было в прошлый раз» знает git,
  копии закоммичены, автоматического обновления не существует; транспорт
  назад (`push`) убран вместе с ними
- заведены META-22 (репозиторное пишется ниже маркера) и META-23 (форк не
  носит `origin:`), META-17 переписан под маркер; буква `X` в префиксе
  зарезервирована за локальными правилами потребителей
This commit is contained in:
av
2026-07-26 12:55:05 +03:00
parent 4de6e0f896
commit c2f68e6be1
5 changed files with 213 additions and 148 deletions
+52 -31
View File
@@ -41,16 +41,20 @@ prefix: META
## Канон и копии
Файлы в `docs/conventions/` с шапкой `origin:` — копии из общего канона
`dev-conventions`, а не собственные документы репозитория. Репозиторное
живёт только внутри локальных регионов `<!-- local:имя --> … <!-- /local -->`:
они исключены из сравнения с каноном, и расхождение по ним — норма, а не
дрейф. Правка вне регионов означает одно из двух: улучшение, которое
возвращают в канон, или сознательное расхождение, записанное в ключ `local:`
шапки. Состояние копий показывает `conv status`, различия — `conv diff`,
обновление из канона — `conv pull`; всё через раннер репозитория.
`dev-conventions`, а не собственные документы репозитория. Копия собирается
из канона целиком, поэтому репозиторное живёт ниже маркера локальной части
в конце файла: обновление сохраняет всё, что ниже маркера, и переписывает
всё, что выше. Откуда взяты копии и где брать обновления — в манифесте
`.conventions.toml` в корне репозитория.
Имя региона обязательно и стабильно: перенос содержимого при обновлении
идёт по именам, и переименование осиротит содержимое во всех копиях.
Отдельного механизма отчёта о расхождении нет: обновление перезаписывает
файлы в рабочем дереве, а что именно изменилось, показывает `git diff` до
коммита. Поэтому в шапке копии хранится только `origin:` — отпечатков
канона и дат синхронизации в ней нет, историю держит git.
Правка выше маркера означает одно из двух: улучшение, которое переносят в
канон, или документ, переставший быть копией, — тогда `origin:` из шапки
убирают.
## Правила
@@ -58,11 +62,11 @@ prefix: META
**ДОЛЖЕН.** Файл описывает ровно один повторяющийся выбор.
**Почему.** Подписка — это набор лежащих в репозитории файлов, и берут файл
целиком. Файл, собравший две темы, вынуждает репозиторий взять правила,
которые ему не нужны, и получать шум в `diff` по чужой половине. Разрезать
позже дорого: путь файлачасть адреса правила, и после разреза внешние
ссылки указывают не туда.
**Почему.** Подписка перечисляется по темам, и тему берут целиком. Файл,
собравший две темы, вынуждает репозиторий взять правила, которые ему не
нужны, и вычитывать чужую половину при каждом обновлении. Разрезать позже
дорого: перенос правила в другой файл — это новый префикс и новая
нумерация, поэтому после разреза все внешние ссылки обходят руками.
### META-2. Конвенция заводится, когда решение принимается третий раз
@@ -152,9 +156,9 @@ prefix: META
(вкус формулировки, выбор границы, суждение о ситуации), не может быть
ДОЛЖЕН — его модальность СЛЕДУЕТ по построению, а не по слабости.
### META-7. Факт механизации фиксируется в локальном регионе со ссылкой на правило
### META-7. Факт механизации фиксируется в копии со ссылкой на правило
**ДОЛЖЕН.** Регион `механизировано` называет идентификатор правила и
**ДОЛЖЕН.** Запись о механизации называет идентификатор правила и
конкретную проверку.
**Почему.** Механизация — состояние конкретного репозитория, канон о ней не
@@ -181,7 +185,7 @@ prefix: META
### META-9. Общая механизация разрешает удалить норму из канона
**ДОПУСКАЕТСЯ.** Правило, уехавшее в общий конфиг линтера или в общую роль,
удаляется из канона одним `push`.
удаляется из канона.
**Почему.** Формулировка, дублирующая работающую у всех проверку,
размазывает внимание: файл на несколько сотен строк заставляет человека и
@@ -232,15 +236,15 @@ prefix: META
### META-14. Отступления перечисляются поимённо, со ссылкой на правила
**ДОЛЖЕН.** В локальном регионе перечислены отступления, которые уже есть в
коде, с идентификатором правила и причиной.
**ДОЛЖЕН.** В локальной части копии перечислены отступления, которые уже
есть в коде, с идентификатором правила и причиной.
**Почему.** Иначе репозиторий выглядит соблюдающим конвенцию, а проверить
это можно только чтением всего кода. Со ссылками отступления счётны: видно,
сколько правил конвенции репозиторий реально не соблюдает. Пустой регион при
сколько правил конвенции репозиторий реально не соблюдает. Пустой список при
этом почти всегда означает не отсутствие отступлений, а то, что их не искали.
### META-15. Запись в регионе отступлений разбирается по масштабу
### META-15. Запись об отступлении разбирается по масштабу
**ДОЛЖЕН.** Судьба записи зависит от того, что в ней сказано:
@@ -256,15 +260,35 @@ prefix: META
правила в каноне, которую чинят один раз для всех, или лишнюю подписку,
где файл просто не нужен. Оставленная отступлением, она прячет обе.
### META-17. Репо-специфичная часть «Связано» — в локальном регионе
### META-17. Ссылки на код репозитория стоят в локальной части, а не в «Связано»
**ДОЛЖЕН.** Раздел «Связано» стоит в конце файла; канонические ссылки — в
общем тексте, ссылки на ADR, код и файлы конкретного репозитория — в
локальном регионе.
**ДОЛЖЕН.** Раздел «Связано» канона содержит только ссылки, верные у всех
потребителей; ссылки на ADR, код и файлы конкретного репозитория — в
локальной части копии.
**Почему.** Общий текст уезжает `push`-ем ко всем потребителям, и ссылка на
чужой файл у них битая с первого дня. Регион исключён из сравнения, поэтому
та же ссылка внутри него никого не задевает и не даёт вечного шума в `diff`.
**Почему.** Текст канона приезжает ко всем потребителям, и ссылка на чужой
файл у них битая с первого дня. Ниже маркера та же ссылка никого не
задевает и переживает обновление, потому что обновление её не трогает.
### META-22. Репозиторное в копии пишется ниже маркера локальной части
**ДОЛЖЕН.** Правки репозитория вносятся ниже маркера, а не в текст,
пришедший из канона.
**Почему.** Обновление перезаписывает всё, что выше маркера, поэтому правка
там живёт до первого `pull`. Заметить пропажу можно, только вычитав
`git diff` целиком — а он в этот момент и без того полон изменений канона,
и своя строка теряется среди чужих.
### META-23. Документ, переставший быть копией, не носит `origin:`
**НЕ ДОЛЖЕН.** Файл, который развели с каноном намеренно, шапку `origin:`
не сохраняет.
**Почему.** По `origin:` решается, какие файлы пересобирать из канона. Форк,
оставивший шапку, при первом же обновлении теряет ровно то, ради чего его
заводили. Происхождение такого документа остаётся в истории коммита, где оно
никого не вводит в заблуждение.
### META-18. README директории перечисляет конвенции с однострочным описанием
@@ -284,6 +308,3 @@ prefix: META
идентификатором служит и напоминанием, и адресом, по которому за
подробностями идут; перенос деталей туда же вернул бы задачу поддержки двух
текстов.
<!-- local:точки-входа -->
<!-- /local -->