Files
claude[bot] d35a52a3f1
Проверка (CI) / Предполёт: документация, провенанс, процесс (push) Failing after 13m31s
Проверка (CI) / Классификация изменённых файлов (push) Failing after 14m40s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Skipped
Проверка (CI) / HACS: валидация репозитория (push) Skipped
Проверка (CI) / Hassfest: манифест интеграции (push) Skipped
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Skipped
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Skipped
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Skipped
Проверка (CI) / Доказательство выполненных проверок (push) Failing after 1m38s
docs: review document for #647
Issue: #647
User-Visible: no
2026-09-25 08:57:28 +00:00

18 KiB
Raw Permalink Blame History

CODE-REVIEW-647-r1

Issue: #647 · Этап: code · Заход: r1 · SHA материала: f0ba7c5da97418e2b81a257d7b8eda4604e3a41e

Скоуп

ТЗ (редакция r2, спор закрыт SPEC-REVIEW-647-r2, зелёный) требует: убрать текстовый счётчик устройств «N устр.» из шапки основной панели; вынести × закрытия редактора из активной кнопки режима в отдельный слот постоянного размера 24×24 px сразу после группы кнопок режимов; слот пустой и инертен (aria-hidden, без фокуса) вне редактора; слот виден на любой ширине, где видны кнопки режимов, включая 721–1100 px, где раньше скрывался счётчик; ширина шапки и позиции соседних контролов не меняются при входе/выходе/переключении редакторов; кликабельная зона × не меньше 24×24 px; настраиваемая метрика «Количество устройств» сводной панели (#437) не затрагивается.

Диапазон материала — один коммит 44fed222/f0ba7c5d поверх dev (27d78801; dev с тех пор получил только неконфликтующий коммит приёмки golden 632d6a2f). Правка: src/houseplan-card.ts (шапка), src/styles/chrome.styles.ts (слот и ×), src/styles/dialogs.styles.ts (удаление .count/медиа-правила), 4 словаря i18n (удаление count.devices), новый смок demo/smoke_toolbar_stable_width.mjs, 3 переведённых смока, 6 мутантов, документы (UX-MODES.md, STYLING-HOOKS.md, data-hp-contract.json), оба changelog, бандл.

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

Дешёвые гейты подтверждены зелёным Validate на этом SHA (run 36113808861): typecheck, npm test, npm run build+сверка копий бандла. Их не перегонял. Сам прогнал то, что Validate не покрывает и что требует эта задача (визуальный/раскладочный диф):

Гейт Команда Результат
Пересборка бандла для смоков npm run bundle:sync OK, рабочее дерево после сборки совпало с закоммиченным (без диффа)
Юниты (перепроверка) npm test 3070/3070 pass, совпадает с заявленным
check-docs (режим, которым реально пользуется Validate) node scripts/check-docs.mjs --screenshots=warn Documentation checks passed (7 files, 12 external links); предупреждение о несвежих скриншотах — ожидаемо, §11.4 (см. «Чего не проверял»)
mutation-gate --check (якоря 6 новых мутантов целы) node scripts/mutation-gate.mjs --check все 6 toolbar-* — ok
Новый смок node demo/smoke_toolbar_stable_width.mjs OK, все проверки true на 1400/1000/768/390 px + ru
Мутант AC6 (медиа-скрытие слота ≤1100px) правка chrome.styles.ts → сборка → смок → откат смок красный: FAILED (9) — совпадает с заявленным в хендоффе числом
Мутант AC2 (слот display:none вне редактора) то же FAILED (8) — совпадает
Мутант AC5 (переменная размера слота 13px) то же FAILED (12) — совпадает
3 переведённых смока smoke_editor_tabs, smoke_edge_cases, smoke_hidden_flag все OK
node scripts/smoke-select.mjs --base origin/dev --head HEAD — 3 прямых совпадения (smoke_decor, smoke_modes, smoke_space_settings), 41 слабая связь через общие имена _mode/stopPropagation
Прямые совпадения smoke-select smoke_decor.mjs, smoke_modes.mjs, smoke_space_settings.mjs все OK (см. «Находки», Low-1 — smoke_decor не был назван в перечне гейтов автора)
AC8 (сводная панель) demo/smoke_summary_panel.mjs OK
Смежные header-смоки из перечня автора (переисполнены выборочно) smoke_kiosk, smoke_houseplan_panel, smoke_dialog_footer_width все OK
count.devices действительно не используется больше нигде grep -rn "count.devices" src/ demo/ scripts/ пусто — ключ мёртв, удаление безопасно
Бюджет ядра node --test test/core-file-budget.test.mjs 7/7 pass; фактически 12886 строк при потолке 12889 (под потолком, не «ровно на потолке», как написано в хендоффе — расхождение безвредное, не находка)

Слабые связи smoke-select (41 файл, общие символы _mode/stopPropagation) не прогонялись поштучно: диф ограничен CSS-раскладкой шапки и разметкой одного элемента, названные символы в них встречаются по всему ядру не по смежной причине (PDF-экспорт, стены, декор и т.д. не читают шапку). Прямые совпадения и AC-названные смоки покрывают risk surface этой задачи.

AC · разбор

Таблица «AC · чем доказан · чем краснеет» в теле issue заполнена по всем защитным AC (AC1–AC6), включая AC7 (регресс, без мутанта — верно помечено как таковой) и AC8 (существующие мутанты сводной панели). Пустых третьих столбцов нет.

  • AC1 (К1, нет числа). Прочитано: <span class="count"> и i18n-ключ count.devices удалены из шапки и всех 4 словарей (src/houseplan-card.ts дифф, src/i18n/{en,ru,de,fr}.json). grep подтвердил отсутствие иных чтений ключа. Смок w*_noHeaderCount + ru_noHeaderCount — зелёные, лично прогнал.
  • AC2 (К2, ширина шапки стабильна) / AC3 (К3, соседи не прыгают). Слот вынесен из кнопки режима как отдельный <span class="editor-close-slot"> с фиксированным width/height: var(--hp-editor-close-size) = 24px что вне редактора, что внутри — размер не зависит от содержимого. Кнопки .modetab больше не содержат × ни в одном состоянии. Смок w*_widthAndTabsStable/w*_idleSlotKeepsSize — зелёные; мутант «слот схлопывается вне редактора» лично воспроизведён, краснеет (8 FAILED, совпадает с заявленным).
  • AC4 (К4, × только в редакторе, слот инертен). aria-hidden выставлен ровно при this._mode === 'view'; в этом состоянии CSS [aria-hidden='true']{pointer-events:none} и в дереве нет кнопки (тернарник this._mode !== 'view' ? html\...` : nothing) — значит слот действительно без фокусируемых потомков, а не просто визуально пуст. Проверено чтением; смок w*_idleSlotInert` зелёный.
  • AC5 (К5, hit-target ≥24×24). Кнопка .closex внутри слота — width/height: 100%, слот — 24×24 через переменную; отрицательные поля старой реализации убраны. Мутант «переменная = 13px» лично воспроизведён, краснеет (12 FAILED, совпадает).
  • AC6 (К6, × не прячется на 721–1100 px). Правило @media (max-width: 1100px){.head .count{display:none}} удалено вместе со счётчиком (dialogs.styles.ts дифф), новый .editor-close-slot его не наследует — отдельный класс, отдельный файл (chrome.styles.ts). Мутант «добавить то же правило слоту» лично воспроизведён, краснеет (9 FAILED на 1000/768 px, 1400 зелёный — ровно то, что просил Medium-1 из SPEC-REVIEW-647-r1).
  • AC7 (К7, нет overflow). Регресс-проверка, мутанта нет (верно помечено в таблице). Смок w768/w390_noHeadOverflow зелёный, лично прогнал; дополнительно smoke_dialog_footer_width (соседняя раскладка шапки) зелёный.
  • AC8 (сводная панель #437 не изменилась). Источник «Количество устройств» в отдельном модуле сводной панели, диф его не касается. smoke_summary_panel.mjs — зелёный, лично прогнал.

Документы синхронизированы: docs/UX-MODES.md — строка про panel-host (device count убран из перечня) и абзац про × (слот 24×24, ссылка на #195 сохранена); docs/STYLING-HOOKS.md — editor-close теперь описан как «слот после кнопок режимов»; docs/data-hp-contract.json — editor-close.elements сужен до ["button"] (соответствует коду: data-hp="editor-close" теперь только на <button>, не на <ha-icon>). docs/USER-GUIDE.ru.md счётчик не упоминал — правка не нужна, подтверждено grep. Golden и docs:capture — по §11.4 предрелizный гейт, не гейт код-ревью; ТЗ верно зафиксировало это как риск.

Одно число, видимое дважды: кликабельная зона × (24×24 px) названа и в docs/UX-MODES.md, и в CSS-переменной --hp-editor-close-size: 24px (chrome.styles.ts), и в новом AC5/К5 — источник один (переменная), документ и тест её же и проверяют, расхождения нет.

Трейлеры и changelog

Коммит несёт Issue: #647 и User-Visible: yes; оба changelog (docs/CHANGELOG.md, docs/CHANGELOG.ru.md) правлены в этом же коммите, текст соответствует пользовательскому результату из ТЗ (число исчезло, × не дёргает шапку, зона клика прежняя, «Количество устройств» сводной панели не изменилось).

Находки

Low-1. smoke-select называет demo/smoke_decor.mjs прямым совпадением по символам _mode/stopPropagation, но в перечне прогнанных гейтов хендоффа этого смока нет (назван smoke_decor нигде, хотя modes, houseplan_panel, space_settings — два других прямых совпадения — присутствуют). Смок реально зелёный — лично прогнал node demo/smoke_decor.mjs, все проверки прошли. Дефекта нет, это неполнота раскрытия «какие гейты прогнал» из трёх прямых совпадений smoke-select. Снимаю без возврата автору, с записью здесь.

Других находок нет: High — 0, Medium — 0.

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

  • Реализация буквально соответствует «принято предположительно» ТЗ: слот стоит на месте бывшего счётчика, отдельный класс без наследования правил .count, размер — одна переменная.
  • Кнопки режимов после правки не зависят от this._mode по ширине — единственный источник роста шапки убран, а не замаскирован.
  • Слот рендерится только внутри ветки this._canEdit, как и раньше сами кнопки режимов — для домочадца/киоска (не редактор) меняется ровно то, что заявлено в сценарии ТЗ: исчезает число, слота не появляется, потому что кнопок режимов там и не было.
  • 6 мутантов зарегистрированы в scripts/mutation-registry.mjs рядом с мутантами шапки/режимов, все опираются на реальный guard-прогон нового смока; 3 из 6 лично воспроизведены с результатом, совпадающим с заявленным автором числом упавших проверок — доверие к оставшимся трём (AC1, AC3, AC4) основано на чтении кода (тривиальные проверки: удалённый узел, убранный тернарник, перестановка атрибута) и на mutation-gate --check, подтвердившем целостность якорей патчей.
  • count.devices подтверждён мёртвым по всему дереву (src/, demo/, scripts/) — можно было безопасно удалить.
  • docs/data-hp-contract.json синхронизирован с фактической разметкой (data-hp="editor-close" переехал с <ha-icon> на <button>).

Чего не проверял

  • Golden-эталоны и docs:capture. ТЗ прямо называет их предрелизным гейтом (§11.4: «Golden, браузерные смоки... запускаются перед бетой, после того как код-ревью пройдено»); диф действительно меняет визуал (число пропадает из широких кадров, × переезжает из кнопки в слот во всех кадрах редактора) — пересъёмку и приёмку (golden:accept -- --reviewed, docs:capture) должен выполнить отдельный шаг на Linux CI, не этот раунд ревью.
  • Остальные ~38 из 41 «слабой связи» smoke-select (PDF-экспорт, стены, декор-объекты, локализация админки и т.д.) — не прогонял: общие символы _mode/stopPropagation не создают правдоподобного пути к раскладке шапки в этих сценариях, а полный прогон матрицы — предрелизная обязанность, не гейт ревью.
  • pytest tests_backend — диф не касается custom_components/**/*.py.
  • npm run invariants — диф не касается геометрии модели.
  • Windows/WSL и HA-харнесс — не запускал (не требуется этой задачей).
  • Мутанты AC1/AC3/AC4 (toolbar-device-count-returns, toolbar-close-back-inside-tab, toolbar-close-slot-idle-focusable) — не воспроизводил лично их фактическое покраснение; проверил чтением кода и статической целостностью якорей (mutation-gate --check).

Вердикт

High: 0 · Medium: 0 (в скоупе, вне скоупа не заводились) · Low: 1 (снят ревьюером с записью, без возврата). Все 8 AC доказаны либо воспроизведённым красным мутантом, либо чтением кода с объяснением инварианта. Реализация закрывает ровно тот сценарий, который просил владелец: число убрано, × стабилен по позиции и размеру на всех проверяемых ширинах, сводная панель не задета.

Зелёный.


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

  • Ветка: issue/647-toolbar-stable-width, коммит f0ba7c5da974 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 1adfc8927e46176aa74764f46be70bd5e3ff8b08
    git log --all --format='%H %T' | grep 1adfc8927e46
    
  • Тело issue: 96f3d23ef7e626083567418cc5d5c098150d97627da79dc8ebe77b949f39a1c1
  • Вердикт конвейера: green · High 0