15 KiB
SPEC-REVIEW-464-r1
- Issue: https://github.com/Matysh/houseplan-card/issues/464
- Этап: ТЗ (PROCESS.md §2.4), трек — полный
- ТЗ:
docs/specs/464-zigbee-topology-layer-order.mdна веткеissue/464-zigbee-topology-layer - Заход: r1 (первый), блокирующих циклов израсходовано 0/4
- Материал ревью: ветка
issue/464-zigbee-topology-layer, HEADaae9efb9ff251ef1471cab685dee2c8c785dea5c, коммит «docs: specify Zigbee topology layer order» (Issue: #464·User-Visible: no). Диапазон изменений отorigin/dev: толькоdocs/specs/464-zigbee-topology-layer-order.md(новый, 455 строк) иdocs/specs/README.md(+2/-1). Продуктовый код не тронут — соответствует хендоффу автора и статусуS4-spec-review.
Скоуп ревью
Задача переведена аналитикой с trivial на полный трек: причина названа явно
(изменение публичного контракта слоёв, закреплённого в #54/#457, пересечение
full-card compositor/lazy overlay/live-camera projection) — критерий §5
«нет нового UX-контракта» не проходит, и это названо, а не подразумевается.
Продуктовых вопросов у владельца по существу два, и оба уже закрыты его же
комментарием в issue до написания ТЗ: точный порядок трёх уровней и параметры
окантовки серого пунктира (1 px, #2e2e2e, просветы сохраняются). ТЗ проверено
на точное соответствие этому комментарию.
Как проверялось
- Прочитаны
docs/SCOPE.md,AGENTS.md,PROCESS.mdцеликом (включая §2.4, §2.5, §2.10, §5, §7.1, §7.2), тело issue #464 и все пять комментариев (включая уточнение владельца, две редакции аналитики и хендофф автора). - Прочитан документ ТЗ целиком, сверен на присутствие всех разделов §7.1.
- Проверены на согласованность с ТЗ канонические документы подсистемы —
docs/specs/054-zigbee-topology-overlay.md,docs/specs/457-zigbee-route-arrows.md,docs/ARCHITECTURE.md(раздел «Contextual Zigbee topology»),docs/UX-MODES.md,docs/USER-GUIDE.ru.md(раздел про связи Zigbee). - Технические утверждения §3 (root cause) сверены построчно с текущим кодом
dev— не как код-ревью, а чтобы отличить подтверждённый факт от догадки, выданной за решение:- место монтирования:
renderZigbeeTopologyOverlay(...)вызывается прямо перед<div class="devlayer" data-hp-live-layer="camera">вsrc/houseplan-card.ts:11827→:11839— подтверждает «overlay — sibling перед.devlayer»; z-index::hostвsrc/hp-zigbee-topology-overlay.ts:45=5,.devlayerвsrc/styles/plan.styles.ts:1306-1310=6— подтверждает заявленный конфликт уровней;- двойная camera-проекция:
data-hp-live-layer="camera"сейчас стоит и на host-теге оверлея (src/zigbee-topology-overlay-bridge.ts:21), и на.devlayerнезависимо, аlive-viewport.ts:101,155перебирает оба совпаденияquerySelectorAll— подтверждает мотивацию §7.4 «убрать собственную camera-проекцию у вложенного overlay»; - контракт unknown-LQI сегодня: один
<line stroke-width=2 stroke-dasharray="5 5">без обводки (src/hp-zigbee-topology-overlay.ts:237-238), плюс глобальноеline { vector-effect: non-scaling-stroke }(строка 47) — подтверждает, что план «второй совпадающий stroke шире, тот же non-scaling-stroke» технически реализуем без новых свойств; docs/specs/054-...md:154-155действительно фиксирует «над архитектурой/decor, но под device markers» — старый контракт, который #464 заменяет, назван и процитирован верно.
- место монтирования:
- Проверена реализуемость заявленного способа доказательства AC, а не только
его название: raster-probe через
createImageBitmap/OffscreenCanvas) — уже рабочий паттерн вdemo/smoke_device_icon_pixel_alignment.mjs,demo/smoke_active_chain_ink.mjs,demo/smoke_grid_scale_invariance.mjs,demo/golden/run.mjs;npm run benchmark:zigbee-topologyуже существует вpackage.json;scripts/mutation-gate.mjsуже содержит мутанты дляzigbee-topology*(zigbee-topology-zha-read-starts-scan,zigbee-topology-ambiguous-marker-selectedи др.) — расширение тем же инструментом, не изобретение нового. - Проверены трейлеры коммита (
Issue: #464,User-Visible: no— корректно для документации без продуктового поведения) и двусторонняя связь issue ↔ ТЗ ↔docs/specs/README.md(запись добавлена, ссылка на файл и issue на месте). - Дешёвые гейты не гонялись повторно: диапазон правок — только
docs/specs/**(класс C), продуктовый код не менялся,typecheck/test/buildне могут покраснеть от .md-файла. Указанный в контексте зелёный Validate на этом же SHA (aae9efb9) относится к предыдущему код-ревью, а не к этому документу; для спек-ревью он не требуется и не использовался как замена чтения.
Находки
Не найдено ни одной блокирующей (High) находки. Находок Medium/Low в скоупе задачи и вне его — нет.
Ниже — что отдельно проверялось на «догадку, выданную за факт», и почему не стало находкой:
- Три уровня z-порядка (§4, §7.1) — не придуманы автором, а дословно повторяют уточнение владельца от 2026-09-05 в комментарии issue. Совпадение точное.
- Параметры окантовки unknown-LQI (§8:
#2e2e2e, 4 px casing / 2 px core → 1 px с каждой стороны, сохранённые просветы) — арифметика прямо выводится из уточнения владельца («обводка 1 px», «сохранение прозрачных промежутков»), а не изобретена. - Технические причины, почему «просто поднять z-index» и «снять stacking
context с
.devlayer» не работают (§3) — подтверждены чтением реального кода, а не заявлены голословно (см. «Как проверялось», п.4). - Технические решения реализации (namespaced-атрибут на
.dev, boundedMutationObserver(childList), второй<line>вместо SVG-фильтра, локальные уровни 7/8) вынесены в явный раздел §20 «Принятые технические предположения — можно менять на ревью» — это правильная граница §7.1: не продуктовый вопрос владельцу, а решаемая автором и оспариваемая ревьюером деталь. Возражений по существу к перечисленным пяти пунктам нет: способ (второй непрерывный<line>той же геометрии) корректно даёт кромку без превращения зазоров в сплошную линию, аchildList-only observer с отключением вdisconnectedCallbackсоответствует уже описанному в §12 требованию «не создавать цикл/leak». - Открытых продуктовых вопросов к владельцу в тексте ТЗ нет, и в текущем виде они и не нужны: оба вопроса, которые вообще относятся к продуктовому классу (§7.1: что видно, какой объём изменений), уже закрыты его же комментарием до начала написания ТЗ.
Что проверено и корректно
- Все обязательные разделы §7.1 присутствуют: сценарий (§1) · что человек увидит до/после (§2) · проблема и подтверждённая причина (§3) · скоуп (§5) и не-скоуп (§6) · контракт поведения (§7-8) · режимы/touch/доступность (§9) · модель данных и миграция (§10) · i18n (§11) · AC1-AC3 с доказательством (§14) · план автотестов (§15) · риски (§17) · откат (§18) · release-артефакты (§19).
- AC1-AC3 пронумерованы, каждый указывает способ доказательства
(
smoke+ raster + ревью кода /smoke+ mutation), формулировки однозначны — можно проверить по конкретным пиксельным точкам и computed stacking level, а не по общему впечатлению. - Не-скоуп (§6) корректно отсекает смежные темы (получение snapshot, adapters,
состав incident links/route selection, цветовая шкала известного LQI, любые
config/i18n/backend изменения, touch/kiosk/editors) и явно обязывает вернуть
задачу в
S3-spec, если потребуется их затронуть. - Откат (§18) конкретен: один продуктовый коммит убирает namespaced-атрибут, второй stroke и возвращает overlay в sibling-позицию; данных/config миграции нет, поэтому откат кода данных не касается.
- Release-артефакты (§19) полны: оба changelog, оба User Guide, ARCHITECTURE.md,
TESTING.md, явная пометка supersede в #54/#457, обоснование отсутствия нового
постоянного golden-эталона (hover — не часть golden matrix), обязательность
golden:verify,bundle:budget, mutation, полного Linux docs-screenshot цикла (поскольку меняетсяsrc/**). - Производительность (§12) и security/privacy (§13) описаны предметно и не содержат новых поверхностей: lazy-загрузка не расширяется, endpoint sync ограничен DOM текущего space, DOM-атрибут не содержит IEEE/entity id.
- Трейлеры коммита корректны (
Issue: #464,User-Visible: no), ветка и имя файла соответствуют конвенции,docs/specs/README.mdобновлён и ссылается на файл, файл ссылается на issue.
Чего не проверял
- Не проверялся продуктовый код — его не существует в этой ветке на момент ревью (класс A не тронут ни одним файлом), что и требуется на этапе ТЗ.
- Не прогонялись
npx tsc --noEmit,npm test,npm run build— диапазон правок ограниченdocs/specs/**(класс C), эти гейты не могут быть чувствительны к markdown-диффу, и запуск не дал бы дополнительного сигнала. - Не запускались браузерные смоки,
golden:verify,bundle:budget,benchmark:zigbee-topology,mutation-gate.mjs— на этом этапе продукта, которого они проверяют, ещё нет; их реализуемость и совместимость с существующей инфраструктурой проверена чтением (см. «Как проверялось», п.5), а не исполнением, поскольку исполнять пока нечего. - Не проверялась реализация #457/#459 построчно за пределами тех фрагментов, что нужны были для сверки цитируемого контракта (§3, §6 «Связано»).
Материал раунда
- Ветка:
issue/464-zigbee-topology-layer - SHA материала:
aae9efb9ff251ef1471cab685dee2c8c785dea5c - ТЗ:
docs/specs/464-zigbee-topology-layer-order.md(новый файл на этом SHA) - Предыдущего раунда нет — это r1, разделы «Закрытие раунда r0» и «Унаследовано из r0» не применяются.
Вердикт
Зелёный. Готово к разработке.
Материал раунда
- Ветка:
issue/464-zigbee-topology-layer, коммитaae9efb9ff25— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
0d024bed021c9e5afb86b77757195a1de1034813git log --all --format='%H %T' | grep 0d024bed021c - ТЗ
docs/specs/464-zigbee-topology-layer-order.md, блобfbefda4d5cf5acf53895d037cf7b0a5a1cf484f2git log --all --find-object=fbefda4d5cf5acf53895d037cf7b0a5a1cf484f2 -- docs/specs/464-zigbee-topology-layer-order.md