docs: review document for #180

Issue: #180
User-Visible: no
This commit is contained in:
claude[bot]
2026-08-19 08:30:56 +00:00
parent 3540d24f18
commit f69ac71ef7
+184
View File
@@ -0,0 +1,184 @@
# SPEC-REVIEW-180-r1
- **Issue:** [#180](https://github.com/Matysh/houseplan-card/issues/180) — hp-color-opacity: unified picker не покрывает ripple/activity-color и state-color settings (wall/light/temp/LQI/glow)
- **ТЗ:** `docs/specs/180-all-color-call-sites.md` (коммит `3540d24`, ветка `issue/180-unified-color-picker`)
- **Трек:** обычный (метка `small` не установлена; лимит циклов ревью ТЗ — 4)
- **Ревьюер:** Claude, роль «ревьюер ТЗ» (сессия отдельна от анализа/автора)
- **Цикл:** r1/4
## Вердикт
**Зелёный.** High: 0 · Medium: 0. Одна Low-находка, ниже — с записью «waived».
## Скоуп проверки
Этап — ревью ТЗ (PROCESS.md §2.4). Материал: тело issue #180, оба комментария
(аналитика владельца + хендофф автора ТЗ), файл `docs/specs/180-all-color-call-sites.md`,
`docs/specs/README.md`, канонический `docs/specs/057-color-opacity-picker.md`
(родительский контракт `hp-color-opacity`), `docs/USER-GUIDE.ru.md`,
`docs/TOUCH-SUPPORT.md`, `docs/CONFIG-COMPATIBILITY.md` и фактическое состояние
`src/houseplan-card.ts`, `src/hp-color-opacity.ts`, `src/logic.ts`, `src/types.ts`,
`src/i18n/{en,ru}.json` на ветке `issue/180-unified-color-picker` (совпадает с
`origin/dev` + два документационных коммита). Продуктовый код на этой ветке не
менялся — проверено `git diff --name-only origin/dev...HEAD`: только
`docs/specs/180-all-color-call-sites.md` и `docs/specs/README.md`.
## Как проверялось
Ревью состязательное: каждое фактическое утверждение ТЗ (номера полей, названия
свойств API, i18n-ключи, персистентная модель) сверено с реальным кодом на ветке,
а не принято со слов автора.
1. Прочитаны `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` (полностью, включая §7.1,
§4, §5) — для критериев обязательных разделов, лимита циклов и трека.
2. Прочитано issue #180 целиком: исходная находка ревьюера #57, комментарий
аналитики владельца (2026-08-19, сам зафиксировал продуктовый контракт —
мигрировать все 15 полей), хендофф автора ТЗ.
3. Прочитан весь файл ТЗ `docs/specs/180-all-color-call-sites.md` (17 разделов).
4. Прочитан канонический `docs/specs/057-color-opacity-picker.md` — сверен
заявленный публичный API `hp-color-opacity` (`color`, `opacity`,
`showOpacity`, `disabled`, `label`, `opacityLabel`, `pickerLabels`,
событие `hp-color-opacity-change`) с тем, что ТЗ #180 обещает переиспользовать.
5. Построчно сверены с исходным кодом (`Read`/`Grep`):
- все пять native `<input type="color">` в `src/houseplan-card.ts`
(14503, 15085, 19332, 19529, 19548) — состав и группировка полей совпадают
с таблицей §4 ТЗ (11 через `_renderColorRow`, плюс bgColor/ripple/roomColor/
space bgColor);
- публичные свойства `hp-color-opacity` (`src/hp-color-opacity.ts:34-62`) —
`showOpacity`, `pickerLabels`, `opacityLabel`, `disabled` реально существуют;
- уже мигрированный Glow (`houseplan-card.ts:19158-19168`) как прецедент
паттерна `showOpacity=false` + игнорирование opacity в draft — совпадает с
§7.2 и техническим предположением №2 ТЗ;
- модель данных: `FillColors` (`src/types.ts:1287-1302`, тип `{c,a}`),
`space.settings.room_color/room_opacity` (`src/logic.ts:1245-1246`,
`houseplan-card.ts:13447-13448`), `marker.ripple_color`
(`src/types.ts:131`), `settings.bg_color`/`space.settings.bg_color`
(`houseplan-card.ts:13449, 14436-14437`) — все совпадают с §9 ТЗ буквально;
- i18n-ключи, на которые ссылается ТЗ (`gs.wall_fill`, `gs.bg_default`,
`gs.bg_theme`, `space.bg_inherit`, `space.bg_inherited`,
`marker.activity_color`, `marker.ripple_size`, `space.room_color`,
`space.opacity`) — присутствуют в обоих `en.json`/`ru.json` парами.
6. Терминология сверена с `docs/USER-GUIDE.ru.md`: «Общие настройки», «Пространство»,
формулировка decor-picker («нажмите на образец цвета, чтобы открыть выбор цвета
и прозрачности», строка 947) и существующее описание пульсации активности
(строки 721-748) — ТЗ не придумывает новых терминов.
7. Формулировка `Touch editor: supported` (§11 ТЗ) сверена с каноническим
списком трёх допустимых фраз в `docs/TOUCH-SUPPORT.md:149-151` — совпадает
буквально.
8. `docs/CONFIG-COMPATIBILITY.md` — подтверждено, что задача не вводит и не
меняет персистентные поля, поэтому реестр совместимости не затрагивается;
ТЗ §9 прямо констатирует это, а не молчит об этом.
9. Проверена трассируемость: `docs/specs/README.md:113-114` содержит обе строки
(issue ↔ ТЗ) для #57 и #180; коммит `3540d24` несёт корректные трейлеры
`Issue: #180` / `User-Visible: no` (`git log -1 --format=... 3540d24`).
10. Проверена феासибельность golden-плана: `demo/golden/{harness,accept,matrix}.mjs`
построены вокруг произвольного `scenario.id`/`viewport`/`theme` — добавление
трёх новых сценариев (general settings, marker mobile, space) механически
возможно без архитектурных изменений инфраструктуры.
11. Проверено отсутствие незамеченных мест: полный `grep -rn "type=[\"']color[\"']" src/*.ts`
— ровно 5 совпадений в `houseplan-card.ts` (совпадает с инвентаризацией ТЗ)
плюс одно в `src/styles.ts:2162` — CSS-селектор, разбор ниже.
12. Проверено, что day/night фон (`bgMode: 'daynight'`) не хранит собственных
цветов (процедурный градиент по `docs/SUN.md`), то есть инвентаризация ТЗ
(пять шаблонов/15 полей) действительно исчерпывающая, а не пропускает шестое
скрытое место.
Гейты для этапа спек-ревью не прогонялись — на этой стадии нет продуктового кода
для typecheck/test/build; сам факт отсутствия правок в `src/**` подтверждён diff'ом
(п.10 выше), а не декларацией автора.
## Находки
### Low-1 — CSS-селектор `input[type='color']` не упомянут в плане очистки
**Файл:** `src/styles.ts:2162` (`.colorrow input[type='color'] { width: 42px; ... }`).
После миграции ни один элемент в DOM не будет соответствовать этому селектору —
правило станет мёртвым. ТЗ формулирует source-invariant AC1 как «в `src/**/*.ts`
отсутствует `input[type=color]` в любой допустимой Lit-форме» — эта фраза точна
для шаблонов, но явно не называет `styles.ts` и не включает очистку CSS в план
тестов (§13, п.1: «Рекурсивный scan `src/**/*.ts` запрещает native
`input[type=color]`»). Риск скорее методологический, чем поведенческий: если
исполнитель реализует scan буквальным regex по всему `src/**/*.ts` без разбора
Lit-шаблонов от строковых литералов CSS, тест либо ложно упадёт на не относящемся
к делу файле, либо (если scan ограничат template literals) осиротевшее правило
останется в бандле молча.
**Воспроизведение:** `grep -rn "type=\"color\"\|type='color'" src/*.ts` — 5
совпадений в `houseplan-card.ts` (реальные шаблоны) + 1 в `styles.ts` (CSS
селектор), тогда как ТЗ и его AC1 описывают только первые пять.
**Серьёзность:** Low — не блокирует ни один AC, не меняет наблюдаемое поведение,
исправляется одной строкой при реализации.
**Решение ревьюера:** waived, с записью. AC1 в применении к «допустимой Lit-форме»
де-факто ограничивает scope шаблонами; удаление мёртвого CSS-правила — естественное
следствие реализации АС2/АС3 (все пять consumers перестают рендерить native input)
и не требует отдельного продуктового решения владельца. Не выношу отдельным issue:
находка ниже порога Medium (PROCESS.md §3.8), достаточно фиксации здесь.
## Что проверено и корректно
- **Обязательные разделы §7.1** — все присутствуют и в правильном порядке:
сценарий (§1), что человек увидит до/после (§2), проблема (§3), scope/не-scope
(§4-5), контракт поведения (§6-7), UX/accessibility (§8), модель данных и
совместимость (§9), i18n (§10), touch как часть UX-контракта (§11), AC1-AC8 с
доказательством у каждого (§12), план автотестов (§13), риски (§14), откат (§15),
release-артефакты (§16). Плюс два продуктовых обязательных пункта — персона/
поверхность/момент и однострочное «что увидит человек» — закрыты §1-2 без
терминов реализации.
- **Трек выбран верно.** Сложность 4/10, пять разных dialog families, alpha/
nullable/inherit контракты — превышает порог «одна поверхность» и «сложность
≤3» из §5 PROCESS.md; `small` не применили обоснованно.
- **Инвентаризация полная и точна.** Все 15 полей и все 5 native-шаблонов из §4
ТЗ подтверждены построчно в текущем `src/houseplan-card.ts`; ни одно
дополнительное место (day/night, decor, room custom fill, Glow — уже
мигрированные #57 consumers) не пропущено и не задвоено.
- **Технические утверждения не являются догадками.** Каждое поведенческое
обещание (nullable/default/inherit модель, `showOpacity=false` не пишет alpha,
`hp-color-opacity` API) имеет прямой аналог в уже смерженном коде (#57, Glow) —
это перенос существующего паттерна, а не изобретённое поведение.
- **AC проверяемы и однозначны.** Все 8 AC пронумерованы, у каждого — конкретный
способ доказательства (unit/source-scan, DOM/browser smoke, golden, round-trip
unit); ни один не сформулирован расплывчато настолько, чтобы допускать
произвольную трактовку «выполнено».
- **Продуктовая неопределённость закрыта на входе, а не додумана.** Ключевой
продуктовый вопрос («что входит в #180 — весь остаток native color inputs или
уже нет») задан и решён самим владельцем в комментарии аналитики 2026-08-19,
до написания ТЗ; спека честно ссылается на это решение (§4, преамбула) вместо
того чтобы выдавать его за собственную догадку автора.
- **Assumed-block корректен.** §17 содержит 5 явно технических предположений
(структура компонентов, обработка `opacity=1` для color-only, локальность
layout-классов, отсутствие reset callback у picker, golden thresholds на
реализации) — ни одно из них не является продуктовым вопросом, который следовало
бы задать владельцу.
- **Терминология и touch-формулировка соответствуют канону** — сверено с
`docs/USER-GUIDE.ru.md` и `docs/TOUCH-SUPPORT.md` построчно (см. «Как
проверялось», пп. 6-7).
- **Совместимость.** §9 явно и верно констатирует отсутствие изменений схемы/
миграции; сверка с `docs/CONFIG-COMPATIBILITY.md` подтверждает, что реестр не
требует новой записи.
- **Трейлеры и трассируемость корректны** для документационного коммита на этом
этапе (`Issue: #180`, `User-Visible: no`, ссылки issue ↔ ТЗ в
`docs/specs/README.md`).
## Чего не проверял
- Golden pixel-thresholds и точные scenario id — по ТЗ (§17, п.5) выбираются на
реализации по полному Linux-артефакту; на этапе спек-ревью нет артефакта для
проверки.
- Реальную работу браузерных smoke/golden сценариев — код ещё не написан
(подтверждено diff'ом), поэтому запуск `npm test`/`npm run build`/
`node demo/smoke_color_picker.mjs` на этом этапе неприменим и не выполнялся.
- Backend/Python — задача не касается `custom_components/**/*.py`; pytest не
запускался, это верно для class A/B TS-only изменения.
- Производительность на реальном железе — компонентная модель без новых
observers/network подтверждена чтением, а не профилированием (профиль не
требуется до S7-code-review при отсутствии заявленного perf-риска).
## Итог
ТЗ #180 выполнимо, проверяемо и не содержит выданных за факт догадок: каждое
поведенческое утверждение либо повторяет уже принятый контракт #57, либо сверено
с текущим кодом. Единственная находка (Low, мёртвый CSS-селектор вне явного
scope AC1) waived с запиской, доработки ТЗ не требует. Готово к `S5-ready`.