Files
houseplan-card/docs/reviews/SPEC-REVIEW-231-r1.md
T
2026-08-22 15:18:55 +00:00

193 lines
17 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-231-r1
- **Issue:** #231 — декоративный слой виден поверх заливок комнат
- **ТЗ:** `docs/specs/231-decor-layer-order.md` @ commit `e023adb` (dev)
- **Заход:** r1 · блокирующих циклов израсходовано 0 из 4
- **Вердикт:** жёлтый · High: 0 · Medium: 1 (в скоупе, чинится в этом ТЗ)
## Скоуп ревью
Первый заход, дельты нет — разбор ТЗ целиком: продуктовая рамка (`docs/SCOPE.md`),
обязательные разделы §7.1 PROCESS.md, однозначность и доказуемость каждого AC,
отсутствие догадок, выданных за решение, соответствие терминологии
`docs/USER-GUIDE.ru.md`, согласованность с канонической документацией
подсистемы (`docs/BACKDROP.md`, `docs/DECOR-EDITOR.md`, `docs/CANVAS.md`,
`docs/SUN.md`) и с фактическим кодом.
## Как проверялось
1. Прочитаны `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` §2.4/§7.1/§7.2/§2.9/§2.10.
2. Прочитано тело issue #231 и все 6 комментариев: два уточнения владельца по
целевой позиции слоя, аналитика, вопрос Q1 с default, решение владельца по
Q1, финальный хендофф со ссылкой на ТЗ. Открытых продуктовых вопросов на
момент ревью нет, `blocked` снят.
3. Прочитано ТЗ `docs/specs/231-decor-layer-order.md` целиком.
4. Сверено с фактическим кодом `src/houseplan-card.ts`:
- подтверждён текущий порядок вызова `_renderDecorLayer()` (строка 16584) —
он действительно предшествует рендеру заливок комнат (цикл с 16596),
hover-заливке (16726), обычным тоннелям (16727), Glow-base комнат (16728),
Glow-base тоннелей (16729), `_renderGlowLayer` (16730) и `_renderSunRays`
(16731); стены (16747), символы проёмов (16763) и `devlayer` (16794) идут
ещё позже. Абсолютные номера строк в теле issue (`:16042…:16238`)
разошлись с HEAD (там сейчас `:16584…`), но порядок элементов, который
единственно имеет значение для ТЗ, подтверждается независимо чтением кода
— не является дефектом ТЗ;
- целевая позиция ТЗ (между обоими проходами тоннелей и `_renderGlowLayer`)
соответствует названным строкам 16729/16730;
- проверено, что `.decorlayer .dshape { pointer-events: none; }`
(`src/styles.ts:1235`) и включается только в `.stage.mode-decor` —
утверждение ТЗ §9/§13 «decor не перехватывает tap/click вне редактора
декора» верно независимо от DOM-позиции слоя, не является догадкой;
- проверено `.glow-pools-frame/.glow-pools/.glow-spot { isolation: isolate }`
(`src/styles.ts:678`) — комментарий у кода прямо говорит, что этот блок
изолирует screen-blend от «room data fill, Glow base, paper and
backdrop»; ТЗ §8.2 корректно описывает это как риск и явно требует не
переносить decor молча, если целевая fixture покажет иной результат —
не догадка, а обозначенное предположение (§19.2) с открытым эскейпом;
- подтверждено, что `houseplan-space-card` не рисует decor вообще
(`grep decor src/space-render.ts` — одно упоминание, к теме не относится);
- подтверждено, что изометрический слой (`iso-shadows-svg`/`iso-walls-svg`,
16774–16782) — отдельные `<svg>` после закрытия основного плана, поэтому
перестановка decor внутри основного SVG не меняет его позицию относительно
3D-стен; риск в таблице §16 корректен.
5. Проверено `docs/BACKDROP.md` — «Layer order» там даёт грубую группировку
(«sun / walls / openings / rooms / decor» одним пунктом), которая не
различает internal order и в этом и есть источник бага; ТЗ верно ставит её
актуализацию в release-артефакты (§18).
6. Проверено `docs/DECOR-EDITOR.md` — контракта видимого порядка в View там нет
вообще (только editor-opacity), обновление не требуется, ТЗ не настаивает
(«при необходимости») — согласовано.
7. Проверено `docs/CANVAS.md` («who owns the pointer», «Architectural connection
overlay») и `docs/SUN.md` (four-phase background) — оба документа говорят о
decor на уровне, который порядок внутри плана не меняет; актуализация не
нужна, ТЗ их не трогает — корректно.
8. Проверена регистрация ТЗ в `docs/specs/README.md:71` — присутствует.
9. Проверены существующие смоки: `demo/smoke_decor.mjs`, `demo/smoke_decor_text.mjs`,
`demo/smoke_hide_layers.mjs`, `demo/smoke_backdrop.mjs`, `demo/smoke_glow.mjs`
(`hoverLayerOrder`, строки 244–261) — ни один не проверяет порядок decor
относительно hover-заливки комнаты (см. находку ниже).
10. Прогон гейтов для ревью спецификации не требуется (диапазон правок —
документация ТЗ и issue, продуктовый код не менялся); `git diff --check`
и `node scripts/check-docs.mjs --external`, упомянутые автором в хендоффе,
достаточны для этого этапа и не перепроверялись повторно — они не относятся
к предмету ревью (корректность и доказуемость контракта), а к гигиене
коммита ТЗ.
## Находки
### Medium (в скоупе — чинится в этом же ТЗ)
**M1. Нормативная позиция decor относительно room hover fill не имеет
привязанного AC/доказательства.**
- **Где:** `docs/specs/231-decor-layer-order.md` §8.1 (нормативный порядок
слоёв, пункт «room hover fill» между room fills и opening tunnels) и §14
(AC1–AC8).
- **Суть:** §8.1 явно требует: «любой `[data-hp="decor"]` следует в DOM после
room fill, **hover fill**, обоих видов тоннелей и Glow-base» — hover-заливка
комнаты прямо включена в обязательный нижний контур. Однако ни один AC этого
не проверяет:
- AC1 говорит про «room fill» (заливку), не про hover;
- AC2 перечисляет ровно три вещи, после которых должен идти decor —
«обычный тоннель, Glow-base комнаты и Glow-base тоннель» — hover fill в
списке нет;
- AC3 описывает верхнюю границу (Glow/солнце/стены/символы/устройства), тоже
не про hover.
Значит Goal 5 из §5 («Защитить порядок… тестом, который падает при возврате
старого расположения слоя») в этой конкретной паре (decor vs hover fill) не
реализуется ни одним названным доказательством. Существующий
`demo/smoke_glow.mjs` уже умеет сравнивать DOM-позицию (`hoverLayerOrder`,
строка 260: `hoverFillLayer.compareDocumentPosition(glowLayer)`), но
`decorlayer` в нём не упоминается вовсе — расширить эту же проверку стоит
недорого.
- **Сценарий отказа:** реализация вставляет decor куда-то между room fill и
Glow-base (что удовлетворяет AC1/AC2/AC3 буква в букву — «после обычного
тоннеля» и т.д. формально не нарушены только если decor вставлен после
тоннелей, но ничего не мешает случайно вставить decor **до** hover fill,
например прямо перед строкой рендера hover — тоннели и Glow-base всё ещё идут
после него по факту кода, так что AC2 останется зелёным, а на реальном плане
при наведении на комнату с decor внутри hover-подсветка ляжет поверх
декоративной линии/фигуры, а не под неё, что расходится с §8.1 и остаётся
недоказанным дефектом.
- **Почему не High:** это пробел в покрытии доказательства, а не неверное
продуктовое решение — сам порядок (decor после hover fill) уже прямо задан
диаграммой владельца в теле issue (позиции `:16202` до целевой `:16205→:16206`)
и корректно перенесён в §8.1; чинится добавлением одной фразы в AC2 (или
отдельного AC) и одной строки в план тестов (§15.1/§15.2), без обращения к
владельцу.
- **Что сделать:** явно включить hover fill в формулировку AC2 (например:
«…после hover fill, обычного тоннеля, Glow-base комнаты и Glow-base
тоннеля…») и добавить в §15.2/§15.1 конкретное доказательство — расширение
`smoke_glow.mjs`/`hoverLayerOrder` или отдельный targeted-assert на
`compareDocumentPosition` между `.room-hover-fill-layer` и `.decorlayer`.
## Что проверено и корректно
- Продуктовая рамка: сценарий, персона, «что человек увидит до/после» —
присутствуют, соответствуют `docs/SCOPE.md`/аналитике владельца в issue
(владелец сам отнёс задачу к J1 в комментарии-аналитике; повторно отдельно
в ТЗ можно не обосновывать).
- Все обязательные разделы §7.1 PROCESS.md на месте: сценарий, что увидит
человек, проблема, скоуп/не-скоуп, контракт поведения (§8–§9), UX (§10),
данные/миграция/i18n (§11), AC1–AC8 (кроме отмеченного пробела), план
автотестов (§15), риски (§16), откат (§17), release-артефакты (§18).
- Явный блок «Принятые предположения» (§19) присутствует и корректно помечает
как assumption именно то, что действительно не было продиктовано владельцем
дословно (например, что Glow-base — часть пола, а live Glow/солнце — часть
света) — не выдаёт догадку за факт, ревьюер может её оспорить (не оспариваю:
подтверждается разделением функций `_renderGlowBaseRooms`/`_renderGlowLayer`
в коде).
- Причина бага (§3) точно подтверждена чтением кода — вызов decor
действительно предшествует рендеру комнат.
- Решение владельца по Q1 (без нового флага «под планом», единый порядок для
старого и нового decor) корректно и полностью перенесено в §8.3/§19.1, без
расширения скоупа.
- Открытый технический риск с Glow/CSS isolation (§8.2) не замалчивается: ТЗ
прямо требует не переносить decor поверх live Glow «молча» и возвращать
вопрос владельцу, если fixture покажет иное — правильная эскалация вместо
догадки.
- «Не входит в задачу» (§7) корректно исключает per-object флаг, изменение
геометрии старого декора, любые изменения заливки/Glow/солнца/стен,
добавление decor в статическую карточку и в скрытую изометрию отдельным
рендерером, новый UI/i18n/миграцию.
- Touch/UX (§10): корректно ссылается на `docs/TOUCH-SUPPORT.md`, не создаёт
новых focus targets/жестов; View/kiosk-контракт (блокирующий по
TOUCH-SUPPORT.md) не расширяется и не сужается.
- Данные/миграция/i18n (§11): корректно — рендер-порядок не персистентное
поле, миграция не нужна, что подтверждается отсутствием изменений в
`custom_components/houseplan/validation.py`/типах decor.
- AC5 (documented mutant) явно требует, чтобы smoke падал по существу
(AC1/AC2), а не просто по отсутствию DOM-узла — соответствует духу
`scripts/mutation-gate.mjs` и извлечённому там же уроку про тесты, которые
«ни разу не проверяли на способность падать».
- Golden-план (§15.3) корректно ограничивает принятие эталона отдельным
reviewed Linux-артефактом, Windows — только диагностика; согласуется с
AGENTS.md.
- Регистрация ТЗ в `docs/specs/README.md` на месте.
## Чего не проверял
- Не проверял и не мог проверить визуальный результат Glow-blend на decor в
браузере — эта проверка относится к этапу реализации/код-ревью (targeted
fixture, §8.2), на этапе спецификации нет кода, который можно запустить.
- Не прогонял тяжёлые гейты (typecheck/test/build/golden/smoke) — на этом
этапе продуктовый код не менялся, они не относятся к предмету ревью ТЗ и
будут частью код-ревью.
- Не проверял `docs/TESTING.md` на предмет уже существующей документации
layer-order/mutant contract для decor — в текущей редакции ТЗ такого
описания там нет, и ТЗ (§12) верно относит его актуализацию к зонам
изменений реализации, а не к самой спецификации.
- Не оценивал производительность фактически (нет кода) — только сверил, что
§13 не описывает новых наблюдателей/таймеров/network calls, что достаточно
для стадии ТЗ.
## Резюме
Одна находка Medium в скоупе (M1 — отсутствует доказательство для одной
конкретной, но явно нормативной, границы порядка: decor относительно room
hover fill). High-находок нет. Остальной контракт — порядок слоёв, hide/editor
parity, компат старого decor, touch/UX, данные/i18n, release-артефакты — точен,
проверяем и обоснован чтением кода, а не заявлением автора. Вердикт: жёлтый,
возврат автору на правку ТЗ (добавить hover fill в AC2 и тест-план), без
обращения к владельцу.