docs: review document for #459

Issue: #459
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-05 11:18:37 +03:00
committed by Codex
parent ba47395337
commit 50bc1d6955
+102
View File
@@ -0,0 +1,102 @@
# Код-ревью #459 — заход r1
Настройка «Zigbee links»: подсказка о функции, её ограничениях и легенда цветов и пунктира.
Ветка `issue/459-zigbee-links-help`, HEAD `951cbd0174bbbc4cb069cf5f8832da8cc49f2ace`, база `origin/dev` = `b04e4aacce4ab1f13f320dd1dfe7501b78da571e`.
## Скоуп
Диапазон `git diff origin/dev...HEAD` — 41 файл. Продуктовый код:
- `src/hp-zigbee-topology-settings.ts` — импорт `hp-help`, локальный `_help()`, кружок у заголовка секции;
- `src/i18n/topology.ts` — новая `hasTopologyTranslation()`, зеркало `hasTranslation` основного словаря;
- `src/i18n/topology/{en,ru,de,fr}.json` — два новых ключа (`help`, `help_aria`);
- `test/zigbee-topology.test.mjs` — 7 новых тестов (AC1, AC2, AC3, AC3b, AC4, AC5, AC6);
- `scripts/mutation-gate.mjs` — два мутанта;
- `docs/CHANGELOG.md` / `docs/CHANGELOG.ru.md` — записи в том же коммите, что и фича;
- golden-эталон `general-color-popover-desktop-en` принят вторым коммитом с `Release:`/`Baseline-Reviewed:`;
- `dist/**`, `custom_components/houseplan/frontend/**`, `docs/images/screenshots.json` — производные сборки/скриншотов.
Оверлей (`hp-zigbee-topology-overlay.ts`), логика топологии (`zigbee-topology.ts`, `zigbee-topology-runtime.ts`), `lqiColor` (`logic.ts`) и `hp-help.ts` не тронуты — соответствует §5 контракта («что не меняется»).
## Как проверялось
Материал — `git log --oneline origin/dev..HEAD` (2 коммита) и `git diff origin/dev...HEAD`. Читал код построчно и сверял с контрактом ТЗ (тело issue + все 9 комментариев, включая утверждённый r2 SPEC-REVIEW и финальный текст §4.1).
Validate на `951cbd01` зелёный (прогон 33953825960), поэтому `npx tsc --noEmit`, полный `npm test` и `npm run build` не перегонял. Дельта не трогает геометрию/модель (стены, `layout`, `marker.space`, `open_spans`), поэтому `npm run invariants` не требуется.
Что прогнал сам:
| Гейт | Результат |
|---|---|
| `node scripts/bundle-sync.mjs` (подготовка стенда для смоков — `demo/srv/assets` не в репозитории) | наложил дистрибутив без изменений в git-дереве |
| `demo/smoke_zigbee_topology_hover.mjs` (назван в AC8) | **OK**, все 12 проверок `true` — оверлей, цвета, дефолт-офф, ленивая загрузка не изменились |
| `node scripts/smoke-select.mjs --base b04e4aac --head 951cbd01` | **НЕОПРЕДЕЛЁННОСТЬ** — символы `_help`, `hasTopologyTranslation`, `topologyT`, `DICTIONARIES`, `Lang`, `TopologyI18nKey`, `langOf` не связаны ни с одним смоком доказуемо; кроме уже прогнанного `smoke_zigbee_topology_hover` (AC8), других смоков задача не называет, и диф — новый namespace-компонент без побочных эффектов на другие поверхности, широкого символа нет |
| `node scripts/bundle-budget.mjs` | **OK**, initial View 297 476 Б (потолок 298000±2000, budget 300000) — подтверждает заявленные автором «на 2 байта меньше `dev`»; есть предупреждение о низком запасе, но это унаследованный долг #367, не новый в этой задаче |
| `node scripts/check-docs.mjs --external` | **OK**, 7 файлов, 12 внешних ссылок |
| `node scripts/mutation-gate.mjs --id=topology-help-renders-without-aria` | **OK** — мутант пойман, тест краснеет |
| `node scripts/mutation-gate.mjs --id=topology-help-drops-arrow-legend` | **OK** — мутант пойман, тест краснеет |
| `node --test test/zigbee-topology.test.mjs` (полный файл, 18 тестов) | **OK**, 18/18 pass |
| Дисциплина «тест умеет падать» для AC6 (гейт паритета словарей) | вручную удалил `help_aria` из `de.json`, тест на паритет упал ожидаемо; вернул файл на место (`git status` чист) |
| Чтение `general-color-popover-desktop-en.png` | подтверждаю глазами: единственное изменение — кружок «?» у «Zigbee links», остальное — сдвиг вниз ~14px без регрессии рендера |
| `docs/images/screenshots.json`, `baselines-index.json` дифф | только `sourceFingerprint`/`sourceSha256` и хэш одной сцены; `imageSha256` во всех 10 скриншот-сценах документации не изменился — рекапча была из-за отпечатка, не из-за пикселей |
Не прогонял: полный `npm test`, `npx tsc --noEmit`, `npm run build`, полный `npm run golden:verify` (153 сцены) — уже подтверждены Validate на этом SHA; `python -m pytest tests_backend` — `custom_components/**/*.py` не тронут; `npm run invariants` — геометрия/модель не задеты; performance-профили — не названы в AC и не тронуты чувствительные пути.
## Проверка по AC
- **AC1** (кружок у заголовка, наведение/фокус/клик) — подтверждено чтением: `render()` кладёт `${this._t('title')}${this._help()}` в `.section` (строка 187), а не в `.toggle`. Открытие по наведению/фокусу/клику — поведение самого `hp-help.ts`, не тронутого этой задачей, доказательство ссылкой корректно.
- **AC2** (fail-closed без одного из ключей) — `_help()` проверяет `hasTopologyTranslation(lang, 'help')` и `...'help_aria'`, возвращает `nothing`. Тест `кружок справки не рисуется без подписи для скринридера` гоняет `hasTopologyTranslation` напрямую, включая случай `no_such_key` → `false` и англ. фолбэк для `de`. Мутант `topology-help-renders-without-aria` (правит резолв на `?? key`, имитируя старую фиктивную проверку) пойман.
- **AC3 / AC3b** (шесть+один пункт легенды по-русски) — тест проверяет 10 паттернов по нормативной ru-строке, все совпадают: LQI, 40, 180, пунктир, исходящая→координатор, входящие, «без стрелки», «подпись на конце стрелки», «отсутствие стрелки», «дерево маршрут», «не путь пакета». Мутант `topology-help-drops-arrow-legend` (вырезает предложение про стрелки) пойман.
- **AC4** (границы шкалы = `lqiColor`, не константа) — тест импортирует `lqiColor` из скомпилированного `logic.js` и берёт hue(40)=0, hue(180)=120 из функции, затем ищет те же числа в тексте. Подтверждено чтением `logic.ts:8-10`: `hue = clamp(0..120, (lqi-40)/140*120)` — ровно то, что описывает ТЗ.
- **AC5** (нет переносов строк) — проверено для всех четырёх словарей; строки `help`/`help_aria` непустые.
- **AC6** (паритет ключей+плейсхолдеров четырёх словарей) — новый гейт лежит в `test/zigbee-topology.test.mjs`, а не в `test/i18n.test.mjs`, как предполагали «Затронутые файлы» ТЗ (низкая находка ниже). Сам гейт работает: проверил падением при удалении ключа.
- **AC7** (ядро и бандл не растут) — `core-file-budget.test.mjs` следит только за `houseplan-card.ts` и `houseplan-editor-runtime.ts` — ни один не тронут. `bundle-budget.mjs` зелёный, инициальный чанк на 2 байта меньше `dev`.
- **AC8** (оверлей не изменился) — `smoke_zigbee_topology_hover.mjs` прогнан лично, все проверки `true`.
Контракт §2 («не переиспользуем `_help()` редактора») и §3 (плоские ключи `help`/`help_aria`) подтверждены построчно: основной `_help()` в `houseplan-editor-runtime.ts:1228` типизирован `I18nKey`/`t()` основного словаря и требует пару `<ключ>.help`/`<ключ>.help.aria` — несовместим с namespace `topologyT`. Новый `hasTopologyTranslation` — точное зеркало `hasTranslation` (`src/i18n.ts:38-41`), включая англ.-фолбэк.
Перевод легенды на en/de/fr сверен вручную по всем шести пунктам плюс оговорке о приближённости — ни один язык не потерял смысловой блок (проверка ru тестами, en/de/fr — чтением, не исполнением).
## Что проверено и корректно
- Оба мутанта реально ловятся (не «зелёный на бумаге» — прогнал сам).
- AC6-гейт умеет падать (тест на паритет специально сломан и восстановлен).
- Единственная задетая golden-сцена соответствует заявленному визуальному изменению, остальные 152 сцены документации не изменили пиксели.
- `User-Visible: yes` в коммите `040902fe` сопровождается правкой обоих changelog в этом же коммите; коммит `951cbd01` (принятие эталона) несёт `Release:`/`Baseline-Reviewed:` и помечен `User-Visible: no`, что верно — сам golden-коммит не меняет видимое поведение сверх уже объявленного.
- Геометрия/модель/провайдеры/конфиг не затронуты — соответствует §5 контракта.
- Числа 40 и 180 в подсказке имеют один источник (`lqiColor`), а не отдельную константу — AC4 гейт это блокирует, а не полагается на честное слово.
## Низкие находки (без блокировки, приняты с запиской)
1. **Расхождение отчёта с диффом:** автор пишет «+22 утверждения в шести новых тестах», в дифе — семь новых тестов (`AC1`…`AC6`, `AC3b` отдельно). Чисто редакторская неточность в отчёте, не в коде; не влияет на проверяемость.
2. **`data-help-key` не проставлен.** Оба существующих места, где строится `<hp-help>` (`houseplan-editor-runtime.ts:1232`, `houseplan-onboarding-runtime.ts:58`), кладут `data-help-key=${key}` — по этому атрибуту `demo/smoke_help_affordance.mjs` находит конкретный кружок. Новый локальный `_help()` в `hp-zigbee-topology-settings.ts` этот атрибут не ставит. Ни один AC его не требует, поведение кружка не страдает — но если когда-нибудь понадобится смок, целящийся именно в этот кружок, привычный селектор `hp-help[data-help-key="..."]` не сработает. Не блокирует, реализатор может добавить одной строкой при желании.
3. **Гейт паритета словарей уехал из плана.** ТЗ ожидало «несколько строк в существующем тесте» (`test/i18n.test.mjs`), реализация — новый тест в `test/zigbee-topology.test.mjs`. Гейт работает (проверил падением), но заявленный в «Затронутых файлах» путь не совпал с фактическим — организационная, не функциональная деталь.
Ни одна находка не блокирует и не относится к Medium: ни AC, ни продуктовое поведение не задеты.
## Чего не проверял и почему
- Полный `npm test`, `npx tsc --noEmit`, `npm run build`, полный `npm run golden:verify` — Validate уже зелёный на `951cbd01` этой же веткой (ссылка в задаче), а диф не расширяет их сверх того, что покрыто точечными прогонами выше.
- `python -m pytest tests_backend` — `custom_components/**/*.py` в дифе нет (только синхронизированная копия фронтенд-бандла).
- `npm run invariants` — диф не касается стен, `layout`, `marker.space`, `open_spans` или иных геометрических ссылок.
- Performance-профили — не названы в AC и не задеты диффом.
- Остальные 222 браузерных смока — не выбраны инструментом (`НЕОПРЕДЕЛЁННОСТЬ`) и не относятся по теме к namespace-компоненту без побочных эффектов; единственный релевантный (`smoke_zigbee_topology_hover`, AC8) прогнан.
## Итог
Все восемь AC доказаны — тестом с проверенной способностью падать (AC1–AC6) либо смоком, прогнанным лично (AC8), либо бюджетным гейтом (AC7). Два мутанта реально ловятся. Контракт §1–§5 ТЗ выполнен буквально, включая обе оговорки, которые владелец сознательно исключил из текста (координатор без исходящей стрелки, соседи вне пространства). Три находки Low не влияют на корректность и не блокируют.
**Вердикт: зелёный.**
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/459-zigbee-links-help`, коммит `951cbd0174bb` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `0232ce77f553298708b5cdf4558455cc2ffd721d`
```
git log --all --format='%H %T' | grep 0232ce77f553
```