Files
houseplan-card/docs/reviews/CODE-REVIEW-602-r2.md
T
2026-09-20 21:46:00 +00:00

16 KiB
Raw Blame History

CODE-REVIEW-602-r2

Issue: #602 · Этап: code · Заход: r2 · блокирующих циклов израсходовано 1 из 4 Материал: e1fa2591a4cc7cb5a86ee43183353eb3b9783984 (issue/602-dialog-polish), рабочая копия ревью — на этом SHA, git status чист на всём протяжении разбора.

Скоуп раунда

Предыдущий заход (r1, материал c69d73f1, документ docs/reviews/CODE-REVIEW-602-r1.md) дал единственную находку — Medium в скоупе: npm run golden:verify был красным (8 из 173 сцен different), а AC15/план тестирования ТЗ требуют его зелёным. Всё остальное (AC1–AC14, AC16, трейлеры, i18n, отдельно проверенный риск с авто-раскрытием radar-формы) r1 закрыл без замечаний.

Дельта этого раунда — строго git diff c69d73f1..e1fa2591:

  • demo/golden/baselines/baselines-index.json — обновлены хэши и метаданные приёмки;
  • 8 PNG-файлов эталонов (ровно те 8 сцен, что r1 назвал different);
  • docs/reviews/CODE-REVIEW-602-r1.md — публикация документа r1 (добавлен конвейером, не автором; не несёт функциональных изменений).

src/**, test/**, demo/smoke_*, локали, docs/USER-GUIDE*, docs/CHANGELOG* в дельте не тронуты. Это ровно то действие, которое r1 назвал единственным недостающим шагом (принятие эталонов на канонической Linux-сборке с трейлерами Release:/Baseline-Reviewed:) — не рефакторинг, не смена контракта, не задета новая подсистема. По PROCESS.md §2.9 разбор сужен до дельты; полный повторный прогон всех AC1–AC16 не требуется, так как ни один из них не зависит от кода, тронутого дельтой.

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

Гейт Статус Как проверено
typecheck/npm test/npm run build + сверка 3 копий бандла зелёный, не перегонял Validate на точном материале e1fa2591 — прогон 35539075873, conclusion: success, headSha совпадает (проверено gh run list --commit e1fa2591…). Дельта раунда не трогает src/**, пересчитывать нечего.
node scripts/check-docs.mjs --strict не перегонял, не применимо Дельта не трогает src/**/docs/images/**; отпечаток документации не мог измениться этим коммитом (уже был зелёным на c69d73f1, см. r1).
npm run golden:verify (закрытие Medium r1) зелёный, проверено на канонических CI-прогонах, не перегонял локально Два независимых прогона на точных SHA дают причинно-следственную пару: (1) прогон 35538133817 на материале 8ca877c9 (код идентичен c69d73f1, только + документ r1) — conclusion: failure, это тот самый диагностический Linux-снимок, из которого взяты 8 кадров; (2) прогон 35539075873 на материале ревью e1fa2591 — job «Golden-кадры против принятых эталонов» conclusion: success (не skip — проверено gh api .../check-runs, это полный, а не dedup-прогон). Разница между (1) и (2) — ровно принятие 8 эталонов, ничего больше.
Целостность принятых эталонов зелёный, проверил сам Пересчитал SHA-256 всех 8 принятых PNG в рабочей копии и сверил с записями baselines-index.json — совпадают побайтово для всех 8 (device-dialog-desktop-en/de, device-dialog-mobile-ru, device-help-popover-light-ru, settings-help-zoom-200-en-light/ru-dark, device-ripple-color-popover-mobile-ru, space-room-color-popover-desktop-ru). Ни один файл вне этого списка не изменился (git diff c69d73f1..e1fa2591 --stat — 10 файлов, из них 8 названы явно).
Провенанс и allowlist приёмки зелёный, проверил чтением demo/golden/accept.mjs Скрипт (не тронут этой дельтой, инфраструктура доверенная и ранее не была предметом замечаний) отказывается писать эталоны без --reviewed, проверяет buildFingerprint === sourceFingerprint(ROOT) (гарантия, что кадры сняты именно с этого исходника), считает «свидетелей» — необъявленные сцены, совпавшие байт-в-байт (#355) — и отказывает при их нехватке (floor). В принятом индексе witnesses.count: 104 при floor: 10 — с большим запасом, то есть посторонний дрейф вне 8 объявленных сцен инструментом исключён. foreignCapture.reason в индексе прямым текстом фиксирует «съёмка на Linux CI, приёмка на Windows автора после визуальной проверки» — это осознанный, задокументированный путь, а не сокрытие.
Трейлеры коммита e1fa2591 зелёный, проверил сам git show -s --format=%B: Issue: #602, User-Visible: no, Release: v1.77.0-beta.3 (совпадает с package.json version), Baseline-Reviewed: …/runs/35538133817 — ровно то, что требует scripts/validate-commit-provenance.mjs:64-77 для коммитов, трогающих demo/golden/baselines/*.{png,json}, и ровно то, что r1 указал как «что нужно».
Мутанты по диффу (6/6 шардов) зелёный, не перегонял Тот же прогон 35539075873 — все 6 шардов success; дельта раунда не содержит логики, которую могли бы поймать мутанты (только бинарные эталоны и JSON-метаданные).
Смоки (demo/smoke_*.mjs) не гонял, не применимо Дельта не трогает ни один smoke-файл и ни один файл, который smoke-и импортируют (src/**, dist/**) — scripts/smoke-select.mjs не даёт новых кандидатов относительно уже проверенного в r1 диапазона. Полный набор смоков r1 уже прогнал сам на функциональном коде (746147d0/c69d73f1), эта дельта его не меняет — наследуется.
npm run invariants, python -m pytest tests_backend, performance-профили не гонял Дельта не трогает геометрию/custom_components/**/*.py/перф-пути — то же основание, что и в r1, не изменилось.

Находки

Нет. Единственная находка r1 закрыта именно тем действием, которое r1 предписал; новых находок дельта не создаёт (дельта не содержит логики — только данные эталонов, их индекс и публикацию документа предыдущего раунда).

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

Находка r1 Чем закрыта Где это видно
Medium: npm run golden:verify красный на материале ревью (8/173 different: device-dialog-desktop-en/de, device-dialog-mobile-ru, device-help-popover-light-ru, settings-help-zoom-200-en-light/ru-dark, device-ripple-color-popover-mobile-ru, space-room-color-popover-desktop-ru), обещанный тестовый артефакт (принятые baseline-кадры) отсутствовал Коммит e1fa2591: принятие ровно этих 8 эталонов через accept.mjs --reviewed на артефакте канонического Linux-прогона 35538133817, с трейлерами Release:/Baseline-Reviewed:, как и требовало r1 дословно («Что нужно») git diff c69d73f1..e1fa2591 -- demo/golden/baselines — те же 8 id, ни одного лишнего; gh api .../35539075873/check-runs → job golden success (не skip); хэши PNG совпадают с индексом (см. таблицу выше)

Побочное наблюдение без действия: документ r1 в прозе назвал общее число сцен «150» («8 из 150 сцен different»), тогда как в самом индексе на материале r1 (c69d73f1) их уже было 173, и это же число совпадает с явным GOLDEN_SCENARIOS.length и с «165 сохранены без изменений» из комментария автора (165+8=173). Похоже на опечатку в тексте документа r1, а не на ошибку разбора — состав 8 названных сцен и итоговое решение («нужен golden:accept») от этого не меняются, поэтому не поднимаю как находку.

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

Без повторной проверки в этом раунде — дельта их не задевает, основание см. в docs/reviews/CODE-REVIEW-602-r1.md на SHA c69d73f1f26b3277fde938a4eb08195c561e46ba:

  • AC1/AC8 — лишние подписи/заголовок убраны, синхронно по 4 локалям;
  • AC2 — центрирование тумблера (top: 50%/translateY(-50%)), защитный AC подтверждён мутацией руками;
  • AC3/AC5 — числовые поля не обрезаются/не перекрывают слайдер (grid-раскладка .hpf-range);
  • AC4 — подписи шкалы совпадают с концами трека (84px единый резерв);
  • AC6/AC7/AC14 — однострочные футеры, mobile icon-only, confirm в одну строку на 320/360/560;
  • AC9 — climate-toggle перенесён после «Additional actions»;
  • AC10 — нейтральный dialog.unsaved убран из всех 4 диалогов и локалей;
  • AC11–AC13 — единая toggle-секция радара, восстановление черновика Off→On, защитный AC подтверждён мутацией руками; savedUnsupported/virtual-ветки структурно не тронуты;
  • AC16 — оба changelog и docs/USER-GUIDE* правлены в коммите 746147d0 с User-Visible: yes;
  • трейлеры 746147d0/c69d73f1 — корректны;
  • отдельно проверенный и закрытый риск: авто-раскрытие radar-формы для распознанного, но ещё не сохранённого устройства — унаследованное (не из диффа #602) и задокументированное в docs/USER-GUIDE.md поведение, не регрессия;
  • соответствие docs/SCOPE.md (J4/J6) и docs/TOUCH-SUPPORT.md — оценено в ревью ТЗ (зелёный вердикт spec r2) и не пересматривается на этапе кода без изменения контракта.

Ни один из этих пунктов дельта c69d73f1..e1fa2591 не задевает (она не содержит src/**).

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

  • npm test/npm run typecheck/npm run build — не перегонял. Дешёвые гейты зелёные на точном SHA e1fa2591 (Validate 35539075873), дельта раунда их не меняет.
  • node scripts/check-docs.mjs --strict — не перегонял, дельта не трогает src/**/ docs/images/**.
  • Полная матрица demo/smoke_*.mjs — не гонял; дельта не содержит кода, который смоки исполняют, smoke-select не даёт новых кандидатов сверх уже проверенных в r1.
  • npm run invariants, python -m pytest tests_backend, performance-профили — не гонял, как и в r1: дельта не касается геометрии, custom_components/**/*.py или перф-путей.
  • Локальный повторный прогон npm run golden:verify — не гонял руками (нет причины: два канонических Linux-прогона на нужных SHA уже дают прямую причинно-следственную пару «до фикса красный → после фикса зелёный», это сильнее локального дубля на этой же машине).
  • Ручная проверка в браузере HA — не проводилась (среды HA нет), как и в r1.

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

  • SHA: e1fa2591a4cc7cb5a86ee43183353eb3b9783984 (issue/602-dialog-polish)
  • Дерево материала: идентично рабочей копии на момент вывода вердикта (git status --short пуст непосредственно перед выводом)
  • ТЗ: тело issue #602, зелёный вердикт спецификации r2
  • Предыдущий код-ревью: docs/reviews/CODE-REVIEW-602-r1.md, материал c69d73f1, вердикт жёлтый · High 0 · Medium 1

Вердикт

Зелёный. Единственная Medium-находка r1 закрыта именно предписанным действием, дельта раунда не содержит функционального кода и не создаёт новых находок.


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

  • Ветка: issue/602-dialog-polish, коммит e1fa2591a4cc — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: eed53eb273f319a3cf3c49bf42d1625feca21672
    git log --all --format='%H %T' | grep eed53eb273f3
    
  • Тело issue: 8f8081ec29db1c104189682530643bde421d91127170b2c635107c595950a5a9
  • Вердикт конвейера: green · High 0