# Задание A43: интерфейс по макетам и работающий холст ## Дата поступления 2026-08-31 ## База `origin/main` (`ff303b5`) — туда уже слиты правки ревьюера по вебу и A41 (чистая первая установка). ``` git fetch origin --prune git checkout -b antigravity/a43-frontend-canvas origin/main ``` В `main` напрямую не пушить. ## Порядок исполнения Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-5** написан для аудитора. Это задание **по интерфейсу**. Провайдеры, обнаружение моделей и квоты — задание A42, туда не залезать. Пересечение файлов: `app.js` и `workflow.js` правит только это задание; A42 работает в Python. Исполнитель работает на машине владельца (Windows), где хаб запущен и есть живой снапшот с подключёнными аккаунтами. Это принципиально: макет надо сверять с работающим интерфейсом, а не с воображаемым. --- ## Задача Владелец: «криво отрисовано», «окно интерактивно ужасно, посмотри как сделано у n8n», «вообще весь интерфейс не соответствует фронтенду, просто посмотри как отрисовано в макете». ## Что уже сделано ревьюером — не переделывать В базовой ветке уже исправлено, проверено и закоммичено: ``` app.js экран маршрутизации читал currentSnapshot.profiles — такого ключа в снапшоте нет (поле называется all_profiles). Отсюда пустая колонка аккаунтов, счётчик «0 аккаунтов» и иконки-заглушки в цепочках. app.js убрана полоса квоты с зашитым width:80%, одинаковая у всех аккаунтов workflow.css подписи связей центрируются (не было text-anchor) и получили обводку workflow.js список моделей берётся из discovered_models провайдера, а не из preferred_models профиля; настроенная модель всегда есть в списке ``` Последнее чинило скрытую подмену: если модели агента не было в списке, ни один вариант не выбирался, показывался первый, и сохранение записывало агенту не ту модель. ## Про генераторы интерфейса Владелец спрашивал про `github.com/abi/screenshot-to-code`. Ревьюер проверил и **не рекомендует**: инструмент выдаёт самостоятельную страницу на Tailwind без данных, а клиент здесь без сборки и без npm, всё держится на привязке к `/api/snapshot` (решение зафиксировано в `docs/web-api/CONTRACT.md` §1). Переподключать сгенерированную страницу к снапшоту, действиям и опросу состояния дороже, чем сверстать по макету. Опираться на макеты из `Desktop/фронтенд/` напрямую. --- ## P0-1. Холст ведёт себя как холст Сейчас `workflow.css:28` задаёт `.workflow-canvas` фиксированную высоту 430 px и `overflow:hidden`, а обработчики мыши висят только на узлах и портах (`workflow.js:171`). Колесо не обрабатывается, полотно не двигается. Всё, что выехало за 430 px, недостижимо — узел не вернуть, связь не увидеть. Требуется поведение, привычное по n8n: 1. **Панорамирование полотна** — перетаскиванием пустого места и средней кнопкой. 2. **Масштаб колесом** с курсором как центром, а не только кнопками. 3. **Холст тянется по высоте окна**, а не заперт в 430 px. 4. **Вписать в экран** — кнопка уже есть (`fitWorkflowGraph`), она должна учитывать панорамирование. 5. **Узел нельзя утащить в недосягаемость**: либо границы, либо «вписать» всегда возвращает всё в поле зрения. Связи и узлы считаются в одной системе координат — это ревьюер проверил, ошибки там нет. При добавлении панорамирования **сохранить это свойство**: смещение обязано применяться к обоим слоям одинаково, иначе связи отклеятся от узлов. ## P0-2. Экраны соответствуют макетам Пройти по макетам из `Desktop/фронтенд/` и привести экраны в соответствие: сетка, отступы, типографика, состояния карточек, расположение панелей. 1. **Расхождения перечислить списком** до начала работы — что именно не совпадает на каждом экране. Список приложить к отчёту. 2. **Скриншот до и после** по каждому экрану. Это единственный способ показать владельцу результат: он сравнивает глазами. 3. **Три темы остаются рабочими** — светлая, средняя, тёмная. Средняя была реализована в стилях, но отсутствовала в списке выбора; проверить, что все три переключаются. 4. **Ничего не ломать в данных.** Экран берёт данные из снапшота; если макет требует поля, которого в снапшоте нет, — показать `Н/Д` с причиной и назвать это в отчёте, а не придумать значение. ## P0-3. Пустые состояния и честность 1. **Пустое — это пустое, а не ошибка.** Нет подключённых аккаунтов — экран говорит об этом и предлагает подключить, а не показывает ноль как поломку. 2. **Загрузка отличается от отсутствия.** «Список моделей ещё не получен» и «моделей нет» — разные сообщения. 3. **Ни одного зашитого числа в интерфейсе.** Полоса с `width:80%` уже убрана; поискать оставшиеся такие же. Любой процент, столбик или счётчик обязан приходить из снапшота. ## P0-4. Проверка исполнением Прогнать тесты недостаточно — дефекты этого задания видны только глазами. 1. **Открыть хаб** и пройти все экраны на живом снапшоте владельца. 2. **Холст**: подвигать полотно, покрутить колесо, утащить узел за край и вернуть кнопкой «вписать». 3. **Инспектор агента**: убедиться, что показанная модель совпадает с настроенной, а список содержит модели провайдера. 4. **Маршрутизация**: колонка аккаунтов заполнена, счётчик совпадает с числом подключённых, перетаскивание работает. 5. **Три темы** переключить и посмотреть каждый экран. ## P0-5. Аудит вторым проходом 1. **Сверить скриншоты с макетами**, а не с описанием работы. Совпадение проверяется глазами, а не отчётом исполнителя. 2. **Связи не отклеились от узлов** ни на одном масштабе и смещении — проверить на нескольких значениях. 3. **Зашитые числа** искать целенаправленно по всему клиенту. 4. **Проверить, что данные не потерялись**: экраны, которые работали, продолжают работать. 5. **Побочные изменения** объяснить. 6. **Пропущенный пункт назвать пропущенным.** --- ## Ограничения - **Без сборки, без npm, без фреймворка** — решение зафиксировано в `docs/web-api/CONTRACT.md` §1. Tailwind, React и генераторы страниц не вносить. - Python не трогать: провайдеры и квоты — задание A42. - Учётные данные и `~/.hermes/agy_profiles/` не трогать. - Версию `0.1.1` не поднимать. - Правило честности без исключений. ## Критерии приёмки 1. Ветка в `origin`, `git status` чист. 2. Холст панорамируется и масштабируется колесом; высота не заперта; связи держатся за узлы на любом масштабе и смещении — проверено. 3. Расхождения с макетами перечислены списком; по каждому экрану приложены скриншоты до и после. 4. Три темы работают на всех экранах. 5. Пустые состояния показываются как пустые, загрузка отличается от отсутствия. 6. Зашитых чисел в интерфейсе не осталось. 7. Экран маршрутизации, инспектор агента и список аккаунтов проверены на живом снапшоте. 8. `ruff check .` чисто; релизный гейт не ухудшен. 9. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На `origin/main` сейчас **491 passed**. ## Главное Владелец смотрит на готовый макет и на работающую программу и видит разные вещи. Плюс холст, из которого узел можно утащить за край и не вернуть. Задание закрывает ровно это: чтобы экран совпадал с макетом, а граф вёл себя как граф, к которому владелец привык в n8n. ## Порядок сдачи Передать точный `FINAL_COMMIT_SHA`.