Files
houseplan-card/docs/reviews/SPEC-REVIEW-493-r1.md
T
2026-09-09 02:53:36 +03:00

208 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-REVIEW-493-r1
Issue: [#493](https://github.com/Matysh/houseplan-card/issues/493) — «Сводная панель: ограничить picker и исправить локальные настройки,
мобильную форму и lifecycle».
ТЗ: [`docs/specs/493-summary-panel-hardening.md`](https://github.com/Matysh/houseplan-card/blob/issue/493-summary-panel-hardening/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).
## Как проверялось
1. Прочитаны `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` (§1–§10, §2.10 для
формата раунда — не понадобился, это r1 без предшествующего вердикта).
2. Прочитано тело issue #493 и все три комментария (аналитика S2, «ТЗ готово»,
и отчёт о сбое автопрогона ревью).
3. Прочитан ТЗ-документ целиком (482 строки).
4. Сверены обязательные разделы §7.1 PROCESS.md построчно с оглавлением
документа — все 13 присутствуют (см. таблицу ниже).
5. **Фактическая проверка проблемы (§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`
— жёсткая трёхколоночная grid `max-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`) их не вызывает вообще.
6. Сверены заявленные в ТЗ канонические контракты с действующими документами
подсистемы:
- `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` §«Сводная панель» — термины ТЗ («Настройки сводной
панели», локальный показ, два ползунка размера) совпадают с уже описанной
пользователю формулировкой; новых пользовательских терминов не введено.
7. Проверено, что `local identity` (ключ включает `hass.user.id`) — уже
действующее поведение (`summary-panel-runtime-loaded.ts:252-254`), а не
новое продуктовое решение, которое требовало бы вопроса владельцу.
8. Проверены лимиты 10 блоков / 20 значений в текущем коде
(`summary-panel-editor.ts:230,242`) — совпадают с «не в скоупе» ТЗ §4.
9. Проверена регистрация ТЗ в `docs/specs/README.md` (двусторонняя ссылка
issue ↔ ТЗ на месте) и трейлеры коммита (`Issue: #493`, `User-Visible: no`
— корректно для чисто документационного коммита).
10. `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» не
применяется.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/493-summary-panel-hardening`, коммит `14beeb8470a7` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `ff7e45438b049665f1e751ef4943d9ee25044779`
```
git log --all --format='%H %T' | grep ff7e45438b04
```
- ТЗ `docs/specs/493-summary-panel-hardening.md`, блоб `19ebcb9df3035661a422cc0d02af71897b73f7c5`
```
git log --all --find-object=19ebcb9df3035661a422cc0d02af71897b73f7c5 -- docs/specs/493-summary-panel-hardening.md
```
- Вердикт конвейера: `green` · High 0