mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 19:58:50 +00:00
177 lines
15 KiB
Markdown
177 lines
15 KiB
Markdown
# CODE-REVIEW-252-r2
|
||
|
||
Вердикт: зелёный · заход r2 · блокирующих циклов израсходовано 0 из 4 · High: 0 · Medium: 0
|
||
|
||
## Скоуп раунда: почему это переиздание r2, а не новый разбор с нуля
|
||
|
||
Этот запуск — повторное проведение того же раунда r2, а не заход r3. Round r2
|
||
уже был проведён и опубликован (комментарий issue от 2026-08-23T07:56:33Z,
|
||
документ `docs/reviews/CODE-REVIEW-252-r2.md`, зелёный вердикт, High:0/Medium:0),
|
||
но пайплайн не довёл дело до конца: автор сообщил (2026-08-23T07:56:45Z), что
|
||
автоматический прогон [упал](https://github.com/Matysh/houseplan-card/actions/runs/32625878719)
|
||
и статусная метка не переставилась. С точки зрения оркестратора раунд не
|
||
завершён (бюджет §4 не потрачен: зелёный вердикт цикл не расходует), поэтому
|
||
задача пришла на повторное r2, а не на r3.
|
||
|
||
Проверено, что переиздавать нечего заново с нуля:
|
||
|
||
- SHA, на котором был получен предыдущий вердикт r2: `b58136aa2cc943652af5adb8a94047b668d68dc6`.
|
||
- Текущий HEAD: `3741bddc6236ffe3d85965dc630704e578561710`.
|
||
- `git diff b58136a..HEAD --stat` → ровно один файл:
|
||
`docs/reviews/CODE-REVIEW-252-r2.md | 249 +++++++++++++++++++++++++++++++++++++`
|
||
(1 file changed, 249 insertions(+)) — это САМ ранее опубликованный документ
|
||
ревью, закоммиченный шагом публикации предыдущего (упавшего после вердикта)
|
||
прогона. Ни один файл `src/**`, `demo/**`, `docs/CANVAS.md` и т.п. между
|
||
`b58136a` и текущим HEAD не менялся.
|
||
|
||
Значит, весь код, который уже был полностью разобран в CODE-REVIEW-252-r1
|
||
(на пре-ребейзном коммите, полный разбор) и CODE-REVIEW-252-r2 (на
|
||
пост-ребейзном `b58136a`, тоже полный разбор — ребейз на ушедший вперёд `dev`
|
||
подпадает под §7.2), остался байт-в-байт тем же кодом. Дельта этого раунда —
|
||
пустая по существу. Полный разбор AC по коду в третий раз подряд на неизменном
|
||
дереве был бы именно той «потерей времени», от которой явно предостерегает
|
||
инструкция («полные наборы — это предрелизный гейт, а не гейт ревью»).
|
||
|
||
Дополнительно проверено расхождение с `origin/dev`, который тем временем ушёл
|
||
дальше собственной прошлой проверки в CODE-REVIEW-252-r2 (там уже был учтён
|
||
`a952f5f`/#256 и его review-документ `2d1fca1`, оба признаны не пересекающимися
|
||
с #252 по файлам). С тех пор `dev` получил ещё два коммита:
|
||
|
||
- `10999a5` — `ci(process): привести ветку к dev до код-ревью, а не после` (#257),
|
||
правит только `.github/workflows/process.yml`;
|
||
- `4b6331f` — `docs(process): описать приведение ветки к dev до код-ревью` (#257),
|
||
правит только `PROCESS.md`.
|
||
|
||
Оба — чистый процесс/CI, ноль пересечения по файлам с диффом #252
|
||
(`src/space-reference-repair.ts`, `plan-optimizer.ts`, `houseplan-card.ts`,
|
||
`styles.ts`, i18n, доки CANVAS/CONFIG-COMPATIBILITY/USER-GUIDE, golden-сцены).
|
||
Ретроактивно новое правило «ребейзить до ревью» на уже идущий с r1 код-ревью
|
||
#252 не распространяется (правило описывает будущий шаг пайплайна перед
|
||
следующим запуском ревью, а не требование к уже проверенному коду). Само
|
||
слияние ветки #252 в `dev`, как и раньше, потребует технического ребейза —
|
||
это не меняет оценку текущего диффа.
|
||
|
||
## Закрытие раунда r1 (CODE-REVIEW-252-r1)
|
||
|
||
| Находка r1 | Чем закрыта | Где видно |
|
||
|---|---|---|
|
||
| Low, снято с записью на будущее: мёртвый ключ `gs.optimize_reference_warning` остался в `en.json`/`ru.json`, код его больше не вызывает | Ключ полностью удалён из обоих словарей коммитом `6c779b5` | `git diff origin/dev...HEAD -- src/i18n/en.json src/i18n/ru.json` — строка присутствует только как удаление; `test/i18n.test.mjs:77` (`assert.doesNotMatch(..., /this\._t\('gs\.optimize_reference_warning'/)`) прогнан лично в этом раунде в составе `npm test` (1140/1140) — зелёный |
|
||
|
||
Это закрытие не изменилось со времени предыдущего r2 — код тот же самый.
|
||
|
||
## Унаследовано из r1
|
||
|
||
Полный построчный разбор кода (`src/space-reference-repair.ts` целиком,
|
||
изменённые фрагменты `plan-optimizer.ts`/`houseplan-card.ts`/`styles.ts`,
|
||
все юнит- и smoke-тесты, канонические доки, release-артефакты) взят из
|
||
CODE-REVIEW-252-r1 (документ в `docs/reviews/CODE-REVIEW-252-r1.md`, SHA
|
||
проверки в этом раунде — `b58136aa2cc943652af5adb8a94047b668d68dc6`, где этот
|
||
разбор был повторён ПОЛНОСТЬЮ заново после ребейза, а не как наследование —
|
||
см. раздел «Скоуп» того документа). Наследуется без повторного построчного
|
||
чтения в этом раунде:
|
||
|
||
- классификация владельца (`absent`/`live-in-missing-space`/`unverified`) —
|
||
доказательная схема, три исхода, fail-closed при неполном/неавторитетном
|
||
registry и при неизвестном namespace (AC1–AC3);
|
||
- отчёт без внутренних id в основном тексте, id — только в свёрнутых
|
||
«Подробностях» (AC4);
|
||
- Preview/Cancel/Apply/Undo и идемпотентность #248 не регрессируют (AC5, AC6);
|
||
- осознанное и задокументированное расширение поведения detach у #244
|
||
(немедленное авто-удаление stale-позиции заменено общей классификацией;
|
||
переименованные тесты и `docs/CANVAS.md`/`docs/CONFIG-COMPATIBILITY.md`
|
||
прямо называют это заменой, а не регрессом);
|
||
- `docs/CANVAS.md:494-497` заменён (не дополнен), release-артефакты (оба
|
||
changelog, канонические доки, синхронные bundle-копии) в одном
|
||
поведенческом коммите с `User-Visible: yes`;
|
||
- golden-семантика двух #252-сцен (`optimize-orphan-references-dark-en`,
|
||
`optimize-orphan-references-light-ru`), доказанная полным
|
||
`golden:verify` (97/97) дважды — на пре-ребейзном дереве в r1 и на
|
||
пост-ребейзном `b58136a` в r2.
|
||
|
||
Основание доверять этому наследованию без повторного чтения — не слова
|
||
автора, а свежая проверка в этом раунде (см. ниже), что дерево с тех пор не
|
||
изменилось ни на байт.
|
||
|
||
## Как проверялось в этом раунде
|
||
|
||
Лично прогнано на текущем HEAD (`3741bdd`), не со слов автора и не по
|
||
памяти о прошлых раундах:
|
||
|
||
- `npx tsc --noEmit` → чисто, без вывода;
|
||
- `npm test` → 1140/1140 pass, 0 fail, 0 skipped (включает
|
||
`test/model-invariants.test.mjs` — 12/12, в т.ч. `#253: исчезнувшая запись
|
||
толщины` и `readModel понимает экспорт/config/get/сырой config (#254)` —
|
||
обязательный гейт, диф трогает layout-ссылки на пространства);
|
||
- `npm run build` → зелёный; `sha256sum dist/houseplan-card.js
|
||
custom_components/houseplan/frontend/houseplan-card.js` →
|
||
`e5389ba8e8250c6030fb5365b81619b0d2b4687b4c32f2f2c227ca527b7dbcec` для
|
||
обеих копий — **тот же хеш**, что зафиксирован в CODE-REVIEW-252-r1
|
||
независимо от меня в этом раунде; совпадение хеша — самостоятельное
|
||
машинное доказательство того, что исходный код не менялся с r1/r2, а не
|
||
доверие на слово;
|
||
- `npm run bundle:sync` → пересобрал и синхронизировал нетрекаемую
|
||
стенд-копию `demo/srv/assets/houseplan-card.js` (не коммитится с #255) —
|
||
зелёно;
|
||
- `node scripts/check-docs.mjs` → «Documentation checks passed (7 files, 10
|
||
external links)» — обязателен, диф трогает `src/**`;
|
||
- `node scripts/mutation-gate.mjs --check` (дешёвый режим, без пересборки
|
||
бандла на каждого мутанта) → 139/139 `ok`, включая все четыре мутанта
|
||
этой темы: `orphan-space-detach-disabled`,
|
||
`orphan-space-ambiguous-signature-guessed`,
|
||
`orphan-cleanup-partial-registry-deletes`,
|
||
`orphan-cleanup-proven-owners-kept`. Дорогой полный прогон (пересборка на
|
||
каждого мутанта) не повторялся: он уже дважды пройден целиком (r1 —
|
||
136/136, r2 — переподтверждён) на этом же дереве, а `--check` подтверждает,
|
||
что реестр патчей и код с тех пор не разошлись;
|
||
- `node scripts/smoke-select.mjs --base origin/dev --head HEAD` → те же 6
|
||
смоков, что в r1/r2: `smoke_orphan_space_references`, `smoke_grid_snap`,
|
||
`smoke_optimize_coordinate_canonicalization`,
|
||
`smoke_optimize_geometry_preflight`, `smoke_optimize_micro_interval`,
|
||
`smoke_warm_dialogs`; остальные 165 не пересекаются по символам
|
||
(инструмент не назвал других связей);
|
||
- все 6 отобранных смоков лично прогнаны headless-Chromium в этом раунде —
|
||
все `OK`, все булевы поля результата `true` (в т.ч.
|
||
`idsExistOnlyInClosedDetails`, `explicitCleanupRebuildsPreviewWithoutWriting`,
|
||
`undoRestoresDeadRefs` из `smoke_orphan_space_references`).
|
||
|
||
Не повторял в этом раунде (обоснование):
|
||
|
||
- **`golden:verify` (полный, 97 сценариев).** Уже пройден целиком дважды в
|
||
этом же код-ревью: в r1 на пре-ребейзном дереве и в r2 на `b58136a` —
|
||
оба раза 97/97, включая обе #252-сцены. Текущее дерево байт-в-байт
|
||
идентично `b58136a` (доказано выше диффом и совпадением SHA-256 бандла).
|
||
Третий полный прогон на неизменном дереве не добавил бы информации и
|
||
прямо противоречил бы правилу соразмерности гейтов ревью.
|
||
- **`mutation-gate.mjs` без `--check` (полная пересборка на мутанта).** По
|
||
той же причине — уже дважды 136+/136+ на этом дереве, `--check` в этом
|
||
раунде подтвердил отсутствие расхождения.
|
||
- **`python -m pytest tests_backend`** — диф не трогает
|
||
`custom_components/**/*.py` (только сгенерированный JS-бандл в той же
|
||
папке).
|
||
- **`npm run invariants -- --config <файл>`** — точечного экспорта живой
|
||
инсталляции для этой ветки по-прежнему нет; вместо него — `npm test`
|
||
прогнал `test/model-invariants.test.mjs` на всех fixture-моделях проекта
|
||
(см. выше), это тот же `checkReferences`, что стоит за флагом.
|
||
- **Performance-профили** — не названы в AC8, путь maintenance-only, не
|
||
render loop (§12 ТЗ).
|
||
- **Ручное браузерное тестирование** — не входит в конвейер ревью; заменено
|
||
headless smoke (свежепрогнанные) и дважды пройденным полным golden.
|
||
|
||
## Находки
|
||
|
||
Нет находок уровня High или Medium. Low-находка r1 (мёртвый i18n-ключ)
|
||
закрыта — см. таблицу выше.
|
||
|
||
## Итог
|
||
|
||
Код не изменился с зелёного вердикта предыдущего r2 (`b58136a`) ни на
|
||
байт — единственная разница в дереве это сам ранее опубликованный документ
|
||
ревью. Этот раунд — техническое переиздание того же вердикта после сбоя
|
||
пайплайна на шаге после публикации (перестановка метки), а не пересмотр
|
||
кода. Все дешёвые гейты, обязательные для каждого раунда, лично прогнаны
|
||
заново на текущем HEAD и зелёные, включая независимое совпадение SHA-256
|
||
собранного бандла с зафиксированным в r1. AC1–AC8 остаются подтверждёнными
|
||
полным разбором r1/r2 (см. «Унаследовано из r1» и исходные документы).
|
||
Дрейф `origin/dev` (#256, #257) не пересекается с диффом #252 и не требует
|
||
пересмотра. Новых issue не требуется.
|