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