## Why Раздача «Отчаянные домохозяйки» — один торрент на 8 сезонов, 180 файлов — распозналась негодно: в план попало ровно 100 файлов, потому что промпт усекает список файлов жёсткой константой `defaultMaxFiles = 100`. Остальные 80 файлов модель не видела, в интерфейсе они не показаны никак, а причины ревью распухли до сорока строк «пропуск серий в сезоне N». Порядок строк раскладки в UI — тот, в каком их вернула модель, то есть вперемешку по сезонам. Просто поднять лимит нельзя: каждый элемент плана обязан нести дословную копию пути (~70 токенов на кириллице), 180 файлов дают ~15k выходных токенов при нашем же потолке `defaultMaxTokens = 4000`. Обрыв генерации при этом неотличим от мусора — `finish_reason` из ответа разбирается, но не проверяется, и обрыв уходит в три бессмысленных ретрая с полным промптом. Вход тут не проблема (12–15k токенов промпта — ничто для современной модели), проблема целиком на стороне ответа. ## What Changes - **BREAKING (контракт с моделью, не с пользователем)**: элемент `files[]` в ответе LLM адресует файл номером из напечатанного нами списка (`i`), а не дословной копией пути. `src` заполняем сами резолвом индекса. Выход падает с ~85 до ~14 токенов на файл; путь, которого нет в торренте, становится невыразимым. Старый формат с `src` принимается как запасной, чтобы привычка модели не давала ретрая на пустом месте. - Негодный элемент ответа (номер вне диапазона, повторная адресация файла, элемент без номера и пути) отбрасывается поимённой причиной, а не роняет весь план: иначе одна ошибка в одном из 180 элементов воспроизводит ровно тот отказ, против которого change и затевается. Элемент, несущий и номер, и путь, резолвится по номеру, а расхождение между ними становится причиной ревью — бесплатной сверкой против сдвига адресации. - Жёсткое усечение списка файлов снимается: модели показываются все файлы раздачи. `max_files` и `max_tokens` выводятся в `[recognition]` с дефолтами 500 и 8000 — сейчас оба зашиты в код и на проде не крутятся. - Повторная попытка перестаёт переприсылать список файлов: номера названы в первом сообщении диалога, и цена неудачного распознавания больше не растёт вместе с числом попыток. - Порядок файлов, напечатанных в промпте, детерминирован и совпадает с порядком резолва индексов — иначе повторное распознавание из ревью сдвинет привязку. - Обрыв генерации (`finish_reason` = `length`) распознаётся как отдельная причина ухода в review и не ретраится тем же промптом. - В раскладке видны все файлы торрента: попавшие в план — с ролью и целью, не попавшие — отдельной строкой. Молчаливый пропуск файла моделью перестаёт быть невидимым. Загрузки, распознанные до этого изменения, списка файлов не имеют — и виджет говорит об этом прямо, вместо того чтобы показать план как полный перечень. - Строки раскладки упорядочены полностью — разложенные по (сезон, серия, путь), затем файлы плана без цели, затем файлы вне плана, — а не по порядку ответа модели. - Причины ревью по нумерации серий сворачиваются: перечисление недостающих серий по сезону одной строкой и сводка покрытия плана вместо строки на каждый разрыв. Покрытие показывается, когда покрыты не все файлы, но блокирует авто-раскладку только непокрытый видеофайл: иначе опущенный моделью `.nfo` выключил бы авто-путь на типовых раздачах. Отсюда же следствие для решения: `Reasons` перестают быть однородным списком «причин не-авто» — в них появляются информационные строки, и решение считается по блокирующим причинам, а не по длине списка. Вне объёма: детерминированный разбор сезона/серии из имён файлов и сверка с ответом модели — следующий change (этап B). Здесь модель по-прежнему единственный источник разметки файлов. ## Capabilities ### New Capabilities Нет. ### Modified Capabilities - `recognition`: контракт ответа LLM (адресация файла индексом вместо дословного пути), отказ от усечения списка файлов и вывод лимитов в конфиг, обрыв генерации как отдельная причина review, форма причин по нумерации серий, решение auto/review считается по блокирующим причинам (в `Reasons` появились информационные строки). - `web-ui`: раскладка показывает все файлы раздачи, включая не попавшие в план, и упорядочена по сезону и серии. ## Impact - `internal/recognize`: `prompt.go` (нумерация и печать списка, схема в промпте, correction-сообщение без повторной печати списка), `validate.go` (резолв индекса вместо поиска пути, отбраковка негодных элементов, свёртка предупреждений, покрытие по видеофайлам), `recognize.go` (упорядочивание входного списка в самом узле, лимиты, обработка обрыва). - `internal/llm`: `finish_reason` доводится до вызывающего в `Response`. - `internal/config`: `[recognition].max_files`, `[recognition].max_tokens`; `config.example.toml` и `docs/database.md` (настройки с числовым значением). - `internal/httpapi/files.go` и `web/templates/partials/layout_widget.html`: сортировка, файлы вне плана, колонка `#` (номер строки виджета обязан совпасть с номером адресации либо исчезнуть), строка о недоступном списке файлов. - Хранилище: миграция `0012` — колонка со списком файлов раздачи в таблице `recognition`, и правка ER-схемы в `docs/database.md` (без неё краснеет шаг `canon` гейта). - Совместимость: сохранённые планы в БД хранят `src` путями и не меняются. Записи, созданные до миграции, списка файлов не имеют — виджет называет это явно. Уже применённые раскладки не затрагиваются. - Риск: ошибка модели в индексе становится тихой (валидный, но не тот файл). Смягчение — требование уникальности индексов и сводка покрытия в причинах; перекрёстная проверка разметки приходит в этапе B.