From e37285c7562654a1f6945e6f4058f98d431a1cd0 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 6 Sep 2026 12:25:38 +0000 Subject: [PATCH] docs: review document for #474 Issue: #474 User-Visible: no --- docs/reviews/SPEC-REVIEW-474-r2.md | 159 +++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 docs/reviews/SPEC-REVIEW-474-r2.md diff --git a/docs/reviews/SPEC-REVIEW-474-r2.md b/docs/reviews/SPEC-REVIEW-474-r2.md new file mode 100644 index 00000000..fdbfd088 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-474-r2.md @@ -0,0 +1,159 @@ +# SPEC-REVIEW-474-r2 + +- **Issue:** #474 — «Стартовый граф: арт мебели уходит в ленивый чанк» +- **ТЗ:** `docs/specs/474-lazy-furniture-art.md` +- **Предыдущий раунд:** r1, вердикт красный, документ `docs/reviews/SPEC-REVIEW-474-r1.md` + (коммит `54efafbd`), материал на SHA `bb180899ff7932dd81f5a3afc8fe4975ede8df76`. +- **Правка автора:** коммит `ce08dc2c7102d3923e438dbdb10a788ab899e37a` («докс: ТЗ #474 + r1 — редактор передаёт арт рантайму синхронно, golden-ожидание по образцу iso»). +- **SHA материала этого раунда:** `ce08dc2c7102d3923e438dbdb10a788ab899e37a` + (единственный файл в дельте — `docs/specs/474-lazy-furniture-art.md`, + 27 добавлено / 9 удалено; `git diff bb180899..ce08dc2c -- docs/specs/474-lazy-furniture-art.md`). +- **Трек:** полный. Заход r2, блокирующих циклов израсходовано 1 из 4 до этого вердикта. +- **Вердикт: жёлтый** (Medium ниже, в скоупе задачи, без High). + +## Скоуп разбора + +Раунд не первый и дельта строго локальна: один файл, один коммит поверх материала +r1, оба абзаца дельты — прямой ответ на High- и Low-находки r1 (третья точка +готовности арта в редакторе; неточная аналогия в риске golden). Полного разбора +ТЗ заново не делаю — см. «Унаследовано из r1» ниже. Разбираю: (а) закрывает ли +правка обе находки r1 по существу, а не по заявлению; (б) не завела ли сама +правка новую неоднозначность в контракте или AC, которую дельта затрагивает +(изменённые разделы: §2 п.3, §4.2 таблица методов, §4.3 «Запуск и бут», §4.6 +таблица свидетелей, §6 AC7, §6.2 риск golden, §8 затронутые файлы). + +## Как проверялось + +- `git diff bb180899..ce08dc2c -- docs/specs/474-lazy-furniture-art.md` — построчно. +- Каждое новое фактическое утверждение сверено с деревом на `ce08dc2c` (код не + менялся с r1, дерево то же, что и в r1, плюс сам ТЗ): + - `src/editor-runtime-loader.ts` — подтверждён `EditorRuntimeLoaderOptions.install: + (runtime) => void`, вызывается из `_loadWithRetry()` один раз после + конструктора и до `_setState('ready')` — ровно то, на что ссылается новый + текст §4.3 («install в EditorRuntimeLoader редактора»), это не домысел; + - `src/decor-image-editor.ts:271/282` (`renderFurniturePalette`, `preview`) и + `src/houseplan-editor-runtime.ts:4931` (`_renderFurniturePlacementPreview`) — + имена и точки вызова, названные в правке, существуют, номера строк сходятся + с точностью до контекста; + - `demo/golden/harness.mjs:818` (`ensureIsoRuntime`) — реальный прецедент, + на который теперь ссылается исправленный риск в §6.2, вместо снятой ложной + аналогии с языком; + - полный текст ТЗ на `ce08dc2c` прочитан целиком, чтобы дельта (два абзаца) + не проверялась в отрыве от остального контракта — так нашлась находка ниже. +- Гейты (`typecheck`/`test`/`build`/`bundle:budget`) не гонялись: этап spec, + продуктового кода по задаче нет — прогон был бы гейтом на пустом месте, как и + в r1. + +## Закрытие раунда r1 + +| Находка r1 | Чем закрыта | Где это видно | +|---|---|---| +| **High** — единственная точка запуска `ensure()` (приём конфига) не покрывает открытие палитры/призрака в редакторе на конфиге без мебели; AC7 ломается для сценария «первый предмет» | Добавлена третья, синхронная точка готовности: `FurnitureArtRuntime.adopt(art, fingerprint)`, вызываемая из `install` редакторного `EditorRuntimeLoader` при статическом импорте арта редактором. `pending` в редакторе теперь структурно невозможен: `adopt` отрабатывает до первого рендера палитры, не дожидаясь `ensure()`/содержимого конфига | §4.2 (новая строка `adopt` в таблице методов), §4.3 абзац «Редактор — третья точка, синхронная (ревью r1)», AC7 переформулирован под «pending в редакторе не бывает», новый свидетель `furniture-art-editor-adopt-skipped` (§4.6), гард которого — `smoke_furniture` на конфиге без мебели (тот же смок и то же условие `decor=[]`, что и в воспроизведении r1) | +| **Low** — риск §6.2 ссылался на несуществующее ожидание `LANGUAGE_RUNTIME` в harness «как ждёт язык» | Формулировка заменена на реальный прецедент `ensureIsoRuntime`; дополнительно риск усилен требованием, чтобы harness бросал, если в сцене с мебелью `.dfurn` меньше числа предметов конфига (fallback должен быть красным, а не пустым кадром) | §6.2, строка «Golden-сцены с мебелью станут недетерминированными» | + +Обе находки закрыты по существу, не только по заявлению: механизм `adopt` +проверяется реальным контрактом `EditorRuntimeLoader.install`, а не новым +самостоятельным изобретением, и ссылка на `ensureIsoRuntime` — существующий код, +а не повторная неточная аналогия. + +## Унаследовано из r1 + +Без повторной проверки в этом раунде принято всё, чего дельта не касалась +(документ `docs/reviews/SPEC-REVIEW-474-r1.md`, SHA `bb180899`): + +- сценарий и «что человек увидит» (§1.1–1.2), продуктовая рамка и связь с + персоной `docs/SCOPE.md`; +- разрез каталог/арт (§4.1) и единственная точка чтения арта во View + (`houseplan-card.ts` `furnitureGraphic`), перевод магнита `furniture-placement` + на `furnitureSymbol`; +- корректность образца `LanguageRuntime` и нонс-механизма (`hp_retry`) как базы + контракта `FurnitureArtRuntime`; +- `core-file-budget` и заявление «ядро не растёт» (числа не менялись дельтой); +- не-скоуп по `houseplan-space-card` (§3); +- i18n-ключ `toast.furniture_art_load_failed` (не занят, по образцу + `toast.locale_load_failed`); +- нумерация и полнота обязательных разделов §7.1, явный блок предположений (§9), + связь issue↔ТЗ. + +Эти пункты дельта r1→r2 не трогает ни текстуально, ни по содержанию (см. diff +выше — правки только в §2 п.3, §4.2, §4.3, §4.6, AC7, §6.2, §8), поэтому +переносятся без повторной проверки. + +## Находки этого раунда + +### [Medium, в скоупе] Счётчик свидетелей в AC9 и §8 не обновлён после добавления седьмого + +**Файл:** `docs/specs/474-lazy-furniture-art.md`, AC9 (раздел 6) и раздел 8 +(«Затронутые файлы»). + +Правка r1→r2 добавила в таблицу §4.6 новую строку — седьмой свидетель +`furniture-art-editor-adopt-skipped` (гард `install` редактора не вызывает +`adopt`) — не убрав ни одной из прежних шести. Итого в §4.6 сейчас семь строк: +`furniture-art-eager-import`, `furniture-art-fallback-never-settles`, +`furniture-art-no-retry-nonce`, `furniture-art-boot-gate-ignored`, +`furniture-placement-needs-art`, `furniture-art-fingerprint-unchecked`, +`furniture-art-editor-adopt-skipped`. + +При этом: +- AC9: «**Шесть** свидетелей §4.6 в реестре, каждый «поймано 1 из 1»» — число не + правлено этим коммитом (в r1-версии ТЗ, где строк было шесть, формулировка была + верна: r1-документ ревью прямо фиксирует «шесть свидетелей §4.6», см. + `docs/reviews/SPEC-REVIEW-474-r1.md`, «Чего не проверял»); +- §8 «Затронутые файлы»: «`scripts/mutation-gate.mjs` — **шесть** мутантов» — та + же стале число, тот же коммит её не тронул. + +Это не спор о поведении — контракт по существу понятен и AC7 закрыт корректно +(находка выше). Но code review будет сверять реестр мутантов с AC9 буквально +(«шесть, каждый поймано 1 из 1») и рискует не заметить необходимость завести +седьмой мутант `furniture-art-editor-adopt-skipped` в `mutation-gate.mjs`, если +проверять только по счётчику, а не по факту чтения §4.6. AC должен быть +самодостаточным числом, а не требовать сверки с другой таблицей, которая была +изменена позже. + +**Что нужно ТЗ:** заменить «шесть» на «семь» в AC9 и в §8 (`scripts/mutation-gate.mjs` +— семь мутантов), либо явно сослаться на §4.6 без числа. Это правка на месте +(в скоупе задачи, не отдельный issue) — Medium без High даёт жёлтый вердикт. + +## Что проверено и корректно (сверх наследуемого) + +- Новый метод `adopt` в §4.2 не противоречит остальной таблице: идемпотентность + («повторный adopt — no-op»), проверка отпечатка ровно как у `ensure()` — общее + защитное свойство теперь явно распространено на оба входа, и `furniture-art-fingerprint-unchecked` + в §4.6 обновлён («ensure и adopt»), а не оставлен только для одного пути. +- AC7 переформулирован согласованно с текстом §4.3 (то же «pending в редакторе не + бывает», тот же список смоков) — не осталось двух разных описаний одного и + того же сценария в разных разделах. +- §6.2 golden-риск теперь описывает поведение, согласованное с §4.3 (единый + бут-гейт `hpboot`, ожидание встроено, а не отдельная golden-специфичная + реализация) — не вводит второй, конкурирующий механизм ожидания. +- Идентификаторы, на которые ссылается правка (`EditorRuntimeLoaderOptions.install`, + `renderFurniturePalette`, `preview`, `_renderFurniturePlacementPreview`, + `ensureIsoRuntime`), существуют в дереве под теми же именами — утверждение о + поведении не выдано за факт без основания. + +## Чего не проверял + +- Всё, что перечислено в «Унаследовано из r1» — не проверялось повторно, дельта + этих разделов не касается. +- Численные пороги AC1 и реализуемость семи (после исправления счётчика) свидетелей + как мутантов в `scripts/mutation-gate.mjs` — как и в r1, это код, которого пока + нет; переносится на code review. +- Гейты (`typecheck`/`test`/`build`/`bundle:budget`/`golden`/смоки) не гонялись — + этап spec, кода по задаче ещё нет. + +--- + + + +## Материал раунда + +- Ветка: `issue/474-lazy-furniture-art`, коммит `ce08dc2c7102` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `b087deec17ea42c9cd87f4738a90b69f7deba132` + ``` + git log --all --format='%H %T' | grep b087deec17ea + ``` +- ТЗ `docs/specs/474-lazy-furniture-art.md`, блоб `9ac07c2aad7a940779d0fb060e74524fc492afbb` + ``` + git log --all --find-object=9ac07c2aad7a940779d0fb060e74524fc492afbb -- docs/specs/474-lazy-furniture-art.md + ```