# 🐞 Не затирать сохранённое вложение более бедным ответом

- **Тип:** fix
- **Категория:** Очередь — Заведена урожаем ревью и встала в конец машинально: место в плане стройки назначает человек.
- **Зачем:** Пустой ответ распознавателя сохранённое больше не стирает, а более короткий — стирает: вложение заменяется, и пересчитать архив становится нечем.
- **Теги:** review-2026-08-15

Сохранённый ответ провайдера заменяется только тем, что не беднее прежнего.

Задача `remove-telegram-intake` закрыла половину этого класса: текст и структура
реплик пустым больше не затираются, и норма записана требованием спеки хранилища
«Пустой результат не кладётся поверх сохранённого». Сырой ответ провайдера
защищён только от **пустого** — условием на непустую длину; ответ не пустой, но
короче прежнего, проходит это условие и заменяет сохранённое.

Цена именно у вложения самая высокая. Оно единственное, из чего архив
пересчитывается без повторной оплаты: решение хранить его дословно записано
[ADR-2026-08-14-provider-payload-stored-verbatim](../../docs/adr/ADR-2026-08-14-provider-payload-stored-verbatim.md),
и обещание там прямое — «когда мы научимся размечать говорящих, архив
пересчитается из сохранённого без единого рубля».

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

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

Довести запись до сохранённого ответа, вернуть её на рубеж отправленной и
опросить снова, отдав со стороны провайдера ответ короче прежнего. Вложение
заменяется на короткое; прежнего не остаётся нигде. Оракул того же класса для
пустого ответа уже написан — `TestEmptySecondAnswerKeepsArchivedText`, — и этот
пишется по его образцу.

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

- коллекция `recognitions`, колонка `payload` — сохранённый ответ провайдера вложением;
- спека `storage`, требование «Пустой результат не кладётся поверх сохранённого»
  — норма расширяется с пустого на «беднее прежнего»;
- определение «беднее»: длина в байтах либо число реплик разбора — выбирается
  задачей.

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

- Более короткий ответ сохранённое вложение не заменяет. Оракул: проверка по
  образцу `TestEmptySecondAnswerKeepsArchivedText` — второй опрос отдаёт ответ
  короче, сохранённое вложение остаётся прежним, и проверка убеждается, что до
  второго обращения дело дошло.
- Более полный ответ сохранённое заменяет. Оракул: та же проверка наоборот —
  второй ответ длиннее, вложение обновилось.
- Норма записана требованием спеки, а не только кодом. Оракул: правленое
  требование `storage` и ссылка на него из кода.

## Рамки

Найдено прогоном ревью задачи `remove-telegram-intake` 2026-08-15, враждебный
проход, секция свойств без построенного пути: пустой случай доказан падающим
тестом и закрыт, этот — выведен из того же кода и оракула не имеет. Тексту и
структуре реплик защита уже стоит, трогать их не надо.
