- каталог задач переехал в tasks/ в корне, спринт упразднён — приоритет теперь порядок строк в BACKLOG.md, четыре задачи набора вернулись в беклог - гейт: путь docs.py переведён на av-dev-docs вместо снесённого av-dev-pm, добавлены шаги tasks.py check и openspec.py check - относительные ссылки внутри задач и ссылки из docs/ на задачи починены
73 lines
5.5 KiB
Markdown
73 lines
5.5 KiB
Markdown
# 🐞 Отправлять на ревью раздачу с непомещающимся именем вместо отказа
|
||
|
||
- **Тип:** 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 как универсальную константу не стоит, но и
|
||
выяснять предел у ядра в рантайме ради этой задачи не требуется — достаточно
|
||
консервативного значения с объяснением, откуда оно.
|