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

22 KiB
Raw Blame History

CODE-REVIEW-627-r3

Материал: b921ba71847df37416bed1c15e3d645953ffa1c9 (рабочая копия уже на нём; git fetch/checkout не выполнялись). Дерево c76d64409884dfb646eb723f3e868003e923cce9. Заход r3, блокирующих циклов израсходовано 1 из 4 (полный трек, лимит 4).

r2 (docs/reviews/CODE-REVIEW-627-r2.md, материал 47d07281b6ce…, дерево e19b817f43f3…) был зелёным и цикла не образовал (#227). r3 существует не потому, что r2 что-то вернул автору, а потому, что автор запушил новый коммит: b921ba71 — ребейз ветки на ушедший вперёд origin/dev (успевший вобрать #642, «диалог «Оптимизировать планы» — свой модуль») с пересборкой бандла и пересчётом потолков. 47d07281 в текущей истории не резолвится (ребейз его осиротил) — по [§2.10] это не находка, а обычное дело; материал ищется по дереву. Дерево, эквивалентное содержимому 47d07281, живо в текущей истории как 70fe860bac6259fc1f32114a6b3fe191fe8d966a (коммит «test(smoke): danger confirmation waits for the composite language gate (#627 r1 M1)», тот же M1-фикс, что и в r2), поэтому дельта раунда объявлена как git diff 70fe860b..b921ba71.

Скоуп

ТЗ #627 (полный трек, из аудита T9 M2-A): не новая функциональность, а бюджетно-техническая работа над уже закрытыми job'ами J4/J6 (docs/SCOPE.md) — держит bundle-budget.mjs честным гейтом ленивых графов онбординга/редактора, без новой видимой поверхности. User-Visible: no на всех трёх коммитах — корректно, ниже подтверждено.

Объявление дельты (git diff 70fe860b..b921ba71 --stat): 74 файла — scripts/bundle-budget.mjs (17 строк: константа потолка + комментарий-причина), scripts/monolith-baseline.json (одно число), и 72 файла механической пересборки (dist/**, custom_components/houseplan/frontend/**, три копии бандла синхронны). src/**/*.ts, test/**, demo/** дельтой не тронуты — подтверждено и git diff --stat, и node scripts/smoke-select.mjs --base 70fe860b --head b921ba71:

Исполняемого frontend-диффа нет (src/**/*.ts не тронут).
Browser-smoke этим диффом не выбираются — это не «пропустить проверки»,
а «выбирать нечего»: смоки проверяют собранную карточку.
Тронуто файлов: 76.

Дельта локальна по содержимому (две строки логики — числовая константа и её обоснование), хотя коммит и называется «ребейз». Тем не менее я разобрал её не по минимуму, а вместе с двумя пробелами доказательств, унаследованными от r1/r2 (см. «Как проверялось»): впервые в истории задачи собранный бандл — совместный продукт #627 и #642 (до этого коммита #642 жил только в origin/dev, 82a48ee0 был выпущен поверх него, но ни разу не гонялся в браузере после реального слияния кода обеих задач в одно дерево), и два смока, тронутых ещё исходным коммитом 82a48ee0 и прямо относящихся к контракту задачи, ни разу не запускались ни в r1, ни в r2. Формально это не входит в дельту r3, но раз я всё равно поднимал браузер для проверки собранного дерева — закрыл оба пробела тем же прогоном; см. ниже.

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

Дешёвые гейты подтверждены зелёным Validate на этом самом SHA (run 36025312110, conclusion: success, headSha = b921ba71847df37416bed1c15e3d645953ffa1c9 — проверено напрямую через gh run view --json). Разбивка по джобам:

Джоб Результат
Классификация изменённых файлов success
Предполёт: документация, провенанс, процесс success
Переиспользование: это дерево уже проверено success
Мутанты по диффу (6/6 шардов) success
Фронтенд: типы, юниты, мутанты, синхрон бандла success
Hassfest / HACS / pytest / geometry parity / browser smokes (3 шарда) / perf-smoke / golden skipped (workflow_dispatch, не heavy)
Доказательство выполненных проверок success

Джоб «Фронтенд» содержит npm test → npm run build → bundle-tree.mjs + npm run bundle:budget → npm run lint:unused (в этом порядке, .github/workflows/validate.yml:779-791) — то есть typecheck, юниты, сборка, гейт потолка LAZY_EDITOR_GZIP_CEILING и гейт связности монолита (bundleBytes против scripts/monolith-baseline.json) уже подтверждены на этом точном SHA. Их я не перегонял.

Прогнано лично на b921ba71 (дёшево, для точных чисел в этом документе и потому что новых чисел для CI-подтверждения годится не «похоже», а «совпало»):

Гейт Команда Результат
Bundle sync (проверка свежести/синхрона копий) node scripts/bundle-sync.mjs git status --short пуст и до, и после — закоммиченный dist/ уже байт-в-байт синхронен с custom_components/** и распакован в demo/srv/assets
Bundle budget npm run bundle:budget lazy editor: 228621 B gzip (потолок 229600 B ±2000), lazy onboarding: 27468 B gzip (потолок 28500 B ±2000), initial View: 289418 B gzip (потолок 290400 ±2000) — совпадает с числами коммита b921ba71 дословно
Мёртвый код и связность монолита npm run lint:unused monolith: delegates=154 portMembers=348 hostRefs=4869 portPrivates=94 harnessPrivates=101 bundleBytes=2508211 / ok все числа равны базе

Арифметика коммита проверена построчно:

  • LAZY_EDITOR_GZIP_CEILING: 229600, полоса 2000 → нижняя граница 227600; при замере 228621 запас сверху 229600−228621=979, запас снизу 228621−227600=1021 — совпадает с текстом комментария в scripts/bundle-budget.mjs:572 дословно.
  • monolith-baseline.json bundleBytes: база origin/dev (0f234f76, тот же коммит, что и merge-base ветки с origin/dev) — 2499182 (проверено git show 0f234f76:scripts/monolith-baseline.json), текущее — 2508211, разница +9029 — совпадает с текстом коммита («десять новых чанков словарей и записи манифеста»); остальные пять чисел монолита (delegates/portMembers/hostRefs/portPrivates/harnessPrivates) не изменились ни на йоту относительно базы dev — тоже заявлено в коммите и подтверждено прогоном.
  • Комментарий к LAZY_EDITOR_GZIP_CEILING над константой (строки 559–567 до правки) на промежуточном коммите 82a48ee0 содержит незаполненные плейсхолдеры XXX («замер XXX», «Центр оставляет XXX Б сверху и XXX Б до нижней границы») — артефакт промежуточного состояния ветки после первого ребейза на origin/dev с #642, где числа ещё не были пересчитаны. Это не находка: 82a48ee0 не является вершиной ни одного опубликованного ревью (ни r1, ни r2 его не рецензировали как отдельный SHA — их материал уже был позже осиротевшим 40959feb/47d07281), а в материале этого раунда, b921ba71, плейсхолдеры заменены настоящими числами, что я и проверил выше побайтово. Упоминаю, чтобы явно снять вопрос, а не оставить его как тихо замеченную странность.

Смоки. smoke-select для дельты 70fe860b..b921ba71 не выбирает ничего (см. выше) — формально этого достаточно. Тем не менее я поднял браузер (нужно было для проверки живой пересборки бандла) и заодно закрыл два пробела в доказательствах, оставленные r1/r2:

Смок Почему запущен Результат
smoke_lazy_admin_locale.mjs Ядро AC4–AC7; первый прогон на дереве, где бандл собран совместно с #642 OK, все 38 полей true
smoke_danger_confirmation.mjs M1 (r1) / его фикс (r2) — держится ли регрессия закрытой на пересобранном бандле OK, все 25 полей true, включая {de,fr}GateSettledBeforeAsking
smoke_optimize_geometry_preflight.mjs Тронут 82a48ee0 (добавлено ожидание языкового гейта перед card._editorRuntime.optimizePlans.open() — новый порт из #642); ни r1, ни r2 не упоминают этот файл ни разу (grep -n optimize по обоим документам — пусто), хотя правка именно этого файла явно перечислена в теле коммита b921ba71 («smoke_optimize_geometry_preflight: …, разрешено в коммите задачи») без единой ссылки на прогон OK, все 16 полей true — пробел закрыт
smoke_dialog_segments_i18n.mjs Единственный смок, явно названный в ТЗ issue («План автотестов»: «...smoke_dialog_segments_i18n (4 локали × 4 диалога; переключение языка должно ждать гейт)») для риска ровно той же природы, что и M1; тронут 82a48ee0, но ни r1, ни r2 его не упоминают OK, все 60 полей true — пробел закрыт
smoke_color_picker.mjs, smoke_free_walls.mjs, smoke_space_scale_defaults.mjs, smoke_summary_panel.mjs, smoke_toggle_confirmation.mjs, smoke_ux_fixes.mjs Ещё 6 смоков получили тот же защитный «дождаться aria-busy» патч в 82a48ee0 (за пределами явного списка ТЗ — самостоятельный аудит автора), ни один не упомянут ни в r1, ни в r2 Все 6 — OK, без единого false-поля

Итого 9 браузерных смоков лично прогнаны на b921ba71, все зелёные без единого красного поля — включая четыре, которые пять раундов до этого (r1: три коммита, r2, теперь r3-до-этого-прогона) молча пропускали.

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

  • Индивидуальные прогоны 5 мутантов #627 по --id (onboarding-loader-skips-namespace-ensure и др.) — на этом SHA не перегонял; src/** в дельте 70fe860b..b921ba71 не тронут, а мутанты гейтят именно src/**. Опираюсь на личный прогон r1 (на уже осиротевшем SHA, но тем же дереве src/**) плюс на «Мутанты по диффу (6/6 шардов) — success» в CI на b921ba71 — это диффовый прогон относительно доказанного предка, не индивидуальный запуск по --id, но за отсутствием изменений src/** он лишь переподтверждает то же дерево, а не проверяет что-то новое.
  • golden:verify, перф-смок, pytest tests_backend, Hassfest/HACS, geometry parity — все skipped в CI (не heavy, workflow_dispatch) и не гейт этой дельты: ни эталонов рендера, ни Python, ни геометрии дифф не касается.
  • Полный smoke-select --base origin/dev --head HEAD (а не --base 70fe860b) — не гонял: он воспроизвёл бы ровно то же самое (дельта origin/dev..HEAD содержит src-правки #627, уже разобранные в r1), а не что-то специфичное для этого раунда.
  • Остальные ~250 несвязанных смоков вне плана ТЗ и списков связей — не прогонял, это предрелизная обязанность, не гейт ревью.
  • Живой стенд Home Assistant — не поднимал.

Находки

Нет. High 0, Medium 0.

Low-наблюдение, снятое без действия: патч «подождать aria-busy до 250×20мс» теперь инлайново продублирован в 12 файлах demo/smoke_*.mjs (проверено grep -rl "hasAttribute('aria-busy')"), при том что demo/serve.mjs уже экспортирует несколько общих утилит смоков (watchPage, check, checkAll, reportPageErrors, finish) — общий хелпер сюда напрашивается. Не поднимаю до Medium: сам приём (а не его вынесение в хелпер) был явно одобрен r1 как решение M1 («чинится тем же приёмом, что уже применён к девяти другим смокам»), дублирование не в дельте r3 (весь список — из 82a48ee0, уже принятого в r1/r2), и это стиль тестового харнесса, а не продуктовый код.

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

AC Проверено в r3 Итог
AC1 (bundle-budget.mjs печатает и гейтит онбординг) Не тронут дельтой; CI (Фронтенд job) переподтвердил npm run lint:unused/bundle:budget на этом SHA Унаследовано + переподтверждено CI
AC2 (числовые потолки и запасы) Переисполнено лично: npm run bundle:budget на b921ba71 — редактор 228621 ≤ 229600 (запас к полосе 979/1021 Б, >500), онбординг 27468 ≤ 28500 (запас 34526−27468=27058 ≥ 6500, 244433−228621=15812 ≥ 15000), initial View 289418 (было 289457 до задачи — фактически снижение, не рост; в полосе потолка) — причина перецентровки редакторского потолка (#642) записана в комментарии константы дословно с числами Доказан заново на текущем SHA
AC3 (9 ленивых чанков, владение графами) Не тронут дельтой (test/i18n-lazy-namespaces.test.mjs, test/bundle-assets.test.mjs не изменились с r1); CI Unit tests зелёные на b921ba71 Унаследовано из r1
AC4 (холодное открытие on ru/de/fr, первый кадр на языке) Лично: smoke_lazy_admin_locale.mjs — OK на пересобранном бандле Переисполнено
AC5 (live-переключение языка, составной гейт) Лично: тот же смок + smoke_danger_confirmation.mjs (M1) + smoke_optimize_geometry_preflight.mjs + smoke_dialog_segments_i18n.mjs + 6 доп. смоков с тем же патчем — все OK Переисполнено, шире, чем требовала дельта
AC6 (отказ обеих попыток → английский только в пространстве) Не тронут дельтой; smoke_lazy_admin_locale.mjs (поля failure*) — OK в прогоне выше Унаследовано + переподтверждено прогоном
AC7 (холодный View/en-редактор/Zigbee не тянут лишних чанков) Не тронут дельтой; те же поля смока — OK Унаследовано
Трейлеры git show <sha> -s --format='%B' на 82a48ee0/70fe860b/b921ba71 — везде Issue: #627, User-Visible: no Корректно
Changelog git diff 70fe860b b921ba71 --stat -- docs/CHANGELOG.md docs/CHANGELOG.ru.md — пусто; верно при User-Visible: no и отсутствии видимых изменений Корректно
Одно число — один источник grep -rn "229_600|229600|2508211" scripts test src — по одному вхождению каждое, только в объявлении константы/базы Корректно

Закрытие раунда r2

r2 был зелёным, «Находки: Нет» — закрывать нечего. Таблица приведена для формы, соответствия сокращённому шаблону:

Находка r2 Чем закрыта Где видно
— — —

Унаследовано из r2

Без повторной проверки в r3 принято из docs/reviews/CODE-REVIEW-627-r2.md (материал 47d07281b6ce… / дерево e19b817f43f3…, вердикт зелёный · заход r2 · High 0 · Medium 0), поскольку src/**, test/**, demo/** в дельте 70fe860b..b921ba71 не тронуты:

  • AC3, AC6, AC7 — доказаны в r1, не пересчитывались повторно ни в r2, ни здесь.
  • Полный реестр из 7 мутантов #627 (5 новых + 2 с обновлёнными якорями), лично прогнанных r1-ревьюером по --id, «поймано 1 из 1» каждый.
  • check-docs.mjs --screenshots=warn, check-inputs.mjs --coverage (0), CONTRIBUTING.md/tsconfig.test.json — содержательно не менялись.

Не унаследовано, а переисполнено заново лично в r3 (см. «Как проверялось»): M1-фикс (smoke_danger_confirmation.mjs) и AC4/AC5 — потому что артефакт (собранный бандл) впервые стал совместным продуктом #627+#642, и это первый раз, когда кто-либо гонял браузерные смоки против именно такого дерева.

Вердикт

Зелёный. Дельта раунда (scripts/bundle-budget.mjs, scripts/monolith-baseline.json + механическая пересборка) арифметически честна и подтверждена и CI, и лично. Ни одной находки. Дополнительно: два смока, явно относящихся к контракту задачи (один — по прямому тексту ТЗ, другой — по собственному упоминанию в теле коммита без прогона) и шесть смоков с тем же защитным патчем, ни разу не запускавшихся в r1/r2, лично прогнаны на этом SHA и зелёные — пробел в доказательствах предыдущих раундов закрыт, а не унаследован молча.



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

  • Ветка: issue/627-lazy-admin-locales, коммит b921ba71847d — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: c76d64409884dfb646eb723f3e868003e923cce9
    git log --all --format='%H %T' | grep c76d64409884
    
  • Тело issue: 11ffae080ad26691a4b8dbd32f7736895c0c25a3f0cabe1b09da0e21666e6562
  • Вердикт конвейера: green · High 0