mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 13:18:58 +00:00
134 lines
9.4 KiB
Markdown
134 lines
9.4 KiB
Markdown
# CODE-REVIEW — issue #528, заход r1
|
||
|
||
**SHA материала:** `f37ccdcebc3f454cb03c8cd25f5081a45eb4e22f` (рабочая копия уже на нём)
|
||
**Ветка:** `issue/528-marker-identity-witness`
|
||
**Класс изменения:** B (`demo/smoke_space_switch_transitions.mjs`) — issue переиспользован, продуктовый код и реестр мутантов не тронуты (совпадает с заявленным «Ограниченный объём»).
|
||
|
||
## Скоуп
|
||
|
||
Свидетель #525 (`demo/smoke_space_switch_transitions.mjs`) ловил мутант
|
||
`device-markers-rendered-without-keys` через побочный признак: отсутствие
|
||
бегущего перехода `box-shadow` на `.device-shell-frame` после переключения
|
||
пространства. #524 убрал этот переход из стилей (перф-регрессия Firefox),
|
||
признак стал тривиально истинным, и позиционное переиспользование DOM-узлов
|
||
маркеров перестало ловиться — свидетеля ослепили не намеренно, а как
|
||
побочный эффект соседней задачи.
|
||
|
||
Задача #528 узкая: маркерная половина свидетеля должна судить по идентичности
|
||
узла (`data-id` привязанного к узлу до/после переключения), а не по анимации.
|
||
Дверная половина (`op-leaf`/`op-arc`) остаётся как есть — там переход часть
|
||
продуктового контракта (#525) и её не просили трогать.
|
||
|
||
## Диф (весь, 16 строк)
|
||
|
||
Один файл, `git diff origin/dev...HEAD --stat`:
|
||
```
|
||
demo/smoke_space_switch_transitions.mjs | 17 ++++++++++++++++-
|
||
```
|
||
|
||
Добавлено:
|
||
1. Перед первым переключением (`c._pickSpace(ids[0])`) собираются ссылки на
|
||
все узлы `[data-hp="device"]` вместе с их `data-id` (`markersBefore`).
|
||
2. `markersDrawnInTheFirstSpace = markersBefore.length >= 3` — страховка от
|
||
вырожденного сравнения на пустом множестве (сама тоже проверяется
|
||
`checkAll`, дефолт `true`).
|
||
3. После второго `_pickSpace` вычисляется `reused` — узлы из `markersBefore`,
|
||
которые остались подключены (`isConnected`) и сменили `data-id`;
|
||
`noMarkerNodeReusedForAnotherDevice` и диагностический список
|
||
`reusedMarkerNodes` (ожидаемо пустой, `checkAll(res, { ..., reusedMarkerNodes: [] })`).
|
||
4. Старая проверка `noMarkerTransitionOnSwitch` (по переходу оболочки) не
|
||
удалена — она просто перестала быть единственной, что безопасно (AC не
|
||
требовал её убирать).
|
||
|
||
## Как проверялось
|
||
|
||
**Дешёвые гейты этого SHA уже зелёные** (Validate
|
||
[34572622663](https://github.com/Matysh/houseplan-card/actions/runs/34572622663),
|
||
success): `typecheck`/`test`/`build` не перегонял — diff не трогает `src/**`,
|
||
`test/**` юнитов, конфиги сборки. `node scripts/check-docs.mjs` также не
|
||
требуется: diff не задевает `src/**`, отпечаток скриншотов не устаревает.
|
||
|
||
`node scripts/smoke-select.mjs --base 78bc76073ea2...(merge-base) --head HEAD`
|
||
подтвердил ожидаемое: «Исполняемого frontend-диффа нет (`src/**/*.ts` не
|
||
тронут)», browser-smoke по этому инструменту не выбираются — выбирать
|
||
нечего, изменённый файл сам и есть свидетель.
|
||
|
||
Главная проверка — не общий гейт, а прямое доказательство по AC, и оно уже
|
||
есть на этом самом SHA в логах Validate, job «Мутанты по диффу (1/6)»
|
||
(id `103177915852`):
|
||
|
||
```
|
||
07:05:52 ok чистый прогон: node demo/smoke_space_switch_transitions.mjs
|
||
07:06:16 ok device-markers-rendered-without-keys: тест покраснел, как обязан
|
||
```
|
||
|
||
Это ровно то, что требуют AC2 и AC3: чистый (немутированный) прогон смока
|
||
целиком зелёный, и на замутированном коде (`repeat(devs, (d) => d.id, ...)` →
|
||
`devs.map(...)` в `src/houseplan-card.ts:11787`, реестр
|
||
`scripts/mutation-gate.mjs:7325`) свидетель краснеет. Не заявление автора —
|
||
факт из лога CI на материале ревью.
|
||
|
||
Дополнительно прочтением (без исполнения):
|
||
- `demo/serve.mjs:68-78` (`check`/`checkAll`) — сравнение через
|
||
`JSON.stringify`, так что `reusedMarkerNodes: []` в `checkAll` действительно
|
||
требует пустой массив, а не просто «поле определено».
|
||
- `src/space-render.ts:607` — реальная разметка маркера несёт
|
||
`data-hp="device" data-id="${d.id}"`, соответствует селектору смока.
|
||
- `src/styles/devices.styles.ts:200-215` — `.device-shell-frame` сейчас имеет
|
||
только `transition: border-color .15s, opacity .2s` (без `box-shadow`),
|
||
подтверждает описанную в issue причину: старый переход правда убран #524,
|
||
и старая проверка правда стала тривиальной.
|
||
- Логика `reused` (строки 124-129): узел считается «переиспользованным
|
||
чужим id», только если он ещё подключён к дереву (`isConnected`) и его
|
||
`data-id` изменился относительно зафиксированного до переключения — именно
|
||
позиционное переиспользование, а не обычное удаление узла или сохранение
|
||
того же устройства между пространствами (когда `data-id` не меняется).
|
||
Разобрано корректно.
|
||
|
||
## Проверено и корректно
|
||
|
||
- AC1 — реализовано: сравнение по ссылкам на узлы, а не по CSS-переходу;
|
||
подтверждена и защита от вырожденного случая (`markersDrawnInTheFirstSpace`).
|
||
- AC2 — доказано логом CI на этом SHA (мутант красный), не голым заявлением.
|
||
- AC3 — доказано тем же логом («чистый прогон» = OK целиком); дверная
|
||
половина (`op-leaf`/`op-arc`, `noOpeningTransitionOnSwitch`,
|
||
`theTwoDoorsDifferInState` и т. д.) не тронута, дифф это подтверждает.
|
||
- Трейлеры: `Issue: #528`, `User-Visible: no` — верно, диф не меняет
|
||
видимое поведение продукта, changelog не требуется.
|
||
- Скоуп: ни продуктовый код, ни `scripts/mutation-gate.mjs` не изменены —
|
||
соответствует заявленному в issue ограничению.
|
||
|
||
## Чего не проверял и почему
|
||
|
||
- `npx tsc --noEmit`, `npm test`, `npm run build`, сверку бандла —
|
||
не требуется: diff не трогает `src/**`/`test/**`/конфиги сборки, а Validate
|
||
на этом же SHA уже зелёный.
|
||
- `node scripts/check-docs.mjs` — diff не трогает `src/**`.
|
||
- `npm run invariants` — diff не трогает геометрию/toplogy/marker.space.
|
||
- `npm run golden:verify` — diff не может изменить видимый рендер (только
|
||
тестовый файл).
|
||
- `python -m pytest tests_backend` — Python не тронут.
|
||
- Полный прогон `demo/smoke_*.mjs` вручную — не требуется отдельно: ровно тот
|
||
смок, который меняется, уже прогнан CI на материале ревью дважды (чистый и
|
||
замутированный), что сильнее локального прогона без мутанта.
|
||
|
||
## Вердикт
|
||
|
||
Зелёный. AC1–AC3 выполнены и подтверждены логом CI на самом материале
|
||
ревью, а не заявлением автора; изменение в границах заявленного скоупа,
|
||
трейлеры верны.
|
||
|
||
---
|
||
|
||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||
|
||
## Материал раунда
|
||
|
||
- Ветка: `issue/528-marker-identity-witness`, коммит `f37ccdcebc3f` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||
- Дерево материала: `3a16a24c59b27eac3280c63ce77f48ca13875750`
|
||
```
|
||
git log --all --format='%H %T' | grep 3a16a24c59b2
|
||
```
|
||
- Тело issue: `f178b89645d3d0967d356c110b81f4262fd676aa9b7bf30203cb8ffb9b63190b`
|
||
- Вердикт конвейера: `green` · High 0
|