docs: перевод документации на канон av-dev

- Раскладка docs/ приведена к канону 2: заведены passport/architecture/
  database/security/review и research; docs/specs, drafts, backlog, review/
  и BRIEF.md разобраны и удалены, беклог переехал в docs/tasks (34 задачи,
  6 целей, слаги на английский).
- Нарративы specs удалены как дубли openspec-спек после поимённой сверки;
  остаток заведён задачами (редактор маппинга ревью, крайние случаи
  именования), отказ от сущности title промоутнут в ADR.
- Проектные копии агентов и скиллов ревью/пайплайна удалены в пользу
  плагинов av-dev-pm и av-dev-pipeline; в task gate добавлен шаг canon
  вместо er-schema.
This commit is contained in:
av
2026-08-04 09:27:26 +03:00
parent 08bef2cac0
commit 42d5b73a04
128 changed files with 1606 additions and 4889 deletions
+44 -24
View File
@@ -1,33 +1,53 @@
# Конвенции кода
Кросс-каттинг правила того, **как** мы пишем код (логирование, ошибки,
именование) — в отличие от `docs/specs/` и `openspec/specs/`, которые
описывают, **что** система делает.
Как мы пишем код — в отличие от `openspec/specs/`, который описывает, что
система делает, и от [../architecture.md](../architecture.md), который
описывает, как она сложена.
**Прозой здесь остаётся только то, что не выражается правилом.** Как только
свойство удаётся проверить машиной, оно уезжает в `.golangci.yml` или в
`internal/archrules`, а формулировка отсюда **удаляется** (остаётся пометка
«механизировано» со ссылкой на линтер). Процедура — [промоут находка →
конвенция → правило → удаление](../../.claude/skills/review-pipeline/references/promote.md).
Причина: файл на несколько сотен строк размазывает внимание по тривиальному —
и модель, и человек добросовестно проверят именование и не дойдут до формы
решения.
**Прозой остаётся только то, что не выражается правилом.** Свойство, ставшее
правилом линтера или тестом-сканером, отсюда **удаляется** и переезжает в
перечень «Механизировано» ниже. Причина: файл на несколько сотен строк
размазывает внимание по тривиальному — и модель, и человек добросовестно
проверят именование и не дойдут до формы решения. Процедура промоута —
`references/promote.md` скилла `av-dev-pipeline:review-pipeline`.
Конвенции **не** переносятся в OpenSpec: это не capability. Короткие
инварианты дублируются в [CLAUDE.md](../../CLAUDE.md) (агент читает его
всегда) и кратко в `openspec/config.yaml``context` (подмешивается в
генерацию артефактов); детали — здесь. Обоснование «почему» — в `docs/adr/`.
Обоснование «почему именно так» живёт в [../adr/](../adr/README.md); инварианты
с severity — в [CLAUDE.md](../../CLAUDE.md).
## Записи
- [logging.md](logging.md) — логирование: уровни, поля, что не логируем.
- [config.md](config.md) — конфигурация: TOML, секреты через деплой
(Ansible+Vault), валидация на старте.
- [logging.md](logging.md) — логирование: уровень по адресату, единственный
логирующий чекпоинт, поля, `ext.*`, что не логируем.
- [errors.md](errors.md) — ошибки: stdlib, обёртка `%w`, `errors.Is`/`As`,
трансляция на внешней границе.
- [database.md](database.md) — БД и идентификаторы: TEXT ULID PK через
`internal/ident` (без AUTOINCREMENT), lowercase + нормализация на границах,
естественные ключи у деталей.
трансляция доменной ошибки на внешней границе, sentinel против типизированной.
- [config.md](config.md) — конфигурация: TOML, секреты рендерит деплой в файл
`0600`, самодокументируемый `config.example.toml`, валидация на старте.
- [database.md](database.md) — БД и идентификаторы: время в UTC RFC 3339, TEXT
ULID через `internal/ident`, `ident.Parse` на входной границе, естественные
ключи у деталей.
- [web-ui.md](web-ui.md) — веб-UI на htmx: единый партиал = страница = фрагмент,
ветвление `isHTMX`, деградация без JS, ошибка = 200 + фрагмент, самозавершающийся
поллинг, вендоринг/кэш статики.
ветвление по `isHTMX`, деградация без JS, ошибка на htmx-пути = 200 +
фрагмент, самозавершающийся поллинг, вендоринг и кэш статики.
## Механизировано
Проверяется `task gate`; прозой не дублируется и в промптах ревью не
пересказывается.
| Правило | Где механизировано |
| --- | --- |
| `msg` лога — константная категория, данные в полях, единый стиль ключ-значение | `.golangci.yml``sloglint` (`static-msg`, `kv-only`, `no-mixed-args`) |
| В stdout напрямую не пишем (`fmt.Print*`) | `.golangci.yml``forbidigo` |
| Конфигурация только из TOML, `os.Getenv` для конфига не используем | `.golangci.yml``forbidigo` |
| Время только через `store.Now()``time.Now` запрещён вне `internal/{ident,store}` | `.golangci.yml``forbidigo` |
| Сравнение ошибок через `errors.Is`/`As`, не `==` и не приведением типа | `.golangci.yml``errorlint` |
| Ошибки — только stdlib (`github.com/pkg/errors`, `cockroachdb/errors` запрещены) | `.golangci.yml``depguard` |
| Опечатки в тексте | `.golangci.yml``misspell` |
| Транспорты не зависят друг от друга | `internal/archrules``TestТранспортыНеЗависятДругОтДруга` |
| Ядро не зависит от транспортов | `internal/archrules``TestЯдроНеЗависитОтТранспортов` |
| Миграции без `AUTOINCREMENT` и без серверного времени | `internal/archrules``TestМиграцииБезAutoincrementИСерверногоВремени` |
| Ошибки не матчатся по тексту сообщения | `internal/archrules``TestОшибкиНеМатчатсяПоТексту` |
| Покрытие изменённых строк, секреты в диффе, миграция без правки `database.md` | `scripts/gate.py`, `scripts/diff-coverage.py`, `docs.py check` |
Непойманное место механизации означает, что проход по конвенциям будет
добросовестно проверять уже проверенное.
+2 -2
View File
@@ -1,7 +1,7 @@
# Конвенция: база данных и идентификаторы
Как мы устраиваем таблицы и ключи в SQLite. Актуальная схема —
[../specs/database.md](../specs/database.md); обоснование выбора ULID —
[../database.md](../database.md); обоснование выбора ULID —
`openspec/changes/ulid-identity/design.md` (после архивации — в истории git).
**Механизировано:** `AUTOINCREMENT` и `DEFAULT (datetime('now'))` в новых
@@ -52,4 +52,4 @@
- Миграции — goose (`internal/store/migrations`): SQL-файлы для DDL;
Go-миграции (`goose.AddMigrationContext`) — когда нужен код (генерация
id, backfill). При изменении структуры обновляем ER-схему
[../specs/database.md](../specs/database.md) в том же change.
[../database.md](../database.md) в том же change.
+1 -1
View File
@@ -97,7 +97,7 @@ jellybit — **приложение, а не библиотека**: внешн
в review/failed: коллизия, рассинхрон, сбой ФС) и `reasons` распознавания,
сохранённые в БД и показываемые на экране ревью и в Telegram-карточке. Это
**операторская поверхность владельца**: сервис однопользовательский в
доверенной LAN (см. [architecture.md](../specs/architecture.md)), эти поля —
доверенной LAN (см. [architecture.md](../architecture.md)), эти поля —
диагностический контекст для того, кто разбирает задачу. Здесь сырой текст
ошибки (пути, фрагмент ответа LLM/qBittorrent) **допустим и полезен** — но:
- **секреты запрещены** абсолютно (токены/ключи/пароли/`Authorization`) — так