mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 11:49:16 +00:00
committed by
Sergey Matyunin
parent
a63aef0239
commit
d13ecf1237
@@ -0,0 +1,180 @@
|
||||
# SPEC-REVIEW-457-r1
|
||||
|
||||
- Issue: [#457](https://github.com/Matysh/houseplan-card/issues/457) — Топология
|
||||
Zigbee: показывать направление связи стрелкой на конце линии
|
||||
- ТЗ: `docs/specs/457-zigbee-route-arrows.md`
|
||||
- SHA материала: `f3a1dd84` (ветка `issue/457-zigbee-route-arrows`, коммит
|
||||
«docs: specify Zigbee route arrows»)
|
||||
- Заход: r1 · блокирующих циклов израсходовано 0 из 4
|
||||
- Трек: полный (issue помечен `feature`, `P2`, `S4-spec-review`; `small` не
|
||||
назначен, и это соответствует критериям §5 — новый UX-контракт, производная
|
||||
графовая модель, новые i18n-строки и browser-smoke)
|
||||
|
||||
## Скоуп ревью
|
||||
|
||||
ТЗ описывает дерево аплинков Zigbee-топологии к координатору (BFS от узла с
|
||||
`role: coordinator`), стрелки на рёбрах этого дерева при hover-диагностике, и
|
||||
parent bubble для случаев, когда следующий узел на пути нельзя показать на
|
||||
плане (другое пространство / нет маркера у устройства / нет маркера у
|
||||
координатора). Развивает существующий контракт #54
|
||||
(`docs/specs/054-zigbee-topology-overlay.md`), который явно исключал
|
||||
«вычисление либо изображение маршрута до координатора» из своего non-scope —
|
||||
#457 законно открывает этот пункт отдельной задачей.
|
||||
|
||||
Я не пишу и не правлю ни ТЗ, ни продуктовый код — только оцениваю.
|
||||
|
||||
## Как проверялось
|
||||
|
||||
Ревью ТЗ на этом этапе не гоняет гейты (кода ещё нет — весь diff класса A/B/D
|
||||
пуст, изменена только документация класса C). Работа состояла в очной сверке
|
||||
каждого фактического утверждения ТЗ с реальным состоянием репозитория на SHA
|
||||
`f3a1dd84`, а не с пересказом автора:
|
||||
|
||||
- прочитан `docs/SCOPE.md` — задача продолжает J7 («Is my Zigbee mesh healthy
|
||||
here?»), конфликта со scope нет, это уже подтвердила и аналитика Codex в
|
||||
issue;
|
||||
- прочитан `PROCESS.md` §2.4, §2.9 (не применимо к r1), §5, §7.1, §7.2 — все
|
||||
обязательные разделы шаблона проверены поимённо;
|
||||
- прочитано тело issue #457 целиком и все 6 комментариев (аналитика владельца,
|
||||
два уточнения владельца, финальные решения владельца, аналитика и оценка
|
||||
Codex, хендофф на ревью) — сверено, что все продуктовые вопросы закрыты
|
||||
решениями владельца **до** написания ТЗ, а не оставлены на усмотрение
|
||||
реализации;
|
||||
- прочитан `docs/USER-GUIDE.ru.md` (раздел про Zigbee-диагностику, строки
|
||||
200–230) и `docs/USER-GUIDE.md` — терминология «Показывать связи Zigbee при
|
||||
наведении на устройство», admin-only, mouse-only, «снимок соседства, а не
|
||||
маршрут каждого текущего пакета» уже зафиксирована и ТЗ её не переизобретает;
|
||||
- прочитан базовый контракт `docs/specs/054-zigbee-topology-overlay.md`
|
||||
целиком — проверено, что #457 не противоречит и не дублирует его AC, а
|
||||
расширяет ровно тот пункт non-scope, который #54 сознательно оставил открытым;
|
||||
- построчно сверены все технические утверждения ТЗ с текущим кодом:
|
||||
`src/zigbee-topology.ts` (модель `ZigbeeTopologyLink`/`ZigbeeHoverLine`,
|
||||
`observation()` — `relationship` действительно принимает только `string`,
|
||||
`resolveMappedTopologyHover`, `omittedCount` действительно нигде не
|
||||
выводится, `mapTopologyNodes` — четыре причины `unmatched_device` /
|
||||
`ambiguous_placement` / `provider_scan_failure` / `drawable()`),
|
||||
`src/hp-zigbee-topology-overlay.ts` (`viewBox="0 0 100 100"
|
||||
preserveAspectRatio="none"`, `.halo` радиус `1.22`, `remote` bubble, `pointer-
|
||||
events: none`, `forced-colors` блок), `src/zigbee-topology-overlay-bridge.ts`
|
||||
и вызов в `src/houseplan-card.ts` (нет проекции названий пространств в
|
||||
overlay сегодня, но паттерн `space.title || space.id` уже существует в файле
|
||||
и его перенос в bridge не требует нового конфига), `src/zigbee-topology-
|
||||
settings.ts` (`enabled: false` по умолчанию);
|
||||
- прочитана реальная анонимизированная фикстура
|
||||
`test/fixtures/zigbee2mqtt-networkmap-real-anonymized.json` — подтверждено,
|
||||
что координатор (`type: Coordinator`) присутствует, `relationship: 2`
|
||||
(число) и `depth: 15` действительно в данных, как заявлено в ТЗ;
|
||||
perf-бюджеты `normalize 80 ms / map 160 ms / first hover 180 ms / 20 repeated
|
||||
hovers 120 ms` в §12 ТЗ дословно совпадают с `BUDGETS` в
|
||||
`demo/benchmark_zigbee_topology.mjs`, а лимиты «1000 nodes / 6000 links» — с
|
||||
`TOPOLOGY_MAX_NODES`/`TOPOLOGY_MAX_LINKS`;
|
||||
проверено существование всех названных в AC инструментов доказательства:
|
||||
`test/zigbee-topology.test.mjs`, `demo/smoke_zigbee_topology_hover.mjs`,
|
||||
`demo/benchmark_zigbee_topology.mjs` — ни один AC не ссылается на
|
||||
несуществующий или придуманный гейт;
|
||||
- проверено, что backend Python не затронут: `grep` по `custom_components/`
|
||||
на «zigbee» не находит ничего, provider-обращения (`zha/devices`) идут через
|
||||
`hass.callWS` из фронтенда — подтверждает §16 «Backend Python не меняется»;
|
||||
- сверен формат `docs/CHANGELOG.md`/`docs/CHANGELOG.ru.md` (секция
|
||||
`## Unreleased`) с требованием §19 добавить одну пользовательскую запись.
|
||||
|
||||
Полный набор автотестов/typecheck/build на этом этапе не запускался — кода нет,
|
||||
гонять нечего; это ожидаемо для ревью ТЗ и не является пропуском гейта.
|
||||
|
||||
## Находки
|
||||
|
||||
Блокирующих (High) и находок в скоупе (Medium) нет.
|
||||
|
||||
### Low — зафиксировано, без правки
|
||||
|
||||
1. **§8, «При недостатке места bubble может сместиться на противоположную
|
||||
сторону marker»** не даёт алгоритмического критерия «недостатка места»
|
||||
(порог, приоритет сторон). Это единственное место контракта, где решение
|
||||
явно оставлено на усмотрение реализации, но не занесено в «Принятые
|
||||
предположения» (§20). Не блокирует: AC9 всё равно требует, чтобы bubble
|
||||
«оставался внутри видимой области overlay» и не обрезал текст, то есть
|
||||
наблюдаемое поведение проверяемо независимо от конкретного алгоритма
|
||||
позиционирования. Снимаю без правки: технический выбор компоновки внутри
|
||||
уже описанного визуального инварианта — по §7.1 такие решения ревьюер вправе
|
||||
не эскалировать, а просто отметить.
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- Обязательные разделы §7.1 присутствуют все и в порядке, продиктованном
|
||||
процессом: сценарий → что человек увидит → проблема → скоуп/не-скоуп →
|
||||
контракт → UX → данные/миграция → i18n → AC → тесты → риски → откат →
|
||||
release-артефакты (§§1–19 ТЗ).
|
||||
- Оба «первых» продуктовых раздела (сценарий, что человек увидит до/после)
|
||||
называют персону из `docs/SCOPE.md`, поверхность и момент, без терминов
|
||||
реализации в разделе 2 — соответствует требованию.
|
||||
- Открытых продуктовых вопросов нет: все три развилки, которые обсуждались в
|
||||
комментариях (смысл стрелки, поведение при недоступном endpoint, поведение
|
||||
при неизвестном пути) закрыты явными решениями владельца **до** написания
|
||||
ТЗ, и ТЗ им не противоречит ни в одном разделе.
|
||||
- Технических догадок, выданных за факт и не помеченных как предположение, не
|
||||
найдено: единственное место, где реализация имеет свободу (алгоритм
|
||||
выбора родителя, имена типов, точный визуальный размер наконечника, formula
|
||||
позиционирования bubble при недостатке места) либо прямо названо в §20
|
||||
«Принятые предположения», либо (см. Low выше) не влияет на проверяемость
|
||||
AC.
|
||||
- Каждый AC1–AC12 — проверяемое утверждение с явным способом доказательства
|
||||
(unit / resolver unit / browser smoke / benchmark / bundle-budget /
|
||||
check-docs), без формулировок вида «работает корректно» без критерия.
|
||||
Инвариант «по стрелкам приходишь в координатор» сформулирован как свойство
|
||||
дерева (§6.4), а не как свойство итоговой картинки — ТЗ прямо проговаривает,
|
||||
почему это важно (обрыв цепочки на неразмещённом/удалённом узле не должен
|
||||
делать AC1 невыполнимым в обычном доме).
|
||||
- Конструкция «дерево аплинков по полному графу, включая неразмещённые узлы,
|
||||
рисуется только по размещённым» корректно закрывает реальный дефект текущего
|
||||
кода: `omittedCount` в `resolveMappedTopologyHover` сегодня действительно
|
||||
считается, но нигде не выводится (проверено чтением
|
||||
`src/zigbee-topology.ts:307-333` и `src/hp-zigbee-topology-overlay.ts`) — ТЗ
|
||||
не выдумывает проблему.
|
||||
- Все построчные технические ссылки на код и фикстуры, использованные для
|
||||
обоснования решений (числовой `relationship` у Z2M, `depth: 15`, отсутствие
|
||||
проекции названий пространств в overlay, дефолт `enabled: false`,
|
||||
perf-бюджеты, лимиты 1000/6000), подтверждены чтением соответствующих файлов
|
||||
— расхождений с фактическим состоянием кода не найдено.
|
||||
- Не-скоуп (§5) корректно исключает смежные, но посторонние задачи
|
||||
(асимметрия LQI, постоянный mesh-граф, touch-жест, автоматическое размещение
|
||||
координатора) и совпадает с явными решениями владельца в issue не заводить
|
||||
их сейчас.
|
||||
- Откат (§18) и release-артефакты (§19) содержательны и не формальны:
|
||||
пользовательский откат — существующий тумблер, кодовый откат — конкретные
|
||||
поверхности для удаления.
|
||||
|
||||
## Чего не проверял
|
||||
|
||||
- Реализуемость perf-бюджетов на **новом** коде (построение дерева) — это
|
||||
предмет измерения на этапе код-ревью через
|
||||
`npm run benchmark:zigbee-topology`, сейчас кода не существует.
|
||||
- Полный typecheck/test/build/golden/check-docs — не применимо к этапу ТЗ, код
|
||||
не менялся (diff — только `docs/specs/457-zigbee-route-arrows.md`).
|
||||
- Фактическую компоновку bubble в браузере (описанный в Low пункт) — там нет
|
||||
кода для запуска, только текст контракта.
|
||||
- Backend-тесты (`pytest tests_backend`) — не применимо, Python не
|
||||
затронут ни диффом, ни планом ТЗ.
|
||||
|
||||
## Вердикт
|
||||
|
||||
Полный, тщательно проверенный по коду и данным документ, без открытых
|
||||
продуктовых вопросов и без непомеченных догадок. Единственное замечание —
|
||||
Low, снято без правки с записью в этом документе.
|
||||
|
||||
`Вердикт: зелёный · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 0`
|
||||
|
||||
---
|
||||
|
||||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `issue/457-zigbee-route-arrows`, коммит `f3a1dd84e19d` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||
- Дерево материала: `0c76f7e322a59f7e81bbae32a7b013d63584ca5f`
|
||||
```
|
||||
git log --all --format='%H %T' | grep 0c76f7e322a5
|
||||
```
|
||||
- ТЗ `docs/specs/457-zigbee-route-arrows.md`, блоб `2c8350e397b0192a8f0db3d1c3ee0bf9f5f6e1f6`
|
||||
```
|
||||
git log --all --find-object=2c8350e397b0192a8f0db3d1c3ee0bf9f5f6e1f6 -- docs/specs/457-zigbee-route-arrows.md
|
||||
```
|
||||
Reference in New Issue
Block a user