- 13 конвенций по осям arch / lang / stack / common; репозитории берут оттуда копии в свой docs/conventions/ и коммитят их у себя - conv — синхронизация копий: add / status / diff / pull / push, локальные регионы исключены из сравнения, поэтому расхождение не даёт шума
9.9 KiB
status
| status |
|---|
| обязательная |
Как мы ведём конвенции
Конвенция описывает повторяющийся выбор: как называть директории, как раскладывать данные, как оформлять ошибки. Она отвечает на вопрос «как принято», а не «что здесь происходит». Одна конвенция — один файл.
Механической проверки у самой этой конвенции нет — осознанное исключение: проверять «правильно ли написана конвенция» нечем, а обязательный статус нужен, чтобы правила ниже не обсуждались заново в каждом репозитории.
Канон и копии
Файлы в этой директории с шапкой origin: — копии из общего канона
dev-conventions, а не собственные документы репозитория. Отсюда:
- репозиторное пишется только внутрь локальных регионов
<!-- local:имя --> … <!-- /local -->: они исключены из сравнения с каноном, и расхождение по ним — норма, а не дрейф; - правка вне регионов означает одно из двух: улучшение, которое надо
вернуть в канон, или сознательное расхождение, записанное в ключ
local:шапки; - состояние копий показывает
conv status, различия —conv diff, обновление из канона —conv pull; всё через раннер репозитория.
Имя региона обязательно и стабильно: перенос содержимого при обновлении идёт по именам.
Отличие от соседей
docs/adr/— решение, принятое однажды и постфактум («почему выбрали Authelia, а не Keycloak»). Запись неизменяема.docs/specs/и OpenSpec, где они есть, — что система делает, наблюдаемое поведение как контракт. Конвенция — как написан код; в спеки она не переносится, это не capability.docs/drafts/— оперативная хроника и черновики, «что собираюсь сделать».docs/conventions/— правило на будущее, применяемое многократно. Живой документ: правится, когда договорённость меняется.
Направление: конвенция → код
Конвенция формулируется независимо от того, как устроено конкретное приложение. Код следует конвенции, а не наоборот.
Если код расходится с правилом — это отступление, и оно записывается в локальный регион, а не переписывает правило. Правило меняется только тогда, когда оно неверно по существу: содержит фактическую ошибку, внутреннее противоречие или условие применимости, которое не даёт ответа.
Практическое следствие: в тексте конвенции не должно быть утверждений о текущем состоянии репозитория. «Так сделано у нас» — это регион отступлений; норма пишется в настоящем предписывающем времени.
Статус
Каждая конвенция объявляет статус в шапке:
- рекомендуемая — так стоит делать в новом коде; существующий переезжает по мере касания, отдельной кампанией не переписывается;
- обязательная — нарушение считается ошибкой; по возможности проверяется линтером или хуком, а не вниманием.
Конвенция без механической проверки держится только на внимании — это нормально для рекомендуемой и плохо для обязательной.
Когда заводить
Когда одно и то же решение принимается третий раз и каждый раз чуть по-другому. Единичный выбор — не конвенция; если он ещё и был спорным, ему место в ADR.
Путь находки: находка → конвенция → правило линтера → удаление прозы. Первые два шага делаются в репозитории, где заболело; общая часть продвигается в канон.
Прозой — только то, что не выражается правилом
Как только свойство удаётся проверить машиной, его формулировка перестаёт работать: файл на несколько сотен строк размазывает внимание по тривиальному, и человек с агентом добросовестно проверят именование, не дойдя до формы решения.
Но удаление прозы в общем каноне устроено иначе, чем в одиночном репозитории. Механизация — состояние конкретного репозитория:
- из канона формулировка не удаляется, пока правило не механизировано у всех потребителей: иначе те, у кого линтера нет, останутся без правила;
- факт механизации фиксируется в локальном регионе
механизировано— со ссылкой на конкретное правило; - когда механизация стала общей (правило уехало в общий конфиг линтера или
в общую роль), формулировка удаляется из канона одним
push.
Трудноизменяемые слои
У схемы БД, формата хранения и раскладки директорий шкала «рекомендуемая → переезжает по мере касания» не работает: таблица не переезжает от того, что её потрогали. Для таких конвенций:
- область действия пишется явно — «применяется к новым таблицам и миграциям», а не к состоянию схемы;
- механизируется граница изменения, а не состояние — линтер запрещает
AUTOINCREMENTв новых миграциях, а не в существующей схеме: старое не падает, новая ошибка невозможна; - список отступлений постоянный, а не список задач на дочистку.
Честный список отступлений
В локальном регионе перечисляем отступления, которые уже есть в коде, — иначе репозиторий делает вид, что правилу следует. У рекомендуемой конвенции пустой список отступлений почти всегда означает, что их просто не искали.
Отступление — это «правилу не следуем здесь и вот почему». Если регион разросся до «мы это правило вообще не применяем», значит либо у правила неверно сформулировано условие применимости (чинить в каноне), либо репозиторию не нужна эта конвенция (не подписываться).
Оформление
- Имя файла — kebab-case по теме:
app-directories.md. - Раздел «Связано» в конце: ADR с обоснованием, спеки, код, который эту конвенцию механизирует. Репо-специфичная часть «Связано» — в локальном регионе, канонические ссылки — в общем тексте.
- README директории перечисляет конвенции с однострочным описанием, чтобы список читался без открывания файлов.
- Короткие инварианты дублируются туда, что агент читает безусловно
(
AGENTS.md/CLAUDE.md): сама по себе конвенция агенту не видна, он дойдёт до неё, только если его туда отправили. Детали остаются здесь, в файл-точку-входа едет одна строка на правило.