hermes-hub/agents/inbox/2026-08-23-A12-antigravity-flash-interface.md
Hermes Team 78cd826624 docs(tasks): A11 и A12 — разделение работ между двумя исполнителями
A11 (Pro, тяжёлая ветка): интеграция с Hermes — перехват без роли,
граница между учётными системами Hub и Hermes, токены Codex и безопасное
переключение аккаунта, замена зонда обнаружения моделей на agy models,
устранение выдуманного запасного списка в адаптере.

A12 (Flash, быстрая ветка): компактные карточки аккаунтов, разбор
дублирующих разделов «Провайдеры»/«Квоты», причина у каждого Н/Д, тест
на достижимость службы обнаружения моделей, живое подключение Grok.

Заданы строгие непересекающиеся списки файлов, чтобы параллельная работа
не дала конфликтов. В A12 порядок работы с git расписан пошагово: pull в
начале, push ветки сразу после первого коммита, обязательная проверка
финального push через git log origin/<ветка>.

A10 удалено — заменено этой парой.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 13:00:36 +07:00

220 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Задание A12 (Antigravity Flash, другой ПК): интерфейс и чистка разделов
## Дата поступления
2026-08-23
## База
Проверочный HEAD на момент выдачи: **`cdfd9f1`**.
## Ветка
`antigravity/interface-cleanup`
## Кому
Быстрая ветка работ. Задачи описаны подробно и не требуют проектных решений — только аккуратное исполнение.
---
## Порядок работы с git — читать первым
Прошлый раз работа A9 была готова, но **не отправлена в `origin`**, и трое суток её не существовало для проекта. Чтобы это не повторилось, порядок жёсткий.
**Шаг 1. В самом начале — обновить локальную копию из git:**
```
cd <каталог репозитория>; git fetch origin --prune; git status
```
Если рабочее дерево чистое:
```
git checkout main; git pull --ff-only origin main
```
Если есть незакоммиченные правки — сначала сохранить их отдельной веткой, вслепую сбрасывать нельзя.
**Шаг 2. Создать ветку от свежего `main` и сразу отправить её:**
```
git checkout -b antigravity/interface-cleanup
git push -u origin antigravity/interface-cleanup
```
Пустая ветка в `origin` ничего не ломает и никого не обязывает. Зато с этого момента работа перестаёт зависеть от одного диска.
**Шаг 3. Пушить после каждого осмысленного коммита**, не копить.
**Шаг 4. В самом конце — обязательный финальный push и проверка, что он прошёл:**
```
git push origin antigravity/interface-cleanup
git status
git log --oneline -1 origin/antigravity/interface-cleanup
```
Последняя команда должна показать ваш финальный коммит. Если не показывает — push не прошёл, повторить.
Зафиксировать фактический `BASE_SHA` через `git rev-parse --short HEAD` и указать его в отчёте. Не считать `cdfd9f1` актуальным автоматически — параллельно идёт A11.
---
## Параллельная работа: строгая граница по файлам
Одновременно выполняется **A11** вторым исполнителем.
**Ваши файлы:**
```
src/antigravity_provider/router/ui/**
src/antigravity_provider/router/model_discovery.py
src/antigravity_provider/router/model_discovery_service.py
src/antigravity_provider/router/router_config.py
src/antigravity_provider/router/auto_assigner.py
src/antigravity_provider/router/unified_health.py
installer/**
tests/test_ui_*.py
```
**Не ваши** (зона A11): `hermes_plugin.py`, `router_engine.py`, `codex_oauth.py`, `profile_manager.py`, `quota_collector.py`, `adapters/**`, `agy_subprocess.py`, `docs/UI_STATE_CONTRACT.md`.
Понадобился чужой файл — скажите, будет заказан отдельно.
---
## Что принято по A9
Проверено исполнением, работа хорошая: миграция конфигурации подняла 16 профилей до 22, `claude` и `grok` получили слоты, резервная копия создаётся, десять профилей владельца не тронуты, комментарии не потеряны, флаг `/reinstall` заработал, предупреждение CS0219 исчезло.
**Один урок, который стоит запомнить.** Служба обнаружения моделей была написана правильно, но **недостижима**: файл назван `model_discovery_service.py`, а интерфейс импортирует `model_discovery`. Импорт в `ui/model_catalog.py` обёрнут в `except ImportError`, поэтому ошибки не возникало — выбор моделей просто оставался пустым навсегда, с надписью «Список моделей ещё не получен». Ревьюер добавил точку входа при слиянии.
Защитный `except ImportError` уместен в бою, но он же прячет несобранную интеграцию. Пишете модуль для чужого потребителя — проверьте импорт **исполнением**, а не глазами.
---
## Что уже сделал Codex и переделывать не нужно
У Codex закончились лимиты, его работа влита частично. Не откатывайте:
- выбор модели: `ui/model_catalog.py` с честным пустым состоянием;
- **карточка кликабельна целиком** (`cursor="hand2"` + привязка `<Button-1>`), «три точки» перестали быть единственным входом;
- **окно настроек роли**: `_open_agent_settings_modal`;
- **правая панель «Статус в реальном времени» убрана**, центр расширен;
- жёсткие срезы `providers[:3]` и `agents[:5]` в диаграмме устранены;
- причины у части `Н/Д` через `unavailable_reason`.
Codex остановился ровно перед двумя пунктами ниже — они и есть основная работа задания.
---
## P0-1. Компактные карточки аккаунтов
`accounts_view.py` не менялся вообще. Это самый заметный для владельца пункт.
Жалобы дословно: **«аккаунты должны выглядеть как у кокпит тулс, компактно»**, **«вид не тот, не надо делать раскрывающееся окно»**, **«в аккаунтах квота так и не отображается»**.
Требуется:
- плотный список фиксированной высоты: провайдер, идентичность, роль, состояние авторизации, квота — одной строкой, **без раскрытия**;
- **квота видна сразу**, числом и полосой, с указанием пула и периода. У Antigravity четыре пула, и «просто процент» вводит в заблуждение;
- шестнадцать аккаунтов читаются без прокрутки внутрь карточек;
- **дельта-отрисовку по стабильным ключам не терять** — изменение одного аккаунта не перерисовывает остальные.
Данные для квоты **уже есть и настоящие**. На живых аккаунтах владельца приходят измеренные значения от провайдера:
```
ag-w2 Claude/GPT — неделя осталось 37.4% source=provider_api
ag-w3 Claude/GPT — неделя осталось 90.1% source=provider_api
ag-w1 Gemini — неделя осталось 99.7% source=provider_api
```
Где данных нет — `Н/Д` с причиной, а не ноль и не прочерк без объяснения. У `opencode-go` и `grok` провайдер лимитов не отдаёт, и причина уже заполняется в `unavailable_reason`.
Про дельта-отрисовку: в корне репозитория лежит `COCKPIT_TOOLS_ARCHITECTURE_COMPARISON.md` — там описано, почему это важно: при пересборке всех карточек на 50 аккаунтах выходит больше тысячи операций с виджетами в UI-потоке, и окно заметно подвисает. Документ — архитектурное сравнение, а не макет: берите принцип обновления и плотность, не буквальную вёрстку.
**Тест:** изменение квоты одного аккаунта не пересоздаёт виджеты остальных.
## P0-2. Разобрать дублирующие разделы
`quotas_view.py` не менялся, `providers_view.py` тронут на девять строк.
Жалоба: **«провайдеры и квоты и лимиты вообще не понятно для чего нужны, там всё то же, что и в аккаунты»**.
Владелец прав: после появления квот в карточках аккаунтов отдельный раздел квот потерял смысл. Нужно **решение**, а не сохранение обоих на всякий случай.
- **«Квоты и лимиты»** — убрать из навигации либо оставить только то, чего нет в «Аккаунтах»: сводка по провайдеру целиком, история расхода, ближайшие сбросы. Нет такого содержания — убрать раздел.
- **«Провайдеры»** — оставить относящееся к провайдеру, а не к аккаунту: доступность runtime, обнаруженные модели, версия CLI, состояние авторизации в целом.
В отчёте перечислить, что перенесено, что удалено и почему. Пустой раздел не оставлять: либо содержание, либо нет пункта навигации.
## P0-3. Причина у каждого Н
Жалоба: **«что означает н/д в маршрутизация запросов»**.
Codex закрыл частично: `unavailable_reason` используется в `components.py` и на «Обзоре», но не везде.
Везде, где стоит `Н/Д`, причина должна быть доступна — подсказкой при наведении и текстом рядом, если место позволяет. Формулировки конкретные: «нет телеметрии: роль ещё не вызывалась», «провайдер не отдаёт лимиты», «аккаунт не подключён». Данные для этого есть.
Это претензия не к честности, а к молчаливости: владелец видит прочерк и не знает, это поломка, ненастроенное или неизмеримое.
## P0-4. Тест на достижимость службы обнаружения моделей
Ревьюер добавил точку входа `router/model_discovery.py`, и выбор моделей снова собран. Но защита от повторения этой ошибки отсутствует.
Требуется тест, который **падает**, если служба недостижима по согласованному пути:
- модуль: `src/antigravity_provider/router/model_discovery.py`
- класс: `ModelDiscoveryService`
- получение экземпляра: classmethod `get()`
Тест обязан отличать «службы нет» от «служба есть, но импорт не тот». Проверять через `ui/model_catalog` недостаточно — там `except ImportError` всё проглотит; импортируйте модуль напрямую.
## P0-5. Подключение Grok и Claude довести до конца
После миграции из A9 слоты появились, проверено:
```
find_free_slot(grok) -> grok-worker-1
find_free_slot(claude) -> claude-orch
```
Мастер больше не должен упираться в «свободный слот не найден». Но проверить нужно **весь путь**, а не только выдачу слота: подключение, назначение роли, появление в маршрутизации, тест профиля.
Жалоба владельца была **«при подключении грока ошибка»**. Принимается только пройденный вживую сценарий со скриншотами.
## P1-6. Порядок провайдеров в диаграмме
A9 задал детерминированный порядок провайдеров в `unified_health.get_provider_summaries()` (по числу авторизованных профилей, затем по общему числу слотов, затем по имени) и привёл `total_providers` к пяти.
Убедиться, что диаграмма на «Обзоре» этот порядок соблюдает и показывает всех пятерых, а не первых трёх. Срезы Codex убрал, но проверить связку целиком стоит — раньше `claude` и `grok` молча отбрасывались.
---
## Ограничения
- Строгая граница по файлам — см. выше.
- Не выдумывать числа, идентификаторы и названия моделей. Нет данных — `Н/Д` с причиной либо блок отсутствует.
- Три темы сохранить, дельта-отрисовку не терять.
- Мастер не ломать: шесть потоков подключения, трёхэлементная распаковка `start_profile_oauth`, `destroy()` в `_finish` выполняется всегда.
- Сеть и подпроцессы — не в UI-потоке. Замерено: `agy models` в одном прогоне отвечает за 40 секунд, в следующем висит больше двух минут.
- Тег `v0.1.1` не создавать.
## Критерии приёмки
1. **Ветка в `origin`**, финальный коммит виден через `git log origin/antigravity/interface-cleanup`. Ни один файл зоны A11 не изменён.
2. Карточка аккаунта компактна, фиксированной высоты, без раскрытия; квота видна сразу с указанием пула и периода; шестнадцать аккаунтов без внутренней прокрутки.
3. Дельта-отрисовка сохранена: изменение одного аккаунта не пересоздаёт виджеты остальных; проверено тестом.
4. Принято решение по «Провайдерам» и «Квотам»; перенесённое и удалённое перечислено; пустых разделов нет.
5. У каждого `Н/Д` доступна причина.
6. Есть тест, падающий при недостижимости `router/model_discovery.ModelDiscoveryService`.
7. Grok и Claude подключаются вживую: подключение, роль, маршрутизация, тест профиля.
8. Диаграмма показывает всех пятерых провайдеров в заданном порядке.
9. Прогон **в обоих окружениях** — без UI-зависимостей и с `customtkinter`/`pillow`/`psutil`; обе команды и оба результата в отчёте. На `main` полный набор даёт 307 passed, 2 skipped.
10. `ruff check .` чисто. Релизный гейт не ухудшен.
11. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, точный `X passed / Y skipped / Z failed`.
12. **Скриншоты живого сценария с настоящими данными**: «Аккаунты» с видимыми квотами, подключение Grok, окно роли. Пустых состояний не присылать.
## Главное
Владелец сказал: «надо чтобы хаб уже заработал». Квоты настоящие, роли настраиваются, подключение Grok разблокировано. Осталось, чтобы шестнадцать аккаунтов читались с одного взгляда и в каждом непонятном месте был ответ, почему там прочерк.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`. **Сдано только после появления ветки в `origin`** — проверьте это командой перед тем, как отчитаться.