hermes-hub/agents/inbox/2026-08-21-A6-antigravity-dashboard-data.md
Hermes Team 2407d47606 docs(task): A6 and B5 — back the approved dashboard mockup with real data
The mockup's headline blocks divide three ways against the code at 2b2ccd8:
already available (latency, readiness, events, routing chain), derivable but not
yet exposed (per-provider aggregates, call share, host metrics via the unused
psutil dependency, active leases), and absent by design (task queues, service
window, incidents, provider RPS/SLA).

A6 supplies the second group; B5 redesigns against the contract and restores the
four account actions that d0d15ae dropped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 17:28:33 +07:00

115 lines
10 KiB
Markdown
Raw Permalink 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.

# Задание A6 (Antigravity): данные для нового дашборда
## Дата поступления
2026-08-21
## База
Проверочный HEAD: **`2b2ccd8`**, `origin/main` = `2b2ccd8`. `git fetch`, зафиксировать `BASE_SHA`.
## Ветка
`antigravity/dashboard-data`
---
## Что принято по A5
Проверено исполнением:
- телеметрия пишется и агрегируется: 3 вызова → `total_prompt_tokens=360`, `completion=135`, суммы сходятся; `source: own_measurement`;
- **честность подтверждена тремя проверками**: без вызовов `has_data=False` и `p50=None` вместо нулей; провайдер не вернул `usage``total_tokens=None`, а не оценка; подставленные в запрос `hunter2` и секретный текст в файл телеметрии **не попали**;
- ограничение размера настоящее: очередь 10 000 записей, файл 5 МБ, 3 ротации;
- контракт разделён правильно — Gap 12 закрыт как самоизмеряемый, для неизмеримого заведён **новый Gap 13**, молчаливой пропажи ограничений нет;
- долги: `HKCU` за флагом `HERMES_HUB_NO_REGISTRY`, `fastapi`/`uvicorn` перенесены в `optional-dependencies`.
Одна неточность в отчёте: YAML-комментарии помечены «Закрыт», фактически сохраняются только заголовочные. Теряются пять внутренних, включая пояснения к таблице цен, которые вы же и добавили. Не блокирует, но статус — «частично».
---
## Контекст
Владелец утвердил макет главного экрана в трёх цветовых схемах. Codex получает задание на редизайн (B5). Часть блоков макета уже обеспечена данными после A5, часть — нет. Ваша задача: закрыть недостающее, чтобы Codex рисовал правду, а не заглушки.
Разбор макета по источникам:
| Блок макета | Источник | Состояние |
|---|---|---|
| Время отклика 412 мс | `TelemetryService` latency | **есть** |
| Агенты онлайн 18/20 | `SystemReadiness` | **есть** |
| Последние события | `EventLogService` | **есть** |
| Провайдеры 3/3 + мс на каждого | `get_aggregates(provider=…)` | есть срез, **не выставлен в снапшот** |
| Доли маршрутизации 45/35/20 % | доля вызовов по провайдеру | **выводимо, не считается** |
| Счётчики запросов 128/74/56 | вызовы по ролям | **выводимо, не считается** |
| Квота сегодня 78 % | `QuotaSnapshot`, baseline `None` | Н/Д до реального 429 — так и оставить |
| Системные показатели CPU/Память/Диск/Сеть | `psutil` — в зависимостях, **не используется** | см. P1-3 |
| Активные задачи 24 | подсистемы задач нет | см. P1-4 |
| Очереди задач по приоритетам | подсистемы очередей нет | **не делать** |
| Окно обслуживания 09:0021:00 | понятия нет | **не делать** |
---
## P0-1. Вывести телеметрию в снапшот
`get_aggregates()` уже умеет резать по `provider`, `profile_id`, `model`, `role` — но наружу, в `HubSnapshot`, ничего из этого не попадает. UI получает снапшот и не может показать ни латентность, ни токены.
Добавить в снапшот готовые агрегаты:
- общие: латентность P50/P95, токены, доля ошибок, число вызовов;
- **на провайдера**: латентность и число вызовов — для правой панели «Статус в реальном времени»;
- **на роль**: число вызовов — для счётчиков на схеме маршрутизации.
Считать в том же цикле обновления, что и остальное состояние, чтобы UI не инициировал вычисления сам. Окно агрегации — параметр, по умолчанию сутки.
## P0-2. Доля вызовов по провайдеру
Проценты на схеме (45 / 35 / 20) — это распределение вызовов между провайдерами за окно. Данные для этого уже в телеметрии, самой доли нет.
Добавить в агрегаты `call_share` по провайдеру. При отсутствии вызовов в окне — `None`, а не «0 %» и не равномерное деление. Правило прежнее: нет данных — нет числа.
## P1-3. Показатели хоста через `psutil`
`psutil` объявлен обязательной зависимостью и **не используется ни в одном модуле**. Между тем блок «Системные показатели» на макете — это CPU, память, диск и сеть **самой машины**, и они измеримы честно.
В контракте Gap 13 сейчас объявляет их «неизмеримыми, так как не относятся к логике роутера». Формулировка неточна: они не относятся к провайдерам, но вполне измеримы. Владелец включил их в утверждённый макет — значит, они нужны.
Требуется: сбор показателей хоста через `psutil` с источником `host_measurement`, отдельным от `own_measurement` (вызовы роутера) и от данных провайдера. Обновить Gap 13: оставить в нём только действительно недоступное — RPS провайдера, SLA, uptime внешних сервисов.
Частота опроса — щадящая, в общем цикле обновления, без отдельного потока на каждый показатель.
## P1-4. Активные вызовы
«Активные задачи» на макете — в терминах Hermes Hub это вызовы, выполняющиеся прямо сейчас. `LeaseManager` уже знает число занятых лизов по каждому профилю; наружу это не выставлено (`active_leases` в `ProfileHealthRecord` всегда 0 — старое замечание, до сих пор не закрыто).
Вывести в снапшот число активных вызовов — суммарно и по профилям. Очереди по приоритетам **не изобретать**: подсистемы очередей нет, и придумывать её ради макета не нужно.
## P1-5. Дописать контракт
Все новые поля — в `docs/UI_STATE_CONTRACT.md`: имя, тип, источник (`own_measurement` / `host_measurement`), окно агрегации, поведение при отсутствии данных. Раздел 8 уже есть, дополнить его.
## P2-6. Остаток долга
YAML-комментарии: сохраняются только заголовочные, внутренние теряются. Либо довести до полного round-trip, либо переписать статус в контракте и отчёте на «частично» с указанием, что именно теряется.
---
## Ограничения
- Граница прежняя: зона Codex (`router/ui/**`, `hermes_hub_app.py`, `tests/test_ui_*.py`) — не трогать.
- Никаких оценок вместо измерений. Отсутствие данных — `None`, не ноль, не среднее, не равномерное распределение.
- Не изобретать подсистемы ради макета: очередей задач и окна обслуживания в продукте нет.
- Тег `v0.1.1` не создавать.
## Критерии приёмки
1. Ни один файл зоны Codex не изменён.
2. В `HubSnapshot` доступны агрегаты: общие, на провайдера, на роль; проверено тестом.
3. `call_share` считается верно на известном наборе вызовов; при отсутствии вызовов — `None`; проверено тестом.
4. Показатели хоста собираются через `psutil` с источником `host_measurement`; при недоступности `psutil` — отсутствие данных, а не нули.
5. Число активных вызовов отражает реальные лизы; проверено тестом с занятым лизом.
6. Gap 13 переформулирован: в нём осталось только недоступное.
7. Контракт дополнен по всем новым полям.
8. Прогон **в обоих окружениях**; обе команды и оба результата в отчёте.
9. `ruff check .` чисто; release gate PASSED на финальном коммите.
10. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, точный `X passed / Y skipped / Z failed`.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.