tasks: два дефекта из ревью tvdb-title-locale взяты в спринт
- metadata-title-sanitize: название из метабазы подставляется в план мимо санитизации и уезжает в имя каталога дословно - long-title-to-review: имя длиннее ~237 байт роняет раскладку в failed вместо отправки на ревью
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# 🐞 Отправлять на ревью раздачу с непомещающимся именем вместо отказа
|
||||
|
||||
- **Тип:** fix
|
||||
- **Категория:** Ядро продукта
|
||||
- **Зачем:** название длиннее ~237 байт роняет раскладку в failed с текстом системной ошибки: пользователь видит «file name too long» вместо карточки ревью, где это чинится подсказкой
|
||||
- **Теги:** sprint:2026-08-06
|
||||
|
||||
Длина компонента пути ограничена файловой системой (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](../../conventions/errors.md) — перевод доменной ошибки на внешней
|
||||
границе.
|
||||
- Проверка длины стоит **до** первой операции с файловой системой. **Оракул:**
|
||||
чтение диффа на ревью; тест на пустоту каталога цели его подтверждает.
|
||||
|
||||
## Рамки
|
||||
|
||||
Обрезать или переименовывать название самостоятельно нельзя — это решение
|
||||
человека, у него для этого есть подсказка на ревью. Предел длины зависит от
|
||||
файловой системы; зашивать 255 как универсальную константу не стоит, но и
|
||||
выяснять предел у ядра в рантайме ради этой задачи не требуется — достаточно
|
||||
консервативного значения с объяснением, откуда оно.
|
||||
Reference in New Issue
Block a user