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>
120 lines
9.4 KiB
Markdown
120 lines
9.4 KiB
Markdown
# Ревью, раунд 4: вердикт по кандидату v0.1.1
|
||
|
||
**Отчёт исполнителя описывает `8314d46`. Фактический `origin/main` — `3aae1a8`, на 3 коммита впереди.**
|
||
Проверка проводилась по фактическому HEAD.
|
||
|
||
**Вердикт: ⛔ тег `v0.1.1` не выпускать.** Заявленное в отчёте сделано и подтверждено, но на текущем HEAD релизный гейт **падает**, а публичный фид обновлений указывает на несуществующий пакет.
|
||
|
||
---
|
||
|
||
## 1. Заявленное в отчёте — подтверждаю
|
||
|
||
| Пункт | Проверка | Итог |
|
||
|---|---|---|
|
||
| Канонический `.cs`: `EnsurePythonDependencies` | `installer/HermesHubSetup.cs:89` — проверка импорта → `ensurepip` → `pip` → фолбэк на `uv` → повторная верификация | ✅ |
|
||
| Канонический `.cs`: копирование assets | строки 263–269, три целевых каталога (install dir, плагин, hermes home) | ✅ |
|
||
| Post-install smoke test | строка 303, `HERMES_HUB_IMPORT_OK`, проверяется ExitCode и наличие маркера | ✅ |
|
||
| M1 — dev-bypass | `allow_dev_local` по умолчанию `False`, оба продакшен-вызова передают `False` явно (`:130`, `:187`) | ✅ |
|
||
| M2 — счётчик гейта | `16/16` в заголовке и в сообщении согласованы | ✅ |
|
||
| M3 — кэш настроек | mtime-кэш + `invalidate_settings_cache()` при сохранении | ✅ |
|
||
| Публичный фид | `HTTP 200`, манифест валидный, v0.1.1 | ✅ |
|
||
|
||
Блокер раунда 3 (исправление P0-1 не в каноническом установщике) **закрыт**.
|
||
|
||
---
|
||
|
||
## 2. ⛔ Блокер 1: релизный гейт падает на текущем HEAD
|
||
|
||
Отчёт цитирует `[RELEASE GATE: PASSED]` — это результат для `8314d46`. На `3aae1a8` фактически:
|
||
|
||
```
|
||
[RELEASE GATE: FAILED] One or more checks failed. Release blocked.
|
||
```
|
||
|
||
Причина — новый `tests/test_codex_opencode_wizard.py` из коммита `3aae1a8` импортирует `customtkinter` на уровне модуля **без `pytest.importorskip`**, и сбор всей сессии прерывается:
|
||
|
||
```
|
||
ERROR tests/test_codex_opencode_wizard.py
|
||
!!! Interrupted: 1 error during collection !!!
|
||
1 skipped, 3 deselected, 1 error
|
||
```
|
||
|
||
Падают пункты гейта 2, 3 и 4. Это возврат ровно того дефекта, который закрывался как **S8** в раунде 2: отсутствие опциональной UI-зависимости должно давать *skip*, а не обрывать прогон. Остальные три тестовых модуля (`test_ui_refinement`, `test_p0_release_gate`, `test_oauth_lifecycle`) `importorskip` содержат — забыли только в новом.
|
||
|
||
Без этого файла суite зелёный: **57 passed, 4 skipped, 3 deselected**. Исходный код, который тестируется (`CodexOAuthSession`, `enable_clipboard_shortcuts`, `HubEntry`, `extract_jwt_identity`), на месте.
|
||
|
||
**Оговорка:** на машине, где `customtkinter` установлен, гейт пройдёт. Но инвариант «отсутствие UI-зависимости не ломает прогон» нарушен — а это ровно тот сценарий, ради которого существует P0-1.
|
||
|
||
**Правка:** одна строка `pytest.importorskip("customtkinter")` в новом файле.
|
||
|
||
---
|
||
|
||
## 3. ⛔ Блокер 2: фид обновлений указывает на несуществующий пакет
|
||
|
||
Манифест живой и отдаёт `HTTP 200`, но пакет из него — нет:
|
||
|
||
```
|
||
package_url: https://github.com/ochenstarik-ui/hermes-hub-releases/releases/download/v0.1.1/hermes-hub-0.1.1.zip
|
||
-> HTTP 404
|
||
gh release list --repo ochenstarik-ui/hermes-hub-releases -> пусто
|
||
```
|
||
|
||
Пункт гейта 7 проверяет только наличие полей `version` и `package_url` в манифесте, но не достижимость самого пакета — поэтому печатает `[LIVE STATUS] Public update manifest live`. Формально верно, по существу — обновление скачать нельзя.
|
||
|
||
Сейчас это не проявится (манифест объявляет 0.1.1, приложение 0.1.1 → «обновлений нет»), но как только выйдет 0.1.2, пользователь получит ошибку загрузки.
|
||
|
||
**Правка:** опубликовать релизный ассет с заявленным `sha256`, а в `check_production_update_feed` добавить HEAD-запрос по `package_url`.
|
||
|
||
---
|
||
|
||
## 4. Артефакт релиза непроверяем из репозитория
|
||
|
||
Отчёт приводит SHA256 собранного установщика `1D41B9D6…`. Проверить его нельзя:
|
||
|
||
```
|
||
файлов dist/ в git: 0 (dist/ в .gitignore)
|
||
локальный dist/HermesHubSetup.exe: 7e2531… (сборка от 20.08 00:16, устаревшая)
|
||
dist/checksums.txt: содержит старую сумму 7E2531…
|
||
```
|
||
|
||
Собранный установщик существует только на машине исполнителя. Любой, кто клонирует репозиторий, установщика не получает, а `checksums.txt` вводит в заблуждение. Для релиза артефакт должен попасть в GitHub Release (там же, где ассет обновления), а `checksums.txt` — обновляться сборочным скриптом.
|
||
|
||
Заявленный clean-install тест в изолированном venv я подтвердить не могу — воспроизвести его без артефакта нечем. Код установщика при этом проверен и выглядит корректно (см. раздел 1).
|
||
|
||
---
|
||
|
||
## 5. Отчёт отстал от кода на 2097 строк
|
||
|
||
После `8314d46` в `main` влиты три коммита, которых отчёт не касается:
|
||
|
||
```
|
||
0d9005f fix(oauth): eliminate ERR_CONNECTION_REFUSED, immediate listener binding, single session reuse
|
||
249a888 feat(oauth): Cockpit Tools model, manual callback fallback, race protection
|
||
3aae1a8 feat(wizard): Codex OAuth/API Key & OpenCode Go with clipboard UX
|
||
```
|
||
|
||
`+2097 / −232` строк: новый `codex_oauth.py` (296), переработанный `profile_oauth.py` (+296), `add_account_wizard.py` (+880), `components.py` (+83), два новых тестовых модуля.
|
||
|
||
Это функциональная разработка, а не закрытие замечаний, и она не отревьюирована. Беглая проверка на утечки: в `codex_oauth.py` и `profile_oauth.py` токены и коды в логи не пишутся — логируются только `source` и HTTP-код. Полноценного ревью этих коммитов не проводилось.
|
||
|
||
**Вердикт по релизу не может покрывать неотрецензированный код.** Либо тег ставится на `8314d46` (после закрытия блокера 2), либо новые коммиты идут на отдельное ревью.
|
||
|
||
---
|
||
|
||
## 6. Условия выпуска v0.1.1
|
||
|
||
1. Добавить `pytest.importorskip("customtkinter")` в `tests/test_codex_opencode_wizard.py`; убедиться, что гейт зелёный в окружении **без** UI-зависимостей.
|
||
2. Опубликовать релизный ассет `hermes-hub-0.1.1.zip` с суммой из манифеста; расширить проверку 7 HEAD-запросом по `package_url`.
|
||
3. Положить `HermesHubSetup.exe` в GitHub Release и обновить `dist/checksums.txt` сборочным скриптом.
|
||
4. Определиться с областью тега: `8314d46` либо отдельное ревью коммитов `0d9005f…3aae1a8`.
|
||
|
||
Пункты 1 и 2 — блокирующие. 3 и 4 — обязательны для честного релиза, но могут быть закрыты процедурно.
|
||
|
||
---
|
||
|
||
## 7. Остаточное из прошлых раундов (не блокирует)
|
||
|
||
- Комментарии в `router_profiles.yaml` стираются при сохранении.
|
||
- `model_timeout_seconds`, `monitoring_interval_seconds`, `auto_monitoring` сохраняются, но не читаются (работают 4 настройки из 7).
|
||
- `tests/test_installer.py` по-прежнему пишет в Start Menu и `HKCU` при запуске с `-m installer`.
|
||
- `_CM_LOCK` на всё время subprocess; глобальная запись `gemini:antigravity` без восстановления; session affinity без TTL; `router_state.json` без межпроцессной блокировки; roadmap-модули не подключены; веб-стек мёртв.
|