- лестница механизации из пяти ступеней, два круга проверок, перечень правил таблицами по родам, перечень подавлений с причинами, порядок заведения правила; названы остатки правил и отклонённые подъёмы - утверждения «Механизировано» в четырёх записях конвенций и единые точки в architecture.md приведены к сегодняшнему состоянию; изъятие «транспорт знает адаптер хранилища» названо строкой - в журнал дефектов записаны две находки: узнавание конца потока по тексту и правило гейта, обходимое одной лишней строкой
62 lines
5.1 KiB
Markdown
62 lines
5.1 KiB
Markdown
# Конвенции кода
|
||
|
||
Как мы пишем код — в отличие от `openspec/specs/`, который описывает, что
|
||
система делает, и от [../architecture.md](../architecture.md), который описывает,
|
||
как она сложена.
|
||
|
||
**Прозой остаётся только то, что не выражается правилом.** Свойство, ставшее
|
||
правилом линтера или тестом-сканером, отсюда **удаляется** и переезжает в
|
||
перечень «Механизировано» документа [../autotests.md](../autotests.md) — дома
|
||
инструментов, которые читают код. Причина: файл на несколько сотен строк
|
||
размазывает внимание по тривиальному — и модель, и человек добросовестно
|
||
проверят именование и не дойдут до формы решения.
|
||
|
||
Обоснование «почему именно так» живёт в [../adr/](../adr/README.md); инварианты с
|
||
severity — в [CLAUDE.md](../../CLAUDE.md).
|
||
|
||
## Откуда взяты и что с расхождениями
|
||
|
||
Четыре записи перенесены из проекта jellybit — тот же Go, тот же автор, те же
|
||
задачи. Код transcriber написан раньше и **части правил не следует**: ключи —
|
||
UUID вместо ULID, лог пишется на каждом шаге и дублируется воркером, `msg` —
|
||
предложение с заглавной буквы вместо константной категории.
|
||
|
||
Из этого перечня закрыты два. Доменные ошибки проверялись приведением типа до
|
||
2026-08-11, задача `errors-as-instead-of-typecast`. Время брали `time.Now()` по
|
||
месту до 2026-08-13 — теперь его читает единая точка `internal/clock`, и правило
|
||
держит линтер. Оба места больше не долг, а регрессия.
|
||
|
||
Пятая, `web-ui.md`, тоже пришла оттуда, но не прижилась: jellybit работает на
|
||
htmx, а здесь решено делать SPA — и перенесённый текст снят целиком.
|
||
|
||
Каждое такое место названо в своей записи строкой «*Расхождение:*». Читается оно
|
||
как **долг, а не как нарушение**: правила действуют на новый код, переписывание
|
||
существующего — отдельная работа. Проходу ревью строка «Расхождение» говорит, что
|
||
находка на этом месте уже известна и новой не считается.
|
||
|
||
## Записи
|
||
|
||
- [logging.md](logging.md) — логирование: уровень по адресату, единая логирующая
|
||
точка на доменной границе, словарь полей, `ext.*`, что не логируем.
|
||
- [errors.md](errors.md) — ошибки: stdlib, обёртка `%w`, `errors.Is` и
|
||
`errors.As`, трансляция доменной ошибки на внешней границе, sentinel против
|
||
типизированной.
|
||
- [config.md](config.md) — конфигурация: TOML, секреты рендерит выкладка в файл
|
||
`0600`, самодокументируемый `config.dist.toml`, проверка на старте.
|
||
- [database.md](database.md) — БД и идентификаторы: время в UTC RFC 3339, TEXT
|
||
ULID, разбор на входной границе, естественные ключи у деталей.
|
||
- [web-ui.md](web-ui.md) — веб-UI: Vue 3 с Vite и статикой в бинарнике,
|
||
однофайловые компоненты, таблица маршрутов, состояние в экране, одна обёртка
|
||
над `fetch`, показ ошибок и состояний списка.
|
||
|
||
## Что из этого проверяет машина
|
||
|
||
Перечень правил, доведённых до проверки, и место настройки каждого — в
|
||
[../autotests.md](../autotests.md). Там же сказано, что из перечисленного в
|
||
записях осталось прозой и потому проверяется человеком на каждом ревью заново, и
|
||
там же названы остатки правил — то, что правило не ловит. Числа механизированного
|
||
здесь нет намеренно: оно протухает при каждом новом правиле.
|
||
|
||
Здесь этот перечень не повторяется. Дом у него один, и он не тут: конвенции
|
||
говорят, как писать код, а не какими инструментами его читают.
|