Files
houseplan-card/docs/reviews/CODE-REVIEW-211-r2.md
T
2026-08-19 22:05:42 +00:00

150 lines
11 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.
# CODE-REVIEW-211-r2 — коррекция compatibility-смока после полного Linux CI
- **Issue:** https://github.com/Matysh/houseplan-card/issues/211
- **ТЗ:** `docs/specs/211-device-icons-visual-parity.md` (принято `SPEC-REVIEW-211-r2`, зелёный)
- **Предыдущий цикл:** `docs/reviews/CODE-REVIEW-211-r1.md` — зелёный, реализация
(`4e82976`, `270cf63`) уже слита в `dev` до того, как полный Linux smoke
вскрыл устаревшую проверку; поэтому временный `S8-merged` был гонкой двух
событий, а не итоговым статусом (см. комментарии владельца в issue).
- **Диапазон этого цикла:** `origin/dev..HEAD` = один коммит
`4d1b62b` — `test: align locked marker smoke with design package` ·
`Issue: #211` · `User-Visible: no`
- **Цикл:** r2/4
## Скоуп проверки
Весь диапазон `git diff origin/dev...HEAD` — это 11 строк в одном файле,
`demo/smoke_cover_no_plate.mjs` (7 добавлено, 4 удалено). Ничего в `src/**`,
`custom_components/**`, конфиге, i18n или changelog не тронуто — класс B
(гейт/тест), трейлер `User-Visible: no` соответствует. Изменение правит один
устаревший compatibility-факт (`lockedLockIsNeutral` → `lockedLockKeepsPackageFace`)
внутри смока, который сам по себе не входит в диапазон реализации #211, но
проверяет побочный контракт («у замка есть рамка, замок не становится
нейтральным»), задетый переходом на дизайн-пакет #179/#211.
Продуктовый код в этом цикле не проверяется повторно — он уже был предметом
`CODE-REVIEW-211-r1` (зелёный) и в этом диапазоне не менялся.
## Как проверялось
### Гейты — прогнаны
```
npx tsc --noEmit → чисто
npm test → 939 pass, 0 fail, 0 skipped
npm run build → OK
cmp dist/houseplan-card.js custom_components/.../houseplan-card.js → идентичны
cmp dist/houseplan-card.js demo/srv/assets/houseplan-card.js → идентичны
node demo/smoke_cover_no_plate.mjs → все факты true, OK
node demo/smoke_device_icon_design.mjs → все факты true, OK (доп. проверка
основного AC3-смока лежащей рядом поверхности; продукт не менялся с r1, но
это самый дешёвый способ убедиться, что коррекция теста не разошлась с
уже принятым CSS)
```
### Проверка «тест умеет падать» (обязательная дисциплина, применена к
единственному изменённому предикату)
Правило `.dev.lock-locked` в `src/styles.ts` вернул временно к состоянию до
основного фикса `4e82976` (`background: var(--device-core-bg); color: #000`,
без `theme-light`/`theme-dark` расщепления — то есть ровно то поведение,
которое проверял старый `lockedLockIsNeutral`), пересобрал `dist` и
синхронизировал `demo/srv/assets/houseplan-card.js` (демо-сервер отдаёт
именно эту копию, не `dist/` напрямую — без этого шага мутация не была бы
видна смоку). Результат:
```
"lockedLockKeepsPackageFace": false
FAILED (1): lockedLockKeepsPackageFace: expected true, got false
```
Все остальные факты смока остались зелёными — падение точечное, как и
должно быть для правки одного предиката. После проверки `src/styles.ts`
восстановлен из копии, `npm run build` прогнан повторно, `dist` синхронизирован
обратно в `demo/srv/assets` и в `custom_components/houseplan/frontend`;
`git status` — чистое дерево, диффа не осталось.
Дополнительно проверено чтением: новые ожидаемые значения
(`rgb(0, 0, 0)`/`rgb(255, 255, 255)` для Light, `rgb(37, 37, 37)`/
`rgb(255, 255, 255)` для Dark) — это буквальный computed-style результат
правил `.dev.lock-locked`, `.dev.theme-light.lock-locked`,
`.dev.theme-dark.lock-locked` (`src/styles.ts:2035-2048`), которые сами уже
были зафиксированы и приняты в `CODE-REVIEW-211-r1` как соответствующие §7.3
ТЗ (`Lock Light: core black / glyph white`, `Lock Dark: core #252525 / glyph
white`). `--device-face-bg`/`--device-face-fg` транслируются в
`background`/`color` `.device-core` напрямую (`src/styles.ts:1988-1989`), так
что тест меряет ровно то, что видит пользователь, а не побочный токен.
### Оценка ветвления по теме в самом тесте
Смок не переключает `hass.themes.darkMode`, а демо-фикстура (`demo/srv/demo.html`)
не задаёт его вовсе, поэтому `device-face.ts:24` (`hass.themes.darkMode ?
'theme-dark' : 'theme-light'`) в этом прогоне детерминированно даёт
`theme-light` — веткой `rgb(37, 37, 37)` тест здесь фактически не исполняется.
Это не дефект: тёмная ветка того же контракта (`darkLockUsesWhiteGlyphAndDarkShell`)
уже отдельно и явно проверяется вычисляемым фактом в
`demo/smoke_device_icon_design.mjs` и была подтверждена в r1 независимым
before/after прогоном. Тернарное выражение здесь написано корректно и
симметрично на случай, если смок когда-нибудь начнёт переключать тему, но не
создаёт для этого дублирующего покрытия — фиксирую как наблюдение, не как
находку.
### Коммит и трейлеры
`4d1b62b`: `Issue: #211`, `User-Visible: no` — верно, диапазон не содержит
изменений продукта, изменений в changelog не требуется.
## Что проверено и корректно
- Правка ограничена одним файлом гейта (`demo/smoke_cover_no_plate.mjs`),
относится к предмету #211 (AC3, Lock state parity) и устраняет расхождение
между устаревшим pre-#179 предположением теста («заблокированный замок —
нейтральный, глиф всегда чёрный») и принятым дизайн-пакетом («core черный/
`#252525`, глиф всегда белый»).
- Новый предикат `lockedLockKeepsPackageFace` измеряет именно тот CSS,
который производит видимый пиксель (`background`/`color` на `.device-core`
через `--device-face-bg`/`--device-face-fg`), не побочный токен.
- Предикат доказанно умеет падать: воспроизведена красная линия на
до-фиксовом правиле, падение точечное (1 из ~60 фактов файла), после
восстановления кода все факты снова зелёные.
- Остальные факты того же файла (cover plate/morph/valve/window/unlocked-lock)
не задеты диапазоном и остались зелёными — регрессии в соседних, не
относящихся к #211 проверках нет.
- `tsc`, unit-suite и build чистые; три копии бандла идентичны после
восстановления дерева.
- Коммит несёт корректный `Issue:`/`User-Visible:` трейлер для class B.
## Находки
Нет находок уровня High, Medium или Low. Единственное отмеченное выше
наблюдение (тернарная dark-ветка предиката не исполняется в этом конкретном
прогоне) не поднимаю как находку: поведение для Dark уже покрыто отдельным,
явно исполняемым фактом в другом смоке, а сам тернар написан правильно и не
вводит риск регрессии.
## Чего не проверял и почему
- **Полный набор из 127 browser smokes** — не запускал; диапазон правит один
предикат в одном уже существующем файле, не относящийся к нему smoke не
может быть задет текстовой правкой ассерта.
- **`npm run golden:verify`** — не запускал; диапазон не меняет ни один файл,
влияющий на рендер (только тестовый ассерт), видимый результат не может
измениться.
- **`python -m pytest tests_backend -q`** — не запускал; `custom_components/**/*.py`
не тронут.
- **Performance-профили** — не запускал; диапазон не касается DOM/CSS/JS
продукта.
- **Полный Linux CI-прогон** — не запускал локально; это гейт CI на выходе
из код-ревью, а не задача рецензента. (Именно такой прогон и обнаружил
устаревший факт, который правит этот коммит — второй такой же прогон на
этом SHA пройдёт штатно через пайплайн после зелёного вердикта.)
## Вердикт
Единственное изменение цикла — точечная и доказанная (падает на старом
поведении, зелёное на новом) коррекция стороннего compatibility-теста,
приводящая его в соответствие с уже принятым в r1 дизайн-контрактом #211/#179.
Продуктовый код не менялся, регрессий нет, трейлеры корректны.
**Зелёный.**