hermes-hub/agents/inbox/2026-08-21-A7-antigravity-two-defects.md
Hermes Team 1efaf78a7a docs(task): A7 — two dashboard data defects found by execution
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 <noreply@anthropic.com>
2026-08-21 21:54:01 +07:00

7.4 KiB
Raw Blame History

Задание 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 читает синглтон:

active_leases_total = LeaseManager.get().total_active_count()

router_engine.py:31 создаёт собственный экземпляр:

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:57psutil.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.