62 lines
5.2 KiB
Markdown
62 lines
5.2 KiB
Markdown
# Отчёт: Задание 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`.
|