Both agents work on other machines and push straight to git. A8 and B7 were pinned to8cddc9fwhile main had already moved to7f912f1, 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>
18 KiB
Задание A8 (Antigravity): запуск, развёртывание, самопроверка
Дата поступления
2026-08-22
База
Проверочный HEAD на момент выдачи: 7f912f1. Обязательно обновить локальную копию — см. следующий раздел.
Ветка
antigravity/deployment-doctor
Перед началом: обновить локальную копию
Задание выдано, когда origin/main был 7f912f1. Ваша рабочая копия на другой машине почти наверняка отстала — за последние сутки в main вошло 9 коммитов, включая работу Codex по интерфейсу и ваши же принятые задания A6–A7.
Порядок:
cd <каталог репозитория>; git fetch origin --prune; git status
Если рабочее дерево чистое:
git checkout main; git reset --hard origin/main
Если есть незакоммиченные правки — сначала сохранить их отдельной веткой, вслепую сбрасывать нельзя.
После обновления зафиксировать фактический BASE_SHA командой git rev-parse --short HEAD и указать его в отчёте. Не считать 7f912f1 актуальным автоматически: пока вы работаете, main может уйти вперёд.
Ветку создавать от свежего origin/main, не от старого состояния. Иначе слияние принесёт откат чужой работы — так уже случалось: ветка Codex содержала устаревшую распаковку start_profile_oauth, и при неаккуратном слиянии подключение Antigravity-аккаунта снова бы сломалось.
Что принято по A7
Проверено исполнением: лизы объединены (engine.leases is LeaseManager.get() → True, снапшот показывает {'codex-orch': 1}), CPU прогревается (первое измерение 25.0 вместо нуля), сеть стала скоростью net_speed_mbps. Прогон: headless 195, с UI-зависимостями 249, ruff чисто, гейт PASSED.
Контекст: владелец впервые эксплуатировал Hub
Вчера и сегодня продукт запускали вживую. Результат: роутер работает, оболочка — нет. В журнале зафиксирован настоящий каскад отказоустойчивости:
20:07:10 Переключение роли 'orchestrator': сбой 'codex-orch' — Insufficient quota
20:07:10 Успешное переключение: резервный профиль 'ag-orch-fallback'
20:07:10 Переключение: сбой 'ag-orch-fallback' — Individual quota reached
20:07:10 Успешное переключение: резервный профиль 'opengo-3'
Это первое доказательство, что ядро делает то, ради чего создавалось. Всё остальное, о чём сообщил владелец, — дефекты вокруг ядра.
P0-1. Hub перестал запускаться: зависимость живёт в чужом окружении
Симптом: «программа запускается и сразу закрывается». Причина воспроизведена:
ModuleNotFoundError: No module named 'customtkinter'
Лаунчер запускает pythonw.exe — без консоли, поэтому трейсбек уходит в никуда и окно просто не появляется. Ещё в 09:41 Hub стартовал нормально; пакет исчез между 09:41 и вечером. Наиболее вероятная причина — кнопка «Repair install» в диалоге ошибки Hermes: она пересоздаёт venv агента и стирает всё доустановленное.
Я вернул пакет вручную, Hub снова импортируется. Но проблема архитектурная: Hub держит свои зависимости в venv чужого приложения, которое их периодически сносит.
Требуется:
- Самолечение при запуске. Перед созданием окна проверять импорт
customtkinter,PIL,psutil,yaml. Если чего-то нет — доустановить в venv Hermes и повторить, либо показать понятное окно с одной кнопкой «Установить зависимости». - Ошибка запуска должна быть видимой. Сейчас любой сбой до создания окна = тишина. Писать трейсбек в
logs/startup.logдо импорта UI и, при падении, показывать нативное окно с текстом ошибки и путём к логу. Файл уже есть, но пишется слишком поздно. - Оценить переход на собственный venv Hub рядом с
%LOCALAPPDATA%\Programs\HermesHub\, чтобы обслуживание Hermes не ломало Hub. Если решение — остаться в venv Hermes, записать это как осознанный выбор с обоснованием.
P0-2. Мастер предлагает провайдеров, для которых нет профилей
Симптом владельца: «завершить не нажимается, пишет что всё исчерпано, но нет».
Причина: мастер предлагает пять провайдеров, а в конфигурации роутера профили есть только для трёх.
antigravity 10 профилей
openai-codex 3 профиля
opencode-go 3 профиля
claude НЕТ НИ ОДНОГО
grok НЕТ НИ ОДНОГО
AutoAssigner.find_free_slot перебирает claude-orch, claude-worker-1… не находит их в конфиге, пропускает все и возвращает candidates[0] — то есть несуществующий claude-orch. Дальше мастер сохраняет авторизацию в слот, которого нет, назначение роли отвечает «профиль не найден», завершение не проходит.
Требуется: профили для claude и grok во встроенной конфигурации и в шаблоне router_profiles.example.yaml, по образцу существующих, с ролями в цепочках. И find_free_slot не должен возвращать идентификатор, отсутствующий в конфиге, — при отсутствии свободных слотов возвращать None с внятной причиной.
Тест: для каждого провайдера, который предлагает мастер, find_free_slot возвращает либо существующий профиль, либо None.
P0-3. Кнопка «Тест» открывает окно авторизации
Симптом: «при тесте открывается опять окно авторизации и ничего».
В журнале: Ошибка теста ag-orch-fallback (gemini-3.7-flash): Antigravity error: agy error: authentication failed or timed out.
Проверка учётных данных в do_test_profile выполняется, но затем вызывается адаптер, а он запускает agy — и этот подпроцесс сам открывает браузер, когда токен просрочен. Требование «тест никогда не запускает OAuth» стоит в проекте с первого аудита и нарушено на уровне подпроцесса.
Требуется: запускать agy в неинтерактивном режиме, чтобы при невалидных учётных данных он возвращал ошибку, а не открывал окно. Если у CLI нет такого флага — проверять валидность токена до вызова и не доходить до подпроцесса. Результатом теста в этом случае должно быть «Авторизация истекла, требуется повторный вход», а не молчаливое окно браузера.
Тест: просроченные учётные данные дают ошибку авторизации без попытки интерактивного входа.
P0-4. Установка должна быть зеркалом, а не наслоением
HermesHubSetup.cs:279 делает CopyDirectoryRecursive — только копирует, никогда не удаляет. Развёрнуто у владельца 51 файл от 19 августа против 70 в репозитории, и среди них четыре модуля, удалённых нами как мёртвый код:
router/capability/
router/skills/skill_registry.py
router/supervisor/lifecycle_supervisor.py
router/gui_server.py
Сами по себе инертны, но однажды уже ввели в заблуждение: тесты подхватывали runtime.py из развёрнутой копии.
Требуется точное зеркало источника: удалять файлы, которых нет в источнике, исключать __pycache__. Тест: развернуть, удалить файл из источника, развернуть снова, убедиться, что в цели его нет.
P0-4bis. Установщик должен различать первую установку и переустановку
Требование владельца: если программа уже установлена, мастер обязан предлагать переустановку, а не повторять сценарий первой установки.
Сейчас SetupEngine.IsInstalled вычисляется (HermesHubSetup.cs:86), но в интерфейсе не используется ни разу. Мастер всегда показывает одни и те же экраны — «Добро пожаловать в установку» → «Параметры установки» → «Установить», — независимо от того, стоит Hub на машине или нет.
Требуется: при обнаружении установленной копии первый экран показывает её состояние и предлагает действия.
Hermes Hub уже установлен
Установленная версия : 0.1.0 (19.08.2026)
Версия в дистрибутиве: 0.1.1
[ Переустановить ] [ Удалить ] [ Отмена ]
Переустановка означает точное зеркало: файлы программы и плагина приводятся в соответствие дистрибутиву, а всё, чего в новой версии нет, — удаляется. Это тот же механизм, что и в P0-4, но вызванный явной кнопкой.
Что удаляется: устаревшие модули, файлы переименованных и перенесённых пакетов, __pycache__, скомпилированные остатки прошлых версий.
Что обязано сохраниться: router_profiles.yaml, каталоги профилей с авторизацией (agy_profiles, codex_profiles, opengo_profiles и аналогичные), hub_settings.json, журналы, состояние роутера и телеметрии. Пользовательские данные лежат отдельно от программных файлов — переустановка их не касается.
Перед удалением показать, что именно будет удалено, хотя бы количеством файлов. Молча стирать нельзя.
Тихий режим: добавить флаг /reinstall с тем же поведением и кодами возврата, что и у остальных режимов. Существующий /repair либо привести к этой же семантике, либо явно развести: сейчас он объявлен, но отличие от обычной установки не документировано.
Тесты:
- В песочнице: развернуть версию A, удалить файл из источника, запустить переустановку версии B — файла в цели нет, остальные соответствуют источнику.
- Пользовательские данные переживают переустановку: создать профиль с
auth.json,router_profiles.yamlс правкой иhub_settings.json, переустановить, убедиться, что всё на месте и не изменилось. - Обнаружение установленной копии: при наличии
HermesHub.exeмастер показывает экран переустановки, при отсутствии — обычный сценарий.
P0-5. Команда самопроверки
Расширить print_diagnostics_cli до проверки, отвечающей на вопрос «работает ли Hub» без запуска десктопа Hermes:
- зависимости в venv с указанием, чего не хватает;
- свежесть развёрнутого плагина против версии приложения (для этого при установке писать манифест: версия, дата, коммит);
- валидность
router_profiles.yaml, число профилей и ролей; - по каждому профилю: провайдер, идентичность, авторизация, квота, источник данных;
- реальный тестовый вызов по одному профилю на провайдера;
- итог одной строкой: готов / частично / не готов, с причинами.
Секреты в выводе маскируются.
P1-6. Остаток по YAML
Внутренние комментарии router_profiles.yaml теряются (7 → 2). Либо полный round-trip, либо статус «частично» с перечнем теряемого — в контракте и отчёте.
Ограничения
- Граница прежняя: зона Codex (
router/ui/**,hermes_hub_app.py,tests/test_ui_*.py) — не трогать. Исключение по P0-1: проверка зависимостей до создания окна лежит в точке входа; согласовать минимальную правку, остальное — данными. - Тег
v0.1.1не создавать.
Критерии приёмки
- При наличии установленной копии мастер предлагает переустановку и удаление, а не сценарий первой установки; версии установленной и новой видны на экране.
- Переустановка удаляет устаревшие файлы и сохраняет пользовательские данные; оба условия проверены тестами в песочнице.
- Hub запускается на машине без
customtkinter: либо доустанавливает, либо показывает окно с понятной ошибкой. Проверено на изолированном venv. - Любой сбой до создания окна попадает в
startup.logс трейсбеком. - Для всех пяти провайдеров мастера
find_free_slotвозвращает существующий профиль илиNone. - Тест профиля с просроченной авторизацией не открывает браузер.
- Повторное развёртывание удаляет исчезнувшие файлы.
- Самопроверка работает без запущенного Hermes и печатает связный вердикт без секретов.
- Прогон в обоих окружениях; обе команды и оба результата в отчёте.
ruff check .чисто; release gate PASSED на финальном коммите.- Отчёт:
START_HEAD,FINAL_HEAD,origin/main,git status, точныйX passed / Y skipped / Z failed.
Порядок сдачи
Передать точный FINAL_COMMIT_SHA.