diff --git a/agents/inbox/2026-08-31-A48-interface-by-mockup.md b/agents/inbox/2026-08-31-A48-interface-by-mockup.md new file mode 100644 index 0000000..b025bd4 --- /dev/null +++ b/agents/inbox/2026-08-31-A48-interface-by-mockup.md @@ -0,0 +1,189 @@ +# Задание A48: интерфейс по макетам — исполнитель Codex + +## Дата поступления +2026-08-31 + +## Исполнитель + +**Codex на сервере `192.168.1.81`.** Не Antigravity. + +Задание **отменяет A46**: там та же работа была поставлена Antigravity. Два агента в одних файлах уже приводили к тому, что один переключал ветку под работой другого. Владелец фронтенда — только это задание. + +## База + +``` +репозиторий: /srv/projects/Agent projects/hermes-hub (уже на 80aab00) +макеты: /srv/projects/Agent projects/Разное/фронтенд +общая память: /srv/projects/AI-Memory (см. корневой AGENTS.md) +живой хаб: http://127.0.0.1:8080 +``` + +``` +git fetch origin --prune +git checkout -b codex/a48-interface-by-mockup origin/main +``` + +В `main` напрямую не пушить. + +## Порядок + +Codex работает одним исполнителем, поэтому второго прохода внутри задания нет. Вместо него — **самопроверка по пункту P0-6** и приёмка ревьюером. Пункты, помеченные «приложить», — это то, по чему работу будут принимать. + +Перед началом прочитать общую память по правилам корневого `AGENTS.md`: протокол, состояние и задачи проекта. После работы обновить их. + +--- + +## Почему это задание существует + +Задание A43 объявили выполненным. Владелец поставил сборку на две машины и написал: «интерфейс вообще не изменился, какой был, такой и остался. Зачем тогда было задание на изменение по макетам?» + +Он прав. Вот что изменил A43: + +``` +app.js +297 шесть карточек показателей, обвязка холста +workflow.js +136 панорамирование, зум колесом +index.html +8 +workflow.css 15 снят потолок высоты 430 px +style.css НЕ ОТКРЫВАЛСЯ НИ РАЗУ +``` + +`style.css` — это и есть внешний вид. Привести экраны к макетам, не тронув его, нельзя. + +Работу приняли по зелёным тестам. **Тесты внешний вид не видят.** Отсюда главное требование этого задания — проверка глазами, см. P0-3. + +**Холст переделывать не нужно.** Панорамирование, зум колесом и снятый потолок высоты работают и остаются. + +--- + +## P0-1. Первоисточник — текстовые ТЗ, а не только картинки + +Рядом с макетами лежат два документа, и в них требования подробнее, чем видно на изображении: + +``` +Разное/фронтенд/1.txt ТЗ по главному экрану «Обзор»: рабочее пространство + агентной системы, визуальные workflow, Agent Files, + LIVE-мониторинг +Разное/фронтенд/3.txt ТЗ по вкладке «Маршрутизация» +``` + +Из `3.txt` важное разграничение, которое легко нарушить: **на «Маршрутизации» настраивается очерёдность аккаунтов внутри агента; связи между агентами живут на «Обзоре».** Не смешивать. + +Прочитать оба целиком до начала работы. Расхождения между текстом и картинкой — вынести владельцу, а не решать молча. + +## P0-2. Вёрстка + +Экраны привести к макетам `1.1` … `7.1`: сетка, отступы, типографика, состояния карточек, расположение панелей, палитра. + +1. **Открыть `style.css`.** Если по итогам работы он не изменён — задание не выполнено. +2. Правки в `index.html` и `app.js` — по необходимости; клиент **без сборки, без npm, без фреймворка** (решение зафиксировано в `docs/web-api/CONTRACT.md` §1). Tailwind, React и генераторы страниц не вносить. +3. **Три темы** — светлая, средняя, тёмная — работают на каждом экране. Цвета через переменные, не литералами. + +Заметные расхождения, найденные ревьюером на экране «Обзор»: + +``` +шапка в макете поиск (Ctrl+K), уведомления, настройки, карточка + пользователя; в сборке две кнопки +логотип вензель и подпись против значка молнии +панель холста вертикальный столбец инструментов слева — отсутствует +карточки узлов в макете иконка, файл .md, строка «модель • аккаунт»; + в сборке три обрезанные строки без модели и аккаунта +инспектор в макете вкладки, конфигурация исполнения, Agent File, + инструменты, быстрые действия; в сборке пустая заглушка +нижний ряд в макете три карточки, в сборке две +подписи связей режутся карточками узлов: «ТАНОВКА ЗАД», «РАЙПРИЁМКА» +``` + +Про подписи: центрирование уже исправлено в `workflow.css`, дело **не в стиле текста**. Их перекрывают карточки узлов — лечится порядком слоёв и расстоянием между узлами в раскладке. + +## P0-3. Проверка глазами — обязательная часть работы + +Codex работает на том же сервере, где запущен хаб. Это ключевое отличие от прошлого захода: **сверять есть с чем прямо на месте.** + +1. Открыть `http://127.0.0.1:8080` и пройти все экраны. +2. **Скриншот до и после по каждому экрану**, рядом фрагмент макета. Приложить. +3. Проверить каждую тему. +4. Холст: подвигать полотно, покрутить колесо, утащить узел за край и вернуть кнопкой «вписать». +5. Подписи связей читаются на нескольких масштабах и не перекрываются. + +Отчёт без скриншотов приниматься не будет: другого способа проверить эту работу нет. + +## P0-4. Что из макета не переносить + +Макеты нарисованы с правдоподобными данными. В живой интерфейс они попасть не должны: + +``` +кольцевая диаграмма с числом 42 пример, а не измерение +«Gemini 1.5 Flash • acc-02» подпись примера +версия v2.9.0 в проекте 0.1.1, заморожена намеренно +«94.2%», «+20% к вчера» выдуманные показатели +``` + +Правило проекта: **число появляется только после измерения.** Нет данных под элемент — `Н/Д` с причиной. Загрузка и отсутствие пишутся разными словами: «список ещё не получен» и «моделей нет» — разное. + +Модель и аккаунт для карточки узла **в снапшоте есть** — брать оттуда. + +Элемент, которому нечего обслуживать (кнопки несуществующих приложений экосистемы внизу макета), не рисовать и **назвать пропущенным** в отчёте. + +## P0-5. Данные берутся из снапшота + +Единственный источник — `GET /api/snapshot`. Это `dataclasses.asdict(HubSnapshot)`, имена полей ровно как в датаклассе: + +``` +all_profiles профили; ключа "profiles" НЕ существует +providers сводки провайдеров, у них discovered_models +routing, agents, workflow, readiness, quotas, metrics +``` + +Перед чтением поля перечислить поля датакласса. Обращение к несуществующему ключу молча даёт пустоту: именно так экран маршрутизации показывал «0 аккаунтов» при шести подключённых. + +Список моделей провайдера — `discovered_models` **у провайдера**. У профиля `preferred_models` — это настройки владельца, и `model_states` строится из них же. + +## P0-6. Самопроверка перед сдачей + +Пройти по списку и приложить результат: + +1. `git diff --stat` — есть ли в списке `style.css`. +2. `python -m pytest -q` — сравнить с базой, на `origin/main` сейчас **496 passed**. +3. `python -m ruff check .` +4. `PYTHONPATH=src python scripts/verify_multi_provider_router.py` +5. Скриншоты собраны по всем экранам и всем темам. +6. Поиск по клиенту: не осталось ли зашитых чисел и процентов. +7. Пункт, который не сделан, **назван пропущенным**. + +--- + +## Ограничения + +- Без сборки, без npm, без фреймворка. +- Python не трогать: провайдеры и квоты — задание A42. +- Холст A43 не переделывать, только доводить. +- Учётные данные и `~/.hermes/agy_profiles/` не трогать. +- Службы `qwen-coder` и `qwen-compressor` не трогать: они только что восстановлены после того, как их подменили заглушкой. +- Версию `0.1.1` не поднимать. +- Правило честности без исключений. + +## Критерии приёмки + +1. Ветка в `origin`, `git status` чист. +2. `style.css` изменён; вёрстка приведена к макетам. +3. Оба текстовых ТЗ прочитаны; разграничение из `3.txt` соблюдено — очерёдность аккаунтов на «Маршрутизации», связи агентов на «Обзоре». +4. По каждому экрану приложены скриншоты до и после рядом с фрагментом макета. +5. Пройдены все макеты `1.1` … `7.1`. +6. Инспектор реализован по макету; отсутствующие данные показаны как `Н/Д` с причиной. +7. Карточки узлов показывают модель и аккаунт из снапшота. +8. Подписи связей не перекрываются карточками; проверено на нескольких масштабах. +9. Ни одного числа из макета в живом интерфейсе. +10. Три темы работают на всех экранах. +11. Холст не сломан: панорамирование, зум, «вписать». +12. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше 496. +13. Память проекта в AI-Memory обновлена: состояние, задачи, worklog. +14. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. + +## Главное + +Владелец ждал сборку, поставил её на две машины и увидел прежний интерфейс. Холст стал лучше — но это один экран из семи, а вёрстку не начинали. + +У этого задания есть преимущество, которого не было у прошлого: исполнитель сидит на том же сервере, где работает хаб, и может открыть его и сравнить с макетом сам. Поэтому сдача — скриншоты, а не описание сделанного. + +## Порядок сдачи +Передать точный `FINAL_COMMIT_SHA`. \ No newline at end of file diff --git a/docs/reports/A48.md b/docs/reports/A48.md new file mode 100644 index 0000000..9a6abbb --- /dev/null +++ b/docs/reports/A48.md @@ -0,0 +1,59 @@ +# A48 — промежуточный отчёт, НЕ ГОТОВО К ПРИЁМКЕ + +Дата: 2026-08-31. Исполнитель: Codex, один исполнитель, без субагентов. + +## Контрольные точки + +- START_HEAD: `80aab00ee2bef353e12d128bd8ba6a6dde503abd`. +- origin/main перед началом: `80aab00ee2bef353e12d128bd8ba6a6dde503abd`. +- Ветка: `codex/a48-interface-by-mockup`, отдельный worktree `hermes-hub-a48`. +- FINAL_HEAD / FINAL_COMMIT_SHA: **ещё не определён — визуальная приёмка не завершена**. SHA промежуточного коммита передаётся в сообщении исполнителя. +- Главный checkout и незакоммиченная `.agents/` сохранены; ветка A47 не переключалась. +- Живой хаб фактически слушает порт 5800, сообщает сборку `81a58f6`. На 8080 работает другое приложение; оно не изменялось. +- Предпросмотр клиента A48: loopback 5801, защищённый API пересылается в существующий хаб без добавления авторизации и без изменения служб. Для другого порта браузеру требуется отдельный вход владельца. + +## Что изменено в клиенте + +- `style.css`: общая сетка семи страниц, навигация, типографика, состояния карточек, отдельные цвета поверхностей/обрамления для трёх тем, адаптивность. +- Утверждённый логотип из существующих assets; SVG-значки меню, поиск по экранам/агентам/аккаунтам с Ctrl+K, переходы к событиям и настройкам. Вместо вымышленного Administrator указано отсутствие профиля пользователя в API. +- Обзор: столбец инструментов, модель и аккаунт на узле, автоматический первоначальный выбор агента, сводка инспектора и переходы к существующему редактору Agent File. Три нижние карточки; кольцевая статистика не выдумана. +- Сохранены механизмы панорамирования и масштабирования A43. Подписи связей выделены в отдельный SVG-слой; размещение учитывает прямоугольники узлов и других подписей. Добавлено разнесение узлов как явно сохраняемый черновик. +- Маршрутизация читает `RolePipeline.nodes` вместо отсутствующего `preferred_chain`; порядок сохраняется существующим `save_chain`. Фильтры провайдеров/состояний, поиск, выбор модели, кнопочное добавление и удаление профиля из цепочки. Связи агентов остаются на Обзоре. +- Списки моделей — `ProviderSummary.discovered_models`. Настроенная, но не обнаруженная модель отмечается неподтверждённой. «Список ещё не получен» и «доступных моделей нет» различаются по времени обновления провайдера. +- Аналитика исправлена на `telemetry.by_provider` / `by_role`. Состояние — на `metrics.host`. Нулевые измерения не заменяются отсутствием данных. +- Настройки сгруппированы; не полученные настройки не выдаются за текущие значения. Сохраняются только явно выбранные изменения. Поля, не имеющие источника/обработчика в этом потоке, помечены Н/Д. +- Журнал показывает события workflow из снапшота (не более 60). Это **не полный журнал сервера**: при требовании единственного источника `/api/snapshot` более широкий журнал недоступен. Детали события и фильтры предусмотрены. + +## Источники проверены до изменения чтения + +HubSnapshot: generation, seq, timestamp, profiles_by_provider, all_profiles, readiness, agents, providers, routing, quotas, metrics, is_stale, workflow. + +Прочитаны определения ProfileViewModel, ProviderSummary, RolePipeline, SystemReadiness, HostMetricsSnapshot, TelemetryAggregates, WorkflowEvent и реализация WorkflowService.snapshot. Текстовые ТЗ `1.txt` и `3.txt` прочитаны полностью. Все изображения `1.1`–`7.1` просмотрены. + +## Проверки + +- База origin/main: **495 passed / 1 skipped / 0 failed**, 4 deselected. +- Текущий клиент: **495 passed / 1 skipped / 0 failed**, 4 deselected. В A48 указано 496 passed, но это не воспроизводится даже на исходной базе; Python и тестовые маркеры не изменены. +- `python -m ruff check .`: чисто. +- `PYTHONPATH=src python scripts/verify_multi_provider_router.py`: **10/10**. +- `scripts/release_gate.py`: **PASSED**. Сам скрипт содержит 7 групп проверок; 10/10 относится к отдельному router verifier. +- `node tests/test_workspace_a48.js`: прошёл (модели, отсутствие/нулевая квота, host metrics, telemetry keys, экранирование). +- `node tests/test_web_handlers_dom_contract.js`: прошёл. +- `node --check` для трёх файлов клиента и `git diff --check`: чисто. +- Первый промежуточный запуск pytest дал 1 сбой: новый стартовый обработчик вызывался из файла, который тест загружает отдельно. Инициализация перенесена в собственный JS-файл; повторный тест прошёл. +- Поиск демонстрационных чисел/версий/моделей: совпадения только с геометрией кривой (0.42) и настройкой порога (20%), не со статистикой. + +## Визуальные доказательства и пропуски + +[Галерея макет / до / промежуточная вёрстка](../screenshots/a48/index.html). + +- Собраны **21 исходный снимок**: 7 экранов × 3 темы, авторизованный живой хаб. +- Собраны 21 снимок `layout-only` без входа для проверки базовой сетки/тем. Они НЕ заменяют требуемые скриншоты после с реальными данными; часть последних мелких CSS-правок требует повторной съёмки. +- **ПРОПУЩЕНО / ожидает входа:** 21 авторизованный снимок после, инспектор на живом снапшоте, панорамирование/зум/узел за край/вписать, читаемость подписей на нескольких масштабах, проверка действий маршрутизации и выбора модели с подключёнными аккаунтами, повторный полный визуальный проход. +- **ПРОПУЩЕНО намеренно:** кнопки несуществующих приложений экосистемы, выдуманные графики/рост процентов/кольцо 42, версия v2.9.0, неподдерживаемые настройки уведомлений/backup/2FA, история температур и сетевых замеров без источника, вымышленный профиль Administrator. +- Отличия от макета: используется существующий утверждённый растровый логотип с кремовой подложкой, а не генерация нового вензеля; нет фиктивных аккаунтов и назначений. Точные плотность и отступы окончательно не приняты. +- Ограничение backend: `set_model` меняет предпочтение профиля, общее для его использования в разных ролях. Независимые модели на каждую пару роль/аккаунт нельзя честно обещать без отдельного изменения backend. Python в A48 не менялся. + +## Продолжение + +После входа владельца на 5801: перезагрузить клиент, проверить консоль и DOM, исправить найденные дефекты, снять авторизованные после для всех тем, пройти холст, обновить галерею и отчёт. Только затем назначить FINAL_COMMIT_SHA и пометить A48 выполненным. diff --git a/docs/reports/a48-baseline-tests.txt b/docs/reports/a48-baseline-tests.txt new file mode 100644 index 0000000..758f032 --- /dev/null +++ b/docs/reports/a48-baseline-tests.txt @@ -0,0 +1,32 @@ +........................................................................ [ 14%] +........................................................................ [ 29%] +........................................................................ [ 43%] +........................................................................ [ 58%] +...s.................................................................... [ 72%] +........................................................................ [ 87%] +................................................................ [100%] +=============================== warnings summary =============================== +src/antigravity_provider/router/web/server.py:437 + /srv/projects/Agent projects/hermes-hub-a48/src/antigravity_provider/router/web/server.py:437: DeprecationWarning: + on_event is deprecated, use lifespan event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). + + @app.on_event("startup") + +../hermes-hub/.venv/lib/python3.11/site-packages/fastapi/applications.py:4681 + /srv/projects/Agent projects/hermes-hub/.venv/lib/python3.11/site-packages/fastapi/applications.py:4681: DeprecationWarning: + on_event is deprecated, use lifespan event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). + + return self.router.on_event(event_type) # ty: ignore[deprecated] + +../hermes-hub/.venv/lib/python3.11/site-packages/fastapi/testclient.py:1 + /srv/projects/Agent projects/hermes-hub/.venv/lib/python3.11/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead. + from starlette.testclient import TestClient as TestClient # noqa + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +495 passed, 1 skipped, 4 deselected, 3 warnings in 22.69s diff --git a/docs/reports/a48-release-gate.txt b/docs/reports/a48-release-gate.txt new file mode 100644 index 0000000..f8ae535 --- /dev/null +++ b/docs/reports/a48-release-gate.txt @@ -0,0 +1,28 @@ +====================================================================== + Hermes Hub — Release Gate Verification Suite (Target: v0.1.1) +====================================================================== + +Running 1. Version Consistency ([UNIT VERIFIED])... + [UNIT VERIFIED] Version 0.1.1 is consistent across all manifests + +Running 2. P0 Release Blockers (16/16) ([UNIT VERIFIED])... + [UNIT VERIFIED] 16/16 P0 release blockers & regression checks verified + +Running 3. Auto-Updater & Rollback ([INTEGRATION VERIFIED])... + [INTEGRATION VERIFIED] Auto-updater, SHA-256 verification, and rollback verified + +Running 4. Full Offline Pytest Suite ([INTEGRATION VERIFIED])... + [INTEGRATION VERIFIED] All unit and integration tests passed offline + +Running 5. Zero Hardcoded Developer Paths ([STATIC VERIFIED])... + [STATIC VERIFIED] Zero hardcoded developer paths in src/ + +Running 6. Zero Credentials & AST Secret Scan ([SECURITY VERIFIED])... + [SECURITY VERIFIED] Zero secret files, live tokens, or obfuscated secret assignments in src/ + +Running 7. Public Production Update Feed ([LIVE STATUS])... + [LIVE STATUS] [MANIFEST_LIVE=True, PACKAGE_LIVE=True, PACKAGE_HASH_VERIFIED=True] Manifest live (vbuild-2026.08.31) and release asset verified at https://github.com/ochenstarik-ui/hermes-hub/releases/download/build-2026.08.31/checksums.txt + +====================================================================== + [RELEASE GATE: PASSED] All criteria verified. Ready for Candidate v0.1.1 +====================================================================== diff --git a/docs/reports/a48-router.txt b/docs/reports/a48-router.txt new file mode 100644 index 0000000..fb1c750 --- /dev/null +++ b/docs/reports/a48-router.txt @@ -0,0 +1,28 @@ +Router failover for role 'manager': switched from failed profile 'synth-codex' to 'synth-ag' +====================================================================== +HERMES MULTI-PROVIDER ACCOUNT ROUTER: AUTOMATED VERIFICATION +====================================================================== +1. Checking profile inventory and provider counts... + [PASS] Чистая конфигурация по умолчанию (0 профилей, добавление по мере подключения) +2. Checking role fallback policies... + [INFO] Роли с пустыми цепочками (чистый старт / не назначены): analyst, code-reviewer, cost-controller, dependency-agent, developer-1, developer-2, guardian, integration-expert, manager, researcher, security-expert, tech-writer, tester + [PASS] Все 13 ролей валидны и ссылаются только на существующие профили +3. Checking model family extraction... + [PASS] Model family parsing correct +4. Checking health states and simulated quota... + [PASS] Quota simulation and recovery verified +5. Checking session affinity engine... + [PASS] Session affinity tracking & update verified +6. Checking concurrency lease limits... + [PASS] Concurrency leases correctly enforced +7. Checking Antigravity profile environment directory isolation... + [PASS] Profile directory isolated at /home/ochenstarik/.hermes/agy_profiles/ag-w2 +8. Checking provider error classification... + [PASS] Error classifications for all 3 providers verified +9. Checking full failover execution loop... + [PASS] Отказоустойчивость прошла цепочку synth-codex -> synth-ag +10. Checking disabled router passthrough... + [PASS] Router clean bypass mode verified +---------------------------------------------------------------------- +VERIFICATION COMPLETE: 10/10 CHECKS PASSED (0 errors, 0 warnings) +====================================================================== diff --git a/docs/reports/a48-tests.txt b/docs/reports/a48-tests.txt new file mode 100644 index 0000000..9edca6e --- /dev/null +++ b/docs/reports/a48-tests.txt @@ -0,0 +1,32 @@ +........................................................................ [ 14%] +........................................................................ [ 29%] +........................................................................ [ 43%] +........................................................................ [ 58%] +...s.................................................................... [ 72%] +........................................................................ [ 87%] +................................................................ [100%] +=============================== warnings summary =============================== +src/antigravity_provider/router/web/server.py:437 + /srv/projects/Agent projects/hermes-hub-a48/src/antigravity_provider/router/web/server.py:437: DeprecationWarning: + on_event is deprecated, use lifespan event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). + + @app.on_event("startup") + +../hermes-hub/.venv/lib/python3.11/site-packages/fastapi/applications.py:4681 + /srv/projects/Agent projects/hermes-hub/.venv/lib/python3.11/site-packages/fastapi/applications.py:4681: DeprecationWarning: + on_event is deprecated, use lifespan event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). + + return self.router.on_event(event_type) # ty: ignore[deprecated] + +../hermes-hub/.venv/lib/python3.11/site-packages/fastapi/testclient.py:1 + /srv/projects/Agent projects/hermes-hub/.venv/lib/python3.11/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead. + from starlette.testclient import TestClient as TestClient # noqa + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +495 passed, 1 skipped, 4 deselected, 3 warnings in 21.28s diff --git a/docs/screenshots/a48/before/accounts-dark.png b/docs/screenshots/a48/before/accounts-dark.png new file mode 100644 index 0000000..61ad1cb Binary files /dev/null and b/docs/screenshots/a48/before/accounts-dark.png differ diff --git a/docs/screenshots/a48/before/accounts-light.png b/docs/screenshots/a48/before/accounts-light.png new file mode 100644 index 0000000..e418df0 Binary files /dev/null and b/docs/screenshots/a48/before/accounts-light.png differ diff --git a/docs/screenshots/a48/before/accounts-medium.png b/docs/screenshots/a48/before/accounts-medium.png new file mode 100644 index 0000000..51ed639 Binary files /dev/null and b/docs/screenshots/a48/before/accounts-medium.png differ diff --git a/docs/screenshots/a48/before/analytics-dark.png b/docs/screenshots/a48/before/analytics-dark.png new file mode 100644 index 0000000..fb2d18b Binary files /dev/null and b/docs/screenshots/a48/before/analytics-dark.png differ diff --git a/docs/screenshots/a48/before/analytics-light.png b/docs/screenshots/a48/before/analytics-light.png new file mode 100644 index 0000000..3f46455 Binary files /dev/null and b/docs/screenshots/a48/before/analytics-light.png differ diff --git a/docs/screenshots/a48/before/analytics-medium.png b/docs/screenshots/a48/before/analytics-medium.png new file mode 100644 index 0000000..1dad46a Binary files /dev/null and b/docs/screenshots/a48/before/analytics-medium.png differ diff --git a/docs/screenshots/a48/before/health-dark.png b/docs/screenshots/a48/before/health-dark.png new file mode 100644 index 0000000..7eeb582 Binary files /dev/null and b/docs/screenshots/a48/before/health-dark.png differ diff --git a/docs/screenshots/a48/before/health-light.png b/docs/screenshots/a48/before/health-light.png new file mode 100644 index 0000000..5a7514d Binary files /dev/null and b/docs/screenshots/a48/before/health-light.png differ diff --git a/docs/screenshots/a48/before/health-medium.png b/docs/screenshots/a48/before/health-medium.png new file mode 100644 index 0000000..9b2d4ab Binary files /dev/null and b/docs/screenshots/a48/before/health-medium.png differ diff --git a/docs/screenshots/a48/before/logs-dark.png b/docs/screenshots/a48/before/logs-dark.png new file mode 100644 index 0000000..911def7 Binary files /dev/null and b/docs/screenshots/a48/before/logs-dark.png differ diff --git a/docs/screenshots/a48/before/logs-light.png b/docs/screenshots/a48/before/logs-light.png new file mode 100644 index 0000000..9e732ca Binary files /dev/null and b/docs/screenshots/a48/before/logs-light.png differ diff --git a/docs/screenshots/a48/before/logs-medium.png b/docs/screenshots/a48/before/logs-medium.png new file mode 100644 index 0000000..fd5ad6a Binary files /dev/null and b/docs/screenshots/a48/before/logs-medium.png differ diff --git a/docs/screenshots/a48/before/overview-dark.png b/docs/screenshots/a48/before/overview-dark.png new file mode 100644 index 0000000..a616d78 Binary files /dev/null and b/docs/screenshots/a48/before/overview-dark.png differ diff --git a/docs/screenshots/a48/before/overview-light.png b/docs/screenshots/a48/before/overview-light.png new file mode 100644 index 0000000..b975c50 Binary files /dev/null and b/docs/screenshots/a48/before/overview-light.png differ diff --git a/docs/screenshots/a48/before/overview-medium.png b/docs/screenshots/a48/before/overview-medium.png new file mode 100644 index 0000000..b0fc704 Binary files /dev/null and b/docs/screenshots/a48/before/overview-medium.png differ diff --git a/docs/screenshots/a48/before/routing-dark.png b/docs/screenshots/a48/before/routing-dark.png new file mode 100644 index 0000000..f8982da Binary files /dev/null and b/docs/screenshots/a48/before/routing-dark.png differ diff --git a/docs/screenshots/a48/before/routing-light.png b/docs/screenshots/a48/before/routing-light.png new file mode 100644 index 0000000..7fbd62a Binary files /dev/null and b/docs/screenshots/a48/before/routing-light.png differ diff --git a/docs/screenshots/a48/before/routing-medium.png b/docs/screenshots/a48/before/routing-medium.png new file mode 100644 index 0000000..3d4b2cb Binary files /dev/null and b/docs/screenshots/a48/before/routing-medium.png differ diff --git a/docs/screenshots/a48/before/settings-dark.png b/docs/screenshots/a48/before/settings-dark.png new file mode 100644 index 0000000..7f182bc Binary files /dev/null and b/docs/screenshots/a48/before/settings-dark.png differ diff --git a/docs/screenshots/a48/before/settings-light.png b/docs/screenshots/a48/before/settings-light.png new file mode 100644 index 0000000..600a1b7 Binary files /dev/null and b/docs/screenshots/a48/before/settings-light.png differ diff --git a/docs/screenshots/a48/before/settings-medium.png b/docs/screenshots/a48/before/settings-medium.png new file mode 100644 index 0000000..d7ed670 Binary files /dev/null and b/docs/screenshots/a48/before/settings-medium.png differ diff --git a/docs/screenshots/a48/index.html b/docs/screenshots/a48/index.html new file mode 100644 index 0000000..9dfb91c --- /dev/null +++ b/docs/screenshots/a48/index.html @@ -0,0 +1,4 @@ +A48 — визуальная проверка, НЕ ПРИНЯТО + +

A48 · Сравнение с макетами

Промежуточный материал. A48 не принято. «До»: живой хаб, сборка 81a58f6, 21 снимок. Справа: только проверка вёрстки без авторизованных данных, НЕ приёмочные скриншоты «после». Полный проход инспектора, холста и тем после входа ещё не выполнен.

База кода: 80aab00. Контрольная ширина снимков: 1280 px. Макеты имеют разные исходные размеры; изображения показаны полностью, без подмены данных.

+ diff --git a/docs/screenshots/a48/layout-only/accounts-dark.png b/docs/screenshots/a48/layout-only/accounts-dark.png new file mode 100644 index 0000000..917bc57 Binary files /dev/null and b/docs/screenshots/a48/layout-only/accounts-dark.png differ diff --git a/docs/screenshots/a48/layout-only/accounts-light.png b/docs/screenshots/a48/layout-only/accounts-light.png new file mode 100644 index 0000000..83db60b Binary files /dev/null and b/docs/screenshots/a48/layout-only/accounts-light.png differ diff --git a/docs/screenshots/a48/layout-only/accounts-medium.png b/docs/screenshots/a48/layout-only/accounts-medium.png new file mode 100644 index 0000000..1de2a94 Binary files /dev/null and b/docs/screenshots/a48/layout-only/accounts-medium.png differ diff --git a/docs/screenshots/a48/layout-only/analytics-dark.png b/docs/screenshots/a48/layout-only/analytics-dark.png new file mode 100644 index 0000000..98bd40c Binary files /dev/null and b/docs/screenshots/a48/layout-only/analytics-dark.png differ diff --git a/docs/screenshots/a48/layout-only/analytics-light.png b/docs/screenshots/a48/layout-only/analytics-light.png new file mode 100644 index 0000000..d97c4cd Binary files /dev/null and b/docs/screenshots/a48/layout-only/analytics-light.png differ diff --git a/docs/screenshots/a48/layout-only/analytics-medium.png b/docs/screenshots/a48/layout-only/analytics-medium.png new file mode 100644 index 0000000..7fc358f Binary files /dev/null and b/docs/screenshots/a48/layout-only/analytics-medium.png differ diff --git a/docs/screenshots/a48/layout-only/health-dark.png b/docs/screenshots/a48/layout-only/health-dark.png new file mode 100644 index 0000000..0066414 Binary files /dev/null and b/docs/screenshots/a48/layout-only/health-dark.png differ diff --git a/docs/screenshots/a48/layout-only/health-light.png b/docs/screenshots/a48/layout-only/health-light.png new file mode 100644 index 0000000..a1008e8 Binary files /dev/null and b/docs/screenshots/a48/layout-only/health-light.png differ diff --git a/docs/screenshots/a48/layout-only/health-medium.png b/docs/screenshots/a48/layout-only/health-medium.png new file mode 100644 index 0000000..cf5a0ac Binary files /dev/null and b/docs/screenshots/a48/layout-only/health-medium.png differ diff --git a/docs/screenshots/a48/layout-only/logs-dark.png b/docs/screenshots/a48/layout-only/logs-dark.png new file mode 100644 index 0000000..175cb79 Binary files /dev/null and b/docs/screenshots/a48/layout-only/logs-dark.png differ diff --git a/docs/screenshots/a48/layout-only/logs-light.png b/docs/screenshots/a48/layout-only/logs-light.png new file mode 100644 index 0000000..45cbf87 Binary files /dev/null and b/docs/screenshots/a48/layout-only/logs-light.png differ diff --git a/docs/screenshots/a48/layout-only/logs-medium.png b/docs/screenshots/a48/layout-only/logs-medium.png new file mode 100644 index 0000000..2ebf5f6 Binary files /dev/null and b/docs/screenshots/a48/layout-only/logs-medium.png differ diff --git a/docs/screenshots/a48/layout-only/overview-dark.png b/docs/screenshots/a48/layout-only/overview-dark.png new file mode 100644 index 0000000..f77d65d Binary files /dev/null and b/docs/screenshots/a48/layout-only/overview-dark.png differ diff --git a/docs/screenshots/a48/layout-only/overview-light.png b/docs/screenshots/a48/layout-only/overview-light.png new file mode 100644 index 0000000..3754220 Binary files /dev/null and b/docs/screenshots/a48/layout-only/overview-light.png differ diff --git a/docs/screenshots/a48/layout-only/overview-medium.png b/docs/screenshots/a48/layout-only/overview-medium.png new file mode 100644 index 0000000..3a2703a Binary files /dev/null and b/docs/screenshots/a48/layout-only/overview-medium.png differ diff --git a/docs/screenshots/a48/layout-only/routing-dark.png b/docs/screenshots/a48/layout-only/routing-dark.png new file mode 100644 index 0000000..13de6ac Binary files /dev/null and b/docs/screenshots/a48/layout-only/routing-dark.png differ diff --git a/docs/screenshots/a48/layout-only/routing-light.png b/docs/screenshots/a48/layout-only/routing-light.png new file mode 100644 index 0000000..2881287 Binary files /dev/null and b/docs/screenshots/a48/layout-only/routing-light.png differ diff --git a/docs/screenshots/a48/layout-only/routing-medium.png b/docs/screenshots/a48/layout-only/routing-medium.png new file mode 100644 index 0000000..d294d10 Binary files /dev/null and b/docs/screenshots/a48/layout-only/routing-medium.png differ diff --git a/docs/screenshots/a48/layout-only/settings-dark.png b/docs/screenshots/a48/layout-only/settings-dark.png new file mode 100644 index 0000000..a6d5602 Binary files /dev/null and b/docs/screenshots/a48/layout-only/settings-dark.png differ diff --git a/docs/screenshots/a48/layout-only/settings-light.png b/docs/screenshots/a48/layout-only/settings-light.png new file mode 100644 index 0000000..9e50418 Binary files /dev/null and b/docs/screenshots/a48/layout-only/settings-light.png differ diff --git a/docs/screenshots/a48/layout-only/settings-medium.png b/docs/screenshots/a48/layout-only/settings-medium.png new file mode 100644 index 0000000..f07c560 Binary files /dev/null and b/docs/screenshots/a48/layout-only/settings-medium.png differ diff --git a/docs/screenshots/a48/reference/1.1.png b/docs/screenshots/a48/reference/1.1.png new file mode 100644 index 0000000..d18eb5b Binary files /dev/null and b/docs/screenshots/a48/reference/1.1.png differ diff --git a/docs/screenshots/a48/reference/2.1.png b/docs/screenshots/a48/reference/2.1.png new file mode 100644 index 0000000..051dd5c Binary files /dev/null and b/docs/screenshots/a48/reference/2.1.png differ diff --git a/docs/screenshots/a48/reference/3.1.png b/docs/screenshots/a48/reference/3.1.png new file mode 100644 index 0000000..4b71ed5 Binary files /dev/null and b/docs/screenshots/a48/reference/3.1.png differ diff --git a/docs/screenshots/a48/reference/4.1.png b/docs/screenshots/a48/reference/4.1.png new file mode 100644 index 0000000..5121f28 Binary files /dev/null and b/docs/screenshots/a48/reference/4.1.png differ diff --git a/docs/screenshots/a48/reference/5.1.png b/docs/screenshots/a48/reference/5.1.png new file mode 100644 index 0000000..6b39bb3 Binary files /dev/null and b/docs/screenshots/a48/reference/5.1.png differ diff --git a/docs/screenshots/a48/reference/6.1.png b/docs/screenshots/a48/reference/6.1.png new file mode 100644 index 0000000..6ef9150 Binary files /dev/null and b/docs/screenshots/a48/reference/6.1.png differ diff --git a/docs/screenshots/a48/reference/7.1.png b/docs/screenshots/a48/reference/7.1.png new file mode 100644 index 0000000..68e478f Binary files /dev/null and b/docs/screenshots/a48/reference/7.1.png differ diff --git a/src/antigravity_provider/router/web/static/app.js b/src/antigravity_provider/router/web/static/app.js index 87b6896..96189f5 100644 --- a/src/antigravity_provider/router/web/static/app.js +++ b/src/antigravity_provider/router/web/static/app.js @@ -88,6 +88,7 @@ function initNavigation() { function switchView(viewName) { activeView = viewName; + document.body.dataset.view = viewName; document.querySelectorAll('.nav-item').forEach((btn) => { btn.classList.toggle('active', btn.dataset.view === viewName); }); @@ -98,9 +99,9 @@ function switchView(viewName) { const titles = { overview: 'Обзор системы', accounts: 'Аккаунты и квоты', - routing: 'Главный экран управления маршрутизацией', + routing: 'Маршрутизация', analytics: 'Аналитика и телеметрия', - health: 'Состояние и диагностика', + health: 'Состояние системы', logs: 'Журнал событий', settings: 'Настройки Hermes Hub', }; @@ -533,6 +534,7 @@ function updateGlobalHeader() { if (!currentSnapshot) return; const readiness = currentSnapshot.readiness || {}; + renderAccountSummary(currentSnapshot); const allProfiles = Object.values(currentSnapshot.all_profiles || {}); const connectedAccounts = readiness.accounts_connected_count ?? allProfiles.filter( (p) => isConnectedProfile(p) @@ -725,7 +727,7 @@ function renderAccountCard(profile) { const roles = (profile.assigned_roles || []).join(', ') || 'Роль: Н/Д'; const identity = profile.email || profile.account_identity || profile.display_name || profile.profile_id; const healthState = profile.health_state || 'unknown'; - const healthLabel = profile.health_label_ru || (profile.enabled ? 'Работает' : 'Отключён'); + const healthLabel = profile.health_label_ru || 'Н/Д: состояние не проверялось'; const plan = profile.plan_code && profile.plan_code !== 'UNKNOWN' ? profile.plan_code : ''; const quotaSnap = profile.quota_snapshot || (currentSnapshot.quotas || {})[profile.profile_id]; @@ -770,7 +772,7 @@ function renderAccountCard(profile) {