From 972e34911cb31182eafecbf1ecf9ad6ebee8e727 Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Sun, 23 Aug 2026 22:49:45 +0700 Subject: [PATCH] =?UTF-8?q?docs(task):=20A21=20=E2=80=94=20=D1=87=D0=B5?= =?UTF-8?q?=D1=82=D1=8B=D1=80=D0=B5=20=D0=BD=D0=B5=D0=B4=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=8E=D1=89=D0=B8=D1=85=20=D1=8D=D0=BA=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B2=D0=B5=D0=B1-=D0=B8=D0=BD=D1=82=D0=B5=D1=80?= =?UTF-8?q?=D1=84=D0=B5=D0=B9=D1=81=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Веб покрывает пять экранов из девяти. Не хватает Аналитики, Состояния, Журнала событий и Настроек. Данные для первых двух уже в снапшоте: metrics.telemetry (19 вызовов, 15 отказов, латентность p50/p95/max) и metrics.host плюс readiness. Для двух других источника в API нет вовсе — нужны GET /api/events (EventLogService в backend есть) и GET /api/settings без секретов. Зона Flash на это задание расширена на router/web/** целиком, включая server.py: A20 в web/ не заходит, конфликта не будет. Обнаружение моделей в задание НЕ включено, хотя A18 его пропустил: причина оказалась глубже и лежит в авторизации agy, это чинит A20. Co-Authored-By: Claude Opus 5 --- ...-08-24-A21-antigravity-flash-web-parity.md | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 agents/inbox/2026-08-24-A21-antigravity-flash-web-parity.md diff --git a/agents/inbox/2026-08-24-A21-antigravity-flash-web-parity.md b/agents/inbox/2026-08-24-A21-antigravity-flash-web-parity.md new file mode 100644 index 0000000..d2d70f0 --- /dev/null +++ b/agents/inbox/2026-08-24-A21-antigravity-flash-web-parity.md @@ -0,0 +1,162 @@ +# Задание A21 (Antigravity Flash): довести веб-интерфейс до паритета с десктопом + +## Дата поступления +2026-08-24 + +## База +Проверочный HEAD на момент выдачи: **`187f181`**. + +## Ветка +`antigravity/web-parity` + +--- + +## Порядок работы с git + +``` +cd <каталог репозитория>; git fetch origin --prune; git status +git checkout main; git pull --ff-only origin main +git checkout -b antigravity/web-parity +git commit -m "..." <- сначала коммит +git push -u origin antigravity/web-parity +``` + +В конце: + +``` +git status <- дерево чистое +git log --oneline -1 origin/antigravity/web-parity <- ваш финальный коммит +``` + +--- + +## Что принято по A18 + +Действие `set_model` сделано и устроено правильно: живёт в `action_handler`, валидирует модель по списку провайдера, десктоп и веб зовут одно и то же. + +**Но обнаружение моделей (P0-2) не сделано вовсе** — `model_discovery_service` и зонд не менялись, ручного обновления нет, кэша на диске нет. Из-за этого `set_model` отклоняет **любую** модель, включая настоящую: сравнивать не с чем. + +``` +do_set_model('ag-w2','gemini-3.1-pro-high') +-> (False, "список моделей провайдера ещё не получен") +``` + +Это второе задание подряд, где пункт про обнаружение остался нетронутым. **В это задание он не включён** — выяснилось, что причина глубже и лежит в авторизации: `agy models` отвечает «Please sign in» при шести валидных OAuth-профилях, потому что Hub не пишет `oauth_creds.json` в формате, который CLI ожидает. Это чинит **A20**, и обнаружение доделывается там же, после авторизации. + +Отдельно скажу прямо, потому что это повторяется: **пропущенный пункт нужно называть в отчёте пропущенным.** Не «сделано», не молчание — просто «не успел» или «не смог, потому что». Один такой абзац экономит раунд. + +## Что принято по A16 — и это важно для нового задания + +Веб-клиент был лучшей работой за все раунды. Экран «Аккаунты» с квотами, пулами и периодами, честный индикатор источника данных, восемь содержательных скриншотов. Это задание — продолжение той же работы. + +--- + +## Задача: четыре недостающих экрана + +Веб покрывает пять экранов из девяти: + +``` +есть: Аккаунты, Обзор, Маршрутизация, Модели и провайдеры, Команда +нет: Аналитика, Состояние, Журнал событий, Настройки +``` + +Цель — паритет, чтобы десктоп можно было наконец перестать тащить второй веткой. Пока паритета нет, **десктоп не трогаем**: `router/ui/**` остаётся рабочим. + +## P0-1. Аналитика — данные уже есть + +`snapshot.metrics.telemetry` заполнена настоящими измерениями. С машины владельца: + +```json +"global": { + "window_seconds": 86400, "total_calls": 19, + "successful_calls": 4, "failed_calls": 15, + "call_share": 1.0, "error_rate": 0.7895, + "latency_p50_ms": 1.4, "latency_p95_ms": 81631.1, "latency_max_ms": 81777.7, + "total_prompt_tokens": null, "total_completion_tokens": null, "total_tokens": null +} +``` + +Показать: вызовы, доля ошибок, латентность p50/p95/max, разрезы по провайдерам и ролям (они рядом в том же объекте). + +**Токены равны `null` — это не ноль.** Провайдеры их не отдают. Показывать «Н/Д» с причиной, ни в коем случае не «0». + +Обратите внимание на сами числа: 15 отказов из 19 и p95 в 81 секунду — это следствие сломанной авторизации `agy`, которую чинит A20. Экран должен честно показывать такую картину, а не сглаживать её. + +## P0-2. Состояние — данные тоже есть + +`snapshot.metrics.host`: + +```json +"cpu_percent": 11.8, "memory_percent": 75.5, "memory_used_mb": 9077.9, +"disk_percent": 53.7, "disk_used_gb": 255.7, "net_speed_mbps": null +``` + +Плюс `snapshot.readiness`: `state`, `title_ru`, `summary_ru`, `roles_ready_count` / `total_roles`, `accounts_connected_count` / `total_accounts`, `providers_ready_count` / `total_providers`, `warnings`. + +`net_speed_mbps` равен `null` — показывать «Н/Д», не ноль. Список `warnings` вывести целиком: это готовности ради него и считаются. + +## P0-3. Журнал событий — источника в API нет, его нужно добавить + +Проверено: **событий в снапшоте нет ни в каком виде.** В backend они есть — `EventLogService` в `unified_health.py` с методом `get_events(limit, category)`. + +Требуется новый эндпоинт: + +``` +GET /api/events?limit=&category=<необязательно> +-> {"events": [{"timestamp","category","message","details","level"}]} +``` + +Отдавать в обратном хронологическом порядке, с разумным пределом по умолчанию. **Секреты в события не попадают** — существующий тест на отсутствие секретов в ответах должен продолжать проходить, и на новый эндпоинт его нужно распространить. + +На экране: лента с фильтром по уровню и категории и поиском по тексту. + +## P0-4. Настройки — текущих значений в API тоже нет + +Действие `save_settings` существует, а прочитать текущие значения через API нельзя: в снапшоте их нет. + +Требуется: + +``` +GET /api/settings -> текущее содержимое hub_settings.json +``` + +**Без секретов.** Поле `web_api_token` наружу не отдавать никогда — ни целиком, ни частично. Отдавать признак «токен задан / не задан». + +На экране: параметры, выбор темы, интервал обновления квот, пути. Сохранение — через существующее действие `save_settings`, второй реализации не заводить. + +## P0-5. Контракт + +Оба новых эндпоинта — в `docs/web-api/CONTRACT.md`, с примерами ответов. Версию контракта поднять. + +Это не бюрократия: контракт версии 1.0 описал каталог `static/`, но не назвал, **кто его отдаёт**, — обе стороны выполнили написанное, и в браузере был 404. Пропуск был на авторе контракта, но цена — потерянный раунд. + +--- + +## Ограничения + +- Параллельно идёт **A20** (авторизация Antigravity). Его файлы: `oauth.py`, `profile_oauth.py`, `profile_manager.py`, `agy_subprocess.py`, `adapters/**`, `model_discovery*`, `credentials.py`. **Ничего из этого не трогать.** +- **Ваша зона на это задание расширена**: `router/web/**` целиком, включая `server.py` — там нужны два новых эндпоинта. A20 в `web/` не заходит, конфликта не будет. +- `router/ui/**` не трогать: десктоп остаётся рабочим до паритета. +- Правило честности без исключений: `null` — это «Н/Д» с причиной, а не ноль. Отличать «данных нет» от «данные грузятся» — механизм `is_loading` уже работает на «Аккаунтах», используйте его же. +- Секреты не отдавать ни в одном новом эндпоинте. +- Тег `v0.1.1` не создавать. + +## Критерии приёмки + +1. Ветка в `origin`, финальный коммит виден, `git status` чист. +2. Четыре экрана работают на данных: Аналитика, Состояние, Журнал событий, Настройки. +3. `GET /api/events` и `GET /api/settings` реализованы и описаны в контракте; версия контракта поднята. +4. Тест на отсутствие секретов распространён на новые эндпоинты и проходит; `web_api_token` наружу не отдаётся. +5. Ни одно `null` не показано как ноль; у каждого «Н/Д» есть причина. +6. Ни один файл зоны A20 не изменён; `router/ui/**` не тронут. +7. **Скриншоты всех четырёх экранов с настоящими данными.** Открыть и посмотреть перед тем, как прикладывать: в прошлый раз три из восьми оказались пустым чёрным кадром. +8. `ruff check .` чисто; релизный гейт не ухудшен. +9. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, точный `X passed / Y skipped / Z failed`. На `main` сейчас 342 passed, 2 skipped. +10. **Если какой-то пункт не сделан — сказать об этом прямо**, с причиной. + +## Главное + +После этого задания веб покрывает всё, что умеет десктоп, и владелец сможет пользоваться Hub на своём сервере с Ubuntu, не запуская окно по SSH. Это же условие для того, чтобы перестать поддерживать два интерфейса — а интерфейс был узким местом каждого раунда этого проекта. + +## Порядок сдачи +Передать точный `FINAL_COMMIT_SHA`. Сдано только после появления коммита в `origin`.