Files
houseplan-card/docs/reviews/SPEC-REVIEW-474-r2.md
T
2026-09-06 16:10:01 +03:00

160 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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, кода по задаче ещё нет.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `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
```