Files
houseplan-card/docs/reviews/CODE-REVIEW-597-r1.md
T
2026-09-19 14:19:54 +00:00

20 KiB
Raw Blame History

CODE-REVIEW-597-r1

Issue: #597 · Этап: код-ревью · Заход: r1 · блокирующих циклов израсходовано 0/2 (лёгкий трек, лимит 2) Материал: 2b89f699618a3fa3e9bafc07dfa71e07a8e19960 (рабочая копия), диапазон git diff origin/dev...HEAD Ветка приведена конвейером к актуальному dev до ревью (45dac1c0 → 2b89f699, +2 коммита dev сверху) — разбор проведён полностью (§7.2), не по дельте.

Скоуп

Шаг 2 эпика #591 (шаг 1 — #594, в dev). Генератор общего набора контролов (src/styles/form-kit.styles.ts) разрезан на пять именованных фрагментов (formKitCardsCss, formKitFocusCss, formKitDisabledCss, formKitSwitchRowCss, formKitSwitchCaptionCss); редактор боковой панели (src/summary-panel-editor-style.ts) подставляет каждый на своё место вместо собственной копии тех же правил. Ни одна строка src/summary-panel-editor.ts (разметка) не меняется. Изменение задумано как «ноль видимых изменений» — К1–К5 ТЗ.

Диапазон диффа (без сгенерированного класса D): src/styles/form-kit.styles.ts, src/summary-panel-editor-style.ts, scripts/mutation-registry.mjs, test/form-kit.test.mjs, три новые фикстуры в test/fixtures/. Класс A задет — полный флоу обязателен и пройден (ТЗ в теле issue, ревью ТЗ зелёное на r2).

Как проверялось

Дешёвые гейты (typecheck, npm test, npm run build со сверкой бандла) на этом SHA уже подтверждены зелёным Validate (https://github.com/Matysh/houseplan-card/actions/runs/35446978510) — не перегонялись. Вместо этого бюджет раунда потрачен на чтение кода и на гейты, которые Validate в этом прогоне не покрывает: в нём smoke, golden и performance_smoke стоят skipped (обычный push в задачную ветку, не кандидат беты и не PR — эти джобы включаются только на heavy).

Гейт Прогнан Результат
npx tsc --noEmit, npm test, npm run build + сверка 3 копий бандла нет — подтверждено зелёным Validate на этом SHA success (ссылка выше)
npm run bundle:sync (пересборка + сверка дерева) да, лично dist/houseplan-card.js побайтово совпал с закоммиченным после чистой пересборки — git status пуст
npm run bundle:budget (AC7) да, лично initial View 290843/291400, lazy editor 222359/222900, lazy furniture art 16942/17900 — совпало цифра в цифру с хендоффом
node scripts/no-new-any.mjs --base origin/dev --head HEAD да «Новых any нет»
node scripts/smoke-select.mjs --base origin/dev --head HEAD да одна зарегистрированная связь — smoke_summary_panel_polish.mjs ← summaryPanelEditorCss; остальных совпадений нет (диф — 2 файла, 9 символов на изменённых строках)
node demo/smoke_summary_panel.mjs (AC4) да, лично OK
node demo/smoke_summary_panel_polish.mjs (AC4) да, лично OK
node demo/smoke_room_settings.mjs (AC5) да, лично OK
npm run golden:verify (AC6) да, лично (в песочнице есть Chromium — у автора не было) 80/80 сцен passed, exit 0 — расхождений ноль
node scripts/check-docs.mjs (обязателен — diff трогает src/**) да, лично ERROR: отпечаток скриншотов документации устарел — см. находку M1
npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs && node --test test/form-kit.test.mjs да, лично 5/5 тестов зелёные
Мутант form-kit-fragment-drifts-from-panel (padding 14px→13px) да, лично, дважды (с восстановлением) оба теста #597 краснеют: AssertionError на побайтовом сравнении
Проба M1 ревью ТЗ (литерал фрагмента карточки-группы в блочном комментарии рядом с листом панели) да, лично тест 1 краснеет ровно заявленным текстом: карточка-группа: правило осталось литералом...; после снятия — снова зелёный
Проба на стык фрагментов диалогов (лишний \n в sharedCss) да, лично тест 2 (#597 лист диалогов карточки не изменился ни на байт) краснеет
Независимая пересборка фикстур с кода origin/dev (не доверяя хендоффу) да, лично панель: 14585 байт, побайтово совпало с test/fixtures/summary-panel-editor.css; диалоги без переключателя — 1885 байт, с ним — 2399 байт, оба побайтово совпали со своими фикстурами
python -m pytest tests_backend -q нет диф не касается custom_components/**/*.py
Perf-профили нет не названы в AC, диф не трогает чувствительные пути (src/iso-*, src/live-*, src/render-*)
npm run docs:accept -- --identical (диагностика находки M1) да, лично (изменения отменены, не коммитились) «Все 11 кадров попиксельно совпали с закоммиченными: принят только отпечаток исходников»

Не гонял полный набор смоков (250 в матрице) — задача узкая (2 файла CSS, один потребитель), smoke-select называет одну связь, остальные не относятся к диффу; прогон всей матрицы — предрелизная обязанность, не гейт ревью.

Находки

M1 (Medium, в скоупе задачи) — устаревший обязательный гейт check-docs не закрыт

node scripts/check-docs.mjs на материале ревью красит:

ERROR screenshot source fingerprint is stale; run npm run docs:capture and accept before the beta candidate (#479)

PROCESS.md §8 называет этот гейт безусловно обязательным при любом диффе по src/**: «отпечаток скриншотов документации считается по всему src/**, поэтому любая правка фронтенда делает его устаревшим... выборка «по diff и AC» здесь не работает — diff всегда попадает, и решать нечего». Диф задачи меняет src/styles/form-kit.styles.ts и src/summary-panel-editor-style.ts — значит гейт применим и обязан быть закрыт в рамках задачи, а не оставлен следующей.

Это не гипотетический риск: ровно тот же паттерн уже стоил продукту инцидента — «скриншоты не пересняли в #230 и #234, и dev стоял с красным job docs, пока это не нашли при следующей задаче (#237)» (PROCESS.md §8). Непосредственный предшественник этой ветки — коммит fc4d55c7 docs: отпечаток скриншотов после правки комментария рантайма (#593) — обновил отпечаток сразу после последней правки src/** перед этой задачей (0565c7ad, #593); других правок src/** между fc4d55c7 и материалом ревью нет, кроме самой задачи #597. То есть именно этот коммит впервые за долгое время сделал отпечаток снова устаревшим и не закрыл это следующим шагом, хотя предыдущая задача сделала это ровно так.

Проверил, что правка дешёвая и не открывает новый спор с ТЗ: прогнал npm run docs:accept -- --identical — «Все 11 кадров попиксельно совпали с закоммиченными: принят только отпечаток исходников» (0 расхождений, как и обещает К1/AC1 задачи — вывод CSS не изменился ни на пиксель). Изменения не коммитил (ревьюер не правит материал); откатил рабочую копию.

Раздел ТЗ «Release-артефакты» («Документация не меняется») отвечает только за прозу (docs/*.md, USER-GUIDE.ru.md) и не называет отпечаток скриншотов отдельно — в этом смысле находка и к ТЗ (пропущенный release-артефакт), и к реализации (гейт не прогнан и не закрыт до хендоффа). Ни AC1–AC8, ни хендофф не упоминают check-docs, хотя PROCESS.md называет его обязательным именно по факту диффа src/**, независимо от AC.

Чем краснеет: сам гейт — node scripts/check-docs.mjs без флагов (умолчание --screenshots=strict) на материале ревью. В обычном пуше в задачную ветку CI джоб «Предполёт» использует --screenshots=warn и поэтому зелёный на этом SHA — это маскирует находку в Validate, но не отменяет требование PROCESS.md §8 и не меняет исход на кандидате беты, где режим строгий.

Правка: npm run docs:accept -- --identical и коммит обновлённого docs/images/screenshots.json (только отпечаток, без изменения PNG) в этой же задаче — ровно то, что сделал непосредственный предшественник (fc4d55c7).

Находка в скоупе задачи (диф сам её и вызвал) — по §2.7/§7.2 чинится в текущем issue, отдельный issue не заводится.

Что проверено и корректно

  • К1/AC1 (ноль видимых изменений в листе панели). Независимо от хендоффа пересобрал formKitCss-composition на коде origin/dev (через временный откат src/styles/form-kit.styles.ts к версии dev и компиляцию) и сравнил результат с закоммиченной фикстурой: 14585 байт, побайтовое совпадение. Тест test/form-kit.test.mjs подтверждает это же на актуальном коде.
  • К2/AC2 (одна копия). Прочитал src/summary-panel-editor-style.ts — ни один из пяти литералов PANEL_FRAGMENTS не встречается в файле, только вызовы formKit*Css(SUMMARY_PANEL_FORM_KIT). Мутационная проба (литерал карточки-группы в блочном комментарии рядом с листом) краснит тест ровно словами хендоффа; без правки M1 прежняя проверка (min-height: 54px) её бы пропустила — это подтверждено чтением истории обеих находок ревью ТЗ r1/r2.
  • К3/AC3 (генератор не меняет смысла листа диалогов). Пересобрал formKitCss(CARD_DIALOG_FORM_KIT) в обеих формах на коде origin/dev и сравнил с новыми фикстурами: без переключателя 1885 байт, с ним 2399 — побайтовое совпадение в обоих случаях, независимо от заявленного в хендоффе. Проба с лишним переносом строки на стыке фрагментов (sharedCss) краснит именно этот тест — свидетель реален, а не декларативен.
  • К4 (граф загрузки). Ни formKitCardsCss/formKitFocusCss/... не экспортированы вовне лениво загружаемых модулей за пределы прежних; git diff --stat подтверждает изменения только в тех же двух файлах, что и раньше несли этот CSS. npm run bundle:budget — initial View / lazy editor / lazy furniture art в пределах прежних потолков, цифры совпали с хендоффом.
  • К5 (разметка панели не тронута). src/summary-panel-editor.ts вне диффа (git diff --name-only -- src/).
  • AC4/AC5 (смоки панели и диалога комнаты). Прогнал все три смока лично: smoke_summary_panel.mjs, smoke_summary_panel_polish.mjs, smoke_room_settings.mjs — все OK.
  • AC6 (эталоны golden). Автор не прогонял (в песочнице нет Chromium) — в этой среде Chromium доступен, прогнал сам: 80/80 сцен passed, exit 0. Расхождений нет ни в одной сцене, включая те, что рендерят диалоги на общем наборе контролов (диалог комнаты и т.п.).
  • AC7 (бюджет бандла). Числа совпали цифра в цифру с хендоффом.
  • AC8 (полный набор). npm test и npm run gate:small подтверждены зелёным Validate на этом SHA; отдельно прогнал целевой файл test/form-kit.test.mjs (5/5) и no-new-any (чисто).
  • Мутант form-kit-fragment-drifts-from-panel. Зарегистрирован в scripts/mutation-registry.mjs, гард — сам целевой тест. Применил мутацию (padding: 14px → 13px) дважды независимо — оба раза оба теста #597 падают с AssertionError; без мутации — зелёные. Мутант реален, не декоративен.
  • Провенанс коммита. Один коммит, трейлеры Issue: #597 и User-Visible: no на месте; User-Visible: no не требует changelog, диф не трогает пользовательский текст ни в одном из двух changelog-файлов.
  • i18n. Диф не касается i18n-файлов — согласуется с ТЗ («i18n: нет»).
  • Классы риска §2.6. async/данные и права/геометрия — неприменимо (чистый CSS-рефакторинг без сети, без геометрии). Визуал — главный риск, закрыт двойным свидетелем: побайтовым текстовым сравнением (сильнее кадра, ловит перестановку правил, которую пиксель не отличит) и личным прогоном golden:verify на полной матрице. Объём/perf — AC7 подтверждён. Host/input — разметка и обработчики не менялись (К5), поведение то же.
  • Факт из ТЗ, использованный как опора доказательства («у панели нет golden-кадра»). Проверил demo/golden/matrix.mjs — сцены с dialog: 'summary' действительно нет. Утверждение не является догадкой.

Чего не проверял

  • Полный набор из 250 браузерных смоков — не оправдано диффом (smoke-select называет одну прямую связь, диф — 2 CSS-файла с нулевым изменением собранного вывода для панели и диалогов карточки).
  • python -m pytest tests_backend — диф не касается Python.
  • Performance-профили — не названы в AC, диф не в чувствительных путях (src/iso-*, src/live-*, src/render-*, houseplan-card.ts).
  • Полный HA-харнесс (fcntl, недоступен вне Linux+HA) — не относится к CSS.
  • process-gate.mjs --issues — не имеет значения для решения ревьюера, статус и лейблы issue уже видны напрямую через gh.
  • npm run docs:accept -- --identical — прогнал только для диагностики находки M1 (подтвердить, что правка дешёвая), результат не коммитил: правку делает автор в задаче.

Вердикт

Жёлтый. Единственная находка (M1, Medium) — в скоупе задачи, вызвана самим диффом и чинится одной командой плюс коммитом отпечатка; отдельный issue не заводится. Все восемь AC доказаны свидетелями, которые я лично проверил на умение краснеть (мутант + две пробы совпали с заявленными в хендоффе текстами ошибок); AC6 закрыт мной вместо автора, у которого не было среды. Технический план задачи (разрезание генератора на фрагменты, подстановка вместо редизайна) корректен и полностью соответствует контракту К1–К5.


Материал раунда

  • Ветка: issue/597-panel-on-form-kit, коммит 2b89f699618a — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 94639a89f4617d5498d0a2c63027db0fa2dab139
    git log --all --format='%H %T' | grep 94639a89f461
    
  • Тело issue: 8a56815128285d56f2c2f9f63eb6d8ae211525202f38e8bdd75159aa7c55412c
  • Вердикт конвейера: yellow · High 0