Commit graph

34 commits

Author SHA1 Message Date
ochenstarik-ui
377c567b85 fix(installer,release): находки agy с живой Windows-машины (A61)
Ветка 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>
2026-09-04 00:57:08 +07:00
ochenstarik-ui
ec656a0e08 fix(release): конвейер не публикует релиз, которым нельзя обновиться
Найдено сверх задания и сверх аудита.

Каждый прогон Release Pipeline завершался ошибкой — все пять последних,
включая тег текущего релиза v0.1.3-b1. Причина та же, что у красного CI: шаг
Release Gate падал на test_a37_isolation_guards и test_a41_clean_install. До
публикации не доходил ни один прогон, релизы выкладывались мимо конвейера.

Отсюда ловушка. release.yml собирает hermes-hub-<версия>.zip и
update_manifest.json, а update_manager ищет строго HermesHubSetup.exe или
hermes-hub-setup.sh. Настоящие релизы содержат установщики и checksums.txt,
то есть собраны не этим конвейером. Пока тесты были красными, конвейер падал
и ничего не публиковал; как только они позеленели, случайная защита исчезла:
первый же тег опубликовал бы "latest" без установщиков, и любое обновление
отвечало бы "В релизе не найден подходящий файл обновления для текущей
платформы".

Ловушка закрыта до публикации: release_gate.py --assets dist проверяет, что
собранный набор содержит установщик и checksums.txt, и падает с названной
причиной и подсказкой про installer/build_installer.*. После публикации
добавлен шаг release_gate.py --publication-only — строгий режим, ради
которого ворота и разделялись.

Сборку установщиков в release.yml не переписывал: проверяется только
настоящей публикацией по тегу, это решение владельца. Конвейер по-прежнему не
доходит до публикации, но падает теперь с честной причиной вместо чужой.

Отчёт перенесён в agents/done/ по конвенции репозитория.

Тесты: 777 -> 778 passed, 2 skipped, 4 deselected. ruff check . чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 19:01:30 +07:00
ochenstarik-ui
61e7933334 fix(release): отчёт ворот не роняет прогон на cp1252-консоли
Шаг Release Gate падал UnicodeEncodeError'ом на Windows-раннере: отчёт
печатается по-русски, консоль раннера — cp1252. Тот же класс дефекта, что и
в verification-скрипте, и то же лекарство — force_utf8_output до первого
вывода. Проверено прогоном под PYTHONIOENCODING=cp1252.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 19:01:30 +07:00
ochenstarik-ui
eac8352dc2 fix(release,web): ворота публикации перестали пропускать всё подряд, /api/action — межсайтовые запросы
P0 аудита, каждый сначала подтверждён исполнением, а не принят со слов.

1. Release Gate объявлял проверку хеша, которой не было. Печаталась строка
   PACKAGE_HASH_VERIFIED=True при том, что hashlib в scripts/release_gate.py
   не вызывался ни разу: скачивались байты 0-10 через заголовок Range, и
   этого хватало, чтобы счесть хеш проверенным. «Проверенным ассетом» при
   этом оказывался первый в списке — checksums.txt, а не пакет.

2. Ворота публикации были fail-open. Измерено в трёх условиях: полный обрыв
   сети -> PASS, манифест 404 -> PASS, пакет 404 -> PASS. Ворота пропускали
   релиз при любом исходе, включая полное отсутствие релиза.

   Разделено на офлайновую часть (проверки 1-7: версии, тесты, updater,
   статика, секреты, список разрешённых адресов) и Publication Gate: релиз
   есть, ассеты есть, пакет скачан ЦЕЛИКОМ, SHA-256 сошёлся с опубликованным
   checksums.txt. Публикационные ворота блокируют в режиме публикации
   (--publication или HERMES_RELEASE_PUBLICATION_GATE=1); в обычном прогоне
   CI, где релиза для ветки нет и быть не должно, результат сообщается как
   есть и не блокирует. Неизмеренное называется причиной, а не выдаётся за
   проверенное. Проверено на живом релизе v0.1.3-b1: два пакета скачаны
   целиком, хеши сошлись.

3. POST /api/action на loopback принимал межсайтовые запросы. Токен там не
   требуется, а действие меняет состояние: удаляет учётные данные, чистит
   аккаунты, переключает маршрутизацию, запускает входы OAuth. CORS от этого
   не защищает — он мешает прочитать ответ, а не отправить запрос. Измерено
   на конфигурации по умолчанию: POST с Content-Type text/plain уходит
   кросс-сайтом без предварительного запроса, request.json() разбирает тело
   независимо от Content-Type, и запрос с Origin чужого сайта без токена
   доходил до исполнителя действий.

   Проверяется Sec-Fetch-Site, при его отсутствии — Origin против адреса
   запроса. Собственный интерфейс, адресная строка и не-браузерные клиенты
   работают как раньше. Защита распространена на все пять небезопасных
   методов, не только на /api/action.

4. pricing fallback: safe_load вместо safe_dump. dump сериализовал текст
   обратно в строку, проверка isinstance(data, dict) не выполнялась никогда,
   таблица цен не загружалась ни разу, а except это глушил.

5. Симуляция Linux в тесте stop_running_hub падала на Windows: os.getuid там
   не существует.

Тесты: 756 -> 776 passed, 2 skipped, 4 deselected. ruff check . чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 19:01:30 +07:00
ochenstarik-ui
7136ab2878 fix(security): граница workspace держится одинаково на Windows и Linux
Оба красных Windows-джоба CI падали по причинам, воспроизведённым локально.

1. Инвариант A37 не держался на Windows. "rm -rf $HOME/.hermes" проходил
   мимо защиты: переменной HOME в окружении Windows нет, expandvars оставлял
   "$HOME" как есть, путь переставал быть абсолютным, склеивался с каталогом
   проекта и оказывался "внутри разрешённого корня". Зеркальная дыра на
   Linux: "%USERPROFILE%\.hermes" и "C:\Windows" проходили так же.

   Разбор пути сведён в один конвейер: классификация диалекта shell по самой
   команде (а не по системе-хозяину) -> раскрытие распознанных переменных, с
   разрешением HOME/USERPROFILE в домашний каталог даже когда их нет в
   окружении -> нормализация разделителей -> канонизация -> сравнение с
   защищёнными корнями. Каждый несостоявшийся шаг закрывает проход:
   непроверяемый путь не считается разрешённым. Через тот же конвейер
   пропущены validate_path, is_forbidden_path и is_inside_allowed_root.

2. UnicodeEncodeError ронял verify_multi_provider_router.py на cp1252-консоли
   Windows-раннера — падал вывод, не логика. Общий помощник
   console_encoding.force_utf8_output ставит UTF-8 на потоки и оставляет
   запасной путь, если перекодировать поток нельзя. Той же реализацией
   заменён самодельный блок в cli_commands.

Проверено: скрипт проходит 10/10 под PYTHONIOENCODING=cp1252 и ascii.
Новые тесты воспроизводят окружение обеих систем на любой из них и падают
на прежнем guard ровно на дефекте из CI (6 failed), проходят на новом.

Тесты: 739 -> 755 passed, 2 skipped, 4 deselected. ruff check . чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 19:01:30 +07:00
Hermes Team
6cb0d7c636 fix(profiles): пустые слоты появлялись сами, потому что запрос пути создавал каталог
Владелец спросил, откуда 25 каталогов профилей, когда заводил единицы.
Проверено исполнением: обращение к get_profile_dir создавало каталог. Спросили
четыре пути — появились четыре каталога.

В коде зашит список «стандартных» слотов — ag-orch-primary, ag-orch-fallback,
ag-1..ag-20, ag-w1..ag-w10 — в двух местах: agy_subprocess и
model_discovery_service. Любой обход этого списка материализовал их все. Отсюда
ag-w1..ag-w4, ag-cold-*, ag-spare-* — владелец их не создавал.

Спросить, где профиль жил бы, и завести его — разные действия. Создание теперь
запрашивается явно, create=True, и это делают только те, кто действительно
заводит профиль.

Тесты и сценарий проверки, опиравшиеся на побочное создание, приведены к новому
поведению: они проверяют изоляцию пути, а не то, что каталог возник сам.

669 passed, 2 skipped; ruff чисто; релизный гейт пройден.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 15:27:33 +07:00
ochenstarik-ui
ddeba2db0e fix(a54): validate accounts synchronously and manage Windows runtime lifecycle 2026-08-31 20:54:19 +07:00
ochenstarik-ui
5abcb7d525 feat(memory): A47 memory freshness checker, tests, and CI/CD contract 2026-08-31 14:57:21 +07:00
ochenstarik-ui
2b89372b0f feat(config): A41 чистая конфигурация при первой установке, безопасность учетных данных и сброс
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 чисто.
2026-08-31 02:27:42 +07:00
Hermes Team
380c218547 fix(installer): установка на Windows падала с кодом 12 из-за устаревшей проверки
Владелец получил «Ошибка установки (Код: 12)». Код 12 — провал скрипта
scripts/verify_multi_provider_router.py, который виндовый установщик запускает
после развёртывания. На Linux он не запускается, поэтому там всё вставало.

Скрипт пережил три изменения продукта и не был под них обновлён:

1. Требовал роль "orchestrator". A28 переименовал её в "manager", и проверка
   падала на первом же шаге. Теперь актуальное имя спрашивается у реестра
   ролей, а не помнится в скрипте.

2. Требовал непустую цепочку у КАЖДОЙ роли. A28 добавил роли, объявленные без
   реализации — guardian и cost-controller, — у них аккаунтов ещё нет.
   Установка падала из-за роли, которой никто не пользуется. Теперь пустая
   цепочка допустима и лишь отмечается, а обязательна она только у
   оркестрирующей роли: без неё маршрутизация действительно не работает.

3. Зашивал порядок цепочки codex -> antigravity -> opengo-3 и конкретные
   идентификаторы профилей. Но порядок — выбор владельца, он меняет его мышью,
   и любая перестановка роняла установку. Проверка переписана на механизм:
   берётся настоящая цепочка, роняются все профили кроме последнего
   достижимого, и проверяется, что маршрутизатор дошёл именно до него.
   Учтён предел max_failover_attempts — за него цепочка не проходится.

Карта адаптеров дополнена claude, grok и local: раньше в ней были только три
провайдера, и хвост цепочки из остальных не покрывался.

Проверено на конфигурации владельца: 10/10 CHECKS PASSED, код возврата 0.
486 passed, ruff чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 02:03:42 +07:00
Hermes Team
ab2ee12db4 feat(local): скрипт прописывания локальных моделей и назначения ролей
У владельца на сервере два llama.cpp: Qwen3.8-27B на 8081 под тяжёлую
разработку и Qwen3-4B на 8082 под служебные роли — cost-controller,
dependency-agent, tech-writer, tester и суммаризацию.

Скрипт прописывает оба профиля и добавляет их в цепочки соответствующих
ролей. Дополняет конфигурацию, не переписывает: чужие профили и порядок
аккаунтов сохраняются, повторный запуск ничего не меняет.

Идентификаторы моделей не выдумываются — спрашиваются у самих серверов через
/v1/models. Сервер не ответил — профиль не трогается, причина названа.
Проверено: при отсутствии серверов скрипт отказывается и объясняет.

max_concurrency выставляется в 1: у обоих серверов --parallel 1, и больше
единицы означает очередь и лавину таймаутов.

Локальный профиль ставится ПОСЛЕДНИМ в цепочке: модель бесплатна и не
исчерпывается, поэтому она хороший последний рубеж, когда платные квоты
кончились. Существующий порядок при этом не переставляется.

Есть обратное соответствие для сборок, где тринадцати ролей ещё нет:
developer-1 -> coder-primary, tech-writer и tester -> fast, а служебные роли
пропускаются с явным сообщением, потому что аналога им там нет. Проверено на
обоих наборах ролей.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 21:32:01 +07:00
ochenstarik-ui
b4ae08ef53 fix(ci): stop hanging hermetic tests and unblock clean/headless runners
Preflight and updater tests no longer probe 8081/8082 or GitHub.
Hermetic runs fail-fast on non-loopback sockets. GUI helpers are
importable without customtkinter. CI installs the web extra, and
pytest-timeout plus a wall-clock wrapper bound the suite.
2026-08-27 12:03:37 +00:00
Hermes Team
8b8aebf928 feat(integration): consolidate A28, A29 and A30 on top of origin/main with green release gate 2026-08-26 09:10:10 +07:00
Hermes Team
e90f6331a2 fix(launcher): сообщение при запуске не совпадало с настройками; смена токена
Владелец привязал хаб на сервере к сети, а лаунчер всё равно напечатал
«Headless Mode», показал http://127.0.0.1:5800 и посоветовал пробросить порт
через ssh -L. Текст был зашит и настроек не читал: инструкция вела поднимать
туннель к серверу, который уже был виден напрямую. Инструкция, не
совпадающая с реальностью, хуже отсутствующей — тот же класс дефекта, что и
снятая заглушка про «вход через веб невозможен».

Теперь сообщение читает web_api_host из hub_settings.json: при 127.0.0.1
показывает проброс порта и подсказывает про enable_lan_access.py, при
сетевой привязке — реальный адрес из hostname -I и напоминание про токен.

Добавлен --rotate: смена токена понадобилась немедленно, потому что
выданный токен был вставлен в переписку и скомпрометирован. Без флага
поведение прежнее — повторный запуск токен не трогает.

Проверено: без --rotate токен сохраняется, с --rotate меняется; bash -n на
лаунчере проходит; переводы строк LF.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 10:47:29 +07:00
Hermes Team
44808bdc4e feat(web): скрипт открытия хаба в домашнюю сеть, с подтверждением цели
Владелец хочет попадать в хаб на сервере по сети, а не через SSH-туннель.
Для этого нужны привязка к 0.0.0.0 и токен: без токена при небlocalhost
привязке сервер отказывается стартовать.

Скрипт ДОПОЛНЯЕТ hub_settings.json, а не переписывает: рядом лежат тема,
интервал обновления квот и параметры маршрутизации. Запись атомарная,
повторный запуск сохраняет прежний токен.

Изменение требует явного --yes, а каталог печатается всегда. Причина не
теоретическая: при отладке скрипт молча взял HERMES_HOME из окружения и
записал настройки не в тестовую копию, а в живой хаб рабочей машины,
привязав его к сети. Откачено, наружу ничего не вышло — адрес читается при
старте, процесс не перезапускался, netstat подтвердил только 127.0.0.1.
Предпросмотр по умолчанию закрывает этот класс ошибки.

Попутно install-linux.sh разворачивает scripts/: они входили в поставку, но
на установленной машине не оказывались, поэтому вспомогательных инструментов
там просто не было.

Проверено на копии настроек: предпросмотр не меняет файл, применение
сохраняет прежние ключи, повторный запуск не меняет токен, посторонний
каталог не затрагивается.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 10:27:16 +07:00
Hermes Team
36b449bc6c fix(installer): ошибка 12 при установке — проверка требовала конфигурацию от 20 августа
Владелец получил «Ошибка установки (Код: 12)» на чистой машине.

Причина: scripts/verify_multi_provider_router.py, который установщик
запускает после развёртывания, требовал РОВНО 16 профилей и дословно
заданные цепочки ролей. Миграция из A9 законно доводит конфигурацию до
22 профилей, добавляя claude и grok. Проверено: скрипт падал с
«Expected 16 profiles, got 22», то есть установка обрывалась на любой
машине, где миграция отработала.

Проверки переписаны структурными: есть ли профили у каждого провайдера,
непусты ли цепочки ролей и ссылаются ли они только на существующие
профили. Смысл проверки — работоспособна ли маршрутизация, а не совпадает
ли конфигурация с зафиксированной когда-то. Скрипт проходит 10/10.

Отдельно: код 12 возвращался и при отказе проверки, и из общего catch —
владелец видел число без причины. Непредвиденный сбой отделён в код 15,
обе ветки теперь пишут пояснение в интерфейс установщика.

Тесты: 373 passed, ruff чисто. Установщик пересобран.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:35:36 +07:00
Hermes Team
e738dd0c5d feat(web): A21 — паритет веб-интерфейса: аналитика, состояние, события, настройки 2026-08-23 22:59:02 +07:00
Hermes Team
c730c769e0 Merge remote-tracking branch 'origin/antigravity/installers' into review/all 2026-08-23 22:24:29 +07:00
Hermes Team
2e445c28ef feat(installer): A19 — установщики Windows и Linux, запуск веб-интерфейса окном приложения 2026-08-23 22:14:47 +07:00
Hermes Team
05cf17503d feat(router): A18 — выбор модели, действие set_model, персистентный кэш и выбор в веб-клиенте 2026-08-23 22:08:08 +07:00
Hermes Team
d9d6e08d32 feat(web): A16 — веб-клиент без сборки, компактные аккаунты, живые квоты, честная авторизация и скриншоты экранов 2026-08-23 19:37:36 +07:00
Hermes Team
8d97cf76de feat(ui): A14 — компактные карточки аккаунтов, доступность пулов квот и живые скриншоты сценариев 2026-08-23 18:21:20 +07:00
Hermes Team
99af66d717 feat(ui): A12 — компактные карточки аккаунтов, доступность причин Н/Д, упорядочивание провайдеров и тест службы моделей 2026-08-23 13:30:20 +07:00
Hermes Team
50fde5f16e refactor(plan-a): close residual blockers, concurrency race, and feed verification
- 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
2026-08-20 22:55:43 +07:00
63c0385f5c fix: repair seven undefined names and make CI ruff step meaningful
`ruff check .` failed on every push since CI was added (1221 findings), so the
job aborted before pytest and the release gate ever ran. Adds [tool.ruff]
selecting bug-catching rules only (E9, F63, F7, F82, F811); style and
modernization rules stay off until their ~1200 findings are burned down.

That selection immediately surfaced seven live defects:
- hermes_hub_app: HubModal used but never imported, so the "Назначить" role
  modal raised NameError — the handler added to close an earlier review
  finding could never open.
- hermes_hub_app: three `after(0, lambda: ...(e))` callbacks referencing the
  except-bound name, which Python unbinds at block exit, so every UI error
  path raised NameError instead of reporting the error.
- auto_assigner: build_team_hierarchy referenced an undefined `is_main` and
  crashed on every call.
- ui/assets and live_provision_and_validate: annotations naming Any/Tuple
  without importing them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:28:08 +07:00
Hermes Team
0c511cd3b6 feat(hub): Plan A stabilization, refresh architecture, delta UI, and capability routing
- 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
2026-08-20 21:20:51 +07:00
Hermes Team
8314d46c43 fix: update canonical installer with dependency resolution and close release blockers 2026-08-20 18:17:08 +07:00
Hermes Team
42dfe2caa6 feat: production update feed architecture, host allowlist, and truthful release gate 2026-08-20 17:25:30 +07:00
Hermes Team
2f5e6d9f7a fix: strengthen secret scanning and oauth configuration 2026-08-20 17:23:40 +07:00
Hermes Team
65482e8eee fix(router): address review findings B1-B4 and S1-S9 with full regression suite 2026-08-20 17:04:49 +07:00
Hermes Team
7926de9ad2 feat(release): recovery stabilization, built-in updater, release gate, and v0.1.1 release pipeline 2026-08-20 16:29:35 +07:00
Hermes Team
7609ad87c2 feat(hub): product stabilization, native windows ux v3, provider icons, and architecture roadmap 2026-08-20 11:01:52 +07:00
Hermes Team
e66248ab09 feat: initialize standalone Hermes Hub 2026-08-20 10:53:49 +07:00
Hermes Team
fdf9eccbdb feat: initialize standalone Hermes Hub 2026-08-20 00:17:11 +07:00