16 KiB
SPEC-REVIEW-493-r1
Issue: #493 — «Сводная панель: ограничить picker и исправить локальные настройки,
мобильную форму и lifecycle».
ТЗ: docs/specs/493-summary-panel-hardening.md
(коммит 14beeb84, докс-only: docs/specs/493-summary-panel-hardening.md +
docs/specs/README.md).
Этап: ТЗ на ревью (S4-spec-review). Заход r1. Блокирующих циклов израсходовано 0/4.
Трек: полный (аналитик назвал 4 нарушенных критерия small — сложность/риск >3,
больше одной поверхности, есть межwriter-совместимость, есть влияние на
производительность и touch).
Скоуп ревью
Материал — ровно коммит 14beeb84 на ветке issue/493-summary-panel-hardening
(рабочая копия уже на нём, git diff --check показывает только этот коммит,
никакого продуктового кода в диапазоне 71aeb860..14beeb84 нет). Задача
продолжает утверждённое исключение #437 из docs/SCOPE.md (read-only summary
overlay, J1/J6) и закрывает пять подтверждённых аудитом acceptance-пробелов
(F3–F6, B4), не дублируя #490 (lost-ACK recovery/live invalidation).
Как проверялось
- Прочитаны
docs/SCOPE.md,AGENTS.md,PROCESS.md(§1–§10, §2.10 для формата раунда — не понадобился, это r1 без предшествующего вердикта). - Прочитано тело issue #493 и все три комментария (аналитика S2, «ТЗ готово», и отчёт о сбое автопрогона ревью).
- Прочитан ТЗ-документ целиком (482 строки).
- Сверены обязательные разделы §7.1 PROCESS.md построчно с оглавлением документа — все 13 присутствуют (см. таблицу ниже).
- Фактическая проверка проблемы (§3 ТЗ) по текущему коду, а не на слово
автора — аудит цитирует конкретные строки на устаревшем SHA
ea6061e9, и с тех пор в код никто не коммитил (ветка ТЗ — чисто docs), так что актуальный код на HEAD это тот же код:- F3 подтверждён:
src/summary-panel-editor.ts:45-52,219-222—allEntitiesстроится сортировкой всегоhass.statesвнутри рендер-функции иentities.map()кладёт полный список<option>в каждую value-строку. - F4 подтверждён:
src/houseplan-card.ts:3182-3183вsetConfig()перезаписывает_kioskScaleизLS_KIOSKбезусловно;loadLocal()вsrc/summary-panel-runtime-loaded.ts:276-288перезатирает то же поле местнымparseSummaryLocal, но порядок вызовов (setConfig→connectedCallback→loadLocal) — источник наблюдаемого сброса. - F5 подтверждён:
_leaveCardRoute()(src/houseplan-card.ts:7472-7533) обнуляет explicit editor/dialog поля (_supportDialog,_markerDialog, …), но нигде не трогаетthis._summary(summary runtime/dialog), который создаётся отдельно (src/houseplan-card.ts:2285,2613). - F6 подтверждён:
.summary-local-sizesвsrc/summary-panel-style.ts:188-190— жёсткая трёхколоночная gridmax-content minmax(140px,1fr) 48px, без media/container query. - B4 подтверждён:
config/setвызываетpreserve_summary_panel_namespaceиvalidate_summary_panel_references(custom_components/houseplan/websocket_api.py:1588,1593),ws_plan_optimize(там же,:1890-1970) их не вызывает вообще.
- F3 подтверждён:
- Сверены заявленные в ТЗ канонические контракты с действующими документами
подсистемы:
docs/CONFIG-COMPATIBILITY.md(«Summary panel namespace (#437)») — omission-preserve и change-aware reference validation, которые ТЗ §10 расширяет на Optimize, совпадают с уже описанным контрактомconfig/set, это последовательное расширение, а не новое изобретение.docs/TOUCH-SUPPORT.md— «summary panel… and its simple settings form» прямо названы поддерживаемой touch-first View-поверхностью с требованием 44×44 px и «reachable content on a narrow viewport»; это точно то, что ТЗ §9/AC6 требует для обеих форм (admin и local-only), значит требование не является новым UX-контрактом, а закрывает уже объявленный, но нарушенный на практике (F6) контракт.docs/specs/437-summary-panel.md:580уже требовал «200% browser zoom» — значит требование 200%-увеличенного текста в AC6 не изобретено этим ТЗ, а унаследовано из уже принятого контракта #437 (и совпадает с паттерном, который используется в #57/#86/#180 для аналогичных форм).docs/USER-GUIDE.ru.md§«Сводная панель» — термины ТЗ («Настройки сводной панели», локальный показ, два ползунка размера) совпадают с уже описанной пользователю формулировкой; новых пользовательских терминов не введено.
- Проверено, что
local identity(ключ включаетhass.user.id) — уже действующее поведение (summary-panel-runtime-loaded.ts:252-254), а не новое продуктовое решение, которое требовало бы вопроса владельцу. - Проверены лимиты 10 блоков / 20 значений в текущем коде
(
summary-panel-editor.ts:230,242) — совпадают с «не в скоупе» ТЗ §4. - Проверена регистрация ТЗ в
docs/specs/README.md(двусторонняя ссылка issue ↔ ТЗ на месте) и трейлеры коммита (Issue: #493,User-Visible: no— корректно для чисто документационного коммита). git diff --checkна диапазоне коммита: единственное замечание — лишняя пустая строка в конце файла (см. Low ниже).
Гейты
Материал этого раунда — документ (класс C, докс-only коммит). Продуктовый код,
тесты и бандл не менялись, поэтому дорогие/дешёвые гейты (typecheck, npm test, npm run build, смоки, golden, check-docs, инварианты модели) к этому
диффу неприменимы и не гонялись — гонять их значило бы проверять код, который
эта задача ещё не написала. Зелёный Validate на 14beeb84, на который ссылается
задание, покрывает ровно то же самое docs-only состояние дерева. Единственная
механическая проверка, применимая к самому файлу ТЗ, — git diff --check
(см. выше, результат — Low).
Проверка обязательных разделов ТЗ (PROCESS.md §7.1)
| Раздел §7.1 | Есть в документе | Где |
|---|---|---|
| Сценарий | да | §1 |
| Что человек увидит до/после | да | §2 |
| Проблема | да | §3, с проверяемыми числами и ссылками на код |
| Скоуп и не-скоуп | да | §4 |
| Контракт поведения | да | §5–§8, §10–§11 |
| UX | да | §6, §9 |
| Модель данных и миграция | да | §12 |
| i18n | да | §13 |
| AC1…ACn с доказательством | да | §15, все 10 называют метод и негативного свидетеля |
| План автотестов | да | §16 |
| Риски | да | §17 |
| Откат | да | §18 |
| Release-артефакты | да | §19 |
Дополнительно: продуктовые вопросы владельцу не заданы, и это оправдано — видимое поведение уже зафиксировано #437/аудитом, а раздел §20 «Принятые технические предположения» корректно выносит все нерешённые технические детали (лимит 100 строк, место backend helper, механизм инвалидации индекса, имена файлов) в явный блок «предположительно, поменять свободно», как требует §7.1. Ни одного случая, когда догадка о поведении подана как факт без пометки, не найдено — там, где ТЗ утверждает конкретное поведение (F3–F6, B4, лимиты, touch-контракт, 200%-zoom), утверждение подтверждено либо действующим кодом, либо действующим каноническим документом.
Находки
Low — лишняя пустая строка в конце файла ТЗ
docs/specs/493-summary-panel-hardening.md заканчивается двумя \n\n
(git diff --check подтверждает: «new blank line at EOF»). Чисто
косметическое, не влияет на содержание, ссылки или AC. Снимается решением
ревьюера без правки — цена отдельного цикла ради одного символа выше цены
находки.
Других находок — High, Medium в скоупе или Medium вне скоупа — не выявлено.
Что проверено и корректно
- Все 13 обязательных разделов §7.1 присутствуют и содержательны.
- Каждый из пяти «подтверждённых сценариев» проблемы (F3–F6, B4) верифицирован чтением текущего кода на HEAD, а не принят на слово автора.
- Все 10 AC пронумерованы, для каждого указан способ доказательства (unit/backend/smoke/golden/performance) и названа мутация/негативный свидетель, который должен покраснеть — соответствует требованию «доказуемость» на этапе ТЗ.
- Touch- и zoom-требования (AC6, 44×44 px, 200% text, 320/390 px) — не новый
UX-контракт, а закрытие уже объявленного в
docs/TOUCH-SUPPORT.mdиdocs/specs/437-summary-panel.mdконтракта, нарушенного на практике (F6). - Backend-контракт (§10, писательская матрица §11) — прямое расширение уже
задокументированного в
docs/CONFIG-COMPATIBILITY.mdповеденияconfig/setнаplan/optimize, без новых persisted-полей и без version bump (§12), что соответствуетdocs/SCOPE.md(не расширяет панель до dashboard framework). - Раздел «Принятые технические предположения» (§20) корректно отделяет нерешённые инженерные детали от продуктового контракта; все пункты не затрагивают видимое поведение и могут быть оспорены ревьюером кода без возврата к владельцу.
- Откат (§18) назван реалистично и явно запрещает частичный откат (backend guard без generation token и наоборот).
- Issue ↔ ТЗ связь двусторонняя (
docs/specs/README.mdобновлён в том же коммите), трейлеры коммита корректны (Issue: #493,User-Visible: no).
Чего не проверял
- Не проверялась реализация (её ещё нет — коммит docs-only); всё, что относится к фактическому поведению кода после реализации, — предмет код-ревью.
- Не прогонялись
typecheck/test/build/смоки/golden/check-docs— диапазон ревью не содержит измененийsrc/**илиcustom_components/**, эти гейты неприменимы к этапу спецификации. - Не проверялись предположения §20 на техническую реализуемость (например, выбор конкретного DOM-примитива для picker) — это осознанно оставлено инженеру и ревьюеру кода.
- Не запрашивалось у владельца ничего сверх того, что уже решено в комментарии аналитика — открытых продуктовых вопросов в ТЗ нет и не найдено.
Вердикт
Зелёный. ТЗ полно, каждый заявленный факт проблемы подтверждён чтением действующего кода, каждый AC проверяем и называет негативного свидетеля, обязательные разделы на месте, технические предположения явно отделены от продуктового контракта, скоуп не выходит за рамки утверждённого исключения #437. Единственная находка — Low, снята без правки.
Материал раунда
- SHA материала:
14beeb8470a7189ddef5a8bd99a15630e2232d4e(веткаissue/493-summary-panel-hardening, рабочая копия HEAD detached на этом коммите). - Дерево ТЗ:
docs/specs/493-summary-panel-hardening.md— 481 строка, добавлен этим коммитом целиком (см.git show --stat 14beeb84). - Предшествующего вердикта нет — это r1; раздел «Унаследовано из r0» не применяется.
Материал раунда
- Ветка:
issue/493-summary-panel-hardening, коммит14beeb8470a7— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
ff7e45438b049665f1e751ef4943d9ee25044779git log --all --format='%H %T' | grep ff7e45438b04 - ТЗ
docs/specs/493-summary-panel-hardening.md, блоб19ebcb9df3035661a422cc0d02af71897b73f7c5git log --all --find-object=19ebcb9df3035661a422cc0d02af71897b73f7c5 -- docs/specs/493-summary-panel-hardening.md - Вердикт конвейера:
green· High 0