diff --git a/CLAUDE.md b/CLAUDE.md index f91c313..88fc4e7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,8 +28,8 @@ code in this repository. - Нормативно только заглавное написание (правило RFC 8174): строчное «должен» в прозе нормой не является. - ДОЛЖЕН требует двух условий сразу: назван вред от нарушения (META-25) и - норма проверяема машиной (META-6). Проверяемость сама по себе до ДОЛЖЕН не - повышает — иначе шкала наполняется проверяемыми мелочами. + вердикт о нарушении воспроизводим (META-6). Воспроизводимость сама по себе + до ДОЛЖЕН не повышает — иначе шкала наполняется проверяемыми мелочами. - ДОПУСКАЕТСЯ адресовано рецензенту: помеченный им выбор на ревью не обсуждается. - **МЕХАНИЗИРОВАНО** — не модальность, а способ проверки: отметка стоит @@ -93,9 +93,11 @@ code in this repository. - META-5: расхождение кода с правилом — отступление, а не повод переписать правило. Направление всегда конвенция → код; факт «в приложении уже иначе» не является аргументом. -- META-6: ДОЛЖЕН без механической проверки либо механизируется, либо - понижается в СЛЕДУЕТ. Правило, непроверяемое машиной в принципе (вкус - формулировки, суждение о ситуации), — СЛЕДУЕТ по построению. +- META-6: ДОЛЖЕН требует воспроизводимого вердикта — двое проверяющих по + тексту правила отвечают одинаково. Правило, вердикт которого зависит от + суждения (вкус формулировки, уместность в конкретном месте), — СЛЕДУЕТ по + построению. META-27: машинная проверка желательна, но ступени не задаёт; + проверяющий по умолчанию — читатель правила, человек или агент. - META-10: блок ПОЧЕМУ не удаляется никогда, в том числе после того, как норма уехала в линтер. - META-1: один файл — ровно один повторяющийся выбор. META-2: конвенция diff --git a/GUIDE.md b/GUIDE.md index 1b8d2a1..036fd1c 100644 --- a/GUIDE.md +++ b/GUIDE.md @@ -157,33 +157,51 @@ prefix: META переписывает его снова. Направление «конвенция → код» держится ровно тем, что факт не считается аргументом. -### META-6. `ДОЛЖЕН` без механической проверки либо механизируется, либо понижается +### META-6. Высшая модальность требует воспроизводимого вердикта -**ДОЛЖЕН.** Правило, нарушение которого объявлено ошибкой, получает -машинную проверку или переводится в СЛЕДУЕТ. +**ДОЛЖЕН.** Правило со ступенью ДОЛЖЕН или НЕ ДОЛЖЕН формулируется так, что +двое проверяющих по одному его тексту выносят один и тот же вердикт. -**ПОЧЕМУ.** Без проверки правило держится на внимании: нарушения копятся -молча и всплывают выборочно — на том ревью, куда дошли руки. Для СЛЕДУЕТ -это честно, а ДОЛЖЕН при этом обещает то, чего не делает, и через несколько -таких случаев обесценивает остальные ДОЛЖЕН в файле. +**ПОЧЕМУ.** Проверяют конвенцию в первую очередь агент и человек — они читают +текст правила и по нему смотрят код. Проверка, стало быть, есть у каждого +правила с первого дня, и её инструмент — формулировка, а не скрипт. Отсюда +цена невоспроизводимой нормы: вердикт зависит от того, кто читал, нарушения +всплывают выборочно, а отступление нечем записать — неизвестно, нарушено ли. +Для СЛЕДУЕТ это честно, там суждение и есть содержание правила; ДОЛЖЕН в +таком виде обещает то, чего не делает, и через несколько случаев обесценивает +остальные ДОЛЖЕН в файле. -Отсюда следствие: правило, машинная проверка которого невозможна в принципе -(вкус формулировки, выбор границы, суждение о ситуации), не может быть -ДОЛЖЕН — его модальность СЛЕДУЕТ по построению, а не по слабости. +Отсюда следствие: правило, вердикт которого зависит от суждения по построению +(вкус формулировки, выбор границы, уместность в конкретном месте), не может +быть ДОЛЖЕН — его модальность СЛЕДУЕТ по природе нормы, а не по слабости. ### META-25. Высшая модальность выбирается, только когда назван вред **СЛЕДУЕТ.** Правило получает ДОЛЖЕН или НЕ ДОЛЖЕН, если в обосновании сказано, что́ ломается при нарушении. -**ПОЧЕМУ.** Машинная проверка — условие необходимое (META-6), но не -достаточное: проверяемых мелочей больше, чем важных вещей, и без второго -условия единственным фильтром остаётся удобство проверки. Шкала наполняется -опрятностью, читатель перестаёт отличать «уронит прод» от «неаккуратно» — и -обесцениваются все ДОЛЖЕН в файле, ровно то, от чего META-6 защищает с -другой стороны. Само это правило машиной не проверяется: «вред назван» -устанавливается чтением, поэтому его собственная модальность по META-6 — -СЛЕДУЕТ. +**ПОЧЕМУ.** Воспроизводимость вердикта — условие необходимое (META-6), но не +достаточное: воспроизводимо проверяемых мелочей больше, чем важных вещей, и +без второго условия единственным фильтром остаётся удобство проверки. Шкала +наполняется опрятностью, читатель перестаёт отличать «уронит прод» от +«неаккуратно» — и обесцениваются все ДОЛЖЕН в файле, ровно то, от чего META-6 +защищает с другой стороны. Собственная ступень этого правила — СЛЕДУЕТ: +форма обоснования ничем не ограничена, поэтому «вред назван» вердикта не +даёт — один читатель увидит названный вред там, где другой увидит объяснение +мотива. + +### META-27. Механизация правила желательна, но ступени не задаёт + +**СЛЕДУЕТ.** Правило со ступенью ДОЛЖЕН получает машинную проверку, когда +такую проверку можно написать. + +**ПОЧЕМУ.** Линтер не забывает, ничего не стоит на каждом прогоне и краснеет +до ревью, а не на нём: там, где проверка пишется, она дешевле самого +внимательного чтения, и путь «находка → конвенция → проверка → удаление +прозы» кончается ею (META-9). Условием ступени она при этом не является: +проверяющий по умолчанию — читатель правила (META-6), а если требовать +скрипт, весь канон стоит в СЛЕДУЕТ до того дня, когда скрипты появятся. +Ступень говорит о важности нормы, а не о состоянии инструментов. ### META-7. Факт механизации фиксируется в копии со ссылкой на правило diff --git a/LANGUAGE.md b/LANGUAGE.md index afd9c96..1b36c1c 100644 --- a/LANGUAGE.md +++ b/LANGUAGE.md @@ -162,13 +162,14 @@ Directives, Part 2, по одной форме записи на ступень, 1. нарушение причиняет названный вред, а не расходится со вкусом — META-25, он же критерий BCP 14, где высшая модальность резервируется под то, что действительно ломается, и не употребляется для навязывания метода; -2. норма проверяема машиной — META-6, иначе обязательность держится на - внимании и обещает то, чего не делает. +2. вердикт о нарушении воспроизводим — META-6: по тексту правила двое + проверяющих приходят к одному ответу, иначе обязательность держится на + том, кто читал. Не выполнено первое — правилу место в СЛЕДУЕТ или нигде. Не выполнено -второе — в СЛЕДУЕТ. Проверяемость сама по себе не повышает правило до -ДОЛЖЕН: механически проверяемых мелочей больше, чем важных вещей, и -безразборное повышение обесценивает шкалу быстрее, чем её отсутствие. +второе — в СЛЕДУЕТ. Воспроизводимость сама по себе не повышает правило до +ДОЛЖЕН: проверяемых мелочей больше, чем важных вещей, и безразборное +повышение обесценивает шкалу быстрее, чем её отсутствие. Модальность живёт на **правиле**, а не на файле. Файловый статус (`status: рекомендуемая` / `обязательная` в шапке) не используется: он @@ -249,6 +250,19 @@ Directives, Part 2, по одной форме записи на ступень, правило обязательно, а о том, чем эта обязательность обеспечена. В 29148 это два разных атрибута требования, и здесь тоже два. +**Проверяющий по умолчанию — читатель правила**, человек или агент. Канон +пишется прежде всего под агента: он читает конвенцию и по ней смотрит код, +то есть проверка есть у каждого правила с первого дня, и её инструмент — +формулировка нормы. Поэтому вторым условием ДОЛЖЕН стоит воспроизводимость +вердикта (META-6), а не наличие скрипта: ступень говорит о важности нормы и о +том, сколько внимания она получает при проверке, а не о состоянии +инструментов. Линтер сильнее чтения — он не забывает, ничего не стоит на +каждом прогоне и краснеет до ревью, — поэтому механизация желательна везде, +где проверка пишется (META-27), и остаётся концом пути «находка → конвенция → +проверка → удаление прозы». Но обязательным условием высшей ступени она не +является: иначе весь канон стоял бы в СЛЕДУЕТ до появления скриптов, которых +пока нет ни одного. + Когда правило механизировано у всех потребителей, его норма из канона удаляется, а модальность и обоснование остаются: diff --git a/TODO.md b/TODO.md index a1de3a0..c2b296e 100644 --- a/TODO.md +++ b/TODO.md @@ -4,38 +4,12 @@ решения. Закрытый вопрос отсюда удаляется — принятое решение живёт в `README.md`, `GUIDE.md` или `LANGUAGE.md`, а не в этом файле. -Две секции: сначала язык и подход, потом канон с тулингом. Пункты 1–9 +Две секции: сначала язык и подход, потом канон с тулингом. Пункты 1–8 пришли из внешнего ревью описания языка и проверены по файлам на месте. # Язык и подход -## 1. Два определения второго условия ДОЛЖЕН, и META-6 не соблюдается - -Противоречие двойное, и это самое серьёзное из найденного. - -**Расхождение формулировок.** `LANGUAGE.md` требует, чтобы норма была -«проверяема машиной» — то есть проверяема в принципе. META-6 требует, чтобы -она «получала машинную проверку» — то есть фактически. Ни одной проверки не -реализовано, поэтому по первому чтению канон в порядке, по второму — весь в -нарушении. Автору нового правила нечем ответить на вопрос «можно ли ДОЛЖЕН -до того, как написан линтер, и как долго». - -**Следствие META-6 массово не соблюдается.** «Правило, непроверяемое машиной -в принципе, — СЛЕДУЕТ по построению», а ДОЛЖЕН стоит у META-1 («ровно один -повторяющийся выбор» — суждение), META-5 («неверно по существу» — суждение), -META-13, META-15, SLOG-8 («уровень выбирается по адресату»), CONF-9 -(«комментарий, из которого ясно»). META-25 при этом демонстративно понижает -**себя** до СЛЕДУЕТ по этой же логике: критерий известен и применяется -выборочно. - -Развилка: либо следствие META-6 слишком сильное и его надо ослабить явно — -например, различив «проверяемо машиной» и «проверяемо воспроизводимо, в том -числе чтением», — либо половина ДОЛЖЕН канона стоит не на своей ступени. -Пока непонятно, что из двух, невозможно ни писать новые правила, ни -реализовать проверку META-6: она либо промолчит всегда, либо покраснеет на -всём каноне, и её отключат — ровно сценарий из обоснования META-12. - -## 2. Граница правила не определена +## 1. Граница правила не определена Форма объявляет четыре части, но почти каждое крупное правило несёт абзацы **после** блока ПОЧЕМУ: KEYS-5, SLOG-25, MIGR-11, GERR-26. Язык не говорит, @@ -55,7 +29,7 @@ META-13, META-15, SLOG-8 («уровень выбирается по адрес Решить надо две вещи: где кончается правило и что делать с нормами, которые уже сидят в хвостах. -## 3. Примеры в LANGUAGE.md сидят на живых идентификаторах +## 2. Примеры в LANGUAGE.md сидят на живых идентификаторах Учебные примеры используют настоящие префиксы канона с номерами, которые в каноне означают другое: @@ -74,7 +48,7 @@ META-13, META-15, SLOG-8 («уровень выбирается по адрес Лечится дёшево: примеры берут префиксы на `X`, зарезервированные как раз под то, что каноном не занято. -## 4. «Тема» — несущий идентификатор без определения и реестра +## 3. «Тема» — несущий идентификатор без определения и реестра META-21 велит ссылаться на соседнюю конвенцию именем темы, манифест подписывается `topics = ["time", …]`, сборка собирает файл темы из слоёв — @@ -87,13 +61,13 @@ META-21 велит ссылаться на соседнюю конвенцию файла темы тихо осиротит все текстовые ссылки во всех копиях. Вопрос уже не гипотетический: пара `arch/db-identifiers.md` против -`lang/go/db-schema.md` (см. вопрос 13) показывает, что имена слоёв одной +`lang/go/db-schema.md` (см. вопрос 12) показывает, что имена слоёв одной темы могут не совпадать. Смежно: `extends: arch/time.md` у SLOG ломает гарантию META-24 («базовый слой отсутствовать не может») — она верна только для базы своей темы, а машинной проверке негде узнать тему, кроме имени файла. -## 5. GUIDE выведен из-под проверок ложным основанием +## 4. GUIDE выведен из-под проверок ложным основанием `LANGUAGE.md` исключает обвязку из проверок формулировкой «она ключевые слова цитирует, а не употребляет». Для `GUIDE.md` это неверно: META-правила @@ -109,7 +83,7 @@ META-21 велит ссылаться на соседнюю конвенцию Честнее развести: `GUIDE.md` язык **употребляет** и проверяется как конвенция, `LANGUAGE.md` и `README.md` — цитируют. -## 6. МЕХАНИЗИРОВАНО не переживает нового подписчика +## 5. МЕХАНИЗИРОВАНО не переживает нового подписчика META-8 запрещает удалять норму, пока механизирована не у всех, и защищает тем самым потребителей, существующих **на момент удаления**. Будущих не @@ -127,7 +101,7 @@ META-8 запрещает удалять норму, пока механизир в тексте канона, то есть ровно то, что запрещает META-4. Либо это законное исключение, и тогда его надо назвать, либо конфликт. -## 7. Семантика ключевых слов в копию не едет +## 6. Семантика ключевых слов в копию не едет Строка о версии языка перечисляет слова, но не их значения, а всё нетривиальное в шкале живёт только в `LANGUAGE.md`, который в репозиторий не @@ -143,7 +117,7 @@ META-8 запрещает удалять норму, пока механизир копиями короткую выжимку семантики; расширить строку о версии до двух-трёх предложений; или признать ограничение и записать его явно. -## 8. Две «механические» проверки без источника данных +## 7. Две «механические» проверки без источника данных В списке «разбором текста» стоят два пункта, которые без дополнительного реестра нерешаемы: @@ -159,7 +133,7 @@ META-8 запрещает удалять норму, пока механизир реестр снятых номеров не объявлен частью языка, оба пункта принадлежат списку «чтением». -## 9. Натяжки в опоре на стандарты +## 8. Натяжки в опоре на стандарты Три места, где источнику приписано чуть больше, чем в нём есть: @@ -178,7 +152,7 @@ META-8 запрещает удалять норму, пока механизир Остальное в таблице проверку выдержало, включая вторую половину `MAY` из BCP 14 и списки эквивалентных словесных форм ISO Directives. -## 10. Одиннадцать таблиц не прочитаны на взаимоисключительность +## 9. Одиннадцать таблиц не прочитаны на взаимоисключительность `LANGUAGE.md` объявил, что строки таблицы решений взаимоисключающи по умолчанию, а иной порядок объявляется явно. Объявление не делает таблицы @@ -193,7 +167,7 @@ BCP 14 и списки эквивалентных словесных форм IS Работа читательская, машине не даётся; в список проверок она уже записана в разделе «Чтением, потому что машине не даётся». -## 11. Описание языка отдельно от набора конвенций +## 10. Описание языка отдельно от набора конвенций `LANGUAGE.md` и `GUIDE.md` описывают, **как** пишутся конвенции; `conventions/` — **один конкретный** набор. Сейчас они склеены в одном @@ -216,7 +190,7 @@ BCP 14 и списки эквивалентных словесных форм IS # Канон, тулинг, подключение -## 12. Тулинг: две разные задачи в одном `conv` +## 11. Тулинг: две разные задачи в одном `conv` Сейчас в `conv` смешаны две категории работы, и они расходятся по всему — по частоте запуска, по тому, кто запускает, и по тому, что считается @@ -247,22 +221,22 @@ BCP 14 и списки эквивалентных словесных форм IS ссылках: это установка, а не целостность, но список подписок ему нужен из манифеста. -Часть проверок из этого списка сейчас нереализуема по причинам из вопросов 2 -и 8, так что порядок такой: сначала язык, потом чекер. +Часть проверок из этого списка сейчас нереализуема по причинам из вопросов 1 +и 7, так что порядок такой: сначала язык, потом чекер. Перед тем как переписывать, стоит посмотреть на два готовых прототипа: дистрибуцию пакетов Vale (`.vale.ini` → `vale sync` → `styles/`) как образец манифеста и `vendir.yml` — как пример того, где проходит граница между «чего хочу» и «что получил». -## 13. Пары слоёв и темы без базы +## 12. Пары слоёв и темы без базы Отложено сознательно, но список стоит держать перед глазами: - `SLOG` объявляет `extends: arch/time.md` — расширение **чужой** темы. Сборщик темы `logging` на это наткнётся: базового слоя с темой `logging` нет, а `arch/time.md` он тянуть не должен. Чинится переводом в обычную - ссылку «связано». Вдобавок это ломает гарантию META-24 — см. вопрос 4. + ссылку «связано». Вдобавок это ломает гарантию META-24 — см. вопрос 3. - Темы без арх-слоя: `db-schema`, `errors`, `web-ui`. Собираются в файл с одной секцией — само по себе не ломается, но это и есть тот невыделенный арх-слой из известного долга. @@ -274,7 +248,7 @@ BCP 14 и списки эквивалентных словесных форм IS - Вынос арх-ядра из `errors` и `logging` закроет две хрупкие ссылки из `web-ui` (стек) в go-слой — единственные ссылки стек → язык в каноне. -## 14. Подключение к репозиториям +## 13. Подключение к репозиториям Ничего ещё не подключено. Кандидаты — jellybit и pet-project-server. Понадобится: заполнить локальную часть копий тем, что сейчас в этих @@ -283,7 +257,7 @@ BCP 14 и списки эквивалентных словесных форм IS строка в `AGENTS.md` каждого потребителя про то, что файлы в `docs/conventions/` — копии. -## 15. Тулинг на Go, живущий независимо +## 14. Тулинг на Go, живущий независимо Сейчас `conv` — питоновский скрипт внутри канона, то есть тулинг и данные в одном репозитории и правятся одним движением. Мысль: вынести в отдельный @@ -292,10 +266,10 @@ Go-бинарь со своим релизным циклом, ставить ч Что за этим стоит помимо вкуса: независимый бинарь физически не даёт править инструмент «заодно» с правкой конвенции, работает против **любого** канона и -любого потребителя — что прямо требуется вопросом 11, — и снимает питон из +любого потребителя — что прямо требуется вопросом 10, — и снимает питон из зависимостей репозиториев-потребителей. -Порядок обратный ожидаемому: пока вопрос 11 не сделан, инструмент всё равно +Порядок обратный ожидаемому: пока вопрос 10 не сделан, инструмент всё равно работает против одного конкретного канона, и независимый релизный цикл ему -нечего обслуживать. Сначала 11, потом 15. Разделение из вопроса 12 при этом +нечего обслуживать. Сначала 10, потом 14. Разделение из вопроса 11 при этом дешевле заложить сразу, чем отпиливать потом.