Files
houseplan-card/docs/reviews/CODE-REVIEW-459-r2.md
T
2026-09-05 08:46:15 +00:00

20 KiB
Raw Blame History

Код-ревью #459 — заход r2

Настройка «Zigbee links»: подсказка о функции, её ограничениях и легенда цветов, пунктира и стрелок.

Ветка issue/459-zigbee-links-help, HEAD 50bc1d6955dc59ffbd9c10cc31be26418bf1674d, база origin/dev = 7320937f627f18d0f473ca526d68906bea620a27 (после ребейза; #457 уже влился в dev).

Почему разбор ПОЛНЫЙ, а не по дельте

Раунд r2 открыт не находкой ревьюера, а ребейзом: код-ревью r1 (951cbd01) вынесло зелёный вердикт (комментарий 9), но к моменту его публикации dev продвинулся на 10 коммитов и слияние конфликтовало (комментарии 10–11). Автор сделал git rebase origin/dev, запушил 50bc1d69 и вернул S7-code-review (комментарий 12).

Ребейз на ушедший вперёд dev — это один из явно названных случаев, когда разбор остаётся полным независимо от размера дельты (§7.2, §2.9): база изменилась, а не только правка автора. Поэтому я:

  1. заново прогнал все дешёвые гейты на текущем HEAD (ниже);
  2. заново подтвердил каждый AC самостоятельно (тестом или чтением);
  3. отдельно проверил, что именно изменилось при ребейзе и что — нет.

Материал ребейза: что реально изменилось

Побайтовое сравнение продуктовых файлов задачи между 951cbd01 (материал r1) и 50bc1d69 (текущий HEAD):

git diff 951cbd0174bb HEAD -- src/hp-zigbee-topology-settings.ts src/i18n/topology.ts

— пусто. Файл-компонент и резолвер hasTopologyTranslation не изменились ни на символ.

Блок тестов #459 в test/zigbee-topology.test.mjs (от маркера // #459. до конца файла) сравнен построчно — идентичен. Дифф всего файла между теми же SHA показывает изменения (162 строки), но это тесты #457, добавленные в dev после 951cbd01, не пересекающиеся с блоком #459.

Четыре словаря topology/{en,ru,de,fr}.json получили от #457 три новых ключа (route_device_not_on_plan, route_coordinator_not_on_plan, route_other_space) — не пересекаются со строками help/help_aria этой задачи и добавлены во все четыре языка одинаково (паритет AC6 не пострадал — проверено гейтом ниже).

scripts/mutation-gate.mjs: два мутанта topology-help-* этой задачи не менялись; #457 добавил в тот же файл свои четыре мутанта рядом.

Конфликт при ребейзе (по словам автора, комментарий 12) был только в производных/документационных файлах: docs/CHANGELOG*.md (обе записи, #457 и #459, сохранены — проверил чтением, обе на месте в обоих языках), docs/images/screenshots.json (отпечаток источника, пересчитан штатно) и весь закоммиченный бандл (пересобран заново). Я подтвердил это сверкой дифф-статов и содержимого, а не принял на слово.

src/hp-help.ts, hp-zigbee-topology-overlay.ts, device-presentation.ts, logic.ts — не тронуты ни этой задачей, ни ребейзом (git diff origin/dev...HEAD по этим путям пуст). Контракт §5 ТЗ («что не меняется») держится.

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

Материал — git log --oneline origin/dev..HEAD (5 коммитов) и git diff origin/dev...HEAD (42 файла: 8 продуктовых/тестовых + генерируемые + документация). Зелёного Validate на 50bc1d69 нет: единственный прогон на этом SHA (33954914944) — failure, один упавший джоб «Смоки в браузере (шард 1 из 3)», лог которого называет ровно FAIL smoke_furniture — то же самое, что автор описал в комментарии 12 и на что завёл отдельный #460 (trivial, S6-in-progress, не про #459). Проверил сам, не на слово: gh run view 33954914944 --log-failed показывает единственную причину падения — smoke_furniture, диф #459 этот файл не трогает.

Поэтому дешёвые гейты прогнал сам, на 50bc1d69:

Гейт Результат
npx tsc --noEmit OK, без ошибок
npm test 1987 pass / 0 fail / 1 skip (1988 тестов, npm run inventory подтверждает то же число); все 7 тестов #459 (AC1, AC2, AC3, AC3b, AC4, AC5, AC6) — ok
npm run build чисто, git status после сборки пуст — закоммиченный dist byte-for-byte совпадает со свежей сборкой
npm run bundle:sync пересборка + синхронизация custom_components/houseplan/frontend и demo/srv/assets; git status после — чисто, три копии совпадают
npm run bundle:budget initial View 297 496 Б (потолок 298 000±2000, budget 300 000) — совпадает с заявленным автором числом; потолок не поднимался; предупреждение о низком запасе — унаследованный долг #367, не новый
node scripts/check-docs.mjs passed, 7 файлов, 12 внешних ссылок
node scripts/mutation-gate.mjs --check 463 якоря (совпадает с заявленным автором «Реестр 457 → 459»), оба мутанта topology-help-* — ok; один посторонний FAIL — backend-гейт tests_backend/test_ha_websocket.py падает из-за отсутствующего локально модуля pytest, окружение не задевает custom_components/**/*.py (не тронут этой задачей)
node scripts/mutation-gate.mjs --id=topology-help-renders-without-aria лично применил мутацию — целевой тест покраснел, дерево вернулось чистым
node scripts/mutation-gate.mjs --id=topology-help-drops-arrow-legend то же — покраснел, поймано
node demo/smoke_zigbee_topology_hover.mjs (AC8) OK, 21/21 проверок true — оверлей, цвета, стрелки, default-off, ленивая загрузка не изменились
node scripts/smoke-select.mjs --base origin/dev --head HEAD НЕОПРЕДЕЛЁННОСТЬ — 2 изменённых файла src/**, 7 символов (DICTIONARIES, Lang, TopologyI18nKey, _help, hasTopologyTranslation, langOf, topologyT), ни один не связан ни с одним из 223 смоков доказуемо. Единственный смок, названный в AC (smoke_zigbee_topology_hover, AC8), прогнан отдельно выше вручную — инструмент про него не обязан знать, так как оверлей сам не менялся
npm run golden:verify 153/153 passed, 0 расхождений — включая general-color-popover-desktop-en, единственную сцену, задетую этой задачей (принятый на r1 эталон пережил ребейз без нового расхождения)
node --test test/single-source-numbers.test.mjs 3/3 pass (общий гейт «одно число — один источник», диф его не расширяет и не нарушает)

Не прогонял: python -m pytest tests_backend (диф не трогает custom_components/**/*.py); полные performance-профили (не названы в AC, диф не задевает чувствительные пути); npm run invariants (диф не касается стен/layout/marker.space/open_spans — задача только про словарь и один компонент настройки, геометрия не затронута).

Проверка по AC — заново, не по памяти r1

  • AC1 — render() кладёт ${this._t('title')}${this._help()} в .section (строка 187 файла, не изменилась с r1), не в .toggle. Тест подсказка вызывается из блока настройки топологии проверяет именно эту разметку — прогнан, зелёный. Открытие по наведению/фокусу/клику — поведение самого hp-help.ts (не тронут).
  • AC2 — _help() проверяет hasTopologyTranslation(lang,'help') и ...'help_aria' до рендера, иначе nothing. Мутант topology-help-renders-without-aria лично применён и пойман (см. таблицу выше).
  • AC3 / AC3b — тест подсказка называет все шесть пунктов легенды проверяет 10 паттернов по нормативной ru-строке (LQI, 40, 180, пунктир, исходящая→координатор, входящие, «без стрелки», «подпись на конце стрелки», «отсутствие стрелки»); отдельный тест ловит оговорку о приближённости (дерево маршрут, не путь пакета). Прогнаны — зелёные. Мутант topology-help-drops-arrow-legend лично применён и пойман.
  • AC4 — тест импортирует lqiColor из собранного test-build/logic.js и берёт hue(40)=0, hue(180)=120 из функции, затем ищет те же числа в тексте — границы не захардкожены в тесте отдельной константой. Прогнан — зелёный.
  • AC5 — для всех четырёх словарей: нет \n в help, обе строки (help, help_aria) непустые. Прогнан — зелёный.
  • AC6 — гейт паритета ключей и плейсхолдеров четырёх словарей против английского; проверил, что три новых ключа route_* от #457 не сломали паритет (все четыре языка получили одинаковый набор). Прогнан — зелёный.
  • AC7 — core-file-budget не задет (файл не входит в список ядровых), bundle:budget — 297 496 Б, на 2 Б меньше dev по словам автора; лично прогнал и подтвердил число, потолок не поднимался.
  • AC8 — smoke_zigbee_topology_hover.mjs лично прогнан, все проверки true.

Утверждённый нормативный текст §4.1 (654 знака ru) сверен посимвольно (len(help)==654 в Python) — совпадает дословно с текстом, зафиксированным владельцем в теле issue. Переводы en/de/fr прочитаны целиком: каждый несёт все пункты легенды и оговорку о приближённости без потерь смысла.

Закрытие раунда r1

Раунд r1 (комментарий 9, документ docs/reviews/CODE-REVIEW-459-r1.md, SHA 951cbd01) вынес зелёный вердикт без Medium — переоткрытия по существу не было, только вынужденный технический возврат из-за конфликта слияния (комментарий 11). Формальных «находок к исправлению» из r1 нет; ниже — судьба трёх Low, отмеченных там:

Находка r1 (Low) Статус в r2
Отчёт реализации называл «шесть новых тестов», в дифе — семь не тронуто и не требовалось: чисто редакторская неточность отчёта, к коду отношения не имеет
Новый _help() не проставляет data-help-key (в отличие от houseplan-editor-runtime.ts:1232, houseplan-onboarding-runtime.ts:58) не исправлено, по-прежнему так — проверил чтением всех трёх мест повторно; не блокирует ни один AC, поведение кружка не страдает
Гейт паритета AC6 лёг в test/zigbee-topology.test.mjs, а не в test/i18n.test.mjs, как называли «Затронутые файлы» ТЗ не тронуто — организационное расхождение, гейт работает (перепроверил падением не требовалось: тест сам содержит зелёную/фейлящую пару сценариев)

Ни одна не блокирует и в r2 не эскалируется — все три и раньше были приняты без правки с запиской, а код с тех пор не менялся.

Унаследовано из r1 без повторного построчного разбора

Ниже — то, что я не выводил заново с нуля, а принял на основании доказанной побайтовой идентичности кода (раздел «Материал ребейза» выше) и полного документа docs/reviews/CODE-REVIEW-459-r1.md (SHA 951cbd01):

  • построчная сверка контракта §1–§5 ТЗ с кодом (импорт hp-help, локальный _help(), namespace topologyT, отказ от переиспользования редакторского _help()) — код не менялся, вывод r1 в силе;
  • перевод легенды на en/de/fr сверен вручную построчно в r1; я самостоятельно перечитал все три файла в этом раунде (раздел AC выше) и подтверждаю тот же вывод независимо, а не только по ссылке;
  • откат (§ ТЗ «Откат») — не проверялся заново, код рендера и словарей не менялся, ревертить по-прежнему нечего кроме вызова хелпера.

Каждый AC при этом я подтвердил заново сам (гейты и тесты выше), а не принял на слово — «унаследовано» здесь относится только к смысловому построчному разбору контракта, не к проверяемости.

Что проверено и корректно

  • Все восемь AC доказаны прогонами на текущем HEAD, не на памяти о r1.
  • Оба мутанта реально ловятся — применил лично, не поверил реестру.
  • golden:verify — 153/153, включая сцену, задетую этой задачей и ребейзом.
  • Ребейз не потерял ни одной записи CHANGELOG, не сломал паритет словарей, не задел оверлей/hp-help/logic.ts.
  • Единственный красный CI на 50bc1d69 — независимо подтверждённый предсуществующий флейк smoke_furniture (#460), не имеющий отношения к #459 и не тронутый этим диффом.
  • Трейлеры коммитов: Issue: #459 на всех пяти, User-Visible: yes в feat-коммите сопровождается правкой обоих changelog в том же коммите; Release:/Baseline-Reviewed: на коммитах, трогающих demo/golden/baselines/**.

Чего не проверял и почему

  • python -m pytest tests_backend — custom_components/**/*.py в дифе нет.
  • Полные performance-профили — не названы в AC, диф не задевает чувствительные к перфу пути (текст словаря и один компонент настройки).
  • npm run invariants — диф не касается стен, layout, marker.space, open_spans или иных геометрических ссылок.
  • Остальные 222 браузерных смока сверх названного в AC8 — инструмент отбора вернул НЕОПРЕДЕЛЁННОСТЬ, тематически ни один не относится к namespace-компоненту без побочных эффектов на других поверхностях.

Итог

Продуктовый код и тесты этой задачи не изменились ни на символ со времени зелёного r1 — ребейз задел только производные файлы и документацию, и это подтверждено сравнением, а не заявлено. Полный самостоятельный прогон гейтов на текущем HEAD (50bc1d69) — тесты, сборка, бюджет, документация, мутанты, golden, целевой смок — зелёный. Восемь AC доказаны заново. Три Low из r1 остаются в силе, без блокировки. Красный CI на этом SHA — подтверждённо посторонний флейк, заведённый отдельным issue.

Вердикт: зелёный.


Материал раунда

  • Ветка: issue/459-zigbee-links-help, HEAD 50bc1d6955dc59ffbd9c10cc31be26418bf1674d.
  • База: origin/dev = 7320937f627f18d0f473ca526d68906bea620a27.
  • Предыдущий материал (r1, зелёный): 951cbd0174bbbc4cb069cf5f8832da8cc49f2ace, документ docs/reviews/CODE-REVIEW-459-r1.md.
  • Побайтовое сравнение продуктовых файлов 951cbd01→50bc1d69: src/hp-zigbee-topology-settings.ts, src/i18n/topology.ts — пусто (идентичны); блок #459 в test/zigbee-topology.test.mjs — идентичен построчно.

Материал раунда

  • Ветка: issue/459-zigbee-links-help, коммит 50bc1d6955dc — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 4cb9c23fd0ca54ef2841de18ac1b353fc54c5c3c
    git log --all --format='%H %T' | grep 4cb9c23fd0ca