# Задание: Правдивость данных и готовность к релизу 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 ; 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 ` → HTTP 200, sha256 совпадает. 8. Регрессия не внесена: полный `pytest tests/` зелёный **в окружении без UI-зависимостей** (проверка инварианта `importorskip`), релизный гейт PASSED. 9. Новые тесты на P0-1 и P0-2, падающие на текущем `0c511cd`. ## Что НЕ входит в задание Новая функциональность. Задание закрывает дефекты и готовит релиз; любые новые возможности — после тега.