# ✨ Резать длинную запись на фрагменты и продолжать с места остановки

- **Тип:** feature
- **Категория:** Очередь — Резка на фрагменты — самая глубокая переделка конвейера, и она идёт по замеренным числам.
- **Зачем:** Шаг конвейера повторяется целиком: перезапуск на пятом часу шестичасовой записи начинает распознавание заново и оплачивает его второй раз.

Запись в пределах потолка доходит до текста целиком, долгая задача не занимает
воркер на часы, а перезапуск на середине продолжает работу с первого
неотмеченного фрагмента.

Запись делится на фрагменты, каждый распознаётся отдельно, готовый фрагмент
отмечается в базе. После перезапуска работа продолжается с первого неотмеченного, а
текст собирается из фрагментов по порядку.

## Затрагивает

- принцип «шаг конвейера идемпотентен по повтору» из `docs/architecture.md`:
  шаг перестаёт быть неделимым;
- таблица фрагментов задачи: порядковый номер, границы по времени, состояние,
  текст — и её миграция;
- состояния конвейера `created` → `converted` → `transcribe` → `done`;
- конвертер: деление записи на фрагменты по времени;
- адаптер SpeechKit: обращение на фрагмент вместо обращения на запись;
- раскладка `data/files`: файлы фрагментов рядом с исходным.

## Критерии приёмки

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

## Рамки

Длину фрагмента назначает ответ разведки `speechkit-limits` — до неё задача не
берётся. Раскладка `data/files` меняется, а это необратимо: формат согласуется с
человеком. Прогон на боевых ключах ради проверки запрещён — подставной
распознаватель.
