docs: review document for #584
Проверка (CI) / Классификация изменённых файлов (push) Successful in 20s
Проверка (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) Failing after 34s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 19s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 27s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Failing after 44s
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Skipped
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Skipped
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 6m17s
Проверка (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) / Доказательство выполненных проверок (push) Failing after 15s

Issue: #584
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-16 21:19:57 +00:00
parent 62d86e0f83
commit 06bf9b6921
+215
View File
@@ -0,0 +1,215 @@
# CODE-REVIEW-584-r2 — #584: физический габарит мебели равен заявленным размерам
- Issue: [#584](https://github.com/Matysh/houseplan-card/issues/584)
- Этап: `code` (PROCESS.md §2.7)
- Диапазон материала раунда: `9bf41ec3..62d86e0f`
- Материал ревью — ровно `62d86e0f8361a0ed4cc7b9af184252ab5ee63dd0`, рабочая копия уже на нём;
`git fetch`/`git checkout`/`git pull` на другой коммит не делал.
- Предыдущий раунд: [`CODE-REVIEW-584-r1.md`](CODE-REVIEW-584-r1.md), вердикт
**жёлтый**, материал `9bf41ec3`, комментарий-вердикт
`github-actions @ 2026-09-16T21:12:07Z`.
- Заход: **r2** — разбор по дельте (PROCESS.md §2.9, issue #214)
- Блокирующих циклов израсходовано: 1/4 (бюджет тратят жёлтый/красный; r1 был жёлтым)
## Дельта раунда
```
git diff 9bf41ec3..62d86e0f --stat
docs/reviews/CODE-REVIEW-584-r1.md | 260 +++++++++++++++++++++++++++++++++++++
1 file changed, 260 insertions(+)
```
Между материалом r1 (`9bf41ec3`) и материалом r2 (`62d86e0f`) в дереве изменился
**ровно один файл** — сам документ ревью r1, положенный шагом публикации
конвейера. Продуктового кода, тестов, паков, генераторов, changelog — нулевая
дельта.
`origin/dev` за это время продвинулся `7c5fd32a → e0b16c76`, но `e0b16c76`
уже был предком материала `9bf41ec3` (это чужой докс-коммит, влившийся в
`dev`), а не переписыванием истории — проверено `git merge-base --is-ancestor
e0b16c76 HEAD` (истина) и `git merge-base origin/dev HEAD == e0b16c76`. Значит
это не ребейз на ушедший вперёд `dev` (§7.2), ветка ветки просто линейно
впереди; полный повторный разбор по этой причине не требуется.
Единственное действие раунда — комментарий автора
`Matysh @ 2026-09-16T21:13:28Z` «M1 закрыт: число названо», закрывающий
единственную блокирующую находку r1 (M1) без изменения кода.
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **M1** (Medium, в скоупе) — раздел «Производительность»/«Риски» ТЗ требует назвать рост ленивого чанка `furniture-plan-art.generated` числом; число не было названо ни в хендоффе, ни в коммитах, ни в CHANGELOG | Комментарий `Matysh @ 2026-09-16T21:13:28Z` называет число по официальному источнику — полю `bundle-manifest.mjs`, а не по блобам исходника: `lazyFurnitureArtGzipBytes` 10 254 → 23 338 Б (+13 084 Б, +128 %); заодно назван эффект на холодный старт (`initialViewGzipBytes` +47 Б, +0,016 %) и на весь ленивый набор (`lazyGzipBytes` +13 136 Б, +3,1 %) | Issue #584, комментарий 2026-09-16T21:13:28Z. **Числа проверены мной независимо, не на слово** — см. «Как проверялось» |
## Как проверялось
Материал ревью — ровно `62d86e0f`; `git checkout`/`fetch` на другой коммит не
делал.
Дешёвые гейты на этом SHA уже подтверждены Validate (упомянуто в задании
ревью: прогон `35151230014`, `success`) — это тот же код, что и на `9bf41ec3`
(дельта раунда не трогает исходники), поэтому `npx tsc --noEmit`, `npm test`,
`npm run build`+сверка бандлов, `check-docs.mjs`, browser-смоки,
`golden:verify`, мутанты — повторно не гонял. Причина не «доверие», а
«нулевая дельта кода»: r1 эти гейты уже проверил на идентичном дереве
(`9bf41ec3`), а r2 к дереву ничего не добавил кроме доксового файла, который
эти гейты не касается.
Единственное, что требовало самостоятельной проверки в этом раунде —
достоверность чисел из закрывающего комментария M1. Числа не входят ни в один
автоматический гейт как утверждение соответствия ТЗ (сам факт наличия числа в
отчёте гейтом не проверяется), поэтому свериться нужно было вручную:
```
python3 -c "
import json
d = json.load(open('custom_components/houseplan/frontend/houseplan-assets.json'))
for k in ['initialViewGzipBytes','lazyGzipBytes','lazyFurnitureArtGzipBytes']:
print(k, d.get(k))
"
# HEAD (62d86e0f): initialViewGzipBytes 291158, lazyGzipBytes 433657, lazyFurnitureArtGzipBytes 23338
git show origin/dev:custom_components/houseplan/frontend/houseplan-assets.json > /tmp/dev-manifest.json
python3 -c "... тот же код на /tmp/dev-manifest.json ..."
# dev (e0b16c76, тот же код мебели что и 7c5fd32a): initialViewGzipBytes 291111, lazyGzipBytes 420521, lazyFurnitureArtGzipBytes 10254
```
Результат совпадает с комментарием **побитно**:
| поле | `dev` (было) | `HEAD` (стало) | дельта в комментарии | дельта, посчитанная мной |
|---|---|---|---|---|
| `lazyFurnitureArtGzipBytes` | 10 254 | 23 338 | +13 084 Б, +128 % | +13 084 Б, +127,6 % → округление до +128 % корректно |
| `lazyGzipBytes` | 420 521 | 433 657 | +13 136 Б, +3,1 % | +13 136 Б, +3,124 % → округление корректно |
| `initialViewGzipBytes` | 291 111 | 291 158 | +47 Б, +0,016 % | +47 Б, +0,0161 % → округление корректно |
Источник чисел — реальный закоммиченный файл манифеста
(`custom_components/houseplan/frontend/houseplan-assets.json`, поле пишет
`scripts/bundle-manifest.mjs`, тот же источник, которым руководствуется
`scripts/bundle-budget.mjs` при проверке бюджета `INITIAL_VIEW_GZIP_BUDGET =
301 066`), а не отдельный ручной подсчёт по blob'ам, как было у меня в r1.
Значит число теперь официальное и воспроизводимое любым будущим ревьюером той
же командой, а не разовый расчёт ревьюера.
Дополнительно проверено: `291 158 < 301 066` — initial-View бюджет не задет
(и не мог быть задет: арт мебели лежит в ленивом чанке, `initialViewFiles` его
не включает — подтверждено ещё в r1 чтением `lazyFurnitureArtFiles`).
## Унаследовано из r1
Без повторной проверки в этом раунде принято всё, что установил
[`CODE-REVIEW-584-r1.md`](CODE-REVIEW-584-r1.md) на материале `9bf41ec3`,
поскольку дельта `9bf41ec3..62d86e0f` не касается ни одного из этих
доказательств (единственный изменённый файл — сам r1-документ):
- **AC1** (границы `[0,artW]×[0,artH]` ±0.1) — `test/furniture-visual-bounds.test.mjs`,
мутант `furniture-symbol-may-keep-inner-padding` логически прослежен, красит
тест.
- **AC2** (одинаковые `w/h` → одинаковый габарит) — наследуется от AC1
транзитивно.
- **AC3** (трансформ сохраняет бокс при угле/зеркалировании/масштабе) —
прямые углы точное равенство, 15°/37° вложенность и покрытие >97 %.
- **AC4** (склейка путей сохраняет относительные команды) —
`test/furniture-path-join.test.mjs`, мутант
`furniture-paths-joined-without-reset` логически прослежен; попутная находка
про `stairs`/`tv` подтверждена в исходном сгенерированном коде.
- **AC5** (`furniture:check` падает на нарушении пп.1/2/5) — прочитан код
`svgArt()`/`loadPack()`, три `fail()`-условия соответствуют контракту.
- **AC6** (golden пересняты, диффы объяснены) — 9 кадров, каждый объяснён в
коммите `9bf41ec3`, `Baseline-Reviewed` присутствует.
- **AC7** (скоуп ограничен паком/генератором/`furniture.ts`/тестами) —
`git diff --stat` не содержит редактора/hit-area/конфига/i18n.
- **AC8** (гейты зелёные на точном SHA) — два прогона Validate на `9bf41ec3`
проверены по `headSha` (`35149944216` light, `35145083038` full).
- Математика legacy `plant` (растяжение `1/0.96`), независимая сверка
`svg-path-bounds.mjs` с продакшен-парсером `parseSvgPath` до `1e-6`,
добросовестность приёмки дизайнерского пака, трейлеры и changelog обоих
коммитов, «одно число — один источник» (не применимо), touch/security
(без изменений) — все пункты раздела «Что проверено и корректно» r1.
- Раздел «Чего не проверял» r1 (визуальный осмотр PNG глазами,
`model-invariants`/`pytest` — не применимо, полный перф-профиль
`large-house-*`) остаётся в той же силе: дельта раунда их не касается.
Новое в этом раунде, что r1 не мог проверить (числа появились только сейчас):
воспроизведение и проверка чисел M1 — выполнено выше, не наследуется, а
проверено заново.
## Находки
Не найдено. M1 (единственная блокирующая находка r1) закрыта комментарием с
числами, которые я сверил с закоммиченным манифестом бандла независимо и
получил точное побитное совпадение — не принято на слово. Нового кода,
который нужно было бы разбирать, дельта не вносит, поэтому новых находок по
построению взяться не может (AC не пересматривались, потому что дельта их не
задевает).
### Low — не найдено
## Что проверено и корректно
- **Точность чисел M1** — см. таблицу выше, совпадение до последнего байта
между комментарием и полем `houseplan-assets.json` на `dev` (`e0b16c76`,
тот же код мебели, что и старый `7c5fd32a`) и на `HEAD` (`62d86e0f`).
- **Источник чисел — официальный, не разовый расчёт.** Комментарий ссылается
на поле, которое реально существует в производственном манифесте и
используется гейтом `bundle-budget.mjs`, а не на постороннюю метрику.
- **Смысл цифр в комментарии корректен**: холодный старт (`initialViewGzipBytes`)
практически не меняется (+47 Б — это запись имени нового чанка, не сам
чанк), рост сосредоточен в ленивом чанке мебели, который загружается только
при открытии мебели на плане — соответствует утверждению ТЗ «решение — за
владельцем, если рост окажется заметным» и корректно передаёт масштаб
(+128 % локально в ленивом чанке, но всего +3,1 % во всём ленивом наборе и
+0,016 % в критичном для UX холодном старте).
- **Отсутствие рецидива рабейза/дивергенции**: `origin/dev` продвинулся, но
остался предком материала — не §7.2 «другой код после ребейза».
- Всё унаследованное из r1 (см. раздел выше) остаётся в силе — дельта его не
подрывает: правка M1 не касается ни одного файла, участвующего в AC1–AC8.
## Чего не проверял
- **`npx tsc --noEmit`, `npm test`, `npm run build`+сверка бандлов,
`check-docs.mjs`, browser-смоки, `golden:verify`, mutation-gate** — не
гонял повторно: дельта раунда не меняет ни одного файла, участвующего в
этих гейтах (единственный новый файл — `docs/reviews/CODE-REVIEW-584-r1.md`,
сам по себе документация ревью, не код, не тесты, не арт). Эти гейты уже
зелены на идентичном дереве кода — на `9bf41ec3` в r1 (проверено там по
`headSha`) и на `62d86e0f` в актуальном Validate (`35151230014`, `success`,
указан в задании ревью).
- **Полный визуальный осмотр 9 golden-кадров глазами** — не открывал заново;
это уже было явным пунктом «чего не проверял» в r1 и дельта раунда кадры не
трогает.
- **`model-invariants.mjs`, `pytest tests_backend`** — не применимо, как и в
r1: дельта не трогает геометрию комнат/стен/backend, а в этом раунде вообще
не трогает исходный код.
## Вердикт
**Зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0 → в задаче.**
Единственная блокирующая находка r1 (M1 — рост ленивого чанка мебели не был
назван числом, как того требует раздел «Производительность»/«Риски» ТЗ)
закрыта комментарием автора с числами по официальному источнику
(`bundle-manifest.mjs`/`houseplan-assets.json`). Числа проверены мной
независимо по закоммиченному манифесту на обоих концах диапазона и совпадают
с комментарием побитно: `lazyFurnitureArtGzipBytes` 10 254 → 23 338 Б (+128 %),
`lazyGzipBytes` +3,1 %, `initialViewGzipBytes` (холодный старт, критичный для
бюджета `bundle-budget.mjs`) +47 Б (+0,016 %) — бюджет `301 066` Б не
приближается. Продуктового кода в дельте раунда нет, `origin/dev` продвинулся,
но остался предком материала (не ребейз, §7.2 не применяется). AC1–AC8,
скоуп, трейлеры и changelog наследуются из r1 без повторной проверки — дельта
их не касается. Новых High/Medium/Low находок не появилось.
---
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/584-furniture-physical-bounds`, коммит `62d86e0f8361` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `894d037879b76147721b484c5c769dd32eba7383`
```
git log --all --format='%H %T' | grep 894d037879b7
```
- Тело issue: `2b6d41955420844101142131ce4f789615f0ac788609ae654f4b416448b03b9b`
- Вердикт конвейера: `green` · High 0