Files
jellybit/openspec/changes/archive/2026-08-10-long-title-to-review/specs/file-layout/spec.md
T
av b9f0929d0c layout: непомещающееся целевое имя уводит задачу в review вместо failed
- предел длины компонента (255 байт) проверяется в BuildLinks до первой
  операции с ФС: ни каталога, ни ссылки при отказе не создаётся
- причина пустого предпросмотра считается на показе (ReviewData.PreviewError)
  и печатается в панели действий и в карточке Telegram: у задачи без
  записанной причины взять её больше неоткуда
2026-08-10 12:16:44 +03:00

71 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## ADDED Requirements
### Requirement: Непомещающееся целевое имя уходит в review
Система SHALL отклонять раскладку целиком, если хотя бы один компонент целевого
пути (папка тайтла, папка сезона, имя файла с расширением и суффиксами) длиннее
предела, и SHALL переводить задачу в `review` с доменной причиной, а не в
`failed`. Проверка SHALL выполняться до первой операции с файловой системой: ни
каталога, ни ссылки при отказе не создаётся. Причина SHALL нести собственный код,
отличный и от кода коллизии, и от общего кода отказа построения плана, а
человекочитаемый текст SHALL называть непомещающийся компонент и НЕ SHALL
содержать текста системной ошибки.
Предел SHALL меряться в **байтах** UTF-8-представления имени, а не в символах:
кириллическое название упирается вдвое раньше латинского той же длины в знаках.
Величина — **255 байт** (`NAME_MAX` у ext4/xfs/btrfs); она фиксирована и у ядра не
выясняется, потому что раскладка обязана отказать до обращения к диску. На
файловой системе с меньшим пределом остаётся сегодняшний исход — отказ ядра и
`failed`; это осознанный остаток, а не пробел.
Проверка длины SHALL выполняться **после** проверки нахождения пути под корнем
библиотеки: путь, вышедший за песочницу, SHALL отклоняться как выход за
библиотеку, иначе находка безопасности спряталась бы за косметической причиной.
Самостоятельно обрезать или переименовывать название система НЕ SHALL — это
решение человека.
#### Scenario: Слишком длинное имя файла уходит в review
- **GIVEN** распознавание даёт название, из которого имя целевого файла
складывается длиннее 255 байт
- **WHEN** выполняется раскладка
- **THEN** задача переходит в `review` с причиной «имя не помещается», ни один
каталог и ни одна ссылка не созданы, а текст системной ошибки человеку не
показан
#### Scenario: Предел меряется в байтах
- **GIVEN** два названия одинаковой длины в знаках — латинское и кириллическое
- **WHEN** строятся целевые пути
- **THEN** кириллическое отклоняется вдвое раньше латинского, а граница
проходит между 255 и 256 байтами
#### Scenario: Слишком длинное имя папки тайтла уходит в review
- **GIVEN** название укладывается в имя файла, но папка тайтла с годом и
provider-тегом длиннее предела
- **WHEN** выполняется раскладка
- **THEN** задача переходит в `review` с той же причиной, каталог тайтла не
создан
#### Scenario: Выход за библиотеку важнее длины
- **GIVEN** целевой путь одновременно выходит за корень библиотеки и длиннее
предела
- **WHEN** строятся целевые пути
- **THEN** отказ называет выход за библиотеку, а не длину имени
#### Scenario: Подсказка человека чинит случай
- **GIVEN** задача в `review` с причиной «имя не помещается»
- **WHEN** человек задаёт название короче и применяет раскладку заново
- **THEN** раскладка проходит штатно и задача переходит в `done`
#### Scenario: Унаследованная база в предел помещается всегда
- **GIVEN** база имени унаследована от живой папки-якоря по правилу сходимости
- **WHEN** строятся имена файлов внутри этой папки
- **THEN** они помещаются в предел, потому что папка-якорь лежит на диске и уже
не длиннее предела, а хвост имени файла не длиннее хвоста имени папки