203 lines
22 KiB
Markdown
203 lines
22 KiB
Markdown
# Промт: фронт-сессия S3 — слой данных (вход под замком)
|
||
|
||
Ты — фронтенд-сессия TextMachine, четвёртая по счёту. Зона записи — **только `frontend/`**;
|
||
сессия не коммитит — лендит оркестратор (протокол — стоящий промт `FRONTEND_SESSION_PROMPT.md`
|
||
§«Зона и git», он в силе целиком). Пре-коммит хук стоит и самоустанавливается при `npm install`.
|
||
|
||
> Промт написан сессией S2 по просьбе владельца — как передача с той точки, где S2 встала.
|
||
> Ратифицирует и правит его оркестратор; при расхождении с его хендофф-промтом побеждает тот.
|
||
|
||
## Входное состояние (04.08, проверено исполнением, а не заявлено)
|
||
|
||
- **Пройдено S0–S2:** план · инструменты и скриншот-цикл · `tokens.css` по замерам референса ·
|
||
оболочка трёх панелей (`src/shell/`) · примитивы `src/ui/` на `react-aria-components` ·
|
||
витрина `/showcase` и нагрузочный `/scale` (2284 раздела, 1200 терминов).
|
||
- `npm run check` — 5 гейтов (prettier · eslint тип-осведомлённый · stylelint · tsc · vitest,
|
||
**77 тестов**), `npm run check:full` — + сборка + три скриншота с гейтом доступности axe.
|
||
Всё зелёное на 04.08.
|
||
- **Данные всё ещё синхронная фикстура:** `src/api/` отдаёт объекты из `src/mock/` напрямую.
|
||
Это диспозиция Ф-15, а не недосмотр: асинхронность приезжает вместе с MSW, то есть в S3.
|
||
- **Гейты, которые ты застаёшь:** одно место для цвета и размера (TSX-половина в
|
||
`eslint.config.js`, CSS-половина в `stylelint.config.js`) · три шва — фикстуры видит только
|
||
`src/api/`, глобальный CSS только `src/main.tsx`, `react-aria-components` только `src/ui/` —
|
||
закрытые и для статического, и для динамического импорта · сеть запрещена вне `src/api/`
|
||
во всех транспортах (`fetch`/`EventSource`/`WebSocket`/`XMLHttpRequest`, включая
|
||
`window.*`) · тест общности: код языка не зашивается в разметку, стили не ветвятся по
|
||
`:lang(…)` · контракт-тест токенов и структурные тесты CSS-модулей.
|
||
- ⚠ **На момент написания промта в дереве лежали незакоммиченные правки** по ревью оркестратора
|
||
(`frontend/src/{api/types.ts,generality.test.ts,mock/book.ts,mock/scale.ts,showcase/Context.tsx,
|
||
showcase/Reader.module.css,tokens/tokens.css,tokens/tokens.test.ts}`, `eslint.config.js`,
|
||
`frontend/docs/*`). Их лендит оркестратор. **Первым делом сверься с `git log` и `git status`:**
|
||
если правок в дереве нет — они уже уехали, ничего восстанавливать не нужно.
|
||
|
||
## Замок на входе — первое действие сессии
|
||
|
||
**Проверь сам, промту не верь** (он написан 04.08 и мог устареть):
|
||
|
||
1. Существует ли `docs/architecture/14-api-contract/` (спека + компаньон)? — **на 04.08 вечера: ДА, ратифицирован (D39.99), замок ОТКРЫТ**;
|
||
2. Строки 95 в таблице единого бэклога больше НЕТ — она ЗАКРЫТА (D39.99, закрытые строки уходят в D-лог); если видишь её живой — дерево старее канона, стоп и пинг.
|
||
|
||
**Открыт** (контракт есть и ратифицирован) → скоуп S3 ниже.
|
||
**Закрыт** → раздел «Если замок закрыт» (контингенция; на вечер 04.08 замок ОТКРЫТ — D39.99). Не начинай S3 «пока
|
||
на своих типах, потом поправим»: моки, снятые не с того контракта, разойдутся с API — ровно
|
||
то, ради чего строка 95 заведена.
|
||
|
||
## Обязательное чтение до кода (порядок)
|
||
|
||
1. `frontend/docs/FRONTEND_SESSION_PROMPT.md` — стоящий промт: сценарий §3, жёсткие ограничения
|
||
§4, «как работать» §7. **Его не редактировать.** ⚠ Раскладка §2 частично устарела — её
|
||
перевешивают решения владельца из журнала зоны.
|
||
2. `frontend/docs/frontend-PROGRESS.md` целиком: «Текущее состояние» · «Решения владельца по продукту» ·
|
||
«Открытые вопросы» · хронику 04.08 (в ней — что S2 построила, где отошла от референса и что
|
||
поправило ревью оркестратора).
|
||
3. `frontend/docs/FRONTEND_PLAN.md` — §0.1 (карта канона: что читать перед чем), **§0.2
|
||
(транспорт: с движком фронт не разговаривает никогда — это ратифицированный анти-паттерн,
|
||
D39.81/D39.85)**, §5.4 и §5.4.1 (формы обхода гейтов и названные границы), **§6 (что уже
|
||
известно про движок и как это меняет форму данных — читать до первой строки типов)**.
|
||
4. `frontend/docs/STACK_DECISIONS.md` — §2 пины (там уже названы `@tanstack/react-query` и `msw`),
|
||
§5 транспорт и правила стрима, §7 риск ре-ингеста. Библиотеки сам не выбирай и версии
|
||
по памяти не «обновляй»: твои знания об экосистеме устарели, сверка — live по npm.
|
||
5. `docs/research/23-engine-platform-seam.md` — `docs/README.md` требует читать его **перед любым
|
||
кодом стыка**; форма событий и правило ре-синка оттуда.
|
||
6. `frontend/docs/BACKLOG.md` — строки **Ф-14** (вход фронта в контракт), **Ф-15** (закрывается
|
||
этой сессией), Ф-19, Ф-21.
|
||
7. `references/*.png` и `.shots/*.png` — открой и посмотри до первой правки.
|
||
|
||
## Решения владельца 04.08 вечер (D39.100) — правки спеки ПЕРВЫМ шагом S3
|
||
|
||
Контракт ратифицирован, четыре К-вопроса закрыты владельцем; спеку правишь ты (минорный бамп
|
||
версии, регенерация типов, батарея), компаньон-К-таблицу — статусами «решено»:
|
||
|
||
1. **К-1 закрыт: десять статусов приняты.**
|
||
2. **К-8 закрыт механизмом «как Claude Code»** (ПТ-35, П-5): `BookStatus` получает
|
||
11-е значение **`paused`** (стоп по потолку; резюмируемый; в `failed` не мапить — уже
|
||
запрещено спекой); пользователь видит оповещение «перевод остановлен: лимиты исчерпаны»,
|
||
сами лимиты — страница в настройках (СТАТУС использования, не суммы: запрет денег на
|
||
проводе в силе). API лимитов проектирует платформа (П-5) — поле/эндпоинт в спеку НЕ
|
||
выдумывать, только статус и семантику оповещения.
|
||
3. **К-5 закрыт: ETA показывать** — `eta_seconds` в прогресс-модель (движок отдаёт,
|
||
`status.go:112`; поле опциональное — оценка бывает недоступна).
|
||
4. **К-3 закрыт с канон-уточнением: метка главы — ИЗ ДАННЫХ книги, зашитых форм нет.**
|
||
«Глава N» — это шаблон langpack-ДАННЫХ, не закон: легальна книга вовсе без номеров и
|
||
глав. Дерево рендерит label, который дал манифест (строка 100)/heading (К-2), внутренний
|
||
порядок — непрозрачный индекс. Проверь спеку и фикстуры на зашитую форму «Глава N».
|
||
5. После правок: байт-сверка зонной спеки с ратифицированной копией
|
||
(`docs/architecture/14-api-contract/openapi.yaml`) — расхождение отдай оркестратору
|
||
на пере-ратификацию диффом, сам канон не правь.
|
||
|
||
## Скоуп S3 — слой данных, и ни шагом дальше
|
||
|
||
1. **`src/api/` становится асинхронным**: MSW как сетевой мок + серверное состояние на пинах
|
||
из STACK_DECISIONS §2 (версии сверить live на дату сессии; `.npmrc` держит `save-exact`).
|
||
Каждый новый пин — строкой в таблицу `FRONTEND_PLAN.md` с датой релиза и «зачем нам».
|
||
2. **Фикстуры всех состояний, а не одного счастливого:** ожидание · ошибка · пусто ·
|
||
частично · длинный хвост · потеря соединения на стриме. Правило S1/S2, которое здесь
|
||
действует сильнее всего: **фикстура по умолчанию — трудный случай.** Наивный счётчик глав
|
||
должен на ней давать ноль (идёт черновая волна), иначе скриншот-цикл смотрит на удобное.
|
||
3. **Живой прогресс — `EventSource` за швом `src/api/`** (STACK_DECISIONS §5; гейт сети уже
|
||
запрещает его где-либо ещё). Докачка по `Last-Event-ID`/ревизии — часть контракта, не выдумка.
|
||
4. **Ф-15 закрывается здесь:** ветки ожидания/ошибки/пустоты появляются вместе с MSW, а не
|
||
после первого продуктового экрана.
|
||
5. **Типы `src/api/types.ts` приводятся к контракту.** Что в них сегодня заведомо временное:
|
||
булев `signed` вместо трёхзначного `auto|draft|approved` · ключ строки банка, собранный
|
||
из (`src`, `dst`, `type`), — у движка термин уникален по (`src`, `sense`, `since_ch`,
|
||
`until_ch`) · отсутствие ревизии для докачки. Всё это перечислено строкой Ф-14.
|
||
**Закрытые юнионы получают явную ветку неизвестного значения** (строка Ф-22) — сегодня её нет
|
||
ни у одного, и строгость тайпчека здесь НЕ страхует: `runStates[book.state]`
|
||
(`showcase/Library.tsx:103`) — обращение к `Record` по КОНЕЧНОМУ юниону, а
|
||
`noUncheckedIndexedAccess` добавляет `undefined` только индексным сигнатурам (проверено `tsc`
|
||
на пробе: обращение по юниону компилируется молча, ругается только `Record<string, …>`).
|
||
Значит состояние прогона из будущего контракта даёт `undefined.tone` — падение дерева
|
||
библиотеки, а не пустую метку; `noteTone` тем же классом тихо уводит незнакомую ступень
|
||
замечания в СПОКОЙНУЮ ветку. **Место ветки — шов `src/api/`, где значение входит**, а не
|
||
каждый компонент: перевод «вердикт → вид» уже расползался по экранам, и контрольный вопрос
|
||
владельца требует, чтобы новое значение правило один файл.
|
||
6. **Поля не выдумывать.** Нет в контракте — это вопрос владельцу/оркестратору в
|
||
«Открытые вопросы» журнала зоны, а не догадка в типе. Дефект «фикстура выдумала поле»
|
||
в этой зоне случался дважды и оба раза стоил экрана.
|
||
|
||
**Не в скоупе:** экраны S4–S7 · редактор текста · светлая тема · мобильная раскладка ·
|
||
React Compiler (Ф-2) · Tauri (Ф-5).
|
||
|
||
## Если замок закрыт
|
||
|
||
Контингенция на случай, если проверка замка даст «закрыт» (на вечер 04.08 замок ОТКРЫТ); тогда правильный ход — не ждать молча и не строить экраны
|
||
на синхронных моках (порядок этапов Ф-1 стоит именно на слое данных).
|
||
|
||
- **Доведи Ф-14 до артефакта, который можно отдать автору контракта:** не список намерений,
|
||
а перечень с обоснованием на каждый пункт — язык кодами · состояние прогона отдельно от
|
||
выполнения главы · прогресс пофазно по ЮНИТАМ · ревизия/`Last-Event-ID` · трёхзначный статус
|
||
подписи · поля банка (`type`/`sense`/`since_ch`) и ключ строки · продуктовый словарь вердиктов
|
||
(ПТ-33; §4.1 запрещает протечку внутренностей конвейера на экран). Половина уже написана
|
||
в строке Ф-14 и в §6 плана — собери, а не сочиняй заново.
|
||
- Отдай его оркестратору пингом в `frontend/docs/frontend-PROGRESS.md` и **остановись**:
|
||
заводить контракт своим решением фронт не может (шапка `BACKLOG.md`).
|
||
⚠ **Испр. сессией S3 04.08 по слову владельца:** здесь стояло «пингом в `docs/PROGRESS.md`» —
|
||
это чужая зона, и шапка журнала фронта фиксирует решение владельца 02.08 «в `docs/PROGRESS.md`
|
||
оркестратора не пишут». Канал передачи — журнал своей зоны; оркестратор пишет туда же.
|
||
- Ф-16, Ф-17, Ф-18, Ф-20 — **не трогать**: у каждой в бэклоге стоит свой триггер, и ни один
|
||
из них не наступил.
|
||
|
||
## Ловушки, купленные S2 — не переоткрывать
|
||
|
||
- **`react-aria-components`:** `Tab` не принимает клавиатурных обработчиков (обработчик живёт
|
||
на ряду вкладок) · у роли `tab` дети презентационные, поэтому крестик закрытия — не кнопка
|
||
(axe роняет `nested-interactive`), закрытие с клавиатуры — `Delete`, объявить его нечем (Ф-17) ·
|
||
**невыбранная `TabPanel` не рендерится вовсе** (`dist/private/Tabs.mjs:276`), отсюда потеря
|
||
прокрутки при переключении вкладки (Ф-19, замерено дважды) · `Tree` — это `treegrid`/`row`,
|
||
а не `treeitem`; раскрытие — `<Button slot="chevron">` · `renderEmptyState` обёрнут
|
||
в `role="option"` (зонд S2 принял это за дефект кода).
|
||
- **`react-resizable-panels` v4:** `className`/`style` панели уезжают во ВЛОЖЕННЫЙ div, у него
|
||
всегда inline `overflow:auto` · `Separator` обязан быть прямым ребёнком `Group` · ключ
|
||
хранилища раскладки содержит состав видимых панелей, поэтому сворачивание удалением панели
|
||
меняет ключ (сделано осознанно: так поле оболочки остаётся ровно замеренным).
|
||
- **Скриншот-цикл:** `vite build` и `preview` в один момент дают пустой экран — это гонка,
|
||
а не регрессия; перезапусти прогон, прежде чем «чинить» рабочий код.
|
||
- **Зонды и живые нарушения:** файлы зондов удалять за собой (в S2 агенты ревью оставили свои
|
||
в чужом дереве), правленые файлы восстанавливать из памяти процесса, **а не `git checkout`** —
|
||
в дереве могут лежать незакоммиченные правки параллельных сессий.
|
||
- **Первому красному результату зонда не верить:** три «находки» первого прогона S2 оказались
|
||
дефектами зонда (селектор бил по трём панелям сразу), и соблазн «починить» рабочий код был
|
||
вполне реальный.
|
||
- **esquery:** селектор вида `Property[key.value=/^--/] > Literal[…]` ловит собственный ключ
|
||
свойства — в TSX-гейте это записано комментарием, не убирай его.
|
||
|
||
## Технические рамки
|
||
|
||
- Новый маршрут → сразу в `KNOWN_ROUTES` (`scripts/shot.mjs`); тест сверяет списки и упадёт.
|
||
- Гейты не ослаблять. Точечное подавление — только именованное правило с причиной.
|
||
- Файл = компонент + модуль стилей рядом; >150 строк — делить. Комментарии — одна-две строки
|
||
«почему», не «что».
|
||
- Тексты фикстур — настоящие пропорции кириллицы и иероглифов, объём минимальный: вопрос
|
||
авторского права (В-2) у владельца, цитаты не расширять.
|
||
|
||
## Как работать
|
||
|
||
1. **Ревью исполнением — мандат проекта, не пожелание:** приложение поднимается, скриншоты
|
||
сняты и ПРОСМОТРЕНЫ, каждый гейт проверен живым нарушением с перечнем форм, `npm run check:full`
|
||
зелёный. «Должно работать» ревью не является.
|
||
2. **Скриншот-цикл — с первого изменения**, критерий сведения — не растровое совпадение,
|
||
а плотность и впечатление (стоящий промт §8).
|
||
3. **Адверсариальная самопроверка перед финишем** (author≠reviewer): пройди по своим правкам
|
||
с установкой опровергать. S1 так поймала пять дефектов в собственных гейтах, S2 — восемь.
|
||
4. **Спорное с каноном или новое продуктовое решение не принимай сам:** вопрос в «Открытые
|
||
вопросы к владельцу» журнала зоны, и продолжай то, что вопроса не требует.
|
||
|
||
## Готово — это когда
|
||
|
||
- Замок проверен и результат записан: либо S3 сделана, либо в журнале лежит, чем сессия
|
||
занималась вместо неё и почему.
|
||
- Если S3 сделана: `src/api/` асинхронен, MSW отдаёт все состояния, ветки ожидания/ошибки/пустоты
|
||
живые, Ф-15 закрыта, типы сведены с контрактом, а расхождения — не «поправим потом»,
|
||
а строки бэклога с триггером.
|
||
- `npm run check:full` зелёный; новые маршруты в `shot.mjs`; скриншоты просмотрены.
|
||
- `frontend/docs/frontend-PROGRESS.md`: обновлено «Текущее состояние», добавлена хроника сессии
|
||
(что построено · что видно на снимках · где отошёл от канона и почему · что осталось);
|
||
строки бэклога получили диспозиции.
|
||
- Ничего не закоммичено: дерево подготовлено и передано оркестратору.
|
||
|
||
## Что ждёт не тебя (не решай сам)
|
||
|
||
**В-1** данные привязаны к одной машине (вопрос на движок/платформу) · **В-2** копирайт фикстур ·
|
||
**В-3/Ф-21** каким словом называть ступень замечания (словарь продуктовый, ПТ-33) ·
|
||
**Ф-11** контраст палитры ниже WCAG на четырёх узлах — принято как есть до слова владельца.
|