Проверено исполнением, оба главных пункта закрыты.
P0-1, восстановление после отказа авторизации: выбран самый честный из
предложенных вариантов — снятие отметки по событию починки, а не по
таймеру. HealthTracker подписывается на EVENT_ACCOUNT_ADDED и
EVENT_ACCOUNT_AUTH_CHANGED. Проверено: профиль с AUTH_REQUIRED после
события возвращается в строй без ручного вмешательства.
P0-2, проверка моделей. Выдуманная модель отклоняется; базовое имя
gemini-3.7-flash принимается (поправка учтена); склеенное
gemini-3.1-pro-high тоже. Главное — при ПУСТОМ кэше выдумка больше не
проходит: молчаливое согласие устранено.
P0-3, ручное обновление списка моделей: действие refresh_models плюс
кнопка в клиенте.
Исправлено при слиянии:
1. Блокировка файла состояния была переведена с неблокирующей на
БЕСКОНЕЧНО блокирующую. Исходный вариант был неверен — при неудаче
исключение проглатывалось и запись шла без блокировки, — но
бесконечное ожидание хуже: на Unix flock(LOCK_EX) висит вечно, и один
застрявший держатель подвесил бы приложение целиком. Впереди
Linux-сервер. Ожидание ограничено 5 секундами, дальше честный отказ.
Проверено: 6 потоков по 5 записей — 0.11 с, ошибок нет.
2. Действие refresh_models не было занесено в контракт. Ровно тот дрейф,
ради предотвращения которого контракт и существует. Контракт поднят
до 1.3, действий стало девятнадцать.
Тесты: 370 passed, ruff чисто.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>