Для agy: три installer-теста и компиляция C# исключены из каждого прогона
CI (addopts = "not installer") и никогда не выполнялись на реальной сборке;
ни один тег release.yml не дошёл до публикации (все падали на Release Gate,
устранено в HUB-1, но конвейер после починки ни разу не прогонялся). Задание
просит собрать dist/HermesHubSetup.exe, прогнать installer-тесты и один цикл
release.yml на настоящей Windows-машине с реальными учётными данными agy —
это то, что серверная сессия сделать не может.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Найдено сверх задания и сверх аудита.
Каждый прогон 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>
Тринадцать файлов существовали только на диске ПК владельца, в рабочей
копии, отставшей от origin/main на 122 коммита. Их реализация и тесты
давно влиты: tests/test_a42_provider_connect.py,
test_a49_subagents_skills_memory.py, test_a51_hub_controls_hermes.py,
test_a52_local_models_supervisor_dual.py, test_a55_account_connection.py,
test_a56_context_compression.py и другие. Постановок, объясняющих, что
эти тесты обязаны доказывать, в репозитории не было.
Правило записано в agents/AGENTS.md: задание живёт в репозитории, а не в
переписке и не в личных папках на диске.
A48, A50 и A54 не переносятся: они уже есть на origin под другими именами,
содержимое совпадает с точностью до перевода строки в конце файла.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Задание для серверной сессии Claude (не для agy): довести main до зелёного и
закрыть P0 аудита Hermes Hub. Шаг 1 плана слияния — стабильный Hermes как эталон
переноса.
Причина красного main найдена ревьюером в логе CI, а не по аудиту:
- test_a37_isolation_guards.py:394 — WorkspaceBoundaryGuard пропускает
rm -rf $HOME/.hermes на Windows (провал security-инварианта);
- verify_multi_provider_router.py:63 — UnicodeEncodeError на cp1252 при печати
русского текста.
Остальные P0 (Release Gate hash, publication gate fail-open, /api/action CSRF) —
подтвердить исполнением перед правкой. pricing safe_dump — реальный, в P1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Поставил v0.1.2-b7 в изолированную песочницу (свои HOME и HERMES_HOME, живая
установка не тронута) и запустил обновление на v0.1.3-b1. Хаб умер через шесть
секунд и за 150 секунд не поднялся. Установка при этом не произошла вовсе:
манифест и код остались на 0.1.2.
В задании было написано, что установщик доживает сиротой и файлы обновляет.
Прогон это опроверг. Настоящая цепочка: хаб зовёт установщик через
capture_output=True, то есть читателем его вывода становится сам хаб; установщик
на шаге [0/6] снимает хаб; у трубы не остаётся читателя; следующий echo даёт
SIGPIPE, и установщик умирает на шаге [1/6], не поставив ничего. Проверено
контрольным опытом: тот же скрипт с выводом в файл доходит до конца, с трубой
умирает. Отсюда следует, что перестановкой schedule_restart делу не помочь.
Тем же прогоном найдено второе: deployed_at пишется в момент установки, а не
сборки, и сравнивается с датой публикации релиза. Хаб на b7 при живом b1 ответил
«установлена сборка новее опубликованного релиза» и обновление не предложил.
Переустановил старую сборку — выпал из обновлений молча. Вынесено в P0-5.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EDLuenXmGjWaS2rs8E72En
A59 влит, база задания указана коммитом. Порог тестов поднят с 725 до 740:
столько в main после слияния с ветками A58 и A59.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EDLuenXmGjWaS2rs8E72En
A59 довёл обновление до экрана: окно при запуске, видимая загрузка, честное Н/Д,
отмена. Дальше механизм обрывается на самом простом — установщик снимает тот
процесс, который его запустил и ждёт результата, поэтому перезапуск не наступает
никогда.
Корень один на обеих системах. На Linux install-linux.sh снимает всё по шаблону,
никого не исключая. На Windows StopOwnedRuntime строит цепочку предков, но
проверяет её только для дочерних процессов, а сам процесс-цель снимает
безусловно — прочитано по коду, подтвердить исполнением.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EDLuenXmGjWaS2rs8E72En
Владелец показал, как это сделано в Cockpit Tools: окно при запуске, видимая
загрузка, останов служб, установка и запуск без участия человека.
Строить заново нечего. Проверено: проверка при запуске уже выполняется, но в
тихом режиме; обработчик хода скачивания в загрузчике уже написан, но его
результат никуда не выводится; останов и перезапуск держатся на schedule_restart
и не проверены на обеих системах.
Внешнее условие: лента релизов отстала на v0.1.2-b7 при установленной 0.1.3 —
пока свежий релиз не опубликован, обновлять не на что.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец теряет время не на сам обход, а на то, что узнаёт о слетевшем патче
случайно, по невнятному отказу посреди работы.
Установлено ревьюером: строки отказа в бинарнике нет — её присылает сервер, но
отказывается работать клиент. Прокси не помогает, измерено на двух странах:
ограничение привязано к аккаунту. Патчер владельца правит четыре байта машинного
кода, подменять в настройках нечего.
Хаб только читает и сообщает; действие остаётся за владельцем и выполняется его
собственным средством. Патчить чужой бинарник хабу запрещено отдельным пунктом.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Хаб сейчас записывает чужой файл учётных данных своим кодом: формат восстановлен
по рабочему профилю владельца и по строкам в бинарнике. Работает, но до
следующего обновления agy — и отказ будет молчаливым.
Проверено запуском: подкоманд login или auth у agy нет, вход только запуском CLI
без аргументов. Значит вход переносится в терминал с HOME на каталог профиля,
а браузерный путь остаётся запасным для удалённого случая.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Установка на Windows упала с кодом 12, и причина была не в новом коде, а в
накопленном состоянии: конфигурация тащила роль под старым именем, роли без
цепочек и 24 пустых заготовки, переживших несколько переименований. Проверка
споткнулась о наследие.
Владелец сформулировал вывод: при первой установке всё должно начинаться с
нуля — сначала аккаунты, потом распределение по агентам.
Задание разводит два случая: конфигурации нет — первая установка, профилей не
создаётся вовсе; конфигурация есть — обновление, ничего не трогается. Плюс
явная кнопка сброса с подтверждением и резервной копией.
Отдельным пунктом, из-за цены ошибки: сброс касается только маршрутизации.
Каталог agy_profiles не затрагивается ни при каких условиях — потеря учётных
данных означает повторный ручной вход в два десятка аккаунтов, включая
Antigravity со входом по ссылке для каждого профиля.
Требуется также прогнать проверочный скрипт установщика на ПУСТОЙ
конфигурации: он этого случая никогда не видел, у него всегда было 24
профиля, и падение на чистой машине дало бы тот же код 12 новому
пользователю.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Отчёт benchmarks/BENCHMARK_REPORT.md открывается словами «Все метрики сняты
реальным исполнением на стенде». Для трёх строк из семи это неправда.
Сверено с диском сервера. Четыре модели существуют, их размеры совпадают с
отчётом до сотых: 17,67 / 8,37 / 4,60 / 2,33 ГБ. Трёх других нет вовсе:
deepseek-coder-v2-lite и phi-4-14b — каталоги пусты, файлов GGUF нет;
nemotron-cascade-30b не существует на сервере нигде. При этом в
benchmark_results.json DeepSeek и Phi-4 помечены COMPLETED, а у Nemotron
статус честнее, но числа при нём всё равно проставлены.
На этом построена рекомендация: DeepSeek-Coder-V2-Lite назван «лучшим
выбором для максимальной скорости» с точностью до десятой доли — по модели,
которая никогда не запускалась. Владелец собирается менять рабочую модель, и
цена такой строки — неверное решение, а не неточность в документе.
Замеры по четырём настоящим моделям признаны и переделке не подлежат;
главный вывод — Qwen2.5-Coder-14B держит качество 27B при втрое большей
скорости — остаётся в силе.
Задание вводит правило: строка появляется только при наличии пути к файлу,
размера в байтах из stat, контрольной суммы и сырых таймингов от сервера.
Модель не скачалась — раздел «не проверено» с причиной, это принимается.
Добавлены новые кандидаты, отобранные по проверенным характеристикам:
qwen2.5-coder-32b, granite4.2:8b (на диске лежит 3.2-preview, а не релиз),
nemotron-3.5-lightning, laguna-xs-2.1, lfm2.5. Отклонены с проверкой:
gpt-oss:120b (80 ГБ), Qwen3.8-Flash-Next (125B/6B, ужатое IQ1_S — 72,5 ГБ).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Локальная модель не закрывает задачи: Hermes сообщает о таймауте 180 секунд
после четырёх вызовов и переключается на другого провайдера.
Причина измерена, а не предположена. Служба запущена с --reasoning on и
--reasoning-budget 4096, а модель выдаёт 13,4 токена в секунду. На простой
задаче рефакторинга с лимитом 1500 токенов получено:
сгенерировано 1500 токенов за 111,6 с
рассуждений 5483 символа
ответа 0 символов
Весь лимит уходит на размышления, до ответа модель не доходит. За 180 секунд
она успевает около 2400 токенов — и это тоже одни рассуждения.
Отключение рассуждений на уровне запроса проверено и работает:
reasoning_effort: none ответ за 19,5 с
chat_template_kwargs: enable_thinking=false ответ за 11,4 с
Одиннадцать секунд вместо ста одиннадцати. Серверный флаг --reasoning off
решил бы это грубо, лишив рассуждений насовсем, поэтому владелец выбрал
гибкий путь: параметры задаёт хаб, по профилю.
Задание требует не зашивать ни enable_thinking, ни reasoning_effort: набор
ключей зависит от версии llama.cpp, и это данные конфигурации, а не
константы кода. Отдельным критерием — проверка живым запросом к серверу
владельца с замером времени до и после.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Локальный кодер выдаёт 13,6 токена в секунду, и владелец хочет понять, есть
ли модель быстрее при сопоставимом качестве.
Базовая линия снята ревьюером на живом сервере и вписана в задание, чтобы не
мерилась заново: Qwen3.8-27B даёт 13,6 ток/с генерации, Qwen3-4B — 124,1,
разница почти девятикратная. Цена контекста измерена точно: 39 КиБ на токен у
27B и 81,5 у 4B.
Отдельно измерен диск, и он оказался узким местом: Crucial BX500 без DRAM,
187 МБ/с мимо кэша, NVMe на машине нет. Загрузка 19-гигабайтной модели с
холодного диска занимает около 100 секунд. Первый замер дал 4,1 ГБ/с, но это
было чтение из кэша оперативной памяти — случай вписан в задание как
предупреждение.
Из списка владельца проверкой отклонён gpt-oss:120b: в карточке модели прямо
указано 80 ГБ и H100. Остальные отсортированы по пригодности для V100, где
скорость определяется активными параметрами, а не общим размером, поэтому
модели MoE поставлены первыми.
Главное требование задания: мерить качество, а не только скорость. Модель,
выдающая 120 ток/с неработающего кода, хуже той, что даёт 13 ток/с рабочего.
Нужен набор из настоящих правок по репозиторию, а не синтетические задачки.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Повод пришёл из разбора новостей: OpenAI описала инцидент, где
экспериментальные агенты использовали внутренний Artifactory как канал связи
между собой, обменивались найденными обходами и в итоге скомпрометировали
часть инфраструктуры Hugging Face. Вывод: deny internet != secure agent.
Задание опирается не на этот инцидент, а на наши собственные случаи, каждый
из которых проверен или произошёл в проекте:
- CORS стоял как allow_origins=["*"] с allow_credentials=True, а на localhost
токен не требуется вовсе: любая открытая рядом страница получала полный
снапшот со всеми аккаунтами и могла вызывать /api/action. Закрыто в
c35bc48;
- агенты координируются через публичный репозиторий, и однажды работа ушла в
main минуя ревью;
- агент Codex переключил ветку в каталоге, где работал ревьюер;
- учётные данные 24 аккаунтов лежат общей кучей, разделения по агентам нет;
- ревьюер удалил учётные данные grok-worker-1, проверяя кнопку удаления, и
ничто этому не помешало;
- хаб открыт в домашнюю сеть поверх HTTP.
Отдельным критерием вынесено требование, что защита не должна ломать продукт:
хаб с включёнными ограничениями обязан оставаться полностью работоспособным.
Выполнять после A34 и A35: пока нельзя подключить аккаунт и хаб не участвует
в вызовах Hermes, укреплять периметр преждевременно.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец описал рабочую схему: flash 3.7 пишет как Кодер 1, gemini pro
проверяет его как Кодер 2 и возвращает на доработку до одобрения, опус 4.6
включается ревьюером после одобрения Pro и при необходимости возвращает
работу Кодеру 2. Две вложенные петли.
Смысл экономический: опус не тратится на то, что отсеет Pro, а Pro не
тратится на то, что flash исправит сам.
Имена моделей взяты из кэша обнаружения на аккаунтах владельца, а не из
головы. Три места, где легко ошибиться, вынесены в задание отдельно:
«гемини про» — это gemini-3.1-pro-high, версии 3.7 у Pro нет вовсе; «опус
4.6» называется claude-opus-4-6-thinking; у flash идентификаторы приходят с
суффиксом усилия, но базовое имя gemini-3.7-flash валидно — ревьюер однажды
уже утверждал обратное и был неправ.
Отдельным пунктом — обязательные пределы итераций. Две вложенные петли без
ограничителя жгут квоту молча, и это самый дорогой дефект в задании.
Приёмка требует журнала живого прогона, где петля действительно сработала:
конвейер, прошедший с первого раза, ничего не доказывает.
Зависит от A35: без него хаб в вызовах Hermes не участвует и конвейер будет
собран, но не заработает.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец заметил, что настройки Hermes не соответствуют настройкам хаба.
Проверка подтвердила худшее: хаб не участвует в вызовах Hermes вообще.
Доказано исполнением. В исходниках Hermes, agent/conversation_loop.py:3221,
middleware вызывается без параметра role — передаются model, provider,
base_url, session_id, task_id, platform, но не роль. А плагин при
неопределённой роли делает next_call(request), то есть пропускает вызов мимо
маршрутизатора. Подача того же набора аргументов на живой плагин:
как зовёт Hermes (без роли) -> МИМО хаба
если роль передана -> обработал хаб
Механизм исправен целиком, его просто никто не включает: аккаунты, цепочки,
квоты и переключение при исчерпании настраиваются и не применяются.
Пропуск появился не по небрежности, а как защита: раньше при неопределённой
роли всё уходило как orchestrator, цепочка исчерпывалась, и текст ошибки
роутера подставлялся вместо ответа модели. Поэтому задание требует третьего
пути — выводить роль из того, что Hermes уже передаёт, с настраиваемой ролью
по умолчанию, сохранив предохранитель на исчерпанную цепочку.
Hermes править запрещено: чужой продукт, правка затрётся при обновлении.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Проверка кандидата A28-A31 в браузере вскрыла блокирующую регрессию: при
переписывании клиента в A29 функции удалили, а вызовы в разметке оставили.
Консоль на живой сборке:
openAddAccountWizard is not defined «+ Добавить аккаунт» не работает
checkUpdates is not defined падает при каждой загрузке
handleNodeAccountChange не сменить аккаунт у агента
handleNodeModelChange не сменить модель
handleRefreshProviderModels не обновить список моделей
Подключить аккаунт в новой сборке невозможно, назначить агенту тоже. При этом
startDeviceAuth и startRedirectAuth в коде остались, но не вызываются ниоткуда.
A34 собирает в один порядок: восстановление подключения (блокирует остальное),
адаптеры OpenRouter и NVIDIA с несколькими аккаунтами, интерфейс автопоиска
локальных серверов поверх готовой серверной части, и удаление десктопа по A32.
Задание опирается на ветку review/a28-a31-fixes, где лежат исправления
ревьюера, и перечисляет их отдельным разделом, чтобы не переделывались.
A32 добавлен в репозиторий: он был написан ранее, но остался только локально.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец передал набор описаний субагентов. Ревьюер сверил каждое с кодом:
большая часть уже реализована в Hermes Hub и сильнее шаблонов. Model Router —
это сам Hub; Retry & Fallback — router_engine с цепочками и порогами квот из
A26; Coordinator в части конфликтов доступа — LeaseManager с max_concurrency,
настраиваемым на профиль. Всё это внесено в задание таблицей «не
реализовывать заново», чтобы к вопросу не возвращались.
В работу вошло только отсутствующее:
- роль «Проверяющий готовность»: проект терял раунды на коде 12 установщика,
неустановленных fastapi/uvicorn, обязательном --effort и отсутствующем
ag_slot_oauth.py — всё это выяснялось посреди прогона;
- состояние прогона для workflow из A30, как механика, а не роль;
- ограничение одновременных вызовов и контекст для локальных моделей: на
сервере владельца два llama.cpp с --parallel 1 и почти исчерпанной памятью;
- маскирование почт: sanitize_snapshot вычищает секреты, но слово email в
server.py не встречается ни разу, а хаб теперь открыт в домашнюю сеть
поверх HTTP.
Отдельно зафиксировано для роли контроля затрат: поля токенов в телеметрии
есть, но провайдеры их не отдают, поэтому расход можно только оценивать — и
оценку нельзя выдавать за измерение.
Выполнять после A28, A29 и A30.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец передал готовый дизайн: брендбук с тремя темами, макеты главного
экрана, маршрутизации и остальных разделов, логотипы. Плюс список из
двенадцати субагентов с расписанными обязанностями.
Объём не помещается в одно задание, поэтому разделено на три с явными
границами по файлам:
A28 реестр ролей и двенадцать субагентов Antigravity, основа
A29 дизайн-система и экран «Маршрутизация» Antigravity
A30 главный экран: граф workflow, LIVE, файлы Codex
Каждое опирается на состояние, снятое исполнением, чтобы агенты не
переписывали работающее и не выясняли заново:
- новая роль уже добавляется через конфигурацию и доходит до снапшота, но
подпись падает в сырой идентификатор, потому что таблицы имён зашиты в
четырёх местах;
- workflow, связей между агентами и файлов агентов в проекте нет вовсе —
это разработка с нуля, а не доработка;
- источники данных для дашборда существуют и настоящие, параллельный
заводить не нужно;
- веб-слой без сборки, и это обосновано в контракте.
В каждом задании отдельно оговорено, что демонстрационные значения с
макетов (12 задач, 3.42 с, 94.2%, account-01) — иллюстрация и в код попасть
не должны. Поверхность для выдуманных данных здесь самая большая за проект.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец обновляется вручную на трёх машинах. Механизм обновления в проекте
есть, но мёртв в каждом звене, и это проверено: веб-клиент check_updates не
вызывает вовсе (0 вхождений); DEFAULT_UPDATE_URL смотрит на заброшенный
второй репозиторий, чей манифест застыл на 0.1.1 от 21 августа; версия
захардкожена в 0.1.1 и подниматься не должна, поэтому сравнение по semver
никогда не скажет «есть обновление».
Рабочая часть — apply_update_sync с резервной копией, py_compile-проверкой и
откатом — сохраняется, переписывать её не нужно.
В задании принято решение, которое агентам не следует угадывать: признак
новизны — коммит, а не версия, источник — релизы основного репозитория, куда
поставка идёт на самом деле.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец сформулировал, ради чего задумывался хаб: вручную распределять
аккаунты по агентам и следить за квотами, подставляя другой аккаунт там, где
лимит подходит к концу. Модель слотов этому мешает — она навязывает
внутреннее устройство конфигурации и уже привела к тому, что подключённый
аккаунт не появился в маршрутизации.
Задание опирается на три факта, снятых исполнением, чтобы агенты не
переписывали работающее: один профиль уже может обслуживать все шесть ролей;
произвольный идентификатор профиля регистрируется, то есть потолок в три
аккаунта Codex держит только зашитый список в auto_assigner; порогов квот в
коде нет вовсе.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Владелец дал доступ по ключу. На 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>
У владельца сервер 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>
Решение владельца по итогам живой эксплуатации: разделов семь вместо
девяти. Убираются «Команда агентов» и «Модели и провайдеры», их
содержимое перераспределяется между маршрутизацией и обзором. Аналитика
остаётся, но должна объяснять свои метрики.
Маршрутизация становится местом управления: перестановка блоков
перетаскиванием, смена модели на месте, кнопка «Изменить цепочку»
убирается.
В задание вынесен вывод из только что найденного дефекта: в веб-мастере
стояли выдуманные коды устройства GRK-7842 и CDX-9104, а тест ТРЕБОВАЛ
наличия неверного адреса, то есть защищал выдумку от исправления.
Пункт P0-6 для второго прохода дополнен проверкой на выдуманные
значения и на тесты, закрепляющие дефект.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Написано под схему владельца: 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>
Владелец возразил на моё утверждение, что 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>
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>
Веб покрывает пять экранов из девяти. Не хватает Аналитики, Состояния,
Журнала событий и Настроек.
Данные для первых двух уже в снапшоте: 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>
Маршрутизация через 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>
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>
Решение владельца: у него сервер с 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>
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>
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>
У 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>
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>
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>
Добавлен раздел P0-0: правка _finish уже в main (7090c8a), её нельзя
потерять при слиянии. Там же второй дефект того же класса —
splash.py вызывает несуществующий AssetManager.get_splash_logo.
Дефект «вызов несуществующего метода» встречается третий раз и под
pythonw всегда молчаливый, поэтому в критерии приёмки добавлено
требование механической проверки UI-слоя.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>