tasks: спроектирован контракт приложения и переставлена голова очереди
- json-api-for-spa: адреса приложения уехали в своё пространство /app/, приём стал POST /app/audiorecords, опрос /api/status/:id убран, заведены список, карточка, текст, /app/me и /app/config; имя файла отправителя легло своей колонкой рядом с заголовком - три действия над записью — правка заголовка, возврат в работу и журнал событий — собраны задачей audiorecord-actions - голова очереди: контракт, каркас, экран загрузки, список, действия - в прежних задачах поправлены адреса, рубежи конвейера и остатки Telegram
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# ✨ Дать владельцу править запись, возвращать её в работу и видеть её путь
|
||||
|
||||
- **Тип:** feature
|
||||
- **Категория:** Очередь — Три действия живут на экране одной записи, а заводит его список
|
||||
- **Зачем:** С записью нельзя сделать ничего: заголовок ставит одна языковая модель, остановленную возвращает в работу только владелец сервиса в панели, а журнал событий пишется и не читается никем, кроме него же
|
||||
|
||||
Экран одной записи перестаёт быть окном просмотра: с него запись переименовывают,
|
||||
возвращают в работу после отказа и смотрят её путь по рубежам.
|
||||
|
||||
Три действия собраны одной задачей, потому что живут на одном экране и стоят на
|
||||
одном контракте: порознь каждое несло бы свой адрес и свою правку того же экрана.
|
||||
Собраны они после решения владельца 2026-08-15, которым разведены колонки
|
||||
заголовка и имени файла и назначено пространство адресов `/app/`.
|
||||
|
||||
**Переименование.** Колонка заголовка объявлена местом для «пользовательского или
|
||||
сгенерированного» названия, а поставить его человеку нечем: заполняет её один
|
||||
`llm-insights-adapter`. Отсюда же второй вопрос, который решается здесь: что
|
||||
происходит с заголовком, поставленным человеком, когда модель посчитает свой.
|
||||
|
||||
**Возврат в работу.** Паспорт описывает сценарий «отказ на середине» и кончает
|
||||
его тем, что владелец записи узнаёт о неудаче. Дальше пусто: разовый сбой
|
||||
`ffmpeg` оставляет запись остановленной, пока владелец сервиса не откроет панель.
|
||||
Само снятие остановки написано — `entity.Resume` чистит все три сторожа и ставит
|
||||
время входа в рубеж заново. Цена названа прямо: повтор запускает платное
|
||||
распознавание, и запускает его теперь пользователь, а не владелец сервиса —
|
||||
значит у возвратов нужен предел, и его величину выбирает эта задача.
|
||||
|
||||
**Путь записи.** Журнал событий заполняется на смену рубежа, остановку и снятие
|
||||
остановки, а читается только в панели: `architecture.md` говорит про него прямо,
|
||||
что «экрана у него пока нет». Владельцу записи он нужен там, где карточка
|
||||
отвечает «остановлена»: без пути «встала сразу» неотличимо от «висела два часа».
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- `PATCH /app/audiorecords/{id}` — правка заголовка, и только его;
|
||||
- `POST /app/audiorecords/{id}/resume` — возврат остановленной записи в работу;
|
||||
- `GET /app/audiorecords/{id}/events` — события своей записи по времени;
|
||||
- предел числа возвратов и место, где он считается: колонка записи либо журнал
|
||||
событий;
|
||||
- ответ карточки записи — признак того, можно ли вернуть запись в работу сейчас;
|
||||
- шаг конвейера, кладущий посчитанный заголовок: признак того, что заголовок
|
||||
поставлен человеком;
|
||||
- экран одной записи из `records-list-screen`: три действия и показ пути;
|
||||
- перевод рубежей и причин остановки в текст для человека — тот же словарь, что
|
||||
на карточке;
|
||||
- спека `pipeline` — возврат в работу нормирован там со стороны панели;
|
||||
спека `storage` — журнал событий описан там как канал владельца сервиса;
|
||||
правка записи её владельцем не нормирована нигде.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- Заголовок правится владельцем и переживает перезагрузку экрана, посчитанный
|
||||
его не затирает, а пустой возвращает показ по имени файла отправителя. Оракул
|
||||
— три теста: правка и чтение карточки; шаг расчёта заголовка по записи с
|
||||
правленым заголовком; правка пустым значением и чтение списка.
|
||||
- Заголовок ограничен длиной и очищен от управляющих знаков — теми же правилами,
|
||||
какими приём чистит имя файла. Оракул — тест на строке сверх предела и со
|
||||
знаками управления.
|
||||
- Остановленная запись возвращается в работу с сохранённого рубежа с очищенными
|
||||
сторожами, неостановленная отвечает отказом, а возвраты сверх предела — тоже,
|
||||
и запись остаётся остановленной. Оракул — три теста: возврат записи с
|
||||
накопленными отказами и признаком прежнего захвата, затем захват с того же
|
||||
рубежа; возврат записи в работе; возвраты сверх предела.
|
||||
- Владелец видит события своей записи по времени, и машинного текста отказа в
|
||||
них нет: событие несёт причину остановки, а не сообщение зависимости. Оракул —
|
||||
два теста: запись, прошедшая два рубежа и остановку; остановленная запись с
|
||||
текстом ошибки в колонке.
|
||||
- Чужая запись на всех трёх адресах отвечает тем же, чем несуществующая, — и
|
||||
кодом, и телом. Оракул — тест на двух учётных записях, по разу на каждый
|
||||
адрес.
|
||||
|
||||
## Рамки
|
||||
|
||||
Правку прочих полей записи не заводим: меняется один заголовок. Краткое описание
|
||||
и темы остаются за языковой моделью — их правка руками это отдельное решение,
|
||||
которого никто не принимал. Панель владельца сервиса остаётся как есть: она
|
||||
возвращает записи без предела, потому что деньгами распоряжается он. Правил, по
|
||||
которым отказ отличается от приговора, не трогаем — это
|
||||
`failure-verdict-vs-retry`. Событий не добавляем и журнал не переписываем:
|
||||
показываем записанное.
|
||||
|
||||
Берётся после `records-list-screen` — экран одной записи заводит она.
|
||||
Reference in New Issue
Block a user