From 2407d47606558d4108dcae967e883e5caf5196e6 Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Fri, 21 Aug 2026 17:28:33 +0700 Subject: [PATCH] =?UTF-8?q?docs(task):=20A6=20and=20B5=20=E2=80=94=20back?= =?UTF-8?q?=20the=20approved=20dashboard=20mockup=20with=20real=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- ...026-08-21-A6-antigravity-dashboard-data.md | 115 +++++++++++++ .../2026-08-21-B5-codex-mockup-redesign.md | 151 ++++++++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 agents/inbox/2026-08-21-A6-antigravity-dashboard-data.md create mode 100644 agents/inbox/2026-08-21-B5-codex-mockup-redesign.md diff --git a/agents/inbox/2026-08-21-A6-antigravity-dashboard-data.md b/agents/inbox/2026-08-21-A6-antigravity-dashboard-data.md new file mode 100644 index 0000000..18b1692 --- /dev/null +++ b/agents/inbox/2026-08-21-A6-antigravity-dashboard-data.md @@ -0,0 +1,115 @@ +# Задание 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:00–21: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`. diff --git a/agents/inbox/2026-08-21-B5-codex-mockup-redesign.md b/agents/inbox/2026-08-21-B5-codex-mockup-redesign.md new file mode 100644 index 0000000..adf44ec --- /dev/null +++ b/agents/inbox/2026-08-21-B5-codex-mockup-redesign.md @@ -0,0 +1,151 @@ +# Задание B5 (Codex): редизайн по утверждённому макету, три цветовые схемы + +## Дата поступления +2026-08-21 + +## База +Проверочный HEAD: **`2b2ccd8`**, `origin/main` = `2b2ccd8`. `git fetch`, зафиксировать `BASE_SHA`, работать от свежего `main`. + +## Ветка +`codex/mockup-redesign` + +## Зависимость +Параллельно выполняется **Задание A6 (Antigravity)** — оно поставляет данные для правой панели, схемы маршрутизации и показателей хоста. Разделы, помеченные ниже «после A6», начинать, когда соответствующие поля появятся в `docs/UI_STATE_CONTRACT.md`. Всё остальное можно делать сразу. + +--- + +## P0. Сначала вернуть то, что пропало + +В редизайне фаз 2–6 (`d0d15ae`) с экрана «Аккаунты» исчезли управляющие элементы. История файла: + +``` +a7027b4 действий = 4 ← до редизайна +d0d15ae действий = 1 ← после +2b2ccd8 действий = 1 ← сейчас +``` + +Пропали, при живых обработчиках в `hermes_hub_app._handle_action`: + +| Действие | Обработчик | Триггер в UI | +|---|---|---| +| `test` — «⚡ Тест» | есть | только меню «Команда» | +| `set_main` — «★ Сделать основным» | есть | только меню «Команда» | +| `set_orchestrator` — «👑 Назначить оркестратором» | есть | только меню «Команда» | +| `assign_role` — «Назначить роль» | есть, вместе с модалкой | **нигде** | + +Владелец установил сборку и сообщил, что функции перестали работать — это оно. + +**Вернуть все четыре на экран «Аккаунты»** и добавить тест: для каждого обработчика в `_handle_action` существует хотя бы один вызывающий элемент в UI. Дефект этого класса возникает третий раз, механическая проверка обязательна. + +--- + +## Макет + +Утверждён главный экран «Обзор» в трёх схемах: **тёмная**, **средняя (гибрид)**, **светлая (бежевая)**. Все три — один и тот же layout, различаются палитрой. Остальные вкладки привести к тому же языку. + +### Композиция + +- **Левая панель**: логотип, вертикальная навигация, пользователь внизу, версия. +- **Верхняя строка**: индикатор состояния, поиск с подсказкой `Ctrl + K`, кнопка «+ Добавить аккаунт», уведомления, справка, настройки. +- **Строка KPI**: пять карточек в ряд. +- **Центр**: схема маршрутизации — провайдеры слева, оркестратор в центре, кластеры агентов справа, связи с подписями. +- **Правая панель**: «Статус в реальном времени», «Системные показатели», «Очереди задач». +- **Низ**: «Последние события» — таймлайн с тегами. + +### Три темы + +Палитры вынести в `theme.py` как три набора токенов с общими именами. Переключение — в настройках, с сохранением выбора. Ни один экран не должен содержать цвет вне токенов: смена темы обязана менять всё приложение, а не часть. + +Семантика цвета сохраняется во всех трёх: зелёный — работает, янтарный — предупреждение, красный — ошибка, серый — нет данных. **Золото остаётся брендом, а не статусом.** + +--- + +## Что чем наполнять + +Это главная часть задания. Источник каждого блока проверен по коду на `2b2ccd8`. + +### Есть данные — рисовать по-настоящему + +| Блок | Источник | +|---|---| +| Время отклика | `TelemetryService`, латентность P50, источник `own_measurement` | +| Агенты онлайн 18/20 | `SystemReadiness.roles_ready_count` / `total_roles` | +| Последние события | `EventLogService` | +| Цепочка маршрутизации, приоритеты, резервы | `RolePipeline` / `PipelineNode` | +| Состояние провайдеров, авторизация, здоровье | `ProviderSummary`, `ProfileViewModel` | +| Тариф аккаунта | `plan_code` + `plan_source` | +| Причина переключения | `PipelineNode.failover_reason` | + +### После A6 — появятся данные + +| Блок | Что придёт | +|---|---| +| Латентность по каждому провайдеру в правой панели | агрегаты по провайдеру | +| Доли 45 / 35 / 20 % на схеме | `call_share` по провайдеру | +| Счётчики 128 / 74 / 56 запросов | вызовы по ролям | +| CPU, память, диск, сеть | `psutil`, источник `host_measurement` | +| Активные вызовы | число занятых лизов | + +До появления этих полей — «Н/Д», не заглушки с числами. + +### Данных нет и не будет — не рисовать + +| Блок макета | Причина | +|---|---| +| Очереди задач по приоритетам | подсистемы очередей в продукте нет | +| Окно обслуживания 09:00–21:00 | понятия нет | +| «Инциденты» как раздел | подсистемы инцидентов нет; ближайшее реальное — журнал событий с фильтром по ошибкам | +| RPS провайдера, SLA, uptime | провайдеры не отдают, Gap 13 | +| Квота 78 % при отсутствии данных | baseline у всех провайдеров `None`; реальное значение появляется только после настоящего 429 | + +Пункт про квоту важен: на макете она нарисована заполненной, но по контракту до первого 429 данных нет. Показывать «Н/Д» с пояснением, а не 78 %. + +**Правило без исключений:** если поля нет в `docs/UI_STATE_CONTRACT.md` — числа в интерфейсе не будет. Ни примера, ни placeholder'а, ни «пока так». Продукт создан, чтобы показывать правду о квотах и маршрутах; первый аудит этого проекта нашёл именно выдуманные метрики, и повторения не будет. + +Пустое место в макете лучше заполнять тем, что есть на самом деле: состоянием авторизации, семейством моделей, позицией в цепочке отказоустойчивости, временем последней проверки. + +--- + +## Остальные вкладки + +Привести к тому же языку: та же сетка, та же плотность, те же компоненты, постоянная правая панель деталей вместо модальных окон. + +- **Команда** — иерархия «оркестратор → роли → агенты», карточка агента с провайдером, аккаунтом, моделью, состоянием квоты. +- **Аккаунты** — сохранить дельта-отрисовку по ключам, вернуть четыре действия (P0), группировка по провайдерам, поиск, фильтры. +- **Маршрутизация** — цепочка основной → резервы с активным узлом и причиной переключения. +- **Провайдеры** — сводка, обнаруженные модели, состояние. +- **Квоты и лимиты** — мульти-корзинные квоты с пометкой оценки и временем сброса. +- **Аналитика** — агрегаты телеметрии: латентность, токены, переключения, доля ошибок. Раздел появляется после A6. +- **Журнал событий** — таймлайн с фильтрами, поиском и уровнями. +- **Настройки** — параметры, выбор темы, пути, обновления. +- **Оркестратор** — если отдельным разделом, то на реальных данных о главной роли; иначе не заводить пустой экран. + +Экран без данных не создавать: либо скрыть пункт навигации, либо честное «Скоро». + +--- + +## Ограничения + +- Граница: ваша зона — `src/antigravity_provider/router/ui/**`, `hermes_hub_app.py`, `tests/test_ui_*.py`. +- Итеративно: после каждой вкладки приложение запускается. +- Сеть, подпроцессы, опрос OAuth — только в фоне. +- Дельта-отрисовку по стабильным ключам не терять; полных пересборок виджетов не возвращать. +- Мастер подключения не ломать: шесть рабочих потоков и трёхэлементная распаковка `start_profile_oauth`. +- Секреты маскировать. +- Проверить на 1280×720, 1366×768, 1920×1080 при масштабировании 100 %, 125 %, 150 %. +- Тег `v0.1.1` не создавать. + +## Критерии приёмки + +1. Ни один файл чужой зоны не изменён. +2. Четыре действия вернулись на «Аккаунты»; тест проверяет соответствие обработчиков и триггеров. +3. Три темы переключаются, покрывают всё приложение; ни одного цвета вне токенов. +4. Приложение запускается, все разделы открываются без ошибок. +5. Ни одного числа без поля в контракте: очереди, окно обслуживания, RPS, SLA, CPU до A6 — отсутствуют или «Н/Д». +6. Дельта-отрисовка сохранена: изменение одного аккаунта не перерисовывает остальные. +7. Прогон **в обоих окружениях** — без UI-зависимостей и с `customtkinter`/`pillow`/`psutil`; обе команды и оба результата в отчёте. +8. `ruff check .` чисто; release gate не ухудшен. +9. Отчёт: скриншоты каждой вкладки во всех трёх темах и раздел «расхождения с макетом» с причиной по каждому пункту. + +## Порядок сдачи +Передать точный `FINAL_COMMIT_SHA`.