layout: непомещающееся целевое имя уводит задачу в review вместо failed
- предел длины компонента (255 байт) проверяется в BuildLinks до первой операции с ФС: ни каталога, ни ссылки при отказе не создаётся - причина пустого предпросмотра считается на показе (ReviewData.PreviewError) и печатается в панели действий и в карточке Telegram: у задачи без записанной причины взять её больше неоткуда
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# Причина, по которой человек не видит плана, считается на показе, а не читается из состояния
|
||||
|
||||
- **Дата:** 2026-08-10
|
||||
- **Источник:**
|
||||
[openspec/changes/archive/2026-08-10-long-title-to-review/design.md](../../openspec/changes/archive/2026-08-10-long-title-to-review/design.md),
|
||||
Решение 6 и раздел `Risks / Trade-offs`; отчёт триажа того же change,
|
||||
находка 1
|
||||
|
||||
## Контекст
|
||||
|
||||
Проверка длины целевого имени встала в `layout.BuildLinks` — туда же, где
|
||||
собираются оба предпросмотра экрана ревью. Это дало даром совпадение показанного
|
||||
с применённым, но и вторую половину: непомещающееся имя обнуляет предпросмотр, а
|
||||
без предпросмотра экран прячет команду «Применить».
|
||||
|
||||
Первым решением панель действий брала текст из `error_msg` — причины, записанной
|
||||
при последнем переходе. Ревью показало, что на самом частом входе этого поля
|
||||
нет вовсе: задача, пришедшая в `review` из-за отсутствия матча, попадает туда с
|
||||
пустой причиной и до раскладки не доходит. Замер триажа на двух деревьях:
|
||||
|
||||
```
|
||||
до изменения: предпросмотр строится, «Применить» доступна,
|
||||
применение доводит до failed с текстом ядра
|
||||
после: предпросмотр пуст, команды нет, причины нет —
|
||||
экран печатает «Подтверди источник», хотя источник ни при чём
|
||||
```
|
||||
|
||||
То есть изменение, чья цель — «человек узнаёт причину», на этом входе
|
||||
диагностируемость ухудшало.
|
||||
|
||||
## Решение
|
||||
|
||||
**Причина отказа считается в момент показа и отдаётся транспорту значением
|
||||
(`worker.ReviewData.PreviewError`); записанная в состоянии используется только
|
||||
когда посчитанной нет.**
|
||||
|
||||
Цитата из `design.md`, Решение 6:
|
||||
|
||||
> Оба предпросмотра ревью (карточка и строка источника) строят пути тем же
|
||||
> `BuildLinks`, поэтому вердикт на показе и вердикт на применении совпадают по
|
||||
> устройству, а не по договорённости.
|
||||
|
||||
Отсюда следует и обратное: раз вердикт считается на показе, там же считается и
|
||||
его причина. Посчитанная предпочитается записанной по двум причинам сразу:
|
||||
записанной может не быть вовсе, а после смены источника она уже про другой план — команды,
|
||||
меняющие эффективный источник, поля ошибки не чистят.
|
||||
|
||||
**Чтение при этом состояние не двигает.** Построение предпросмотра остаётся без
|
||||
побочных эффектов; причина уходит наружу возвращаемым значением.
|
||||
|
||||
Это второй случай одного класса за день. Первый —
|
||||
[ADR-2026-08-10-sanitize-at-every-entry](ADR-2026-08-10-sanitize-at-every-entry.md):
|
||||
гарантия, поставленная на запись, не покрывает то, что записано раньше. Здесь она
|
||||
не покрывает то, что не записано вовсе.
|
||||
|
||||
## Рассмотренные варианты
|
||||
|
||||
- **Записывать причину в состояние при построении предпросмотра.** Отвергнуто:
|
||||
чтение начало бы двигать состояние. Запрет уже стоял в коде отдельным
|
||||
комментарием — предпросмотр не переводит задачу в `review` при рассинхроне
|
||||
папок, — и заводить исключение ради текста на экране значило бы снять правило.
|
||||
- **Оставить как есть, записав остаток сценарием спеки.** Отвергнуто на
|
||||
чекпоинте: регресс диагностируемости дошёл бы до боевого окружения на самом
|
||||
частом входе.
|
||||
- **Печатать причину только в баннере состояния, панель не трогать.** Отвергнуто:
|
||||
баннер показывает записанное и на этом входе пуст ровно так же.
|
||||
|
||||
## Цена
|
||||
|
||||
Причина живёт в двух местах — записанная в состоянии и посчитанная на показе, — и
|
||||
порядок между ними держится на ревью, а не на типе. Взамен экран ревью объясняет
|
||||
отсутствие команды всегда, а не только когда причину успели записать, и
|
||||
объяснение относится к текущему плану, а не к прошлому.
|
||||
|
||||
Побочно: тот же текст может оказаться и в баннере, и в панели, когда записанная
|
||||
причина совпала с посчитанной. Дубль признан приемлемым — он честен, а
|
||||
код, который его снимал бы, дороже.
|
||||
Reference in New Issue
Block a user