688cb54f26
Решение владельца по #520 (эпик #497 итерация 5): при повторном overflow реактивная рекавери ДОЛЖНА иметь право резать бюджет реплея ниже явно настроенного окна — «чат не должен кирпичиться на overflow» это ИНВАРИАНТ реактивной ветки, а настроенное окно — заявление о ёмкости модели, не обещание о размере реплея; когда провайдер 400-ит, реальность бьёт конфиг. (Не конфликтует с #510 Опция A: та про верхнюю границу НОРМАЛЬНОГО пути — уважать конфиг, пока он влезает.) - Пол эскалации: max(scaled, min(REPLAY_MIN_FLOOR_TOKENS, floor(0.5×threshold))). Было min(REPLAY_MIN_FLOOR_TOKENS, threshold) — жёсткий пол на настроенном бюджете. Теперь БОЛЬШОЕ окно эскалирует НИЖЕ настроенного бюджета до фикс. пола 8k; МАЛОЕ окно (0.5×threshold < 8k) падает до floor(0.5×threshold) — минимум старый 0.5× cut (никогда не хуже, чем раньше), но и не поднимается выше самого бюджета. REPLAY_MIN_FLOOR_TOKENS=8k без изменений (константа уже была). Сброс k на чистом ходу сохранён (счётчик replayOverflowCount не пишется на чистом финализе). - Наблюдаемость: warn-лог (настроенный бюджет не влезает, реплей ниже него, уровень k) + метка турна metadata.replayBelowConfiguredBudget=true — только когда реплей реально ниже настроенного бюджета (не на нормальном in-budget реплее). - Тесты: перепиновка «не раздувает малый бюджет выше себя» (теперь МОЖЕТ резать ниже, Опция B) в обоих spec; новый тест эскалации ниже бюджета (окно 8000→бюджет 5600, k=1→2800, сходимость к полу, сброс на чистом ходу) + большое окно (140k→8k ступенями); тест метки метадаты. Мутации: пол=бюджет краснит below-budget тесты, снятие метки краснит observability-тест. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>