Files
jellybit/docs/conventions
av 66d39297c5 docs: проект переведён на канон документов версии 4
- каталог задач: PLAN.md → ROADMAP.md с каноническими секциями, все 44
  записи получили тип, заголовки приведены к форме своего типа
- расхождения, найденные судьями канона: исключения инварианта «источник
  неприкосновенен», инвариант про один активный infohash, UTC в logging.md,
  поведение из architecture.md заменено ссылками на спеки
- триггеры профиля ревью переписаны под умолчание standard
2026-08-06 13:32:06 +03:00
..

Конвенции кода

Как мы пишем код — в отличие от openspec/specs/, который описывает, что система делает, и от ../architecture.md, который описывает, как она сложена.

Прозой остаётся только то, что не выражается правилом. Свойство, ставшее правилом линтера или тестом-сканером, отсюда удаляется и переезжает в перечень «Механизировано» ниже. Причина: файл на несколько сотен строк размазывает внимание по тривиальному — и модель, и человек добросовестно проверят именование и не дойдут до формы решения. Процедура промоута — references/promote.md скилла av-dev-pipeline:review-pipeline.

Обоснование «почему именно так» живёт в ../adr/; инварианты с severity — в CLAUDE.md.

Записи

  • logging.md — логирование: уровень по адресату, единственный логирующий чекпоинт, поля, ext.*, что не логируем.
  • errors.md — ошибки: stdlib, обёртка %w, errors.Is/As, трансляция доменной ошибки на внешней границе, sentinel против типизированной.
  • config.md — конфигурация: TOML, секреты рендерит деплой в файл 0600, самодокументируемый config.example.toml, валидация на старте.
  • database.md — БД и идентификаторы: время в UTC RFC 3339, TEXT ULID через internal/ident, ident.Parse на входной границе, естественные ключи у деталей.
  • web-ui.md — веб-UI на htmx: единый партиал = страница = фрагмент, ветвление по isHTMX, деградация без JS, ошибка на htmx-пути = 200 + фрагмент, самозавершающийся поллинг, вендоринг и кэш статики.

Механизировано

Проверяется task gate; прозой не дублируется и в промптах ревью не пересказывается.

Правило Где механизировано
msg лога — константная категория, данные в полях, единый стиль ключ-значение .golangci.ymlsloglint (static-msg, kv-only, no-mixed-args)
В stdout напрямую не пишем (fmt.Print*) .golangci.ymlforbidigo
Конфигурация только из TOML, os.Getenv для конфига не используем .golangci.ymlforbidigo
Время только через store.Now()time.Now запрещён вне internal/{ident,store} .golangci.ymlforbidigo
Сравнение ошибок через errors.Is/As, не == и не приведением типа .golangci.ymlerrorlint
Ошибки — только stdlib (github.com/pkg/errors, cockroachdb/errors запрещены) .golangci.ymldepguard
Опечатки в тексте .golangci.ymlmisspell
Транспорты не зависят друг от друга internal/archrulesTestТранспортыНеЗависятДругОтДруга
Ядро не зависит от транспортов internal/archrulesTestЯдроНеЗависитОтТранспортов
Миграции без AUTOINCREMENT и без серверного времени internal/archrulesTestМиграцииБезAutoincrementИСерверногоВремени
Ошибки не матчатся по тексту сообщения internal/archrulesTestОшибкиНеМатчатсяПоТексту
Покрытие изменённых строк, секреты в диффе, миграция без правки database.md scripts/gate.py, scripts/diff-coverage.py, docs.py check

Непойманное место механизации означает, что проход по конвенциям будет добросовестно проверять уже проверенное.