Files
2026-10-02 00:56:09 +03:00

21 KiB
Raw Permalink Blame History

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 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 337890af75b94db584babe05347bf3b6309e4703
    git log --all --format='%H %T' | grep 337890af75b9
    
  • Тело issue: 9dec80eead95ea0cbc014364d7ed09eaef1f7f45b7e2c70f97f1a95c586ac465
  • Вердикт конвейера: green · High 0 · маршрут fix (критерий perf)