From 1efaf78a7a539d18416253b49b7b926aea43c1c0 Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Fri, 21 Aug 2026 21:54:01 +0700 Subject: [PATCH] =?UTF-8?q?docs(task):=20A7=20=E2=80=94=20two=20dashboard?= =?UTF-8?q?=20data=20defects=20found=20by=20execution?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit active_calls is permanently zero: state_store reads LeaseManager.get() while RouterEngine constructs its own instance, so the router's leases are invisible to the snapshot. And psutil.cpu_percent(interval=None) returns 0.0 on its first call, so the dashboard shows CPU 0% at startup — a measured-looking number that is not a measurement. Co-Authored-By: Claude Opus 5 --- .../2026-08-21-A7-antigravity-two-defects.md | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 agents/inbox/2026-08-21-A7-antigravity-two-defects.md diff --git a/agents/inbox/2026-08-21-A7-antigravity-two-defects.md b/agents/inbox/2026-08-21-A7-antigravity-two-defects.md new file mode 100644 index 0000000..6f0608b --- /dev/null +++ b/agents/inbox/2026-08-21-A7-antigravity-two-defects.md @@ -0,0 +1,118 @@ +# Задание A7 (Antigravity): два дефекта в данных дашборда + +## Дата поступления +2026-08-21 + +## База +Проверочный HEAD: **`69cbefc`**, `origin/main` = `69cbefc`. `git fetch`, зафиксировать `BASE_SHA`. + +## Ветка +`antigravity/dashboard-fixes` + +--- + +## Что принято по A6 + +Проверено исполнением, работа хорошая: + +- **разрезы телеметрии в снапшоте.** Прогнал 6 вызовов оркестратора и 2 исследователя (последние с переключением) — получил 10 записей, что верно: неуспешная попытка тоже учитывается. Доли сошлись точно: + +``` +openai-codex : total_calls=6, call_share=0.6 +antigravity : total_calls=2, call_share=0.2 +opencode-go : total_calls=2, call_share=0.2 + сумма = 1.0 +``` + +- **разрез по ролям**: `orchestrator=6`, `research=4` — совпадает с числом попыток; +- **пустое окно честно**: `has_data=False`, `latency_p50_ms=null`, `total_tokens=null`, при этом `total_calls=0` — счётчик как факт, а латентность как отсутствие. Ровно то различие, которого добивались; +- **контракт снова разделён правильно**: Gap 13 закрыт как самоизмеряемый, для недоступного заведён **Gap 14** — RPS провайдера, SLA, очереди задач, окно обслуживания, с сохранённым требованием «Н/Д либо скрыть». Третий раз подряд без молчаливых пропаж; +- прогон: headless 189 passed, с UI-зависимостями 235 passed, ruff чисто, гейт PASSED. + +--- + +## P0-1. `active_calls` всегда ноль: два разных `LeaseManager` + +`state_store.py:172` читает синглтон: + +```python +active_leases_total = LeaseManager.get().total_active_count() +``` + +`router_engine.py:31` создаёт **собственный** экземпляр: + +```python +self.leases = leases or LeaseManager() +``` + +Роутер захватывает лизы в своём приватном менеджере, снапшот читает синглтон, который всегда пуст. Проверено: + +``` +движок и синглтон — один объект? False +id(engine.leases) = 2732720631632 +id(LeaseManager.get()) = 2732720631376 + +после acquire на движке: + движок видит : 1 + синглтон видит: 0 +``` + +Итог: `active_calls_total` в снапшоте будет **постоянно 0** при любой нагрузке. Блок «Активные задачи» на дашборде покажет ноль всегда — то есть правдоподобное, но неверное число. + +Требуется: один источник истины по лизам. Либо `RouterEngine` по умолчанию берёт синглтон, либо `state_store` читает лизы у движка. Второе честнее: лизы принадлежат движку, а не глобальному состоянию. + +**Тест обязателен:** захватить лиз через тот же путь, которым пользуется роутер, и убедиться, что снапшот его видит. + +Попутно: `ProfileHealthRecord.active_leases` по-прежнему всегда 0 и при этом выводится в CLI и API — это отмечалось ещё в первом аудите. Либо заполнять, либо убрать из вывода. + +## P0-2. CPU при первом измерении всегда 0 % + +`host_metrics.py:57` — `psutil.cpu_percent(interval=None)`. Без предыдущей точки отсчёта первый вызов возвращает `0.0` по устройству самой библиотеки. Проверено: + +``` +первый вызов (холодный): 0.0 +второй вызов: 44.1 +третий вызов: 12.0 +``` + +На старте приложения пользователь увидит «CPU 0 %» — и это тот же класс дефекта, с которым мы боролись в квотах: число выглядит измеренным, но измерением не является. + +Требуется одно из: прогреть счётчик при инициализации сервиса (один вызов, результат отбросить), либо возвращать `None` для первого измерения, либо использовать короткий интервал. Первый вариант предпочтительнее — он не создаёт «дырки» в интерфейсе. + +**Тест обязателен:** первое значение не должно быть нулём, полученным из-за холодного старта. + +## P1-3. Остаток по YAML + +Комментарии сохраняются только заголовочные, внутренние теряются: + +``` + # Antigravity (10 accounts) + # OpenAI Codex (3 accounts) + # OpenCode Go (3 accounts) + # Optional: User Model Pricing Table (USD per 1M tokens) + # Telemetry will compute call cost in USD only if a model price is defined below. +``` + +Первыми стираются пояснения к таблице цен, добавленные в A5. В отчёте статус указан «Закрыт» — это неточно. Либо довести до полного round-trip, либо переписать статус на «частично» с перечнем теряемого. + +--- + +## Ограничения + +- Граница прежняя: зона Codex (`router/ui/**`, `hermes_hub_app.py`, `tests/test_ui_*.py`) — не трогать. +- Никаких чисел без измерения. Ноль допустим только как результат подсчёта, а не как значение по умолчанию. +- Тег `v0.1.1` не создавать. + +## Критерии приёмки + +1. Ни один файл зоны Codex не изменён. +2. Захваченный роутером лиз виден в снапшоте; проверено тестом через реальный путь захвата. +3. `ProfileHealthRecord.active_leases` заполняется либо убран из вывода CLI и API. +4. Первое измерение CPU не равно нулю из-за холодного старта; проверено тестом. +5. Статус YAML в отчёте и контракте соответствует фактическому поведению. +6. Прогон **в обоих окружениях**; обе команды и оба результата в отчёте. +7. `ruff check .` чисто; release gate PASSED на финальном коммите. +8. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, точный `X passed / Y skipped / Z failed`. + +## Порядок сдачи +Передать точный `FINAL_COMMIT_SHA`.