mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-02 04:38:55 +00:00
@@ -0,0 +1,175 @@
|
||||
# CODE-REVIEW-746-r1
|
||||
|
||||
Issue: #746 · трек: show · заход: r1 · блокирующих циклов израсходовано 0 из 2
|
||||
Материал: `aa0b60e75498d052625886d1cdc23190566f9bde` (ветка `issue/746-room-fill-alpha`,
|
||||
один коммит поверх `dev` `653d94ef`, ребейз-без-изменения-кода зафиксирован автором
|
||||
в комментарии issue от 2026-10-01T14:27:02Z)
|
||||
Validate на этом SHA: https://github.com/Matysh/houseplan-card/actions/runs/36876972490 — success
|
||||
|
||||
## Скоуп
|
||||
|
||||
Баг: `.room { transition: 0.12s }` анимирует цвет и `fill-opacity`/`stroke-opacity`
|
||||
независимо, видимая непрозрачность — их произведение. Состояния без заливки
|
||||
(`overlay`, `yard`, `outlined`, `picked`) держали альфу **в цвете** (`rgba(...)`,
|
||||
`*-opacity` по умолчанию `1`), а `.styled` — наоборот, непрозрачный цвет плюс
|
||||
`fill-opacity: var(--room-fill-op)`. При переходе между половинами одна растёт,
|
||||
другая падает, и продукт в середине пути больше обоих концов: комнаты вспыхивали
|
||||
серым при открытии «Настроек пространства» на этаже без заливки и темнели при
|
||||
входе/выходе из редактора плана на закрашенном этаже.
|
||||
|
||||
Правка приводит четыре состояния `.room` (`overlay`, `yard`, `outlined`, `picked`)
|
||||
к той же записи, что уже была у `.styled`: непрозрачный цвет + явная
|
||||
`fill-opacity`/`stroke-opacity`, `transparent` — только вместе с нулевой
|
||||
`*-opacity`. Сам переход, `.styled` и переменные `--room-*` не тронуты.
|
||||
Поверхность одна — блок правил `.room` в `src/styles/plan.styles.ts`;
|
||||
`houseplan-space-card` берёт те же стили реэкспортом (`src/styles.ts`), отдельной
|
||||
правки не требует — проверено чтением: `src/styles.ts:10,19` подключает
|
||||
`planStyles` без переопределения `.room.*`.
|
||||
|
||||
Диапазон `git diff origin/dev...HEAD`: `src/styles/plan.styles.ts` (+24/-4),
|
||||
новый `demo/smoke_room_fill_transitions.mjs`, `docs/CHANGELOG.md`,
|
||||
`docs/CHANGELOG.ru.md`, `docs/STYLING-HOOKS.md` — один коммит, трейлеры
|
||||
`Issue: #746` и `User-Visible: yes` на месте, оба changelog в том же коммите.
|
||||
|
||||
## Критерии §5 (трек show) — все пройдены
|
||||
|
||||
- **complexity** — issue оценивает сложность 2/10; правка — точечная замена
|
||||
записи прозрачности в 4 блоках CSS-правил, без новой логики.
|
||||
- **surfaces** — одна поверхность: правила `.room` в одном файле стилей,
|
||||
переиспользуемые всеми рендерами плана.
|
||||
- **migration** — нет миграции конфига; риск для пользовательских правил
|
||||
card-mod (правило, задающее только `fill` без `fill-opacity`, станет
|
||||
невидимым) явно описан в issue, в обоих CHANGELOG и в STYLING-HOOKS.md —
|
||||
не обойдён молчанием.
|
||||
- **ux-contract** — видимое поведение в покое не меняется (доказано пофреймово,
|
||||
см. ниже); исправляется переходный артефакт, а не контракт.
|
||||
- **perf-touch** — чистый CSS, без touch-поверхности; perf-смок в Validate
|
||||
зелёный (не требовался AC, но прогнался сам).
|
||||
- **undocumented** — ожидаемое поведение зафиксировано самим issue (таблица
|
||||
AC с точными числами) и теперь — в `docs/STYLING-HOOKS.md` §3.2 (новый
|
||||
абзац, ссылка на §3.3 «Everything generated» корректна).
|
||||
|
||||
Маршрут: `fix` (вердикт зелёный, `reclassify` неприменим).
|
||||
|
||||
## Как проверялось
|
||||
|
||||
| Гейт | Статус | Как |
|
||||
|---|---|---|
|
||||
| `tsc --noEmit`, `npm test`, `npm run build` + сверка бандла | не перегонял | зелёный Validate на точном SHA `aa0b60e7` (run 36876972490), "Фронтенд: типы, юниты, мутанты, синхрон бандла" — success |
|
||||
| `golden:verify` | не перегонял сам, приняты результаты CI | тот же Validate, job "Golden-кадры против принятых эталонов" — success (`ci:golden` выставлена и отработала) |
|
||||
| Смоки (полная матрица, 3 шарда) | не перегонял всю матрицу | тот же Validate, все три шарда "Смоки в браузере" — success; лог шарда 1 содержит `ok smoke_room_fill_transitions` — сам смок задачи выполнялся в CI и прошёл |
|
||||
| `demo/smoke_room_fill_transitions.mjs` | **прогнал сам, дважды** | см. ниже — независимая проверка автотеста на red/green |
|
||||
| `scripts/smoke-select.mjs --base origin/dev --head HEAD` | прогнал |「НЕОПРЕДЕЛЁННОСТЬ» — диффа в `src/styles/plan.styles.ts` символьная связь с смоками не выводится автоматически (CSS-правила, не функции); решение по AC1 issue и ручной проверке ниже |
|
||||
| pytest / Hassfest / HACS / мутанты по диффу / геометрия TS-Python | не прогонял | нет правок Python/конфига/геометрии — неприменимо, в Validate эти джобы `skipped` |
|
||||
| Мутанты (реестр) | не прогонял и не обязан | трек show, §10.4: мутанты на разработке не гоняются ни на одном треке |
|
||||
|
||||
**Чего не проверял:** полную матрицу golden и смоков заново (доверяю
|
||||
зелёному Validate на точном материале — свежесть подтверждена #343); ручное
|
||||
тестирование в браузере сверх смока (нет штатного гейта, Chromium не
|
||||
запускал для этого — только для перепрогона смока, который сам headless);
|
||||
поведение `.radarsetup .room` — явно вне скоупа в issue («Не-скоуп»).
|
||||
|
||||
### Независимая проверка AC1/AC2 (смок умеет падать)
|
||||
|
||||
Защитный AC — здесь это обязательная таблица «чем доказан · чем краснеет»:
|
||||
|
||||
| AC | Чем доказан | Чем краснеет |
|
||||
|---|---|---|
|
||||
| AC1: видимая непрозрачность заливки/обводки ни в одной точке перехода не превышает больший из концов более чем на 0.005 | `demo/smoke_room_fill_transitions.mjs`, прогнан мной на `aa0b60e7`: **OK**, все проверки (`fillOvershoot`/`strokeOvershoot` ≤ tolerance) зелёные для 4 путей + контроль | Я откатил патч `src/styles/plan.styles.ts` до состояния `origin/dev` (`git apply -R`), пересобрал бандл и перепрогнал тот же смок: **FAILED (6)**, с точными числами из issue — `openSettings` fill/stroke 0 → **0.2413** → 0, `cancelSettings` fill 0.18 → **0.3049** → 0 и stroke 0 → **0.2418** → 0, `enterPlanEditor` fill 0.18 → **0.3172** → 0.06, `leavePlanEditor` fill 0.06 → **0.314** → 0.18. Совпадает с цифрами issue (0.241/0.305/0.317/0.314) и отчётом автора. Тест действительно умеет падать именно на дефекте из issue, не на постороннем |
|
||||
| AC2: кадр в покое не меняется (`overlay`, `styled`, `outlined`, `picked`, `yard`) | Тот же смок, секция `rest`: цвет и видимая непрозрачность по пяти состояниям совпадают с таблицей `REST`, зашитой в смок как ожидание дев-поведения; плюс Golden CI на точном SHA — success | На отклонение кадра покоя красит сам смок (`check` по каждому состоянию и каналу) — отдельно не провоцировал, т.к. правка кода не трогает значения `styled`/рест-часть `overlay` и т.д.; разбор по коду подтверждает: изменились только порядок/форма записи (hex→rgb + отдельная opacity), числовое произведение то же (проверено чтением, не исполнением, для каждой из 4 строк диффа — см. ниже) |
|
||||
|
||||
После обеих проверок рабочая копия и `dist/` возвращены ровно к материалу
|
||||
ревью (`git checkout -- dist/`, `git clean -fd dist/`, `git status` чист,
|
||||
`git rev-parse HEAD` = `aa0b60e75498d052625886d1cdc23190566f9bde`).
|
||||
|
||||
### Разбор по коду (проверено чтением, не исполнением)
|
||||
|
||||
Для каждого изменённого блока: произведение «альфа цвета × *-opacity» в покое
|
||||
не меняется, а при переходе оба сомножителя теперь монотонны от 0 (или от
|
||||
другого конца) к цели, поэтому продукт двух неубывающих/невозрастающих
|
||||
кривых ограничен большим из концов — перелёта быть не может:
|
||||
|
||||
- `.room.overlay`: было `fill: transparent` (альфа 0, `fill-opacity` по
|
||||
умолчанию 1) → стало `fill: transparent; fill-opacity: 0` — продукт 0 в
|
||||
обоих случаях, при переходе к `.styled` оба множителя (альфа цвета и
|
||||
opacity) растут от 0 монотонно → продукт ограничен произведением конечных
|
||||
значений, перелёта нет. Симметрично для `stroke`.
|
||||
- `.room.yard`: было `fill: rgba(75, 140, 90, 0.14)` (продукт 0.14) → стало
|
||||
`fill: rgb(75, 140, 90); fill-opacity: 0.14` (продукт 0.14) — рест не
|
||||
меняется, подтверждено прогоном (`rest.yard.fill = ["rgb(75, 140, 90)",
|
||||
0.14]`).
|
||||
- `.room.outlined`: `rgba(62,166,255,0.06)`/`0.55` → `rgb(...); fill-opacity:
|
||||
0.06` / `stroke-opacity: 0.55` — рест не меняется (подтверждено прогоном).
|
||||
- `.room.picked`: `rgba(255,193,77,0.25)` → `rgb(...); fill-opacity: 0.25`;
|
||||
`stroke: #ffc14d` (уже непрозрачный) получил явный `stroke-opacity: 1` —
|
||||
без визуального эффекта в покое, что и наблюдается (`rest.picked.stroke =
|
||||
["rgb(255, 193, 77)", 1]`).
|
||||
|
||||
Побочный эффект, который автор сам назвал в отчёте и я подтвердил чтением:
|
||||
у `.room.overlay:hover`/`.room.yard:hover` (наведение на незакрашенную
|
||||
комнату) теперь обе половины (`stroke` и `stroke-opacity`) идут от 0 к 1
|
||||
вместо одной — начало затухания визуально чуть мягче, монотонность
|
||||
сохраняется, перелёта нет. Не находка: раскрыто в отчёте автора, не меняет
|
||||
контракт, не заявлено как AC.
|
||||
|
||||
### Проверка «одно число — один источник»
|
||||
|
||||
Числа 0.14 / 0.06 / 0.55 / 0.25 (видимые альфы `yard`/`outlined`/`picked`)
|
||||
встречаются только в `src/styles/plan.styles.ts` — их единственный источник.
|
||||
Поиском (`grep` по RGB-триплетам `75,140,90` / `62,166,255` / `255,193,77`
|
||||
вне `plan.styles.ts`) второго места с тем же числом не нашлось; совпадение в
|
||||
`src/styles/devices.styles.ts:379` (`rgba(62, 166, 255, 0.22)`) — другой
|
||||
компонент (устройство), другое число (0.22), не дублирует величину задачи.
|
||||
`demo/smoke_merge_highlight.mjs` сверяет только подстроку цвета
|
||||
(`includes('255, 193, 77')`), а не альфу — совместимость с переходом на
|
||||
`rgb(...)` + отдельный `fill-opacity` подтверждена прогоном CI (шард 1:
|
||||
смок зелёный).
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- Диапазон диффа `origin/dev...HEAD` — ровно заявленное в ТЗ: `.room.overlay`,
|
||||
`.yard`, `.outlined`, `.picked`; `.styled` и переменные `--room-*` не
|
||||
тронуты (построчная сверка).
|
||||
- `houseplan-space-card` подтверждённо берёт те же стили без дублирования
|
||||
правил.
|
||||
- Трейлеры `Issue: #746`, `User-Visible: yes` на коммите; оба CHANGELOG
|
||||
правлены в том же коммите, текст совпадает с AC3 issue дословно (RU и EN).
|
||||
- `docs/STYLING-HOOKS.md` получил абзац, фиксирующий новый инвариант как
|
||||
контракт — ссылка на §3.3 «Everything generated» для самих величин
|
||||
корректна (значения остаются негарантированными, инвариант записи —
|
||||
гарантирован).
|
||||
- Смок умеет падать именно на дефекте issue (см. раздел выше) — не ложно
|
||||
положительный.
|
||||
- CI на точном SHA материала: Validate, Golden, вся матрица смоков (включая
|
||||
новый) — зелёные.
|
||||
- Метки issue соответствуют треку и объёму: `track:show`, `ci:golden`,
|
||||
`S7-code-review`.
|
||||
- Риски (невидимость для правил card-mod без явной `*-opacity`, более мягкое
|
||||
начало hover-замирания) названы автором и подтверждены разбором, задокументированы
|
||||
в CHANGELOG/STYLING-HOOKS — не висящие Medium.
|
||||
|
||||
## Находки
|
||||
|
||||
Нет. High: 0, Medium: 0 (ни в скоупе, ни вне скоупа).
|
||||
|
||||
## Вердикт
|
||||
|
||||
Зелёный. AC1 и AC2 доказаны автотестом, тест проверен на способность
|
||||
падать лично (red на отменённом патче с теми же числами, что в issue),
|
||||
AC3 (гейт/CHANGELOG) выполнен. Побочных дефектов не найдено, риски раскрыты
|
||||
и задокументированы.
|
||||
|
||||
---
|
||||
|
||||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `issue/746-room-fill-alpha`, коммит `aa0b60e75498` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||
- Дерево материала: `0d71ae29c68313fe4be018c5026ec20ccb600cc8`
|
||||
```
|
||||
git log --all --format='%H %T' | grep 0d71ae29c683
|
||||
```
|
||||
- Тело issue: `e2d6161bb012959bb539ad49b1ed92bdc86fdc4cb703235caab7bca18258dc38`
|
||||
- Вердикт конвейера: `green` · High 0 · маршрут `fix`
|
||||
<!-- hp:usage input_tokens=4495 output_tokens=23527 cache_creation_input_tokens=86008 cache_read_input_tokens=3392622 num_turns=56 -->
|
||||
Reference in New Issue
Block a user