A48 (Codex): вёрстка по макетам. style.css изменён на 178 строк, добавлен
workspace.js, приложены 79 скриншотов — до, после, макеты для сверки.
Проверено глазами: логотип, шапка с поиском, панель инструментов холста,
карточки узлов с моделью и аккаунтом, читаемые подписи связей, инспектор с
вкладками, три карточки внизу. Выдуманных чисел из макета нет, пустые
состояния честные.
A47: хранилище AI-Memory под git локально, память проекта приведена к
действительности, worklog заполнен, составлен перечень агентов сервера.
A45: три кандидата замерены. Файлы и размеры сверены по диску, контрольная
сумма Qwen3-Coder пересчитана независимо и совпала. Скорость 109,6 ток/с
на 64К независимо НЕ перемерена: свободно 1,9 ГБ видеопамяти, проверка
потребовала бы остановить рабочий кодер владельца.
A42: подключение OpenRouter, NVIDIA и Ollama, отдельные ветки обнаружения
моделей, отказ с причиной вместо мнимого успеха.
Конфликт A42 с A41 разрешён в пользу A41: ветка A42 отведена от e7194d3,
до слияния A41 в main, поэтому в ней не было динамических префиксов.
Сохранены _get_prefix и генерация слотов; зашитый provider_slots не взят.
Расширенный список ролей openrouter из A42 принят.
Ожидание теста A42 поправлено: nvidia и nvidia-nim — псевдонимы одного
провайдера с одним адаптером, слоты у них общие.
517 passed, ruff clean, релизный гейт 10/10 и на конфигурации владельца,
и на пустой.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1. P0-1: В action_handler.py в add_account реализовано реальное сохранение профилей
и учетных данных для openrouter, nvidia, nvidia-nim, ollama, local, claude, opencode-go.
Для некорректных действий возвращается честная ошибка ok: False вместо мнимого успеха.
В AutoAssigner добавлены слоты и возможности для openrouter и nvidia.
2. P0-2: В ModelDiscoveryService убраны зашитые списки PID. Добавлены ветки
openrouter, nvidia и выделенная ветка ollama (/api/tags и /v1/models). Ошибки серверов
сохраняются и передаются в интерфейс.
3. P0-3: В unified_health.py разделены статусы временного отката ошибки (STATUS_COOLDOWN)
и исчерпания квоты (STATUS_QUOTA_EXHAUSTED). RATE_LIMITED проверяется до кулдаунов.
В health_tracker.py исключена пометка всего аккаунта при пустом model_name.
В codex_adapter.py уточнена классификация ошибок.
4. tests/test_a42_provider_connect.py: 15 тестов, 500 passed, ruff чисто.
1. P0-1: get_default_router_config() возвращает чистую конфигурацию (0 профилей,
13 канонических ролей с пустыми цепочками). Миграция не внедряет фиктивные профили.
2. P0-2: Учетные данные (~/.hermes/*_profiles/, hub_settings.json) изолированы и
никогда не затрагиваются при сбросе или установке.
3. P0-3: Профили создаются динамически при подключении аккаунтов (ag-1, codex-1, etc.).
Пустые цепочки ролей являются нормальным рабочим состоянием.
4. P0-4: Добавлен экшен reset_router_config и кнопка «Начать настройку заново»
в настройках с подтверждением и созданием бэкапа router_profiles.yaml.bak_<timestamp>.
5. P0-5: scripts/verify_multi_provider_router.py адаптирован и проходит 10/10 PASS
как на пустой конфигурации, так и на заполненной.
6. tests/test_a41_clean_install.py: 6 тестов, 490 passed, ruff чисто.
Реализована поддержка произвольных параметров запроса (request_options) для
локальных профилей:
1. RouterProfileConfig и ProfileViewModel дополнены полем request_options
с полной поддержкой вложенных словарей и сериализацией в YAML.
2. LocalLLMAdapter подмешивает request_options в тело POST /chat/completions.
Явные поля запроса имеют приоритет, при расхождениях пишется warning.
Изоляция провайдеров сохранена: другие адаптеры не трогают request_options.
3. Неизвестные/некорректные параметры обрабатываются чисто и классифицируются
как INVALID_REQUEST с извлечением текста ошибки сервера.
4. В веб-интерфейсе реализована карточка профиля с редактором JSON параметров,
живой валидацией синтаксиса, предпросмотром тела запроса и проверкой
подключения.
5. Отсутствие зашитых параметров enable_thinking и reasoning_effort в логике.
6. 526 passed, 3 skipped, 4 deselected, ruff чисто.
Со скриншота владельца: заголовок «Ролей в строю: 0/6», а ниже шесть
предупреждений «роль работает через резервный аккаунт». Пять ролей
исправно отвечали, интерфейс сообщал, что не работает ни одна.
roles_ready считал только роли со здоровым ОСНОВНЫМ профилем. Роль,
обслуживаемая резервом, попадала в degraded_roles, но не в ready.
Ошибка в худшую сторону: отказ показывался там, где всё работает — а
переключение на резерв это ровно то, ради чего продукт и создан.
Теперь роль с живым резервом считается работающей и одновременно
помечается деградировавшей: оба состояния остаются различимыми.
Попутно склонение: «Есть 1 ролей без рабочего маршрута» заменено на
согласованное с числом — 1 роль, 2 роли, 5 ролей.
Проверено на живых данных: 6/6 в строю, состояние «деградация», а не
«критическое».
Тесты: 375 passed, ruff чисто.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Implemented HubSnapshot and central HubStateStore for normalized in-memory state caching (<0.05ms)
- Refactored AccountsView and RoutingView with reusable AccountCardWidget and RoutingRoleWidget to eliminate widget recreation
- Implemented central HermesRefreshScheduler with 5s tick, concurrency throttling, dedup, and spread initial delays
- Added typed EventBus with thread-safe UI main loop dispatching via root.after
- Implemented dynamic ModelRegistry with capability-based role requirements and multi-dimensional scoring
- Integrated Antigravity separate quota buckets (Claude vs Gemini) and same-account model fallback
- Enhanced SessionAffinityTracker with TTL expiration and LRU capacity bounds
- Eliminated long subprocess holding of _CM_LOCK and ensured Windows credential restoration in finally block
- Added FastAPI REST contracts in gui_server.py as foundation for future Tauri frontend
- Verified 100% pass across all 91 pytest tests and 7/7 release gate criteria