# 🐞 Отправлять на ревью раздачу с непомещающимся именем вместо отказа

- **Тип:** fix
- **Категория:** Ядро продукта — тот же урожай ревью и тот же стык «название → компонент пути»: вторая после первой дешевле
- **Зачем:** название длиннее ~237 байт роняет раскладку в failed с текстом системной ошибки: пользователь видит «file name too long» вместо карточки ревью, где это чинится подсказкой

Длина компонента пути ограничена файловой системой (255 байт на имя, минус
расширение и суффиксы — практический потолок около 237). Название такой длины
приходит из метабазы или из распознавания штатно: длинные оригинальные заголовки
и сериалы с подзаголовком в имя укладываются не всегда.

Сегодня это не проверяется нигде: раскладка доходит до `link(2)`, получает от ядра
`file name too long`, и задача уходит в `failed` с текстом системной ошибки в
поле ошибки. Для владельца это тупик — состояние терминальное, а причина написана
языком ядра.

Правильный исход — **review**: там человек правит название подсказкой, ровно как
при коллизии цели. Коллизия уже так и обрабатывается, то есть путь в системе
есть и его надо переиспользовать, а не изобретать.

Провенанс: ревью изменения `tvdb-title-locale`, находка AD4 —
[отчёт триажа](../../openspec/changes/archive/2026-08-07-tvdb-title-locale/review/report.md).
Понижена там не по доказательности, а по принадлежности к диффу: путь этим
изменением не тронут.

## Воспроизведение

Оракул из отчёта: подать раздачу, у которой имя целевого файла складывается в
250 байт.

```
n=250 → Apply err=… file name too long, results=0
```

Наблюдаемо: задача в состоянии `failed`, в поле ошибки — текст системной ошибки,
ни одной ссылки не создано, карточки ревью нет.

Ожидаемо: задача в `review` с названной причиной «имя не помещается», раскладка
не начата, подсказка человека чинит случай.

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

- `internal/layout` — проверка длины компонента до `link(2)` и доменная ошибка
  вместо системной;
- `internal/worker` — ветка перевода задачи в `review` по этой ошибке, рядом с
  существующей веткой коллизии цели;
- `openspec/specs/file-layout/spec.md` — требование о непомещающемся имени;
  `state-reconciliation` — если переход в `review` заказывается там;
- текст причины в карточке ревью: веб-UI и Telegram показывают её человеку.

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

- Раздача с именем в 250 байт уходит в `review` с доменной причиной, а не в
  `failed` с текстом ядра. **Оракул:** тест на временном каталоге прогона,
  воспроизводящий случай из «Воспроизведения», — проверяет состояние задачи и
  код причины.
- Ни одна ссылка не создана до отказа: частичной раскладки батча не остаётся.
  **Оракул:** тот же тест — проверяет, что каталог цели пуст.
- Причина, показанная человеку, не содержит текста системной ошибки. **Оракул:**
  утверждение теста на текст причины плюс конвенция
  [errors.md](../../docs/conventions/errors.md) — перевод доменной ошибки на внешней
  границе.
- Проверка длины стоит **до** первой операции с файловой системой. **Оракул:**
  чтение диффа на ревью; тест на пустоту каталога цели его подтверждает.

## Рамки

Обрезать или переименовывать название самостоятельно нельзя — это решение
человека, у него для этого есть подсказка на ревью. Предел длины зависит от
файловой системы; зашивать 255 как универсальную константу не стоит, но и
выяснять предел у ядра в рантайме ради этой задачи не требуется — достаточно
консервативного значения с объяснением, откуда оно.
