Files
transcriber/docs/conventions/README.md
T
av 54ca4c0e50 docs: фреймворком приложения выбран Vue 3 с роутером 5 и сборкой Vite
- заведены записка разведки docs/research/spa-framework.md со сравнением Svelte,
  Vue и React на одном экране и решение ADR-2026-08-11-spa-on-vue
- docs/conventions/web-ui.md переписан под Vue: компоненты, маршруты, состояние,
  обращение к API и показ ошибок
- закрыт вопрос «Приложение» в docs/architecture.md, уточнена задача spa-skeleton
2026-08-11 14:51:55 +03:00

5.6 KiB

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

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

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

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

Откуда взяты и что с расхождениями

Четыре записи перенесены из проекта jellybit — тот же Go, тот же автор, те же задачи. Код transcriber написан раньше и части правил не следует: ключи — UUID вместо ULID, время берётся time.Now() по месту, лог пишется на каждом шаге и дублируется воркером, доменные ошибки проверяются приведением типа.

Пятая, web-ui.md, тоже пришла оттуда, но не прижилась: jellybit работает на htmx, а здесь решено делать SPA — и перенесённый текст снят целиком.

Каждое такое место названо в своей записи строкой «Расхождение:». Читается оно как долг, а не как нарушение: правила действуют на новый код, переписывание существующего — отдельная работа. Проходу ревью строка «Расхождение» говорит, что находка на этом месте уже известна и новой не считается.

Записи

  • logging.md — логирование: уровень по адресату, единая логирующая точка на доменной границе, словарь полей, ext.*, что не логируем.
  • errors.md — ошибки: stdlib, обёртка %w, errors.Is и errors.As, трансляция доменной ошибки на внешней границе, sentinel против типизированной.
  • config.md — конфигурация: TOML, секреты рендерит выкладка в файл 0600, самодокументируемый config.dist.toml, проверка на старте.
  • database.md — БД и идентификаторы: время в UTC RFC 3339, TEXT ULID, разбор на входной границе, естественные ключи у деталей.
  • web-ui.md — веб-UI: Vue 3 с Vite и статикой в бинарнике, однофайловые компоненты, таблица маршрутов, состояние в экране, одна обёртка над fetch, показ ошибок и состояний списка.

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

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

Правило Где механизировано
Сравнение ошибок через errors.Is и errors.As, не == и не приведением типа .golangci.ymlerrorlint
Непроверенное возвращаемое значение ошибки .golangci.ymlerrcheck (кроме defer Close и send)
Форматирование исходников .golangci.ymlgofmt
Подозрительные конструкции языка .golangci.ymlgovet, staticcheck, ineffassign, unused
Секреты в коммите lefthook.ymlgitleaks git --staged
Раскладка документов, битые ссылки, миграция без правки database.md docs.py check

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

Из перечисленного в записях правилом выражено одно — сравнение ошибок через errors.Is и errors.As (errorlint, строка таблицы выше). Прозой остаётся всё прочее: ни константный msg лога (sloglint), ни запрет fmt.Print* и os.Getenv (forbidigo), ни запрет сторонних пакетов ошибок (depguard), ни архитектурные тесты-сканеры. Это следующий шаг переноса в правило: свойство, оставшееся прозой, проверяет человек на каждом ревью заново.