Files
houseplan-card/docs/reviews/CODE-REVIEW-584-r2.md
T
claude[bot] 06bf9b6921
Проверка (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
docs: review document for #584
Issue: #584
User-Visible: no
2026-09-16 21:19:57 +00:00

216 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-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