docs: review document for #744

Issue: #744
User-Visible: no
This commit is contained in:
claude[bot]
2026-10-01 23:05:20 +00:00
parent 2bcde13158
commit 92b89d9b80
+217
View File
@@ -0,0 +1,217 @@
# CODE-REVIEW-744-r4
**Issue:** #744 · **Трек:** ask · **Заход:** r4 · блокирующих циклов израсходовано 1 из 4
**Материал:** `2bcde131581a6130f971dcef167299d6cc1129ad` (ветка
`issue/744-floor-geometry-key`, поверх `dev` `c4cb0649` — после слияния #762).
Девять коммитов от merge-base: продуктовые/тестовые К1–К5 `f5b20e07` и
`6ed9aa16` (уже разобраны в r1/r2), `a86be350` (ленивый `space-editor`, уже
разобран в r3 под хешем `0f16312e` — ребейз осиротил старый хеш, содержимое
то же), три docs-коммита, публикующих CODE-REVIEW-744-r1/r2/r3.md
(`bb9aaefe`, `2d7a1c97`, `9882046b`) и два коммита `docs(reviews): индекс
после сдвига каталога` (`3d68a2fe`, `7bbab4b6`), и новый `2bcde131` —
единственная содержательная правка этого раунда.
## Скоуп
r3 был зелёным на материале `0f16312e` (комментарий автора, вердикт
2026-10-01). Пока ревью шло, `dev` продвинулся ещё на 5 коммитов; владелец
зафиксировал это прямо в issue и вернул задачу в `S6-in-progress` **не как
правку кода, а как ребейз** («Код-ревью зелёное — вердикт выше в силе,
переделывать работу не нужно. Не удалось только слияние»). Автор сделал
`git rebase origin/dev` на `dev@c4cb0649` (после #762) и запушил без force
(lease `98db7b1f` → `2bcde131`).
Ребейз дал ровно один конфликт — в `docs/testing-notes/mutation-browser-guards.md`
(таблица пересекалась с чужими правками, ушедшими в `dev` раньше #744): автор
взял строки `dev` и прибавил к ним два мутанта задачи (`floor-geometry-key-*`),
подняв lifecycle 97→99 и Total 214→216. После ребейза один шаг `gate:small`
покраснел на храповике монолита: `bundleBytes` вырос с 2 605 172 до 2 607 854 Б
(+2 682 Б при полосе 2 000) — не потому что код раунда что-то добавил (К1–К5 и
ленивый `space-editor` уже посчитаны в r1/r3), а потому что ребейз сам по себе
сдвинул дерево `dist/` относительно старой базы. Автор поднял базовую линию
отдельным коммитом `2bcde131` с обоснованием (новый модуль ключа этажа + обёртка
ленивого чанка), не трогая продуктовый код.
Задача по-прежнему `track: ask`, критерий §5 «перф» не переоценивается — не
изменился с r1. **`route: fix`.**
### Дельта r3 → r4
Проверено прямым чтением, не только по словам автора: содержимое продуктовых
коммитов не изменилось, изменились только их хеши (ребейз переносит одни и те
же патчи на новый родитель):
- `f5b20e07` (К1–К5, перф floor-geometry-key): `git show f5b20e07 --stat` даёт
те же 13 файлов/456+/24− и тот же текст изменений, что описан в r1 —
с одним отличием: правка `docs/testing-notes/mutation-browser-guards.md`
внутри этого же коммита теперь содержит ребейзнутые числа 97→99/214→216
(было 90→92/205→207 на старой базе r1/r3). Это ожидаемый эффект ребейза
коммита с текстовым конфликтом, не новая правка задачи.
- `6ed9aa16` (тест «судить оба кадра удержанного resize») — 1 файл,
58+/7−, идентичен r2.
- `a86be350` (ленивый `space-editor`) — дифф `src/space-card.ts` побайтово
совпадает с тем, что r3 разобрал под хешем `0f16312e` (тот же `import
'./space-editor'` убран, тот же `async getConfigElement()`).
Единственное новое содержание раунда — коммит `2bcde131`:
```
chore(monolith): raise the bundleBytes baseline for #744 (#744)
scripts/monolith-baseline.json | 2 +-
```
`"bundleBytes": 2605172` → `2607854`. Трейлеры: `Issue: #744`,
`User-Visible: no` — верно: число самим пользователям не видно, это
внутренний храповик монолита (`scripts/monolith-metrics.mjs`,
`docs/testing-notes/...`, не пользовательская поверхность).
## Как проверялось
| Гейт | Статус | Как |
|---|---|---|
| `npx tsc --noEmit`, `npm test`, `npm run build` + `bundle-policy --verify` | не перегонял целиком, но `npm run build` выполнил сам | Validate на точном SHA материала зелёный: https://github.com/Matysh/houseplan-card/actions/runs/36937043475 — сверено `gh run view 36937043475`, `headSha` = `2bcde131581a6130f971dcef167299d6cc1129ad`, `conclusion: success` (не со слов автора). Дополнительно сам прогнал `npm run bundle:sync` (→ `tsc --noEmit && rollup -c` зелёные, бандл собрался за 22,2 с) ради смока ниже; рабочую копию `dist/` вернул `git checkout -- dist/` + `git clean -fd dist/`, `git status --porcelain` пуст после |
| Корректность ребейзнутой таблицы `mutation-browser-guards.md` | **прогнал сам** | Пересчитал список построчно (`grep -c '^- \`'` по секциям): «Custom-element and HA browser lifecycle» = 99, сумма всех секций = 216 — совпадает с заявленным в таблице «99» и «216 / 200». Оба мутанта задачи (`floor-geometry-key-global-epoch`, `floor-geometry-key-ignores-content`) в списке на месте |
| `node scripts/mutation-gate.mjs --check` | **прогнал сам** | exit 0; `browser guards: 216/200` — WARN (не отказ, #699, та же картина что в r3, но с актуальными для текущего `dev` числами); оба мутанта задачи — `ok` |
| `node demo/smoke_floor_geometry_cache.mjs` | **прогнал сам, на пересобранном бандле** | Все проверки `true`/`0`/`[]` как ожидается: AC1 (`ac1GardenVisitBuildsNo*` = 0), AC2а/б/в (`...EqualsAFreshCard` = true), итог `OK`. Это прямое исполнение целевого смока задачи на точном материале раунда, не унаследованная запись |
| `node scripts/smoke-select.mjs --base origin/dev --head HEAD` | **прогнал сам** | 20 прямых совпадений (включая целевой `smoke_floor_geometry_cache.mjs` ← `_cleanFloorCache`) + 41 слабая связь на `_curSpaceCfg` — тот же профиль, что в r3 (дельта `src/space-card.ts` не читает `_curSpaceCfg`); решение не прогонять слабые — не затронуты дельтой |
| Freshness `docs/reviews/INDEX.md` | **прогнал сам** | `node scripts/reviews-index.mjs` → «docs/reviews/INDEX.md свеж» |
| `npm run gate:small`, полный `smoke-select`, golden, Full Performance, `pytest tests_backend`, `npm run invariants` | не перегонял | дельта раунда — ребейз без изменения продуктового кода плюс один chore-коммит над `scripts/monolith-baseline.json`; геометрия, Python и рендер плана не затронуты; AC1–AC5 (К1–К5) и AC4 (performance) уже закрыты исполнением в r1–r3 на коде, который не менялся с тех пор |
## Закрытие раунда r3
r3 был зелёным без находок (0 High, 0 Medium) — закрывать нечего.
## Унаследовано из r3 (и транзитивно из r1/r2)
Продуктовый и тестовый код К1–К5 (`src/floor-geometry-key.ts`,
`src/clean-floor.ts`, `src/stairs-editor.ts`, `src/houseplan-editor-runtime.ts`,
`src/houseplan-card.ts`, `src/space-card.ts`, `demo/smoke_floor_geometry_cache.mjs`,
`demo/benchmark_large_house.mjs`, `demo/performance/card-contract.mjs`,
`scripts/mutation-registry.mjs`, `test/clean-floor.test.mjs`) не менялся
между r3 и r4 — дельта раунда ограничена ребейзом (без изменения содержимого
этих файлов, подтверждено построчно выше) и одним новым chore-коммитом над
`scripts/monolith-baseline.json`. Принято без повторного построчного разбора,
с документом и материалом r2/r3 (`docs/reviews/CODE-REVIEW-744-r2.md`,
материал `d10285b0794d…`; `docs/reviews/CODE-REVIEW-744-r3.md`, материал
`0f16312e8ff1…`):
- Архитектура ключа этажа (`contentFingerprint`, память на эпоху и на пару
объектов записи), её использование в четырёх кэшах и resize-preview со
своим ключом.
- Контракт К1–К5 и защита против «устаревшего кадра» независимым oracle в
смоке — сам смок перепрогнан мной заново в этом раунде на пересобранном
бандле и зелёный, так что это подтверждено исполнением, а не только
унаследовано.
- `StairsEditor.write` больше не чистит `_cleanFloorCache` других этажей.
- Ленивая загрузка GUI-редактора `space-card` (контракт идентичен
`houseplan-card.getConfigElement()`), структурная и поведенческая
корректность подтверждены исполнением в r3 (манифест чанка + Playwright-зонд).
- Два мутанта в `scripts/mutation-registry.mjs` — перепроверено мной
`mutation-gate --check` в этом раунде, оба на месте.
- AC4 — Full Performance против базы `dev`, закрыт в r1→r2, исполнение
проверено r2 напрямую по API/логам; код, который измеряет AC4, с тех пор
не менялся.
- Трейлеры и CHANGELOG RU/EN на продуктовом коммите `f5b20e07` (бывший
`5263403c` до ребейза) — текст дословно совпадает с ТЗ, оба файла правлены
в одном коммите; проверено, что обе строки `#744` сохранились в текущем
`docs/CHANGELOG.md`/`docs/CHANGELOG.ru.md` после ребейза (не были потеряны
слиянием).
## Находки
Нет High. Нет Medium в скоупе. Нет Medium вне скоупа.
Наблюдение r3 о расхождении счётчика в `mutation-browser-guards.md» (92/207
в тексте против 209 фактических) снято этим раундом: ребейз пересчитал
коммит `f5b20e07` против актуальной базы `dev`, и таблица теперь точно
совпадает с фактическим выводом `mutation-gate.mjs` (216/216, 99/99
lifecycle) — подтверждено пересчётом выше.
## Что проверено и корректно
- Дельта раунда (ребейз + `2bcde131`) не меняет ни одного продуктового файла
К1–К5: сверено построчно по diff-статам коммитов `f5b20e07`/`a86be350`,
совпадающим с тем, что уже разобрано в r1/r3.
- Единственная содержательная правка — поднятие `bundleBytes` baseline —
это class D (генерируемое значение), её корректность уже подтверждена
прохождением `gate:small`/Validate на точном SHA (храповик монолита сам
проверяет, что новое число соответствует фактической сборке в пределах
полосы; расхождение завалило бы Validate).
- Конфликт-резолюшн в `docs/testing-notes/mutation-browser-guards.md`
корректен: фактический вывод `mutation-gate --check` (216 всего, 99
lifecycle) совпадает с текстом таблицы после ребейза, оба мутанта задачи
на месте.
- Целевой смок задачи (`demo/smoke_floor_geometry_cache.mjs`, AC1/AC2а/б/в)
зелёный на пересобранном бандле точного материала — не только по
унаследованной записи r3.
- Трейлеры всех коммитов класса A/B раунда (`f5b20e07`, `6ed9aa16`,
`a86be350`, `2bcde131`) содержат `Issue: #744` и корректный
`User-Visible:`; `User-Visible: yes` на `f5b20e07` — оба CHANGELOG правлены
в этом же коммите и сохранились после ребейза.
- `docs/reviews/INDEX.md` свеж относительно опубликованных r1–r3 документов
(`node scripts/reviews-index.mjs`).
- Одно число — один источник: `bundleBytes` 2 607 854 видно один раз — в
`scripts/monolith-baseline.json`, которое читает только
`scripts/monolith-metrics.mjs`/`gate:small`; пользователю это число не
показывается (`User-Visible: no`), второго источника для сверки нет.
## Чего не проверял
- Дешёвые гейты `npx tsc --noEmit`/`npm test`/`bundle-policy --verify`
целиком не перегонял — Validate на точном SHA материала подтверждён
зелёным (`gh run view 36937043475`); `npm run build` тем не менее выполнил
сам (см. таблицу), так что сборка на этом дереве подтверждена дважды
независимо.
- Полный `smoke-select` (всю матрицу 289 смоков), browser-смоки/golden всех
шардов не перегонял — дельта раунда не трогает рендер плана, геометрию или
UI; целевой смок задачи и профильный `mutation-gate --check` прогнал сам.
- Full Performance (AC4) не перезапускал — закрыт исполнением в r1/r2 на
коде, который не менялся с тех пор; дельта этого раунда (ребейз +
baseline-чиcло) не затрагивает горячий путь переключения этажа.
- `npm run invariants` — не запускал, геометрия в этом раунде не менялась
(К1–К5 не тронуты).
- `pytest tests_backend` / HA harness — не запускал, Python не затронут ни
в одном коммите материала.
- Golden (`ci:golden`) — не перегонял; задача не рисует план иначе и дельта
раунда (ребейз + chore) рендера не касается.
- Английскую версию `docs/USER-GUIDE.ru.md`/EN — не проверял: видимое
поведение задачи не изменилось с r1 (`User-Visible: yes` сверен с ТЗ ещё
в r1), дельта этого раунда — `User-Visible: no`.
## Вердикт
Зелёный. Дельта раунда — ребейз на `dev@c4cb0649` (после #762), не менявший
содержимое продуктового и тестового кода задачи (проверено построчно), плюс
один chore-коммит, поднимающий `bundleBytes` baseline монолита на величину,
которую сам раунд и внёс (ключ этажа + ленивый `space-editor`). Конфликт
ребейза в `docs/testing-notes/mutation-browser-guards.md` разрешён верно —
перепроверено пересчётом фактического вывода `mutation-gate --check`.
Целевой смок задачи перепрогнан на пересобранном бандле точного материала и
зелёный. Находок нет. Бюджет циклов остаётся израсходованным на 1 из 4
(унаследовано из r1) — зелёный вердикт цикла не образует.
---
<!-- material-anchors: заполняется публикующим шагом -->
## Материал раунда
- Ветка: `issue/744-floor-geometry-key`, коммит `2bcde131581a6130f971dcef167299d6cc1129ad`.
- `git rev-parse HEAD` на момент ревью: `2bcde131581a6130f971dcef167299d6cc1129ad`.
- Вердикт: `green` · High 0 · Medium 0 · маршрут `fix`.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/744-floor-geometry-key`, коммит `2bcde131581a` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `0272ec42089ccc881841358169ad6e9105944e7c`
```
git log --all --format='%H %T' | grep 0272ec42089c
```
- Тело issue: `9dec80eead95ea0cbc014364d7ed09eaef1f7f45b7e2c70f97f1a95c586ac465`
- Вердикт конвейера: `green` · High 0 · маршрут `fix`
<!-- hp:usage input_tokens=4060 output_tokens=25030 cache_creation_input_tokens=114145 cache_read_input_tokens=2651158 num_turns=53 -->