Files
jellybit/docs/conventions
av 2971a520c7 веб-ui: знак «jb» стал единым для шапки, иконки вкладки и превью ссылки
- логотип сведён в web/static/logo.svg (буквы геометрией, оптическая
  центровка); прежний favicon с «play» убран
- <head> шести страниц свёрнут в партиал head с og-мета; адреса абсолютные,
  база берётся из запроса, хост из недоверенного заголовка проверяется
- растровые ассеты og-cover.jpg и apple-touch-icon.png собирает `task brand`
  из исходников web/*.html
2026-09-02 10:55:45 +03:00
..

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

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

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

Обоснование «почему именно так» живёт в ../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

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