# Задание 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`.