9.4 KiB
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 ++++++++++++++++-
Добавлено:
- Перед первым переключением (
c._pickSpace(ids[0])) собираются ссылки на все узлы[data-hp="device"]вместе с ихdata-id(markersBefore). markersDrawnInTheFirstSpace = markersBefore.length >= 3— страховка от вырожденного сравнения на пустом множестве (сама тоже проверяетсяcheckAll, дефолтtrue).- После второго
_pickSpaceвычисляетсяreused— узлы изmarkersBefore, которые остались подключены (isConnected) и сменилиdata-id;noMarkerNodeReusedForAnotherDeviceи диагностический списокreusedMarkerNodes(ожидаемо пустой,checkAll(res, { ..., reusedMarkerNodes: [] })). - Старая проверка
noMarkerTransitionOnSwitch(по переходу оболочки) не удалена — она просто перестала быть единственной, что безопасно (AC не требовал её убирать).
Как проверялось
Дешёвые гейты этого SHA уже зелёные (Validate
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 на самом материале ревью, а не заявлением автора; изменение в границах заявленного скоупа, трейлеры верны.
Материал раунда
- Ветка:
issue/528-marker-identity-witness, коммитf37ccdcebc3f— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
3a16a24c59b27eac3280c63ce77f48ca13875750git log --all --format='%H %T' | grep 3a16a24c59b2 - Тело issue:
f178b89645d3d0967d356c110b81f4262fd676aa9b7bf30203cb8ffb9b63190b - Вердикт конвейера:
green· High 0