Files
houseplan-card/docs/reviews/SPEC-REVIEW-464-r1.md
T
2026-09-05 21:14:15 +00:00

15 KiB
Raw Blame History

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, HEAD aae9efb9ff251ef1471cab685dee2c8c785dea5c, коммит «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, просветы сохраняются). ТЗ проверено на точное соответствие этому комментарию.

Как проверялось

  1. Прочитаны docs/SCOPE.md, AGENTS.md, PROCESS.md целиком (включая §2.4, §2.5, §2.10, §5, §7.1, §7.2), тело issue #464 и все пять комментариев (включая уточнение владельца, две редакции аналитики и хендофф автора).
  2. Прочитан документ ТЗ целиком, сверен на присутствие всех разделов §7.1.
  3. Проверены на согласованность с ТЗ канонические документы подсистемы — 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).
  4. Технические утверждения §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 заменяет, назван и процитирован верно.
  5. Проверена реализуемость заявленного способа доказательства 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 и др.) — расширение тем же инструментом, не изобретение нового.
  6. Проверены трейлеры коммита (Issue: #464, User-Visible: no — корректно для документации без продуктового поведения) и двусторонняя связь issue ↔ ТЗ ↔ docs/specs/README.md (запись добавлена, ссылка на файл и issue на месте).
  7. Дешёвые гейты не гонялись повторно: диапазон правок — только 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, bounded MutationObserver(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 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 0d024bed021c9e5afb86b77757195a1de1034813
    git log --all --format='%H %T' | grep 0d024bed021c
    
  • ТЗ docs/specs/464-zigbee-topology-layer-order.md, блоб fbefda4d5cf5acf53895d037cf7b0a5a1cf484f2
    git log --all --find-object=fbefda4d5cf5acf53895d037cf7b0a5a1cf484f2 -- docs/specs/464-zigbee-topology-layer-order.md