## Why

Сервис объявлен архивом: записи и расшифровки лежат бессрочно, к ним
возвращаются через месяцы, а поверх них строятся список, темы, уровни текста и
учёт расхода. Держать всё это негде — центральной сущности «аудиозапись» в
сервисе нет вовсе: есть задача конвейера, у которой поля захвата лежат в одной
строке с расшифровкой, указатель на файл переставляет каждый шаг, а отказ стирает
достигнутый рубеж и делает продолжение с места остановки невозможным.

Всякая задача, взятая раньше этой, будет переписана вместе с моделью — потому
владелец 2026-08-14 поставил её первой в план стройки.

## What Changes

- **Центральная сущность — аудиозапись.** Домен записи (владелец, заголовок,
  краткое описание, рубеж, ссылки на приложения) отделяется от того, что нужно
  только конвейеру, и от того, что принадлежит провайдеру распознавания.
- **Приложения к записи живут отдельными строками.** Файлы, тексты, структура
  реплик, темы, журнал событий и попытка распознавания перестают быть колонками
  одной строки и адресуются ссылками с записи.
- **Ссылки на файлы перестают переставляться.** У записи две отдельные ссылки —
  на исходник и на приведённую копию, — и обе живут до конца. Сегодня их одна, и
  прошедшая конвейер запись ведёт на объект во внешнем хранилище: послушать
  загруженное нечем.
- **Копия во внешнем хранилище перестаёт быть файлом записи.** Она существует
  только потому, что распознаватель читает аудио по адресу, и переезжает в
  строку о попытке распознавания вместе с идентификатором операции.
- **Сырой ответ распознавателя сохраняется целиком** — вложением, а не колонкой.
  Результат операции у провайдера не переспрашивается, а связь реплики с
  говорящим сервис строить пока не умеет: когда научится, архив пересчитается из
  сохранённого без единого рубля.
- **Состояние называет достигнутое, а не предстоящее.** Цепочка рубежей:
  `uploaded → normalized → submitted → transcribed → done`. **BREAKING**: перечень
  состояний в ответе о записи меняется целиком — публичный контракт HTTP API
  объявлен проектом необратимым.
- **Остановка становится признаком, а не состоянием.** Прежние `failed` и `dead`
  схлопываются в признак остановки с причиной; достигнутый рубеж при этом
  сохраняется, и снятие признака продолжает работу с места остановки, а не с
  начала. Снимает признак владелец панели — поверхности для владельца записи у
  сервиса пока нет, её заводит задача с экранами.
- **Сторожей становится двое.** Число отказов ограничивает повторы внутри шага,
  время в рубеже — застревание. Сегодня обе роли навешаны на счётчик попыток, и
  он не справляется ни с одной: операция, зависшая у провайдера, опрашивается
  вечно.
- **Предел времени в рубеже** — два числа: час на свою работу, сутки на чужую.
  Достигнут предел — запись останавливается с причиной «застряла».
- **Переход и откладывание разводятся.** Шаг опроса перестаёт изображать переход
  в то же самое состояние: откладывание ставит паузу и снимает захват, а рубежа и
  времени входа в него не трогает.
- **Шаг с внешней оплатой проверяет сделанное** прежде, чем платить второй раз.
- **Воркеры теряют специализацию**, а их число задаётся настройкой; ноль —
  законное значение: записи принимаются и не двигаются.
- **Переноса данных нет.** Сервис на сервере остановлен, прежние записи удалены
  решением владельца 2026-08-14, и новая модель заводится с чистого листа.

## Capabilities

### New Capabilities

- `recognition`: попытка распознавания у внешнего провайдера — что о ней
  хранится, почему сырой ответ сохраняется целиком, как из сохранённого строится
  структура реплик и почему разбор формата провайдера не доходит до конвейера.

### Modified Capabilities

- `pipeline`: цепочка рубежей и смысл состояния; остановка признаком вместо
  состояний отказа и смерти; два сторожа вместо одного; предел времени в рубеже;
  разведение перехода и откладывания; необязательный шаг, чей отказ не роняет
  запись; захват, возвращающий один идентификатор; воркер без специализации и его
  число настройкой.
- `storage`: аудиозапись центральной сущностью и её приложения отдельными
  коллекциями; две отдельные ссылки на файлы вместо одной переставляемой;
  словарь тем на каждого владельца; журнал событий записи; перенос живых записей
  шагом схемы.
- `intake`: перечень состояний в ответе о приёме и об опросе готовности.

## Impact

- **Схема хранилища**: новый шаг — коллекции `audio_records`, `texts`,
  `structures`, `recognitions`, `record_events`, `topics`; прежняя
  `transcribe_jobs` уходит; правка `files`. Применённые шаги не переписываются.
- **Публичный контракт HTTP API**: значения поля состояния. Необратимо.
- `internal/entity` — сущность записи, перечень рубежей, переходы, откладывание,
  остановка признаком.
- `internal/contract` — распознаватель отдаёт доменный результат вместо строки,
  заливка и отправка разделены; контракты репозиториев записи, файлов, текстов,
  структуры, попыток распознавания и журнала.
- `internal/adapter/recognizer/yandex` — разбор потока результата в реплики,
  раздельные заливка и отправка, отдача сырых байтов на хранение.
- `internal/adapter/repo/pocketbase` — запрос захвата, отображение записи,
  правила панели.
- `internal/service` — шаги, таблица выбора следующего шага по рубежу, остановка
  признаком.
- `internal/controller/worker` и `main.go` — пул вместо трёх именованных
  воркеров.
- `internal/config` и `config.example.toml` — число воркеров, срок захвата по
  шагу, два предела времени в рубеже.
- `docs/architecture.md`, `docs/database.md`, инварианты `CLAUDE.md` о колонках
  очереди и о держателе захвата.
- **Предшествующая задача**: `external-call-timeouts` в плане стройки стоит
  ниже, а по «Рамкам» постановки предшествует — без предела по времени у шага
  срок захвата не может его превысить.
