Files
dev-conventions/TODO.md
T
av 4de6e0f896 черновик «К обсуждению» закоммичен
- одиннадцать открытых вопросов по сборке, тулингу и разделению языка и
  набора конвенций: в переписке они теряются, а часть уже противоречит
  README, и это противоречие видно только рядом с текстом
- снята строка «Не коммитится» и поправлено то же утверждение в CLAUDE.md
2026-07-26 09:06:38 +03:00

19 KiB
Raw Blame History

К обсуждению

Черновик для следующего разговора: вопросы и варианты, а не принятые решения.

1. Ссылка на LANGUAGE.md не переживает сборку

Все двенадцать конвенций во вводной прозе пишут «Форма записи — LANGUAGE.md». Обвязка в репозиторий не едет (conv синхронизирует только conventions/), поэтому в собранной копии эта ссылка указывает в никуда.

Это тот же класс дефекта, который вчера закрыло META-21 для ссылок между темами: путь, верный в каноне, молча умирает при сборке. Разница в том, что META-21 предлагает заменить путь на имя темы — а здесь заменять не на что, целевого документа в репозитории просто нет.

Варианты, которые видно сейчас:

  • Убрать упоминание из тел конвенций. Язык записи — забота того, кто пишет канон, а не того, кто читает конвенцию в своём репозитории. Читателю достаточно самого текста: модальные слова и «Почему» самоописательны. Дешевле всего, но копия теряет указание, по каким правилам её править.
  • Возить обвязку вместе с конвенциями. Тогда LANGUAGE.md и, возможно, GUIDE.md появляются в docs/conventions/ как ещё одни синхронизируемые файлы. Честно, но противоречит нынешнему разделению «канон — конвенции, корень — обвязка» и добавляет в репозиторий текст, который агенту при чтении конвенции не нужен.
  • Вкладывать короткую преамбулу в собранный файл. Сборщик пишет в шапку три-четыре строки: что такое модальное слово, что «Почему» обязательно, где лежит полный документ. Самодостаточно и не тащит весь язык, но преамбула дублируется в каждом файле темы.

Сопутствующее: GUIDE.md в телах конвенций не упоминается ни разу — проверено, так что вопрос только про LANGUAGE.md.

2. Тулинг: две разные задачи в одном conv

Сейчас в conv смешаны две категории работы, и они расходятся по всему — по частоте запуска, по тому, кто запускает, и по тому, что считается провалом.

Целостность канона. Префиксы уникальны и не переиспользованы, шапка совпадает с реестром, номера без дыр вниз, у каждого правила модальность и «Почему», ссылки разрешаются, чужой префикс не лезет в норму (META-20), путей канона в тексте нет (META-21). Запускается в каноне, при каждой правке, провал — это ошибка. Логика уже написана и много раз прогнана руками, но живёт в скретчпаде, а не в репозитории.

Установка в проект. Манифест .conventions.toml, сборка файла темы из секций (arch → языки → стеки → local), сохранение локальной секции при пересборке, отчёт «канон ушёл вперёд», предупреждение о висячих ссылках на неподписанные темы. Запускается в репозитории-потребителе, изредка, провал — это чаще «посмотри глазами», чем «ошибка».

Что обсудить:

  • Разделять ли на два исполняемых файла, или хватит подкоманд с честной границей внутри.
  • Валидацию канона стоит ли отдать агенту скиллом вместо (или вдобавок к) скрипту: часть проверок формулируется как «прочитай и скажи, самодостаточна ли норма» — механически это не берётся, а агентом берётся.
  • Куда в этой раскладке ложится запаркованное предупреждение о висячих ссылках: это установка, а не целостность, но список подписок ему нужен из манифеста.

3. Согласованная модель сборки нигде не записана

Самое срочное. Договорённости про плоскую раскладку живут только в переписке, а репозиторий описывает прежнюю модель — и противоречит новой в нескольких местах сразу.

Что решено, но не зафиксировано:

  • копия плоская, файл на тему: docs/conventions/config.md, а не дерево arch/ + lang/;
  • файл темы собирается из секций arch → языки → стеки → local с машиночитаемыми маркерами <!-- conv:section … --> и <!-- conv:local -->;
  • языки и стеки образуют разреженную матрицу; файл темы собирает её строку, многоязычная тема держит несколько языковых секций в одном файле;
  • выбор описывается манифестом .conventions.toml в корне репозитория-потребителя; путь к канону там не хранится;
  • направление строго одностороннее: канон → код. Правка канона делается руками в каноне, потом пересборка;
  • локальные префиксы правил репозитория объявляются в манифесте и не пересекаются с реестром канона.

Что этому прямо противоречит в репозитории сейчас:

  • README.md → «Раскладка в репозитории» показывает зеркальное дерево docs/conventions/arch/db-identifiers.md;
  • README.md → «Команды» и «Контракт с агентом» описывают conv push и conv push --new как штатный путь; при односторонней модели транспорт назад исчезает, остаётся только детект «копия правлена вне локальной секции»;
  • conv содержит cmd_push со всей обвязкой (--new, --force).

4. Именованные регионы → одна локальная секция

Решено заменить регионы <!-- local:имя --> на одну локальную секцию в конце собранного файла: отступление ссылается на идентификатор правила (DIRS-5), а не стоит рядом с ним. Это то, что делает сравнение копии с каноном одним хешем и выкидывает из conv перенос регионов по именам.

Сделать перенос ещё предстоит: в каноне сейчас 31 регион в 12 файлах.

7  связано        7  отступления     7  механизировано
1  эталон / эталоны / словарь / секреты / секретные-поля
1  проверки / поля / модель-владельца / маппинг / границы

Отдельно решить, что делать с связано: сейчас это репо-специфичная часть раздела «Связано» (META-17), и при единой локальной секции она переезжает туда же — надо проверить, что META-17 после этого не противоречит сам себе.

5. Пары слоёв и темы без базы

Отложено сознательно, но список стоит держать перед глазами:

  • SLOG объявляет extends: arch/time.md — расширение чужой темы. Сборщик темы logging на это наткнётся: базового слоя с темой logging нет, а arch/time.md он тянуть не должен. Чинится переводом в обычную ссылку «связано».
  • Темы без арх-слоя: db-schema, errors, web-ui. Собираются в файл с одной секцией — само по себе не ломается, но это и есть тот невыделенный арх-слой из известного долга.
  • Имена тем в паре не совпадают: arch/db-identifiers.md против lang/go/db-schema.md. При сборке по имени темы это две разные темы — проверить, что так и задумано.
  • В lang/go/db-schema.md сидит целый пласт stack/sqlite/ (типы колонок), тоже из известного долга README.

6. Подключение к репозиториям

Ничего ещё не подключено. Кандидаты — jellybit и pet-project-server. Понадобится: заполнить локальные секции тем, что сейчас в этих репозиториях записано по факту; обёртка в раннере (inv conventions / task conventions, единый интерфейс команд у трёх ansible-репозиториев); строка в AGENTS.md каждого потребителя про то, что файлы в docs/conventions/ — копии.

Открытый кусок с прошлого раза: как копия ссылается на канон, не ломая самодостаточность. Абсолютный путь ~/projects/private/dev-conventions в закоммиченном файле не годится — репозиторий перестаёт быть самодостаточным и получает хардкод путей. Пересекается с вопросом 1.

7. Не переизобретено ли это

Проверить перед тем, как вкладываться в тулинг. Ближайшие кандидаты, куда смотреть:

  • copier / cruft — шаблон проекта с последующим update: ровно та же задача «стянуть обновление апстрима, не затерев локальные правки», с ответом через три-way merge вместо наших регионов. Стоит понять, почему у них merge, а у нас исключение из сравнения.
  • vendir — вендоринг чужого содержимого с лок-файлом; ближе к нашей модели «канон это лавка».
  • Vale — линтер прозы с правилами в файлах: значительная часть проверок целостности канона (модальные слова вне правил, запрещённые формулировки) выражается его языком.
  • RFC 2119 / 8174 — канонический источник модальных слов; наш словарь фактически его перевод, полезно сверить границы значений.
  • EARS — шаблоны требований (ubiquitous / event-driven / state-driven); соседняя формализация того же, что мы решили таблицами.
  • Наборы правил для агентовAGENTS.md, cursor rules, скиллы: задачу «раздать читаемые агентом договорённости по репозиториям» сейчас решают несколько продуктов, и там уже могли устояться форматы.

8. Мультиязычность ключевых слов

Модальные слова сейчас русские, и это осознанно: разный словарь держит границу «конвенция — не спецификация» бесплатно. Вопрос — нужен ли английский набор параллельно.

За: канон может однажды понадобиться на английском; агенты натренированы на MUST/SHOULD плотнее, чем на ДОЛЖЕН/СЛЕДУЕТ. Против: два набора — это два способа записать одно, и проверка «модальные слова не встречаются вне правил» усложняется вдвое.

Если делать, то таблица ключевых слов должна принадлежать описанию языка, а не каждой конвенции — то есть вопрос завязан на следующий.

9. Описание языка отдельно от набора конвенций

LANGUAGE.md и GUIDE.md описывают, как пишутся конвенции; conventions/один конкретный набор. Сейчас они склеены в одном репозитории, и из одного описания нельзя собрать второй набор (рабочий, доменный, чужой).

Что это даёт, если разнести:

  • канон объявляет, какой версии языка следует, а тулинг валидирует набор против объявленного описания, а не против зашитых в код правил;
  • таблица модальных слов (вопрос 8) живёт в описании и одна на все наборы;
  • вопрос 1 (LANGUAGE.md не переживает сборку) меняет форму: собранный файл ссылается не на путь, а на язык с версией.

Цена — ещё одна сущность и ещё одна синхронизация. Проверить, не выйдет ли лечение хуже болезни при одном пользователе.

10. Тулинг на Go, живущий независимо

Сейчас conv — питоновский скрипт внутри канона, то есть тулинг и данные в одном репозитории и правятся одним движением. Мысль: вынести в отдельный Go-бинарь со своим релизным циклом, ставить через eget (механизм уже есть в pet-project-server).

Что за этим стоит помимо вкуса: независимый бинарь физически не даёт править инструмент «заодно» с правкой конвенции, работает против любого канона и любого потребителя — что прямо требуется вопросом 9, — и снимает питон из зависимостей репозиториев-потребителей.

Связано с вопросом 2: если тулинг всё равно переписывается, разделение «целостность канона / установка в проект» дешевле заложить сразу, чем отпиливать потом.

11. Ссылки на родительский слой своей темы

Из lang/ и stack/ ссылаться на идентификаторы своего же арх-слоя безопасно: при сборке они оказываются секциями одного файла, и ссылка никуда не ведёт — правило рядом. Ограничение META-20 писалось именно про чужую тему, так что формально это уже разрешено.

Но стоит проговорить явно, потому что сейчас читается уже как запрет:

  • в LANGUAGE.md проверка сформулирована как «чужой префикс не встречается в абзаце с модальностью» — по букве это ловит и GTIMTIME-3, то есть ложно срабатывает на ровно том случае, который разрешён. Должно быть «префикс чужой темы»;
  • обсудить, не добавить ли в META-20 явную строку ДОПУСКАЕТСЯ про родительский слой: правило, которое читают как более строгое, чем оно есть, заставляет авторов дублировать текст без нужды.

Из вчерашнего, не закрыто

  • Вынос арх-ядра из errors и logging: закроет две хрупкие ссылки из web-ui (стек) в go-слой — единственные ссылки стек → язык в каноне.
  • conv check должен уметь отличать ссылку на удалённое правило от упоминания дыры: сейчас META-16 в прозе «Оформления» даёт ложное срабатывание.