Files
houseplan-card/docs/reviews/CODE-REVIEW-304-r2.md
T
2026-08-25 14:30:36 +00:00

166 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CODE-REVIEW-304-r2
**Issue:** [#304 — паритет базовых осей и узлов между инструментами Plan editor](https://github.com/Matysh/houseplan-card/issues/304)
**Ветка:** `issue/304-plan-axis-parity`, HEAD `e603c5496fcbbd674c48a0314ca4f2e6f22a4c71`
**Диапазон:** `origin/dev...HEAD` (4 коммита: `a2b4d32b` код, `7310ce01` скриншоты докс, `33dcd1ce` документ ревью r1, `e603c549` приёмка golden-эталонов)
**Трек:** `small`
**Заход:** r2 · блокирующих циклов израсходовано **1 из 2** (расход только на жёлтый/красный вердикт r1; зелёный вердикт этого раунда цикл не образует)
**Вердикт:** зелёный · High: 0 · Medium: 0
## Скоуп этого раунда (дельта)
Предыдущий раунд (r1) закончился жёлтым вердиктом на SHA `7310ce0134ca8e5b1c32e6816a2e70625ea158e2`
(документ `docs/reviews/CODE-REVIEW-304-r1.md`, коммит `33dcd1ce`). Единственная находка —
**H1**: golden-доказательство неполно, канонический Linux `Validate` для этой ветки (run
`32854408646`, commit `a2b4d32b`) дал `golden: failure` на 5 сценах (`safe-resize-handles-clamp-{light,dark}`,
`opening-placement-{door,passage}-thick-wall-{dark,light}`), новый эталон не был снят/принят.
Дельта r2 = `git diff 7310ce01..HEAD`:
```
demo/golden/baselines/baselines-index.json | 28 +--
demo/golden/baselines/decor-color-popover-mobile-ru.png | Bin
demo/golden/baselines/opening-placement-door-thick-wall-dark.png | Bin
demo/golden/baselines/opening-placement-passage-thick-wall-dark.png | Bin
demo/golden/baselines/opening-placement-passage-thick-wall-light.png | Bin
demo/golden/baselines/room-label-parity-plan-dark.png | Bin
demo/golden/baselines/room-label-parity-plan-light.png | Bin
demo/golden/baselines/safe-resize-handles-clamp-dark.png | Bin
demo/golden/baselines/safe-resize-handles-clamp-light.png | Bin
demo/golden/baselines/space-tab-drop-after-dark.png | Bin
demo/golden/baselines/split-corner-wall-thick-dark.png | Bin
demo/golden/baselines/wall-junctions-plan-preview-light.png | Bin
demo/golden/baselines/wall-junctions-plan-t-dark.png | Bin
docs/reviews/CODE-REVIEW-304-r1.md | 272 +++ (публикация r1, не код)
```
Продуктовый код (`src/houseplan-card.ts`), тесты/смоки и документация пользователя **не менялись**
с r1 — только один коммит класса D (`e603c549`, `demo/golden/baselines/**`) плюс публикация
предыдущего документа ревью (не относится к предмету оценки). Это ровно та дельта, которую и
требовала находка H1: разбор по существу ограничен ею, AC не переоткрываются заново — они не
задеты этим коммитом.
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **H1** (High) — golden-доказательство AC6/«Release-артефакты» неполно: 5 сцен `different` на каноническом Linux `Validate`, эталон не принят | Коммит `e603c549` `test: accept reviewed plan-axis baselines` — принят полный 110-сценовый Linux-артефакт из того же run `32854408646` через `npm run golden:accept -- --reviewed --from=<артефакт>`; новый эталон закрывает все 5 названных сцен | `git show -s --format=%B e603c549` содержит `Release: v1.67.0-rc.3` и `Baseline-Reviewed: https://github.com/Matysh/houseplan-card/actions/runs/32854408646`; `git diff 7310ce01..e603c549 --stat` показывает ровно эти 5 файлов среди 12 изменённых PNG; свежий `Validate` на точном HEAD `e603c549` — run [32858067234](https://github.com/Matysh/houseplan-card/actions/runs/32858067234), job `golden` → `success` (проверил сам, `gh run view 32858067234 --json jobs`) |
| **Low** (снята без правки в r1) — AC1 использует смежную, не буквально идентичную unit/smoke fixture golden-топологию | Не менялась, не требовала правки; остаётся снятой | документ r1, раздел «Low» |
## Как проверялось (r2)
Материал: `git log --oneline origin/dev..HEAD`, `git diff 7310ce01..HEAD` (дельта раунда) и
`git diff origin/dev...HEAD` (полная картина, для сверки, что делта не задевает продукт).
### Прогнано лично в этом раунде
| Проверка | Команда | Результат |
|---|---|---|
| Typecheck | `npx tsc --noEmit` | зелёный, без ошибок |
| Unit | `npm test` | 1299 тестов, **1298 passed, 0 failed, 1 skipped** (тот же pre-existing `#281`-скип, что и в r1; не связан с #304 и с этой дельтой) |
| Bundle-копии | `cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js` | идентичны (код не менялся с r1, пересборка не требовалась) |
| Docs fingerprint | `node scripts/check-docs.mjs` | «Documentation checks passed (7 files, 10 external links)» |
| Provenance/process gate | `node scripts/process-gate.mjs --range=origin/dev..HEAD` | «гейт пройден, предупреждений 1» — единственный WARN («ТЗ docs/specs/304-*.md не найдено») ожидаем для `small` |
| Канонический golden (Linux CI, не локально) | `gh run view 32858067234 --repo Matysh/houseplan-card --json jobs` на точном HEAD `e603c549` | все джобы `success`: `golden`, `docs`, `frontend`, `provenance`, все 3 `smoke`-шарда, `performance_smoke`; `backend`/`hacs`/`hassfest` — `skipped` (файлы этих поверхностей не тронуты, ожидаемо) |
| Число принятых сцен | `ls demo/golden/baselines/*.png | wc -l` = 110; `node -e "import('./demo/golden/matrix.mjs').then(m=>console.log(m.GOLDEN_SCENARIOS.length))"` = 110 | совпадает — принят полный матрикс, ни одна сцена не осталась в стороне |
Дешёвый набор (tsc/unit/build/check-docs) прогнан заново, потому что это правило раунда без
исключений — они стоят минуты независимо от размера дельты. `npm run build` целиком не
перезапускал: код не менялся с r1, байтовое сравнение уже показывает три копии идентичными.
### Что не прогонял и почему
- **`npm run golden:verify` локально** — не запускал. Дельта — это уже принятые эталоны из
канонического Linux-прогона; локальный verify на этой машине (не подтверждённый как каноническое
Linux-окружение) не добавил бы доказательности сверх реального Linux CI-прогона на точном HEAD,
который зелёный (см. таблицу выше).
- **`smoke-select.mjs` / прицельные смоки** — не перезапускал. Дельта не трогает `src/**`,
`demo/smoke_*.mjs`, `test/**` — выбор смоков и их результат наследуются из r1 без изменений
(см. «Унаследовано из r1»).
- **`node scripts/model-invariants.mjs`** — не запускал. Дельта не касается рёбер комнат, `layout`,
`marker.space`, `open_spans`, записей толщины — только растровые PNG-эталоны и индекс манифеста.
- **`python -m pytest tests_backend`** — не запускал, `custom_components/**/*.py` не тронут ни в
этой дельте, ни во всём диапазоне.
- **Полный `demo/smoke_*.mjs`** — не прогонял; наследуется из r1 (не задет дельтой).
### Визуальная сверка новых эталонов (не только доверие к commit message)
Открыл несколько принятых PNG, чтобы не принимать формулировку коммита («below-threshold raster
refresh» для 7 сцен, «intended new layer» для 5) на слово:
- `opening-placement-door-thick-wall-dark.png` и `safe-resize-handles-clamp-light.png` (2 из 5
«смысловых» сцен из H1) — на обеих виден новый статический слой осевых линий/узлов (пунктирные
линии через тела стен) в инструментах **Opening** и **Resize**, чего не было до фикса #304 —
соответствует контракту п.1 issue, ожидаемое изменение;
- `decor-color-popover-mobile-ru.png` (одна из 7 «уже проходивших» сцен) — Background editor,
цветовой попап, никакой связи с Plan editor/осями нет; сцена не может быть затронута кодом
#304 по существу — расхождение байтов до принятия объясняется только суб-пиксельным дрейфом
рендера того же Chromium-прогона, ровно как заявлено в commit message, не скрытой регрессией.
### Механика приёмки — прочитан сам скрипт, не только описание
`demo/golden/accept.mjs` копирует **все** сценарии текущей матрицы (`GOLDEN_SCENARIOS`, 110 штук)
из одного переданного артефакта и атомарно перезаписывает единый манифест
(`sourceFingerprint`/`chromium`/`acceptedAt` — общие для всего набора, не по сцене) — значит
«приняты все 110, из них у 12 изменились байты» — ожидаемое поведение инструмента, не
частичная/избирательная перезапись и не расширение скоупа: манифест домена смоделирован как один
атомарный набор от одного канонического прогона, а не патчворк разных прогонов во времени.
## Унаследовано из r1
Документ `docs/reviews/CODE-REVIEW-304-r1.md` (заход r1, SHA `7310ce0134ca8e5b1c32e6816a2e70625ea158e2`,
опубликован коммитом `33dcd1ce`). Дельта r2 не трогает `src/**`, тесты/смоки, i18n, документацию
пользователя — принято без повторной проверки:
- разбор самой продуктовой правки (`src/houseplan-card.ts`, гейтинг снят в двух местах, transient
state остаётся эксклюзивным «Стенам») — код не менялся с r1;
- AC1–AC5, AC7 — доказательства (unit/smoke, включая проверенную способность нового смока и нового
golden-инварианта падать) не переоткрывались: ни один из задетых файлов не входит в дельту r2;
- границы режимов (View/Device editor/Background editor), transient-контракт п.4, отсутствие
промежуточного кадра (п.7) — код-основа не менялась;
- трейлеры коммита `a2b4d32b` (`Issue: #304`, `User-Visible: yes`, оба changelog в том же коммите) —
проверены в r1, повторно не смотрел;
- i18n/compatibility/performance разбор из r1 — не задет дельтой, наследуется целиком;
- Low-находка r1 (AC1 golden-топология смежная, не идентичная) — остаётся снятой, дельта её не
касается.
## Что проверено и корректно (r2, по существу дельты)
- Ровно 5 сцен из H1 обновлены и визуально показывают ожидаемое новое поведение (#304), а не
случайное изменение;
- ровно 7 дополнительных сцен обновлены синхронно тем же атомарным прогоном приёмки — не выборочная
правка, механика инструмента подтверждена чтением `accept.mjs`; выборочно открытая «decor»-сцена
подтверждает отсутствие скрытой регрессии в этой группе;
- трейлеры коммита `e603c549` полны: `Issue: #304`, `User-Visible: no` (генерируемые артефакты,
продукт не меняется), `Release: v1.67.0-rc.3`, `Baseline-Reviewed:` со ссылкой на реальный
прогон — процесс `provenance` для класса D соблюдён;
- канонический Linux `Validate` на точном итоговом HEAD зелёный целиком, включая `golden` и все
3 смок-шарда — это сильнее локального прогона и снимает саму находку H1 по факту, а не по
утверждению автора;
- полный набор эталонов (110/110) внутренне согласован (единый `sourceFingerprint`/`chromium` в
манифесте) — не оставляет часть эталонов от старого несовместимого Chromium-прогона.
## Чего не проверял
- Полный `demo/smoke_*.mjs` и полный `npm run golden:verify` локально — дельта не требует, см.
«Как проверялось»;
- `python -m pytest tests_backend`, `node scripts/model-invariants.mjs` — не запускал, дельта их
не касается;
- Побайтовую/пиксельную сверку всех 12 изменённых PNG — открыл 2 из «смысловых» пяти и 1 из
«шумовых» семи как выборочную проверку заявления автора; оставшиеся 9 не смотрел глазами, доверился
единому механизму приёмки (`accept.mjs`, прочитан целиком) и совпадению количества принятых сцен
с полной матрицей.
- Точная арифметика «110 passed / 5 different» из текста r1-документа (там написано «110 сцен
passed, 5 different» при общей матрице 110 сцен, что даёт 115 — арифметически не сходится:
видимо, опечатка прежнего раунда, верное соотношение 105/5). Не влияет на существо закрытия
H1 и не относится к дельте r2, поэтому не переоткрывал.
## Итог
Единственная блокирующая находка предыдущего раунда (H1, неполное golden-доказательство) закрыта
по существу: канонический Linux-прогон полного матрикса принят как эталон через штатный
`golden:accept --reviewed`, снабжён обязательными `Release:`/`Baseline-Reviewed:` трейлерами, и
свежий `Validate` на итоговом HEAD зелёный целиком — включая job `golden`. Продуктовый код и его
доказательная база не менялись с r1 и наследуются без повторной проверки. Новых находок в дельте
r2 нет.