diff --git a/agents/inbox/2026-08-23-A10-antigravity-all-remaining.md b/agents/inbox/2026-08-23-A10-antigravity-all-remaining.md new file mode 100644 index 0000000..03e62b5 --- /dev/null +++ b/agents/inbox/2026-08-23-A10-antigravity-all-remaining.md @@ -0,0 +1,178 @@ +# Задание A10 (Antigravity): всё оставшееся — backend и интерфейс + +## Дата поступления +2026-08-23 + +## База +Проверочный HEAD на момент выдачи: **`0165434`**. Обязательно обновить локальную копию — см. следующий раздел. + +## Ветка +`antigravity/all-remaining` + +--- + +## Главное изменение: границы зон больше нет + +У Codex закончились лимиты. **Вся работа переходит к вам, включая интерфейс.** Прежнее ограничение «зона Codex — `router/ui/**`, не трогать» **снимается**: теперь `src/antigravity_provider/router/ui/**` и `tests/test_ui_*.py` ваши. + +Из этого следует требование, которого раньше не было: вы отвечаете и за то, чтобы интерфейс не врал. Правило честности распространяется на экран целиком — ни одного числа, идентификатора или названия модели без измерения. + +--- + +## Перед началом: обновить локальную копию + +Ваш отчёт по A9 назвал базой `6494c51`. С тех пор в `main` вошли: исправление плагина (`2d62d39`), дополнение задания A9 и **влитая частичная работа Codex по B8** (`0165434`). + +``` +cd <каталог репозитория>; git fetch origin --prune; git status +git checkout main; git reset --hard origin/main +``` + +Зафиксировать фактический `BASE_SHA` через `git rev-parse --short HEAD`. + +--- + +## О статусе A9 + +Отчёт по A9 получен и прочитан. **Ни одной строки этой работы в репозитории нет.** Проверено: ветки `antigravity/quotas-models-migration` на `origin` не существует, ни в одной ветке нет ни `model_discovery_service.py`, ни `test_a9_migration_quotas_models.py`, ни миграции в `router_config.py`. + +Работа осталась на вашей машине. Это уже второй такой случай в проекте: ветка Codex сутки лежала только локально, пока её не отправили в git. + +**Первое действие по этому заданию — отправить готовую работу A9 в `origin`**, до всякой новой правки: + +``` +git push origin antigravity/quotas-models-migration +``` + +Ветка в `origin` ничего не ломает и никого не обязывает. Несохранённая работа теряется вместе с диском. + +Пока код не в репозитории, приёмки быть не может: проверка идёт **исполнением, а не по отчёту**, и это не формальность. По A8 отчёт назвал сделанными четыре вещи, из которых ни одна у владельца не работала: профили claude/grok не дошли до существующего конфига, проверка просрочки была написана с опечаткой в имени ключа и не срабатывала ни разу, пересобранный установщик остался на вашей машине из-за `.gitignore`, флаг `/reinstall` не использовался в коде вообще. + +Два числа из отчёта A9, которые нужно объяснить при сдаче: + +- **«218 passed, 29 skipped»**. На `main` в venv Hermes набор даёт **290 passed, 2 skipped**. Двадцать девять пропусков означают, что UI-тесты в вашем окружении не выполнялись — то есть прогон не был полным. Требуется прогон в окружении **с** `customtkinter`, `pillow`, `psutil`. +- **«Release Gate 7/7 PASSED»**. Замер на чистом `main` даёт **FAILED**: проверка 4 (полный офлайн-прогон pytest) падает. Если у вас гейт зелёный — покажите, чем отличается окружение, либо приложите правку, которая его чинит. + +--- + +## P0-1. Довести A9 до репозитория и проверяемого состояния + +Всё содержание задания A9 остаётся в силе без изменений — миграция конфигурации, квоты остальных провайдеров, служба обнаружения моделей, отказ от выдуманных моделей, устойчивый порядок провайдеров, флаги установщика, доставка установщика. Читайте A9 как часть этого задания. + +Добавляются два пункта из дополненного A9, которые ваш отчёт не покрывает, потому что писался до них: + +- **P0-00 — Hub перехватывает каждый вызов Hermes как `orchestrator`.** Следствие устранено ревьюером; от вас — причина: не претендовать на вызов, если роль не определена достоверно; описать границу между учётными системами Hub и Hermes в контракте; подготовить варианты связывания профилей с ценой каждого. +- **P0-01 — обновление токена Codex и безопасное переключение аккаунта** по образцу Cockpit Tools: раздельная проверка `access_token` и `id_token`, обновление по `refresh_token`, остановка клиента **до** подмены учётных данных. + +## P0-2. Обязательный контракт службы обнаружения моделей + +Расхождение, которое сломает выбор моделей молча, и оно уже в коде. + +Codex в `ui/model_catalog.py` импортирует: + +```python +from antigravity_provider.router.model_discovery import ModelDiscoveryService +``` + +Ваш отчёт называет модуль `model_discovery_service.py`. Импорт обёрнут в `except (ImportError, AttributeError, TypeError): return None`, поэтому при несовпадении имени **ошибки не будет** — интерфейс просто всегда покажет «Список моделей ещё не получен». + +Проверено на текущем `main`: каталог возвращает `models=()`, `is_stale=True`, причина «Список моделей ещё не получен». Выбор модели подключён и пуст. + +**Контракт фиксируется:** + +- модуль: `src/antigravity_provider/router/model_discovery.py` +- класс: `ModelDiscoveryService` +- получение экземпляра: classmethod `get()` +- чтение для интерфейса: поля `models`, `fetched_at`, `is_stale`, `unavailable_reason` + +Если у вас модуль назван иначе — переименовать либо добавить `model_discovery.py` точкой входа. + +**Тест обязателен, и он должен падать при несовпадении пути.** Защитный `except ImportError` уместен в бою, но он же прячет несобранную интеграцию: тест обязан отличать «службы нет» от «служба есть, но импорт не тот». + +## P0-3. Компактные карточки аккаунтов + +Codex до этого не дошёл — `accounts_view.py` не менялся. + +Жалобы владельца: **«аккаунты должны выглядеть как у кокпит тулс, компактно»**, **«вид не тот, не надо делать раскрывающееся окно»**, **«в аккаунтах квота так и не отображается»**. + +Требуется: + +- плотный список фиксированной высоты: провайдер, идентичность, роль, состояние авторизации, квота — одной строкой, без раскрытия; +- квота видна сразу, числом и полосой, **с указанием пула и периода**: у Antigravity четыре пула, и «просто процент» вводит в заблуждение. Данные уже есть и настоящие — на живых аккаунтах владельца приходят измеренные значения от провайдера (`ag-w2` — 37.4% остатка недельного пула Claude/GPT, `source=provider_api`); +- шестнадцать аккаунтов читаются без прокрутки внутрь карточек; +- **дельта-отрисовку по стабильным ключам не терять** — изменение одного аккаунта не должно перерисовывать остальные. Это главное преимущество текущей версии, и в `COCKPIT_TOOLS_ARCHITECTURE_COMPARISON.md` описано, почему: при пересборке всех карточек на 50 аккаунтах выходит больше тысячи операций с виджетами в UI-потоке. + +Документ в корне репозитория — архитектурное сравнение, а не макет. Берите из него принцип обновления и плотность, не буквальную вёрстку. + +## P0-4. Разобрать дублирующие разделы + +Codex до этого не дошёл — `quotas_view.py` не менялся. + +Жалоба: **«провайдеры и квоты и лимиты вообще не понятно для чего нужны, там всё то же, что и в аккаунты»**. + +Владелец прав: после появления квот в карточках аккаунтов отдельный раздел квот потерял смысл. Нужно решение, а не сохранение обоих на всякий случай. + +- **«Квоты и лимиты»** — убрать из навигации либо оставить только то, чего нет в «Аккаунтах»: сводка по провайдеру целиком, история расхода, ближайшие сбросы. +- **«Провайдеры»** — оставить относящееся к провайдеру, а не к аккаунту: доступность runtime, обнаруженные модели, версия CLI, состояние авторизации в целом. + +В отчёте перечислить перенесённое и удалённое. Пустой раздел не оставлять. + +## P0-5. Причина у каждого Н/Д + +Жалоба: **«что означает н/д в маршрутизация запросов»**. + +Codex закрыл это частично: `unavailable_reason` используется в `components.py` и на «Обзоре», но не везде. + +Везде, где стоит `Н/Д`, должна быть доступна причина — подсказкой при наведении и текстом рядом, если место позволяет. Формулировки конкретные: «нет телеметрии: роль ещё не вызывалась», «провайдер не отдаёт лимиты», «аккаунт не подключён». Данные для этого есть. + +## P1-6. Подключение Grok и Claude довести до конца + +После миграции конфигурации (A9 P0-0.1) слоты для Grok и Claude появятся, и мастер перестанет упираться в «свободный слот не найден». Но проверить нужно весь путь целиком, а не только `find_free_slot`: подключение, назначение роли, появление в маршрутизации, тест профиля. + +Жалоба владельца была **«при подключении грока ошибка»** — принимается только пройденный вживую сценарий со скриншотами. + +--- + +## Что уже принято и не подлежит переделке + +Проверено исполнением, работает — не откатывать при слиянии: + +- **живые квоты Antigravity**: настоящий опрос `retrieveUserQuotaSummary` с обновлением OAuth-токена при 401, шесть аккаунтов владельца отдают разные измеренные числа; +- **правка плагина `2d62d39`**: при `router_error` вызов уходит вниз по цепочке, а не подменяет ответ модели; закрыта тестом `tests/test_plugin_passthrough.py`; +- **`_finish` мастера**: `destroy()` выполняется всегда, ранние `return` показывают ошибку в самом окне; +- **из работы Codex по B8**: выбор модели (`model_catalog.py`), кликабельная карточка целиком, окно настроек роли `_open_agent_settings_modal`, снятая правая панель, устранённые срезы `providers[:3]` и `agents[:5]`. + +--- + +## Ограничения + +- Границы зон нет — весь репозиторий ваш. Ответственность за честность интерфейса теперь тоже ваша. +- Не выдумывать числа, идентификаторы и названия моделей. Нет данных — `None` в модели, `Н/Д` с причиной на экране. +- Три темы сохранить, дельта-отрисовку не терять. +- Мастер не ломать: шесть потоков подключения, трёхэлементная распаковка `start_profile_oauth`, `destroy()` в `_finish` всегда. +- Сеть и подпроцессы — не в UI-потоке. Замерено: `agy models` в одном прогоне отвечает за 40 секунд, в следующем висит больше двух минут. +- Тег `v0.1.1` не создавать. +- **Ветку пушить сразу после первого коммита.** + +## Критерии приёмки + +1. Работа A9 находится в `origin` и проверяема исполнением. +2. Прогон в окружении **с** UI-зависимостями; число пропусков объяснено; обе команды и оба результата в отчёте. +3. Состояние релизного гейта названо до и после; расхождение с замером ревьюера объяснено. +4. Служба обнаружения моделей доступна по согласованному пути; тест падает при несовпадении импорта; выбор модели в интерфейсе показывает настоящий список. +5. Карточка аккаунта компактна, фиксированной высоты, без раскрытия; квота видна сразу с указанием пула и периода; шестнадцать аккаунтов без внутренней прокрутки; дельта-отрисовка сохранена и проверена тестом. +6. Принято решение по «Провайдерам» и «Квотам»; перенесённое и удалённое перечислено. +7. У каждого `Н/Д` доступна причина. +8. Вызов без достоверной роли уходит вниз, не тратя попыток роутера; правка `2d62d39` сохранена. +9. Граница между учётными системами Hub и Hermes описана в контракте; варианты связывания профилей — с ценой каждого, без односторонней реализации. +10. Grok и Claude подключаются вживую: подключение, роль, маршрутизация, тест профиля — со скриншотами. +11. `ruff check .` чисто. +12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, точный `X passed / Y skipped / Z failed`. +13. **Скриншоты живого сценария с настоящими данными.** Пустых состояний не присылать. + +## Главное + +Владелец сказал: «надо чтобы хаб уже заработал». Ядро работает, квоты Antigravity настоящие, интерфейс наполовину доведён. Осталось закрыть остаток и, что важнее всего, **довести сделанное до репозитория** — работа, лежащая на одной машине, для продукта не существует. + +## Порядок сдачи +Передать точный `FINAL_COMMIT_SHA`.