Правило, которое проверяет машина, не должно оставаться прозой: файл конвенций на сотни строк размазывает внимание по тривиальному — модель добросовестно проверит именование полей лога и не дойдёт до формы решения. Включены sloglint (константный msg, стиль ключ-значение), forbidigo (fmt.Print*, os.Getenv, time.Now мимо store.Now), errorlint (сравнение ошибок), depguard (сторонние пакеты ошибок). internal/archrules — сканеры на то, что линтером не выражается: направление зависимостей ядро↔транспорты, AUTOINCREMENT и серверное время в новых миграциях, матчинг ошибки по тексту. Код приведён к правилам: logging.StartCall как единая точка отсчёта длительности внешних вызовов, store.Now вместо time.Now в httpapi и часах воркера, slog.DiscardHandler в тестах. Перенесённое вычеркнуто из docs/conventions/* и openspec/config.yaml — прозой осталось только то, что правилом не выражается. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Конвенции кода
Кросс-каттинг правила того, как мы пишем код (логирование, ошибки,
именование) — в отличие от docs/specs/ и openspec/specs/, которые
описывают, что система делает.
Прозой здесь остаётся только то, что не выражается правилом. Как только
свойство удаётся проверить машиной, оно уезжает в .golangci.yml или в
internal/archrules, а формулировка отсюда удаляется (остаётся пометка
«механизировано» со ссылкой на линтер). Процедура — промоут находка →
конвенция → правило → удаление.
Причина: файл на несколько сотен строк размазывает внимание по тривиальному —
и модель, и человек добросовестно проверят именование и не дойдут до формы
решения.
Конвенции не переносятся в OpenSpec: это не capability. Короткие
инварианты дублируются в CLAUDE.md (агент читает его
всегда) и кратко в openspec/config.yaml → context (подмешивается в
генерацию артефактов); детали — здесь. Обоснование «почему» — в docs/adr/.
Записи
- logging.md — логирование: уровни, поля, что не логируем.
- config.md — конфигурация: TOML, секреты через деплой (Ansible+Vault), валидация на старте.
- errors.md — ошибки: stdlib, обёртка
%w,errors.Is/As, трансляция на внешней границе. - database.md — БД и идентификаторы: TEXT ULID PK через
internal/ident(без AUTOINCREMENT), lowercase + нормализация на границах, естественные ключи у деталей. - web-ui.md — веб-UI на htmx: единый партиал = страница = фрагмент,
ветвление
isHTMX, деградация без JS, ошибка = 200 + фрагмент, самозавершающийся поллинг, вендоринг/кэш статики.