hermes-hub/agents/inbox/2026-08-21-B3-codex-contract-v11-fields.md
Hermes Team 9ffc815ed5 docs(task): B3 — wire the contract v1.1 fields the UI never picked up
Codex built phases 2-6 against contract v1.0 while Antigravity shipped v1.1, so
eight fields now exist in the snapshot and render nowhere: plan_code,
plan_source, active_quota_status, active_quota_label, quota_status,
failover_reason, unavailable_reason and seq. PlanBadge was built in phase 1 and
still has nothing to display.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:50:22 +07:00

97 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Задание B3 (Codex): подключить поля контракта v1.1
## Дата поступления
2026-08-21
## База
Проверочный HEAD: **`2c612f2`**, `origin/main` = `2c612f2`. Перед началом `git fetch` и обязательно подтянуть `main` — ваши фазы 26 уже влиты, поверх них есть правки.
## Ветка
`codex/contract-v11`. Ветка `codex/ui-redesign` влита в `main`.
---
## Что принято по фазам 26
Проверено исполнением, работа хорошая:
- граница соблюдена — вне вашей зоны только файл отчёта;
- **пересоздания виджетов не осталось нигде**: ни одного `winfo_children()` в `views/`, всё на стабильных ключах;
- **выдуманных метрик нет**, «Н/Д» используется в семи экранах;
- **views вообще не обращаются к backend** — ни `HubStateStore`, ни `scan_all`, ни сервисов; данные приходят только снапшотом;
- мастер подключения пережил слияние: трёхэлементная распаковка `start_profile_oauth` и `oauth_port` на месте;
- защита от краша при старте не только сохранена, но усилена — `update_data` выходит рано вместо отката к хранилищу.
Одна правка с моей стороны: инвариант `tests/test_view_startup_contract.py` требовал обращения к хранилищу и после вашей переделки начал скипаться для всех девяти views, то есть перестал защищать тот самый краш. Переписан под новый контракт — проверка `isinstance(snapshot, HubSnapshot)` теперь обязательна независимо от того, читает ли view хранилище.
---
## Задача
Вы работали по контракту **v1.0**, а Antigravity параллельно выпустил **v1.1** и добавил поля, которых на тот момент не было. Данные в снапшоте есть, но интерфейс их не показывает. Проверено на `2c612f2`:
| Поле | Где появилось | Используется в UI |
|---|---|---|
| `plan_code` | `ProfileViewModel` | **0 файлов** |
| `plan_source` | `ProfileViewModel` | **0 файлов** |
| `active_quota_status` | `AgentViewModel` | **0 файлов** |
| `active_quota_label` | `AgentViewModel` | **0 файлов** |
| `quota_status` | `PipelineNode` | **0 файлов** |
| `failover_reason` | `PipelineNode` | **0 файлов** |
| `unavailable_reason` | `QuotaBucket` | **0 файлов** |
| `seq` | `HubSnapshot` | **0 файлов** |
| `session_id` | `AgentViewModel` | 1 файл |
| `account_identity` | `PipelineNode` | 4 файла |
| `is_estimated` | `QuotaSnapshot` | 2 файла |
Перечитайте `docs/UI_STATE_CONTRACT.md` целиком — он переписан, появился раздел «Provider Truth Matrix».
### 1. Тариф — `PlanBadge` наконец можно показать
Компонент вы сделали в PHASE 1, данные появились в v1.1. Показывать бейдж, когда `plan_source` говорит, что тариф известен от провайдера (`provider_api`, `jwt_claim`, `provider_auth`), и **не показывать** при `inferred`/`unknown` — либо показывать с явной пометкой, что значение выведено, а не получено. Пользователь должен отличать «PRO по данным провайдера» от «похоже на PRO».
### 2. Квоты — состояние без данных
`QuotaBucket.unavailable_reason` объясняет, **почему** данных нет. Сейчас пользователь видит пустоту без причины. Показывать причину в подсказке или подписи корзины.
Важно: по контракту baseline-значения теперь `None`, а не числа. Убедитесь, что `QuotaBar` и `QuotaBucketWidget` корректно отрисовывают именно отсутствие значения, а не «0 %» — ноль означает «квота исчерпана», это принципиально разные состояния.
### 3. Команда — состояние агента
`active_quota_status` и `active_quota_label` показывают, в каком состоянии квота у аккаунта, на котором сейчас работает агент. Это прямо отвечает на вопрос «сколько осталось у того, кто выполняет задачу».
### 4. Маршрутизация — причина переключения
`PipelineNode.failover_reason` и `quota_status` — то, ради чего экран существует: видно не только «активен резерв 1», но и почему ушли с основного. Показывать причину у узла, с которого произошло переключение.
### 5. Свежесть данных
`HubSnapshot.seq` и политика `is_stale` (по контракту — просрочка фонового обновления свыше 300 с). Показать пользователю, что данные устарели, вместо молчаливого показа старых значений.
---
## Ограничения
- Граница прежняя: ваша зона — `src/antigravity_provider/router/ui/**`, `hermes_hub_app.py`, `tests/test_ui_*.py`. Остальное не трогать.
- Не добавлять сбор данных в UI. Не хватает поля — строка в разделе «Backend gaps» отчёта.
- Нет данных — «Н/Д» либо скрытый блок. Ноль и отсутствие значения не путать.
- Секреты маскировать, в логи не писать.
- Тег `v0.1.1` не создавать.
---
## Критерии приёмки
1. Ни один файл чужой зоны не изменён.
2. `PlanBadge` отображается и различает известный тариф от выведенного.
3. Отсутствие данных о квоте отрисовано как отсутствие, а не как ноль; причина видна пользователю.
4. Экран «Команда» показывает состояние квоты активного аккаунта агента.
5. Экран «Маршрутизация» показывает причину переключения там, где она есть в состоянии.
6. Устаревание снапшота видно пользователю.
7. Тесты на каждый пункт: известный и выведенный тариф, корзина без данных против нулевой, причина переключения, устаревший снапшот.
8. Прогон **в обоих окружениях** — без UI-зависимостей и с `customtkinter`/`pillow`/`psutil`; обе команды и оба результата в отчёте. Прогон только headless не считается: ваши UI-тесты там пропускаются.
9. `ruff check .` чисто; release gate не ухудшен.
10. Отчёт: `BASE_SHA`, `FINAL_SHA`, изменённые файлы, что подключено, что осталось, раздел «Backend gaps».
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA` и не вести разработку поверх него до вердикта.