Full audit of the project (93 findings) plus the review record for rounds 1-5: P0 release blockers,65482e8,42dfe2c, the v0.1.1 candidate verdict, and the review of the previously unreviewed OAuth/wizard/quota work. Includes the remediation task with acceptance criteria that42eddb3was verified against. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
87 lines
8.7 KiB
Markdown
87 lines
8.7 KiB
Markdown
# Задание: Правдивость данных и готовность к релизу 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`.
|
||
|
||
## Что НЕ входит в задание
|
||
Новая функциональность. Задание закрывает дефекты и готовит релиз; любые новые возможности — после тега.
|