спека: заведён change large-release-recognition для больших раздач
- контракт с моделью переводится на адресацию файла номером строки списка, усечение промпта снимается, лимиты уходят в конфиг - раскладка показывает все файлы раздачи, покрытие плана блокирует авто только при непокрытом видеофайле
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
## 1. Признак обрыва генерации из LLM
|
||||
|
||||
- [x] 1.1 Довести `finish_reason` до вызывающего: добавить поле в `llm.Response`, заполнить его в `internal/llm/openai.go` (сейчас разбирается и выбрасывается)
|
||||
- [x] 1.2 Тест `internal/llm`: ответ с `finish_reason: "length"` доносит признак обрыва до вызывающего
|
||||
|
||||
## 2. Компактный формат ответа модели
|
||||
|
||||
- [x] 2.1 Добавить `Index` в `recognize.PlanFile` (`i` в JSON), `Src` оставить для запасного формата
|
||||
- [x] 2.2 Переписать схему в `schemaText` (`prompt.go`) под адресацию номером: `i` вместо `src`, явно оговорить, что для ролей `sample`/`ignore`/`extra` номера сезона и серии не нужны, а `notes` — не более пары предложений
|
||||
- [x] 2.3 Поправить шапку списка файлов в `writeFileList`: номер строки — это то, что нужно вернуть в `i`
|
||||
- [x] 2.4 Резолв номера в `validate.go`: при `i` в диапазоне `1..len(in.Files)` заполнять `Src` из своего списка
|
||||
- [x] 2.5 Сохранить приём старого формата: пришёл `src` без `i` — проверять совпадение с реальным файлом торрента, как сегодня
|
||||
- [x] 2.6 Элемент с обоими полями резолвить по `i`; несовпадение присланного `src` с резолвом — причина ревью, а не тихое затирание
|
||||
- [x] 2.7 Отбраковка негодных элементов вместо отказа от плана: номер вне диапазона, повторная адресация файла (побеждает первый элемент), элемент без номера и пути — элемент отбрасывается, план живёт, каждая отбраковка названа причиной; план без единого годного файла считается неразобранным
|
||||
- [x] 2.8 Убедиться, что отбраковка элементов не порождает correction-ретрая (это не ошибка разбора)
|
||||
- [x] 2.9 Тесты `internal/recognize`: резолв номера в путь; номер вне диапазона; дубль адресации; элемент без `i` и `src`; запасной формат с `src`; `i` и `src` вместе — совпадающие и расходящиеся; план, где годных элементов не осталось. Отдельно: резолв не паникует ни на одном входе (`i` = 0, отрицательное, `len+1`, дробное или строковое в JSON, пустой `files[]`, `files[]` длиннее списка раздачи)
|
||||
|
||||
## 3. Порядок списка файлов — свойство узла
|
||||
|
||||
- [x] 3.1 Упорядочивать список файлов по пути внутри `Recognize`, а не у вызывающего: сборки `Input` две — `internal/worker/review.go:126` и `cmd/jellybit/recognize.go:101`
|
||||
- [x] 3.2 Печать промпта и резолв номеров идут по одному и тому же упорядоченному срезу на всех попытках, включая correction-ретрай
|
||||
- [x] 3.3 Тест: `Recognize` с перемешанным `Input` даёт ту же нумерацию, что и с упорядоченным (тест зовёт узел, а не воркер)
|
||||
|
||||
## 4. Лимиты в конфиг
|
||||
|
||||
- [x] 4.1 Добавить `[recognition].max_files` и `[recognition].max_tokens` в `internal/config` с валидацией и дефолтами 500 и 8000
|
||||
- [x] 4.2 Пробросить их в `recognize.Config` на сборке зависимостей (воркер и CLI)
|
||||
- [x] 4.3 Описать обе настройки в `config.example.toml` (назначение, диапазон, единицы) и в `docs/database.md` (настройки с числовым значением)
|
||||
- [x] 4.4 Тест конфига: дефолты применяются, невалидные значения отвергаются
|
||||
|
||||
## 5. Цена попытки не растёт с размером раздачи
|
||||
|
||||
- [x] 5.1 Убрать повторную печать списка файлов из `correctionMessage` (`prompt.go:180`): номера названы в первом сообщении диалога
|
||||
- [x] 5.2 Обрыв ответа по длине — review с причиной «ответ модели обрезан», без повторного запроса ни тем же промптом, ни его вариантом
|
||||
- [x] 5.3 Усечение списка пределом `max_files` — отдельная причина ухода в review; знаменатель покрытия считается по полному числу файлов раздачи, а не по усечённому списку
|
||||
- [x] 5.4 Отказ модели по размеру запроса называть отдельной причиной, а не текстом провайдера
|
||||
- [x] 5.5 Тесты: correction-ретрай не содержит списка файлов и сопоставим по размеру с первой попыткой; обрыв не порождает ни одного повторного запроса (тест считает вызовы фейкового клиента); снятие лимита не умножает число попыток сверх `[llm].max_retries`
|
||||
|
||||
## 6. Свёртка причин и покрытие плана
|
||||
|
||||
- [x] 6.1 Переписать `seriesWarnings` (`validate.go:186`): одна причина на сезон с перечнем недостающих серий вместо строки на каждый разрыв
|
||||
- [x] 6.2 Завести перечень видеорасширений в одном месте рядом с ролями файлов (в проекте такого места сегодня нет) и покрыть его тестом
|
||||
- [x] 6.3 Покрытие плана: число «в плане N из M» показывается, когда покрыты не все файлы; блокирующей причиной становится только непокрытый видеофайл, файлы-спутники в решение auto/review не входят
|
||||
- [x] 6.4 Тесты: сезон с тремя дырами даёт одну причину; непокрытый видеофайл уводит в review; раздача, где не покрыты только `.nfo` и скриншоты, авто-раскладку не теряет
|
||||
|
||||
## 7. Список файлов раздачи рядом с планом
|
||||
|
||||
- [x] 7.1 Миграция `0012`: колонка со списком файлов раздачи (JSON: путь и размер) в таблице `recognition`
|
||||
- [x] 7.2 Обновить ER-схему в `docs/database.md` — иначе краснеет шаг `canon` гейта
|
||||
- [x] 7.3 Заполнять колонку при создании записи распознавания из того же `Input`, из которого построен план (снимок и `src` плана обязаны происходить из одного среза); читать при рендере страниц загрузки и ревью
|
||||
- [x] 7.4 Записи, созданные до миграции: рендер строит строки по плану и явно называет, что список файлов недоступен и полнота не гарантирована — молчаливой деградации быть не должно
|
||||
|
||||
## 8. Раскладка показывает все файлы
|
||||
|
||||
- [x] 8.1 Развернуть `buildFileRows` (`internal/httpapi/files.go`) на файлы раздачи: план подмешивается по `src`, файл без записи получает пометку «не в плане»; ровно одна строка на файл раздачи
|
||||
- [x] 8.2 Полный ключ сортировки: разложенные (сезон, серия, путь) → файлы плана без цели (`extra`/`sample`/`ignore`, по пути) → файлы вне плана (по пути); пустые `season`/`episode` не поднимают файл в начало списка
|
||||
- [x] 8.3 Отобразить пометку «не в плане» и строку о недоступном списке файлов в шаблонах раскладки в единой дизайн-системе
|
||||
- [x] 8.4 Колонка `#` в `web/templates/partials/layout_widget.html:8` печатает порядковый номер строки — привести её к номеру адресации из списка распознавания либо убрать: расхождение сделает разбор ошибок адресации ложным
|
||||
- [x] 8.5 Тесты `internal/httpapi`: файл вне плана присутствует в строках без целевого пути; порядок строк не зависит от порядка `plan.Files` (тест с перемешанным планом); запись без сохранённого списка файлов даёт строку о недоступности
|
||||
|
||||
## 9. Проверка на живом кейсе
|
||||
|
||||
- [ ] 9.1 `task gate` зелёный
|
||||
- [ ] 9.2 Прогнать распознавание раздачи «Отчаянные домохозяйки» (180 файлов) на рабочем эндпоинте: план покрывает все файлы, причины ревью читаются с одного взгляда, раскладка упорядочена по сезонам
|
||||
- [ ] 9.3 Сверить фактический размер ответа модели с `max_tokens`: подтвердить, что запаса хватает, и при необходимости поправить дефолт
|
||||
- [ ] 9.4 Проверить, что сырой ответ модели и ключ LLM не попадают в лог (`docs/conventions/logging.md`), а отброшенные элементы и файлы вне плана видны числом в причинах
|
||||
Reference in New Issue
Block a user