diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index 2b412700..4021fbbe 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,10 +1,11 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 233, issue: 113. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 234, issue: 114. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| | бета v1.79.0-beta.1 | [SHIP-REVIEW-v1.79.0-beta.1.md](SHIP-REVIEW-v1.79.0-beta.1.md) | пакетное ревью ship · — | ⚪ — | 0 | 0 | — | — | +| #742 | [SPEC-REVIEW-742-r1.md](SPEC-REVIEW-742-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | устаревшее число в AC6 (не блокирует) | `src/houseplan-card.ts` `test/core-file-budget.test.mjs` | | #740 | [SPEC-REVIEW-740-r1.md](SPEC-REVIEW-740-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | устаревший номер строки в «Проблема», п.2 | `src/stairs-view.ts` `src/stairs-editor.ts` `stairs-view.ts` `stairs-editor.ts` `stairs.ts` `large-house.mjs` `matrix.mjs` | | #739 | [SPEC-REVIEW-739-r1.md](SPEC-REVIEW-739-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — | | #737 | [SPEC-REVIEW-737-r1.md](SPEC-REVIEW-737-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — | diff --git a/docs/reviews/SPEC-REVIEW-742-r1.md b/docs/reviews/SPEC-REVIEW-742-r1.md new file mode 100644 index 00000000..23700502 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-742-r1.md @@ -0,0 +1,185 @@ +# SPEC-REVIEW-742-r1 + +Issue: #742 — «Первые кадры после загрузки: комната на кадр-два без заливки +(белая бумага)» · Этап: spec · Заход: r1 · Трек: `track:ask` (предложен +агентом, критерий §5 «перф»; владелец не подтверждал строкой — метка остаётся +предложением) · блокирующих циклов израсходовано 0 из 4. + +## Материал раунда + +ТЗ — тело issue #742, раздел `## ТЗ` (целиком, включая «Итог исследования», +«Доказательства», «Скоуп/Не-скоуп», «Контракт поведения», АС1–АС6, «Принято +предположительно»). Кода нет: ветки `issue/742-*` не существует, задача на +`S4-spec-review` впервые. Факты сверялись с текущим `HEAD` репозитория +(`f3cfb93e947c591a7ce1a73bae2d081e649a2332`), а не только с заявленным в ТЗ +`origin/dev` `b3dd9444`, — между ними лёг #725 (`235f60e6`), который тоже +трогает `src/houseplan-card.ts` на описываемом горячем пути. + +## Скоуп проверки + +1. Обязательные разделы §7.1 — присутствие и соответствие шаблону, принятому + в проекте (сверено с #725, чей ТЗ-ревью зелёный, `legacy`/`docs/reviews`). +2. Однозначность и доказуемость каждого AC1–AC6; falsifiability критериев. +3. Фактическая точность технических утверждений ТЗ против текущего кода: + номера строк, имена функций/констант, поведение валидации бэкенда, + существующие файлы (смоки, реестр мутаций, бюджет ядра). +4. Правило §7.1 о расколе продуктовых/технических вопросов и отсутствии + догадок, записанных как факт. +5. Соответствие `docs/SCOPE.md` (какую строку Core user jobs закрывает) и + отсутствие расширения продукта за пределы контракта К1–К4. +6. Применимость §7.1 про дефект растра/композитинга (#690) — обоснованность + отказа от владельческого подтверждения в GPU-браузере. + +## Как проверялось + +Чтением, не исполнением — на этапе spec кода нет, гейты (`tsc`, `npm test`, +`npm run build`, смоки, мутанты, perf) не прогонялись: прогонять нечего +(`docs/process/REVIEWER.md` «Ревью ТЗ» не требует гейтов; §8 касается кода). +Для каждой технической ссылки ТЗ — прямое чтение файла и строки на HEAD: + +| Утверждение ТЗ | Файл:строка в ТЗ | Проверено на HEAD | Результат | +|---|---|---|---| +| `.room { transition: 0.12s; }` | `src/styles/plan.styles.ts:399–400` | да | совпадает дословно | +| Список фигур комнат — `map()` без ключей | `src/houseplan-card.ts:10931` | да | `space.rooms.filter(...).map((r) => {` на строке 10931, подтверждено; структура не изменилась после #725 | +| Комментарий #525/#534 называет только проёмы, не комнаты | `plan.styles.ts:473–493` | да | комментарий о `.op-leaf`, комнаты не упомянуты — задача на добавление верна | +| `.zoomwrap` слайд 0.18s | `plan.styles.ts:594–595` | да | совпадает | +| `_cycleTick` → `_slideTo`, `reduce` без правила для `.room` | `houseplan-card.ts:1653`, `:1457` | да | подтверждено, `_slideTo` вызывается из `_cycleTick`; `if (reduce) return true;` до переходов | +| `_commitSpace` сбрасывает hover/focus | `houseplan-card.ts:1419–1426` | да | совпадает (со сдвигом на пару строк из-за промежуточных правок, по смыслу то же) | +| `DEFAULT_CUSTOM_FILL = { c: '#607d8b', a: 0.18 }` | `src/logic.ts:1301` | да | совпадает | +| `room.id || #${index}` | `src/clean-floor.ts:32` | да | совпадает (`roomKey = room.id || `#${space.rooms.indexOf(room)}``) | +| `data-id` поиск в `room-fit.ts:131` | `src/room-fit.ts:131` | да | совпадает | +| `ROOM_SCHEMA` требует `id`, но `_TEXT` пропускает пустую строку; уникальность пустых `id` не проверяется | `validation.py:1349, 1241 (переиспользован _TEXT), 1729–1739` | да | `_TEXT = vol.All(str, vol.Length(max=MAX_TEXT))` — не `_NONEMPTY_TEXT`; `_space_geometry_invariants` делает `if not item_id: continue`, что подтверждает пропуск проверки для пустых id | +| `openings-rendered-without-keys` — образец для новых мутантов | `scripts/mutation-registry.mjs:9829` | да | существует, имя `rooms-rendered-without-keys`/`rooms-rendered-without-space-key` свободно (нет коллизий) | +| Потолок `src/houseplan-card.ts` 12896, факт 12 874 | `test/core-file-budget.test.mjs` | частично | потолок 12896 подтверждён; факт на HEAD — **12879** строк (мера теста, `split('\n').length`), не 12874. Расхождение в 5 строк из-за #725, влившегося после сверки ТЗ с `b3dd9444` (на том SHA файл давал 12875 — тоже не точно 12874, на строку больше). Не блокирует: гейт — `cap + band` = 12896 + 50 = **12946** (`coreBudgetViolations`), запас с HEAD 67 строк, заведомо достаточно для правки вида «обернуть map в `keyed(repeat(...))`» (та же правка для проёмов стоила `+1` строку на уже присутствующий импорт `keyed`, который в файле уже есть) | +| Смоки из списка «известные красные песочницы» (AC4) и свидетели (AC1–AC3, perf) существуют | `demo/smoke_*.mjs` | да | все перечисленные файлы на месте: `smoke_summary_dialog_scroll`, `smoke_summary_first_paint`, `smoke_infinite_canvas`, `smoke_live_pan_coverage`, `smoke_space_switch_transitions`, `smoke_daycycle_layer_budget`, `smoke_render_perf`, `smoke_visual_continuity` | +| `docs/USER-GUIDE.ru.md` не описывает переходы при смене этажа | — | да | нет упоминаний мигания/перетекания заливки у переключения вкладок этажей; правка не требует правки гайда | +| `legacy/reviews/v1.75.0/CODE-REVIEW-534-r1.md`, `v1.74.0/SPEC-REVIEW-525-r1.md` существуют | — | да | оба файла на месте | +| `docs/reviews/INDEX.md` по #525/#534/#694/#725/#735 без открытых находок, блокирующих #742 | — | да | #725 закрыт зелёным на обоих этапах (найдена и снята только стилистика — устаревший номер строки, прецедент того же класса, что и находка ниже); #694 закрыт зелёным после r2 | +| Шаблон разделов ТЗ (`### UX · данные · i18n · touch` одной строкой) | §7.1 требует UX / модель данных и миграция / i18n тремя пунктами | — | совпадает с принятым в проекте шаблоном — тот же заголовок использован в принятом (зелёном) ТЗ #725; не находка | + +## Находки + +### Low-1 — устаревшее число в AC6 (не блокирует) + +- **Файл/место:** тело issue #742, таблица AC, строка AC6: «потолок + `src/houseplan-card.ts` в `test/core-file-budget.test.mjs` не поднимается + (12 874 строки, потолок 12 896)». +- **В чём неточность:** на HEAD материала (`f3cfb93e`) файл даёт **12879** + строк мерой теста (`split('\n').length`), не 12874. ТЗ сверялось с + `origin/dev` `b3dd9444` (где факт был 12875, тоже не 12874 — похоже на + ручной подсчёт `wc -l` без +1 на конечный перевод строки), а после той сверки + в `dev` влился #725, прибавивший ещё 4 строки к этому же файлу. +- **Почему не блокирует:** реальный гейт — `cap + band` = 12896 + 50 = 12946 + (`coreBudgetViolations`, `test/core-file-budget.test.mjs:77-91`), а не голый + потолок 12896. Запас от текущего факта (12879) до реального порога — 67 + строк; описанная правка (обернуть `.map()` в `keyed(repeat(...))`, по + образцу проёмов/маркеров из #534) исторически стоила около одной строки на + уже присутствующий импорт. Риска упереться в потолок на этой задаче нет. +- **Что сделать:** автору — поправить число в AC6 на актуальное перед тем, как + брать задачу в работу (к моменту ветвления оно снова сдвинется, если `dev` + уйдёт вперёд; ревьюер кода пересчитает факт на своём SHA независимо от + этого ТЗ). Это редакционная, не содержательная правка — не возвращаю цикл + ради неё одной. + +Других High/Medium не найдено. Класс «догадка, записанная как факт» (§7.1) не +обнаружен: все технические утверждения ТЗ подтверждены либо прямым чтением +кода, либо задокументированными «временными зондами» с результатами (таблица +«Доказательства» в теле issue) — это не единичный случай headless-доказательства +«на слово», а пять независимых экспериментов с конкретными числами кадров и +цветов. + +## Что проверено и корректно + +- **Обязательные разделы §7.1** — все присутствуют: сценарий, что человек + увидит до/после, проблема, скоуп/не-скоуп, контракт поведения (К1–К4), + UX·данные·i18n·touch (единым разделом — принятый в проекте шаблон, сверено с + зелёным #725), граничные случаи, критерии приёмки с доказательством и + oracle, план автотестов, затронутые файлы, производительность и бюджеты, + риски, откат, release-артефакты, «принято предположительно». +- **Каждый AC однозначен и привязан к конкретному, воспроизводимому + наблюдению**: AC1–AC3 называют точный смок-файл, точное действие + (`_pickSpace`, вставка комнаты, смена `custom_fill`), точный oracle + (отсутствие `CSSTransition`, сохранение `data-id`, вычисленный `fill`/ + `fillOpacity`) и то, что делает их красными на `dev` сегодня. AC4 — + регрессионный список + `smoke-select`. AC5 — конкретная команда + (`performance.yml`) и обязательная публикация медиан в issue. AC6 — гейт и + два именованных мутанта с ролью каждого (внутренний/внешний ключ). +- **К1–К4 различимы и непротиворечивы** друг другу и «не-скоупу»: уход + перехода **внутри** этажа (К3) явно не трогается, отдельно от смены этажа + (К1/К2); пограничные случаи (совпадающий `id` на двух этажах, комната без + `id`) описаны и привязаны к конкретным AC. +- **Правило §7.1 о продуктовых/технических вопросах** соблюдено: раздел + «Вопросы владельцу» пуст с обоснованием («поведение на смене этажа уже + решено #525, поведение внутри этажа не меняется»), а все технические развилки + (форма правки, вид ключа, расположение свидетеля, судьба правил #734) вынесены + в «принято предположительно» как право ревьюера их оспорить, а не владельца + решать. Я не нашёл технического решения в этом списке, которое стоило бы + оспаривать: форма (`keyed(space.id, repeat(...))`) — уже проверенный в + проекте паттерн (#534), а не новое изобретение. +- **Отказ от владельческого подтверждения в GPU-браузере (§7.1, #690)** + обоснован по существу: симптом воспроизведён и объяснён на уровне + вычисленных CSS-стилей и `getAnimations()`, растр/композитинг/GPU в цепочке + причины не участвуют (отдельно зафиксировано и проверено экспериментом + «отключение перехода убирает белый кадр»), значит дефект не подпадает под + категорию, которая требует подтверждения в реальном браузере владельцем. +- **Трек `ask`** обоснован корректно по критерию «перф» §5: правка меняет + жизненный цикл узлов на горячем пути, предыдущая аналогичная правка (#525) + дала измеримый регресс, который чинила отдельная задача (#534). Понижение до + `show` — явно оставлено на усмотрение владельца, что соответствует правилу + «повышает любой агент, понижает только владелец». +- **Соответствие `docs/SCOPE.md`:** работа — полировка J1/J2 («что происходит + прямо сейчас», живой план без визуального шума/ложного сигнала) и J6 (план + остаётся верным при естественной работе интерфейса — переключении этажей). + Новых поверхностей, сущностей или продуктовых понятий не вводится, значит + граница скоупа не пересекается. +- **Факты из ТЗ, проверенные против кода** (таблица выше) — все совпадают, + кроме одной устаревшей цифры (Low-1). В частности подтверждена корневая + причина (позиционное переиспользование узла Lit + переход на все свойства + `.room`) и то, что существующий свидетель #525 (`onlyTheSwitchItselfAnimates`) + не ловит именно этот случай по названной в ТЗ причине (разные ветки шаблона + до/после `physicalize`). +- **Release-артефакты**: `User-Visible: yes` заявлен и текст RU/EN для + changelog уже готов в ТЗ; разделы «Не выпущено»/«Unreleased» в обоих + changelog-файлах на месте и пусты, правка впишется без конфликта. + +## Чего не проверял + +- **Любые гейты кода** (`tsc --noEmit`, `npm test`, `npm run build`, смоки, + мутанты, perf-профили, `pytest tests_backend`, инварианты модели) — на + этапе `spec` кода нет, ветки `issue/742-*` не существует, гейты не + прогонялись и не должны: это обязанность код-ревью. +- **Численные пороги AC5** (конкретные медианы `spaceSwitchMs`, + `switchCycleMs`, `longTask.countP95`) — они появятся только на коде; ТЗ + требует их опубликовать, но содержательно сравнить не с чем на этом этапе. + Прогон #735 (упомянут как риск: «`switchCycleMs` станет тёплым, AC5 станет + чувствительнее») тоже не перепроверялся — вне материала этого ревью. +- **Ветвление на реальных пяти шаблонах SVG-фигуры комнаты** (`path`/`path`/ + `polygon`/`polygon`/`rect`, `houseplan-card.ts:11004–11034`) не прогонялось + на конкретной демо-фикстуре, чтобы независимо подтвердить, что первые + комнаты обоих этажей действительно попадают в одну и ту же ветку + (`polygon` по `r.poly`), как утверждает AC1. Это утверждение опирается на + таблицу «Доказательства» автора (пять зафиксированных экспериментов с + числами) — принято без переисполнения, это объём разбора ТЗ, а не кода. +- **Визуальное/ручное наблюдение в браузере** — не требуется этим ТЗ (К4 + + AC4, golden не заказан) и не является гейтом ревью ТЗ. + +## Вердикт + +Зелёный. Единственная находка (Low-1) — редакционная неточность числа, +не влияющая на выполнимость или проверяемость AC6, с объяснением и +рекомендацией автору поправить при входе в разработку; цикл за неё не +открываю. + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `f3cfb93e947c` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `e50939c8bb3f8b4e29a26f71023bb9d69ee511d5` + ``` + git log --all --format='%H %T' | grep e50939c8bb3f + ``` +- Тело issue: `e1e4ad3459d8d681dab722e8636915bb56a64599c10e9c2ede34ef4e031e2456` +- Вердикт конвейера: `green` · High 0 · маршрут `fix`