--- version: 1 --- # Язык конвенций Формальный язык, на котором записаны правила этого канона: что считается правилом, чем оно отличается от прозы вокруг, какими словами задаётся обязательность и как на правило сослаться извне. Версия языка — **1**. Номер называется в каждой конвенции: словарь может пополниться, и текст, написанный по предыдущей версии, должен читаться по той, по которой написан. Документ адресован автору набора и в репозиторий-потребитель не едет. К читателю копии едет короткое `READING.md`: словарь со значениями, форма правила и её граница, ссылки, локальная часть — без разделов о ведении набора. Словарь в двух документах обязан совпадать (META-30), и это единственное место, где между ними возможен дрейф. Описание языка ни на один набор конвенций не опирается, поэтому все примеры здесь — вымышленные правила с префиксами на `X` (`XKEY`, `XMIG`, `XLOG`). Такие префиксы канон не занимает никогда, в манифесте набора их нет — значит пример не спутать с настоящим правилом, а перенумерация конвенций описание языка не задевает. ## Опора на стандарты Язык не выводится из вкуса автора. Каждое решение о форме взято из документа, где эта задача уже решена и обкатана, и отклонения от источника названы явно. | Источник | Что взято | Что отклонено | |---|---|---| | **BCP 14** (RFC 2119 + RFC 8174) | шкала модальности; правило «нормативно только заглавное»; сдержанность в высшей модальности; англоязычный словарь как готовый | синонимы `REQUIRED`, `RECOMMENDED`, `OPTIONAL`; `SHALL` как форма требования | | **ISO/IEC Directives, Part 2** | разделение «требование — рекомендация — разрешение — возможность»; запрет модальных глаголов в утверждениях о факте | списки равнозначных словесных форм («is to», «is required to», «only … is permitted») | | **ISO/IEC/IEEE 29148** | характеристики хорошего требования — единичность и проверяемость; обоснование и метод верификации как отдельные атрибуты требования | остальной аппарат требований: приоритеты, источники, матрицы трассируемости | | **DMN** | таблица решений с объявленной политикой совпадения | исполняемая семантика и всё, что предполагает движок решений | | **EARS** | паттерн «нежелательное поведение» — в виде таблицы | шаблоны как форма записи правила: `WHEN`, `WHILE`, `WHERE` | | **OpenSpec** | четырёхчастная форма правила; адресуемость правила идентификатором; форма «условие → следствие» для стыка правил | `SHALL`; `GIVEN/WHEN/THEN` как общая форма записи | Три отклонения стоят объяснения, потому что выглядят как произвол. **Синонимов нет.** BCP 14 держит `REQUIRED` рядом с `MUST` и `OPTIONAL` рядом с `MAY` ради читаемости английской прозы. Одна форма записи на ступень означает, что проверка «модальное слово употреблено вне правила» становится перечислением, а не разбором синонимических рядов. **`SHALL` не используется ни в каком словаре этого языка.** Слово занято спецификациями (OpenSpec), и общая с ними форма стирала бы границу между конвенцией и описанием поведения системы: `SHALL` в конвенции читался бы как контракт, которого конвенция не даёт. Для англоязычного словаря это означает выбор в пользу `MUST` из BCP 14, а не `shall` из ISO/IEC Directives. **`GIVEN/WHEN/THEN` не берётся как общая форма.** У спецификации субъект — система, и её поведение разворачивается во времени: состояние, событие, исход. У конвенции субъект — автор кода, и разворачивать нечего: есть ситуация выбора и вердикт. Это таблица, а не траектория. Тем же рассуждением отклонены шаблоны EARS как форма записи правила, а взято из EARS другое — сообщённое снижение числа дефектов после введения шаблонов. Вывод, что дело в самой обязательности формы, а не в её конкретном виде, наш; он ниже, среди усилений. Исключение — стык правил, где субъект действительно система: там форма «условие → следствие» берётся сознательно, вместе со служебными словами под неё. Это единственное место, и оно описано в «Таблицах решений». ## Где источник усилен Три решения идут дальше источника, и это наши решения, а не его требования. Названы они отдельно, чтобы довод не подменялся ссылкой: спорить с ними нужно по существу, а не со стандартом. - **Обоснование обязательно.** В 29148 rationale — из списка рекомендуемых атрибутов требования; обязательный костяк там другой, это характеристики самого требования. Здесь правило без блока ПОЧЕМУ не принимается, потому что конвенция живёт годами и переживает автора: норма без причины через год либо отменяется первым возражением, либо соблюдается там, где вредит. - **Полнота таблицы решений.** DMN даёт политику совпадения как именованный атрибут, а полноты не требует: индикатор полноты был в первой версии спецификации и из последующих убран, полноту проверяют валидаторы инструментов. Здесь она требуется, потому что таблицу и заводят ради видимости пропуска: неперечисленный случай в прозе не виден, а пустая клетка видна. - **Вывод про обязательность шаблона.** В EARS сообщается о снижении числа дефектов в требованиях после введения шаблонов. Вывод, что выигрыш даёт сама обязательность формы, а не её конкретный вид, — наш: он объясняет, почему мы берём из EARS результат, но не берём сами шаблоны. ## Что даёт формализация Адресуемое правило — не украшение формы, а условие работы трёх механизмов: - **Механизация.** Запись о ней должна говорить «правило `XMIG-4` проверяет `archrules`», а не «`AUTOINCREMENT` в новых миграциях — `archrules`»: во втором случае читатель сам догадывается, к какому утверждению это относится, и догадывается по-разному. - **Отступления.** «У нас не так» бесполезно, пока не сказано, что именно «не так». Со ссылкой на правило отступления становятся счётными: видно, сколько правил конвенции репозиторий реально не соблюдает. - **Промоут находки.** Путь «находка → конвенция → правило линтера» требует ручки, за которую берут конкретное правило. Общий знаменатель — **идентификатор**. Модальные слова и таблицы полезны, но вторичны. ## Единица — правило ```markdown ### XKEY-5. Разбор внешнего идентификатора на границе **ДОЛЖЕН.** Идентификатор, пришедший снаружи, проходит разбор до запроса к базе. **ПОЧЕМУ.** Разбор валидирует формат и нормализует регистр. Сравнение строк в базе побайтовое, поэтому без нормализации запрос молча не находит существующую запись — отладка такого случая стоит дороже, чем сам разбор. ``` Четыре обязательные части: **идентификатор**, **заголовок**, **модальность с нормой**, **обоснование под меткой ПОЧЕМУ**. Пятый блок, ПРИМЕРЫ, необязателен — о нём ниже. Норма — одна фраза; если в неё не влезает, это два правила. Требование единичности взято из ISO/IEC/IEEE 29148: составная норма не проверяема целиком, и нарушение одной её половины нечем адресовать. Метки правила — модальное слово, ПОЧЕМУ, ПРИМЕРЫ — пишутся заглавными и принадлежат словарю набора: скелет правила читается одинаково в любом языке, на который канон переведён. **Правило кончается перед следующим заголовком.** Область правила — от его заголовка до следующего заголовка любого уровня. Внутри области текст принадлежит последнему открытому блоку: метка блок открывает, и блок длится до следующей метки или до конца области. ```markdown ### XKEY-3. Заголовок правила **ДОЛЖЕН.** Норма одной фразой. | № | ситуация | вердикт | ← блок нормы: таблица уточняет её **ПОЧЕМУ.** Причина. Продолжение причины, пример, ← блок обоснования продолжается ссылка на внешнюю практику. ### XKEY-4. Следующее правило ← здесь область кончилась ``` Отсюда три следствия: - **Хвост после ПОЧЕМУ — обоснование** до следующей метки или до конца области, а не безымянная часть правила и не проза вокруг. Требований в нём не живёт: то, что подлежит исполнению, стоит в блоке нормы, где у него есть модальность и адрес. Требование, оставленное в хвосте, требованием не является — сослаться на него нельзя и отступление от него записать нельзя. - **Таблица и список после модальной метки — часть нормы.** Правило, классифицирующее ситуации, ровно так и записывается («Таблицы решений»), а вердикт из такой таблицы адресуется номером строки. - **Проза — это то, что лежит вне областей правил.** Тем самым проверка «заглавных модальных слов вне правил нет» становится реализуемой: границу считает разметка, а не читательское суждение о том, где правило кончилось. Заглавное модальное слово внутри области правила законно, когда это упоминание ступени в обосновании («для СЛЕДУЕТ это честно»). Метку от упоминания отличает положение: метка стоит первой в своём абзаце, полужирным и с точкой. ## Примеры к правилу Пятый блок правила — необязательный, под меткой ПРИМЕРЫ. В нём код, показывающий норму в деле, обычно парой «плохо → хорошо». Стоит он после обоснования: сначала требование, потом причина, потом иллюстрация. ````markdown ### XKEY-5. Внешний идентификатор разбирается до обращения к базе **ДОЛЖЕН.** Значение, пришедшее снаружи, проходит разбор и нормализацию раньше, чем по нему делается запрос. **ПОЧЕМУ.** Синтаксически невалидное значение не может соответствовать записи, поэтому поход в базу за ним — заведомо холостой. **ПРИМЕРЫ.** Плохо — строка уходит в запрос как пришла: ```go row := db.QueryRow("select … where id = ?", r.PathValue("id")) ``` Хорошо — разбор на границе, запроса при неудаче нет: ```go id, err := ident.Parse(r.PathValue("id")) if err != nil { return notFound(w) } row := db.QueryRow("select … where id = ?", id) ``` ```` **Пример иллюстрирует норму, а не задаёт её.** Три следствия, ради которых это сказано: - **требований в блоке нет.** Всё, что подлежит исполнению, стоит в блоке нормы; деталь примера — имя переменной, конкретная функция, форма ответа — требованием не становится. Разошёлся пример с нормой — действует норма, а пример правят; - **это не готовый сниппет.** Код в примере сокращён до того, что показывает правило: обработка ошибок, контекст, импорты в нём условны, и копировать его дословно не нужно; - **пример стареет быстрее нормы.** Он привязан к сегодняшнему API, поэтому расхождение примера с текущим кодом — повод поправить пример, а не отменять правило. Блок необязателен: он окупается там, где норму словами описать дороже, чем показать, — форма вызова, структура записи в логе, раскладка файла. У правила про выбор границы или про уровень лога иллюстрировать нечего. ## Обоснование обязательно Правило без блока ПОЧЕМУ не принимается. Это требование к форме, а не пожелание. В 29148 обоснование — отдельный атрибут требования, но из рекомендуемых; здесь оно обязательно, и вот почему: - **Обоснование — единственный способ увидеть, что правило устарело.** Норма стареет молча; причина стареет заметно. Когда причина отпала, видно, что правило пора убрать, а не соблюдать по инерции. - **Правило без обоснования не переживает спор.** Через год ни автор, ни агент не восстановят мотив, и правило будет либо отменено первым же возражением, либо соблюдено там, где вредит. - **Формулировка обоснования — проверка на то, что это вообще правило.** Если причина не формулируется, перед нами привычка или вкусовщина; ей место в черновиках, а не в конвенции. Обоснование отвечает на «что сломается, если сделать иначе», а не пересказывает норму другими словами. «Потому что так принято» — не обоснование. Форма обоснования при этом ничем не ограничена: рамки здесь только смысловые. Абзац может быть длинным, вести рассуждение, приводить пример, ссылаться на стандарты, внешние практики и чужие проекты — на устройство OpenTelemetry, на умолчания библиотек логирования, на процедуру миграции из документации СУБД. Запрещённых слов и обязательной структуры у обоснования нет, и заводить их не нужно: обязательность несёт норма, а обоснование её объясняет — путаницу между этими двумя ролями исключает правило о заглавных. ## Модальные слова Инвариант языка — **шкала**: пять ступеней в четырёх категориях ISO/IEC Directives, Part 2, по одной форме записи на ступень, заглавными. Какими словами ступени названы — параметр естественного языка набора, а не часть языка конвенций. Этот канон написан по-русски и несёт русский словарь. Пишутся заглавными — это ключевые слова, а не обычный текст. | Слово | Категория | Значение | Отступление | |---|---|---|---| | **ДОЛЖЕН** | требование | нарушение считается ошибкой | только с записью в отступления | | **НЕ ДОЛЖЕН** | требование | запрет | то же | | **СЛЕДУЕТ** | рекомендация | сильная рекомендация; новый код пишем так | допустимо, причину записываем | | **НЕ СЛЕДУЕТ** | рекомендация | обратное к СЛЕДУЕТ | то же | | **ДОПУСКАЕТСЯ** | разрешение | выбор за автором кода; возражение на ревью не принимается | не требуется — правило ничего не запрещает | **Нормативно только заглавное написание.** Это правило RFC 8174, и оно здесь по той же причине, по которой понадобилось там: без него каждое строчное «должен» во вводной прозе становится предметом спора о том, норма это или речь. Строчное слово нормой не является никогда, поэтому проза свободна, а проверка «модальное слово вне правила» сводится к поиску заглавных форм. **Четвёртая категория ISO — возможность — ключевого слова не имеет.** Утверждения о том, что бывает и что технически осуществимо, пишутся обычной прозой и модальных слов не несут. Модальное слово в таком утверждении превращает описание в норму, которую никто не собирался вводить. **ДОПУСКАЕТСЯ адресовано рецензенту.** В BCP 14 у `MAY` есть вторая половина, которую обычно не замечают: сторона, не выбравшая опцию, обязана работать с той, что выбрала. В конвенции этому соответствует запрет возражать: выбор, помеченный ДОПУСКАЕТСЯ, на ревью не обсуждается. Без этой половины слово было бы удобством читателя, а не нормой, и не работало бы в единственной точке, где у конвенции есть принуждение. **ДОЛЖЕН требует двух условий сразу:** 1. нарушение причиняет названный вред, а не расходится со вкусом — META-25, он же критерий BCP 14, где высшая модальность резервируется под то, что действительно ломается, и не употребляется для навязывания метода; 2. вердикт о нарушении воспроизводим — META-6: по тексту правила двое проверяющих приходят к одному ответу, иначе обязательность держится на том, кто читал. Не выполнено первое — правилу место в СЛЕДУЕТ или нигде. Не выполнено второе — в СЛЕДУЕТ. Воспроизводимость сама по себе не повышает правило до ДОЛЖЕН: проверяемых мелочей больше, чем важных вещей, и безразборное повышение обесценивает шкалу быстрее, чем её отсутствие. Модальность живёт на **правиле**, а не на файле. Файловый статус (`status: рекомендуемая` / `обязательная` в шапке) не используется: он неизбежно врёт, потому что один файл смешивает жёсткие требования с советами. В шапке остаются только `topic`, `prefix` и `extends`. ## Словарь другого языка Словарь набора — три перечня, и требования к ним одни и те же. **Шкала обязательности.** Для английского готовый словарь даёт BCP 14; для любого другого языка слова берут из перевода стандарта, если он есть, или переводят сами. Шкала и семантика ступеней при этом не меняются — меняется только запись. | Ступень | Русский | Английский (BCP 14) | |---|---|---| | требование | ДОЛЖЕН | MUST | | запрет | НЕ ДОЛЖЕН | MUST NOT | | рекомендация | СЛЕДУЕТ | SHOULD | | рекомендация против | НЕ СЛЕДУЕТ | SHOULD NOT | | разрешение | ДОПУСКАЕТСЯ | MAY | **Метки.** Обязательности не задают, а размечают: ПОЧЕМУ — обоснование, ПРИМЕРЫ — иллюстрации к норме, МЕХАНИЗИРОВАНО — запись о проверке в копии, СНЯТО — заглушку на месте убранного правила. Стандартом не даются ни в одном языке: в BCP 14 таких понятий нет, слова подбираются под язык так же, как остальные. | Метка | Русский | Английский | |---|---|---| | обоснование | ПОЧЕМУ | WHY | | иллюстрации | ПРИМЕРЫ | EXAMPLES | | способ проверки | МЕХАНИЗИРОВАНО | MECHANIZED | | снятое правило | СНЯТО | RETIRED | **Служебные слова сценарного блока** — `КОГДА`, `ТОГДА`, `И`, `ИЛИ`; таблица и объяснение в разделе «Таблицы решений». Что требуется от любого словаря: - **одна форма на ступень и на метку.** Синонимы отклонены не из аскетизма: проверка «модальное слово вне правила» перечисляет формы, и синонимический ряд превращает перечисление в разбор. - **слово заглавными не встречается в обычной прозе этого языка.** Иначе правило «нормативно только заглавное» перестаёт спасать: проверка ловит оформление, а не модальность. - **модальные слова и метки перечислены в строке о версии языка.** Читателю копии они известны из самого файла, без обращения к этому документу, — иначе конвенция в чужом репозитории теряет ключ к собственному тексту. Служебные слова сценария в строку не входят: структура блока читается из самого блока, и в файле без стыков правил их нет вовсе. - **словарь один на канон.** Два словаря параллельно дают две формы записи одного требования и удваивают каждую проверку; выбор языка — свойство набора, а не отдельного файла. ## Ссылка на язык из конвенции Каждая конвенция называет язык одной строкой во вводной прозе: > Ключевые слова ДОЛЖЕН, НЕ ДОЛЖЕН, СЛЕДУЕТ, НЕ СЛЕДУЕТ, ДОПУСКАЕТСЯ и метки > ПОЧЕМУ, ПРИМЕРЫ, МЕХАНИЗИРОВАНО и СНЯТО толкуются как описано в языке > конвенций версии 1 — тогда и только тогда, когда написаны заглавными. Слова в строке — из словаря того языка, на котором написан набор. Для англоязычного набора та же строка выглядит так: > The key words MUST, MUST NOT, SHOULD, SHOULD NOT, MAY and the marks WHY, > EXAMPLES, MECHANIZED and RETIRED are to be interpreted as described in the > conventions language, version 1, and only when written in capitals. Форма скопирована у BCP 14, где та же задача решается тем же способом: спецификация не прикладывает к себе словарь и не указывает путь к нему, а называет документ и версию. Пути в этой строке нет намеренно — конвенция уезжает в чужой репозиторий, где путей канона не существует, а норму исполнить всё равно можно: строка сама перечисляет ключевые слова набора и сама несёт правило заглавных. ## Обязательность и способ проверки — разные атрибуты Механизация не входит в шкалу модальности: она говорит не о том, насколько правило обязательно, а о том, чем эта обязательность обеспечена. В 29148 это два разных атрибута требования, и здесь тоже два. **Проверяющий по умолчанию — читатель правила**, человек или агент. Канон пишется прежде всего под агента: он читает конвенцию и по ней смотрит код, то есть проверка есть у каждого правила с первого дня, и её инструмент — формулировка нормы. Поэтому вторым условием ДОЛЖЕН стоит воспроизводимость вердикта (META-6), а не наличие скрипта: ступень говорит о важности нормы и о том, сколько внимания она получает при проверке, а не о состоянии инструментов. Линтер сильнее чтения — он не забывает, ничего не стоит на каждом прогоне и краснеет до ревью, — поэтому механизация желательна везде, где проверка пишется (META-27), и остаётся концом пути «находка → конвенция → проверка». Но обязательным условием высшей ступени она не является: иначе весь канон стоял бы в СЛЕДУЕТ до появления скриптов, которых пока нет ни одного. **Механизация нормы не заменяет и не сокращает.** Норма остаётся в правиле навсегда — как и обоснование (META-8, META-10), — сколько бы проверок её ни подпирало. Причин три: - **линтер сообщает, что нарушено, но не сообщает, что требуется.** Без нормы правило нечем исполнить и не с чем сверить вердикт проверки, а проверяющий по умолчанию читает именно норму; - **подписчики появляются позже.** Репозиторий, подключившийся через год, получил бы правило без нормы и без линтера — ни текста, ни проверки; - **«механизировано у всех» набору не проверить:** списка подписчиков у него нет по построению. **Отметка — свойство репозитория, а не набора.** Механизирована норма или нет, зависит от того, чей это репозиторий, поэтому в тексте конвенции отметки нет: её место — запись о механизации в локальной части копии, со ссылкой на идентификатор правила (META-7). ```markdown XMIG-2, XMIG-4 — МЕХАНИЗИРОВАНО: `internal/archrules`, в новых миграциях. ``` Так у правила остаются оба атрибута сразу: обязательность — в норме, которая приезжает из набора и одинакова у всех, способ проверки — в записи, которая принадлежит репозиторию и у каждого своя. ## Таблицы решений Часть правил **классифицирует ситуации**: какой уровень лога, какая категория директории, что делать с невалидным вводом в зависимости от его источника. Каноническая форма для них — таблица «ситуация → вердикт», строки которой нумеруются как подпункты правила (`XLOG-8.1`). Таблица плотнее прозы и не даёт пропустить ветку: пустая клетка видна, а неупомянутый случай в абзаце — нет. От такой таблицы требуются два свойства — первое названо в DMN, второе мы добавили сами («Где источник усилен»): - **Политика совпадения.** По умолчанию строки взаимоисключающи: любой ситуации соответствует ровно одна. Если это не так, таблица объявляет порядок строкой над собой — «применяется первое совпадение». Молчание об этом означает, что при двух подходящих строках читатель выбирает сам, и два автора выберут по-разному. - **Полнота.** Перечислены все случаи, попадающие в область действия. Если возможен случай вне перечисленных, он назван отдельной строкой, а не оставлен на догадку. Сценарный блок остаётся точечным инструментом — для **стыка правил**, когда два правила вместе дают неочевидный результат: ``` КОГДА зависимость недоступна И ретраи вызова исчерпаны ТОГДА внешний вызов даёт запись ERROR, И тик фонового цикла, упавший по той же причине, — запись WARN ``` Такой блок ставится после обоих правил и ссылается на их идентификаторы. Если стыков нет — сценариев в файле нет. Форма «условие → следствие» здесь взята намеренно, хотя как **общая** форма записи она отклонена: на стыке правил субъект действительно система, и результат разворачивается во времени — то самое, для чего эта форма и придумана. Служебные слова блока перечислены ниже и подчиняются тем же требованиям, что модальные: одна форма на роль, заглавными, набор один на канон. | Роль | Русский | Английский | |---|---|---| | условие | КОГДА | WHEN | | следствие | ТОГДА | THEN | | соединение | И | AND | | выбор | ИЛИ | OR | Модальными словами они не являются: обязательности не задают, только структуру. Поэтому в строку о версии языка они не попадают — там перечисляется то, чему нужно определение, а логическая связка читается сама, — и под проверку «модальные слова вне правил» не подпадают. ## Идентификаторы Идентификаторов в языке два: **правило** адресуется префиксом с номером, **конвенция целиком** — именем темы. Ссылаться путём к файлу нельзя ни на то, ни на другое. **Правило.** - Формат — `<ПРЕФИКС>-<номер>`: `XKEY-5`, `XLOG-27`. Префикс принадлежит файлу, нумерация внутри файла сквозная и начинается с единицы. - Строка таблицы, если на неё нужно ссылаться отдельно, — `XKEY-5.1`, `XKEY-5.2`. - **Идентификатор глобален.** Префикс уникален по всему канону, поэтому путь файла в ссылке не нужен: `XKEY-5` адресует правило одинаково изнутри файла, из соседней конвенции и из чужого репозитория. В собранной копии слои разных осей лежат в одном документе, так что ссылка на базовый слой из языкового вообще никуда не ведёт — правило рядом. - **Идентификаторы стабильны и не переиспользуются.** Занять номер снятого правила новым нельзя — иначе ссылка из чужого репозитория начнёт указывать на другое утверждение. То же относится к префиксам: выбывшие хранит манифест набора. - **Снятое правило остаётся заглушкой.** Заголовок и номер сохраняются, норму с обоснованием заменяет блок СНЯТО с датой и причиной. Поэтому нумерация в файле сплошная, а любая ссылка разрешается — либо в правило, либо в объяснение, почему его сняли (META-31, META-32). Отдельного реестра снятых номеров нет: он был бы вторым источником правды рядом с файлом. - Префикс **выбирается под файл, а не выводится по формуле**: он нужен, чтобы по нему искать, а не чтобы его разбирать. Выводимый префикс вдобавок привязал бы идентификатор к таксономии, которую канон перестраивает, и упёрся бы в потолок из числа букв алфавита. - Префиксы на букву `X` каноном не занимаются: они принадлежат локальным правилам репозиториев-потребителей. - Перенос правила в другой файл — смысловое изменение, а не переименование: новый файл означает новый префикс и новую нумерацию. Переезд самого файла между осями идентификаторы не трогает. Порядок правил в файле выбирается по читаемости, не по номерам: номер — это идентификатор, а не позиция. **Тема.** - **Тема — набор правил об одном фокусе разработки:** время, конфигурация, схема БД. Она же — единица подписки: потребитель берёт тему целиком, а не отдельные правила. - Имя темы записывается латиницей. Рекомендуется нижний kebab-case (`db-identifiers`), но годится любой идентификатор, пригодный для имени файла: имя попадает и в файловую систему потребителя, и в его манифест. - **Тему объявляет файл, а не файловая система.** Имя стоит в шапке (`topic:`) и зарегистрировано в манифесте набора. Слои одной темы несут одно и то же имя — по нему они и собираются в один документ, как бы ни назывались их файлы. - **Имя темы не переиспользуется** — как и префикс: оно живёт в шапке `origin:` каждой копии, в подписке манифеста и в тексте ссылок, поэтому снятое имя уходит в раздел выбывших манифеста, а не достаётся другой теме. - Ссылка на конвенцию — имя темы (конвенция `logging`), ссылка на правило — идентификатор (`XLOG-27`). Путь файла не употребляется ни там, ни там: в собранной копии путей канона не существует. ## Что правилом не является Заглавные модальные слова в этих частях **не употребляются** — иначе перестанет быть понятно, что адресуемо, а что нет: - **Область действия** — на что конвенция распространяется во времени («новые таблицы; существующие не переписываются»). Это рамка для всех правил файла, а не правило. - **Связано** — ссылки на смежные конвенции, ADR, код. - **Локальная часть копии** — содержимое принадлежит репозиторию. - Вводная проза, объясняющая предмет конвенции. Все четыре части лежат вне областей правил: до первого заголовка правила или после заголовка, которым область закрылась. Хвост обоснования сюда не относится — он внутри правила, и модальные слова в нём законны как упоминания. ## Как на правила ссылаются копии Ниже маркера локальной части, в репозитории: ```markdown XMIG-2, XMIG-4 — МЕХАНИЗИРОВАНО: `internal/archrules`, в новых миграциях. XMIG-6 не соблюдается в легаси-таблицах `show_history`, `queue`: составные ключи там появились до конвенции, переписывание требует миграции данных. ``` Отсюда видно и то, чего раньше не было видно: конвенция из восьми правил, из которых два механизированы и одно не соблюдается. ## Что стоит проверять машиной Проверке подлежит всё, что язык **употребляет**: файлы конвенций и документ, которым канон сам себя ведёт (в этом каноне — `GUIDE.md`, префикс META). Файл, который язык **цитирует**, — это описание вроде текущего: ключевые слова стоят в нём как предмет разговора, а не как норма, и проверки к нему не применяются. Различает не расположение файла, а роль слова в нём. Ни одна проверка пока не реализована, поэтому при ревью их выполняют чтением. **Форма правила** — разбором текста, в любом файле, который язык употребляет: - модальные и служебные слова принадлежат объявленному словарю канона, а не смеси словарей; - префикс в шапке файла совпадает с манифестом набора, состоит из четырёх заглавных латинских букв, не начинается на `X` и не значится в списке выбывших; - заголовки правил файла используют только его собственный префикс; - нумерация внутри файла сплошная: от единицы до наибольшего номера без пропусков, номера не повторяются, новое правило берёт следующий за наибольшим (META-31); - у каждого `### <ПРЕФИКС>-` есть либо модальное слово с нормой и блок ПОЧЕМУ — ни норма, ни обоснование не удаляются никогда (META-8, META-10), — либо блок СНЯТО с датой и причиной; - блок ПРИМЕРЫ, если он есть, стоит после обоснования и не открывает правило: порядок блоков — норма, ПОЧЕМУ, ПРИМЕРЫ; - вводная проза содержит строку о версии языка; - ссылки вида `<ПРЕФИКС>-` — хоть в тексте набора, хоть в локальной части копии — разрешаются: неразрешённый идентификатор всегда ошибка (META-32); - заглавные модальные слова не встречаются вне областей правил (область — от заголовка правила до следующего заголовка) — кроме строки о версии языка, которая их перечисляет по назначению; - модальная метка стоит первой в своём абзаце: заглавное слово в середине фразы — упоминание ступени, а не вторая норма правила. **Распространение** — разбором текста, только в файлах конвенций: эти проверки о том, что документ уезжает к потребителю, а документ, которым канон ведёт себя, не уезжает никуда. - шапка файла несёт имя темы, и это имя стоит в манифесте набора — среди живых, а не среди выбывших; - ось слоя объявлена в шапке, а не выведена из пути; у одной темы не больше одного слоя без ключей оси — базовый слой единственный; - если директории осей используются, объявленное в шапке совпадает с путём: расхождение означает переезд файла без правки шапки; - имя темы, названное в ссылке или в подписке потребителя, тоже разрешается по манифесту: ссылка на снятую тему не проходит молча; - префиксы локальных правил копии начинаются на `X`; - отметки МЕХАНИЗИРОВАНО в тексте конвенции нет: её место — запись о механизации в локальной части копии (META-7); - словарь в коротком описании языка совпадает с этим: те же ступени, те же метки, те же значения (META-30); - префикс **чужой темы** не встречается в абзаце с модальностью (META-20); префикс арх-слоя своей темы там допустим (META-24), префикс другого языка или стека — нет; - путь файла канона не встречается в тексте конвенции (META-21). **Чтением**, потому что машине не даётся: - строки таблицы взаимоисключающи либо политика совпадения объявлена; - перечисленные в таблице случаи покрывают область действия; - норма исполнима без обращения к другим файлам (в файлах конвенций: они уезжают по одной, а обвязка ссылается на соседей свободно); - обоснование отвечает на «что сломается», а не пересказывает норму; - хвост обоснования не вводит требований, которых нет в блоке нормы; - примеры иллюстрируют норму и не расширяют её: деталь примера не читается как требование. Проверки выше — про запись правила. Граница самой темы (не собрала ли она два решения сразу, нужна ли потребителю целиком) языку не принадлежит: её вопросы стоят в документе, которым набор ведёт себя. ## Версия языка Номер версии называется в каждой конвенции, поэтому он двигается, когда изменение формы способно изменить чтение **уже разданной** копии: копия ссылается на номер, а не на текст, и обязана читаться по той версии, по которой написана. Правки формы до того, как копии разошлись, номер не двигают — читать по ним пока нечего. Смена словаря под другой естественный язык версию не двигает никогда: версия принадлежит шкале, меткам и правилам формы, а не буквам.