Канон документов, каталог задач и OpenSpec

docs/ по канону 12: паспорт с целью проекта, архитектура сегодняшнего
устройства, схема хранилища, модель угроз, конвенции кода, журнал ревью.
Конвенции перенесены из jellybit; места, где код им не следует, помечены
строкой «Расхождение» как объявленный долг.

tasks/ с роадмапом: две достигнутые цели, две запланированные (веб и
многопользовательский режим), два направления (все форматы, долгие
записи) и пять задач в беклоге.

openspec/config.yaml — маршрутизатор с адресами документов, спек пока нет.

CLAUDE.md переписан по форме канона: инварианты с severity, семантика
гейта, запреты с путями. Taskfile получил task gate.
This commit is contained in:
av
2026-08-10 21:19:07 +03:00
parent a4646c0930
commit 4d1c2bf44c
40 changed files with 3656 additions and 71 deletions
+44
View File
@@ -0,0 +1,44 @@
# 🧹 Перевести хранилище на встроенный PocketBase
- **Тип:** chore
- **Категория:** Инфра
- **Зачем:** Хранилище, учётные записи и веб-панель нужны все три, и SQLite с goqu не даёт ни второго, ни третьего.
PocketBase встраивается библиотекой в тот же бинарник и приносит хранилище,
учётные записи и панель администратора разом. Наблюдаемое поведение сервиса
после перевода не меняется: те же два входа, тот же конвейер, тот же текст на
выходе.
Данные не переносим — база заводится с чистого листа, и это решение принято
сознательно.
## Затрагивает
- таблицы `files` и `transcribe_jobs`, каталог `migrations/` и весь механизм
goose;
- `internal/adapter/repo/sqlite` целиком, включая захват задачи через
`FindAndAcquire`;
- `internal/contract`, интерфейсы `FileRepository` и `TranscriptJobRepository`;
- ключ конфигурации `[database] path` и раскладка каталога `data/`;
- сборка образа: PocketBase тянет свой набор зависимостей, а `mattn/go-sqlite3`
с его требованием CGO может уйти;
- `docs/database.md` — схема, представление данных и таблица настроек.
## Критерии приёмки
- Сервис поднимается на чистом каталоге данных, накатывает свою схему сам и
принимает запись обоими входами. Оракул — запуск на пустом `data/` и прогон
записи из Telegram и через `POST /api/audio` до состояния `done`.
- Захват задачи воркером не выдаёт одну запись двум вызывающим. Оракул — тест
на трёх параллельных вызовах захвата по одному состоянию: ровно один
получает запись.
- Задача, брошенная на середине, достаётся снова по истечении срока захвата.
Оракул — тест с проставленным задним числом `acquire_time`.
- `docs/database.md` описывает новую схему, а старые упоминания goose и goqu из
документов канона убраны. Оракул — `task gate`, шаг `docs.py check`.
## Рамки
Данные прежней базы не переносим и не пытаемся сохранить; выкладку не запускаем;
смена формата хранения на сервере необратима, и момент перехода назначает
человек.