From 5557626ea2e1f3ebcccc8a6b46f8c974e224efd4 Mon Sep 17 00:00:00 2001 From: heaven Date: Fri, 14 Aug 2026 19:04:16 +0300 Subject: [PATCH] Issue the S4 frontend prompt: intake and progress screens on contract 0.2.3 with owner decisions on title, rejection phrases and danger tone --- frontend/docs/S4_SESSION_PROMPT.md | 254 +++++++++++++++++++++++++++++ frontend/docs/frontend-PROGRESS.md | 7 + 2 files changed, 261 insertions(+) create mode 100644 frontend/docs/S4_SESSION_PROMPT.md diff --git a/frontend/docs/S4_SESSION_PROMPT.md b/frontend/docs/S4_SESSION_PROMPT.md new file mode 100644 index 00000000..05027e34 --- /dev/null +++ b/frontend/docs/S4_SESSION_PROMPT.md @@ -0,0 +1,254 @@ +# Промт: фронт-сессия S4 — библиотека, загрузка, разбор, прогресс (+ спек-правка 0.2.3) + +> Выдан оркестратором №16 14.08.2026 по D39.130 («гейт S4 пал»). Запуск — по слову владельца. + +## 0. Какую проблему решаем и что даст твой результат + +Продукт — веб-сервис художественного перевода книг: пользователь загружает книгу, запускает +перевод, подписывает словарь терминов, читает результат. Фронт строится этапами S0–S7; пройдено +всё до S3.7 включительно: оболочка трёх панелей по референсу Fleet, слой данных на контракте +OpenAPI (MSW как сетевой мок), i18n-каталог, гейты. Чего до сих пор НЕ существует — +**пути пользователя от «у меня есть файл» до «книга переводится»**: форма добавления книги есть +как вид (модал S3.5 по `antigravity_add_folder.png`), но никуда не отправляет; статусы +`uploading`/`parsing`/`rejected` в контракте есть, а экраном не прожиты; запустить прогон с +экрана нельзя. До сих пор это было честно: серверной ручки загрузки не существовало. 14.08 +платформа P5 принята (D39.130) — `POST /books` построен и жив, и вместе с его приёмкой владелец +контракта ратифицировал пакет правок спеки (**0.2.3**), которые вносишь ты. Твой результат = +пользовательский путь загрузки и запуска работает на форме контракта 0.2.3, и следующая сессия +(S5, подпись банка) строится на книге, которую в интерфейсе можно завести, а не только замокать. + +Ты — девятая фронт-сессия. Промт — твой ЕДИНСТВЕННЫЙ контекст: ты не видишь чужих переписок; +всё несущее — здесь или в названных доках. Дом фронта остаётся миром моков (MSW по контракту); +живой стенд платформы — только опциональная проба, §10. + +## 1. Онбординг (порядок чтения, до кода) + +1. `CLAUDE.md` (корень) — гардрейлы проекта; из них жёсткие для тебя: зона записи ТОЛЬКО + `frontend/`, ты НЕ коммитишь, `.env` не читать, чужие незакоммиченные файлы не трогать. +2. `frontend/docs/FRONTEND_SESSION_PROMPT.md` — живой носитель норм зоны: §«Зона и git», §3 + сценарий (тебе — §3.1–3.4), §4 жёсткие ограничения, §5.1 поддерживаемость, §7 «как работать». + Статусные абзацы там частично исторические — статус этапов только в `frontend-PROGRESS.md`. +3. `frontend/docs/frontend-PROGRESS.md` — шапка «Текущее состояние» + раздел «Решения владельца + по продукту» (перевешивает всё в старых промтах) + записи S3.5–S3.7 и приёмок. +4. `frontend/docs/BACKLOG.md` (Ф-строки) и `frontend/docs/STACK_DECISIONS.md` (пины — не двигать). +5. Контракт: зонная копия `frontend/docs/api-contract/openapi.yaml` (**0.2.2**, байт-зеркало + канона `docs/architecture/14-api-contract/openapi.yaml`) + компаньон-README рядом с каноном + (провенанс, К-вопросы, §2.15 — потолок прогона). +6. Референсы `frontend/references/*.png` — открой глазами, если трогаешь вид. + +**Эхо-протокол:** первый деливерабл — ≤10 строк «что я понял: скоуп / инварианты / не-делать» +ДО работы. Расхождение чинится на минуте пять, не на приёмке. + +## 2. Задача 1 — спек-правка 0.2.3 (делай РОВНО так; ратифицировано D39.130 п.2в + ратификация ниже) + +Правишь ЗОННУЮ копию `frontend/docs/api-contract/openapi.yaml`, бампаешь `info.version` до +**0.2.3**, перегенерируешь типы (`npm run contract`), spectral зелёный. Канон правит оркестратор +диффом при лендинге — байт-сверку не выравнивай сам, расхождение с каноном на время сессии +легально (прецедент Ф-47/0.2.2). Пять правок: + +- **PD-172:** у `createBook` записать проводное правило — часть `file` идёт **последней** в + multipart-форме; поля после файла = 400. Причина (одной строкой в описание): платформа читает + форму потоково и обязана увидеть языки до тела файла. +- **PD-173:** у отклонённой книги появляется **машинная причина** — поле с закрытым enum по + словарю платформы (`source_unreadable` · `not_configured` · `parser_unavailable`; её колонка + `books.reject_reason`, миграция 00013 — сверь имена значений по `platform/` read-only, код + первичен). **Продуктовые фразы различения пишешь ТЫ** (слово владельца 14.08: «пусть сам + придумает, только над хорошими вариантами подумает»). Рамки: фразы должны честно ложиться на + РЕАЛЬНЫЙ флоу отказов (движок отдаёт платформе классы отказа, платформа сводит их в этот enum — + прочитай маппинг read-only, чтобы фраза не врала о причине), при этом НЕ раскрывать внутреннее + устройство (ПТ-33: ни стадий, ни моделей, ни слов вроде «манифест»/«парсер движка»; та же + дисциплина, что у `Problem.title`) и не звучать тревожно (§3.8). Разное следующее действие — + разные фразы: «файл не тот» → проверить файл; «сервис недоступен» → повторить позже. В UI — + через словарь с веткой неизвестного, как все enum; свои фразы вынеси в отчёте отдельным + списком на утверждение владельцем. +- **PD-174:** назвать классы ответов, которые провод уже даёт, а спека молчит: 404 на + `POST /books` у инстанса без интейка; 503 у `resume` на деплое без маркер-команды/шаблона + потолка (0.2.1 ратифицировала 503 только для СТАРТА). +- **PD-180:** описание `createBook` честное: **201 несёт `parsing`**, не «responds immediately … + enters uploading» (`uploading` наблюдаем только параллельным чтением библиотеки); плюс перечень + отказов интейка: 400 (>16 частей формы; текстовое поле >1 КиБ), 413 (потолок тела — порог + принадлежит деплою, числа в спеку не зашивать), **408** (тело не успело за дедлайн маршрута — + медленный клиент, лечение повтором). +- **`title` в `BookIntake`** — необязательное поле: пустое/отсутствующее = «название даст разбор» + (сегодня платформа берёт имя загруженного файла), заполненное = задано вручную и разбор его не + перепишет. **Ратифицировано оркестратором 14.08** как исполнение замечания 12 владельца + (S3.5: «автор вводит название руками ЛИБО скипает — источники различать»; форма это уже + разводит, а отправить рукописное название до сих пор некуда — черновик S3.5 висел без + ратификации). Владелец промт ревьюит — отмена этого пункта одной репликой; дошла отмена + аддендумом → эхо-подтверди и отрази в отчёте. + +## 3. Задача 2 — загрузка книги (форма → `createBook`) + +Половина Ф-26. Модал «Добавить книгу» отправляет форму через слой `src/api/` (типы `createBook` +уже сгенерены), MSW-хендлер — по форме 0.2.3, включая порядок частей (file последним) и ветки +отказов. Экранный путь по §3.2–3.3 сценария: + +- **Прогресс отправки файла** видимый (книги бывают десятки МиБ). `fetch` прогресса отправки не + даёт — механизм выбери сам (XHR либо иное) и аргументируй в отчёте; слой данных остаётся одним + входом, гейт транспорта (`src/api/**` only) в силе. +- После 201 книга в библиотеке в `parsing` — **разбор это отдельный видимый шаг**, не часть + перевода. ⚠ Числового прогресса разбора у контракта НЕТ — процент не выдумывать, честное + состояние «разбирается»; по завершении главы появляются в дереве, статус `not_started`. +- **Отказ (`rejected`) — с причиной** по PD-173 и советом, различимым по классу (файл не тот ≠ + сервис недоступен), фразы — как в задаче 1. Отказные ветки (400/408/413/404) — честные + состояния формы, не алерты; тон — §3.8 («если экран выглядит тревожным — он неправильный»). +- Подтверждение успешной загрузки видимое: размер/объём/язык (§3.2) — из данных контракта + (`character_count`, `chapter_count`, языки), не выдумывая полей. + +## 4. Задача 3 — запуск прогона с ручкой потолка (остаток строки 126 единого бэклога) + +Форма запуска перевода. Ратифицировано (D39.110/115, компаньон §2.15 — не переоткрывать): + +- Перед показом формы читается `GET /books/{id}/run-options`; шкала потолка строится из + `CeilingBounds` **в ГЛАВАХ** — никаких долларов, сумм и оценок стоимости на экране (§4.8 в + силе; пересчёт «главы→деньги» — целиком платформа). +- `ceiling_chapters` обязателен, **ноль выбрать нельзя**; предустановка шкалы = + `default_chapters` от платформы (клиент своё значение не выбирает — это продуктовая политика); + `max_chapters: 0` = старт недоступен, честное исчерпанное состояние вместо шкалы. +- Bounds приходят готовыми и уже подрезанными — клиент **не клампит второй раз** и не выводит + свои; между чтением и стартом они могут уехать — **409 на старте** обрабатывается + пере-чтением run-options и честной фразой, не ретраем втихую. +- Галочка «остановиться на подписи банка» (`verify_bank`) — параметр ЭТОГО запуска, не глобальная + настройка (решение владельца 02.08, §4 п.11 промта зоны). +- **`paused` — прожитое состояние прогресса** (ПТ-35: стоп по потолку = статус `paused` + + оповещение). Фраза «остановлена: лимиты» зарезервирована за владельцем (В-3/В-6) — берёшь + существующую из каталога, не переписываешь; механизм оповещения (статус-полоса/бейдж уже несут + состояние — нужен ли отдельный тост) реши сам и аргументируй. После потолочного стопа `resume` + сам по себе прогон не двигает — resume как «продолжить после потолка» не предлагать (описание + `resume` в спеке); различение «свой потолок vs нет кредита» — К-13, на владельце, не решай. + Страница лимитов `GET /usage` остаётся в настройках = S7 (Ф-27) — эту диспозицию не двигай. +- ⚠ **На ЖИВОЙ платформе потолочный стоп сегодня приезжает `failed`** — потребительская половина + шва (П-15 зоны платформы) ещё не построена, PD-113 открыт. В мире моков строй ПО КОНТРАКТУ + (`paused`, `EventCeiling`); от живого стенда правильного поведения не жди и не подгоняй под + него ни код, ни тесты. + +Прогресс во время прогона — по построенному `useRunStream`: пер-главные индикаторы в дереве и +общий прогресс в статус-полосе уже живут на фикстурах (одна доля без названий фаз, ETA из +`eta_seconds` — ратифицировано); доведи их до пути «книга, заведённая формой, переводится» в +мире моков. Внутренности конвейера не раскрывать (§4.1). + +## 5. Задача 4 — библиотека на настоящем масштабе + +- Хвост Ф-12: дерево глав ПЛОСКОЕ — на 2284 разделах нужна группировка (по сотням или иная — + реши сам по референсу и замеру на `/scale`, аргументируй). +- Все статусы `BookStatus` прожиты в дереве и карточке книги — включая `uploading` (виден + параллельным чтением), `parsing`, `rejected` с причиной. Метки состояния — из словаря с веткой + неизвестного; слова, зарезервированные за владельцем (В-3/В-8), НЕ трогать и не укорачивать. +- Ф-42 (потолок keep-alive вкладок) — по замеру: реши сам, чинить или отложить с записью. + +## 6. Задача 5 — находки приёмки S3.7 (все получают диспозицию) + +Ревью приёмки: 12 подтверждённых (1 high) + 16 минорных. Из подтверждённых **9 несущих — список +ниже**; остальные 3 — поправки к записи S3.7 (цена бандла, дрейф ширин `hidden`, счёт «106 из +119»), их носители — запись оркестратора 14.08 в журнале и задача 7. Каждой — диспозиция в +записке-плане (починено с тестом / не воспроизводится с замером / отложено со строкой): + +1. **(high) Дубль подстановки строк:** запись S3.7 ложно клеймила «заполнение вынесено в + `src/i18n/fill.ts`, его импортируют и приложение, и сцены» — `scenes.mjs` держит собственный + инлайн-филлер `say()` с ДРУГОЙ семантикой пропуска, добавленный самой S3.7. Сведи к одному + носителю. +2. Отметка «перечитывание в пути» ставится без старта чтения и глушит следующие кадры ключа + (`useRunStream.ts:146` на момент приёмки). +3. `onResync` не чистит `asked` — отметки прежней эпохи съедают кадр в окне ресинка (`:42`). +4. Клейм «resync не рвёт живой поток» — принять только по живому инструментированному прогону с + задержкой ответа (статика `resetQueries` говорит обратное). +5. Сцена `hidden`: прекондиция «ушли до прихода банка» не ассертится (гонка с синхронным моком), + сторож дифференциальный — симметричная регрессия замера пройдёт; и «таблица вообще нарисована» + не проверяется (два пустых замера равны). +6. Дырка ESLint-гейта строк: вычисленный литерал (`?? 'Word'`, тернарник) в читаемом атрибуте и + литерал в expression-child проходят — живой экземпляр `Showcase.tsx:134`. +7. Perf-оседание может проходить вакуумно: заходы 2–5 ждут 300 мс против конвенции 700. +8. Zoom-ассерт «в ряд» не запрещает стопку (сравнивает left с left, не с right). +9. Кадр `status` не перечитывает список глав — по собственной посылке Ф-49 его счётчики на + границе стадии тоже протухают. + +Минорные (актуальный остаток свода; часть уже закрыта попутно — сверь и диспозиционируй +коротко): свип языка `catalogue.test.ts` не метёт `package.json` и безрасширенный +`scripts/githooks/pre-commit` · гейт вызовов каталога держится на имени локальной переменной +`text` · шапка `ru.ts` ссылается на несуществующий `src/i18n.test.ts` · perf: удлинение запроса +с 3 до 5 символов само занижает мс/клавишу · защёлка флага съёмки — эвристика окна 150 мс +(знать, не чинить без замера). + +`file:line` — ориентиры на момент приёмки, код первичен. Несогласие с находкой = диспозиция с +замером, не молчание (образец: арбитраж 8.1, где права оказалась сессия). + +## 7. Задача 6 — гигиена зонных доков и арбитраж двух чисел + +Стейлы (аудит-свип 14.08), чинить по факту кода: + +- `FRONTEND_PLAN.md:42-43` — «платформа = ноль строк кода» устарело (P5 принята, D39.130); + `:26-30` — таблица §0.1 подаёт строки 95/99–103 как «чего ещё нет» (95 ратифицирована D39.99, + 99/100/103 построены D39.122/131) и шлёт читать `API_CONTRACT_INPUT.md` как живой вход (он под + баннером «исполнено»); `:207-208` — ссылка на удалённый `src/api/types.ts`. +- `STACK_DECISIONS.md:179` — тулчейн платформы «≥1.26.5» → ратифицирован **1.26.6** (D39.130); + `:144` — состав `npm run check` отстал (4 шага против нынешних 7). +- `FRONTEND_SESSION_PROMPT.md:62` — «скелет P0 ждёт приёмки» → P5 принята и залендена. +- `frontend/README.md:63-66` — зонная копия спеки названа «черновик на ратификацию» — она давно + байт-зеркало ратифицированного канона (D39.99/115). + +Арбитраж чисел ЗАМЕРОМ (два носителя врозь, оба претендуют на факт): цена бандла i18n — +запись S3.7 говорит «724130 (+7999)», Ф-35 говорит «723102 (+6971)»; ключей каталога — запись +«147», Ф-35 и живой `ru.ts` — «157» (верно 157). Прогони сборку и счёт ключей на текущем дереве, +живые носители (BACKLOG/план) приведи к замеру; записи хроники НЕ правятся — расхождение назови +попуткой в своей записи. + +## 8. Задача 7 — завести Ф-строки (долги без носителя, найдены свипом 14.08) + +- **RTL-проверка:** триггер «появление I18nProvider» НАСТУПИЛ в S3.7 — строка с честной ценой. +- **Спойлер достаётся в обход:** размытие глифов не прячет текст от поиска по странице (Ctrl+F) + и печати в PDF — продуктовое слово нужно, строка + В-вопрос владельцу. +- **Канвас-замер ширин не знает `lang`:** при двух CJK-лицах один код-пойнт рендерится + по-разному — строка с условием срабатывания. + +Плюс одно закрытие по слову владельца 14.08 — **Ф-52:** поднять `--color-danger` на ступень до +≥3:1 на полотне панели (тот же приём, что у `--color-note` 2.98→3.07 в S3.7 — минимальный сдвиг +тона, не редизайн), пере-прогнать axe, закрыть строку замером. + +## 9. На владельце — НЕ решать и не трогать + +В-7 (плотность интерфейса; держит Ф-54 — обрезку центра на зуме: ЧИСЛО печатай, не чини) · +В-8 (слово состояния в дереве) · В-9 (языки интерфейса) · В-4/Ф-30 (глава без заголовка — «на +экране ничего не менять», ждёт и строку 160 движка) · Ф-38 (вкладка «Замечания») · К-13/Ф-31 +(различение причин паузы) · В-3/В-6 (фразы ступени и паузы) · граница ПТ-33 (добавочные поля +`BankTerm` — форм не выдумывать). Фразы PD-173 — исключение: их пишешь ты (§2), владелец +утверждает по отчёту. Пины `STACK_DECISIONS` не двигать (Ф-28 — измерено и передано, не патчить). + +## 10. Границы скоупа + +Подпись банка и его редактирование — S5. Читалка — S6. Экспорт, настройки (вкл. страницу +лимитов), светлая тема — S7. Живого канала банка нет (строка 169 единого — гейт S5). +**Добавление ГЛАВЫ (§3.10 промта зоны) не строить:** ручки в контракте не существует — кнопка +без действия запрещена нормой зоны; счёл нужным — предложи черновиком правки спеки с пингом, не +кодом. Мок-слой остаётся домом фронта (Ф-29 — триггер сноса не наступил); **опционально**, если +локальный стенд платформы поднимется без боя — smoke живого `POST /books` через dev-прокси +(same-origin, В-кватер; переключатель `TM_PLATFORM` дев-сервера уже существует — S3 чинила его +достижимость) с честным отчётом; это НЕ гейт сдачи, со стендом не воюй, и помни каветы §4 про +П-15: живой стенд местами отстаёт от контракта — эталон формы всегда спека, не стенд. + +## 11. Самопроверка и сдача (мандат, не пожелание) + +- **Ревью исполнением:** каждый экранный путь прогнан живым браузером (скриншот-цикл/сценарии), + каждый новый гейт и тест проверен ЖИВЫМ нарушением, тесты фиксов падают на до-фиксном коде. + Вердикт о поведении браузера без живого прогона = PLAUSIBLE, не факт (D39.129). +- **Адверсариальное ревью диффа — механизмом, author≠reviewer:** независимые ревью-агенты по + диффу с установкой опровергать; субагенты/параллельные агенты для этого **разрешены явно** — + дефолт-запреты харнесса на этот пункт не распространяются. Артефакт — таблица + «находка → диспозиция» в записи журнала; «перечитал внимательно сам» исполнением НЕ считается. +- **Предметные оси ревью этого пака** (вправе добавить свою или аргументированно снять): + (1) контракт — каждая форма данных из спеки, новая потребность = черновик правки спеки, не + фикстура (класс «фикстура выдумала форму» ловился четырежды); (2) доступность — axe на новых + экранах/сценах, полный путь загрузки и шкала потолка проходимы клавиатурой; (3) статусные + ветки — каждая (uploading/parsing/rejected по причинам/404/408/413/409/paused) показана сценой + или кадром, не только тестом. +- **Заявление = команда:** каждое число отчёта — с командой, которой получено; «сделано» без + прогона не писать; чего НЕ сделал/не удалось — отдельным явным списком. +- Гейты не подгонять: порог/проверку не двигать ради зелени; несогласие с гейтом — пинг. +- Сдача: `npm run check` и `npm run check:full` зелёные; новые сцены в батарее; запись в + `frontend/docs/frontend-PROGRESS.md` (механика, замеры, диспозиции всех находок §6, В-вопросы); + BACKLOG обновлён; дерево НЕ коммитить — лендит оркестратор. + +## 12. Канал вопросов + +Непонятно / промт конфликтует с кодом или доками / нужна правка вне `frontend/` → пинг +оркестратору через владельца и запись в зонный журнал; НЕ интерпретация и НЕ правка чужой зоны. +Настоящие развилки эскалируй быстро — это норма, а не слабость. diff --git a/frontend/docs/frontend-PROGRESS.md b/frontend/docs/frontend-PROGRESS.md index 67fb6ab2..20efbfee 100644 --- a/frontend/docs/frontend-PROGRESS.md +++ b/frontend/docs/frontend-PROGRESS.md @@ -116,6 +116,13 @@ > в PDF (продуктовое слово) · канвас-замер не знает `lang` при двух CJK-лицах — завести Ф-строки > S4-сессией. Промты S3/S3.5/S3.7 архивированы с баннерами-исходами (`docs/archive/prompts/FRONTEND_S3*`), > зонные копии сняты. +> +> **Дописка 14.08 (вечер): S4-промт ВЫДАН** — `S4_SESSION_PROMPT.md` (эта папка), запуск одобрен +> владельцем. Его решения того же дня, внесённые в промт: (1) `BookIntake.title` — в спек-правку +> 0.2.3 (ратификация оркестратора как исполнение замечания 12 S3.5, владелец подтвердил); +> (2) продуктовые фразы причин отказа PD-173 пишет S4-сессия сама — по реальному флоу отказов +> платформы, в границах ПТ-33, на утверждение владельцем по отчёту; (3) Ф-52 — `--color-danger` +> осветлить на ступень до ≥3:1 силами S4 (закрыть замером). > **Запись фронт-сессии S3.7, 10.08.** Долги слоя данных закрыты тестами, падающими на до-фиксном > коде (Ф-49…Ф-51), контракт зонной копии бампнут до **0.2.2** (`BankTerm.sense` обязателен),