19 KiB
SPEC-REVIEW-54-r1
- Issue: https://github.com/Matysh/houseplan-card/issues/54
- Этап: spec (PROCESS.md §2.4)
- Заход: r1 · блокирующих циклов израсходовано 0/4 до этого вердикта
- Материал:
docs/specs/054-zigbee-topology-overlay.mdна SHAa6a3df931079a008dd4e7f7d602800e46c353192(веткаissue/54-zigbee-topology-hover), коммитdocs: specify contextual zigbee links,Issue: #54 · User-Visible: no - Трек: полный (обоснован автором в шапке ТЗ и в аналитических комментариях владельца — сложность/риск, provider-контракты, новый UX/API-контракт)
Скоуп ревью
Первый раунд ревью ТЗ. Диапазон изменений: git diff 6eea4d1c..a6a3df93 показывает
единственный затронутый файл — docs/specs/054-zigbee-topology-overlay.md
(+509/-50 строк относительно предыдущей редакции документа). Продуктовый код
(класс A) не менялся, git show --stat a6a3df93 подтверждает единственный файл
в коммите. Проверка соответствует этапу spec: судится ТЗ, а не реализация.
Как проверялось
- Прочитаны в порядке, заданном инструкцией:
docs/SCOPE.md,AGENTS.md,PROCESS.md(§1–§8, §2.4, §2.5, §2.10, §4, §7.1), тело issue #54 и все пять комментариев (аналитика 2026-08-14/2026-08-30, занятие Stage 0, итог Stage 0 2026-08-31, решение владельца по UX 2026-09-04). - Прочитан
docs/specs/054-zigbee-topology-overlay.mdцеликом (534 строки, 19 разделов). - Сверены канонические документы:
docs/UX-MODES.md(правила View/editor, admin_only editor tabs),docs/TOUCH-SUPPORT.md(контракт View на touch, прецедент hover-only фичи без touch-эквивалента —show_room_tooltip),docs/CONFIG-COMPATIBILITY.md(прецедент нового optional-boolean поля settings без миграции схемы, #426),docs/USER-GUIDE.ru.md(текущий словарь «Общие настройки», отсутствие сегодня раздела про Zigbee — ожидаемо для новой фичи). - Сверена конвенция остальных ТЗ репозитория:
grepпоdocs/specs/*.mdнашёл 10+ полнотрековых спеков с отдельным разделом «Затронутые файлы и модули» (пример:docs/specs/348-german-localization.md:322). node scripts/check-docs.mjs— зелёный (7 файлов, 12 внешних ссылок), подтверждает то, что уже заявил автор в хендоффе.
Гейты — что прогнано и что нет
Этап spec: src/** не менялся, поэтому код-гейты код-ревью (typecheck,
test, build, bundle sync/budget, smoke, mutation) к материалу этого раунда
не относятся и не запускались — запускать их было бы про несуществующий диф.
Прогнан только релевантный документационный гейт:
| Гейт | Результат |
|---|---|
node scripts/check-docs.mjs |
зелёный (перепроверено ревьюером) |
git diff --check 6eea4d1c..a6a3df93 |
без конфликтных маркеров и trailing whitespace (перепроверено) |
Смоки, golden, backend, performance — неприменимы: диф не касается src/**,
custom_components/**, рендера или геометрии.
Находки
Medium (в скоупе задачи, чинится в этой же правке ТЗ)
M1 — нет обязательного раздела «Затронутые файлы и модули».
PROCESS.md §2.5 (DoR) требует буквально: «перечислены затронутые файлы и
модули» как отдельный обязательный пункт готовности к разработке. В ТЗ #54 (19
разделов, см. grep -n "^## " вывод) такого раздела нет вообще — ни списком
путей, ни перечнем логических модулей. Это не вопрос стиля: без него код-ревью
не имеет опорной точки, чтобы проверить полноту диффа реализации против
заявленного скоупа, а переход в S5-ready формально не может закрыть чек-лист
DoR.
Прецедент в этом же репозитории: как минимум 10 недавних полнотрековых ТЗ
(226-entity-parent-dedup.md, 238-opening-inner-distances.md,
264-resize-controller.md, 340-config-set-revision.md,
348-german-localization.md и другие) содержат отдельный раздел с этим именно
заголовком, обычно перед «Риски». У #54 раздел пропущен полностью, хотя текст
ТЗ явно предполагает несколько новых модулей (provider-neutral topology model,
ZHA adapter, Z2M adapter, resolver mapping/cross-space classification, hover
render layer, General Settings UI, i18n ключи) — их достаточно перечислить
логическими именами (директории/модули), точные файлы не обязательны, раздел
18 уже разрешает менять внутренние имена свободно.
Воспроизведение: grep -n "^## " docs/specs/054-zigbee-topology-overlay.md —
среди 19 заголовков нет ни «Затронутые файлы», ни «Модули», ни синонима.
Это находка Medium, а не High: она не делает ни один AC невыполнимым или непроверяемым, продуктового решения владельца не требует (пункт технический, разрешён к свободному выбору автором по §7.1 ТЗ), и чинится добавлением одного раздела в этом же документе.
Low (снимаются данным ревью с запиской, не блокируют)
L1 — имя персоны не совпадает с таблицей docs/SCOPE.md.
§1 ТЗ: «Персона — Enthusiast/Power User из docs/SCOPE.md». Таблица персон в
docs/SCOPE.md (раздел Target audience) содержит ровно три строки: Home
admin (описан как «HA enthusiast, house/large flat… sets up and maintains
the plan»), Household members, Guests/kiosk. Персоны «Enthusiast/Power
User» как отдельной строки в каноне нет — по содержанию это Home admin,
описанный через прилагательное «enthusiast», а не самостоятельная персона.
Смысл ТЗ не меняется (сценарий однозначно про admin с мышью), поэтому не
блокирую, но при правке рекомендую заменить на точное имя из таблицы: «Home
admin (HA enthusiast) из docs/SCOPE.md». Снимаю с запиской, правка
необязательна к отдельному циклу.
L2 — формулировка AC14 «backend/HA contract smoke on Linux CI» не согласована
с явным заявлением §18, что backend House Plan не добавляется.
§18 «Предположения автора»: «House Plan backend не добавляется, пока штатных
HA WebSocket/MQTT surfaces достаточно». АС14 при этом называет доказательством
«adapter unit with fake clock/MQTT + backend/HA contract smoke on Linux CI».
Слово «backend» в доказательстве, скорее всего, значит «контрактный тест
против реального/эмулированного HA backend» (аналог полного HA harness,
который по AGENTS.md — только Linux/WSL), а не про появление
custom_components/houseplan серверной поверхности — но буквальное чтение
допускает обе трактовки и способно завести реализацию не в ту сторону при
планировании гейтов. Не блокирую (не влияет ни на один продуктовый AC), но
рекомендую на правке заменить формулировку на однозначную, например: «adapter
unit with fake clock/MQTT + HA MQTT contract fixture on Linux CI (не House
Plan backend)».
L3 — численные performance-бюджеты не зафиксированы в ТЗ, откладываются на
измеренный dev-стенд перед S7 (§14.6).
AC18 формально требует «сохраняют установленный performance budget», но сам
бюджет для нового topology-пути ещё не существует и по плану тестов (§14,
пункт 6) будет измерен и зафиксирован только перед код-ревью, а не сейчас.
Это не противоречие: методология (fixtures 20/100/500 nodes, что именно
измеряется — normalize/map, first/repeated hover, dense-invalid rejection)
названа, значит требование DoR §2.5 «влияние на производительность… названо»
выполнено по существу. Формально было бы чище явно занести это как пункт
предположений в §18 («точные числовые пороги устанавливаются перед S7 на
измерении, не на этапе ТЗ»), но раздел 14.6 уже говорит то же самое прямым
текстом. Снимаю без требования правки.
Что проверено и корректно
- Структура ТЗ (§7.1). Все обязательные разделы присутствуют: сценарий, что человек увидит до/после, проблема, скоуп/не-скоуп, контракт поведения, UX, модель данных и миграция, i18n, AC1–AC20 с указанием доказательства, план автотестов, риски, откат, release-артефакты.
- Продуктовая рамка. Сценарий и «что человек увидит» описаны в
пользовательских терминах без технической лексики, персона и поверхность
названы (см. L1 — неточное имя, но не отсутствие). Задача явно закрывает J7
docs/SCOPE.md(«Is my Zigbee mesh healthy here?»), ссылка на J7 есть в §17. - Открытых продуктовых вопросов нет. Комментарий владельца от 2026-09-04 закрыл все развилки UX (default-off toggle, mouse-only hover, cross-space — только счётчик без перехода, touch/pen без нового жеста), и они дословно перенесены в §5 и §4.2 не-скоупа. Технических вопросов, ошибочно вынесенных владельцу как продуктовые, не найдено — единственный вопрос от аналитика 2026-08-14 был «вопросов нет».
- Никаких догадок, выданных за факт. Раздел 7 (provider-контракты)
подкреплён конкретными версиями/SHA HA Core, HA Frontend, Zigbee2MQTT и
прямыми ссылками на исходники (§19); утверждения о
zha/topology/updateбез completion/result и о недоступности произвольного Z2M base topic через registry явно обоснованы источником, а не предположением. Раздел 18 честно маркирует технические решения автора как «assumed, change freely», что соответствует правилу — размытое продуктовое не додумано, техническое явно помечено. - AC1–AC20. Каждый критерий сформулирован проверяемо (конкретное условие + конкретное отсутствие/наличие эффекта) и имеет указанный способ доказательства (unit/adapter/browser smoke/golden/mutation/reviewer audit). Ни один AC не описывает решение через реализацию без критерия наблюдаемого поведения. Защитные AC (AC1, AC3, AC5, AC9, AC11, AC15, AC17 — все про «не делает X») имеют названный способ показать, что тест умеет падать (request spy, mutation witness, DOM/computed-style assertions, call-count unit) — это забота код-ревью, но на уровне ТЗ формулировка это уже предусматривает.
- Согласованность контракта. Условия §5.3 (1–5) непротиворечиво стыкуются
с §9 (mapping), §10 (fetch/cache/lifecycle) и AC3: неадмин физически не
получает snapshot (кэш ключуется по HA-соединению, а runtime вообще не
грузится не-админу по §10), поэтому «не видит слой» в AC3 выполняется без
отдельного явного admin-гейта внутри условий hover — проверено логически,
расхождения нет.
Touch/pen carve-out (§4.2, §5.4, §15) прямо разрешён владельцем 2026-09-04 и
имеет прецедент в этом же репозитории —
docs/TOUCH-SUPPORT.mdуже документирует ровно такой же паттерн дляshow_room_tooltip(hover-only информация без touch-замены), так что это не непроверенное решение автора, а соответствие канону. - Совместимость конфига. §8.1 («миграции нет, отсутствие объекта = выкл,
downgrade игнорирует неизвестное поле») повторяет уже принятый в проекте
паттерн из
docs/CONFIG-COMPATIBILITY.md(settings.show_room_tooltip, #426) — новый optional boolean без миграции схемы. Расхождений с каноном нет. - i18n. §12 перечисляет все новые видимые строки и синхронность en/ru/de/fr; формулировки прямо избегают вводящих в заблуждение терминов («наблюдаемые связи», не «текущий маршрут»).
- Release-артефакты и откат. §16–17 называют both changelog, обновление
UX-MODES.md/SCOPE.md/user-guide, reviewed golden, и операционный откат (выключить настройку, per-provider независимое отключение) без миграции назад — соответствует правилу «никогда не удалять данные пользователя на догадке» (снапшот memory-only, base topics не удаляются при выключении).
Чего не проверял и почему
- Код-гейты код-ревью (
typecheck,test,build, bundle sync/budget, smoke-select, no-new-any, mutation runs) — неприменимо: диф этого раунда не касаетсяsrc/**/custom_components/**, тестировать нечего. - Golden/performance/backend прогоны — неприменимо по той же причине; они станут предметом код-ревью, когда появится реализация.
- Фактическую работоспособность provider WebSocket/MQTT контрактов (
zha/devices,bridge/request/networkmap) против живого HA/ZHA/Z2M стенда — вне периметра ревью ТЗ; принимаю как факт §7 со ссылками на источники (Stage 0 research уже прошёл отдельным этапом с итоговым комментарием владельца «GO с условиями» 2026-08-31), это не повторная работа этого ревью. - Точное соответствие будущего кода разделу 8.2 (
ZigbeeTopology,ZigbeeTopologyNodeи т.д.) — модель помечена как assumed/changeable в §18, оценивать её как контракт рано.
Вердикт
Единственная блокирующая-в-скоупе находка (M1) — отсутствие обязательного по DoR раздела «Затронутые файлы и модули». High-находок нет. Три Low сняты записью выше без требования правки. Продуктовая часть ТЗ, провайдерные контракты, AC и UX-контракт корректны и не содержат непомеченных догадок.
Вердикт: жёлтый · заход r1 · блокирующих циклов 1/4 · High: 0 · Medium: 1 → в задаче
Материал раунда
- Ветка:
issue/54-zigbee-topology-hover, коммитa6a3df931079— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
fb166b00299442bc4091dc79538ae54d62106017git log --all --format='%H %T' | grep fb166b002994