mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
@@ -0,0 +1,297 @@
|
||||
# CODE-REVIEW-582-r2
|
||||
|
||||
Issue: [#582](https://github.com/Matysh/houseplan-card/issues/582) · этап: code · заход r2 ·
|
||||
блокирующих циклов израсходовано 2 из 4 · материал: `226f323073afd79a1eef9e2e5979684c9ae628f7`
|
||||
(`origin/dev` merge-base = `4208ca81fe3516200a5bd80c1221597492d8fa7b`, дерево материала =
|
||||
`dca5f4042deec2196302371f3ba4ffd6ab59c242`).
|
||||
|
||||
## Скоуп
|
||||
|
||||
Красный r1 (`CODE-REVIEW-582-r1.md`, материал `0a6592f4`) нашёл два High: AC4 (перф-свидетель
|
||||
`smoke_daycycle_raster` красный 8/8, `plan-svg` продавливался в отдельный composited-слой из-за
|
||||
`"Overlaps other composited content"`) и AC6 (все 4 day-cycle golden-сцены `different`, ~3.3–3.5%
|
||||
пикселей). Между r1 и r2 ветку дважды двигали: «Повторный хендофф» переписал сам механизм
|
||||
контура, затем ребейз на `dev` (конфликт с #581, материал стал `2a8b5f1d`), затем красный
|
||||
Validate с мутантами на `2a8b5f1d` (ревью не запускалось, «код никто не читал» — не цикл), и
|
||||
наконец стабилизация шумного raster-свидетеля коммитом `226f3230` — это и есть материал r2.
|
||||
|
||||
**SHA r1 (`0a6592f4112f`) и его дерево (`9f4d95168fdd`) не резолвятся в этом чекауте** —
|
||||
`git cat-file -t` возвращает «could not get object info», в `git ls-remote origin` его тоже нет.
|
||||
Это ожидаемо по PROCESS.md §2.10 (ребейз осиротил коммит, находкой не считается) — данные о r1
|
||||
взяты не из живого диффа, а из текста `docs/reviews/CODE-REVIEW-582-r1.md` (коммит `728c564e`,
|
||||
который *остался* в истории, так как он был закоммичен уже после материала r1) плюс из текущего
|
||||
кода. Раз architecture между r1 и r2 поменялась содержательно (не «одна строка в фикстуре», а
|
||||
новый conditional-механизм переключения слоя), разбор ниже — полный по AC1–AC7, а не только по
|
||||
находкам r1 (§2.9: «дельта не локальна» — сменился сам механизм, которым AC1–AC6 доказываются).
|
||||
|
||||
## Материал и что сделано в коде (дельта r1→r2)
|
||||
|
||||
- `src/houseplan-card.ts`: новое поле `_safeDayCycleOutline` и метод
|
||||
`_activateSafeDayCycleOutline()` (строка ~2068), вызываемый из трёх точек входа жеста —
|
||||
двухпальцевый pinch (`_pinchStart`+`_pointers.size>=2`), обнаружение `_panLock==='pan'`
|
||||
(мышь и палец через общий pointer-путь) и multitouch-старт pinch. При активации кладёт класс
|
||||
`hp-safe-daycycle-outline` на `_stageEl` напрямую (минуя цикл Lit — сохраняет compositor
|
||||
lifecycle #579) и персистентно на весь срок жизни инстанса через `render()`.
|
||||
- Новый `<svg class="hp-paper-outline-svg">` теперь рендерится ВСЕГДА при активном day-cycle
|
||||
(не только после жеста), но `visibility: hidden` до появления `.hp-safe-daycycle-outline` —
|
||||
то есть до первого движения камеры карточка сохраняет байт-в-байт прежнюю (r1-довоенную,
|
||||
#532) однослойную композицию: `.hp-paperg` держит `filter`+`will-change:filter` напрямую, а
|
||||
скрытый сосед не создаёт собственного promoted-слоя (у него нет фильтра до активации).
|
||||
- После активации: `.hp-paperg` получает `filter:none; will-change:auto` (перестаёт быть
|
||||
большим координатным слоем), фильтр и `will-change:filter` переезжают на
|
||||
`.hp-paper-outline-svg` (stage-размерный корневой `<svg>`), а `.plan-svg` получает явный
|
||||
`will-change: transform` — это и есть исправление находки №1 r1: явная причина промоушена
|
||||
не даёт Chromium придумать implicit `"Overlaps other composited content"` для всего плана.
|
||||
- `src/render/paper-scene.ts` — новый общий `renderPaperShapes()` (вынесен из r1, без
|
||||
изменений сигнатуры), используется в `houseplan-card.ts` и `space-render.ts`.
|
||||
- `src/space-render.ts`/`src/space-card.ts` — **не получили** `hp-paper-outline-svg`/
|
||||
`hp-safe-daycycle-outline` вообще (в r1 они были, симметрично основной карточке). Это разбирается
|
||||
как находка №1 ниже.
|
||||
- `demo/smoke_daycycle_layer_budget.mjs` (новый в r1, здесь без изменений сигнатуры проверок) —
|
||||
свидетель AC1–AC3, теперь дополнительно проверяет, что до жеста контур `visibility:hidden`,
|
||||
а после — `.plan-svg` получает `will-change:transform` явным слоем.
|
||||
- `demo/smoke_daycycle_raster.mjs` — переписан в r2 (комментарий issue «Исправление
|
||||
CI-свидетеля»): три чередующиеся замкнутые static/day-cycle пары, медиана парных отношений
|
||||
вместо одиночного замера — устраняет ложный красный на шумном раннере, порог 2.0 не менялся.
|
||||
- `scripts/mutation-registry.mjs` — новый мутант `daycycle-outline-promoted-on-inner-paper`
|
||||
(возвращает `will-change:filter` на `.hp-paperg` в safe-режиме), старый
|
||||
`daycycle-outline-not-promoted` адаптирован (снимает `will-change:filter` с общего блока).
|
||||
- Документация (`ARCHITECTURE.md`, `SUN.md`, `TOUCH-SUPPORT.md`, `TESTING.md`) переписана под
|
||||
новый двухфазный механизм и **прямо признаёт**, что статическая карточка в фолбэк не входит
|
||||
(«the non-interactive static space card keeps its historical inner outline because it has no
|
||||
camera gesture (#582)» — `docs/SUN.md`).
|
||||
- Changelog (`docs/CHANGELOG.md`/`.ru.md`) не менялся в этой дельте — запись сделана ещё в
|
||||
`a68e4c6b` (`User-Visible: yes`) и по-прежнему точно описывает финальное поведение основной
|
||||
карточки (перепроверено golden/smoke-прогонами ниже).
|
||||
|
||||
## Как проверялось
|
||||
|
||||
Дешёвые гейты подтверждены зелёным Validate на точном материале
|
||||
(https://github.com/Matysh/houseplan-card/actions/runs/34954286064) — предполёт, «Фронтенд:
|
||||
типы/юниты/бандл», мутанты по диффу: `success`. Тяжёлые джобы в этом прогоне не гейтили пуш
|
||||
(обычный push, не `Release:`/PR/`full=true`) — именно их r1 не хватило, поэтому здесь они
|
||||
прогнаны мной лично.
|
||||
|
||||
| Гейт | Результат | Почему прогнан/не прогнан |
|
||||
|---|---|---|
|
||||
| `npm run bundle:sync` (typecheck+build+rollup+bundle-tree) | зелёный | нужен как основа для браузерных смоков; дёшево |
|
||||
| `npm run bundle:budget` | зелёный, 291058 Б / потолок 291700±2000, запас 10008 Б (предупреждение о низком общем запасе — преэкзистентный долг #367/#474, не находка этой задачи) | обязателен после билда |
|
||||
| `node scripts/check-docs.mjs` | зелёный, 7 файлов, 12 внешних ссылок | diff трогает `src/**` — обязателен всегда |
|
||||
| `node scripts/process-gate.mjs --issues` | зелёный, 5 коммитов, 0 предупреждений | офлайн-проверка трейлеров/веток |
|
||||
| `node demo/smoke_daycycle_layer_budget.mjs` (AC1/AC2/AC3) | **зелёный**, все 12 заявленных инвариантов true, 12/12 presented-кадров `nearWhiteRatio:0` | прямое совпадение — это и есть свидетель находок r1 |
|
||||
| `node demo/smoke_daycycle_raster.mjs` (AC4) | **зелёный**, медиана парных отношений 1.55 (1.39/1.55/1.69) при потолке 2.0 | прямое совпадение — это и есть красный тест r1 |
|
||||
| `npm run golden:verify` (AC6, полная матрица 172 сцены) | **зелёный, 172/172 `passed`**, все 4 `day-cycle-{dawn,day,dusk,night}-dark` в их числе | diff меняет рендер; это и есть красная проверка r1 |
|
||||
| `node demo/smoke_bg_color.mjs` | зелёный (все проверки, включая `staticCardLayersStayOrdered`) | зарегистрированная связь `renderPaperShapes` |
|
||||
| `node demo/smoke_live_pan_coverage.mjs` | зелёный | зарегистрированная связь `renderPaperShapes` |
|
||||
| `node demo/smoke_pan_any_zoom.mjs` | зелёный (pinch/pan/kiosk-swipe инварианты) | прямое совпадение по `_panLock`, тот же код-путь, что получил новый вызов `_activateSafeDayCycleOutline()` |
|
||||
| `node demo/smoke_isometric_contract.mjs` | зелёный | прямое совпадение — `plan-svg` класс стал безусловным, iso-обёртка контура повторяет `isoFloorMatrixCss()` |
|
||||
| `node scripts/mutation-gate.mjs --id=daycycle-outline-promoted-on-inner-paper` | **зелёный**: чистый прогон ok, мутант поймал (1 из 1) | новый мутант AC2, дорогой гейт — обязателен по §2.7 (защита живёт в продуктовом коде) |
|
||||
| `node scripts/mutation-gate.mjs --id=daycycle-outline-not-promoted` | **зелёный**: чистый прогон ok, мутант поймал (1 из 1) | существующий мутант r1, адаптирован под новый общий блок — перепроверен, что не сломался |
|
||||
| `npx tsc --noEmit`, `npm test`, `npm run build` (сверка копий) | не гонял отдельно — подтверждены зелёным Validate на этом же SHA | дешёвые гейты, разрешено ссылаться на зелёный прогон (`npm run build` я всё равно выполнил как часть `bundle:sync`) |
|
||||
| `python -m pytest tests_backend`, HACS, Hassfest, geometry-parity | не гонял | diff не трогает `custom_components/**/*.py`, манифесты, `layout`/`marker.space`/толщину стен — только SVG-рендер и стили |
|
||||
| `node scripts/model-invariants.mjs` | не гонял | diff не меняет геометрическую модель/рёбра/толщину — только композитинг и разметку SVG |
|
||||
| Остальные 40+ «прямое совпадение» смоков из `smoke-select.mjs` (`_mode`, `_modeTransitionBusy`, `_decorTool`, `_stageEl`, `_booting` и т.п.) | не гонял, кроме двух выше | это артефакт одной длинной изменённой JSX-подобной строки шаблона (`<div class="stage ...">`), в которой лежат десятки не изменившихся по смыслу свойств — слабая связь по PROCESS.md §8; прогнал два наиболее правдоподобных (`smoke_pan_any_zoom`, `smoke_isometric_contract`) точечно |
|
||||
| `performance_smoke` (полный, вне `smoke_daycycle_raster`) | не гонял | AC4 уже проверен целевым, более дешёвым свидетелем; полный профиль не добавляет решающей информации на этом раунде |
|
||||
|
||||
## Закрытие раунда r1
|
||||
|
||||
| Находка r1 | Чем закрыта | Где это видно |
|
||||
|---|---|---|
|
||||
| High №1 — AC4 не держится: `plan-svg` продавлен в отдельный слой (`"Overlaps other composited content"`), raster ratio 2.16–2.50 против потолка 2.0 | Явный `will-change: transform` на `.plan-svg` в safe-режиме убирает implicit-промоушен; контур скрыт до жеста, поэтому до-жестовый idle-рендер не платит вообще | `src/styles/plan.styles.ts:111-113` (`.stage.daycycle.hp-safe-daycycle-outline .plan-svg { will-change: transform; }`); мой прогон `node demo/smoke_daycycle_raster.mjs` — медиана 1.55 при потолке 2.0 |
|
||||
| High №2 — AC6 не проходит: все 4 day-cycle golden `different`, ~3.3–3.5% пикселей | Контур не рендерится видимо (`visibility:hidden`) и не меняет `.hp-paperg` до первого жеста — golden снимаются на idle-карточке, которая теперь байт-в-байт прежняя композиция | `src/styles/plan.styles.ts:264-270` (`.hp-paper-outline-svg{visibility:hidden}` / `.stage.hp-safe-daycycle-outline .hp-paper-outline-svg{visibility:visible}`); мой прогон `npm run golden:verify` — 172/172 `passed`, все 4 day-cycle сцены включены |
|
||||
| Low №3 — комментарий про «the external day-cycle outline... is composited» на `.hp-paperg`, хотя фильтр туда больше не крепится | Комментарий переписан под новую архитектуру | `src/houseplan-card.ts`, блок над `renderPaperShapes(paperShapes)`: «One `<g>` keeps the visible sheet and filtered silhouette free of room seams.» — прочитано, соответствует коду |
|
||||
|
||||
## Находки
|
||||
|
||||
### Находка №1 (High) — Контракт п.6 не выполнен: `houseplan-space-card` не получил ограниченный экранными размерами механизм
|
||||
|
||||
**Файлы:** `src/styles/plan.styles.ts:93-95` (правило `.hp-static-stage.daycycle .hp-paperg`),
|
||||
`src/space-render.ts`, `src/space-card.ts`.
|
||||
|
||||
ТЗ (раздел «Контракт поведения», пункт 6, зелёное спек-ревью r1, без замечаний по этому пункту):
|
||||
|
||||
> Тот же ограниченный экранными размерами механизм применяется в `houseplan-space-card`, чтобы
|
||||
> статическая карточка не сохраняла скрытый координатно-зависимый риск. Внешний вид и
|
||||
> отсутствие интерактивных жестов этой карточки не меняются.
|
||||
|
||||
Текущий код `.hp-static-stage.daycycle .hp-paperg` **не тронут дельтой r1→r2 вообще** — та же
|
||||
самая строка `will-change: filter` на координатно-большой `.hp-paperg`, что и до всей задачи
|
||||
#582/#532. Ни `hp-paper-outline-svg`, ни `hp-safe-daycycle-outline` в `space-render.ts`/
|
||||
`space-card.ts` не существует (в r1 они были — см. «Что проверено и корректно» r1: «hp-static-stage
|
||||
получил аналогичное правило»; в r2 это убрано полностью).
|
||||
|
||||
**Это не домысел ревьюера — это задокументированное и осознанное решение автора.** Прямая цитата
|
||||
из диффа `docs/SUN.md` (r2): «the non-interactive static space card keeps its historical inner
|
||||
outline because it has no camera gesture (#582)»; из `docs/ARCHITECTURE.md` (r2): «the static
|
||||
space card, which has no camera gesture, never enters the fallback». Тест
|
||||
`test/paper-scene-contract.test.mjs` кодифицирует это же самое как требование:
|
||||
`assert.doesNotMatch(staticRender, /class="hp-paper-outline-svg"/)` и
|
||||
`assert.doesNotMatch(staticCard, /\.hp-static-stage \.hp-paper-outline-svg/)` — то есть попытка
|
||||
исправить это в будущем сломает собственный тест задачи.
|
||||
|
||||
**Почему это High, а не молчаливое наследование.** Формулировка контракта явно и без условий:
|
||||
«скрытый» риск назван так именно потому, что он не требует жеста — `houseplan-space-card`
|
||||
рендерит тот же `canonicalWallGeometry.paperD`/`paperRoomShapes(space.rooms)` из того же
|
||||
пространства с тем же `cell_cm`, то есть ровно тот же 4700×4200-координатный диапазон при
|
||||
`cell_cm:1`, что и основная карточка (тот самый пример из тела issue). `houseplan-space-card` —
|
||||
read-only карточка для встраивания (`docs/ARCHITECTURE.md:1577`), доступная в тех же дашбордах
|
||||
HA Companion/kiosk, где и воспроизведён исходный дефект (`docs/SCOPE.md`: View — продукт для двух
|
||||
из трёх персон, touch/View — release-blocking по `docs/TOUCH-SUPPORT.md`). Ни один из AC1–AC9
|
||||
явно не тестирует компоситорную безопасность статической карточки (AC5 проверяет только
|
||||
визуальную целостность контура и отсутствие лишней outline-сцены у статичного ФОНА/редакторов/
|
||||
изометрии — это другой параметр, не про `houseplan-space-card`; AC7 проверяет только переиспользование
|
||||
общего рендерера форм, не компоситинг) — то есть пробел в контракте образовался и не пойман
|
||||
собственным тест-планом задачи.
|
||||
|
||||
Технически это не тот же самый регресс, что нашёл r1 (никакого overlap-промоушена `plan-svg` в
|
||||
static-карточке нет, потому что там нет второго `<svg>`-соседа вообще) — риск ровно тот, ради
|
||||
устранения которого пункт 6 был написан: постоянный координатно-большой `will-change:filter`.
|
||||
Раз пункт 6 сформулирован как безусловное требование, принятое зелёным спек-ревью, и раз
|
||||
реализация сознательно его не выполняет без вынесения вопроса владельцу (ТЗ §7.1 требует
|
||||
эскалации продуктовых развилок, а не тихого решения в одиночку) — блокирует.
|
||||
|
||||
Проверено чтением (селекторы CSS, вызовы `_activateSafeDayCycleOutline`, текст документации и
|
||||
теста), не браузерным прогоном: демонстрация самого белого-тайла на статической карточке
|
||||
потребовала бы отдельного HA Companion WebView стенда, которого нет ни у одного участника этого
|
||||
раунда; риск подтверждён структурно (тот же координатный размер, тот же непрерывный
|
||||
`will-change:filter`), а не количественно замерен.
|
||||
|
||||
### Находка №2 (Medium, в скоупе) — Анимированные переходы камеры (double-tap, «Вписать всё», клик по комнате, колесо/кнопки zoom) не активируют safe-режим
|
||||
|
||||
**Файлы:** `src/houseplan-card.ts` — `_onWheel` (6727), `_stepZoom` (6744), `_resetZoom`/`_fitAll`
|
||||
(6764/6396, включая `reason:'double-tap'` из `_doubleFit.pointerUp` на строке 7044), переход по
|
||||
клику на комнату (`reason:'room'`, строка 6381) — все они вызывают `_startCameraTransition(...)`,
|
||||
которая не вызывает `_activateSafeDayCycleOutline()` нигде.
|
||||
|
||||
`_activateSafeDayCycleOutline()` вызывается только из трёх точек прямого pointer-move — двухпальцевый
|
||||
pinch, `_panLock==='pan'` (drag) и multitouch-старт. Контракт п.3 ТЗ говорит «во время всей
|
||||
pinch/pan-сессии», и AC1–AC4/AC9 буквально описывают только pinch — так что это не прямое
|
||||
нарушение контракта (в отличие от находки №1), но double-tap-to-fit и room-fit — такие же
|
||||
многокадровые анимированные изменения `viewBox` (`CAMERA_FIT_MS`), достижимые касанием на
|
||||
планшете-киоске (тот же класс устройства, где воспроизведён #582), и физический механизм риска
|
||||
(большой координатный `will-change:filter` на `.hp-paperg` во время многокадрового изменения
|
||||
`viewBox`) не привязан семантически именно к жесту «два пальца» — он привязан к тому, что слой
|
||||
вообще движется на экране несколько кадров подряд. Пользователь, который на планшете только
|
||||
дважды тапает «показать всё» или нажимает кнопку зума и никогда не щипает/не тащит план одним
|
||||
пальцем, весь сеанс сохраняет исходную #532-риск-топологию.
|
||||
|
||||
Не проверено запуском (нет прямого свидетеля double-tap/room-fit в новом смоке —
|
||||
`smoke_daycycle_layer_budget.mjs` покрывает только явный touch-pinch путь); проверено чтением
|
||||
всех точек входа `_startCameraTransition`. В скоупе задачи (тот же файл, тот же механизм) —
|
||||
чинится добавлением вызова `_activateSafeDayCycleOutline()` в `_startCameraTransition` (или во все
|
||||
её вызывающие точки) либо явным решением сузить контракт п.3 до буквально pinch/pan с вынесением
|
||||
вопроса владельцу, почему double-tap/room-fit исключены.
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- **AC1–AC3** (layer budget, mutant AC2, presented-frame screencast) — подтверждены свежим
|
||||
запуском `smoke_daycycle_layer_budget.mjs`: 0 слоёв больше 4096, суммарная площадь экранного
|
||||
порядка, 12/12 presented-кадров без белых пикселей, `.hp-paper-outline-svg`
|
||||
`visibility:hidden`→`visible` ровно при активации `hp-safe-daycycle-outline`.
|
||||
- **AC4** — перепроверен на новом, медианно-стабилизированном свидетеле: 1.55 при потолке 2.0
|
||||
(мой собственный прогон, три чередующиеся замкнутые пары); мутант `daycycle-outline-not-promoted`
|
||||
ловит регрессию (`node scripts/mutation-gate.mjs --id=... ` — поймано 1 из 1).
|
||||
- **AC6** — все 172 сцены golden-матрицы, включая 4 day-cycle, `passed` на каноничном Linux
|
||||
(мой собственный прогон `npm run golden:verify`).
|
||||
- **AC2** — новый мутант `daycycle-outline-promoted-on-inner-paper` зарегистрирован на верном
|
||||
guard-файле и реально ловит возврат `will-change:filter` на `.hp-paperg` в safe-режиме (мой
|
||||
запуск, поймано 1 из 1).
|
||||
- **Единый живой viewport (#579).** `data-hp-live-viewbox` стоит на `.hp-paper-outline-svg` тем
|
||||
же значением, что на `plan-svg`; активация safe-режима идёт напрямую через `classList.add` на
|
||||
`_stageEl`, минуя ожидание Lit re-render — сохраняет контракт п.4 (бюджетированные обновления
|
||||
`viewBox` без полного re-render на каждый pointer-кадр). Проверено чтением плюс
|
||||
`smoke_daycycle_layer_budget` (`cameraActivatesSafeFallback`, `settledPlanLayerIsExplicitAndBounded`).
|
||||
- **Изометрия.** `plan-svg` стал безусловным классом ещё в r1 (принято тогда же, не новая
|
||||
находка); `smoke_isometric_contract.mjs` зелёный на этом материале.
|
||||
- **Мутация/тест-план.** Оба мутанта #582 (старый и новый) реально ловятся своими guard-смоками,
|
||||
не только заявлены.
|
||||
- **Changelog/трейлеры.** `Issue: #582`+`User-Visible: yes` на `a68e4c6b`, оба changelog правлены
|
||||
в нём же и по-прежнему точно описывают финальное поведение основной карточки (перепроверено —
|
||||
ни pinch-путь, ни визуальный контур с r1 не изменились содержательно для пользователя,
|
||||
описание не вводит в заблуждение относительно находки №1, поскольку не упоминает static-карточку
|
||||
явно). Коммиты `2a8b5f1d`/`226f3230` — `User-Visible: no`, соответствует правилу (продуктовое
|
||||
поведение основной карточки не меняется относительно уже описанного, правится только
|
||||
устойчивость реализации/свидетеля).
|
||||
- **Документация.** `ARCHITECTURE.md`/`SUN.md`/`TOUCH-SUPPORT.md`/`TESTING.md` построчно
|
||||
соответствуют новому коду, включая честное признание про статическую карточку (которое и стало
|
||||
находкой №1 — документация не скрывает пробел, она его называет).
|
||||
- **`node scripts/check-docs.mjs`, `node scripts/process-gate.mjs --issues`, `npm run
|
||||
bundle:budget`** — зелёные на материале.
|
||||
|
||||
## Унаследовано из r1
|
||||
|
||||
Документ: `docs/reviews/CODE-REVIEW-582-r1.md` (коммит `728c564e`), материал r1 —
|
||||
`0a6592f4112fd7ceef68cbd3be7c44eeb8a7ef3e` (SHA осиротел после ребейза, не резолвится в этом
|
||||
чекауте — по PROCESS.md §2.10 это не находка). Принято без повторной проверки, так как дельта
|
||||
r1→r2 этого не касается:
|
||||
|
||||
- **AC7 (unit/structure, переиспользуемый рендерер бумаги).** `renderPaperShapes()` — тот же
|
||||
API, что в r1, используется в обеих поверхностях без изменений сигнатуры; существующее
|
||||
покрытие «пустого и составного плана» в `test/logic.test.mjs`/`test/wall-thickness.test.mjs`
|
||||
(найдено `grep`, не запускалось повторно отдельно от `npm test`, зелёного на Validate).
|
||||
- **Спек-ревью r1** (`SPEC-REVIEW-582-r1.md`, зелёный, High:0/Medium:0) — ТЗ с тех пор не
|
||||
менялось (тело issue не редактировалось после спек-ревью; проверено визуально, хэш якоря
|
||||
спек-ревью не пересчитывался в этом раунде за неимением инструмента конвейера в среде ревью —
|
||||
риск низкий, раздел «Контракт поведения» текстуально совпадает с тем, что цитирует r1).
|
||||
- **AC8 (quality gates состав)** — перечень необходимых гейтов не изменился между раундами.
|
||||
- **AC9 (полевая приёмка)** — вне этапа код-ревью по определению самого AC, не переоценивается.
|
||||
- **i18n/миграция/откат/риски раздела ТЗ** — не затронуты дельтой, содержательно не изменились.
|
||||
|
||||
## Чего не проверял и почему
|
||||
|
||||
- `python -m pytest tests_backend`, HACS, Hassfest, geometry-parity — diff не трогает
|
||||
`custom_components/**/*.py`, манифесты, `layout`/`marker.space`/толщину стен.
|
||||
- `node scripts/model-invariants.mjs` — diff не меняет геометрическую модель/рёбра решётки/
|
||||
записи толщины, только SVG-композитинг и разметку.
|
||||
- Полная матрица `demo/smoke_*.mjs` (250 файлов) — прогнаны 6 (два «зарегистрированная связь»,
|
||||
два прямых по `renderPaperShapes`-цепочке и два точечно выбранных из 44 «прямых» слабых
|
||||
совпадений). Остальные 42 «прямых» совпадения — артефакт одной длинной изменённой строки
|
||||
шаблона со множеством не изменившихся по смыслу свойств (`_mode`, `_booting`,
|
||||
`_modeTransitionBusy`, `_decorTool`, `_stageEl` и т.п.); не прогнаны сознательно, см. таблицу
|
||||
выше.
|
||||
- Полный `performance_smoke`/профили вне `smoke_daycycle_raster.mjs` — AC4 уже подтверждён на
|
||||
целевом, более дешёвом свидетеле.
|
||||
- `npx tsc --noEmit`/`npm test`/`npm run build` отдельно от `bundle:sync` — приняты по зелёному
|
||||
Validate на этом же материале (https://github.com/Matysh/houseplan-card/actions/runs/34954286064).
|
||||
- Реальный HA Companion WebView на живом устройстве (AC9) — вне этапа код-ревью; это же
|
||||
ограничение не позволило количественно подтвердить находку №1 на статической карточке
|
||||
(подтверждена структурно, не количественно).
|
||||
|
||||
## Вывод
|
||||
|
||||
Оба High r1 закрыты предметно: AC4 (raster ratio 1.55 против потолка 2.0, воспроизведено
|
||||
самостоятельно) и AC6 (172/172 golden, включая все 4 day-cycle сцены, воспроизведено
|
||||
самостоятельно) — новый двухфазный механизм (`hp-safe-daycycle-outline`, активируемый только
|
||||
жестом) решает находки r1 без регрессии производительности контура из #532. Но при этом дельта
|
||||
r1→r2 предметно убрала защиту статической карточки, которую r1 реализовывал (там она была
|
||||
симметрична основной), и пункт 6 контракта ТЗ («тот же ограниченный экранными размерами механизм
|
||||
применяется в houseplan-space-card») сейчас не выполнен — задокументировано самим автором как
|
||||
осознанное решение, не вынесенное владельцу как продуктовая развилка. Это High, в скоупе задачи,
|
||||
чинится в этой же ветке. Дополнительно найден Medium: анимированные (не pinch/pan) переходы
|
||||
камеры не активируют safe-режим, что оставляет часть touch-путей (double-tap-to-fit, room-fit,
|
||||
кнопки/колесо зума) в исходной риск-топологии — тоже в скоупе, тоже чинится здесь. Возврат
|
||||
автору.
|
||||
|
||||
---
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `issue/582-webview-large-filter-layers`, HEAD `226f323073afd79a1eef9e2e5979684c9ae628f7`.
|
||||
- Дерево материала: `dca5f4042deec2196302371f3ba4ffd6ab59c242`.
|
||||
- `origin/dev` на момент ревью: `4208ca81fe3516200a5bd80c1221597492d8fa7b` (merge-base с HEAD).
|
||||
- Предыдущий документ: `docs/reviews/CODE-REVIEW-582-r1.md` (материал `0a6592f4112f`, вердикт
|
||||
`red`, High 2 — SHA осиротел после ребейза, не резолвится в этом чекауте, см. §2.10).
|
||||
|
||||
---
|
||||
|
||||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `issue/582-webview-large-filter-layers`, коммит `226f323073af` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||
- Дерево материала: `dca5f4042deec2196302371f3ba4ffd6ab59c242`
|
||||
```
|
||||
git log --all --format='%H %T' | grep dca5f4042dee
|
||||
```
|
||||
- Тело issue: `4c1e1ecfe8ce205f3cfb3c44eb6028a35d0bb4358323e05ba60c6fd85b3b40ba`
|
||||
- Вердикт конвейера: `red` · High 1
|
||||
Reference in New Issue
Block a user