hermes-hub/agents/done/2026-08-21-A2-antigravity-contract-gaps.md

5.2 KiB
Raw Blame History

Отчёт: Задание A2 — закрытие пробелов контракта и релизная инфраструктура

Дата: 2026-08-21

Идентификаторы и границы

  • Base SHA: e8a404be035fa04b5f76e3e572c6539fba0e83e4 (актуальный origin/main на старте).
  • Ветка: antigravity/contract-gaps.
  • Контракт: docs/UI_STATE_CONTRACT.md обновлён до версии 1.1 первым шагом.
  • Тег v0.1.1 НЕ создавался.
  • Файлы UI (src/antigravity_provider/router/ui/**, hermes_hub_app.py, tests/test_ui_*.py) НЕ изменялись (git diff --name-only по этим путям полностью пуст).

Реализовано и закрыто

1. Канонические публикаторы событий (Gap 9, P0-1)

  • Для каждого объявленного события реализован канонический метод/вызов в HubStateStore:
    • EVENT_ACCOUNT_UPDATED: apply_delta_account_updated публикует payload {profile_id, profile, generation, seq}.
    • EVENT_ACCOUNT_ADDED: apply_delta_account_added публикует payload {provider, profile_id, profile, generation, seq}.
    • EVENT_ACCOUNT_REMOVED: apply_delta_account_removed публикует payload {provider, profile_id, generation, seq}.
    • EVENT_ACCOUNT_AUTH_CHANGED: publish_auth_changed публикует payload {provider, profile_id, auth_state, profile, generation, seq}.
    • EVENT_QUOTA_UPDATED: apply_delta_quota_updated публикует payload {provider, profile_id, snapshot, quota_snapshot, generation, seq}.
    • EVENT_ROUTING_UPDATED: apply_delta_route_changed публикует payload {role_id, active_profile_id, pipeline, failover_reason, generation, seq}.
    • EVENT_AGENT_UPDATED: apply_delta_route_changed / apply_delta_agent_updated публикует payload {role_id, agent, generation, seq}.
    • EVENT_SYSTEM_READINESS_CHANGED: refresh публикует payload readiness.
    • EVENT_REFRESH_STARTED / EVENT_REFRESH_COMPLETED / EVENT_REFRESH_FAILED: планировщик и state store публикуют с монотонными seq и generation.
  • Неиспользуемые мёртвые константы (EVENT_QUOTA_STALE, EVENT_PROVIDER_HEALTH_CHANGED, EVENT_ROUTING_SLOT_UPDATED) удалены из event_bus.py.

2. Происхождение тарифа в ProfileViewModel (Gap 6, P0-2)

  • В ProfileViewModel добавлено поле plan_source: str = "unknown" ("provider_api", "jwt_claim", "provider_auth", "inferred", "unknown").
  • UnifiedHealthService заполняет plan_source из ident.plan.source. UI может достоверно отображать PlanBadge, проверяя plan_source != "unknown".

3. Расширение AgentViewModel и PipelineNode (Gaps 7, 8, P0-3)

  • AgentViewModel:
    • session_id: Optional[str] = None
    • active_quota_status: str = "healthy" ("healthy", "warning", "exhausted")
    • active_quota_label: str = "" (например "Осталось 85%" или "Исчерпана (429)")
  • PipelineNode:
    • account_identity: str = ""
    • quota_status: str = "healthy"
    • failover_reason: Optional[str] = None (содержит реальную причину переключения: "Исчерпана квота (429)", "Требуется авторизация" и т.д., либо None для активного узла / резерва).

4. Измерение и изоляция квот (Gaps 1, 2, P1-4)

  • Структурное разделение model-family buckets (claude, gemini, gpt, grok, opencode) с честными неизвестными значениями (None, is_estimated=True).
  • Runtime 429 парсит ответ провайдера, сбрасывает квоту до 0% и выставляет source="runtime_event", is_estimated=False.

5. Свежесть данных и защита от устаревших ответов (Gaps 3, 10, 11, P1-5)

  • HubSnapshot содержит публичное поле seq: int.
  • Планировщик завершает сбор квот до перестроения снимка.
  • HubStateStore.refresh проверяет request_seq < self._latest_applied_seq и гарантированно отбрасывает устаревшие ответы без повреждения монотонности снимков.
  • Доказано юнит- и интеграционными тестами с асинхронными задержками.

6. Релизная инфраструктура (P1-6)

  • Пакет дистрибутива собран детерминированно: dist/hermes-hub-0.1.1.zip.
  • Хеши обновлены в dist/checksums.txt.
  • Тег v0.1.1 НЕ создавался.

Проверки

  1. Pytest (headless): 167 passed, 22 skipped, 3 deselected in 15.87s.
  2. Ruff linter: All checks passed!.
  3. Release Gate: 7/7 PASSED.
  4. UI Zone Isolation: 0 files modified in UI area.