конвенции: перенести механизируемое в golangci-lint и internal/archrules

Правило, которое проверяет машина, не должно оставаться прозой: файл конвенций
на сотни строк размазывает внимание по тривиальному — модель добросовестно
проверит именование полей лога и не дойдёт до формы решения.

Включены 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>
This commit is contained in:
av
2026-07-23 18:17:40 +03:00
co-authored by Claude Opus 4.8
parent 6792f7082a
commit 612344bab3
28 changed files with 325 additions and 98 deletions
+5 -6
View File
@@ -5,11 +5,13 @@
раздел «Ошибки» (коротко: лог один раз на доменной границе). Здесь — как
ошибки строятся, оборачиваются и проверяются.
**Механизировано:** сторонние пакеты ошибок — `depguard`; `err == ErrX` и
приведение типа — `errorlint`; матчинг по тексту сообщения — `internal/archrules`.
## Базовая идиома: stdlib
- Только стандартный `errors` + `fmt.Errorf`. Без `pkg/errors` (в режиме
поддержки) и `cockroachdb/errors` (стек-трейсы/Sentry избыточно для
домашнего сервиса). Контекст ошибки несёт `slog`, а не стек.
- Только стандартный `errors` + `fmt.Errorf`: контекст ошибки несёт `slog`, а не
стек — стек-трейсы и Sentry избыточны для домашнего сервиса.
- Если отладка начнёт упираться в «где именно родилась ошибка» — это сигнал
пересмотреть, а не дефолт.
@@ -36,9 +38,6 @@ jellybit — **приложение, а не библиотека**: внешн
## Проверка ошибок
- Сравнение — только `errors.Is(err, ErrX)` (не `err == ErrX`) и
`errors.As(err, &target)`. **Никогда** не матчим по тексту
(`strings.Contains(err.Error(), …)`).
- Граничные ошибки зависимостей **транслируем в доменные у источника**:
`sql.ErrNoRows` → доменный `store.ErrNotFound` в слое store, чтобы выше по
коду не торчал `database/sql`.