Files
houseplan-card/docs/reviews/CODE-REVIEW-579-r2.md
T
claude[bot] 1df463d7cf
Проверка (CI) / Классификация изменённых файлов (push) Successful in 29s
Проверка (CI) / Предполёт: документация, провенанс, процесс (push) Failing after 34s
Проверка (CI) / HACS: валидация репозитория (push) Skipped
Проверка (CI) / Hassfest: манифест интеграции (push) Skipped
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Skipped
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Failing after 1m25s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Skipped
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Skipped
Проверка (CI) / Доказательство выполненных проверок (push) Failing after 33s
docs: review document for #579
Issue: #579
User-Visible: no
2026-09-14 20:24:25 +00:00

156 lines
15 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.
# CODE-REVIEW-579-r2
Issue: [#579](https://github.com/Matysh/houseplan-card/issues/579) — «WebView pinch compositor churn»
Материал: `2c7abe7938ded08d63f277269d8b7e52c04e2d4d` (диапазон `origin/dev..HEAD`: продуктовый коммит
`216990e4` + служебные документы ревью + тестовый коммит `2c7abe79`)
Заход: r2 (разбор по дельте от r1, PROCESS.md §2.9)
Блокирующих циклов израсходовано: 1 из 4 (потрачен r1; зелёный вердикт бюджет не тратит, #227)
## Скоуп раунда
r1 (`docs/reviews/CODE-REVIEW-579-r1.md`, коммит `9bae4d28`, вердикт жёлтый на материале
`216990e4`) закрыл всё, кроме одной находки: **M1 — AC4 (матрица day cycle/Glow/room fills/
hatching/фон) не имела тестового доказательства**. Между `216990e4` и `HEAD` лежит ровно один
новый коммит:
```
2c7abe79 test: cover live viewport effects matrix (#579)
```
`git diff 216990e4..HEAD --stat`:
```
demo/smoke_live_pan_coverage.mjs | 83 ++++++++++++++++-
docs/reviews/CODE-REVIEW-579-r1.md | 182 +++++++++++++++++++++++++++++++++++++
```
Второй файл — служебный документ самого r1 (класс C, публикация предыдущего раунда), не
материал для разбора. Единственный содержательный файл дельты — `demo/smoke_live_pan_coverage.mjs`
(класс B). Продуктовый код (`src/live-viewport.ts`, `src/live-interaction-runtime.ts`) не тронут:
автор прямо заявляет это в хендоффе, и `git diff 216990e4..HEAD -- 'src/**'` пуст — проверено.
Дельта локальна: правка только добавляет evidence к уже принятому продуктовому коду, не меняет
контракт поведения, не трогает новую подсистему и по объёму (один тестовый файл) несопоставима с
исходной задачей. Разбор этого раунда ограничен дельтой и AC4, которую она доказывает; остальные
AC унаследованы из r1 (раздел ниже).
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **M1** — AC4 (day cycle off/on × Glow off/on × room fills/hatching/фон) не имеет тестового доказательства | Добавлена исполняемая матрица 2×2 в `demo/smoke_live_pan_coverage.mjs`: `configureEffectMatrix()` (:161) включает/выключает `bg_mode:'daynight'`/`glow_enabled` на существующей fixture с добавленными стенами (`space.walls`, :406) и контрастным `bg_color:'#123456'`; `effects` (:64) снимает `dayCycle`/`glowPools`/`roomFills`/`hatchedWalls`/`customBackground` из живого DOM в `immediateState` и `heldState`; `expected()` (внутри `runPan`, вызывается для `effectsDay{0,1}Glow{0,1}`, :444-448) требует `roomFills>0 && hatchedWalls>0 && customBackground && dayCycle===expected && glowPools соответствует glow` в ОБОИХ кадрах | Я прогнал `node demo/smoke_live_pan_coverage.mjs` на свежесобранном бандле: все 4 строки матрицы (`effectsDay0Glow0…effectsDay1Glow1`) дают `EffectsVisible:true`, и diagnostics показывают реальные значения (`hatchedWalls:1`, `roomFills:1`, `customBackground:true`, `glowPools` 0/1 согласно строке) — не заглушку |
## Унаследовано из r1
Без повторной проверки принято всё, чего дельта не касается — документ
`docs/reviews/CODE-REVIEW-579-r1.md` (коммит `9bae4d28`), выводы получены на дереве материала
`09aab0675828` (SHA продуктового коммита `216990e4`):
- **AC1** (стабильная promotion-сессия), **AC2** (бюджет сохранён), **AC3** (сцена не пропадает в
представленных кадрах, `continuity:screencast`), **AC5** (паритет SVG/HTML ≤1px), **AC6**
(terminal cleanup), **AC7** (существующее покрытие края) — доказаны в r1 unit-тестами, двумя
мутационными свидетелями (`live-pinch-compositor-demoted-on-budget-refresh`,
`live-pinch-compositor-demoted-on-active-lit-commit`) и `continuity:screencast`; продуктовый код,
который они проверяют, в этом раунде не менялся — доказательства не протухли.
- **AC8** (нет регрессии управления) — `smoke_editor_gestures`, `smoke_smooth_zoom`, `smoke_tap_ctx`,
`smoke_long_press_gesture`, все зелёные в r1; ни один из этих смоков не в дельте.
- **AC9** (производительность) и **AC10** (полевой Companion-контроль) — в r1 честно отмечены как
предрелизные/beta-приёмка, не гейт ревью; дельта их не касается.
- Находка **L1** r1 (AC2 без именованного мутанта, Low, снята с записью) — вне дельты, повторно не
поднимаю.
- Трейлеры продуктового коммита `216990e4` (`Issue: #579`, `User-Visible: yes`, оба changelog),
документация (`docs/ARCHITECTURE.md`, `docs/TESTING.md`, `docs/images/screenshots.json`) — приняты
в r1, дельта их не трогает.
## Как проверялось в этом раунде
Дешёвые гейты уже подтверждены зелёным Validate на `2c7abe79`
(https://github.com/Matysh/houseplan-card/actions/runs/34891309797) — `typecheck`/`unit`/`build`
со сверкой бандла перегонять не стал. Диф этого раунда не трогает `src/**`, поэтому
`check-docs.mjs` и `npm run model-invariants` не в скоупе (не требуются самим дифом) и не
перегонялись повторно — вывод r1 по ним не протухает, т.к. они завязаны на `src/**`, а он не менялся.
Дополнительно к зачёту CI лично прогнал:
| Гейт | Команда | Результат |
|---|---|---|
| Свежая сборка (нужна браузерным смокам — Validate на плейн-push heavy-джобы пропускает) | `npm run bundle:sync` | зелёный, `tsc --noEmit` в составе `build` тоже прошёл |
| `smoke-select` по дифу | `node scripts/smoke-select.mjs --base 216990e4 --head HEAD` | «Исполняемого frontend-диффа нет» — ожидаемо, дельта не трогает `src/**`; сам изменённый смок разбираю напрямую, это он и есть предмет дельты |
| Изменённый смок | `node demo/smoke_live_pan_coverage.mjs` | `OK`, все 65 именованных проверок `true`, включая 20 новых (`effectsDay0Glow0…effectsDay1Glow1` × `ImmediateCoverage/HeldCoverage/UsesTemporaryOverflow/TargetStableWhileHeld/EffectsVisible`) |
| Селекторы матрицы против реальной разметки | чтение `src/houseplan-card.ts`, `src/glow-scene.ts`, `src/day-cycle-render.ts`, `src/space-render.ts` | `.wallbody:not(.solid)[fill^="url("]` (`:9549-9551`), `.room.filled` (`:11666`), `.glowlayer .glow-pool` (`glow-scene.ts:606-615`), `.hp-day-cycle-env .hp-day-cycle-bg.active` (`day-cycle-render.ts:32-38`) — все классы существуют в текущем рендере ровно с этими именами, не выдуманы под тест |
| Дисциплина «тест умеет падать» для изменённого файла | `node scripts/mutation-gate.mjs --id=live-pinch-compositor-demoted-on-active-lit-commit` | «заявленный тест покраснел на мутанте», поймано 1/1 — подтверждает, что изменённый смок остался работоспособным guard'ом после правки, не просто не упал по случайности |
**Не прогонял:** полный `demo/smoke_*.mjs` (дельта не в src, `smoke-select` ничего не выбирает,
кроме самого изменённого файла, который прогнан напрямую); `golden:verify` (дельта не трогает
рендер-код, только тестовую fixture, и golden уже зелёный в r1 на продуктовом коммите);
`python -m pytest tests_backend` (диф не касается `custom_components/**/*.py`);
`npm run model-invariants` (диф не трогает геометрию/`layout`/`marker.space`); performance-профиль
(AC9 остаётся предрелизным гейтом, дельта его не касается); мутант
`live-pinch-compositor-demoted-on-budget-refresh` (его guard — `test/live-viewport.test.mjs`, не в
дельте, не перезапускал).
## AC → доказательство в этом раунде
| AC | Доказано | Чем краснеет |
|---|---|---|
| AC4 эффекты не отключаются | `demo/smoke_live_pan_coverage.mjs`, матрица `effectsDay{0,1}Glow{0,1}` (:406-448), я прогнал — зелёный, значения реальные (не 0/false по умолчанию) | `expected()` (внутри `runPan`) красит `*EffectsVisible`, если `roomFills`/`hatchedWalls`/`customBackground` пропадут или `glowPools`/`dayCycle` не совпадут с ожидаемым состоянием строки матрицы; отдельного `MUTANT_DEFINITIONS`-контрпримера на этот конкретный assert нет — это тот же класс пробела, что уже был снят как Low (L1, AC2) в r1 для соседнего assert'а того же файла, не новая находка |
Все остальные AC — см. «Унаследовано из r1».
## Что проверено и корректно
- Матрица переиспользует уже существующую shared-fixture «coverage-room» (`space.rooms`/
`space.settings`, настраивается один раз перед всеми `runPan`-сценариями файла), а не заводит
отдельный конфиг — `configureEffectMatrix` клонирует `card._serverCfg` и правит только
`settings`, не трогая `rooms`/`walls`. Это единственная точка, где дельта расширяет уже
используемый другими (не относящимися к #579) проверками в этом же файле объект: добавление
`space.walls` (:406) поначалу выглядит риском регрессии для более ранних проверок этого же
файла (`flatMouseRightEdge` и т.п., они используют ту же комнату) — прогон подтвердил, что все
45 pre-existing проверок остались зелёными; стены добавлены только для получения штриховки,
сама fixture раньше стен не имела вовсе.
- `_cfgEpoch++` после подмены `_serverCfg` — не изобретённый в тесте API: то же поле и тот же
паттерн инкремента уже используется продуктовым кодом (`src/houseplan-card.ts:3294`) для
инвалидации кеша по конфигу.
- Трейлеры нового коммита корректны: `Issue: #579`, `User-Visible: no` — коммит меняет только
`demo/**` (класс B), продуктовое поведение не меняет, changelog не требуется.
- «Одно число — один источник»: дельта не добавляет и не меняет пользовательски видимую величину
(тестовые ассерты, не UI) — неприменимо.
## Чего не проверял и почему
- Полный набор `demo/smoke_*.mjs` — дельта не в `src/**`, единственный связанный с изменением
смок прогнан напрямую.
- `golden:verify`, `model-invariants`, `pytest tests_backend`, performance-профиль — не в скоупе
дельты (см. таблицу выше), их выводы из r1/из состояния `src/**` не протухли.
- Физический прогон HA Companion (AC10) — вне окружения ревью, остаётся beta-приёмкой (унаследовано
из r1, дельта не меняет это решение).
## Вердикт
Единственная находка r1 (M1, Medium в скоупе) закрыта исполняемым доказательством: селекторы
матрицы проверены чтением реального рендера и совпадают, прогон смока даёт нетривиальные (не
default-false/0) значения по всем 4 строкам, а изменённый файл остаётся рабочим mutation-guard'ом
для уже принятых в r1 находок AC1/AC6. Новых High или Medium находок в дельте не найдено. Зелёный.
---
## Материал раунда
- Ветка: `issue/579-webview-pinch-compositor`, HEAD `2c7abe7938ded08d63f277269d8b7e52c04e2d4d`.
- Продуктовый коммит остаётся `216990e469f2d123a81c03e99cdcb315ed756be0` (не менялся с r1).
- Предыдущий документ: `docs/reviews/CODE-REVIEW-579-r1.md`, коммит `9bae4d283a6156e39912e9c909c7afb7d59fa518`, вердикт `yellow`, High 0, Medium 1.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/579-webview-pinch-compositor`, коммит `2c7abe7938de` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `723a78780b711457d23f95da0e1753e55361211a`
```
git log --all --format='%H %T' | grep 723a78780b71
```
- Тело issue: `4545e4010a0a0d13588d41c73912f543b83f5091653de15127390b77630498a0`
- Вердикт конвейера: `green` · High 0