hermes-hub/agents/inbox/2026-08-23-A17-antigravity-pro-honest-status.md
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

13 KiB
Raw Blame History

Задание A17 (Antigravity Pro): честный статус аккаунта и настоящая проверка

Дата поступления

2026-08-23

База

Проверочный HEAD на момент выдачи: fb23bff.

Ветка

antigravity/honest-status


Порядок работы с git

cd <каталог репозитория>; git fetch origin --prune; git status
git checkout main; git pull --ff-only origin main
git checkout -b antigravity/honest-status

Сначала коммит, потом push. В прошлый раз работа A15 была выполнена целиком, но осталась незакоммиченной в рабочем каталоге — git в вашем окружении был недоступен, и ветка в origin оказалась пустой. Её нашли случайно.

Если git снова недоступен — скажите об этом первой строкой отчёта, а не в предупреждении под ним. Это меняет весь порядок приёмки.

В конце:

git status                                              <- дерево чистое
git log --oneline -1 origin/antigravity/honest-status   <- ваш коммит

Что принято по A15

Веб-API и вынесение действий в общий ActionExecutor — правильная архитектура, и она работает. Порт путей на Linux почти закрыт: осталось одно место, hermes_hub_app.py:37.

Но в сданном виде не работало ни то, ни другое, и это важнее похвалы:

  1. Десктоп был уничтожен. При выносе действий пропало объявление class HermesHubApp вместе с 13 методами каркаса — __init__, _build_layout, _create_view, _show_view, _refresh_data. Оставшиеся 14 методов оказались вложены внутрь функции _load_saved_theme после её return — синтаксически валидный недостижимый код. Поэтому модуль импортировался, и дефект выглядел безобидным, а launch_hub() упал бы с NameError.

  2. Веб-API падал с 500 на обоих значимых эндпоинтах: get_auth_token и run_server читали config.hub, которого у RouterConfig нет. Работал только /api/healthу него нет проверки авторизации, из-за чего сервер и выглядел поднявшимся.

  3. do_save_settings при переносе потеряла атомарную запись через os.replace, ensure_ascii=False и вызов set_refresh_interval — интервал обновления квот из настроек перестал применяться.

Всё восстановлено ревьюером. Урок один и он общий для проекта: крупное перемещение кода проверяется запуском того, что перемещали. Импорт модуля ничего не доказывает — Python примет и недостижимый код.


Главное: «Работает» — вымышленный статус

Владелец сообщил про два аккаунта: «стоит опенкод аккаунт, который не подключён… аккаунт не работает» и «и грок не работает». Оба показаны зелёным «Работает».

По одному из них причина найдена и уже исправлена: адаптер OpenCode не читал сохранённый ключ (fb23bff). Но осталась причина, общая для обоих и более глубокая.

unified_health.py:429STATUS_HEALTHY с подписью «Работает» назначается в ветке else, когда ни одно условие отказа не совпало:

1. не enabled            -> Отключён
2. нет учётных данных    -> Аккаунт не добавлен / Требуется вход / Холодный резерв
3. cooldown или квота    -> Квота исчерпана
4. rate limit            -> Лимит запросов
5. precord.overall_state -> Ошибка
6. иначе                 -> «Работает»     <- сюда попадает всё непроверенное

Состояния отказа берутся из precord — записей health tracker, которые появляются только после настоящего сбоя в бою. Профиль, который ни разу не вызывали, автоматически получает зелёное «Работает».

То есть надпись означает «мы не знаем о проблемах», а подана как утверждение, что аккаунт работает. Это тот же класс дефекта, из-за которого в первом аудите проекта были удалены выдуманные проценты квот: отсутствие данных выдаётся за положительный результат.

Что требуется

  1. Различать «проверено и работает» и «не проверялось». Профиль без подтверждения не должен выглядеть так же, как подтверждённо рабочий. Формулировку выберите сами, но она обязана быть честной: «Не проверялся» — правда, «Работает» — нет.

  2. Хранить результат и время последней успешной проверки рядом с профилем и отдавать их в снапшоте. Интерфейсу нужно показать «проверено 12:05», а не только цвет.

  3. Состояние отказа по-прежнему приходит из боевых сбоев — это правильно и ломать не нужно.

Тест: профиль со свежесохранёнными учётными данными и без единой проверки не получает статус, утверждающий работоспособность.

P0-2. «Проверить подключение» ничего не проверяет

do_test_profile проверяет наличие учётных данных и доступность локального runtime — и никогда не вызывает модель. Поэтому Grok эту проверку проходит и всё равно не работает.

Так сложилось не случайно: требование «тест не должен запускать OAuth и открывать браузер» стоит в проекте с первого аудита, и ради него вызов модели убрали целиком. Требование верное, но реализация выплеснула вместе с ним смысл проверки.

Требуется настоящая проверка, не нарушающая прежнего запрета:

  • минимальный реальный вызов к провайдеру — самый дешёвый из возможных, с жёстким таймаутом;
  • интерактивный вход не запускается ни при каких условиях: просроченные учётные данные дают ошибку «Авторизация истекла», а не окно браузера. Для Antigravity это уже обеспечено флагами BROWSER=none и CI=1 в окружении подпроцесса и проверкой срока токена до вызова;
  • результат сохраняется как последняя проверка (P0-1) с временем;
  • по каждому провайдеру в отчёте: что именно вызывается и сколько это стоит владельцу. Если у провайдера нет дешёвого способа — сказать об этом прямо, а не имитировать проверку.

Осторожно с ценой: у владельца шесть аккаунтов Antigravity, три Codex, три OpenCode. Проверка всех подряд не должна съедать квоту. Массовую проверку делать по явной команде, а не автоматически при каждом обновлении.

Тест: просроченные учётные данные дают ошибку авторизации без попытки интерактивного входа; успешная проверка фиксируется с временем.

P1-3. Остаток порта на Linux

hermes_hub_app.py:37 по-прежнему читает LOCALAPPDATA напрямую:

_LOCAL = Path(os.environ.get("LOCALAPPDATA", ""))

На Linux это даст пустой путь. Провести через paths.get_hermes_home(), как остальные семь мест.

В agy_subprocess.py два оставшихся упоминания трогать не нужно: строка 41 — комментарий, строка 414 — список переменных окружения, пробрасываемых подпроцессу на Windows, и он там уместен.


Ограничения

  • Параллельно идут A18 (смена модели) и A19 (установщики). Ваши файлы: unified_health.py, health_tracker.py, action_handler.py, adapters/**, state_store.py, hermes_hub_app.py, docs/UI_STATE_CONTRACT.md, docs/web-api/CONTRACT.md. Не ваши: router/web/**, router/ui/**, model_discovery*, installer/**, launcher/**.
  • Меняете снапшот — правьте docs/web-api/CONTRACT.md и скажите об этом в отчёте: против него пишется клиент.
  • Никаких статусов без основания. Нет проверки — так и написать.
  • Тег v0.1.1 не создавать.

Критерии приёмки

  1. Ветка в origin, git status чист. Если git был недоступен — сказано первой строкой отчёта.
  2. Непроверенный профиль не показывается как работающий; проверено тестом.
  3. Результат и время последней проверки хранятся и приходят в снапшоте; контракт обновлён.
  4. «Проверить подключение» делает реальный вызов с таймаутом и не запускает интерактивный вход ни при каких условиях; проверено тестом на просроченных данных.
  5. В отчёте по каждому провайдеру сказано, что вызывается при проверке и во что это обходится владельцу.
  6. Массовая проверка не запускается автоматически при обновлении данных.
  7. hermes_hub_app.py:37 больше не читает LOCALAPPDATA напрямую.
  8. Прогон в обоих окружениях; ruff check . чисто; релизный гейт не ухудшен (сейчас 7/7).
  9. Отчёт: START_HEAD, FINAL_HEAD, origin/main, git status, точный X passed / Y skipped / Z failed. На main сейчас 331 passed, 2 skipped.

Главное

Зелёная галочка на нерабочем аккаунте — худший вид лжи в этом продукте: она не просто бесполезна, она уводит от поиска настоящей причины. Владелец потратил на это два обращения. Лучше честное «не проверялся», чем уверенное «работает».

Порядок сдачи

Передать точный FINAL_COMMIT_SHA. Сдано только после появления коммита в origin.