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>
220 lines
17 KiB
Markdown
220 lines
17 KiB
Markdown
# Задание 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`** — проверьте это командой перед тем, как отчитаться.
|