Правило, которое проверяет машина, не должно оставаться прозой: файл конвенций на сотни строк размазывает внимание по тривиальному — модель добросовестно проверит именование полей лога и не дойдёт до формы решения. Включены 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>
34 lines
2.6 KiB
Markdown
34 lines
2.6 KiB
Markdown
# Конвенции кода
|
|
|
|
Кросс-каттинг правила того, **как** мы пишем код (логирование, ошибки,
|
|
именование) — в отличие от `docs/specs/` и `openspec/specs/`, которые
|
|
описывают, **что** система делает.
|
|
|
|
**Прозой здесь остаётся только то, что не выражается правилом.** Как только
|
|
свойство удаётся проверить машиной, оно уезжает в `.golangci.yml` или в
|
|
`internal/archrules`, а формулировка отсюда **удаляется** (остаётся пометка
|
|
«механизировано» со ссылкой на линтер). Процедура — [промоут находка →
|
|
конвенция → правило → удаление](../../.claude/skills/review-pipeline/references/promote.md).
|
|
Причина: файл на несколько сотен строк размазывает внимание по тривиальному —
|
|
и модель, и человек добросовестно проверят именование и не дойдут до формы
|
|
решения.
|
|
|
|
Конвенции **не** переносятся в OpenSpec: это не capability. Короткие
|
|
инварианты дублируются в [CLAUDE.md](../../CLAUDE.md) (агент читает его
|
|
всегда) и кратко в `openspec/config.yaml` → `context` (подмешивается в
|
|
генерацию артефактов); детали — здесь. Обоснование «почему» — в `docs/adr/`.
|
|
|
|
## Записи
|
|
|
|
- [logging.md](logging.md) — логирование: уровни, поля, что не логируем.
|
|
- [config.md](config.md) — конфигурация: TOML, секреты через деплой
|
|
(Ansible+Vault), валидация на старте.
|
|
- [errors.md](errors.md) — ошибки: stdlib, обёртка `%w`, `errors.Is`/`As`,
|
|
трансляция на внешней границе.
|
|
- [database.md](database.md) — БД и идентификаторы: TEXT ULID PK через
|
|
`internal/ident` (без AUTOINCREMENT), lowercase + нормализация на границах,
|
|
естественные ключи у деталей.
|
|
- [web-ui.md](web-ui.md) — веб-UI на htmx: единый партиал = страница = фрагмент,
|
|
ветвление `isHTMX`, деградация без JS, ошибка = 200 + фрагмент, самозавершающийся
|
|
поллинг, вендоринг/кэш статики.
|