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:
@@ -1,6 +1,6 @@
|
||||
# Авто-раскладка только при подтверждённом матче в метабазе
|
||||
|
||||
- Дата: 2026-06-13
|
||||
- **Дата:** 2026-06-13
|
||||
|
||||
## Контекст
|
||||
|
||||
@@ -21,7 +21,7 @@ jellybit распознаёт содержимое релиза через LLM
|
||||
каноническое имя + `provider_id`. Но русские релизы и аниме часто в них
|
||||
отсутствуют.
|
||||
- Безопасность раскладки уже держится на валидации пути, не на промпте
|
||||
(см. [recognition.md](../specs/recognition.md)); решение «авто vs review» —
|
||||
(см. [recognition](../../openspec/specs/recognition/spec.md)); решение «авто vs review» —
|
||||
второй слой защиты, на уровне доверия результату.
|
||||
|
||||
## Рассмотренные варианты
|
||||
@@ -53,8 +53,8 @@ LLM не противоречат по типу/названию/году. Не
|
||||
подтверждает) и убирает целый класс тихих ошибок «модель уверенно
|
||||
ошиблась». Review здесь — не наказание, а штатный режим для всего, что
|
||||
база не подтвердила (петля «догадка → подсказка → перераспознавание», см.
|
||||
[review-ux.md](../specs/review-ux.md)). Полная модель уверенности — в
|
||||
[recognition.md](../specs/recognition.md).
|
||||
[review](../../openspec/specs/review/spec.md)). Полная модель уверенности — в
|
||||
[recognition](../../openspec/specs/recognition/spec.md).
|
||||
|
||||
## Последствия
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Docker как единица деплоя, образ собирается на сервере
|
||||
|
||||
- Дата: 2026-06-13
|
||||
- Статус: заменено на ADR-2026-07-24-local-image-build
|
||||
- **Дата:** 2026-06-13
|
||||
- **Статус:** заменено на ADR-2026-07-24-local-image-build
|
||||
|
||||
## Контекст
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Go и доставка одним бинарём
|
||||
|
||||
- Дата: 2026-06-13
|
||||
- **Дата:** 2026-06-13
|
||||
|
||||
## Контекст
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Хардлинки вместо копирования и симлинков
|
||||
|
||||
- Дата: 2026-06-13
|
||||
- **Дата:** 2026-06-13
|
||||
|
||||
## Контекст
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# Отдельную сущность «тайтл» не вводим
|
||||
|
||||
- **Дата:** 2026-07-02
|
||||
- **Источник:** черновик `docs/drafts/logical-title-model.md` (разбор от
|
||||
2026-07-01, переработан 2026-07-02; удалён при переводе проекта на канон,
|
||||
полный текст — в истории git). Первый производный change —
|
||||
[openspec/changes/archive/2026-07-02-ulid-identity/design.md](../../openspec/changes/archive/2026-07-02-ulid-identity/design.md).
|
||||
|
||||
## Решение
|
||||
|
||||
Логический тайтл (фильм или сериал, складывающийся из нескольких загрузок во
|
||||
времени) остаётся **вычисляемой группой**, а не хранимой сущностью: доменная
|
||||
идентичность — `download` (ULID + множество инфохэшей), связь с диском —
|
||||
`file_link` с владением целевым путём, а «второй сезон в ту же папку» решается
|
||||
**правилом сходимости папки** при построении плана раскладки.
|
||||
|
||||
## Почему
|
||||
|
||||
Разбор шёл от операций, и у тайтла их не нашлось:
|
||||
|
||||
> У `title` при разборе **не нашлось ни одной собственной операции**: сходимость
|
||||
> папки — правило при построении плана; merge докачивания — per-path логика;
|
||||
> удаление целиком — цикл по вычисляемой группе. Сущность без собственных
|
||||
> операций — это линза, а линзу достаточно вычислять, не хранить.
|
||||
|
||||
Второй аргумент — у папки уже есть дом, и вычисляемый якорь **корректнее**
|
||||
хранимого:
|
||||
|
||||
> «Папка — это title-уровневое состояние, ей нужен дом» разбивается о то, что
|
||||
> дом у папки уже есть — файловая система и `dst_path` живых `file_link`'ов.
|
||||
> Реестр дублировал бы то, что и так записано в БД в N экземплярах. Причём
|
||||
> вычисляемый якорь корректнее хранимого: если все файлы сериала снесли, живых
|
||||
> ссылок нет — и новая загрузка честно создаёт свежую папку; хранимый
|
||||
> `title.folder` указывал бы в пустоту.
|
||||
|
||||
Третий — отказ **устраняет**, а не решает хвост развилок: жизненный цикл тайтла
|
||||
(рождение, смерть, пустой тайтл), слияние тайтлов, ad-hoc тайтл без провайдера,
|
||||
обратная миграция существующих строк, отдельный title-лог.
|
||||
|
||||
## Рассмотренные варианты
|
||||
|
||||
- **L2 — `title` с ключом `(provider, provider_id)`.** Отвергнут: привязывает
|
||||
долгоживущую сущность к провайдеру, который может смениться.
|
||||
- **L2-min — `title` со своим ULID + `title_external_id`** (провайдерные id
|
||||
множеством-атрибутом, симметрично `download_infohash`). Схема красивая и
|
||||
решает смену провайдера, ad-hoc тайтлы и слияние. Отвергнут именно по
|
||||
аргументу выше: собственных операций нет, а сущность тянет жизненный цикл,
|
||||
миграцию и четыре развилки.
|
||||
- **L3 — title-центричная медиатека (модель sonarr).** Отвергнут осознанно: мы
|
||||
не ходим в индексеры, не мониторим тайтлы и не ведём профили качества —
|
||||
контент приносит пользователь. Это граница домена,
|
||||
[passport.md](../passport.md) → «Что целью не является».
|
||||
|
||||
## Последствия
|
||||
|
||||
- `+` Идентичность осталась одноуровневой: `download` — мост между раздачей в
|
||||
qBittorrent и файлами на диске, и каждая сущность цепочки отвечает на свои
|
||||
операции.
|
||||
- `+` Главная боль («второй сезон должен лечь в ту же папку») закрыта дешёвым
|
||||
правилом при построении плана — реализовано change'ем
|
||||
`2026-07-10-series-folder-convergence`, требования влиты в
|
||||
[openspec/specs/file-layout](../../openspec/specs/file-layout/spec.md).
|
||||
- `+` Устранён, а не отложен, хвост развилок вокруг жизненного цикла тайтла.
|
||||
- `−` Группировка тайтла в UI и «удалить тайтл целиком» придётся каждый раз
|
||||
**вычислять** по `(provider, provider_id)` и общей папке; дешёвого хранимого
|
||||
ключа для этого нет.
|
||||
- `−` Рассинхрон «несколько живых папок с одним `(provider, provider_id)`»
|
||||
разрешается только уходом в review — in-app лечения нет, чинится руками на
|
||||
диске.
|
||||
- `−` Слияние загрузок при перезаливе «той же вещи» осталось открытым: когда
|
||||
несколько инфохэшей считать одной загрузкой, а когда разными, — вопрос
|
||||
переехал в задачу про merge-раскладку.
|
||||
|
||||
## Триггер пересмотра
|
||||
|
||||
Записан отдельно, чтобы не гонять этот круг заново:
|
||||
|
||||
> Сущность `title` возвращается в обсуждение, только когда появится **операция
|
||||
> или состояние, которому реально негде жить** в `download` + `file_link` —
|
||||
> например, «переименовать сериал целиком с переносом ссылок» как регулярное
|
||||
> действие или заметки уровня группы. До того — вычисляем.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Конвейер ревью: гейт, generative-проходы и обязательный триаж
|
||||
|
||||
- Дата: 2026-07-23
|
||||
- **Дата:** 2026-07-23
|
||||
|
||||
## Контекст
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Образ собирается локально и едет на сервер через docker save/load
|
||||
|
||||
- Дата: 2026-07-24
|
||||
- **Дата:** 2026-07-24
|
||||
|
||||
## Контекст
|
||||
|
||||
|
||||
+34
-47
@@ -1,64 +1,51 @@
|
||||
# Architecture Decision Records (ADR)
|
||||
# Журнал решений
|
||||
|
||||
Журнал значимых архитектурных решений по jellybit. Одна запись — одно
|
||||
решение. ADR пишем **постфактум**, когда решение принято и зафиксировано
|
||||
в коде/проекте: идеи и неподтверждённые планы живут в `docs/drafts`, а не
|
||||
в ADR. Записи **неизменяемы**: передумали → не правим старую, заводим
|
||||
новую и помечаем старую.
|
||||
Одна запись — одно решение. **ADR это промоут поверх архивного `design.md`**,
|
||||
а не второе сочинение: запись цитирует решение и ссылается на
|
||||
`openspec/changes/archive/<id>/design.md`.
|
||||
|
||||
Главная ценность записи — сохранить **почему**: намерение и причинность.
|
||||
Это важнее аккуратности оформления и полноты остальных секций.
|
||||
Главная ценность записи — сохранить **почему**: намерение и причинность. Это
|
||||
важнее аккуратности оформления и полноты остальных секций.
|
||||
|
||||
Формат и процесс унаследованы от соседнего проекта umbar.
|
||||
## Когда заводить
|
||||
|
||||
## Когда заводить ADR
|
||||
Верно одно из трёх:
|
||||
|
||||
- Выбор технологии или инструмента.
|
||||
- Структурные решения (хранилище, организация компонентов, протоколы).
|
||||
- Решения с долгосрочными последствиями или дорогим откатом.
|
||||
- **Намеренный отказ** от очевидного подхода — чтобы потом не
|
||||
переоткрывать «а почему мы не сделали X».
|
||||
<!-- копия: adr-когда-заводить из av-dev-pm/skills/canon/references/canon.md -->
|
||||
- **дорогой откат** — переделка стоит дороже переписывания одного файла;
|
||||
- **намеренный отказ** от очевидного подхода;
|
||||
- **пересмотр прежнего решения** — тогда у старой записи обязателен статус
|
||||
«заменено на».
|
||||
<!-- /копия: adr-когда-заводить -->
|
||||
|
||||
Не заводить для рутины (бамп версии зависимости, добавление эндпоинта по
|
||||
накатанной схеме) и того, что и так видно из кода и git.
|
||||
Не заводить для рутины и для того, что видно из кода и `git log`.
|
||||
|
||||
## Соглашения
|
||||
|
||||
- **Имя файла = идентификатор:** `ADR-ГГГГ-ММ-ДД-kebab-slug.md`.
|
||||
Идентификатор — имя без `.md`. Slug — латиницей.
|
||||
- **Дата** — когда решение реально принято.
|
||||
- Несколько ADR за один день различаются по slug.
|
||||
- **Заголовок в файле:** `# Человеческий заголовок` (без даты и ID — они
|
||||
в имени файла и в строке «Дата»).
|
||||
- Секция **«Рассмотренные варианты» — опциональна**: оставляй её, только
|
||||
если альтернативы реально рассматривались.
|
||||
- Шаблон новой записи — [`template.md`](template.md).
|
||||
- Имя файла — `ADR-ГГГГ-ММ-ДД-slug.md`, слаг английский, дата — когда решение
|
||||
реально принято. Идентификатор записи — имя файла без `.md`; несколько
|
||||
записей за один день различаются слагом.
|
||||
- **Заголовок в файле** — `# Человеческий заголовок`, без даты и id: они в
|
||||
имени файла и в поле меты.
|
||||
- Секция «Рассмотренные варианты» **опциональна**: оставляй, только если
|
||||
альтернативы реально рассматривались.
|
||||
- Записи неизменяемы: передумали — новая запись, старой ставится статус.
|
||||
- Активная запись статуса не имеет. Значений два: `заменено на ADR-…` и
|
||||
`устарело`; ставятся полем меты записи — `- **Статус:** …` рядом с датой и
|
||||
источником, а не абзацем в теле.
|
||||
- Замена: в новой записи — строка «Заменяет ADR-…», в старой — поле статуса,
|
||||
тело не трогаем (это часть истории), в таблице ниже правится статус.
|
||||
|
||||
## Статусы
|
||||
|
||||
Активная запись статуса **не имеет**. Статус появляется, только когда
|
||||
запись теряет силу, и значений всего два:
|
||||
|
||||
- `заменено на ADR-ГГГГ-ММ-ДД-slug` — решение пересмотрено новой ADR.
|
||||
- `устарело` — решение потеряло смысл и замены нет.
|
||||
|
||||
## Замена и устаревание
|
||||
|
||||
1. Заводим новую ADR; в её «Контексте» — строка
|
||||
«Заменяет ADR-ГГГГ-ММ-ДД-slug».
|
||||
2. В старой ADR добавляем строку `- Статус: заменено на ADR-…` сразу под
|
||||
датой. Тело не трогаем — это часть истории.
|
||||
3. Обновляем статус старой записи в индексе ниже.
|
||||
|
||||
## Список записей
|
||||
## Записи
|
||||
|
||||
Новые сверху.
|
||||
|
||||
| Дата | Запись | Статус |
|
||||
| ---------- | ---------------------------------------------------------------- | ------ |
|
||||
| Дата | Запись | Статус |
|
||||
| --- | --- | --- |
|
||||
| 2026-07-24 | [Локальная сборка образа + доставка docker save/load](ADR-2026-07-24-local-image-build.md) | — |
|
||||
| 2026-07-23 | [Конвейер ревью: гейт, generative-проходы и триаж](ADR-2026-07-23-review-pipeline-generative.md) | — |
|
||||
| 2026-07-02 | [Отдельную сущность «тайтл» не вводим](ADR-2026-07-02-no-title-entity.md) | — |
|
||||
| 2026-06-13 | [Авто-раскладка только при матче в метабазе](ADR-2026-06-13-auto-link-requires-db-match.md) | — |
|
||||
| 2026-06-13 | [Docker как единица деплоя](ADR-2026-06-13-docker-deploy.md) | заменено на ADR-2026-07-24-local-image-build |
|
||||
| 2026-06-13 | [Docker как единица деплоя](ADR-2026-06-13-docker-deploy.md) | заменено на ADR-2026-07-24-local-image-build |
|
||||
| 2026-06-13 | [Хардлинки вместо копирования и симлинков](ADR-2026-06-13-hardlinks.md) | — |
|
||||
| 2026-06-13 | [Go и доставка одним бинарём](ADR-2026-06-13-go-single-binary.md) | — |
|
||||
| 2026-06-13 | [Go и доставка одним бинарём](ADR-2026-06-13-go-single-binary.md) | — |
|
||||
|
||||
+20
-24
@@ -1,36 +1,32 @@
|
||||
# Краткий заголовок решения
|
||||
|
||||
- Дата: ГГГГ-ММ-ДД
|
||||
<!-- Строку статуса добавляют позже, только если запись потеряла силу:
|
||||
- Статус: заменено на ADR-ГГГГ-ММ-ДД-slug
|
||||
- Статус: устарело
|
||||
У активной записи строки статуса нет. -->
|
||||
- **Дата:** ГГГГ-ММ-ДД
|
||||
- **Источник:** openspec/changes/archive/<id>/design.md
|
||||
|
||||
## Контекст
|
||||
<!-- Статус ставится тем же полем и только при пересмотре:
|
||||
- **Статус:** заменено на ADR-ГГГГ-ММ-ДД-slug
|
||||
- **Статус:** устарело
|
||||
У активной записи поля нет. -->
|
||||
|
||||
Что вынудило принять решение: проблема, силы и ограничения (ресурсы,
|
||||
стоимость, время на поддержку, существующая архитектура). Пиши так, чтобы
|
||||
через год было понятно «почему это вообще делалось» без чтения переписки.
|
||||
## Решение
|
||||
|
||||
Что именно решено — одной фразой.
|
||||
|
||||
## Почему
|
||||
|
||||
Намерение и причина. **Цитата из источника, а не пересказ.** Пиши так, чтобы
|
||||
через год было понятно без чтения переписки.
|
||||
|
||||
## Рассмотренные варианты
|
||||
|
||||
<!-- Опциональная секция. Оставь, только если варианты реально
|
||||
рассматривались. Если решение было единственным очевидным — удали
|
||||
её, а причину объясни в «Решении». -->
|
||||
рассматривались. Если решение было единственным очевидным — удали её,
|
||||
а причину объясни в «Почему». -->
|
||||
|
||||
- **Вариант A** — суть, плюсы и минусы.
|
||||
- **Вариант B** — суть, плюсы и минусы.
|
||||
- **Вариант C** — если отвергнут сразу, коротко почему.
|
||||
|
||||
## Решение
|
||||
|
||||
Что именно сделано и — главное — **почему**: какое намерение и какая
|
||||
причина за этим стоят. Если варианты рассматривались — почему выбран
|
||||
этот, а не остальные.
|
||||
- **Вариант A** — суть, почему отвергнут.
|
||||
- **Вариант B** — суть, почему отвергнут.
|
||||
|
||||
## Последствия
|
||||
|
||||
- `+` что стало лучше, какие возможности открылись.
|
||||
- `-` чем платим: новые ограничения, риски, регулярная нагрузка на
|
||||
поддержку.
|
||||
- Что нужно сделать как следствие (если есть).
|
||||
- `+` что стало лучше.
|
||||
- `−` чем платим: ограничения, риски, нагрузка на поддержку.
|
||||
|
||||
Reference in New Issue
Block a user