docs(task): A23 — самовосстановление профилей и честная проверка моделей
Написано под схему владельца: Flash реализует, Pro проводит аудит. Пункт P0-4 — чек-лист для второго прохода, составлен из дефектов, которые уже проходили мимо первого. P0-1: mark_auth_required ставит состояние без срока истечения, а маршрутизация пропускает нездоровый профиль — успеха не случится, отметка не снимется никогда. Подтверждено: после починки авторизации в A22 все шесть профилей Antigravity остались помечены, ревьюер снимал отметки вручную. P0-2: do_set_model пропускает проверку целиком при пустом кэше моделей. Проверено — выдуманная модель записалась в конфигурацию владельца. Отсутствие данных трактуется как разрешение. P0-3: ручного обновления списка моделей нет с A18. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
45fd01a15e
commit
9c6a4e8f6d
1 changed files with 158 additions and 0 deletions
158
agents/inbox/2026-08-24-A23-recovery-and-model-validation.md
Normal file
158
agents/inbox/2026-08-24-A23-recovery-and-model-validation.md
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# Задание A23: самовосстановление профилей и честная проверка моделей
|
||||
|
||||
## Дата поступления
|
||||
2026-08-24
|
||||
|
||||
## База
|
||||
Проверочный HEAD на момент выдачи: **`45fd01a`**.
|
||||
|
||||
## Ветка
|
||||
`antigravity/recovery-and-validation`
|
||||
|
||||
## Порядок исполнения
|
||||
|
||||
Задание выполняется в два прохода, как прошлый раз:
|
||||
|
||||
1. **Flash** реализует.
|
||||
2. **Pro** проводит аудит и правит найденное.
|
||||
|
||||
Схема себя оправдала: в A22 второй проход поймал ложную инструкцию в веб-клиенте. Пункт **P0-4** написан специально для аудитора — он же приёмка.
|
||||
|
||||
---
|
||||
|
||||
## Порядок работы с git
|
||||
|
||||
```
|
||||
cd <каталог репозитория>; git fetch origin --prune; git status
|
||||
git checkout main; git pull --ff-only origin main
|
||||
git checkout -b antigravity/recovery-and-validation
|
||||
git commit -m "..." <- сначала коммит
|
||||
git push -u origin antigravity/recovery-and-validation
|
||||
```
|
||||
|
||||
В `main` напрямую не пушить: работа A20 ушла туда минуя ревью. В конце — push и проверка `git log --oneline -1 origin/antigravity/recovery-and-validation`, `git status` чистый.
|
||||
|
||||
---
|
||||
|
||||
## Что принято по A22
|
||||
|
||||
Задача решена, все три доказательства получены проверкой ревьюера:
|
||||
|
||||
```
|
||||
1. agy models через профиль -> 14 моделей, включая gemini-3.1-pro-high
|
||||
2. adapter.invoke(ag-w1) -> модель ответила «ОК»
|
||||
3. route_request -> переключение codex-worker-1 -> ag-w1, ответ получен
|
||||
```
|
||||
|
||||
Реализация аккуратная: видимая консоль на Windows через `CREATE_NEW_CONSOLE`, терминалы на Linux, `HOMEDRIVE` выставляется корректно. Пересохранение профиля не трогает глобальный `~/.gemini` — проверено.
|
||||
|
||||
Исправлено ревьюером при слиянии: инструкция в веб-клиенте вела на **несуществующий** `launcher/main.py`; тест проверял дословную формулировку и падал при её правке.
|
||||
|
||||
## Отменённое утверждение — прочитать обязательно
|
||||
|
||||
`agents/inbox/2026-08-24-CORRECTION-gemini-model-names.md`.
|
||||
|
||||
Ревьюер четырежды написал, что `gemini-3.7-flash` «у провайдера не существует». **Это неверно.** Модель настоящая, уровень усилия у неё — отдельный параметр. Дефект был в коде: `_model_supported_efforts` вызывала обнаружение без профиля, карта усилий оставалась пустой, подстановка уровня по умолчанию не срабатывала. Исправлено, `gemini-3.7-flash` работает без указания усилия.
|
||||
|
||||
**Конфигурацию владельца по этому поводу не править.**
|
||||
|
||||
---
|
||||
|
||||
## P0-1. Отказ авторизации — состояние без выхода
|
||||
|
||||
Проверено исполнением, дефект подтверждён.
|
||||
|
||||
`health_tracker.mark_auth_required` (строка 376) ставит `overall_state = AUTH_REQUIRED` и **не задаёт ни срока истечения, ни `reset_at`**:
|
||||
|
||||
```python
|
||||
def mark_auth_required(self, profile_id, reason=None):
|
||||
record.overall_state = AUTH_REQUIRED
|
||||
record.last_error = reason
|
||||
self._save_state()
|
||||
```
|
||||
|
||||
Сравните с квотой: у неё `reset_at` есть, и состояние само рассасывается.
|
||||
|
||||
Дальше замыкается круг: маршрутизация **пропускает** нездоровый профиль (`skipped_unhealthy`), значит успешного вызова по нему не случится, значит `mark_success` не вызовется, значит состояние не снимется. **Никогда.**
|
||||
|
||||
Это не теория. После того как A22 починил авторизацию, все шесть профилей Antigravity остались помечены и пропускались — ревьюер вручную вызывал `clear_cooldown`, иначе третье доказательство не прошло бы. Владелец такой команды не знает и знать не должен.
|
||||
|
||||
**Требуется путь наружу.** Варианты на выбор, обосновать в отчёте:
|
||||
|
||||
- срок истечения у `AUTH_REQUIRED`, как у квоты;
|
||||
- периодическая перепроверка помеченных профилей — редкая, чтобы не жечь квоту;
|
||||
- снятие отметки при событии, которое достоверно означает починку: успешный вход через мастер, обновление учётных данных профиля.
|
||||
|
||||
Последнее выглядит самым честным: авторизацию починили — отметка снимается сразу, а не по таймеру.
|
||||
|
||||
**Тест обязателен:** профиль, помеченный `AUTH_REQUIRED`, после починки учётных данных снова участвует в маршрутизации **без ручного вмешательства**.
|
||||
|
||||
Сейчас на машине владельца: 2 «Работает», 6 «Не проверялся», 11 «Аккаунт не добавлен», 3 «Отключён».
|
||||
|
||||
## P0-2. Проверка модели молча отключается
|
||||
|
||||
`do_set_model` валидирует модель по обнаруженному списку — логика написана верно:
|
||||
|
||||
```python
|
||||
if discovered is not None:
|
||||
if model not in discovered and model not in canonical and model not in canonical_short:
|
||||
return False, f"Модель '{model}' отсутствует в списке..."
|
||||
```
|
||||
|
||||
Но при пустом кэше `discovered` равен `None`, проверка **пропускается целиком**, и проходит что угодно. Ревьюер убедился: `do_set_model('ag-w1','такой-модели-нет')` вернул успех и записал это в конфигурацию владельца. Запись убрана вручную.
|
||||
|
||||
Это ровно тот класс дефекта, с которым проект борется с первого аудита: **отсутствие данных трактуется как разрешение**.
|
||||
|
||||
Требуется:
|
||||
|
||||
1. При пустом кэше — **не молчать**. Либо отказать с внятной причиной, либо сохранить с явной пометкой «модель не подтверждена» и показать это в интерфейсе. Молчаливое согласие недопустимо.
|
||||
2. **Прогревать кэш** перед проверкой, если его нет. Кэш на диске уже реализован (`models_cache.json`), обнаружение работает — не хватает только вызова в нужный момент.
|
||||
3. Учесть при сравнении, что в обнаруженном списке идентификаторы склеенные (`gemini-3.7-flash-high`), а в конфигурации может стоять базовое имя (`gemini-3.7-flash`). **Базовое имя — валидно.** Не отвергать его.
|
||||
|
||||
**Тесты:** несуществующая модель отклоняется при наполненном кэше; при пустом кэше поведение осознанное и проверяемое; базовое имя без суффикса усилия принимается.
|
||||
|
||||
## P0-3. Ручное обновление списка моделей
|
||||
|
||||
Действия обновления моделей нет ни среди действий, ни в интерфейсе — пункт остаётся невыполненным с A18.
|
||||
|
||||
Добавить действие обновления и кнопку рядом с выбором модели. Обнаружение ходит в сеть и подпроцесс: выполнять в фоне, интерфейс не блокировать, показывать ход.
|
||||
|
||||
Замерено: `agy models` отвечает за десятки секунд, а иногда висит дольше двух минут. Таймаут обязателен, **прежний кэш при таймауте не затирать**.
|
||||
|
||||
## P0-4. Аудит вторым проходом
|
||||
|
||||
Это пункт для проверяющего. Схема Flash → Pro уже поймала один дефект в A22; ниже то, на что смотреть в первую очередь.
|
||||
|
||||
1. **Запустить то, что изменено.** В A15 вынесли действия и уничтожили класс приложения: модуль импортировался, тесты проходили, а `launch_hub()` упал бы с `NameError`. Импорт ничего не доказывает — Python примет и недостижимый код.
|
||||
2. **Проверить тексты, которые видит владелец.** В A22 инструкция вела на несуществующий файл. Каждый путь и каждая команда в сообщениях интерфейса должны существовать.
|
||||
3. **Проверить утверждения отчёта, а не поверить им.** По A8 отчёт назвал сделанными четыре вещи, из которых ни одна не работала.
|
||||
4. **Проверить, что тесты проверяют суть, а не формулировку.** Два теста уже падали от переписанного текста при верном поведении.
|
||||
5. **Пропущенный пункт назвать пропущенным.** Дважды главные пункты задания оставались нетронутыми, и выяснялось это только при проверке файлов.
|
||||
|
||||
---
|
||||
|
||||
## Ограничения
|
||||
|
||||
- Ваши файлы: `health_tracker.py`, `router_engine.py`, `action_handler.py`, `model_discovery*`, `unified_health.py`, `router/ui/**`, `router/web/**`, соответствующие тесты.
|
||||
- Не откатывать: правку усилий из `45fd01a`, родной вход `agy` из A22, прогрев квот в веб-сервере.
|
||||
- Никаких статусов и значений без основания. Нет данных — сказать об этом, а не пропустить проверку.
|
||||
- Конфигурацию владельца литералами не править.
|
||||
- Тег `v0.1.1` не создавать.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
1. Ветка в `origin`, в `main` напрямую не пушилось, `git status` чист.
|
||||
2. Профиль с `AUTH_REQUIRED` возвращается в маршрутизацию после починки учётных данных **без ручного вмешательства**; проверено тестом.
|
||||
3. Выбранный способ выхода из состояния обоснован в отчёте.
|
||||
4. `do_set_model` не пропускает непроверенную модель молча; поведение при пустом кэше осознанное; базовое имя без суффикса усилия принимается. Три теста.
|
||||
5. Есть ручное обновление списка моделей; интерфейс не блокируется; таймаут не затирает кэш.
|
||||
6. Второй проход выполнен, в отчёте перечислено, что проверялось по пунктам P0-4 и что найдено.
|
||||
7. `ruff check .` чисто; релизный гейт не ухудшен.
|
||||
8. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На `main` сейчас 359 passed, 2 skipped.
|
||||
|
||||
## Главное
|
||||
|
||||
Antigravity наконец работает. Осталось, чтобы он не выпадал навсегда после единственного сбоя авторизации и чтобы выбор модели не соглашался на всё подряд, когда сравнить не с чем.
|
||||
|
||||
## Порядок сдачи
|
||||
Передать точный `FINAL_COMMIT_SHA`. Сдано только после появления коммита в `origin`.
|
||||
Loading…
Reference in a new issue