textmachine/frontend/docs/FRONTEND_SESSION_PROMPT.md

46 KiB
Raw Blame History

S0S3 ОТРАБОТАНЫ. Файл остаётся ЖИВЫМ, но не как задание, а как носитель норм зоны — на него так ссылаются S3_SESSION_PROMPT.md и frontend/README.md. Живое здесь: §«Зона и git», §3 сценарий, §4 жёсткие ограничения, §7 «как работать». Историческое: §«Область ЭТОЙ сессии» (там сказано «этапы S0 и S1, дальше не идти» — это уже неверно) и таблица этапов, где S3 стоит как «хвост S2 или отдельная». Статус этапов — ТОЛЬКО frontend-PROGRESS.md, здесь его нет. Поставлено оркестратором №15 08.08 по слепому онбординг-замеру: холодная сессия открывала файл первым по указателям и читала запрет «дальше не идти».

Промт: сессия ФРОНТ TextMachine — MVP веб-интерфейса

Область ЭТОЙ сессии — этапы S0 и S1, дальше не идти

Фронт режется на шесть сессий. Ты — первая. Твоя работа кончается на витрине токенов, до единого экрана приложения. Это не осторожность: без проверяемой петли обратной связи и сошедшихся токенов все следующие этапы слепы, а смешивание инструментальной работы с интерфейсной сжигает контекст.

Этап Что Сессия
S0 Планирование: как писать фронт. Пины версий, карта файлов, правила, протокол проверки твоя
S1 Инструменты, скриншот-цикл, tokens.css, витрина твоя
S2 Оболочка (три панели, вкладки, статус-полоса) + слой src/ui/ отдельная
S3 Слой данных, MSW, фикстуры всех состояний хвост S2 или отдельная
S4 Библиотека, загрузка, разбор, прогресс перевода отдельная
S5 Банк памяти и подпись (самый тяжёлый) отдельная
S6 Читалка двух колонок и замечания отдельная
S7 Метаданные, экспорт, настройки, сквозной прогон отдельная

S0 лендится отдельным коммитом до первой строки кода — иначе план останется словами.

Обязательное чтение перед работой

  1. frontend/docs/STACK_DECISIONS.mdпины версий и ловушки. Все версии сверены 02.08.2026 многоагентным исследованием с адверсариальной проверкой. Не выбирай библиотеки сам, не «обновляй» пины по памяти: твои знания об экосистеме устарели, а вся документация в сети описывает ПРОШЛЫЕ версии этих инструментов.
  2. docs/product-requirements.md — реестр продуктовых требований владельца.
  3. docs/glossary.md — расшифровка проектных сокращений.
  4. frontend/references/*.png — три скриншота, открой и посмотри (ты умеешь читать изображения).

Кто ты и твоя зона

Ты фронтенд-сессия. Зона записи — только frontend/. backend/, platform/, docs/, eval/ — read-only; расхождения и вопросы — пингом владельцу, не правкой чужой зоны.

⚠ Зона и git (читать ДО первой строки кода)

Ты не коммитишь — лендит оркестратор. Твоё дело: довести дерево до зелёного npm run check, описать сделанное в frontend/docs/frontend-PROGRESS.md и передать.

  1. Писать только внутрь frontend/. Ничего за её пределами — ни docs/, ни backend/, ни platform/, ни корневых файлов, ни .gitignore. Нужна правка вне зоны — пинг владельцу, её сделает оркестратор.
  2. Чужие незакоммиченные файлы в дереве не трогать. Параллельные сессии — норма: то, что лежит рядом изменённым, принадлежит не тебе.
  3. НИКАКИХ git add -A, git add ., reset --hard, amend/rebase, checkout поверх грязного дерева и любой перезаписи истории.
  4. Никогда не готовить к лендингу: START_PROMT.MD (файл владельца), .claude/settings.local.json.

Общие правила проекта — в CLAUDE.md в корне (там же эта норма в каноническом виде).

Что за продукт

Веб-сервис перевода книг (веб-новеллы, ранобэ) с одного языка на другой через ИИ. Пользователь загружает книгу, запускает перевод, подписывает словарь терминов, читает результат, выгружает готовое.

Бэкенда пока нет — точнее, движок перевода есть, но HTTP-API к нему ещё не построено. Ты работаешь на моках (см. §6). Это не помеха: контракт данных зафиксирован ниже, замена моков на реальные запросы будет точечной.

Поправка канона №2 (оркестратор, 04.08, D39.99/100/101): контракт API v0 РАТИФИЦИРОВАН (docs/architecture/14-api-contract/ — OpenAPI 3.1, типы генерятся из спеки), строка 95 закрыта; скелет платформы P0 существует (ждёт приёмки); слой данных S3 строится ПО КОНТРАКТУ, не по гипотезам. ⚠ Поправка канона (фронт-сессия S1, 02.08). Формулировка выше читается как «однажды у движка появится HTTP-API». Это не так, и ошибка дорогая: API будет у платформы, не у движка, а движок фронту не виден вообще. Прежде чем писать слой данных, прочитай FRONTEND_PLAN.md §0.10.2 (карта канона и два провода) и первоисточник docs/research/23-engine-platform-seam.md. Там же цена ошибки: моки, снятые не с того уровня контракта, разойдутся с API — ровно то, ради предотвращения чего заведена строка 95 единого бэклога.


1. Референсы — копировать, а не вдохновляться

В frontend/references/ лежат три скриншота. Открой их своим инструментом чтения файлов — ты умеешь смотреть изображения. Это обязательный первый шаг, до единой строки кода.

  • fleet.pngглавная основа макета. Копируем оболочку целиком: как устроены панели, отступы, скругления, плотность, палитра.
  • antigravity_main.png — пустое состояние (ничего не выбрано).
  • antigravity_chat.png — рабочее состояние с тремя колонками и правой панелью-документом.

Владелец сформулировал прямо: «взять макет Fleet как он есть по блокам и стилю и полностью скопировать, переделав под наши нужды». Это не тот случай, где нужна своя эстетика. Нужна чужая, воспроизведённая точно.

1.1. Измеренные значения — брать эти, не выводить свои

Ниже — не оценка на глаз, а замер пикселей fleet.png (Python/PIL: гистограмма поверхностей, поиск насыщенных пикселей, срез по горизонтали, детект края скругления). Скриншот снят при масштабе 2x — установлено по кнопкам окна macOS: шаг 40 физических пикселей против штатных 20 CSS. Все размеры ниже уже переведены в CSS-пиксели.

Поверхности Fleet:

Роль Значение Где замерено
Фон оболочки: промежутки, верхняя полоса, статус-полоса #090909 10.5% площади
Заливка панели (все три панели одинаковы) #17191a 80.5% площади
Приподнятая поверхность / наведение #27292b
Выбранная строка, активная вкладка #353739
Подсветка текущей строки (синеватая) #152945
Выделение #164e8d
Основной текст #dfe1e3
Акцент (фокус ввода) #746deb тон 243°, насыщенность 0.76
Красный индикатора #b82e45 тон 350°

Геометрия Fleet:

  • Промежуток между панелями — ровно 8px, одинаковый везде: слева, между всеми панелями, справа (замер среза: четыре промежутка по 16 физических пикселей, без единого исключения).
  • Радиус скругления панели — 6px (край выходит на прямую за ~11 физических пикселей).
  • Панели не имеют ни рамок, ни теней: отделение только промежутком и разницей заливки #090909#17191a.

Antigravity — для пустого состояния и настроек (чистый нейтральный серый, без холодного оттенка, в отличие от Fleet):

Роль Значение
Фон #101010
Боковая панель #161616
Приподнятая карточка (поле ввода) #1c1c1c
Заливка кнопки основного действия #252525
Разделитель / граница #323232
Текст #cecece

Что НЕ замерено и требует проверки скриншот-циклом: размеры шрифтов, высота строк, внутренние отступы панелей. Их снимай сам сравнением своей витрины с fleet.png.

Что именно снято с fleet.png (следуй этому буквально)

Оболочка. Очень тёмный, почти чёрный фон окна. Панели лежат на нём отдельными скруглёнными «карточками» (радиус ~810px) с чуть более светлой заливкой, разделённые узкими промежутками фона ~68px. Теней нет вообще — разделение только промежутком и разницей заливки. Это главная визуальная подпись Fleet, и владельцу нравится именно она.

Верхняя полоса. Слева кнопки сворачивания панелей (левая / нижняя / правая), по центру — название текущего контекста, справа — ряд иконок-действий. Тонкие линейные монохромные иконки.

Левая панель. Сверху ряд вкладок внутри самой панели (Files · Search · Git · History · +) — не отдельный сайдбар с иконками, а вкладки в шапке панели. Ниже дерево: корень, узлы с шевронами, иконки типов, у выбранной строки — светлая скруглённая подложка (~6px), а не рамка.

Центр. Полоса вкладок: иконка + имя + крестик; активная вкладка светлее и скруглена. Ниже содержимое с колонкой номеров строк приглушённого цвета, у текущей строки — едва заметная подсветка всей полосы. Мелкие подписи-подсказки над блоками очень тусклым серым. В правом верхнем углу — компактный индикатор проблем.

Нижняя панель центра — отдельная скруглённая карточка со своей вкладкой.

Правая панель. Вкладка с заголовком и +. В пустом состоянии — центрированный блок: иконка, заголовок, описание, ряды «клавиша + подпись». Внизу поле ввода с акцентной рамкой — единственное цветное пятно в панели.

Нижняя статус-полоса лежит на фоне оболочки, вне карточек: слева хлебные крошки, справа компактные метаданные состояния.

Цвет. Практически монохром: серый текст на тёмном. Цвет встречается редко и всегда что-то означает. Акцент — один, холодный.

Типографика. Компактный чистый гротеск ~13px в интерфейсе, моноширинный в содержимом. Плотные строки.

Что снято с antigravity_main.png — пустое состояние

Главная область почти пустая, и по её центру стоит один составной блок — скруглённая карточка ввода с подсказкой внутри и рядом мелких управляющих элементов по нижнему краю. Никаких иллюстраций, никаких «начните работу» с картинками. Просто действие по центру пустоты.

В левой панели: выделенная кнопка основного действия во всю ширину сверху, ниже пункты навигации с иконками, ниже секция-заголовок мелким приглушённым шрифтом с иконками действий справа, ниже дерево. Настройки прибиты к самому низу панели.

Что снято с antigravity_chat.png — рабочее состояние

Три колонки. В правой панели — ряд вкладок сверху (несколько именованных разделов) и содержимое как форматированный документ: заголовки, абзацы, блоки-выноски с цветной левой границей (синяя — заметка, зелёная — подсказка) и мелкие «чипы» с моноширинным текстом внутри абзацев.

Эти выноски — наша модель для подсветки неточностей перевода (см. §4, пункт про ненавязчивость). Цветная полоска слева и тусклая подпись — вместо заливки текста.


2. Раскладка нашего приложения

⚠ Раскладка частично устарела — перевешивают «Решения владельца по продукту» в frontend-PROGRESS.md; метки глав — из ДАННЫХ книги, зашитого «Глава N» не существует (D39.100 К-3).

Оболочка Fleet, наполнение наше.

┌─────────────────────────────────────────────────────────────────┐
│ верхняя полоса: сворачивание панелей · название книги · действия │
├──────────────┬────────────────────────────────┬─────────────────┤
│ ЛЕВАЯ        │ ЦЕНТР                          │ ПРАВАЯ          │
│              │                                │                 │
│ вкладки:     │ вкладки открытых глав          │ вкладки:        │
│ Книги ·      │                                │ О книге ·       │
│ Банк ·       │ содержимое:                    │ Замечания       │
│ Поиск        │ — две колонки оригинал/перевод │                 │
│              │ — или таблица банка памяти     │ метаданные,     │
│ дерево:      │ — или пустое состояние         │ выноски с       │
│  книга       │                                │ неточностями    │
│   ├ глава 1  │                                │                 │
│   ├ глава 2  │                                │                 │
│   └ + глава  │                                │                 │
│              │                                │                 │
│ ⚙ Настройки  │                                │                 │
├──────────────┴────────────────────────────────┴─────────────────┤
│ статус-полоса: путь · состояние · прогресс                       │
└─────────────────────────────────────────────────────────────────┘
  • Левая панель — вкладки в шапке (Книги / Банк памяти / Поиск), дерево книг и глав, Настройки внизу. Клик по книге открывает её состояние, клик по главе открывает главу в центре.
  • Центр — вкладки открытых глав, как файлы в Fleet.
  • Правая панель — вкладки О книге (метаданные) и Замечания (места, требующие внимания).
  • Все три панели сворачиваются кнопками в верхней полосе.

3. Сценарий и экраны

3.1. Пусто — ни одной книги

Центр пустой, по центру — блок добавления книги в духе antigravity_main.png: скруглённая карточка, зона переноса файла с подсказкой, под ней компактный ряд полей (язык оригинала, язык перевода, жанр) и кнопка. Без иллюстраций.

3.2. Загрузка книги

После выбора файла: видимое подтверждение, что файл загружен целиком и успешно — размер, объём, определённый язык. Не молчаливый переход.

3.3. Разбор на главы

Дальше книга разбирается на главы. Показать прогресс разбора; по завершении главы появляются деревом в левой панели. Это отдельный видимый шаг, а не часть перевода.

3.4. Перевод — первый проход

Кнопка запуска перевода. Пока идёт:

  • у каждой главы в дереве — свой индикатор выполнения (крутящийся/прогресс), главы обрабатываются не по порядку и это нормально;
  • общий прогресс по книге в статус-полосе (+ ETA: решение владельца 04.08, D39.100 К-5 — поле eta_seconds добавит в спеку правка S3, опциональное);
  • не рассказывать, что происходит внутри. Никаких «сейчас работает редактор», «идёт добыча глоссария», никаких названий моделей. Пользователь видит «идёт перевод» и прогресс. Всё.

3.5. Банк памяти — подпись

По завершении первого прохода становится доступен банк памяти: таблица терминов книги (имена персонажей, места, термины) с предложенным переводом. Пользователь правит и подписывает.

Таблица должна быть быстрой в работе: терминов бывают сотни, идут подряд, клавиатура важнее мыши (перемещение по строкам, утверждение, правка без мыши). Массовые действия. Отдельная кнопка завершения подписи.

3.6. Перевод — финальный проход

После подписи — кнопка запуска финального перевода. Те же индикаторы, что и в 3.4.

3.7. Чтение и сравнение

Открытая глава в центре: две колонки — оригинал и перевод, пролистываются вместе. Абзацы слева и справа по количеству часто НЕ совпадают — это нормально для художественного перевода, выравнивание идёт по крупным блокам, не построчно. Возможность листать главы вперёд-назад.

3.8. Замечания

Места, где перевод может быть неточен, помечаются ненавязчиво: тонкая цветная полоска у левого края блока и тусклая подпись — по образцу выносок из antigravity_chat.png. Никакой заливки текста, никаких ярких маркеров, никаких иконок-восклицаний. Список всех замечаний главы — в правой панели, вкладка Замечания.

Правило: если экран выглядит тревожным — он неправильный. Замечание — это приглашение посмотреть, а не сигнал аварии.

3.9. Метаданные книги

Правая панель, вкладка О книге: название, языки, жанр, число глав, объём, даты, состояние перевода. Спокойный список пар «поле — значение», не карточки со статистикой.

⚠ Денежных полей здесь нет — см. §4.8.

3.10. Добавление главы

В дереве, под главами книги — действие добавления новой главы. Загруженная глава встаёт в дерево и может быть переведена отдельно.

3.11. Экспорт

Кнопка выгрузки текущей книги. Выбор формата, подтверждение готовности.

3.12. Настройки

Отдельный раздел (открывается из низа левой панели). Внутри: профиль и доступ, конфигурация моделей, параметры перевода по умолчанию. Всё техническое живёт здесь и только здесь — в рабочем потоке его нет.

⚠ Подписки, тарифов, остатка и счетов в MVP НЕТ — см. §4.8.


4. Жёсткие ограничения

  1. Не раскрывать устройство бэкенда. Ни названий моделей, ни стадий конвейера, ни внутренней терминологии в рабочих экранах. Пользователю видны: загрузка, разбор, перевод, банк, готово. Всё техническое — в настройках.
  2. Цвет означает состояние и больше ничего. Интерфейс монохромный. Цветными бывают: полоска замечания, индикатор состояния главы, акцент фокуса. Никаких зелёных кнопок «сохранить» и красных «удалить».
  3. Ненавязчивость замечаний — §3.8. Это отдельное требование владельца, не деталь.
  4. Плотность. Работают подолгу; лучше видеть много, чем красиво и мало. Компактные строки, небольшие отступы, маленькие скругления — как во Fleet.
  5. Только десктоп, тёмная тема, базовая ширина 1440, работать должно и на 1920. Мобильной версии нет.
  6. Русский интерфейс, кириллица в реальных пропорциях.
  7. Никаких готовых UI-китов (MUI, Ant, Chakra) — они не дадут воспроизвести Fleet. Только собственные компоненты на токенах; для поведения выпадающих меню, диалогов и подсказок — headless-примитивы без своих стилей.

Решения владельца от 02.08 — приняты, не переоткрывать

  1. Денег в интерфейсе MVP нет вообще (⚠ поправка 04.08, D39.100/ПТ-35: запрет СУММ в силе, но добавлены статус paused, оповещение «лимиты исчерпаны» и страница СТАТУСА использования в настройках — без долларов). Ни сумм, ни потолков, ни оценки стоимости до запуска, ни счётчика во время прогона, ни подписки, ни остатка. Оплаты в MVP не будет, показывать нечего. Учёт расхода остаётся внутри движка как телеметрия владельца. Если видишь денежное поле в каком-либо разделе этого промта — это остаток прошлой редакции, его быть не должно.
  2. Подсветка сомнительных мест — только на уровне блока и главы. Подчёркивания внутри текста не делаем: у проверок движка нет байтовых смещений, только счётчики. Вопрос закрыт, к нему не возвращаться.
  3. Выравнивание колонок — грубое, по единицам экспорта, ориентир «глава целиком». Механизм в движке уже есть (tmctl export --pairs), достраивать ничего не надо. Читалка обязана нормально выглядеть и когда вся глава оказалась одним блоком.
  4. Остановка на подписи банка — параметр запуска, задаётся галочкой в форме перед каждым прогоном, а не глобальной настройкой.

5. Технический стек

Стек зафиксирован в frontend/docs/STACK_DECISIONS.md — бери пины оттуда, не выбирай сам. Коротко: React 19.2.8 · TypeScript 6.0.3 (не 7 — там нет программного API) · Vite 8.2.0 (внутри Rolldown, не Rollup) · react-router 8.3.0 в библиотечном режиме · TanStack Query 5 + Zustand 5 · CSS Modules + tokens.css · react-aria-components 1.20.0 как ЕДИНСТВЕННАЯ библиотека примитивов · react-resizable-panels 4.12.2 (API v4: Group/Panel/Separator).

Три вещи, которые чаще всего делают неправильно, — прочитай про них в STACK_DECISIONS: раздел про гейт «одно место для цвета», раздел про читалку без синхронизации прокруток, и §7 «Ловушки».

Никакого редактора текста в этом MVP: тексты только читают и сравнивают.

Структура:

frontend/
  references/          скриншоты (уже лежат)
  docs/                этот промт и последующие заметки
  src/
    tokens/            tokens.css — ЕДИНСТВЕННЫЙ источник цвета и размера
    api/               слой данных: сейчас моки, потом HTTP. Один вход.
    mock/              фикстуры
    shell/             оболочка: панели, вкладки, статус-полоса
    features/          books, chapters, bank, reader, settings
    ui/                кнопки, поля, таблица, дерево, выноска

5.1. Поддерживаемость — требование владельца, не пожелание

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

  1. У каждой вещи одно место. Цвет и размер — только tokens.css. Данные — только src/api/. Если значение появилось во втором месте, это ошибка, а не удобство.
  2. Плоско и скучно. Никаких абстракций «на будущее», фабрик, слоёв ради слоёв. Проектный норматив: механизм строится там, где несёт ценность, а не ради архитектурной красоты. Дублирование двух строк лучше преждевременного обобщения.
  3. Файл = один компонент плюс его .module.css рядом. Больше ~150 строк — делить.
  4. Компоненты глупые. Данные приходят пропсами. Запросы живут на уровне экрана, не в листьях дерева.
  5. Состояние ровно в двух местах: TanStack Query — всё серверное, Zustand — состояние интерфейса. Копий серверных данных в локальном состоянии нет. Контекстов «на всякий случай» нет.
  6. Глобальных стилей два файла: сброс и tokens.css. Всё остальное — CSS Modules, они скоупятся сами.
  7. Никаких обёрток над обёртками и никаких UI-китов.
  8. Имена человеческие, без аббревиатур — проектная норма.
  9. Комментарии короткие: одна-две строки «почему», не «что». Простыни не нужны.
  10. Каждый экран открывается в изоляции — свой маршрут и своя фикстура, чтобы его можно было снять скриншотом и проверить отдельно от остальных.

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

6. Данные: моков придерживаться, API не выдумывать

HTTP-слоя ещё нет. Весь доступ к данным — через src/api/, внутри которого сейчас моки. Компоненты не знают, что данные поддельные. Когда появится сервер, меняется один модуль.

Заведи фикстуры на одну книгу целиком: метаданные, 58 глав, у каждой главы оригинал и перевод по несколько абзацев, несколько помеченных мест, таблица банка на 2030 терминов в разных состояниях, состояние прогона.

Материал для фикстур бери реальный — китайский текст с русским переводом, имена и термины. Выдуманный «Lorem ipsum» даст неверную плотность: кириллица длиннее латиницы, иероглифы короче всего, и колонки поедут. Пример реального фрагмента лежит в backend/example/chapter1-zh.txt (читать можно, править нельзя).

Состояния фикстур — по enum BookStatus контракта (docs/architecture/14-api-contract/openapi.yaml: десять значений; paused добавит правка S3 — D39.99/100 К-8); исторический список: книга не начата · разбирается · переводится (первый проход) · ждёт подписи банка · переводится (финал) · готова · остановлена пользователем · отклонена (не удалось разобрать файл) · прервана ошибкой.


7. Как работать — это важнее, чем что писать

7.1. Смотри на то, что построил

Заведи цикл со скриншотами первым делом, до экранов. Скрипт npm run shot поднимает приложение, снимает PNG в frontend/.shots/, ты открываешь этот PNG и смотришь на него (ты умеешь читать изображения), сравниваешь с references/fleet.png, правишь.

Без этого цикла ты пишешь вслепую: код валиден, вид случаен. Это единственный способ выполнить требование «скопировать Fleet».

Установка проверена на этой машине — делай ровно так, sudo не нужен ни на одном шаге. Среда: WSL2, Ubuntu 24.04, Node 22, пароль root недоступен.

npm i -D playwright
npx playwright install chromium        # БЕЗ --with-deps: он требует sudo и ставит лишнее

Chromium запустится не сразу: не хватает четырёх системных библиотек (libnss3.so, libnssutil3.so, libnspr4.so, libasound.so.2). Ставятся локально, без root:

mkdir -p .tooling && cd .tooling
apt-get download libnss3 libnspr4 libasound2t64
for d in *.deb; do dpkg -x "$d" root; done
rm -f *.deb && cd ..

Путь к ним — .tooling/root/usr/lib/x86_64-linux-gnu. Пропиши его прямо в команду, чтобы никто о нём больше не думал:

"scripts": {
  "shot": "LD_LIBRARY_PATH=$PWD/.tooling/root/usr/lib/x86_64-linux-gnu node scripts/shot.mjs"
}

В .gitignore: .tooling/ и .shots/ — бинарники и снимки в репозиторий не едут.

Проверка, что цикл живой (сделай её до всякого интерфейса): отрисуй страницу с панелью #17191a на фоне #090909, радиус 6, отступ 8 — сними, открой, убедись, что видишь именно это. Работает браузер headless, окна нет, графический сервер не нужен.

7.2. Порядок твоей сессии

S0 — план (кода нет). Прочитай всё из блока обязательного чтения. Напиши frontend/docs/FRONTEND_PLAN.md: таблица пинов (пакет · версия · дата релиза · зачем именно нам, сверенная по npm), карта src/ с назначением каждой папки, правила поддерживаемости в проверяемой форме, протокол скриншот-цикла и критерий сравнения с референсом. Заленди отдельным коммитом.

S1 — инструменты и токены.

  1. Проверь node -v — нужно ≥ 22.22. Установи Playwright по процедуре из §7.1 (без sudo).
  2. Каркас: Vite + React + TS, ESLint + stylelint + prettier, единая команда npm run check.
  3. Скриншот-цикл и проверка, что он живой (страница с панелью на фоне, снять, посмотреть).
  4. tokens.css — значения из STACK_DECISIONS/§1.1 этого промта, с комментарием об источнике. Задай @layer явно: порядок каскада между стилями React Aria, токенами и модулями — источник тихих расхождений. Сразу стилизуй скроллбары: дефолтные на Windows толстые и светлые, они ломают вид на трёх панелях.
  5. Витрина: страница из панелей, вкладок, строки дерева и строки таблицы. Сними, положи рядом с fleet.png, посмотри обе, сведи.
  6. Контракт-тест токенов: рендерим корень, сверяем вычисленные значения CSS-переменных с замеренными числами. Это заменяет визуальный гейт с эталонами.

На витрине остановись. Если токены не сошлись — это и есть результат сессии, честно описанный; дальше не иди. Экраны пишут следующие сессии.

7.3. Ревью исполнением — обязательно

Проектная норма: любая сессия, пишущая код, обязана проверять себя исполнением, а не заявлением. Для тебя это значит:

  • приложение реально запускается, экран реально открывается — проверено запуском, не предположением;
  • скриншот снят и просмотрен, а не «должно выглядеть так»;
  • расхождения с референсом названы вслух, даже если исправить не успел;
  • если чего-то не сделал — сказано прямо, без «в основном готово».

Отчёт в конце: что построено, что видно на скриншотах, где отошёл от референса и почему, что осталось.

7.4. Чего не делать

  • Не изобретать API и не ходить в backend/ за данными — только моки.
  • Не тащить UI-киты и не «улучшать» референс своим вкусом.
  • Не рисовать мобильную версию, светлую тему, иллюстрации пустых состояний.
  • Не раскрывать конвейер (§4.1) — это самое лёгкое требование забыть.
  • Не хардкодить цвета и размеры мимо tokens.css.

8. Готово — это когда (для ТВОЕЙ сессии, S0+S1)

  • FRONTEND_PLAN.md заленден отдельным коммитом до кода.
  • npm run check зелёный и делает все четыре шага.
  • npm run shot снимает PNG, ты его открывал и смотрел.
  • tokens.css — единственный источник цвета и размера; гейт против хардкода включён и проверен на живом нарушении (вставь #fff в компонент, убедись, что проверка падает, убери).
  • Витрина снята и сведена с fleet.png; расхождения названы вслух.
  • Контракт-тест токенов проходит.

Критерий сравнения — не растровое совпадение. JetBrains Fleet закрыт (скачивание прекращено 22.12.2025), референс снят на macOS при 2x, наша цель — Windows-Chromium с другим хинтингом шрифтов. Пиксель-в-пиксель недостижим и не является целью. Сходиться обязаны: замеренные цвета, промежутки 8px, радиусы 6px, плотность строк и общее впечатление. Кегли и интерлиньяж — подбором на глаз до похожести, потому что померить их больше негде.

9. Что уже известно про движок — учесть в плане, не открывать заново

Разобрано по коду 02.08. Влияет на форму данных, поэтому знать надо уже на S0.

  • Индикатор прогресса нельзя строить на «готово N из M»: unit становится done только когда есть и черновые строки всех его членов, и строка редактуры. Во время черновой волны это ноль почти всё время. Правильно — пофазно: черновик N/Mредактура N/M.
  • Подпись термина — не UPDATE строки. Банк пересобирается из файлов на каждом прогоне, прямая запись в таблицу молча стирается следующим прогоном. Форма контракта подписи это учитывает.
  • Байтовых смещений у замечаний нет — только счётчики. Поэтому подсветка сомнительных мест идёт на уровне блока и главы, а не внутри текста. Владелец это принял 02.08 (§4.9), вопрос закрыт.
  • Гранулярность пар грубее ожидаемой: финальный текст существует на уровне edit-unit, замерено ~1.9 блока на главу — местами вся глава окажется одним блоком. Читалка обязана нормально выглядеть и в этом случае.

Полный список того, что достраивается в движке — STACK_DECISIONS.md §8.