Ветка installer/a61-live-verification (agy, коммит b0644a3) частично
пересекалась с HUB-1, частично добавляла то, чего в HUB-1 не было. Пункты
взяты по одному, дубли — нет.
## Взято
1. verify_multi_provider_router.py проверял изоляцию пути на ID "ag-w2" —
на живой машине владельца это существующий подключённый профиль, и
"assert not pdir.exists()" падал не из-за бага, а потому что каталог
реального аккаунта и так был на месте (код возврата 12). ID заменён на
заведомо не боевой "ag-probe-isolation-test".
2. HermesHubSetup.cs: CreateStartMenuShortcut/RemoveStartMenuShortcut не
уважали HERMES_HUB_NO_REGISTRY — переменная гасила запись в реестр (A4),
но ярлык в настоящем меню Пуск изолированные тесты всё равно писали.
Добавлена та же проверка, что уже стоит перед записью в реестр. Заодно
LOCALAPPDATA читается из окружения раньше SpecialFolder — расхождение
найдено живым прогоном.
3. test_installer.py: /silent-тест линковался на venv настоящей машины
junction'ом (Windows) или symlink'ом вместо пустых touch-файлов — раньше
проверка живых Win32-зависимостей ничего по сути не проверяла.
4. update_manager.py: запасной перебор известных имён установщика
(hermes-hub-setup.sh/install-linux.sh/HermesHubSetup.exe) до отката на
.zip — подстраховка на случай расхождения определения платформы.
5. release_gate.py: --assets проверял только присутствие файлов. Добавлена
нижняя граница размера (усечённая сборка, найдено вживую) и сверка
SHA-256 каждого установщика с локальным checksums.txt — до всякой
публикации. Своя реализация (agy: только HermesHubSetup.exe, только
argparse-обвязка, несовместимая с --publication-only из HUB-1), но идея
и обе живые находки — его. Проверено полным циклом: собран настоящий
dist/hermes-hub-setup.sh, посчитаны настоящие контрольные суммы,
--assets прошёл на них 12588887 байт, SHA-256 сошёлся.
## Не взято — уже есть шире в HUB-1
- security_guard.py: точечный "$HOME" в тексте команды вместо конвейера
(диалект по команде, ${HOME}, %USERPROFILE%, fail-closed) — версия HUB-1
шире и уже зелёная на настоящем Windows CI.
- test_a59: заглушка os.getuid без проверки ветки Windows (taskkill/wmic) —
версия HUB-1 параметризована на обе ветки.
- Скомпилированные .exe — не переношу: пересборка на Windows после этого
коммита, здесь compилятора нет.
Тесты: 780 -> 781 passed, 2 skipped, 4 deselected. ruff check . чисто.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Установка на сервере владельца прервалась на проверке: «No module named
'fastapi'». Причин две, и обе в установщике.
Первая: запуск через sudo. Установка пользовательская — всё ложится в
$HOME/.hermes и $HOME/.local/bin, root не нужен. Под sudo домашним каталогом
становится /root, венв Hermes там не находится, и установщик уходит на
системный python. Копия при этом ложится в /root/.hermes, где владелец её не
видит. Теперь запуск через sudo распознаётся и отклоняется с объяснением;
осознанный обход остаётся через HERMES_ALLOW_ROOT=1.
Вторая: системный python в Ubuntu 24.04 помечен EXTERNALLY-MANAGED (PEP 668) и
отклоняет pip install — и обычный, и с --user. Установщик обе неудачи проглатывал
(|| true) и продолжал работу до отказа на проверке. Теперь при защищённом
системном python создаётся собственное окружение $HERMES_HOME/venv, а неудача
установки зависимостей прекращает установку с внятным кодом возврата.
--break-system-packages не применяется: имя флага не преувеличивает.
Пусковик научен той же ветке — иначе запуск уходил бы на системный python,
где зависимостей нет и быть не может.
Проверено исполнением на сервере под непривилегированным пользователем:
окружение создано, зависимости установлены, HERMES_HUB_LINUX_VERIFY_OK,
запуск через sudo отклонён с кодом 3.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Implemented 3-tier release feed status (MANIFEST_LIVE, PACKAGE_LIVE, PACKAGE_HASH_VERIFIED)
- Added reproducible package and checksum builder in scripts/build_dist.py
- Preserved user header comments across YAML saves in router_config.py
- Connected model_timeout_seconds, monitoring_interval_seconds, and auto_monitoring to runtime
- Guarded global gemini:antigravity credential swap with _AGY_INVOCATION_LOCK to eliminate concurrent subprocess race
- Added concurrency regression test in tests/test_antigravity_concurrency.py
- Added interprocess file locking (_FileLock) for router_state.json in health_tracker.py
- Sandboxed APPDATA and USERPROFILE in tests/test_installer.py
- Exported roadmap modules in router/__init__.py
- Verified 151 passing tests (100%) and 7/7 release gate checks