mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
170 lines
16 KiB
Markdown
170 lines
16 KiB
Markdown
# SPEC-REVIEW-654-r2
|
||
|
||
**Issue:** [#654](https://github.com/Matysh/houseplan-card/issues/654) — «2.5D: цвет бумаги читается `getComputedStyle` в `render()` — на первом кадре все полы «тёмные»; вероятная вспышка Flat→2.5D при холодной загрузке дашборда»
|
||
**Этап:** spec (ревью ТЗ, PROCESS.md §2.4)
|
||
**Заход:** r2 · блокирующих циклов израсходовано (после этого вердикта): 1 из 4 (зелёный вердикт цикла не образует, PROCESS.md §4)
|
||
|
||
## Вердикт
|
||
|
||
**Зелёный.** High: 0 · Medium: 0 · Low: 0.
|
||
|
||
Единственная находка r1 (Medium, в скоупе — «Release-артефакты» не называли обновление
|
||
`docs/ISOMETRIC.md`) закрыта точечной правкой тела issue: в разделе
|
||
«Release-артефакты» добавлена строка, дословно фиксирующая новый инвариант
|
||
жизненного цикла из «Контракта поведения и UX» (первый кадр 2.5D скрыт
|
||
загрузочной поверхностью до готовности ленивого рантайма, включая kiosk;
|
||
terminal failure безопасно возвращает Flat). Делта раунда локальна — единственная
|
||
добавленная строка текста, ни один AC, ни один другой обязательный раздел
|
||
ТЗ не менялись; технические предпосылки и контракт поведения, проверенные в r1
|
||
построчно по `dev`, актуальны без изменений.
|
||
|
||
## Скоуп проверки (делта, PROCESS.md §2.10)
|
||
|
||
Раунд r2 — проверка по дельте, не с нуля: делта локальна (одна строка текста в
|
||
одном разделе, без ребейза, смены контракта или новой подсистемы), поэтому
|
||
разбор ограничен:
|
||
|
||
1. Тем, что делта закрывает ровно ту находку r1, которая её вызвала, и текст
|
||
закрытия точен, а не декларативен.
|
||
2. Тем, что делта не тронула ни один AC1–AC6 и ни один другой обязательный
|
||
раздел §7.1 — то есть выводы r1 по остальному ТЗ остаются в силе без
|
||
повторной построчной проверки кода.
|
||
3. Тем, что новая строка сама по себе не вводит новую неоднозначность,
|
||
недокументированный продуктовый вопрос или расхождение с
|
||
`docs/ISOMETRIC.md`/`docs/USER-GUIDE.ru.md`.
|
||
4. Тем, что материал раунда (тело issue, git-дерево `dev`) корректно
|
||
зафиксирован для следующего раунда/код-ревью.
|
||
|
||
## Как проверялось
|
||
|
||
- Тело issue #654 и его 4 комментария получены `gh issue view 654 --json
|
||
body,comments,labels,state` (MCP `mcp__github__get_issue`/`get_issue_comments`
|
||
недоступны без разрешения пользователя в этой сессии — эквивалентный путь к
|
||
тому же публичному API).
|
||
- Прочитан целиком документ предыдущего раунда `docs/reviews/SPEC-REVIEW-654-r1.md`
|
||
и его блок «Материал раунда» (тело issue `bd46753e…`, дерево `b4eeb2b0…`,
|
||
дерево-коммит `dev@803c0f0e`).
|
||
- Комментарий автора после r1 (`2026-09-26T05:23:38Z`): «Исправлен Medium r1: в
|
||
release-артефакты и затронутую документацию добавлен docs/ISOMETRIC.md с
|
||
контрактом pending-поверхности для обычного View/kiosk и Flat-fallback при
|
||
terminal failure» — сверен с фактическим текущим текстом раздела
|
||
«Release-артефакты» (см. «Закрытие раунда r1» ниже): строка присутствует
|
||
дословно так, как её описал автор, а не только заявлена в комментарии.
|
||
- Пересчитан sha256 нормализованного тела issue тем же алгоритмом, что использует
|
||
конвейер (`scripts/review-doc-guard.mjs` → `normalizeIssueBody`/`issueBodyDigest`:
|
||
`\r\n`→`\n`, обрезка хвостовых пробелов построчно, обрезка финальных пустых
|
||
строк, sha256 UTF-8): текущий хеш —
|
||
`d96095b1978fa9259b2fe1fa89ed256c0a292a59b2850e254cb56b8fb19a4ad1`, что отличается
|
||
от зафиксированного в r1 (`bd46753eac9a5a3b908addb0135b2054eea85c66f89eda4b4f8bdae8d80d78cd`) —
|
||
подтверждает, что тело действительно редактировалось между раундами, а не
|
||
просто переставлена метка.
|
||
- Проверен текущий `docs/ISOMETRIC.md` (`Activation`, строки 10–28) — контракт
|
||
«Activation» пока не описывает pending-поверхность (реализации ещё нет);
|
||
ТЗ корректно ставит его обновление в «Release-артефакты» как будущий коммит
|
||
реализации, а не как факт о сегодняшнем состоянии документа — расхождения нет.
|
||
- Проверен `docs/reviews/INDEX.md` на прецедент того же паттерна «находка r1 →
|
||
точечная правка → r2 зелёный»: #651 (r1 жёлтый Medium за терминологию
|
||
`docs/ISOMETRIC.md`/`USER-GUIDE.ru.md` → r2 зелёный) и #649 (аналогично) — тот
|
||
же класс находки на той же подсистеме закрывался тем же способом.
|
||
- Проверено через `gh api repos/Matysh/houseplan-card/issues/654/timeline`, что
|
||
никакой посторонней активности (доп. правок, вопросов, споров) между r1 и
|
||
комментарием о фиксе не было — только ожидаемая последовательность
|
||
`label(S4)→verdict→fix comment→label(S4)`.
|
||
- Рабочая копия — `git log -1`: `HEAD` = `6297af6701f990e0f067017f2a00107e4b85d8ec`
|
||
(«docs: review document for #654», это же коммит публикации документа r1),
|
||
дерево `968d87dd97df129defb9581ed5cdbb497bad896a`; это тот же `dev`, что был
|
||
проверен в r1 (`803c0f0e`) плюс сам коммит публикации r1-документа — код
|
||
продукта между раундами не менялся, ветка реализации не создана. Гейты §8
|
||
(`tsc`/`npm test`/`npm run build`/`check-docs`) не прогонялись: на этапе
|
||
`spec` предмет ревью — текст ТЗ, диффа исходного кода ещё нет.
|
||
|
||
## Закрытие раунда r1
|
||
|
||
| Находка r1 | Чем закрыта | Где это видно |
|
||
|---|---|---|
|
||
| Medium: «Release-артефакты» не называют обновление `docs/ISOMETRIC.md`, хотя контракт вводит новый инвариант первого кадра/kiosk-pending | В раздел «Release-артефакты» тела issue добавлена строка: «`docs/ISOMETRIC.md`: обновить раздел Activation — до готовности ленивого 2.5D-рантайма промежуточный Flat-план скрыт существующей загрузочной поверхностью, включая kiosk; terminal failure снимает ожидание и оставляет безопасный Flat-fallback» — дословно соответствует рекомендации r1 («план скрыт до готовности ленивого рантайма… это распространяется на kiosk, terminal failure безопасно возвращает Flat») | Тело issue #654, раздел `## ТЗ` → «Release-артефакты», вторая строка (проверено чтением текущего тела issue, не по заявлению автора) |
|
||
|
||
## Унаследовано из r1 (без повторной проверки)
|
||
|
||
Документ `docs/reviews/SPEC-REVIEW-654-r1.md`, материал — `dev@803c0f0eaab3aea1ea9a87215c35b638a679dafb`, тело issue `bd46753eac9a5a3b908addb0135b2054eea85c66f89eda4b4f8bdae8d80d78cd`:
|
||
|
||
- Обязательные разделы §7.1 присутствуют полностью (сценарий и видимое
|
||
изменение, проблема/причины, скоуп/не-скоуп, контракт поведения и UX, модель
|
||
данных/совместимость, i18n, AC1–AC6, план автотестов, риски, «принято
|
||
предположительно», откат, release-артефакты).
|
||
- Однозначность и доказуемость AC1–AC6, включая конкретный вид доказательства
|
||
(unit/AST/smoke) для каждого.
|
||
- Построчная сверка технических предпосылок ТЗ с `dev`: `getComputedStyle` в
|
||
`_renderBody()` (`src/houseplan-card.ts:10701`), `_effectiveProjection()`
|
||
(`:6002-6008`), предзагрузка чанка в `connectedCallback` (`:2568`), поведение
|
||
kiosk в `setConfig()` (`:3095`), безусловный потолок `BOOT_MAX_MS=1200`
|
||
(`:332-337`, `_bootWatch()` `:6356-6373`), чистота `isoLightFloorRooms`
|
||
(`src/iso-materials.ts:91-99`) и существующее unit-покрытие
|
||
(`test/iso-stage6.test.mjs`).
|
||
- Реальность плана автотестов: существующие
|
||
`demo/smoke_isometric_contract.mjs`, `demo/smoke_iso_tiles.mjs`,
|
||
`demo/smoke_iso_theme_walls.mjs`, `demo/smoke_volumetric_setting.mjs`
|
||
(последний подтверждённо без `page.reload()`).
|
||
- Соответствие `docs/SCOPE.md`: задача внутри узкого исключения #89
|
||
(детерминированная 2.5D-презентация той же геометрии), без расширения
|
||
исключения.
|
||
- Отсутствие скрытых продуктовых вопросов владельцу: единственная пограничная
|
||
зона (новое поведение kiosk) уже зафиксирована как решение в контракте.
|
||
- Раздел «Принято предположительно» корректно закрывает найденное техническое
|
||
напряжение `bootveil` vs `BOOT_MAX_MS=1200` как открытый технический выбор
|
||
автора, а не как находку.
|
||
|
||
Эти выводы не переоценивались заново в r2, так как делта раунда (см. выше) их
|
||
не задевает: ни один процитированный файл/строка/AC не менялся между r1 и r2.
|
||
|
||
## Что проверено и корректно (r2)
|
||
|
||
- Строка-фикс находится в правильном разделе, соответствует формулировке из
|
||
«Контракта поведения и UX» п.1 и «Сценария» (уже провалидированных в r1),
|
||
не противоречит текущему `docs/ISOMETRIC.md` (документ пока не содержит этого
|
||
пункта — ожидаемо, так как реализации ещё нет; ТЗ верно ставит это как будущий
|
||
release-артефакт, а не факт).
|
||
- Новых продуктовых вопросов, скрытых предположений или расхождений с
|
||
`docs/USER-GUIDE.ru.md` правка не вносит: новый текст — не пользовательская
|
||
формулировка (нет новой кнопки/индикатора/строки UI, что подтверждено ещё в
|
||
r1 и не изменилось), а описание внутреннего инварианта для канонического
|
||
документа подсистемы.
|
||
- Материал раунда зафиксирован (тело issue, дерево `dev`) для следующего этапа
|
||
(код-ревью), чтобы делта следующего раунда считалась корректно.
|
||
- Прецедент (#651, #649): тот же паттерн «Medium за пропуск
|
||
`docs/ISOMETRIC.md` в Release-артефактах → точечная правка → зелёный r2» уже
|
||
подтверждён дважды на этой же подсистеме — решение согласуется с устоявшейся
|
||
практикой ревью, а не является разовым снисхождением.
|
||
|
||
## Чего не проверял
|
||
|
||
- Повторно не проверял AC1–AC6, обязательные разделы §7.1, построчное
|
||
соответствие технических предпосылок коду `dev` — делта их не касается, весь
|
||
объём унаследован из r1 (см. раздел выше) без повторного исполнения.
|
||
- Не прогонял `tsc`/`npm test`/`npm run build`/`check-docs` — на этапе `spec`
|
||
нет диффа исходного кода (ветка задачи не создана), гейты §8 к этому раунду
|
||
неприменимы; это будет предметом код-ревью после реализации.
|
||
- Не проверял браузерное поведение и не запускал `smoke-select`/`golden` —
|
||
реализации нет, нечего исполнять.
|
||
- Не оценивал заново фактическую длительность загрузки чанка `iso-scene-render`
|
||
относительно `BOOT_MAX_MS` — этот пункт остался открытым техническим выбором
|
||
автора («принято предположительно»), как и в r1, делта его не трогает.
|
||
- Не запрашивал у владельца ничего: технических вопросов к владельцу в делте
|
||
нет, продуктовых открытых вопросов не появилось.
|
||
|
||
---
|
||
|
||
---
|
||
|
||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||
|
||
## Материал раунда
|
||
|
||
- Ветка: `dev`, коммит `6297af6701f9` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||
- Дерево материала: `968d87dd97df129defb9581ed5cdbb497bad896a`
|
||
```
|
||
git log --all --format='%H %T' | grep 968d87dd97df
|
||
```
|
||
- Тело issue: `d96095b1978fa9259b2fe1fa89ed256c0a292a59b2850e254cb56b8fb19a4ad1`
|
||
- Вердикт конвейера: `green` · High 0
|