обвязка: идентификаторы правил описаны через префиксы

- LANGUAGE.md: раздел «Идентификаторы» переписан под префиксы, в список
  машинных проверок добавлена сверка с реестром
- GUIDE.md перенумерован под префикс META, «номер правила» заменён на
  «идентификатор»
This commit is contained in:
av
2026-07-25 20:55:38 +03:00
parent dcdd92230b
commit 4a7cfca8f6
3 changed files with 96 additions and 60 deletions
+38 -34
View File
@@ -1,3 +1,7 @@
---
prefix: META
---
# Как мы ведём конвенции # Как мы ведём конвенции
Конвенция описывает повторяющийся выбор: как называть директории, как Конвенция описывает повторяющийся выбор: как называть директории, как
@@ -29,11 +33,10 @@
## Оформление ## Оформление
Имя файла — kebab-case по теме: `app-directories.md`. Правилом это не Имя файла — kebab-case по теме: `app-directories.md`. Правилом это не
записано: обоснование сводится к «чтобы адрес правила записано: обоснование сводится к «чтобы имя файла в реестре префиксов
(`stack/ansible/app-directories.md R4`) писался одним способом», а писалось одним способом», а проверить нарушение всё равно проще глазом, чем
проверить нарушение всё равно проще глазом, чем сформулировать норму. Номер сформулировать норму. Номер META-16, под которым это правило существовало,
R16, под которым это правило существовало, оставлен свободным и не оставлен свободным и не переиспользуется.
переиспользуется.
## Канон и копии ## Канон и копии
@@ -51,7 +54,7 @@ R16, под которым это правило существовало, ос
## Правила ## Правила
### R1. Одна конвенция — один файл ### META-1. Одна конвенция — один файл
**ДОЛЖЕН.** Файл описывает ровно один повторяющийся выбор. **ДОЛЖЕН.** Файл описывает ровно один повторяющийся выбор.
@@ -61,7 +64,7 @@ R16, под которым это правило существовало, ос
позже дорого: путь файла — часть адреса правила, и после разреза внешние позже дорого: путь файла — часть адреса правила, и после разреза внешние
ссылки указывают не туда. ссылки указывают не туда.
### R2. Конвенция заводится, когда решение принимается третий раз ### META-2. Конвенция заводится, когда решение принимается третий раз
**СЛЕДУЕТ.** Поводом служит одно и то же решение, принятое третий раз и **СЛЕДУЕТ.** Поводом служит одно и то же решение, принятое третий раз и
каждый раз чуть по-другому. каждый раз чуть по-другому.
@@ -72,7 +75,7 @@ R16, под которым это правило существовало, ос
спорный, читателю нужен вместе с мотивом — это ADR, где мотив и есть спорный, читателю нужен вместе с мотивом — это ADR, где мотив и есть
содержание записи. содержание записи.
### R3. Новая конвенция пишется там, где заболело ### META-3. Новая конвенция пишется там, где заболело
**СЛЕДУЕТ.** Первые шаги пути «находка → конвенция → правило линтера → **СЛЕДУЕТ.** Первые шаги пути «находка → конвенция → правило линтера →
удаление прозы» делаются в репозитории, где случилась находка; в канон удаление прозы» делаются в репозитории, где случилась находка; в канон
@@ -83,7 +86,7 @@ R16, под которым это правило существовало, ос
платят за это все потребители сразу. Формулировка, обкатанная на одном платят за это все потребители сразу. Формулировка, обкатанная на одном
репозитории, приезжает в канон уже с известной границей. репозитории, приезжает в канон уже с известной границей.
### R4. В тексте конвенции нет утверждений о состоянии репозитория ### META-4. В тексте конвенции нет утверждений о состоянии репозитория
**НЕ ДОЛЖЕН.** Норма пишется в настоящем предписывающем времени, без **НЕ ДОЛЖЕН.** Норма пишется в настоящем предписывающем времени, без
описаний того, как сейчас устроен конкретный репозиторий. описаний того, как сейчас устроен конкретный репозиторий.
@@ -94,7 +97,7 @@ R16, под которым это правило существовало, ос
с первого дня. «Так сделано у нас» — содержимое региона отступлений, где оно с первого дня. «Так сделано у нас» — содержимое региона отступлений, где оно
и локально, и проверяемо. и локально, и проверяемо.
### R5. Расхождение кода с правилом — отступление, а не повод переписать правило ### META-5. Расхождение кода с правилом — отступление, а не повод переписать правило
**ДОЛЖЕН.** Правило правится, только когда неверно по существу: содержит **ДОЛЖЕН.** Правило правится, только когда неверно по существу: содержит
фактическую ошибку, внутреннее противоречие или условие применимости, фактическую ошибку, внутреннее противоречие или условие применимости,
@@ -105,7 +108,7 @@ R16, под которым это правило существовало, ос
переписывает его снова. Направление «конвенция → код» держится ровно тем, переписывает его снова. Направление «конвенция → код» держится ровно тем,
что факт не считается аргументом. что факт не считается аргументом.
### R6. `ДОЛЖЕН` без механической проверки либо механизируется, либо понижается ### META-6. `ДОЛЖЕН` без механической проверки либо механизируется, либо понижается
**ДОЛЖЕН.** Правило, нарушение которого объявлено ошибкой, получает **ДОЛЖЕН.** Правило, нарушение которого объявлено ошибкой, получает
машинную проверку или переводится в СЛЕДУЕТ. машинную проверку или переводится в СЛЕДУЕТ.
@@ -119,18 +122,18 @@ R16, под которым это правило существовало, ос
(вкус формулировки, выбор границы, суждение о ситуации), не может быть (вкус формулировки, выбор границы, суждение о ситуации), не может быть
ДОЛЖЕН — его модальность СЛЕДУЕТ по построению, а не по слабости. ДОЛЖЕН — его модальность СЛЕДУЕТ по построению, а не по слабости.
### R7. Факт механизации фиксируется в локальном регионе со ссылкой на номер ### META-7. Факт механизации фиксируется в локальном регионе со ссылкой на правило
**ДОЛЖЕН.** Регион `механизировано` называет номер правила и конкретную **ДОЛЖЕН.** Регион `механизировано` называет идентификатор правила и
проверку. конкретную проверку.
**Почему.** Механизация — состояние конкретного репозитория, канон о ней не **Почему.** Механизация — состояние конкретного репозитория, канон о ней не
знает, а без записи следующий автор либо заведёт вторую проверку того же, знает, а без записи следующий автор либо заведёт вторую проверку того же,
либо будет вычитывать глазами уже проверенное машиной. Без номера правила либо будет вычитывать глазами уже проверенное машиной. Без идентификатора
читатель догадывается сам, к какому утверждению относится проверка, — и читатель догадывается сам, к какому утверждению относится проверка, — и
догадывается по-разному. догадывается по-разному.
### R8. Формулировка не удаляется из канона, пока механизирована не у всех ### META-8. Формулировка не удаляется из канона, пока механизирована не у всех
**НЕ ДОЛЖЕН.** Норма остаётся в каноне, пока хотя бы у одного потребителя **НЕ ДОЛЖЕН.** Норма остаётся в каноне, пока хотя бы у одного потребителя
машинной проверки нет. машинной проверки нет.
@@ -145,7 +148,7 @@ R16, под которым это правило существовало, ос
удалению нормы, а не то, что можно проверить машиной (см. `LANGUAGE.md`, удалению нормы, а не то, что можно проверить машиной (см. `LANGUAGE.md`,
состояние МЕХАНИЗИРОВАНО). состояние МЕХАНИЗИРОВАНО).
### R9. Общая механизация разрешает удалить норму из канона ### META-9. Общая механизация разрешает удалить норму из канона
**ДОПУСКАЕТСЯ.** Правило, уехавшее в общий конфиг линтера или в общую роль, **ДОПУСКАЕТСЯ.** Правило, уехавшее в общий конфиг линтера или в общую роль,
удаляется из канона одним `push`. удаляется из канона одним `push`.
@@ -153,10 +156,10 @@ R16, под которым это правило существовало, ос
**Почему.** Формулировка, дублирующая работающую у всех проверку, **Почему.** Формулировка, дублирующая работающую у всех проверку,
размазывает внимание: файл на несколько сотен строк заставляет человека и размазывает внимание: файл на несколько сотен строк заставляет человека и
агента добросовестно вычитывать тривиальное именование и не доходить до агента добросовестно вычитывать тривиальное именование и не доходить до
формы решения. Явное разрешение нужно, чтобы R8 не читался как запрет формы решения. Явное разрешение нужно, чтобы META-8 не читался как запрет
удалять вообще. удалять вообще.
### R10. Обоснование не удаляется никогда ### META-10. Обоснование не удаляется никогда
**НЕ ДОЛЖЕН.** Блок «Почему» остаётся и после того, как норма уехала в **НЕ ДОЛЖЕН.** Блок «Почему» остаётся и после того, как норма уехала в
линтер. линтер.
@@ -165,7 +168,7 @@ R16, под которым это правило существовало, ос
существует. Без обоснования не видно, когда причина отпала, — проверка существует. Без обоснования не видно, когда причина отпала, — проверка
продолжает работать по инерции, и возразить ей нечем, кроме как отключив. продолжает работать по инерции, и возразить ей нечем, кроме как отключив.
### R11. У трудноизменяемого слоя область действия пишется явно ### META-11. У трудноизменяемого слоя область действия пишется явно
**ДОЛЖЕН.** Конвенция о схеме БД, формате хранения или раскладке директорий **ДОЛЖЕН.** Конвенция о схеме БД, формате хранения или раскладке директорий
называет, к чему применяется: к новым таблицам и миграциям, а не к называет, к чему применяется: к новым таблицам и миграциям, а не к
@@ -177,7 +180,7 @@ R16, под которым это правило существовало, ос
состоянию, и оба исхода плохи — миграция живых данных ради опрятности либо состоянию, и оба исхода плохи — миграция живых данных ради опрятности либо
молчаливый вывод, что конвенция не соблюдается совсем. молчаливый вывод, что конвенция не соблюдается совсем.
### R12. Механизируется граница изменения, а не состояние ### META-12. Механизируется граница изменения, а не состояние
**ДОЛЖЕН.** Проверка запрещает нарушение в новых миграциях, а не в уже **ДОЛЖЕН.** Проверка запрещает нарушение в новых миграциях, а не в уже
существующей схеме. существующей схеме.
@@ -187,7 +190,7 @@ R16, под которым это правило существовало, ос
новое, ради чего заводилась. Проверка границы оставляет старое в покое и новое, ради чего заводилась. Проверка границы оставляет старое в покое и
делает новую ошибку невозможной. делает новую ошибку невозможной.
### R13. Список отступлений трудноизменяемого слоя — постоянный ### META-13. Список отступлений трудноизменяемого слоя — постоянный
**ДОЛЖЕН.** Перечисленные старые таблицы и раскладки живут как есть, а не **ДОЛЖЕН.** Перечисленные старые таблицы и раскладки живут как есть, а не
как задачи на дочистку. как задачи на дочистку.
@@ -197,25 +200,25 @@ R16, под которым это правило существовало, ос
тем, что список перестают вести, — и пропадает единственное место, где видно, тем, что список перестают вести, — и пропадает единственное место, где видно,
где именно правило не действует. где именно правило не действует.
### R14. Отступления перечисляются поимённо, со ссылкой на номера правил ### META-14. Отступления перечисляются поимённо, со ссылкой на правила
**ДОЛЖЕН.** В локальном регионе перечислены отступления, которые уже есть в **ДОЛЖЕН.** В локальном регионе перечислены отступления, которые уже есть в
коде, с номером правила и причиной. коде, с идентификатором правила и причиной.
**Почему.** Иначе репозиторий выглядит соблюдающим конвенцию, а проверить **Почему.** Иначе репозиторий выглядит соблюдающим конвенцию, а проверить
это можно только чтением всего кода. Со ссылками отступления счётны: видно, это можно только чтением всего кода. Со ссылками отступления счётны: видно,
сколько правил конвенции репозиторий реально не соблюдает. Пустой регион при сколько правил конвенции репозиторий реально не соблюдает. Пустой регион при
этом почти всегда означает не отсутствие отступлений, а то, что их не искали. этом почти всегда означает не отсутствие отступлений, а то, что их не искали.
### R15. Запись в регионе отступлений разбирается по масштабу ### META-15. Запись в регионе отступлений разбирается по масштабу
**ДОЛЖЕН.** Судьба записи зависит от того, что в ней сказано: **ДОЛЖЕН.** Судьба записи зависит от того, что в ней сказано:
| № | Что записано | Куда идёт | | № | Что записано | Куда идёт |
|---|---|---| |---|---|---|
| R15.1 | правилу не следуем в перечисленных местах, причина названа | остаётся отступлением | | META-15.1 | правилу не следуем в перечисленных местах, причина названа | остаётся отступлением |
| R15.2 | правило не применяется в репозитории целиком | чинится условие применимости — в каноне | | META-15.2 | правило не применяется в репозитории целиком | чинится условие применимости — в каноне |
| R15.3 | конвенция репозиторию не нужна | копия удаляется, подписки нет | | META-15.3 | конвенция репозиторию не нужна | копия удаляется, подписки нет |
**Почему.** Отступление описывает исключение, и по нему видно, какая часть **Почему.** Отступление описывает исключение, и по нему видно, какая часть
правила нарушена. Запись «мы это правило вообще не применяем» такой правила нарушена. Запись «мы это правило вообще не применяем» такой
@@ -223,7 +226,7 @@ R16, под которым это правило существовало, ос
правила в каноне, которую чинят один раз для всех, или лишнюю подписку, правила в каноне, которую чинят один раз для всех, или лишнюю подписку,
где файл просто не нужен. Оставленная отступлением, она прячет обе. где файл просто не нужен. Оставленная отступлением, она прячет обе.
### R17. Репо-специфичная часть «Связано» — в локальном регионе ### META-17. Репо-специфичная часть «Связано» — в локальном регионе
**ДОЛЖЕН.** Раздел «Связано» стоит в конце файла; канонические ссылки — в **ДОЛЖЕН.** Раздел «Связано» стоит в конце файла; канонические ссылки — в
общем тексте, ссылки на ADR, код и файлы конкретного репозитория — в общем тексте, ссылки на ADR, код и файлы конкретного репозитория — в
@@ -233,7 +236,7 @@ R16, под которым это правило существовало, ос
чужой файл у них битая с первого дня. Регион исключён из сравнения, поэтому чужой файл у них битая с первого дня. Регион исключён из сравнения, поэтому
та же ссылка внутри него никого не задевает и не даёт вечного шума в `diff`. та же ссылка внутри него никого не задевает и не даёт вечного шума в `diff`.
### R18. README директории перечисляет конвенции с однострочным описанием ### META-18. README директории перечисляет конвенции с однострочным описанием
**СЛЕДУЕТ.** Одна плоская таблица: файл и строка о том, про что он. **СЛЕДУЕТ.** Одна плоская таблица: файл и строка о том, про что он.
@@ -241,15 +244,16 @@ R16, под которым это правило существовало, ос
«какая из них про мой случай» решается открыванием каждой. Ценой в десяток «какая из них про мой случай» решается открыванием каждой. Ценой в десяток
файлов это означает, что не открывают ни одной. файлов это означает, что не открывают ни одной.
### R19. Короткие инварианты дублируются в точку входа агента ### META-19. Короткие инварианты дублируются в точку входа агента
**ДОЛЖЕН.** В `AGENTS.md` / `CLAUDE.md` едет одна строка на правило с его **ДОЛЖЕН.** В `AGENTS.md` / `CLAUDE.md` едет одна строка на правило с его
номером; детали остаются в конвенции. идентификатором; детали остаются в конвенции.
**Почему.** Сама по себе конвенция агенту не видна: он дойдёт до неё, только **Почему.** Сама по себе конвенция агенту не видна: он дойдёт до неё, только
если его туда отправили, — а безусловно он читает точку входа. Строка с если его туда отправили, — а безусловно он читает точку входа. Строка с
номером служит и напоминанием, и адресом, по которому за подробностями идентификатором служит и напоминанием, и адресом, по которому за
идут; перенос деталей туда же вернул бы задачу поддержки двух текстов. подробностями идут; перенос деталей туда же вернул бы задачу поддержки двух
текстов.
<!-- local:точки-входа --> <!-- local:точки-входа -->
<!-- /local --> <!-- /local -->
+37 -21
View File
@@ -12,8 +12,8 @@
Не ради строгости. Три конкретные вещи, которые без адресуемых правил не Не ради строгости. Три конкретные вещи, которые без адресуемых правил не
работают: работают:
- **Механизация.** Регион `механизировано` должен говорить «правило R4 - **Механизация.** Регион `механизировано` должен говорить «правило
проверяет `archrules`», а не «`AUTOINCREMENT` в новых миграциях — `MIGR-4` проверяет `archrules`», а не «`AUTOINCREMENT` в новых миграциях —
`archrules`»: во втором случае читатель сам догадывается, к какому `archrules`»: во втором случае читатель сам догадывается, к какому
утверждению это относится, и догадывается по-разному. утверждению это относится, и догадывается по-разному.
- **Отступления.** «У нас не так» бесполезно, пока не сказано, что именно - **Отступления.** «У нас не так» бесполезно, пока не сказано, что именно
@@ -28,7 +28,7 @@
## Единица — правило ## Единица — правило
```markdown ```markdown
### R5. Разбор внешнего идентификатора на границе ### KEYS-5. Разбор внешнего идентификатора на границе
**ДОЛЖЕН.** Идентификатор, пришедший снаружи, проходит разбор до запроса **ДОЛЖЕН.** Идентификатор, пришедший снаружи, проходит разбор до запроса
к базе. к базе.
@@ -38,8 +38,8 @@
существующую запись — отладка такого случая стоит дороже, чем сам разбор. существующую запись — отладка такого случая стоит дороже, чем сам разбор.
``` ```
Четыре обязательные части: **номер**, **заголовок**, **модальность с Четыре обязательные части: **идентификатор**, **заголовок**, **модальность
нормой**, **почему**. Норма — одна фраза; если в неё не влезает, это два с нормой**, **почему**. Норма — одна фраза; если в неё не влезает, это два
правила. правила.
## Правило без «почему» не принимается ## Правило без «почему» не принимается
@@ -79,7 +79,7 @@
Модальность живёт на **правиле**, а не на файле. Прежний файловый статус Модальность живёт на **правиле**, а не на файле. Прежний файловый статус
(`status: рекомендуемая` / `обязательная` в шапке) отменён: он неизбежно (`status: рекомендуемая` / `обязательная` в шапке) отменён: он неизбежно
врал, потому что один файл смешивает жёсткие требования с советами. В шапке врал, потому что один файл смешивает жёсткие требования с советами. В шапке
остаются только `extends` и служебные ключи копии. остаются только `prefix`, `extends` и служебные ключи копии.
Мы **не используем SHALL и прочие английские ключевые слова**. Они заняты Мы **не используем SHALL и прочие английские ключевые слова**. Они заняты
спецификациями (OpenSpec), и общий словарь стирал бы границу «конвенция — спецификациями (OpenSpec), и общий словарь стирал бы границу «конвенция —
@@ -87,13 +87,26 @@
## Идентификаторы ## Идентификаторы
- Формат — `R<номер>`, сквозная нумерация внутри файла, начиная с `R1`. - Формат — `<ПРЕФИКС>-<номер>`: `KEYS-5`, `SLOG-27`. Префикс принадлежит
- Строка таблицы, если на неё нужно ссылаться отдельно, — `R5.1`, `R5.2`. файлу, нумерация внутри файла сквозная и начинается с единицы.
- **Номера стабильны и не переиспользуются.** Удалённое правило оставляет - Строка таблицы, если на неё нужно ссылаться отдельно, — `KEYS-5.1`,
дыру в нумерации; занимать её новым правилом нельзя — иначе ссылка из `KEYS-5.2`.
чужого репозитория начнёт указывать на другое утверждение. - **Идентификатор глобален.** Префикс уникален по всему канону, поэтому
- Глобальный адрес — путь файла плюс номер: `arch/db-identifiers.md R5`. путь файла в ссылке не нужен: `KEYS-5` адресует правило одинаково изнутри
В пределах одного файла достаточно `R5`. файла, из соседней конвенции и из чужого репозитория. В собранной копии
слои разных осей лежат в одном документе, так что ссылка на базовый слой
из языкового вообще никуда не ведёт — правило рядом.
- **Идентификаторы стабильны и не переиспользуются.** Удалённое правило
оставляет дыру в нумерации; занимать её новым нельзя — иначе ссылка из
чужого репозитория начнёт указывать на другое утверждение. То же
относится к префиксам: выбывшие хранит `conventions/prefixes.toml`.
- Префикс **выбирается под файл, а не выводится по формуле**: он нужен,
чтобы по нему искать, а не чтобы его разбирать. Выводимый префикс вдобавок
привязал бы идентификатор к таксономии, которую канон перестраивает, и
упёрся бы в потолок из числа букв алфавита.
- Перенос правила в другой файл — смысловое изменение, а не переименование:
новый файл означает новый префикс и новую нумерацию. Переезд самого файла
между осями идентификаторы не трогает.
Порядок правил в файле выбирается по читаемости, не по номерам: номер — это Порядок правил в файле выбирается по читаемости, не по номерам: номер — это
идентификатор, а не позиция. идентификатор, а не позиция.
@@ -105,7 +118,7 @@
чтобы оно не выглядело недописанным, место нормы занимает отметка: чтобы оно не выглядело недописанным, место нормы занимает отметка:
```markdown ```markdown
### R6. Дефолтов времени в схеме БД нет ### MIGR-6. Дефолтов времени в схеме БД нет
**МЕХАНИЗИРОВАНО.** Проверяется общим правилом линтера; формулировка **МЕХАНИЗИРОВАНО.** Проверяется общим правилом линтера; формулировка
удалена, потому что дублировала работающую проверку. удалена, потому что дублировала работающую проверку.
@@ -113,7 +126,7 @@
**Почему.** Дефолт превращает забытую вставку в тихо работающий код… **Почему.** Дефолт превращает забытую вставку в тихо работающий код…
``` ```
- Номер и заголовок сохраняются: ссылки из репозиториев продолжают - Идентификатор и заголовок сохраняются: ссылки из репозиториев продолжают
указывать на то же утверждение. указывать на то же утверждение.
- «Почему» остаётся навсегда — линтер сообщает, что нарушено, но не - «Почему» остаётся навсегда — линтер сообщает, что нарушено, но не
сообщает, зачем правило существует, и без обоснования нельзя понять, сообщает, зачем правило существует, и без обоснования нельзя понять,
@@ -175,11 +188,11 @@ AND тик фонового цикла упал по той же причине
```markdown ```markdown
<!-- local:механизировано --> <!-- local:механизировано -->
R2, R4 — `internal/archrules` (проверяются в новых миграциях). MIGR-2, MIGR-4 — `internal/archrules` (проверяются в новых миграциях).
<!-- /local --> <!-- /local -->
<!-- local:отступления --> <!-- local:отступления -->
R6 — не соблюдается в легаси-таблицах `show_history`, `queue`: составные MIGR-6 — не соблюдается в легаси-таблицах `show_history`, `queue`: составные
ключи там появились до конвенции, переписывание требует миграции данных. ключи там появились до конвенции, переписывание требует миграции данных.
<!-- /local --> <!-- /local -->
``` ```
@@ -191,12 +204,15 @@ R6 — не соблюдается в легаси-таблицах `show_histor
Сейчас не реализовано; список — на будущее для `conv`: Сейчас не реализовано; список — на будущее для `conv`:
- префикс в шапке файла совпадает с реестром, состоит из четырёх заглавных
латинских букв и не значится в списке выбывших;
- заголовки правил файла используют только его собственный префикс;
- номера уникальны внутри файла и не имеют пропусков вниз (новое правило - номера уникальны внутри файла и не имеют пропусков вниз (новое правило
берёт следующий свободный, а не первый освободившийся); берёт следующий свободный, а не первый освободившийся);
- у каждого `### R<n>` есть модальное слово (или отметка МЕХАНИЗИРОВАНО) и - у каждого `### <ПРЕФИКС>-<n>` есть модальное слово (или отметка
блок «Почему»; МЕХАНИЗИРОВАНО) и блок «Почему»;
- ссылки вида `R<n>` в локальных регионах копии указывают на правила, - ссылки вида `<ПРЕФИКС>-<n>` — хоть в тексте канона, хоть в локальных
которые в каноне ещё существуют; регионах копии — указывают на правила, которые ещё существуют;
- модальные слова не встречаются вне правил. - модальные слова не встречаются вне правил.
## Порядок перевода ## Порядок перевода
+21 -5
View File
@@ -50,9 +50,11 @@ conventions/
stack/<стек>/ привязка к инструменту, хранилищу, транспорту stack/<стек>/ привязка к инструменту, хранилищу, транспорту
``` ```
Пути правил даются относительно `conventions/`: адрес Пути **файлов** даются относительно `conventions/`: `arch/db-identifiers.md`,
`arch/db-identifiers.md R5`, а не `conventions/arch/…` — так же, как они а не `conventions/arch/…` — так же, как они лягут в `docs/conventions/`
лягут в `docs/conventions/` репозитория. репозитория. На **правила** ссылаются идентификатором без пути: `KEYS-5`.
Префикс уникален по всему канону (реестр — `conventions/prefixes.toml`),
поэтому идентификатор не зависит от того, на какой оси файл лежит сегодня.
Тест — по тому, замена чего убивает правило: Тест — по тому, замена чего убивает правило:
@@ -77,9 +79,23 @@ conventions/
пласт `stack/sqlite/` (типы колонок). Это не принцип, а незавершённая пласт `stack/sqlite/` (типы колонок). Это не принцип, а незавершённая
работа. работа.
## Префиксы
Каждый файл канона объявляет в шапке свой префикс правил:
```yaml
prefix: KEYS
```
Четыре заглавные латинские буквы, уникальные по всему канону; реестр —
[`conventions/prefixes.toml`](conventions/prefixes.toml). Префикс выбирается
под файл, а не выводится по формуле, и не переиспользуется никогда. Правила
адресуются идентификатором `KEYS-5` — без пути к файлу. Подробности формы —
`LANGUAGE.md`.
## Расширение ## Расширение
Файл в `lang/` или `stack/` может объявить в шапке: Файл в `lang/` или `stack/` может объявить в шапке ещё и базу:
```yaml ```yaml
extends: arch/db-identifiers.md extends: arch/db-identifiers.md
@@ -109,7 +125,7 @@ local: нет # или: чем и почему разошлись
`origin_hash` — контент-отпечаток, а не git-SHA. Он позволяет отличать `origin_hash` — контент-отпечаток, а не git-SHA. Он позволяет отличать
«канон обновился» от «изменено локально»; без него `status` умеет только «канон обновился» от «изменено локально»; без него `status` умеет только
«differs», а такой отчёт быстро перестают читать. Прочие ключи шапки «differs», а такой отчёт быстро перестают читать. Прочие ключи шапки
(`status`, `extends`) — часть документа: они сравниваются наравне с телом. (`prefix`, `extends`) — часть документа: они сравниваются наравне с телом.
**Локальные регионы** — куски, принадлежащие репозиторию по определению. **Локальные регионы** — куски, принадлежащие репозиторию по определению.
Из сравнения исключаются, поэтому вечного шума в `diff` не дают: Из сравнения исключаются, поэтому вечного шума в `diff` не дают: