mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
129 lines
16 KiB
Markdown
129 lines
16 KiB
Markdown
# 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](https://github.com/Matysh/houseplan-card/actions/runs/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](https://github.com/Matysh/houseplan-card/actions/runs/35538133817) на материале `8ca877c9` (код идентичен `c69d73f1`, только + документ r1) — `conclusion: failure`, это тот самый диагностический Linux-снимок, из которого взяты 8 кадров; (2) [прогон 35539075873](https://github.com/Matysh/houseplan-card/actions/runs/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 закрыта именно предписанным действием, дельта раунда
|
||
не содержит функционального кода и не создаёт новых находок.
|
||
|
||
---
|
||
|
||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||
|
||
## Материал раунда
|
||
|
||
- Ветка: `issue/602-dialog-polish`, коммит `e1fa2591a4cc` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||
- Дерево материала: `eed53eb273f319a3cf3c49bf42d1625feca21672`
|
||
```
|
||
git log --all --format='%H %T' | grep eed53eb273f3
|
||
```
|
||
- Тело issue: `8f8081ec29db1c104189682530643bde421d91127170b2c635107c595950a5a9`
|
||
- Вердикт конвейера: `green` · High 0
|