# Задание: Правдивость данных и готовность к релизу v0.1.1

## Дата поступления
2026-08-21

## Контекст
По итогам ревью раунда 5 (`0d9005f…0c511cd`, +6970 строк) выявлены два блокирующих дефекта одного класса: **пользователю показываются правдоподобные, но выдуманные данные**. Тесты и релизный гейт при этом зелёные — дефекты не детектируются существующими проверками.

Ветка `main` = `0c511cd`. Тег `v0.1.1` снят с `origin` и локально (указывал на `65482e8` без исправления P0-1).

**Просьба: на время выполнения этого задания заморозить `main` для новой функциональности.** За два предыдущих ревью в ветку влилось ~7300 строк, из-за чего вердикт устаревал к моменту выдачи.

---

## Область задачи (Scope)

### P0-1. Сборщик квот не должен выдавать выдуманные числа за данные провайдера

`src/antigravity_provider/router/quota_collector.py` не делает ни одного сетевого вызова (`urlopen`: 0), но возвращает 17 захардкоженных `used_percent` и помечает снапшоты источниками `antigravity_api`, `codex_usage_api`, `opencode_api`, `claude_oauth_usage_api`, `xai_task_usage_api`. Эти значения выводятся в карточке аккаунта (`ui/views/accounts_view.py:168`).

Выбрать один из путей:

**Путь А (предпочтительный) — реальный сбор.** Запрашивать потребление у провайдера там, где есть API; при успехе оставлять источник `*_api`, при неудаче — переключаться на путь Б.

**Путь Б — честная маркировка.** Если данные вычисляются локально:
- источник снапшота — `estimated` или `baseline`, но **не** `*_api`;
- в UI рядом с корзиной квоты — явный признак оценки (значок/подпись «оценка», не проверено у провайдера);
- значения не должны выглядеть как измерение: либо диапазон, либо «нет данных» вместо `9%`.

Смешанный вариант (А с фолбэком на Б) допустим и желателен.

### P0-2. Убрать тихий фолбэк на поддельный код авторизации

`router/codex_oauth.py:103–112` и `router/grok_oauth.py:91–94` при недоступности эндпоинта провайдера генерируют локальные `user_code` (`CDX-…`, `GRK-…`) и `device_code`/`device_auth_id`. По RFC 8628 их выдаёт сервер авторизации; локально сгенерированные ему неизвестны, поллинг гарантированно завершается таймаутом через 15 минут, а пользователь всё это время видит правдоподобный код.

Требуется:
- в обычном режиме при неудаче запроса кода — **немедленная ошибка** с текстом причины в мастере, без запуска поллинга;
- фолбэк на локальную сессию — только под явным `HERMES_HUB_DEV_MODE=1` (по образцу `update_manager.is_allowed_update_host`), с видимой пометкой в UI, что сессия тестовая;
- проверить остальные OAuth-модули (`claude_oauth.py`, `profile_oauth.py`) на такой же паттерн.

### P1-3. Распространить решение по OAuth-клиентам на новых провайдеров

`docs/OAUTH_CLIENT.md` описывает только Google. В коде появились ещё три заимствованных клиента:
```
codex_oauth.py:31  app_EMoamEEZ73f0CkXaXp7hrann          (OpenAI)
grok_oauth.py:30   b1a00492-073a-47ea-816f-4c329264a828  (xAI)
claude_oauth.py    клиент Claude
```
Добавить их в документ с той же структурой: тип клиента, модель угроз, обоснование по RFC 8252/7636, явное указание происхождения.

### P1-4. Определить судьбу `gui_server.py`

Файл вырос ещё на 112 строк, но `run_gui_server` не вызывается ниоткуда (проверено по `.py`, `.bat`, `.ps1`, `.cs`). Либо подключить, либо вынести в `legacy/`, либо удалить вместе с `gui_cockpit.html`. При удалении — убрать `fastapi`/`uvicorn` из обязательных зависимостей `pyproject.toml`.

### P1-5. Организационные пункты релиза (из раунда 4)

1. Опубликовать GitHub Release в `ochenstarik-ui/hermes-hub-releases`: ассет `hermes-hub-0.1.1.zip` с суммой, совпадающей с `sha256` в `update_manifest.json` (сейчас `package_url` → HTTP 404).
2. Положить туда же `HermesHubSetup.exe`; `dist/checksums.txt` обновлять сборочным скриптом, а не вручную.
3. Тег `v0.1.1` ставить только на коммит, прошедший ревью. Если локальный тег остался на машине исполнителя — удалить: `cd <repo>; git tag -d v0.1.1`.

### P2-6. Долг, накопленный за пять раундов (в обычную очередь)

- `capability_matrix`, `lifecycle_supervisor`, `skill_registry`, `deepseek_adapter` — не подключены ни к одному кодовому пути; подключить либо пометить экспериментальными.
- Комментарии в `router_profiles.yaml` стираются при сохранении.
- `model_timeout_seconds`, `monitoring_interval_seconds`, `auto_monitoring` сохраняются, но не читаются (работают 4 настройки из 7).
- `tests/test_installer.py` при `-m installer` пишет в Start Menu и `HKCU`.
- `_CM_LOCK` удерживается на всё время subprocess `agy`; глобальная запись `gemini:antigravity` перезаписывается без восстановления.
- `health_tracker`: запись атомарна, но межпроцессной блокировки нет (last-writer-wins между GUI и Hermes).

---

## Критерии приёмки

Ревью будет проверять ровно это, исполнением:

1. `grep -c urlopen quota_collector.py` > 0 **либо** ни один снапшот с локально вычисленными значениями не имеет источник `*_api`. Проверяется вызовом сборщика и чтением поля `source`.
2. В UI карточки аккаунта для оценочных данных присутствует визуальный признак оценки.
3. При недоступности эндпоинта устройства (мокируется исключением в `_post_json`) и **без** `HERMES_HUB_DEV_MODE`: `start()` возвращает ошибку, `status != "pending"`, поток поллинга не стартует.
4. С `HERMES_HUB_DEV_MODE=1` фолбэк работает и помечен в UI.
5. `docs/OAUTH_CLIENT.md` содержит разделы по OpenAI, xAI и Claude.
6. `run_gui_server` либо вызывается, либо файла нет в `src/`.
7. `curl -I <package_url из манифеста>` → HTTP 200, sha256 совпадает.
8. Регрессия не внесена: полный `pytest tests/` зелёный **в окружении без UI-зависимостей** (проверка инварианта `importorskip`), релизный гейт PASSED.
9. Новые тесты на P0-1 и P0-2, падающие на текущем `0c511cd`.

## Что НЕ входит в задание
Новая функциональность. Задание закрывает дефекты и готовит релиз; любые новые возможности — после тега.
