hermes-hub/agents/inbox/2026-08-20-full-audit-and-improvement-backlog.md
Hermes Team 46a185395c docs(review): add independent audit, five review rounds, and remediation task
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 that 42eddb3 was verified against.

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

256 lines
31 KiB
Markdown
Raw 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.

# Полный аудит Hermes Hub и бэклог доработок
**Дата аудита:** 2026-08-20
**Проверенная ревизия:** `origin/main` @ `5ccfd48` (github.com/ochenstarik-ui/hermes-hub, private)
**Метод:** статический разбор всех исходников + прогон тестов на чистом checkout `origin/main` в отдельном worktree
**Версия:** 0.1.0 (`pyproject.toml`, `compatibility.json`) против 1.3.0 (`about_view.py`, `gui_server.py`)
**Объём:** ~19 500 строк (Python ~15k, C# 0.8k, HTML 0.85k, PS1/BAT 0.25k, docs/config ~2.5k)
> Первая редакция этого документа делалась по локальному снимку `fdf9ecc` (на 3 коммита старше). Все пункты ниже перепроверены по `origin/main`; раздел 2 фиксирует, что именно уже исправлено в `7609ad8`.
---
## 1. Общая оценка
Ядро маршрутизации (`router_engine`, `health_tracker`, `session_affinity`, адаптеры) спроектировано грамотно: чистые слои, dataclass-модели, потокобезопасность, детерминированные тесты с моками. Коммит `7609ad8` («product stabilization») закрыл заметную часть проблем презентационного слоя — появился кэш сканирования, строгий resolver статусов, идентичность приложения в Windows, предпрогрев экранов.
Тем не менее **продукт остаётся неработоспособным как приложение**:
- нативное приложение не запускается на чистой машине — ни один установщик не ставит зависимости UI;
- failover для основного провайдера (Antigravity) не срабатывает никогда из-за формата ошибок `agy_generate`;
- три пользовательских сценария падают с `AttributeError`/`NameError`: удаление credentials, подключение аккаунта по API-ключу, перераспределение ролей;
- настройки не сохраняются и ни на что не влияют;
- «roadmap»-модули (+819 строк) не подключены ни к одному кодовому пути.
**Фактический прогон тестов на чистом checkout `origin/main`:**
`1 failed, 28 passed, 2 skipped` + 1 ошибка сбора (`test_ui_refinement.py` не импортируется без `customtkinter`).
Отчёт `agents/done/…stabilization…md` заявляет «35/35 PASSED» — это верно только на машине, где `dist/` существует локально и зависимости доустановлены руками.
**Зрелость:** ядро — Beta, оболочка — Alpha, упаковка — не готова к дистрибуции.
---
## 2. Что уже исправлено в `7609ad8` (не требует работы)
| Было в аудите | Статус в `origin/main` |
|---|---|
| `TeamView.update_data(app_state)` требует аргумент → главный экран не обновляется | **Исправлено** — сигнатура унифицирована (`app_state=None`) во всех view |
| `scan_all()` вызывается 910 раз за один refresh | **Исправлено** — TTL-кэш 30 с (`unified_health.py:248`) |
| Ложные `HEALTHY`/`QUOTA_EXHAUSTED` у неподключённых слотов | **Исправлено** — введён `STATUS_NOT_CONFIGURED`, устаревшие записи квот чистятся |
| Иконка Python в панели задач | **Исправлено**`SetCurrentProcessExplicitAppUserModelID("HermesHub.Desktop")` + multi-res `.ico` |
| Лаг переключения вкладок | **Исправлено** — предпрогрев всех 8 экранов в `__init__`, переключение через `pack_forget()` |
| Установщик не копирует `assets/branding` | **Исправлено** в новом `installer/HermesHubSetup.py``.cs` и `install.ps1` — нет) |
| Нет документации по разработке/безопасности/производительности | **Исправлено** — добавлены `docs/AUTH.md`, `DEVELOPMENT.md`, `PERFORMANCE.md`, `ROUTER.md`, `SECURITY.md` |
| Нет адаптивности окна | **Исправлено** — debounce-обработчик resize |
---
## 3. P0 — Блокеры (перепроверено на `origin/main`, всё воспроизводится)
| # | Дефект | Файл | Последствие |
|---|---|---|---|
| 1 | `customtkinter` и `pillow` не устанавливаются ни `HermesHubSetup.py`, ни `HermesHubSetup.cs`, ни `install.ps1` | все три установщика | Запуск через `pythonw.exe` завершается молча: ни окна, ни ошибки. Проверено: в `%LOCALAPPDATA%\hermes\hermes-agent\venv` пакета нет |
| 2 | `ProfileAuthManager.get_profile_dir` не существует — это модульная функция, а не метод класса | `profile_manager.py:79` vs `gui_server.py:216`, `hermes_hub_app.py:120`, `add_account_wizard.py:200` | `AttributeError` при удалении credentials и при сохранении API-ключа |
| 3 | `json` не импортирован, но используется | `ui/add_account_wizard.py:200` | `NameError`**Codex и OpenCode Go нельзя подключить через UI вообще** |
| 4 | `AutoAssigner.auto_assign_all` не существует | `hermes_hub_app.py:411`, `team_view.py:188,243` | Кнопки «Перераспределить роли» и «⋮» падают |
| 5 | `agy_generate` возвращает ошибки как успешный `chat.completion`: текст ошибки в `content`, ключа `error` нет | `agy_subprocess.py:584` + `router_engine.py` | `RouterEngine` проверяет `if "error" in response` → не срабатывает → `mark_success`, **failover для Antigravity не работает никогда**, пользователь получает текст ошибки вместо ответа модели |
| 6 | Мастер ждёт `session.status == "error"`, сессия ставит `"failed"` | `add_account_wizard.py:243` vs `profile_oauth.py` | При ошибке OAuth мастер молча висит 120 с |
| 7 | Кнопка «Назначить» шлёт action `assign_role`, обработчика нет | `accounts_view.py:244` vs `hermes_hub_app._handle_action` | Кнопка не делает ничего, без обратной связи |
| 8 | Шаг 4 мастера не применяет выбранную роль — только пишет в журнал | `add_account_wizard.py:_finish` | Выбор пользователя игнорируется |
| 9 | Шаг 3 показывает «✓ Аккаунт успешно проверен» без всякой проверки для API-ключей; список моделей захардкожен (`gpt-4.1`, `qwen-coder`, `deepseek-v2`) | `add_account_wizard.py` | Ложноположительная валидация, вымышленные модели |
---
## 4. P1 — Производительность и отзывчивость UI
| # | Проблема |
|---|---|
| 10 | `_restore_status()` вызывает `get_system_readiness()` **в UI-потоке** через `after(6000, …)`. При холодном/истёкшем кэше — блокировка окна на время сетевого скана 16 профилей |
| 11 | При промахе кэша `scan_all()` опрашивает 16 профилей последовательно (таймаут 10 с на профиль) — нет параллелизма и общего бюджета времени |
| 12 | 5 экранов (`accounts`, `health`, `providers`, `routing`, `logs`) полностью уничтожают и пересоздают виджеты через `winfo_children()` + `destroy()` — мерцание, потеря позиции скролла |
| 13 | Нет периодического автообновления: данные устаревают до ручного нажатия «Обновить» (таймер только для resize) |
| 14 | Тост затирает строку состояния и восстанавливается блокирующим вызовом |
---
## 5. P1 — Логика роутера и корректность состояний
Файлы `router_engine.py`, `health_tracker.py`, `agy_subprocess.py`, `profile_manager.py`, `router_config.py`, `session_affinity.py`, `hermes_plugin.py` в `7609ad8` **не менялись** — все находки в силе.
| # | Проблема | Файл |
|---|---|---|
| 15 | `_CM_LOCK` удерживается всё время subprocess `agy` (до 180+ с) → все Antigravity-профили сериализуются, параллельная работа команды невозможна | `antigravity_adapter.py` |
| 16 | Профильные токены пишутся в **глобальную** запись `gemini:antigravity` Credential Manager и не восстанавливаются → «основной аккаунт Hermes» меняется как побочный эффект маршрутизации; гонки с самим `agy` и Hermes CLI | `antigravity_adapter.py` |
| 17 | `overall_state` не сбрасывается при истечении cooldown (только в `mark_success`) → профиль остаётся «Квота исчерпана» бессрочно | `health_tracker.py:is_healthy` |
| 18 | Роутер решает по состоянию семейства моделей, UI — по `overall_state`: роутер шлёт запросы в профиль, который UI показывает мёртвым | `health_tracker.py` / `unified_health.py` |
| 19 | Session affinity без TTL и вытеснения — неограниченный рост памяти; `session_affinity_ttl_seconds` из шаблона конфига не реализован | `session_affinity.py` |
| 20 | `router_state.json` пишется без межпроцессной блокировки — GUI и процесс Hermes затирают состояние друг друга | `health_tracker.py` |
| 21 | `ProfileHealthRecord.active_leases` всегда 0, но выводится в CLI и API | `health_tracker.py`, `cli_commands.py` |
| 22 | Категория `TRANSIENT` классифицируется, но обрабатывается как обычный отказ — без повтора и задержки | `router_engine.py` |
| 23 | Классификация ошибок по подстрокам (`"429" in err_lower`) — ложные срабатывания на любом тексте с «429» | все адаптеры |
| 24 | `_safe_env()` не используется: `custom_env = dict(os.environ)` передаёт в subprocess `agy` все ключи (`OPENAI_API_KEY` и пр.) | `agy_subprocess.py`, `antigravity_adapter.py` |
| 25 | Нет стриминга ответов — Hermes получает только полный ответ | `router_engine.py` |
| 26 | Нет учёта токенов, стоимости и latency между вызовами | — |
| 27 | В шаблоне `router_profiles.example.yaml` блок `router:` полностью игнорируется загрузчиком (ожидаются ключи верхнего уровня); `max_failover_attempts`, `cooldown_base_seconds`, `cooldown_max_seconds`, `session_affinity_ttl_seconds` отсутствуют в схеме | `router_config.py:load_router_config` |
| 28 | `save_router_config` пишет другую структуру, чем шаблон → первое сохранение («назначить оркестратором») уничтожает комментарии и структуру пользовательского YAML | `router_config.py` |
| 29 | `max_concurrency=1` для Codex и OpenCode во встроенном дефолте, хотя это stateless REST (в шаблоне 2 и 3) — искусственное ограничение пропускной способности | `router_config.py` |
| 30 | `antigravity_llm_execution` перехватывает **все** вызовы `llm_execution` независимо от провайдера и никогда не вызывает `next_call`; ошибка роутера логируется на уровне `debug` | `hermes_plugin.py` |
| 31 | Каталог моделей захардкожен (`gemini-3.7-flash`, `qwen3.8-max`, `kimi-k2.7-code`…) и не сверяется с реальным | `router_config.py` |
| 32 | `discover_models()` определяет каталог, вызывая `agy` с заведомо невалидной моделью и парся текст ошибки | `agy_subprocess.py` |
| 33 | `AutoAssigner.check_duplicate_identity` сравнивает `auth_data["email"]`, но `profile_oauth` сохраняет только `{"token", "auth_method"}`**детектор дубликатов не срабатывает никогда** | `auto_assigner.py` |
---
## 6. P1 — Безопасность
| # | Проблема |
|---|---|
| 34 | `CLIENT_ID`/`CLIENT_SECRET` Google зашиты в код и **склеены из фрагментов строк** (`"GOC" + "SPX" + …`, `oauth.py:26-28`) — приём обхода сканеров секретов, чужой OAuth-клиент. Требует явного решения: собственный клиент или документированное заимствование. Отчёты «0 секретов при сканировании» проходят именно из-за склейки |
| 35 | `ProfileAuthManager.save_profile_auth` пишет токены plaintext без ограничения ACL. `docs/SECURITY_MODEL.md` заявляет изоляцию «правами текущего пользователя ОС», но код прав не выставляет (`chmod` есть только в `CredentialStore` и на Windows не работает) |
| 36 | `access_token` передаётся в query-строке при верификации (`tokeninfo?access_token=…`) — попадает в логи |
| 37 | `CORSMiddleware(allow_origins=["*"], allow_credentials=True)` на локальном API с эндпоинтами `delete`, `set-main`, `oauth/start` (`gui_server.py`) |
| 38 | Лаунчер генерирует и исполняет Python-скрипт `%LOCALAPPDATA%\hermes\hermes_hub_entry.py` при каждом запуске — вектор подмены между записью и стартом |
| 39 | Нет подписи установщика и лаунчера; `dist/checksums.txt` формируется вручную и не проверяется при установке |
| 40 | В `hermes-hub.log` пишутся тексты ошибок провайдеров без санитизации (могут содержать фрагменты токенов) |
---
## 7. P1 — Тесты и качество
| # | Проблема |
|---|---|
| 41 | `pytest tests/` **падает на сборе**: `test_ui_refinement.py``hermes_hub_app``customtkinter` |
| 42 | `test_setup_exe_exists` **падает на чистом checkout**: `dist/` в `.gitignore`, ещё 2 теста уходят в skip. Реальный результат — `1 failed, 28 passed, 2 skipped`, а не заявленные 35/35 |
| 43 | Тесты мутируют реальные пользовательские данные: `do_set_main` пишет `router_active_profile.json`, `do_set_orchestrator` перезаписывает `router_profiles.yaml`, `get_profile_env_dir` создаёт каталоги профилей. Нет фикстуры с временным `HERMES_HOME` |
| 44 | `test_installer.py` **запускает реальный установщик**: копирование в `%LOCALAPPDATA%`, ярлык, запись в реестр |
| 45 | Тесты ходят в сеть (Google tokeninfo, OpenCode `/models`) — недетерминированность |
| 46 | Нет тестов на: `classify_error` всех адаптеров, мастер подключения, YAML round-trip `load↔save`, CLI, логику установщиков |
| 47 | Нет CI (`.github/workflows` отсутствует, репозиторий приватный) |
| 48 | `ruff` в dev-зависимостях, но нет секции `[tool.ruff]` и запуска; нет `mypy` |
---
## 8. P1 — Упаковка, установка, дистрибуция
| # | Проблема |
|---|---|
| 49 | **Два параллельных установщика**: `installer/HermesHubSetup.cs` (711 строк, GUI-мастер, silent-режим, реестр, коды 0/10/11/12) и `installer/HermesHubSetup.py` (101 строка, копирует assets, но без реестра, ярлыка, silent-кодов). Неясно, какой канонический; `dist/HermesHubSetup.exe` собран из `.cs` |
| 50 | Проверка совместимости фиктивна: `compatibility.json` не читается, `MIN_HERMES_VERSION` ни с чем не сравнивается, `IsHermesCompatible = true` всегда при наличии Python → **код возврата 11 недостижим**. То же в `install.ps1` (версия печатается, но не проверяется) |
| 51 | `installer/HermesHubSetup.cs` и `scripts/install.ps1` не копируют `assets/branding` (исправлено только в `.py`-варианте) |
| 52 | `ui/assets.py:39` — захардкоженный fallback `Path("E:/Agent projects/hermes-hub")` в исходниках |
| 53 | `build_launcher.ps1` не передаёт `/win32icon:HermesHub.ico`у самого `.exe` нет иконки (иконка ставится только в рантайме через `iconbitmap`) |
| 54 | `install.ps1` копирует `__pycache__` |
| 55 | `launcher/HermesHub.exe` — собранный бинарник в git; собранный установщик, наоборот, не отслеживается |
| 56 | Нет single-instance guard — повторный клик по ярлыку открывает второе окно |
| 57 | Нет логирования запуска: при `pythonw.exe` любая ошибка импорта = полная тишина |
| 58 | Нет механизма обновления в самом приложении |
| 59 | Версия расходится: `0.1.0` (pyproject, compatibility.json, installer) против `1.3.0` (About, FastAPI) |
| 60 | `scripts/launch_hermes_hub.bat` запускает несуществующий веб-режим на `:8765`; CLI-аргументы `hub --port/--no-browser` парсятся и игнорируются |
---
## 9. P2 — Мёртвый и неподключённый код
| # | Объект | Строк | Статус |
|---|---|---|---|
| 61 | `supervisor/lifecycle_supervisor.py`, `supervisor/policies.py`, `capability/capability_matrix.py`, `skills/skill_registry.py`, `scheduler/task_safety.py`, `adapters/deepseek_adapter.py` | 819 | **Roadmap-модули из `7609ad8` не подключены ни к одному кодовому пути.** Импортируются только тестами (`task_safety` и `deepseek_adapter` — вообще ничем). `DeepSeekResponsesAdapter` не зарегистрирован в `_ADAPTERS` → недостижим через `get_adapter()` |
| 62 | `gui_server.py` + `gui_cockpit.html` | 1177 | Параллельный веб-стек, не запускается ниоткуда; `fastapi`/`uvicorn` остаются обязательными зависимостями |
| 63 | `runtime.generate_chat_completion`, `antigravity_client.py`, `transform.py`, `openai_compat.py`, `cloudcode.py` | ~590 | Прямой API-путь к Antigravity, не используется (весь трафик через `agy` CLI) |
| 64 | `ui/views/dashboard_view.py` («Главная») | 141 | Не подключён к навигации |
| 65 | `ui/splash.py` (`SplashScreen`) | 77 | Не используется |
| 66 | `HealthTracker.get_status_summary()` | — | Не вызывается ниоткуда |
| 67 | Резолвинг `hermes_home` | — | Продублирован в 5 файлах с тремя разными реализациями (`HERMES_HOME` / `LOCALAPPDATA` / `~/.hermes`) |
| 68 | `do_set_main`/`do_test_profile`/`do_delete_credentials` | — | Дублируются между `gui_server.py` и `hermes_hub_app.py` |
---
## 10. P2 — Документация
| # | Проблема |
|---|---|
| 69 | `docs/ARCHITECTURE.md` и `CHANGELOG.md` описывают «Edge App Mode», «FastAPI Backend :8765», «health check gate (HTTP 200)» — этой архитектуры больше нет |
| 70 | `agents/AGENTS.md` и отчёты в `agents/done/` указывают Source of Truth `E:\Agent projects\hermes-hub`; ссылки вида `file:///E:/Agent%20projects/...` мертвы |
| 71 | `docs/SECURITY_MODEL.md` не описывает фактическую подмену глобальной записи `gemini:antigravity` при маршрутизации |
| 72 | Нет описания схемы `router_profiles.yaml` (единственный источник истины — код) и справочника CLI |
| 73 | Отчёты в `agents/done/` содержат утверждения, не подтверждаемые кодом: «35/35 PASSED», «интерактивные переключатели параметров», «9/9 экранов», «иконка вшита в лаунчер». Требуется выравнивание с фактами |
| 74 | UI жёстко на русском, CLI на английском, строки не вынесены — i18n невозможен |
---
## 11. P2P3 — Функциональные пробелы
| # | Пробел |
|---|---|
| 75 | Настройки не сохраняются: `CTkSwitch`/`CTkOptionMenu` не привязаны к `self.settings` (нет ни одного `command=`), `_save_settings()` пишет неизменённый словарь |
| 76 | Ни один параметр не влияет на роутер: `failover_attempts`, `session_affinity`, `auto_failover`, `model_timeout_sec`, `monitoring_interval_min` нигде не читаются |
| 77 | Пути в «Настройках» указывают на `hermes\router_profiles.yaml` и `hermes\auth.json`; реальные — `hermes\config\router_profiles.yaml` и `hermes\agy_profiles\<id>\auth.json` |
| 78 | Нет ручного назначения профиля на роль (только автоматическое) |
| 79 | Экран «Маршрутизация» read-only: нельзя изменить цепочку failover |
| 80 | Нельзя добавить или удалить слот — 16 профилей жёстко зашиты в коде |
| 81 | Кнопка «Обновить модели» не вызывает `adapter.discover_models()` — показываются `preferred_models` из конфига |
| 82 | Фоновый мониторинг здоровья отсутствует, хотя переключатель для него есть |
| 83 | Нет уведомлений (tray/toast) об исчерпании квоты и переключении на резерв |
| 84 | Нет экспорта/импорта конфигурации и резервного копирования профилей |
| 85 | Нет истории квот и использования |
| 86 | Журнал живёт в памяти (200 записей) и обнуляется при перезапуске; `hermes-hub.log` пишется, но не читается обратно |
| 87 | В журнале нет поиска и фильтра по уровню (только по категории) |
| 88 | Тема жёстко тёмная, нет клавиатурной навигации и доступности |
| 89 | `compatibility.json` заявляет `linux`/`darwin`, но Credential Manager, пути и лаунчер — только Windows |
---
## 12. Рекомендуемый план работ
### Этап 1 — Вернуть работоспособность (P0, ~2 дня)
1. Устанавливать `customtkinter`/`pillow` в venv Hermes из установщика; проверять импорт после установки и падать с внятной ошибкой.
2. Исправить `get_profile_dir` (сделать `@staticmethod` либо импортировать функцию), добавить `import json` в мастер.
3. Реализовать `AutoAssigner.auto_assign_all()` либо убрать кнопки.
4. Ввести маркер ошибки в `agy_generate` (`{"error": …}` или исключение) и восстановить failover для Antigravity; покрыть регрессионным тестом.
5. Починить мастер: статус `"failed"`, реальная валидация API-ключа, реальные модели, применение выбранной роли, обработчик `assign_role`.
6. Прогонять `pytest` в изолированном `HERMES_HOME`; убрать запуск установщика и сетевые вызовы из тестов; сделать `test_setup_exe_exists` skip-ом при отсутствии `dist/`.
### Этап 2 — Корректность состояний и отзывчивость (P1, ~3 дня)
7. Все сетевые операции — только в фоне; `after(0, …)` получает готовые данные (включая `_restore_status`).
8. Параллельный опрос профилей с общим бюджетом времени вместо последовательного.
9. Обновление виджетов in-place вместо `destroy()`/пересоздания в 5 экранах.
10. Сброс `overall_state` при истечении cooldown; единый источник истины по здоровью для роутера и UI.
11. TTL и вытеснение в `SessionAffinityTracker`; файловая блокировка `router_state.json`.
12. Сузить `_CM_LOCK` до операции подмены credential и восстанавливать прежнюю запись — либо перейти на изоляцию только через `USERPROFILE`.
13. Связать `settings_view` с реальными параметрами роутера; выровнять пути.
14. Починить `check_duplicate_identity` (сохранять `email` в `auth.json` при OAuth).
### Этап 3 — Безопасность и упаковка (P1, ~2 дня)
15. Решение по OAuth-клиенту; прекратить склейку секрета из фрагментов.
16. ACL/DPAPI для `auth.json`; санитизация логов; убрать токен из query-строки.
17. Убрать `allow_origins=["*"]` либо удалить веб-стек целиком.
18. Выбрать один установщик; реальная проверка версии из `compatibility.json` (сделать код 11 достижимым); исключить `__pycache__`; убрать `E:/…` fallback; встроить иконку через `/win32icon`.
19. Логирование запуска в файл до инициализации UI; single-instance guard.
### Этап 4 — Долг и документация (P2, ~2 дня)
20. Подключить roadmap-модули к реальным кодовым путям (как минимум зарегистрировать `DeepSeekResponsesAdapter` в `_ADAPTERS`) либо явно пометить их как экспериментальные.
21. Удалить или вынести в `legacy/` веб-стек и прямой API-путь; убрать `fastapi`/`uvicorn` из обязательных зависимостей.
22. Единый модуль `paths.py`; устранить дублирование `do_*`.
23. Синхронизировать версию (0.1.0), обновить `ARCHITECTURE.md`/`CHANGELOG.md` под нативную архитектуру, исправить пути `E:\`.
24. Выровнять отчёты в `agents/done/` с фактическим состоянием.
25. Добавить CI (pytest + ruff) и конфигурацию ruff.
### Этап 5 — Развитие (P3)
26. Ручное назначение ролей и редактор цепочек failover.
27. Динамические слоты, реальный `discover_models`.
28. Фоновый мониторинг + уведомления о квотах.
29. Персистентный журнал с поиском; статистика использования.
30. Стриминг ответов, учёт токенов и стоимости.
31. Экспорт/импорт конфигурации, бэкап профилей.
---
## 13. Сводка
| Приоритет | Пунктов | Область |
|---|---|---|
| **Исправлено в `7609ad8`** | 8 | Кэш сканирования, resolver статусов, идентичность Windows, предпрогрев, assets, docs |
| **P0** — блокеры | 9 | Запуск приложения, failover Antigravity, падения UI, мастер подключения |
| **P1** — критично | 51 | Отзывчивость, корректность состояний, безопасность, тесты, упаковка |
| **P2** — важно | 20 | Неподключённый код, архитектурный долг, документация |
| **P3** — развитие | 9 | Новая функциональность |
| **Итого к работе** | **89** | |