21 KiB
CODE-REVIEW-744-r3
Issue: #744 · Трек: ask · Заход: r3 · блокирующих циклов израсходовано 1 из 4
Материал: 0f16312e8ff104bfc72942ca32dc1e452512cafa (ветка issue/744-floor-geometry-key,
поверх dev 8a3bf71e; шесть коммитов от merge-base: 5263403c продукт (К1–К5),
92f57c49 фикс гонки с тостом в смоке — оба уже разобраны в r1/r2 — плюс
ede6d750/dac52855/e7aa1544 (docs-коммиты, публикующие CODE-REVIEW-744-r1.md,
CODE-REVIEW-744-r2.md и обновление INDEX.md) и новый 0f16312e (единственная
содержательная правка этого раунда).
Скоуп
r2 был зелёным на материале d10285b0 (дерево bbc1bb8a2529…). После зелёного
r2 dev ушёл вперёд на 5 коммитов (комментарий автора, 2026-10-01T18:38:23Z),
ветку пересадили на dev 8a3bf71e, и точный ребейзнутый кандидат 6b3dd77b
покраснел на Validate: initial View вырос с 300 954 Б (до #744) до 301 097 Б
gzip — на 31 Б выше абсолютной стены INITIAL_VIEW_GZIP_BUDGET = 301 066 в
scripts/bundle-budget.mjs. Комментарий над стеной требует оплачивать такой
рост выносом кода в ленивый граф, а не поднятием потолка. Автор добавил один
коммит 0f16312e поверх ветки (обычный push, без force) — это и есть дельта
раунда.
Старые SHA (d10285b0, 6b3dd77b, 8c639b15 и материал r1 8c639b15…) не
резолвятся локально — обычное дело после ребейза (§2.10), не находка. Дельта
восстановлена по трём независимым источникам, которые сходятся: (а) хронология
и формулировки комментариев issue, (б) git log --format='%H %ad %s' на текущих
коммитах — таймстемпы коммитов 92f57c49 (16:30 UTC) и 0f16312e (20:35 UTC)
совпадают с временем соответствующих комментариев «Починил»/«Красный кандидат…
Починил» с точностью до нескольких минут, (в) git diff origin/dev...HEAD --stat
даёт ровно тот список файлов, который описывают r1/r2, плюс один новый файл
src/space-card.ts (+4/−2 строки) — больше никаких файлов дельта не трогает.
Задача по-прежнему track: ask, критерий §5 «перф» — не переоценивается здесь,
не изменился с r1. route: fix.
Дельта r2 → r3 — коммит 0f16312e
perf(bundle): load the space-card GUI editor lazily to keep #744 under the initial View budget (#744)
src/space-card.ts | 6 ++++--
src/space-card.ts статически импортировал свой Lovelace GUI config-редактор
(./space-editor, элемент houseplan-space-card-editor) — каждый View-фрейм
платил за форму, которую открывает только редактор дашборда. Правка убирает
import './space-editor' и делает getConfigElement() асинхронным:
public static async getConfigElement() {
await import('./space-editor');
return document.createElement('houseplan-space-card-editor');
}
Это буквально тот же контракт, что уже использует houseplan-card.getConfigElement()
(src/houseplan-card.ts:3060, без обёртки-лоадера — Lovelace сам ждёт промис).
Трейлеры коммита: Issue: #744, User-Visible: no — верно: это внутренний
механизм загрузки конфигуратора карточки на дашборде, а не видимое поведение
Plan/Devices/View (docs/SCOPE.md: редакторы — admin-only поверхность).
Как проверялось
| Гейт | Статус | Как |
|---|---|---|
npx tsc --noEmit, npm test, npm run build + bundle-policy --verify |
не перегонял | Validate на точном SHA материала зелёный: https://github.com/Matysh/houseplan-card/actions/runs/36925575616 (дано в задании ревью, не со слов автора) |
| Структурная корректность нового ленивого чанка | прогнал сам | npm run bundle:sync (build → dist, копия в gitignored demo/srv/assets, рабочую копию dist/ после этого вернул git checkout -- dist/ + git clean -fd dist/ — трекнутый бандл не тронут). Манифест: houseplan-assets/space-editor-BN7nDv_N.js, 1122 Б gzip, imports: ['houseplan-card-*.js'], dynamicImports: [] — ожидаемый отдельный чанк, зависимости (lit/i18n/space-geometry) остаются в общем графе |
Работает ли лениво загруженный редактор houseplan-space-card на самом деле |
прогнал сам, исполнением | Отдельный Playwright-зонд (вне репозитория, /tmp), по образцу demo/smoke_lazy_editor_chunk.mjs: customElements.get('houseplan-space-card-editor') не определён до вызова; HouseplanSpaceCard.getConfigElement() возвращает Promise, резолвится в элемент houseplan-space-card-editor; сетевой запрос чанка space-editor-*.js — ровно один; смонтированный редактор после setConfig/updateComplete рендерит рабочую <ha-form>. Это прямой ответ на «работает ли оно вообще» для кода, у которого нет committed-регрессионного теста (см. «Чего не проверял») |
node scripts/mutation-gate.mjs --check |
прогнал сам | exit 0; оба мутанта #744 (floor-geometry-key-global-epoch, floor-geometry-key-ignores-content) на месте и привязаны к node demo/smoke_floor_geometry_cache.mjs; browser guards: 209/200 — WARN, не отказ (см. «Находки», пункт о расхождении счётчика) |
node demo/smoke_floor_geometry_cache.mjs |
прогнал сам | все проверки true, включая AC1 (ac1GardenVisitBuildsNo* — 0), AC2а/б/в (ac2a…EqualsAFreshCard, ac2bRoomAreaEqualsAFreshCard, ac2cSettledFrameEqualsAFreshCard) — зелёный на точном материале, не только со слов автора |
node scripts/smoke-select.mjs --base origin/dev --head HEAD |
прогнал сам | 20 прямых совпадений (все — существующие свидетели К1–К5 и _cleanFloorCache/spaceModels/_saveConfig, уже учтены AC1/AC2/AC5 и разобраны r1/r2), 41 слабая связь на общий символ _curSpaceCfg (решение ревьюера — не прогонять: не затрагивает дельту этого раунда, src/space-card.ts не читает _curSpaceCfg) |
npm run gate:small, полный smoke-select, golden, Full Performance, pytest tests_backend, npm run invariants |
не перегонял | не затронуты дельтой (src/space-card.ts — не геометрия, не Python, не рендер плана); гейты, относящиеся к К1–К5/AC1–AC5, уже прогнаны и подтверждены в r1/r2 на коде, который не менялся |
Закрытие раунда r2
r2 был зелёным без находок (0 High, 0 Medium) — закрывать нечего. Единственная
находка всей задачи (Medium r1, AC4 на устаревшей базе) была закрыта ещё до r2
и подтверждена исполнением в r2 (gh run view 36905760140); код с тех пор не
менялся, пересматривать нечего.
Унаследовано из r2 (и, транзитивно, из r1)
Продуктовый и тестовый код К1–К5 (src/floor-geometry-key.ts,
src/clean-floor.ts, src/stairs-editor.ts, src/houseplan-editor-runtime.ts,
src/houseplan-card.ts, demo/smoke_floor_geometry_cache.mjs,
demo/benchmark_large_house.mjs, demo/performance/card-contract.mjs,
scripts/mutation-registry.mjs, test/clean-floor.test.mjs) не менялся между
r2 и r3 — дельта раунда ограничена одним файлом (src/space-card.ts),
подтверждено git diff origin/dev...HEAD --stat. Принято без повторного
построчного разбора, с документом и материалом r2
(docs/reviews/CODE-REVIEW-744-r2.md, материал d10285b0794d…):
- Архитектура ключа этажа (
contentFingerprint, память на эпоху и на пару объектов записи), её использование в четырёх кэшах (физические тела, оболочка стен, внутренние контуры, чистый пол) и resize-preview со своим ключом. - Контракт К1–К5 и защита против «устаревшего кадра» независимым oracle в смоке — сам смок перепрогнан мной заново в этом раунде (см. таблицу выше) и зелёный на точном материале, так что это не голое наследование, а подтверждённое исполнением.
StairsEditor.writeбольше не чистит_cleanFloorCacheдругих этажей.- Сторож #735 видит
_wallUnionPool/_innerContourCache. - Два мутанта в
scripts/mutation-registry.mjs, привязка к смоку — перепроверено мнойmutation-gate --checkв этом раунде, оба на месте. - AC4 — Full Performance против актуальной на тот момент базы
dev, закрыт в r1→r2, исполнение проверено r2 напрямую по API/логам (не со слов автора); код с тех пор не менялся — транзитивно валидно. - Трейлеры и CHANGELOG RU/EN на продуктовом коммите
5263403c— текст дословно совпадает с ТЗ, оба файла правлены в одном коммите.
Находки
Нет High. Нет Medium в скоупе.
Одно наблюдение, не находка (не введено этим материалом и не блокирует
ничего): счётчик в docs/testing-notes/mutation-browser-guards.md — строка
«Custom-element and HA browser lifecycle» и «Total» утверждают 92/207, а
mutation-gate --check на текущем дереве печатает фактические 209 browser
guards (WARN выше ориентира 200, не отказ). Причина — коммит d709ea11
(#740, смежная задача, уже на dev до ребейза #744) добавил мутант
stairs-view-tread-lines в список, но не поднял счётчик категории/Total в том
же диффе (git show d709ea11 -- docs/testing-notes/mutation-browser-guards.md:
список +1 строка, цифры в таблице не менялись). #744 корректно прибавил свои
+2 к числу, которое уже было стартовой точкой её собственного ребейза
(90→92, 205→207 в комментарии автора 2026-10-01T17:21:04Z — арифметически
верно относительно базы, которую видел автор в тот момент), так что дрейф не
вносится этим материалом. Гейт не считает по тексту таблицы — он печатает
фактическое число (mutation-gate.mjs), поэтому это не механизм защиты,
который можно было бы тихо сломать, а чисто документационная неточность чужой
задачи. Слишком мелко для отдельного issue (одна строка комментария в таблице,
не влияет ни на один гейт); можно поправить любой следующей правкой файла.
Что проверено и корректно
- Единственная содержательная правка раунда (
0f16312e,src/space-card.ts) решает именно то, что заявлено: initial View гейт — красный повод, лазаньый выносspace-editor— стандартный, уже проверенный в проде паттерн (идентиченhouseplan-card.getConfigElement()). - Структурная корректность подтверждена манифестом (
space-editor-*.jsкак отдельный чанк с ожидаемым размером и графом зависимостей) и поведенчески — прямым исполнением (зонд в этом раунде): элемент не определён до интента, чанк грузится ровно один раз, резолвится форма, которая реально рендерится. Это закрывает отсутствие committed-теста для этого пути фактическим прогоном, а не доверием к комментарию автора («разовая проверка Playwright»). - Трейлеры коммита верны (
Issue: #744,User-Visible: no— изменение не видимо в Plan/Devices/View, только в конфигураторе карточки на дашборде). - Бюджет: initial View 301 097 → 300 489 Б gzip (−608 Б), запас до стены
577 Б; это число видно один раз — в сообщении коммита — источник один
(
scripts/bundle-budget.mjsпри сборке), UI его не отображает, второго источника для сверки «одно число — один источник» нет. - AC1–AC5 К1–К5 ТЗ #744 (унаследовано из r1/r2, частично перепроверено исполнением в этом раунде — см. выше) остаются выполненными; код, который их реализует, не менялся в этом раунде.
mutation-gate --checkзелёный (exit 0), оба мутанта задачи на месте и привязаны к существующему смоку.
Чего не проверял
- Дешёвые гейты
npx tsc --noEmit/npm test/npm run build+bundle-policy --verifyцеликом не перегонял — Validate на точном SHA материала подтверждён зелёным в задании ревью (https://github.com/Matysh/houseplan-card/actions/runs/36925575616);npm run buildтем не менее выполнил сам при сборке зонда (см. таблицу), так что построение бандла на этом дереве подтверждено дважды независимо. - Полный
smoke-select(64/65 на материале r1/r2) и browser-смоки/golden всех шардов не перегонял — дельта (src/space-card.ts) их не касается, а К1–К5 не менялись; свежий целевой смок (smoke_floor_geometry_cache.mjs) и профильныйmutation-gate --checkя прогнал сам. - Full Performance не перезапускал — AC4 закрыт в r1/r2 исполнением на базе,
являющейся предком текущего
dev; дельта этого раунда (src/space-card.ts) не геометрия и не горячий путь переключения этажа, performance-значимых изменений не вносит (само по себе уменьшение initial View — не риск дляswitchCycleMs/spaceSwitchMs, это другой, панельный путь загрузки). npm run invariants— не запускал, геометрия в этом раунде не менялась.pytest tests_backend/ HA harness — не запускал, Python не затронут ни в одном коммите материала.- Golden (
ci:golden) — не перегонял; К5 («кадр не меняется») доказан в r1/r2 смоком и не затронут дельтойsrc/space-card.ts, которая не рисует план. - Автоматического регрессионного смока специально на лениво загружаемый
редактор
houseplan-space-cardв репозитории нет (ни до, ни после этого коммита — уhouseplan-space-card-editorвообще никогда не было автотеста, в отличие отdemo/smoke_lazy_editor_chunk.mjsу главной карточки). Это не regressия от этого коммита (покрытие было нулевым и раньше), и я закрыл пробел исполнением в этом раунде (см. таблицу гейтов) — не Medium: работоспособность доказана, только не оставлена автоматическим стражем на будущее. Не блокирует; кандидат на отдельную мелкую задачу, не на находку этого ревью. - Английскую версию
docs/USER-GUIDE.ru.md/EN — не проверял: задача не меняет видимое поведение (User-Visible: noна правке раунда,yesна основном коммите уже сверен в r1 с ТЗ).
Вердикт
Зелёный. Дельта раунда — один коммит (0f16312e, лениво загружаемый конфигуратор
space-card ради initial View budget), прочитан целиком, структурно и
поведенчески подтверждён исполнением (манифест чанка + Playwright-зонд в этом
раунде), трейлеры верны. Находок нет; одно документационное наблюдение вне
материала этой задачи, не блокирует. Бюджет циклов остаётся израсходованным на
1 из 4 (унаследовано из r1).
Материал раунда
- Ветка:
issue/744-floor-geometry-key, коммит0f16312e8ff104bfc72942ca32dc1e452512cafa. git rev-parse HEADна момент ревью:0f16312e8ff104bfc72942ca32dc1e452512cafa.- Вердикт:
green· High 0 · Medium 0 · маршрутfix.
Материал раунда
- Ветка:
issue/744-floor-geometry-key, коммит0f16312e8ff1— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
337890af75b94db584babe05347bf3b6309e4703git log --all --format='%H %T' | grep 337890af75b9 - Тело issue:
9dec80eead95ea0cbc014364d7ed09eaef1f7f45b7e2c70f97f1a95c586ac465 - Вердикт конвейера:
green· High 0 · маршрутfix(критерийperf)