Commit graph

58 commits

Author SHA1 Message Date
Hermes Team
bad24ff6aa docs(task): A25 — разведка выполнена, задание построено на фактах с сервера
Владелец дал доступ по ключу. На 192.168.1.81 работают два сервера
llama.cpp, оба OpenAI-совместимые, проверено запросами:

  8081  Qwen3.8-27B-Q4_K_M   reasoning on, контекст 65536, -ngl 99
  8082  Qwen3-4B-Instruct    reasoning off, «compressor»

GET /v1/models и POST /v1/chat/completions отвечают 200 на обоих.
Видеокарта Tesla V100-32GB, занято 28.7 из 32.7 ГБ.

Три следствия внесены в задание как определяющие реализацию:
- оба слушают только 127.0.0.1, снаружи недоступны; варианты решения
  предложены владельцу, выбор за ним;
- у обоих --parallel 1, то есть один запрос за раз: лизы Hub обязаны
  ограничивать локального провайдера, иначе роли заблокируют друг друга;
- памяти видеокарты на третью модель нет, слотов ровно два.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 10:46:04 +07:00
Hermes Team
992d0c574c docs(task): A25 — локальная модель как провайдер Hub
У владельца сервер 192.168.1.81 с локальной LLM; хочет использовать её
как субагента. Ценность: локальная модель не имеет квоты и не стоит
денег — идеальный последний резерв. Сейчас у него реально работает один
провайдер из пяти, запаса нет.

Половина работы уже есть: RouterProfileConfig.custom_base_url
существует, deepseek_adapter — готовый образец OpenAI-совместимого
вызова, а профиль через provider: custom у него уже настроен в Hermes.

Первым пунктом — разведка, а не код: ревьюер снаружи увидел открытыми
только 22 и 3000 (Rocket.Chat), порт Ollama закрыт. Что именно слушает,
выясняет владелец на сервере: доступа по SSH нет, вход по ключу не
настроен, пароли не используются.

Отдельным пунктом — честность про квоту: у локальной модели её нет как
понятия, и показывать Н/Д рядом с процентами других провайдеров нельзя,
это читается как «данные не пришли».

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 10:34:13 +07:00
Hermes Team
f757639b7e docs(task): A24 — маршрутизация как главный экран управления
Решение владельца по итогам живой эксплуатации: разделов семь вместо
девяти. Убираются «Команда агентов» и «Модели и провайдеры», их
содержимое перераспределяется между маршрутизацией и обзором. Аналитика
остаётся, но должна объяснять свои метрики.

Маршрутизация становится местом управления: перестановка блоков
перетаскиванием, смена модели на месте, кнопка «Изменить цепочку»
убирается.

В задание вынесен вывод из только что найденного дефекта: в веб-мастере
стояли выдуманные коды устройства GRK-7842 и CDX-9104, а тест ТРЕБОВАЛ
наличия неверного адреса, то есть защищал выдумку от исправления.
Пункт P0-6 для второго прохода дополнен проверкой на выдуманные
значения и на тесты, закрепляющие дефект.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 10:31:10 +07:00
Hermes Team
9c6a4e8f6d docs(task): A23 — самовосстановление профилей и честная проверка моделей
Написано под схему владельца: Flash реализует, Pro проводит аудит.
Пункт P0-4 — чек-лист для второго прохода, составлен из дефектов,
которые уже проходили мимо первого.

P0-1: mark_auth_required ставит состояние без срока истечения, а
маршрутизация пропускает нездоровый профиль — успеха не случится,
отметка не снимется никогда. Подтверждено: после починки авторизации в
A22 все шесть профилей Antigravity остались помечены, ревьюер снимал
отметки вручную.

P0-2: do_set_model пропускает проверку целиком при пустом кэше моделей.
Проверено — выдуманная модель записалась в конфигурацию владельца.
Отсутствие данных трактуется как разрешение.

P0-3: ручного обновления списка моделей нет с A18.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 01:35:52 +07:00
Hermes Team
45fd01a15e fix(agy): подстановка уровня усилия — gemini-3.7-flash работает как есть
Владелец возразил на моё утверждение, что gemini-3.7-flash не существует.
Он прав, утверждение было неверным, и я повторил его в четырёх заданиях.

gemini-3.7-flash — настоящее семейство, уровень усилия у неё отдельный
параметр. В интерфейсе Antigravity это видно прямо: пункт «Gemini 3.7
Flash» с вложенным выбором Low/Medium/High. В коде это отражено:
_display_to_cli разбирает «Gemini 3.7 Flash (High)» в пару
("gemini-3.7-flash", "high"). Меня ввела в заблуждение первая колонка
вывода agy models со склеенными идентификаторами.

Настоящий дефект был в коде: _model_supported_efforts вызывала
discover_models() БЕЗ профиля, то есть в глобальном окружении без входа.
Карта поддерживаемых усилий оставалась пустой, подстановка уровня по
умолчанию не срабатывала, и agy отвергал вызов с «requires --effort» —
при совершенно настоящей модели.

profile_id проведён через agy_generate в _model_supported_efforts.
Проверено исполнением: gemini-3.7-flash без указания усилия отрабатывает
и возвращает ответ.

Моки в test_antigravity_concurrency приведены к терпимости по kwargs.

Добавлена поправка agents/inbox/2026-08-24-CORRECTION-gemini-model-names.md:
ложное утверждение попало в A9, A11, A18 и B8, и без опровержения кто-то
чинил бы несуществующую проблему или сломал рабочую конфигурацию.

Тесты: 359 passed, ruff чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 01:18:00 +07:00
Hermes Team
f514b3e6de docs(task): A22 — вход в Antigravity силами самого agy
A20 закрыто как неверно поставленное. Синтез oauth_creds.json из
OAuth-потока Hub не работает в принципе: проверены и закрыты пять
гипотез (полнота полей, срок токенов, тот же OAuth-клиент, тот же
scope, согласованность активного аккаунта), а решающий опыт показал,
что agy отказывает даже РАБОЧИМ глобальным учётным данным владельца,
положенным в подменённый HOME. Ошибка в гипотезе автора задания.

Полезное следствие разведки: agy уважает подмену HOME — в каталогах
профилей лежат созданные им же файлы. Изоляция работает, не работал
только синтез.

A22 строит вход через родной механизм agy в окружении профиля. Первым
пунктом — разведка: есть ли неинтерактивный вход, что agy выводит,
как определить завершение. Установлено, что без аргументов это TUI:
в пайп ничего не пишет и виснет.

Приёмка только с тремя доказательствами исполнением: непустой вывод
agy models, успешный реальный вызов, route_request без ухода в резерв.

Плюс проверка побочной находки: в глобальном google_accounts.json
активен один аккаунт, а токен принадлежит другому — Hub мог писать
мимо каталога профиля и сломать владельцу обычный agy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 23:38:46 +07:00
Hermes Team
972e34911c docs(task): A21 — четыре недостающих экрана веб-интерфейса
Веб покрывает пять экранов из девяти. Не хватает Аналитики, Состояния,
Журнала событий и Настроек.

Данные для первых двух уже в снапшоте: metrics.telemetry (19 вызовов,
15 отказов, латентность p50/p95/max) и metrics.host плюс readiness.
Для двух других источника в API нет вовсе — нужны GET /api/events
(EventLogService в backend есть) и GET /api/settings без секретов.

Зона Flash на это задание расширена на router/web/** целиком, включая
server.py: A20 в web/ не заходит, конфликта не будет.

Обнаружение моделей в задание НЕ включено, хотя A18 его пропустил:
причина оказалась глубже и лежит в авторизации agy, это чинит A20.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 22:49:45 +07:00
Hermes Team
187f181aec docs(task): A20 — восстановить Antigravity через OAuth
Маршрутизация через Antigravity не работает ни для одного из шести
аккаунтов при полностью валидных токенах: квоты по ним приходят
настоящими через прямой HTTPS, а путь через CLI падает с
AuthExpiredError.

Причина найдена и проверена: agy читает <HOME>/.gemini/oauth_creds.json
с шестью полями, включая id_token и scope. Hub пишет свой auth.json в
другом месте и другой структурой, а id_token и scope теряет в двух
местах — oauth.py:88-92 и profile_oauth.py:241-249. Ни один профиль их
не хранит.

Проверено и не сработало: подмена HOME на каталог профиля, сборка
oauth_creds.json без id_token. Значит id_token обязателен.

Владелец решил остаться на OAuth, прямой API отклонён.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 22:36:35 +07:00
Hermes Team
18695a3f6e docs(tasks): A17, A18, A19 — честный статус, выбор модели, два установщика
A17 (Pro): «Работает» — ветка else в определении здоровья, она означает
«мы не знаем о проблемах», а подана как утверждение. Отказы попадают в
статус только после боевого сбоя, поэтому непроверенный профиль
автоматически зелёный. Плюс «Проверить подключение» не вызывает модель
вовсе — Grok её проходит и не работает.

A18 (Flash): действия смены модели не существует ни среди семнадцати, ни
в клиенте; десктоп это умеет, но логика заперта в методе интерфейса.
И выбирать не из чего: кэш моделей пуст по всем провайдерам, потому что
agy models нестабильна — в одном прогоне 40 секунд, в следующем висит
больше двух минут.

A19: два установщика. Windows — ярлык, открывающий веб окном приложения
через --app без адресной строки (проверено на машине владельца: Edge и
Chrome есть, окно открывается). Linux — скрипт установки, .desktop и
удаление с сохранением данных, плюс честная подсказка про проброс порта
при пустом DISPLAY.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 21:57:11 +07:00
Hermes Team
06b55b49f4 docs(tasks): A15 и A16 — переход на веб-интерфейс
Решение владельца: у него сервер с Ubuntu Server и Xubuntu, Hermes там
будет линуксовый. Веб-интерфейс на сервере строго лучше десктопа.
Десктоп остаётся рабочим до паритета, router/ui/** не трогается.

A15 (Pro): веб-API поверх готового снапшота — GET /api/snapshot и
POST /api/action на семнадцать существующих действий; безопасность
(127.0.0.1 по умолчанию, отказ стартовать на внешнем адресе без токена,
тест на отсутствие секретов в ответе); порт на Linux — восемь мест,
читающих LOCALAPPDATA в обход paths.py; честное сообщение о том, какие
потоки авторизации на headless-сервере не работают. Плюс долг из
прошлого раунда: снапшот не различает «данных нет» и «данные грузятся».

A16 (Flash): клиент без сборки на обычном JS. Не заблокирован сервером —
разрабатывает против docs/web-api/snapshot.example.json. Экраны по
ценности: Аккаунты с видимыми квотами, затем Обзор и Маршрутизация.

Обе стороны пишутся против docs/web-api/CONTRACT.md и до слияния друг
друга не видят — отсюда требование не менять контракт односторонне.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 19:03:48 +07:00
Hermes Team
a18de5d468 docs(tasks): A13 и A14 — оставшийся долг
A13 (Pro): раздел контракта о границе между учётными системами Hub и
Hermes — единственный незакрытый пункт A11; варианты связывания профилей
с ценой каждого; устранение нестабильности набора тестов (шесть корней
Tk дают до семи плавающих ошибок на прогон, мешая отличать настоящую
поломку от шума).

A14 (Flash): два невыполненных пункта A12 — компактные карточки
аккаунтов (accounts_view.py не менялся вообще) и разбор дублирующих
разделов «Провайдеры»/«Квоты» (quotas_view.py не тронут), плюс живые
скриншоты, которых не было.

Принято по A11: пропуск вызова без роли работает — замер 0.10 с без
попыток цепочки; зонд переведён на agy models; выдуманный список
gemini-2.5-* убран; refresh_codex_token появился; source квоты не
опережает данные. Релизный гейт стал зелёным, 7/7.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:52:07 +07:00
Hermes Team
78cd826624 docs(tasks): A11 и A12 — разделение работ между двумя исполнителями
A11 (Pro, тяжёлая ветка): интеграция с Hermes — перехват без роли,
граница между учётными системами Hub и Hermes, токены Codex и безопасное
переключение аккаунта, замена зонда обнаружения моделей на agy models,
устранение выдуманного запасного списка в адаптере.

A12 (Flash, быстрая ветка): компактные карточки аккаунтов, разбор
дублирующих разделов «Провайдеры»/«Квоты», причина у каждого Н/Д, тест
на достижимость службы обнаружения моделей, живое подключение Grok.

Заданы строгие непересекающиеся списки файлов, чтобы параллельная работа
не дала конфликтов. В A12 порядок работы с git расписан пошагово: pull в
начале, push ветки сразу после первого коммита, обязательная проверка
финального push через git log origin/<ветка>.

A10 удалено — заменено этой парой.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 13:00:36 +07:00
Hermes Team
1ce08c0361 docs(task): A10 — вся оставшаяся работа переходит к Antigravity
У Codex закончились лимиты. Границы зон сняты: router/ui/** и
tests/test_ui_*.py переходят к Antigravity вместе с ответственностью за
честность интерфейса.

Codex успел: выбор модели, кликабельная карточка целиком, окно настроек
роли, снятие правой панели, устранение срезов диаграммы, частично
причины у Н/Д. Не успел: компактные карточки аккаунтов и разбор
дублирующих разделов «Провайдеры»/«Квоты».

Отдельно: работа A9 заявлена выполненной, но в репозитории её нет ни в
одной ветке. Первое действие по A10 — отправить её в origin.

Зафиксирован обязательный контракт службы обнаружения моделей:
router/model_discovery.py + ModelDiscoveryService. Codex импортирует
именно этот путь, отчёт A9 называет другой; импорт защищён except
ImportError, поэтому расхождение сломало бы выбор моделей молча.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 12:48:17 +07:00
Hermes Team
95afdfe179 docs(task): A9 — интеграция с Hermes и обновление токенов Codex
P0-00: Hub подключён к Hermes как middleware llm_execution и срабатывает
на каждом вызове, но Hermes не передаёт role — поэтому всё уходило в роль
по умолчанию, цепочка orchestrator исчерпана, и Hermes получал текст
ошибки вместо ответа модели. Следствие устранено в 2d62d39; в задании —
причина: не претендовать на вызов без достоверной роли, описать границу
между учётными системами Hub и Hermes, подготовить варианты связывания
профилей.

P0-01: Codex сохраняет refresh_token, но функции обновления нет вовсе.
Требуется обновление токена, раздельная проверка access_token и
id_token и переключение аккаунта с остановкой клиента до подмены
учётных данных — по образцу Cockpit Tools, присланному владельцем.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 12:27:43 +07:00
Hermes Team
6494c5198a docs(tasks): A9 и B8 по итогам живого прогона владельца
A9 (Antigravity): миграция профилей в существующий router_profiles.yaml —
корень жалобы «при подключении грока ошибка»; квоты для codex и opencode;
служба обнаружения моделей с кэшем и фоновым обновлением; отказ от
выдуманных списков моделей. Плюс четыре утверждения отчёта A8, не
подтвердившиеся проверкой: профили claude/grok до пользователя не дошли,
проверка is_expired была мертва, dist в .gitignore, флаг /reinstall
не используется.

B8 (Codex): выбор модели агента, компактные карточки аккаунтов без
раскрытия, кликабельная карточка целиком, окно настроек роли, снятие
правой панели, устранение жёстких срезов диаграммы, решение по
дублирующим разделам, причина у каждого Н/Д.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 01:20:23 +07:00
Hermes Team
d4517d8ce0 Merge remote-tracking branch 'origin/antigravity/deployment-doctor' into review/a8 2026-08-22 23:37:20 +07:00
Hermes Team
559289d839 docs(task): B7 — зафиксировать исправленный дефект мастера и потребовать проверку на несуществующие методы
Добавлен раздел P0-0: правка _finish уже в main (7090c8a), её нельзя
потерять при слиянии. Там же второй дефект того же класса —
splash.py вызывает несуществующий AssetManager.get_splash_logo.

Дефект «вызов несуществующего метода» встречается третий раз и под
pythonw всегда молчаливый, поэтому в критерии приёмки добавлено
требование механической проверки UI-слоя.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:45:05 +07:00
Hermes Team
c75fb35082 docs(tasks): require agents to refresh their local checkout before starting
Both agents work on other machines and push straight to git. A8 and B7
were pinned to 8cddc9f while main had already moved to 7f912f1, and
neither task said to pull first — branching from a stale checkout is how
merges revert other people's work.

Adds an explicit "update your local copy" section to A8 and B7: fetch,
reset to origin/main, record the actual HEAD as BASE_SHA rather than the
SHA printed in the document, and branch from fresh main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:25:50 +07:00
Hermes Team
d2d2a69357 feat(installer): implement P0-4bis reinstall detection, UI screen, and user data preservation 2026-08-22 21:25:39 +07:00
Hermes Team
ee5108eb3e fix(deployment): implement self-healing bootstrap, Claude & Grok profiles, non-interactive test mode, mirror installer, and comprehensive doctor CLI 2026-08-22 21:22:21 +07:00
7f912f1920 docs(task): A8 — reinstall acceptance criteria
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:20:49 +07:00
3c55d0c624 docs(task): A8 — installer must offer reinstall when Hub is already present
SetupEngine.IsInstalled is computed but never reaches the wizard UI, so the
first-install flow repeats verbatim on a machine that already has Hub. Adds the
reinstall screen, the mirror semantics it triggers, the list of user data that
must survive it, and a /reinstall silent flag.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:20:12 +07:00
20078f5ff6 docs(task): A8 and B7 — defects found during the first live run
The owner used the product and the router proved itself: the log shows a real
failover chain codex-orch -> ag-orch-fallback -> opengo-3 driven by actual quota
errors. Everything around that core failed.

Hub stopped launching because customtkinter vanished from the Hermes venv, most
likely wiped by that app's repair-install; pythonw swallows the traceback, so it
looks like the window never opens. The wizard offers five providers while the
router config defines profiles for three, so find_free_slot returns a
non-existent claude-orch. The test action still reaches the agy subprocess, which
opens a browser on expired credentials. The routing "configure" button only
raises a toast about drag-and-drop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 20:13:01 +07:00
Hermes Team
8cddc9fee2 Merge remote-tracking branch 'origin/main' into review/a7 2026-08-22 08:41:09 +07:00
35101d1043 docs(task): B6 — routing graph on the Team screen, and a Hub that demonstrably works
Adopts the graph half of the 104-point n8n-derived brief and states plainly what
is excluded: n8n's canvas edits its own workflow execution engine, while Hermes
Hub's engine resolves a role into a provider/account/model for a single call.
Execution trees, agent-as-tool contracts, cancellation and review loops have no
layer to sit on here.

Adds the requirement that has been missing all along: screenshots taken with a
live connected account, not an empty configuration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 22:25:40 +07:00
Hermes Team
9f72e8ec39 fix(dashboard): unify LeaseManager, warm up initial CPU measurement, add live network speed, and clarify YAML comment support 2026-08-21 22:18:59 +07:00
09d5e5dccb docs(task): A7 — add network counter presented as a live metric
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 21:58:23 +07:00
1efaf78a7a docs(task): A7 — two dashboard data defects found by execution
active_calls is permanently zero: state_store reads LeaseManager.get() while
RouterEngine constructs its own instance, so the router's leases are invisible
to the snapshot. And psutil.cpu_percent(interval=None) returns 0.0 on its first
call, so the dashboard shows CPU 0% at startup — a measured-looking number that
is not a measurement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 21:54:01 +07:00
Hermes Team
69cbefcab6 feat(dashboard): expose telemetry breakdown, provider call_share, host metrics, and active leases 2026-08-21 17:44:56 +07:00
2407d47606 docs(task): A6 and B5 — back the approved dashboard mockup with real data
The mockup's headline blocks divide three ways against the code at 2b2ccd8:
already available (latency, readiness, events, routing chain), derivable but not
yet exposed (per-provider aggregates, call share, host metrics via the unused
psutil dependency, active leases), and absent by design (task queues, service
window, incidents, provider RPS/SLA).

A6 supplies the second group; B5 redesigns against the contract and restores the
four account actions that d0d15ae dropped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 17:28:33 +07:00
Hermes Team
2b2ccd8fb2 feat(telemetry): implement empirical call telemetry, metrics aggregates, user pricing, and update state contract 2026-08-21 16:57:57 +07:00
f5d002c46f docs(task): A5 — persist the telemetry the router already measures
Latency, token usage and failover counts flow through router_metadata on every
call and are then discarded; nothing in the project accumulates them. Four of
the seven headline numbers on the mockups are therefore honestly derivable from
our own calls rather than fabricated. RPS, SLA and host resource metrics stay in
Active Limitations.

Also carries the three debts forward for the third time: HKCU in the installer,
fastapi/uvicorn as required dependencies, and YAML comment loss.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 16:53:15 +07:00
31e4e7f66c docs(task): B4 — restore the account actions the redesign dropped
accounts_view went from four user actions to one in d0d15ae: test, set_main,
set_orchestrator and assign_role lost their triggers, and assign_role is now
unreachable entirely although its handler and modal still exist. Also scopes
what the approved mockups can and cannot drive, since their headline numbers
are exactly the metrics Gap 12 says the backend does not measure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:53:06 +07:00
Hermes Team
9d93a1739b feat(security): isolate subprocess credentials, implement selection explanation matrix, and resolve installer registry isolation 2026-08-21 10:17:19 +07:00
33b99982b2 docs(task): A4 — credential isolation, remaining debts, provider explain trace
The agy subprocess still inherits the entire environment, so every provider key
travels into it; _safe_env() was written for exactly this and has never been
called. That is the oldest unfixed finding in the project.

Also scopes out the "AI news" proposal: lifecycle supervisor, skill registry and
MCP lifecycle target modules this repo deleted as dead code or never had, so
only credential isolation and the provider explain trace are adopted from it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 10:10:46 +07:00
Hermes Team
ff8776b963 feat(release): close contract audit v1.2, release feed verification, diagnostic CLI, and failover event logging 2026-08-21 10:05:30 +07:00
9ffc815ed5 docs(task): B3 — wire the contract v1.1 fields the UI never picked up
Codex built phases 2-6 against contract v1.0 while Antigravity shipped v1.1, so
eight fields now exist in the snapshot and render nowhere: plan_code,
plan_source, active_quota_status, active_quota_label, quota_status,
failover_reason, unavailable_reason and seq. PlanBadge was built in phase 1 and
still has nothing to display.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:50:22 +07:00
5b6f69b6b4 docs(task): A3 — release artifact, contract honesty, remaining debts
A2 closed the gaps that blocked the UI, but three declared gaps (4, 5, 12)
vanished from the contract without being closed. Gap 12 was the instruction
telling the UI to render N/A for latency, RPS and cost — it disappeared exactly
as Codex starts the dashboard. The release asset still returns 404.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:43:44 +07:00
Hermes Team
2035c1455f feat(state): close contract gaps v1.1, canonical event publishers, and view model enrichment 2026-08-21 08:20:56 +07:00
e8a404be03 docs(task): next Antigravity assignment — close the gaps its own contract declares
Seven of the twelve backend gaps in UI_STATE_CONTRACT.md block the UI outright:
no targeted event has a publisher, plan provenance never reaches
ProfileViewModel, and AgentViewModel/PipelineNode lack the fields the Team and
Routing screens need. Verified on c6876e9, alongside the release asset still
returning 404 and YAML comment loss now at 5 to 2 rather than 5 to 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:16:44 +07:00
c6876e96b2 docs(task): reissue the UI redesign assignment against the published contract
Codex was handed Task A by mistake and duplicated the state-layer work that
Antigravity had already merged. This reissues its own scope, rebased on the
facts at 39b1f92: PHASE 1 is merged, docs/UI_STATE_CONTRACT.md now exists, and
the twelve backend gaps it declares are mapped to what the UI may and may not
render.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:13:46 +07:00
Hermes Team
83e1f78818 merge: complete antigravity state layer 2026-08-21 00:10:56 +07:00
Hermes Team
86c9189edd feat(state-layer): event-driven quota, seq freshness guards, and state layer stabilization
- Added HubStateStore targeted delta update methods (apply_delta_quota_updated, apply_delta_account_added, apply_delta_account_removed, apply_delta_route_changed)
- Added seq sequence freshness tracking in HubStateStore to drop stale out-of-order responses
- Added trigger_refresh_provider in HermesRefreshScheduler
- Bound multi-bucket quotas to specific model families (Claude vs Gemini) with truthful is_estimated tracking
- Connected OAuth completion to targeted account added events across all providers
- Pinned antigravity_provider package root to repo via __init__.py and added import invariant verification
- Added unit tests in tests/test_state_layer_and_event_driven_quota.py and tests/test_import_invariants.py
- Zero modifications to UI zone files (views, components, theme, wizard, hermes_hub_app.py)
2026-08-20 23:48:36 +07:00
f171a8069d test(conftest): skip GUI tests by marker instead of by test name
The headless guard matched any test whose name contained "ui", "view" or
"wizard", so static checks that never touch the toolkit were skipped too. That
is how four real failures stayed invisible: they lived in modules the name
filter silently removed. Selection is now the `ui` marker alone; modules that
import the GUI stack already guard themselves with pytest.importorskip, which
tests/test_import_invariants.py enforces.

Headless goes from 152 to 156 passed — four tests that were being skipped by
accident now actually run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 23:41:48 +07:00
8a52f79b21 docs(task): fix control character mangling the plugin path
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 23:37:12 +07:00
8143150ebc docs(task): add findings that only surface with UI dependencies installed
Running the suite with customtkinter present exposes four failures the headless
run never reaches: hermes_hub_app mutates sys.path so tests load the stale
installed plugin copy, and two OAuth lifecycle tests fail outright. conftest's
name-based skip hid both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 23:36:36 +07:00
93883f9ce4 docs(task): split Plan A and UI redesign into two non-overlapping assignments
The UI redesign draft duplicated eight Plan A phases on the same files
(accounts_view, routing_view, hermes_hub_app, unified_health), which would have
put two agents into the same merge conflicts. Ownership is now split by file
path, with docs/UI_STATE_CONTRACT.md as the interface between them.

Four draft items were already implemented at 50fde5f and are marked as such
rather than reassigned: OAuth URL copy-before-open, keyed account card reuse,
the no-fake-metrics rule, and the importorskip guard.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 23:13:59 +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
559a56d80b docs(task): Plan A refactoring task with verified baseline statuses
Every Round 4 finding re-checked against HEAD 63c0385 instead of being carried
forward as still-open. Four are already fixed (customtkinter collection guard,
_CM_LOCK scope, gemini:antigravity restore, session affinity TTL), two are
partial, one is obsolete (web stack moved to legacy/), and five remain open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:31:07 +07:00
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