hermes-hub/agents/inbox/2026-08-23-A16-antigravity-flash-web-client.md
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

14 KiB
Raw Blame History

Задание A16 (Antigravity Flash, другой ПК): веб-клиент

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

2026-08-23

База

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

Ветка

antigravity/web-client


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

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

Сначала коммит, потом git push -u origin antigravity/web-client. В конце — push и проверка:

git status                                       <- дерево чистое
git log --oneline -1 origin/antigravity/web-client  <- ваш финальный коммит

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

Приложены восемь скриншотов, пять содержательных. Скриншот «Аккаунты» подтверждает компактные карточки фиксированной высоты без раскрытия. В unified_health добавлено свойство auth_label_ru — правка вне заявленной зоны, но безобидная. Слияние без конфликтов, 316 passed.

Что не сошлось, и это важно для нового задания.

accounts_view.py и quotas_view.py не изменялись — второе задание подряд. Пункты при этом оказались закрыты чужой работой: компактные карточки пришли из components.py, а пункт навигации «Квоты и лимиты» убрал Codex ещё в 40b3466. То есть в отчёте они числятся сделанными вами, а сделаны не вами.

Три скриншота из восьми — пустой чёрный кадр: шаг мастера Grok, окно роли, детали аккаунта. Два весят ровно по 1148 байт. Живое подключение Grok ими не подтверждено, а именно оно и требовалось.

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


Решение владельца: переходим на веб-интерфейс

У владельца сервер с Ubuntu Server и Xubuntu. Веб-интерфейс там строго лучше десктопа. Десктоп остаётся рабочим до паритета — router/ui/** не трогаем вообще.

Ваша часть — клиент. Параллельно A15 делает серверную.

Читать перед началом: docs/web-api/CONTRACT.md. Это единственный источник истины. Вы пишете против документа, а не против чужого кода — сервера вы не увидите до слияния. Любое отклонение от контракта — дефект, даже если у вас всё работает.

Вы не заблокированы готовностью сервера

Рядом лежит docs/web-api/snapshot.example.json — настоящий снапшот с машины владельца: 63 профиля, 187 КБ, почты замаскированы, секретов нет.

Разрабатывайте против этого файла. Пока сервера нет, fetch('/api/snapshot') подменяется загрузкой фикстуры — один флаг в начале app.js. Когда сервер появится, переключение будет стоить одну строку.


P0-1. Клиент без сборки

src/antigravity_provider/router/web/static/
    index.html
    app.js
    style.css

Обычный JavaScript и fetch. Без npm, без сборки, без фреймворка.

Это не вкусовщина. Проект ведут агенты на трёх машинах; любой шаг сборки означает согласование версий Node и дрейф lock-файлов. Страница, которую можно открыть файлом и отладить в браузере без инструментов, снимает целый класс проблем. React в проекте отклонён и раньше, по той же причине.

Опрос /api/snapshot раз в 5 секунд и после каждого действия.

Обязательно: поле seq в снапшоте монотонно растёт. Ответ с seq меньше уже применённого игнорировать — иначе поздний ответ затрёт свежий. Этот дефект в десктопе уже ловили, повторять не нужно.

P0-2. Экраны — порядок по ценности

Не пытайтесь сразу повторить все девять разделов десктопа. Порядок такой, и он не случаен:

1. Аккаунты — самый нужный экран и самая старая жалоба владельца.

  • плотный список фиксированной высоты: провайдер, идентичность, роль, состояние авторизации, квота — одной строкой, без раскрытия;
  • квота видна сразу, числом и полосой, с указанием пула и периода. У Antigravity четыре пула, «просто процент» вводит в заблуждение — нужно Claude/GPT — неделя, а не 62%. В фикстуре эти данные есть, посмотрите структуру quotas;
  • шестнадцать аккаунтов читаются без прокрутки внутрь карточек.

2. Обзор — готовность, роли, схема маршрутизации, последние события.

3. Маршрутизация — цепочка основной → резервы, активный узел, причина последнего переключения.

Дальше — по остатку времени. Пустой раздел не заводить: либо содержание, либо нет пункта меню.

P0-3. Действия

Все через POST /api/action с телом {"action": "...", "data": {...}}. Семнадцать имён перечислены в контракте.

Ответ {"ok": bool, "message": str}. ok: false приходит с кодом 200 — это нормальный отказ действия, а не ошибка сети. Обрабатывать как результат, а не как сбой.

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

  • результат действия виден в месте действия, а не в строке состояния внизу, где его не замечают;
  • при ошибке модальное окно не закрывается — человек должен видеть причину;
  • долгие операции (refresh_all, test) возвращают «запущено» сразу, результат приходит следующим снапшотом. Показывать это как выполняющееся, а не как зависшее.

P0-4. Честность на экране

Правило проекта действует в вебе без исключений.

  • Ни одного числа, идентификатора или названия модели без измерения.
  • Нет данных — «Н/Д» и причина рядом, доступная пользователю. Причина уже приходит в снапшоте полем unavailable_reason. Владелец прямо спрашивал: «что означает н/д в маршрутизации» — прочерк без объяснения его не устраивает.
  • Отличать «данных нет» от «данные ещё грузятся». Найдено при проверке прошлого раунда: квота появляется только после фонового опроса, а до него карточки стоят пустыми и это выглядит как поломка. A15 добавит в снапшот поле состояния — до его появления показывайте загрузку по отсутствию значения при is_stale.

P0-5. Авторизация на сервере без экрана — сказать правду

Разобрано по коду:

Провайдер Поток На headless-сервере
OpenAI Codex device-code работает — код вводится с любой машины
Grok device-code работает
Antigravity redirect на localhost не работает
Claude redirect на localhost не работает

У двух последних редирект придёт на машину пользователя, а не сервера.

A15 сообщит клиенту доступность потоков с причиной. Недоступный поток показывать отключённым с объяснением и обходным путём, а не рабочей кнопкой, которая молча ничего не сделает. Это то же правило честности: кнопка, обещающая невозможное, — та же ложь, что выдуманная квота.

Для device-code повторить то, что уже отработано в десктопе: пронумерованная последовательность, код крупно и моноширинным, кнопки копирования ссылки и кода. Владелец жаловался «появляется код, куда его вставлять, не понятно» — не повторяйте.

P0-6. Оформление

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

Ширина от 1280 и выше. Мобильную вёрстку не делать.


Ограничения

  • Ваши файлы: src/antigravity_provider/router/web/static/**, tests/test_web_client_*.py. Не ваши: router/web/ кроме static/, router/ui/**, backend целиком.
  • Контракт не менять в одностороннем порядке. Нужна правка — скажите, она согласуется с A15.
  • Секретов на клиенте не хранить и в URL не передавать.
  • Тег v0.1.1 не создавать.

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

  1. Ветка в origin, финальный коммит виден, git status чист.
  2. Клиент работает против snapshot.example.json без сервера; переключение на живой API — не более одной строки.
  3. Никакой сборки: страница открывается и отлаживается без npm и без инструментов.
  4. Ответ с устаревшим seq игнорируется; проверено тестом.
  5. «Аккаунты»: плотный список без раскрытия, квота видна сразу с пулом и периодом, шестнадцать аккаунтов без внутренней прокрутки.
  6. «Обзор» и «Маршрутизация» на реальных данных фикстуры.
  7. У каждого «Н/Д» доступна причина; загрузка отличается от отсутствия данных.
  8. ok: false обрабатывается как результат, а не как сбой; ошибка видна в месте действия; окно при ошибке не закрывается.
  9. Недоступные на сервере потоки авторизации показаны отключёнными с причиной и обходным путём.
  10. Скриншоты каждого экрана — открытые и проверенные. Пустой кадр не прикладывать.
  11. ruff check . чисто; релизный гейт остаётся 7/7.
  12. Отчёт: START_HEAD, FINAL_HEAD, origin/main, git status, точный X passed / Y skipped / Z failed.

Главное

Веб-интерфейс — единственный способ пользоваться Hub на сервере владельца. Первый экран, который должен заработать по-настоящему, — «Аккаунты» с видимыми квотами: это самая старая незакрытая жалоба, и она тянется с самого начала проекта.

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

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