обвязка: идентификаторы правил описаны через префиксы
- LANGUAGE.md: раздел «Идентификаторы» переписан под префиксы, в список машинных проверок добавлена сверка с реестром - GUIDE.md перенумерован под префикс META, «номер правила» заменён на «идентификатор»
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
---
|
||||
prefix: META
|
||||
---
|
||||
|
||||
# Как мы ведём конвенции
|
||||
|
||||
Конвенция описывает повторяющийся выбор: как называть директории, как
|
||||
@@ -29,11 +33,10 @@
|
||||
## Оформление
|
||||
|
||||
Имя файла — kebab-case по теме: `app-directories.md`. Правилом это не
|
||||
записано: обоснование сводится к «чтобы адрес правила
|
||||
(`stack/ansible/app-directories.md R4`) писался одним способом», а
|
||||
проверить нарушение всё равно проще глазом, чем сформулировать норму. Номер
|
||||
R16, под которым это правило существовало, оставлен свободным и не
|
||||
переиспользуется.
|
||||
записано: обоснование сводится к «чтобы имя файла в реестре префиксов
|
||||
писалось одним способом», а проверить нарушение всё равно проще глазом, чем
|
||||
сформулировать норму. Номер META-16, под которым это правило существовало,
|
||||
оставлен свободным и не переиспользуется.
|
||||
|
||||
## Канон и копии
|
||||
|
||||
@@ -51,7 +54,7 @@ R16, под которым это правило существовало, ос
|
||||
|
||||
## Правила
|
||||
|
||||
### R1. Одна конвенция — один файл
|
||||
### META-1. Одна конвенция — один файл
|
||||
|
||||
**ДОЛЖЕН.** Файл описывает ровно один повторяющийся выбор.
|
||||
|
||||
@@ -61,7 +64,7 @@ R16, под которым это правило существовало, ос
|
||||
позже дорого: путь файла — часть адреса правила, и после разреза внешние
|
||||
ссылки указывают не туда.
|
||||
|
||||
### R2. Конвенция заводится, когда решение принимается третий раз
|
||||
### META-2. Конвенция заводится, когда решение принимается третий раз
|
||||
|
||||
**СЛЕДУЕТ.** Поводом служит одно и то же решение, принятое третий раз и
|
||||
каждый раз чуть по-другому.
|
||||
@@ -72,7 +75,7 @@ R16, под которым это правило существовало, ос
|
||||
спорный, читателю нужен вместе с мотивом — это 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`,
|
||||
состояние МЕХАНИЗИРОВАНО).
|
||||
|
||||
### R9. Общая механизация разрешает удалить норму из канона
|
||||
### META-9. Общая механизация разрешает удалить норму из канона
|
||||
|
||||
**ДОПУСКАЕТСЯ.** Правило, уехавшее в общий конфиг линтера или в общую роль,
|
||||
удаляется из канона одним `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 | правилу не следуем в перечисленных местах, причина названа | остаётся отступлением |
|
||||
| R15.2 | правило не применяется в репозитории целиком | чинится условие применимости — в каноне |
|
||||
| R15.3 | конвенция репозиторию не нужна | копия удаляется, подписки нет |
|
||||
| META-15.1 | правилу не следуем в перечисленных местах, причина названа | остаётся отступлением |
|
||||
| META-15.2 | правило не применяется в репозитории целиком | чинится условие применимости — в каноне |
|
||||
| META-15.3 | конвенция репозиторию не нужна | копия удаляется, подписки нет |
|
||||
|
||||
**Почему.** Отступление описывает исключение, и по нему видно, какая часть
|
||||
правила нарушена. Запись «мы это правило вообще не применяем» такой
|
||||
@@ -223,7 +226,7 @@ R16, под которым это правило существовало, ос
|
||||
правила в каноне, которую чинят один раз для всех, или лишнюю подписку,
|
||||
где файл просто не нужен. Оставленная отступлением, она прячет обе.
|
||||
|
||||
### R17. Репо-специфичная часть «Связано» — в локальном регионе
|
||||
### META-17. Репо-специфичная часть «Связано» — в локальном регионе
|
||||
|
||||
**ДОЛЖЕН.** Раздел «Связано» стоит в конце файла; канонические ссылки — в
|
||||
общем тексте, ссылки на ADR, код и файлы конкретного репозитория — в
|
||||
@@ -233,7 +236,7 @@ R16, под которым это правило существовало, ос
|
||||
чужой файл у них битая с первого дня. Регион исключён из сравнения, поэтому
|
||||
та же ссылка внутри него никого не задевает и не даёт вечного шума в `diff`.
|
||||
|
||||
### R18. README директории перечисляет конвенции с однострочным описанием
|
||||
### META-18. README директории перечисляет конвенции с однострочным описанием
|
||||
|
||||
**СЛЕДУЕТ.** Одна плоская таблица: файл и строка о том, про что он.
|
||||
|
||||
@@ -241,15 +244,16 @@ R16, под которым это правило существовало, ос
|
||||
«какая из них про мой случай» решается открыванием каждой. Ценой в десяток
|
||||
файлов это означает, что не открывают ни одной.
|
||||
|
||||
### R19. Короткие инварианты дублируются в точку входа агента
|
||||
### META-19. Короткие инварианты дублируются в точку входа агента
|
||||
|
||||
**ДОЛЖЕН.** В `AGENTS.md` / `CLAUDE.md` едет одна строка на правило с его
|
||||
номером; детали остаются в конвенции.
|
||||
идентификатором; детали остаются в конвенции.
|
||||
|
||||
**Почему.** Сама по себе конвенция агенту не видна: он дойдёт до неё, только
|
||||
если его туда отправили, — а безусловно он читает точку входа. Строка с
|
||||
номером служит и напоминанием, и адресом, по которому за подробностями
|
||||
идут; перенос деталей туда же вернул бы задачу поддержки двух текстов.
|
||||
идентификатором служит и напоминанием, и адресом, по которому за
|
||||
подробностями идут; перенос деталей туда же вернул бы задачу поддержки двух
|
||||
текстов.
|
||||
|
||||
<!-- local:точки-входа -->
|
||||
<!-- /local -->
|
||||
|
||||
+37
-21
@@ -12,8 +12,8 @@
|
||||
Не ради строгости. Три конкретные вещи, которые без адресуемых правил не
|
||||
работают:
|
||||
|
||||
- **Механизация.** Регион `механизировано` должен говорить «правило R4
|
||||
проверяет `archrules`», а не «`AUTOINCREMENT` в новых миграциях —
|
||||
- **Механизация.** Регион `механизировано` должен говорить «правило
|
||||
`MIGR-4` проверяет `archrules`», а не «`AUTOINCREMENT` в новых миграциях —
|
||||
`archrules`»: во втором случае читатель сам догадывается, к какому
|
||||
утверждению это относится, и догадывается по-разному.
|
||||
- **Отступления.** «У нас не так» бесполезно, пока не сказано, что именно
|
||||
@@ -28,7 +28,7 @@
|
||||
## Единица — правило
|
||||
|
||||
```markdown
|
||||
### R5. Разбор внешнего идентификатора на границе
|
||||
### KEYS-5. Разбор внешнего идентификатора на границе
|
||||
|
||||
**ДОЛЖЕН.** Идентификатор, пришедший снаружи, проходит разбор до запроса
|
||||
к базе.
|
||||
@@ -38,8 +38,8 @@
|
||||
существующую запись — отладка такого случая стоит дороже, чем сам разбор.
|
||||
```
|
||||
|
||||
Четыре обязательные части: **номер**, **заголовок**, **модальность с
|
||||
нормой**, **почему**. Норма — одна фраза; если в неё не влезает, это два
|
||||
Четыре обязательные части: **идентификатор**, **заголовок**, **модальность
|
||||
с нормой**, **почему**. Норма — одна фраза; если в неё не влезает, это два
|
||||
правила.
|
||||
|
||||
## Правило без «почему» не принимается
|
||||
@@ -79,7 +79,7 @@
|
||||
Модальность живёт на **правиле**, а не на файле. Прежний файловый статус
|
||||
(`status: рекомендуемая` / `обязательная` в шапке) отменён: он неизбежно
|
||||
врал, потому что один файл смешивает жёсткие требования с советами. В шапке
|
||||
остаются только `extends` и служебные ключи копии.
|
||||
остаются только `prefix`, `extends` и служебные ключи копии.
|
||||
|
||||
Мы **не используем SHALL и прочие английские ключевые слова**. Они заняты
|
||||
спецификациями (OpenSpec), и общий словарь стирал бы границу «конвенция —
|
||||
@@ -87,13 +87,26 @@
|
||||
|
||||
## Идентификаторы
|
||||
|
||||
- Формат — `R<номер>`, сквозная нумерация внутри файла, начиная с `R1`.
|
||||
- Строка таблицы, если на неё нужно ссылаться отдельно, — `R5.1`, `R5.2`.
|
||||
- **Номера стабильны и не переиспользуются.** Удалённое правило оставляет
|
||||
дыру в нумерации; занимать её новым правилом нельзя — иначе ссылка из
|
||||
чужого репозитория начнёт указывать на другое утверждение.
|
||||
- Глобальный адрес — путь файла плюс номер: `arch/db-identifiers.md R5`.
|
||||
В пределах одного файла достаточно `R5`.
|
||||
- Формат — `<ПРЕФИКС>-<номер>`: `KEYS-5`, `SLOG-27`. Префикс принадлежит
|
||||
файлу, нумерация внутри файла сквозная и начинается с единицы.
|
||||
- Строка таблицы, если на неё нужно ссылаться отдельно, — `KEYS-5.1`,
|
||||
`KEYS-5.2`.
|
||||
- **Идентификатор глобален.** Префикс уникален по всему канону, поэтому
|
||||
путь файла в ссылке не нужен: `KEYS-5` адресует правило одинаково изнутри
|
||||
файла, из соседней конвенции и из чужого репозитория. В собранной копии
|
||||
слои разных осей лежат в одном документе, так что ссылка на базовый слой
|
||||
из языкового вообще никуда не ведёт — правило рядом.
|
||||
- **Идентификаторы стабильны и не переиспользуются.** Удалённое правило
|
||||
оставляет дыру в нумерации; занимать её новым нельзя — иначе ссылка из
|
||||
чужого репозитория начнёт указывать на другое утверждение. То же
|
||||
относится к префиксам: выбывшие хранит `conventions/prefixes.toml`.
|
||||
- Префикс **выбирается под файл, а не выводится по формуле**: он нужен,
|
||||
чтобы по нему искать, а не чтобы его разбирать. Выводимый префикс вдобавок
|
||||
привязал бы идентификатор к таксономии, которую канон перестраивает, и
|
||||
упёрся бы в потолок из числа букв алфавита.
|
||||
- Перенос правила в другой файл — смысловое изменение, а не переименование:
|
||||
новый файл означает новый префикс и новую нумерацию. Переезд самого файла
|
||||
между осями идентификаторы не трогает.
|
||||
|
||||
Порядок правил в файле выбирается по читаемости, не по номерам: номер — это
|
||||
идентификатор, а не позиция.
|
||||
@@ -105,7 +118,7 @@
|
||||
чтобы оно не выглядело недописанным, место нормы занимает отметка:
|
||||
|
||||
```markdown
|
||||
### R6. Дефолтов времени в схеме БД нет
|
||||
### MIGR-6. Дефолтов времени в схеме БД нет
|
||||
|
||||
**МЕХАНИЗИРОВАНО.** Проверяется общим правилом линтера; формулировка
|
||||
удалена, потому что дублировала работающую проверку.
|
||||
@@ -113,7 +126,7 @@
|
||||
**Почему.** Дефолт превращает забытую вставку в тихо работающий код…
|
||||
```
|
||||
|
||||
- Номер и заголовок сохраняются: ссылки из репозиториев продолжают
|
||||
- Идентификатор и заголовок сохраняются: ссылки из репозиториев продолжают
|
||||
указывать на то же утверждение.
|
||||
- «Почему» остаётся навсегда — линтер сообщает, что нарушено, но не
|
||||
сообщает, зачем правило существует, и без обоснования нельзя понять,
|
||||
@@ -175,11 +188,11 @@ AND тик фонового цикла упал по той же причине
|
||||
|
||||
```markdown
|
||||
<!-- local:механизировано -->
|
||||
R2, R4 — `internal/archrules` (проверяются в новых миграциях).
|
||||
MIGR-2, MIGR-4 — `internal/archrules` (проверяются в новых миграциях).
|
||||
<!-- /local -->
|
||||
|
||||
<!-- local:отступления -->
|
||||
R6 — не соблюдается в легаси-таблицах `show_history`, `queue`: составные
|
||||
MIGR-6 — не соблюдается в легаси-таблицах `show_history`, `queue`: составные
|
||||
ключи там появились до конвенции, переписывание требует миграции данных.
|
||||
<!-- /local -->
|
||||
```
|
||||
@@ -191,12 +204,15 @@ R6 — не соблюдается в легаси-таблицах `show_histor
|
||||
|
||||
Сейчас не реализовано; список — на будущее для `conv`:
|
||||
|
||||
- префикс в шапке файла совпадает с реестром, состоит из четырёх заглавных
|
||||
латинских букв и не значится в списке выбывших;
|
||||
- заголовки правил файла используют только его собственный префикс;
|
||||
- номера уникальны внутри файла и не имеют пропусков вниз (новое правило
|
||||
берёт следующий свободный, а не первый освободившийся);
|
||||
- у каждого `### R<n>` есть модальное слово (или отметка МЕХАНИЗИРОВАНО) и
|
||||
блок «Почему»;
|
||||
- ссылки вида `R<n>` в локальных регионах копии указывают на правила,
|
||||
которые в каноне ещё существуют;
|
||||
- у каждого `### <ПРЕФИКС>-<n>` есть модальное слово (или отметка
|
||||
МЕХАНИЗИРОВАНО) и блок «Почему»;
|
||||
- ссылки вида `<ПРЕФИКС>-<n>` — хоть в тексте канона, хоть в локальных
|
||||
регионах копии — указывают на правила, которые ещё существуют;
|
||||
- модальные слова не встречаются вне правил.
|
||||
|
||||
## Порядок перевода
|
||||
|
||||
@@ -50,9 +50,11 @@ conventions/
|
||||
stack/<стек>/ привязка к инструменту, хранилищу, транспорту
|
||||
```
|
||||
|
||||
Пути правил даются относительно `conventions/`: адрес
|
||||
`arch/db-identifiers.md R5`, а не `conventions/arch/…` — так же, как они
|
||||
лягут в `docs/conventions/` репозитория.
|
||||
Пути **файлов** даются относительно `conventions/`: `arch/db-identifiers.md`,
|
||||
а не `conventions/arch/…` — так же, как они лягут в `docs/conventions/`
|
||||
репозитория. На **правила** ссылаются идентификатором без пути: `KEYS-5`.
|
||||
Префикс уникален по всему канону (реестр — `conventions/prefixes.toml`),
|
||||
поэтому идентификатор не зависит от того, на какой оси файл лежит сегодня.
|
||||
|
||||
Тест — по тому, замена чего убивает правило:
|
||||
|
||||
@@ -77,9 +79,23 @@ conventions/
|
||||
пласт `stack/sqlite/` (типы колонок). Это не принцип, а незавершённая
|
||||
работа.
|
||||
|
||||
## Префиксы
|
||||
|
||||
Каждый файл канона объявляет в шапке свой префикс правил:
|
||||
|
||||
```yaml
|
||||
prefix: KEYS
|
||||
```
|
||||
|
||||
Четыре заглавные латинские буквы, уникальные по всему канону; реестр —
|
||||
[`conventions/prefixes.toml`](conventions/prefixes.toml). Префикс выбирается
|
||||
под файл, а не выводится по формуле, и не переиспользуется никогда. Правила
|
||||
адресуются идентификатором `KEYS-5` — без пути к файлу. Подробности формы —
|
||||
`LANGUAGE.md`.
|
||||
|
||||
## Расширение
|
||||
|
||||
Файл в `lang/` или `stack/` может объявить в шапке:
|
||||
Файл в `lang/` или `stack/` может объявить в шапке ещё и базу:
|
||||
|
||||
```yaml
|
||||
extends: arch/db-identifiers.md
|
||||
@@ -109,7 +125,7 @@ local: нет # или: чем и почему разошлись
|
||||
`origin_hash` — контент-отпечаток, а не git-SHA. Он позволяет отличать
|
||||
«канон обновился» от «изменено локально»; без него `status` умеет только
|
||||
«differs», а такой отчёт быстро перестают читать. Прочие ключи шапки
|
||||
(`status`, `extends`) — часть документа: они сравниваются наравне с телом.
|
||||
(`prefix`, `extends`) — часть документа: они сравниваются наравне с телом.
|
||||
|
||||
**Локальные регионы** — куски, принадлежащие репозиторию по определению.
|
||||
Из сравнения исключаются, поэтому вечного шума в `diff` не дают:
|
||||
|
||||
Reference in New Issue
Block a user