mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
Ревью #682 r1, Medium: перенос добавляет документу уровень вложенности (`docs/reviews/X.md` → `legacy/reviews/<тег>/X.md`, `docs/specs/` → `legacy/specs/`), а относительные ссылки внутри перенесённых документов и в соседях, ссылавшихся на них, никто не пересчитывал — на `97d19268` 53 битые ссылки в 46 файлах (заявление «все 26 резолвятся» в `7feb6177` было верно только до переноса документов ревью). Гейты архив не смотрят. `reviews-archive.mjs`: `repairLinks` пересчитывает ссылку, если она не резолвится от нового места, а цель находится от нового или старого места через карту переносов; битая и до переноса ссылка не трогается. `--apply` делает это само, `--repair-links=<rev>` — для всех переименований `<rev>..HEAD`, `--check-links` печатает битые. Этим коммитом `--repair-links=origin/dev` переписал ровно 53 ссылки в 46 файлах; остались две прежние «...»-заглушки в CODE-REVIEW-448-r2 (битые и на dev). Тесты: перенесённый документ, сосед со ссылкой в архив, ТЗ со ссылкой на позже перенесённое ревью, битая-до-переноса не трогается, в `legacy/` битых нет; мутант `reviews-archive-links-from-new-place-only`. PROCESS §2.10 и DEVELOPMENT › Release называют переписывание и `--check-links`. Issue: #682 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
161 lines
14 KiB
Markdown
161 lines
14 KiB
Markdown
# CODE-REVIEW-204-r1
|
|
|
|
- Issue: [#204](https://github.com/Matysh/houseplan-card/issues/204)
|
|
- ТЗ: [docs/specs/204-space-create-display-defaults.md](../../specs/204-space-create-display-defaults.md)
|
|
- Ветка: `issue/204-space-create-display-defaults`, коммит `12c4f77`
|
|
- Диапазон: `origin/dev..HEAD` = `f703242` (spec) → `ec0ccaf` (spec review doc) → `12c4f77` (реализация)
|
|
- Вердикт: **зелёный**
|
|
|
|
## Скоуп ревью
|
|
|
|
Этап `code` по PROCESS.md §2.7: реализация против ТЗ #204 (единственный
|
|
implementation-коммит `12c4f77`, `User-Visible: yes`). Задача — честные
|
|
create-dialog defaults для «Всегда отображать границы комнат» и «Отображать
|
|
названия комнат»: File `false/false`, Draw `true/true`, сохранение выбора
|
|
пользователя (`displayTouched`) при последующих File↔Draw, и убрать скрытую
|
|
Save-подмену `draw && mode==='create' ? true : d.showBorders`. Обычный Create
|
|
и Floors/Areas onboarding должны следовать одной политике.
|
|
|
|
## Как проверялось
|
|
|
|
1. Прочитаны в порядке: `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` §2.7,
|
|
тело issue #204 и все комментарии (аналитика, ТЗ, код-ревью спеки,
|
|
реализация), `docs/USER-GUIDE.ru.md` (раздел «Пространства» — таблица
|
|
«Источник плана» уже содержала термин «Без изображения» до этого коммита),
|
|
`docs/UX-MODES.md` (подтверждено: описывает только рантайм-резолвер
|
|
`show_borders`/`show_names`, не create-dialog UX — не затронут, non-scope
|
|
ТЗ верен).
|
|
2. Прочитан весь `git diff origin/dev...HEAD` построчно: новый модуль
|
|
`src/space-dialog.ts`, точки интеграции в `src/houseplan-card.ts`
|
|
(`_openSpaceDialog('create')`, `_openNextImport`, `_saveSpaceDialog`,
|
|
радиокнопки File/Draw, оба `_boolInput` переключателя), новый unit-файл
|
|
`test/space-dialog.test.mjs`, новый браузерный smoke
|
|
`demo/smoke_space_create_display_defaults.mjs`, правка существующего
|
|
`demo/smoke_space_settings.mjs`, запись мутанта в
|
|
`scripts/mutation-gate.mjs`, документация (`CHANGELOG.md`/`.ru.md`,
|
|
`USER-GUIDE.ru.md`, `TESTING.md`, `STATUS.md`, `docs/specs/README.md`),
|
|
`tsconfig.test.json`.
|
|
3. Построчно сверена корневая причина ТЗ (§3) с диффом: скрытая ветка
|
|
`show_borders: draw && d.mode === 'create' ? true : d.showBorders` (и
|
|
аналог для `show_names`) в `_saveSpaceDialog()` заменена на прямую запись
|
|
`d.showBorders`/`d.showNames` — подмена действительно убрана, не
|
|
переименована.
|
|
4. Проверен весь конечный автомат `displayTouched` (§6 ТЗ) против
|
|
`src/space-dialog.ts`: `initialSpaceDisplayDraft` (File `false/false`,
|
|
`displayTouched:false`), `switchSpacePlanSource` (проецирует source-default
|
|
пока `!displayTouched`, иначе меняет только `source`), `touchSpaceDisplay`
|
|
(ставит `displayTouched:true`, второй control не трогает) — все 6 пунктов
|
|
контракта покрыты один в один, скрытых переходов не осталось.
|
|
5. Проверено, что обычный Create (`_openSpaceDialog('create')`,
|
|
`src/houseplan-card.ts:13239`) и каждый шаг onboarding (`_openNextImport`,
|
|
`src/houseplan-card.ts:13613`) используют один и тот же
|
|
`...initialSpaceDisplayDraft()` — общий чистый state, без риска утечки
|
|
touched между этажами (AC5).
|
|
6. Проверено, что Edit (`src/houseplan-card.ts:13214`) выставляет
|
|
`displayTouched: true` сразу — источник переключается без авто-сброса
|
|
уже сохранённых values (AC6), что и есть корректное поведение «Edit не
|
|
должен применять create-only defaults».
|
|
7. Прогнаны все заявленные автором гейты локально (см. таблицу ниже),
|
|
включая исполнение (не чтение) целевого мутанта — тест обязан был
|
|
покраснеть без патча и покраснел на мутанте.
|
|
8. Проверены трейлеры всех трёх коммитов диапазона (`Issue: #204` на каждом;
|
|
`User-Visible: no` на двух docs-коммитах, `User-Visible: yes` на
|
|
реализации) и что оба changelog (`docs/CHANGELOG.md`,
|
|
`docs/CHANGELOG.ru.md`) правлены в том же коммите `12c4f77`, что и продукт
|
|
(`git show --stat 12c4f77`).
|
|
9. Проверено побайтовое совпадение трёх копий бандла после чистой пересборки
|
|
(`dist`, `custom_components/houseplan/frontend`, `demo/srv/assets`) —
|
|
идентичны и `git diff` после пересборки пуст, т.е. закоммиченные копии не
|
|
разошлись с исходником.
|
|
|
|
## Гейты — что прогнано и результат
|
|
|
|
| Гейт | Статус | Результат |
|
|
|---|---|---|
|
|
| `npx tsc --noEmit` | прогнан | green, без ошибок |
|
|
| `npm test` | прогнан | 916/916 green (включая 4 новых теста `space-dialog.test.mjs`) |
|
|
| `npm run build` + сверка 3 копий бандла | прогнан | build green; `md5sum` трёх копий совпадает; `git diff --stat` после build пуст |
|
|
| `git diff --check` | прогнан | без ошибок пробелов |
|
|
| `node demo/smoke_space_create_display_defaults.mjs` | прогнан | green (`OK`), проверены все состояния AC1–AC8 |
|
|
| `node demo/smoke_space_settings.mjs` | прогнан | green (`OK`), regression не сломан |
|
|
| `node scripts/mutation-gate.mjs --check` | прогнан | green, якорь мутанта найден ровно 1 раз |
|
|
| `node scripts/mutation-gate.mjs --id=space-create-hidden-display-override` | прогнан (исполнение) | «чистый прогон» зелёный без мутанта, с мутантом — «тест покраснел, как обязан», поймано 1/1 |
|
|
|
|
**Не прогонялось и почему:**
|
|
- `npm run golden:verify` — диф не меняет геометрию, рендер, стили или слои
|
|
(только checked-state двух HA switches и порядок записи двух boolean в
|
|
Save); визуального следствия нет, ТЗ §10 явно исключает golden.
|
|
- Полный набор `demo/smoke_*.mjs` (127 файлов) — задача касается одной
|
|
поверхности (create-dialog + onboarding wizard), два целевых смока плюс
|
|
regression-смок покрывают её; по процессу полный набор — предрелизный
|
|
гейт, а не гейт ревью.
|
|
- `python -m pytest tests_backend -q` — диф не затрагивает
|
|
`custom_components/houseplan/**/*.py`; backend принимает произвольные bool
|
|
без изменений (подтверждено в самой ТЗ и не оспаривается диффом).
|
|
- performance-профили — путь не является perf-чувствительным (локальные
|
|
boolean transitions без I/O), в AC не назван.
|
|
|
|
## Проверка AC (PROCESS §2.7: автотест + доказано, что умеет падать, либо чтение с явной пометкой)
|
|
|
|
| AC | Как доказан | Итог |
|
|
|---|---|---|
|
|
| AC1 | `smoke_space_create_display_defaults.mjs`: `freshFile`/`untouchedDraw` | подтверждено исполнением |
|
|
| AC2 | тот же smoke: Save сразу после Draw → `savedMixed`/`reopenedMixed` (мутантно доказано отдельно на mixed-паре) | подтверждено исполнением |
|
|
| AC3 | unit `space-dialog.test.mjs` («every supported Draw pair...») + smoke `mixedTouched`/`savedMixed`/`reopenedMixed` | подтверждено исполнением |
|
|
| AC4 | smoke `untouchedDraw`/`untouchedFileAgain` (до touch) и `mixedFile`/`mixedDrawAgain` (после touch) | подтверждено исполнением |
|
|
| AC5 | smoke `onboardingFirst`/`onboardingSecond` — второй этаж не наследует touched первого | подтверждено исполнением |
|
|
| AC6 | smoke `savedFileDefaults` (File create) + `editSourcePreservesPair` (Edit не сбрасывает при смене source) | подтверждено исполнением |
|
|
| AC7 | smoke `cancelDidNotWrite` (снапшот `_serverCfg` до/после Cancel идентичен) + `freshAfterCancel` | подтверждено исполнением |
|
|
| AC8 | unit «source and display transitions are immutable and preserve unrelated fields» (title/cellCm через spread) + regression `smoke_space_settings.mjs` (atticSettings побайтно) | подтверждено исполнением |
|
|
| AC9 | `mutation-gate.mjs --id=space-create-hidden-display-override`: старый hidden override восстановлен патчем, гард обязан покраснеть — исполнено, поймано 1/1 | подтверждено исполнением, тест доказанно умеет падать |
|
|
| AC10 | таблица гейтов выше | подтверждено исполнением |
|
|
|
|
Отдельно проверено чтением, не исполнением: путь `_warmReviveDialog` (§2810)
|
|
восстанавливает весь снятый снапшот `_spaceDialog` целиком через spread —
|
|
поле `displayTouched` уже присутствует в снапшоте на момент захвата, разрыва
|
|
контракта при warm-remount нет.
|
|
|
|
## Находки
|
|
|
|
Нет ни High, ни Medium, ни Low.
|
|
|
|
## Что проверено и корректно
|
|
|
|
- Скрытая Save-подмена `draw && mode==='create' ? true : d.showBorders`
|
|
(и аналог для `show_names`) удалена буквально, а не переименована —
|
|
`src/houseplan-card.ts` теперь пишет ровно `d.showBorders`/`d.showNames`.
|
|
- Общий helper `src/space-dialog.ts` используется одинаково обычным Create,
|
|
onboarding (`_openNextImport`) и радиокнопками — реализация п. «Onboarding
|
|
расходится с обычным Create» риска (§11 ТЗ) закрыта одной точкой правды,
|
|
а не дублированием логики.
|
|
- Edit-режим стартует с `displayTouched: true`, что предотвращает
|
|
create-only default reset при смене источника существующего пространства.
|
|
- Мутационный тест не просто присутствует «для галочки»: реально исполнен,
|
|
подтверждает что тест красный без патча (`runCleanGuards`) и красный
|
|
именно на мутанте — дисциплина «тест умеет падать» соблюдена.
|
|
- Три копии бандла синхронны, трейлеры и оба changelog в одном коммите —
|
|
требования AGENTS.md/PROCESS.md выполнены.
|
|
- Терминология `docs/USER-GUIDE.ru.md` («Без изображения») уже существовала
|
|
в этом разделе до правки — не изобретена, взята из документа.
|
|
- `docs/specs/README.md`: порядок строк в таблице был не отсортирован по
|
|
номеру issue уже до этого коммита (не новая проблема, ссылка на #204
|
|
вставлена корректно).
|
|
|
|
## Чего не проверял
|
|
|
|
- Полный browser smoke-набор (127 файлов), `golden:verify`,
|
|
`performance_smoke` и backend pytest — не запускались; обоснование см.
|
|
таблицу гейтов выше. Остаются предрелизным гейтом по процессу.
|
|
- Ручная проверка в реальном браузере (визуальный клик по диалогу) не
|
|
проводилась — путь доказан Playwright-смоками поверх собранного бандла,
|
|
что эквивалентно для этой поверхности (нет ручного цикла тестирования на
|
|
этапе code review по регламенту).
|
|
- Touch/keyboard input specifics (real device) не проверялись — ТЗ §8
|
|
утверждает общий `change`-обработчик для pointer/touch/keyboard, что
|
|
подтверждено чтением кода (`_boolInput` — единая точка на `<ha-switch>`/
|
|
`<input type=checkbox>`), не отдельным touch-тестом.
|
|
- `docs/specs/040-floor-area-onboarding.md` целиком не перечитывался повторно
|
|
на этапе code review — при spec review уже подтверждено отсутствие
|
|
конфликтующих утверждений про defaults; код (`_openNextImport`) реализует
|
|
именно контракт §6 ТЗ #204, что и было предметом проверки здесь.
|