Тринадцать файлов существовали только на диске ПК владельца, в рабочей копии, отставшей от origin/main на 122 коммита. Их реализация и тесты давно влиты: tests/test_a42_provider_connect.py, test_a49_subagents_skills_memory.py, test_a51_hub_controls_hermes.py, test_a52_local_models_supervisor_dual.py, test_a55_account_connection.py, test_a56_context_compression.py и другие. Постановок, объясняющих, что эти тесты обязаны доказывать, в репозитории не было. Правило записано в agents/AGENTS.md: задание живёт в репозитории, а не в переписке и не в личных папках на диске. A48, A50 и A54 не переносятся: они уже есть на origin под другими именами, содержимое совпадает с точностью до перевода строки в конце файла. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
130 lines
12 KiB
Markdown
130 lines
12 KiB
Markdown
# Задание 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`.
|