textmachine/frontend/docs/archive/S4_SESSION_PROMPT_2026-08-14.md

30 KiB
Raw Blame History

АРХИВ — ОТРАБОТАН. Исполнен девятой фронт-сессией 14.08.2026, принят приёмкой оркестратора №17 (D39.135, лендинг 267aa35, 15.08): контракт 0.2.3 в каноне, фикс-лист ФС-1..12 — запись приёмки в frontend/docs/frontend-PROGRESS.md. ⚠ Пункт §2 «поле после файла = 400» опровергнут кодом платформы и амендирован D39.135 п.2б. Инструкции отсюда не исполнять.

Промт: фронт-сессия S4 — библиотека, загрузка, разбор, прогресс (+ спек-правка 0.2.3)

Выдан оркестратором №16 14.08.2026 по D39.130 («гейт S4 пал»). Запуск — по слову владельца.

0. Какую проблему решаем и что даст твой результат

Продукт — веб-сервис художественного перевода книг: пользователь загружает книгу, запускает перевод, подписывает словарь терминов, читает результат. Фронт строится этапами S0S7; пройдено всё до 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.13.4), §4 жёсткие ограничения, §5.1 поддерживаемость, §7 «как работать». Статусные абзацы там частично исторические — статус этапов только в frontend-PROGRESS.md.
  3. frontend/docs/frontend-PROGRESS.md — шапка «Текущее состояние» + раздел «Решения владельца по продукту» (перевешивает всё в старых промтах) + записи S3.5S3.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.23.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-оседание может проходить вакуумно: заходы 25 ждут 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/99103 как «чего ещё нет» (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/ → пинг оркестратору через владельца и запись в зонный журнал; НЕ интерпретация и НЕ правка чужой зоны. Настоящие развилки эскалируй быстро — это норма, а не слабость.