docs: review document for #54

Issue: #54
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-04 11:05:11 +00:00
parent a6a3df9310
commit c53702cdfa
+218
View File
@@ -0,0 +1,218 @@
# 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` на SHA `a6a3df931079a008dd4e7f7d602800e46c353192` (ветка `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: судится ТЗ, а не реализация.
## Как проверялось
1. Прочитаны в порядке, заданном инструкцией: `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).
2. Прочитан `docs/specs/054-zigbee-topology-overlay.md` целиком (534 строки, 19
разделов).
3. Сверены канонические документы: `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 — ожидаемо для
новой фичи).
4. Сверена конвенция остальных ТЗ репозитория: `grep` по `docs/specs/*.md`
нашёл 10+ полнотрековых спеков с отдельным разделом «Затронутые файлы и
модули» (пример: `docs/specs/348-german-localization.md:322`).
5. `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 → в задаче
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/54-zigbee-topology-hover`, коммит `a6a3df931079` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `fb166b00299442bc4091dc79538ae54d62106017`
```
git log --all --format='%H %T' | grep fb166b002994
```