19 KiB
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. - Единственная содержательная правка — поднятие
bundleBytesbaseline — это 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).- Одно число — один источник:
bundleBytes2 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) — зелёный вердикт цикла не образует.
Материал раунда
- Ветка:
issue/744-floor-geometry-key, коммит2bcde131581a6130f971dcef167299d6cc1129ad. git rev-parse HEADна момент ревью:2bcde131581a6130f971dcef167299d6cc1129ad.- Вердикт:
green· High 0 · Medium 0 · маршрутfix.
Материал раунда
- Ветка:
issue/744-floor-geometry-key, коммит2bcde131581a— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
0272ec42089ccc881841358169ad6e9105944e7cgit log --all --format='%H %T' | grep 0272ec42089c - Тело issue:
9dec80eead95ea0cbc014364d7ed09eaef1f7f45b7e2c70f97f1a95c586ac465 - Вердикт конвейера:
green· High 0 · маршрутfix