mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
@@ -0,0 +1,193 @@
|
||||
# CODE-REVIEW-508-r2
|
||||
|
||||
Issue: #508 — «Сводная панель: в диалоге настроек не работает прокрутка — колесом мыши и touch на мобильных»
|
||||
Материал: `6ac513caa09a8e583869879412aa3a0c67d04488` (рабочая копия уже на нём). Ветка приведена конвейером к
|
||||
`dev` до ревью: `e23d742c → 6ac513ca`, поверх легло 1 коммит `dev` (несвязанный — `docs: review document
|
||||
for #502`).
|
||||
Заход: r2 · блокирующих циклов израсходовано 0 из 4. Ребейз на ушедший вперёд `dev` формально делает
|
||||
дерево другим (§7.2) → разбор полный, а не по дельте.
|
||||
|
||||
## Почему вообще r2, если r1 был зелёным без находок
|
||||
|
||||
Код-ревью r1 (`docs/reviews/CODE-REVIEW-508-r1.md`, материал `768e1281`) уже завершилось вердиктом
|
||||
«зелёный, находок нет» с исчерпывающим личным прогоном гейтов, мутантов, смоков и подтверждением автора
|
||||
на живом стенде HA. Сразу после публикации вердикта автор сообщил в issue: «Автоматическое ревью не
|
||||
отработало» — статусная метка не переставилась, конвейер оставил задачу на месте. Затем конвейер
|
||||
перебазировал ветку на успевший уйти вперёд `dev` (там landing получил несвязанный коммит с ревью-доком
|
||||
для issue #502) и передал её на повторное ревью уже под новым SHA. Автор с момента r1 в код и ТЗ не
|
||||
вносил ничего — это не возврат на правки, а техническое повторение ревью из-за сбоя механики метки плюс
|
||||
ребейз. Поэтому раздела «находка → возврат → правка» в этом раунде по существу нет: проверка ниже —
|
||||
подтверждение, что ребейз не изменил и не сломал ничего, а не разбор чьих-то правок.
|
||||
|
||||
## Скоуп
|
||||
|
||||
Не изменился с r1: один функциональный коммит (`e38beed7`, экс-`768e1281`) — класс A (`src/hp-dialog.ts`,
|
||||
`src/summary-panel-editor.ts`) + класс B (новый смок `demo/smoke_summary_dialog_scroll.mjs`, контрактный
|
||||
юнит-тест `test/hp-dialog-contract.test.mjs`, два мутанта в `scripts/mutation-gate.mjs`) + класс C
|
||||
(`docs/ARCHITECTURE.md`, оба CHANGELOG) + класс D (пересобранный бандл во всех копиях,
|
||||
`docs/images/screenshots.json` — только фингерпринт). `hp-dialog` получает opt-in булев атрибут
|
||||
`flex-content` (`?flexcontent` на `ha-dialog`, обе HA-ветки рендера); нативная `<dialog>`-ветка не тронута.
|
||||
Диалог настроек сводной панели его объявляет — единственный из десяти вызывающих `<hp-dialog>`.
|
||||
|
||||
J1 (`docs/SCOPE.md`) — обзорная сводная панель входит в «show the whole home at a glance»; чистый
|
||||
баг-фикс регресса после #505, скоуп не расширен, продукт не меняет договор.
|
||||
|
||||
## Как проверялось (это не дельта — это независимая перепроверка «ничего не изменилось»)
|
||||
|
||||
Первый шаг — не поверить заявлению «ребейз ничего не тронул», а доказать его:
|
||||
|
||||
```
|
||||
git diff 768e1281 e38beed7 --stat # r1-материал vs текущий фикс-коммит
|
||||
```
|
||||
|
||||
Результат: единственная разница — файл `docs/reviews/SPEC-REVIEW-502-r1.md` (несвязанный коммит `dev` для
|
||||
issue #502). Все файлы продукта — `src/hp-dialog.ts`, `src/summary-panel-editor.ts`,
|
||||
`test/hp-dialog-contract.test.mjs`, `docs/ARCHITECTURE.md`, оба CHANGELOG, `scripts/mutation-gate.mjs`,
|
||||
`demo/smoke_summary_dialog_scroll.mjs`, весь пересобранный бандл — побайтово идентичны материалу r1.
|
||||
`docs/images/screenshots.json` проверен построчно (`grep imageSha256` на диффе): изменились только
|
||||
`sourceFingerprint`/`sourceSha256`-контекст, ни один `imageSha256` не сдвинулся.
|
||||
|
||||
Это и определило объём: код доказанно тот же, что уже получил зелёный вердикт с личными прогонами гейтов,
|
||||
мутантов и смоков (не только заявлением автора — заявление в r1 тоже было перепроверено исполнением). Все
|
||||
выводы AC1–AC6 из r1 остаются в силе автоматически, потому что применяются к тому же байт-в-байт коду. Тем
|
||||
не менее раунд объявлен «полным» (ребейз, §7.2), поэтому ниже — не просто ссылка на r1, а собственный
|
||||
прогон части гейтов на текущем SHA `6ac513ca`, чтобы исключить эффекты самого ребейза (окружение сборки,
|
||||
конфликт слияния бандла и т. п.), а не только идентичность текста диффа.
|
||||
|
||||
### Дешёвые гейты
|
||||
|
||||
Validate на `6ac513ca` зелёный (дано в задаче ревью, https://github.com/Matysh/houseplan-card/actions/runs/34397342070)
|
||||
— `tsc`, `npm test` (2436/2436), `npm run build` со сверкой бандла уже подтверждены конвейером на этом
|
||||
самом SHA, повторно не гонял.
|
||||
|
||||
### Прогнано лично на `6ac513ca` (не на материале r1 — на текущем SHA)
|
||||
|
||||
| Гейт/смок | Результат |
|
||||
|---|---|
|
||||
| `node --test test/hp-dialog-contract.test.mjs` (AC1 текстовая часть, AC4) | 3/3 pass |
|
||||
| `node scripts/check-docs.mjs` (диф трогает `src/**`) | «Documentation checks passed (7 files, 12 external links)» — совпадает с числом из r1 |
|
||||
| `node scripts/bundle-sync.mjs` (пересборка + раскладка по трём местам: `dist`, `custom_components/houseplan/frontend`, `demo/srv/assets`) | выполнено; `git status --porcelain` после — пусто (отслеживаемые копии не разошлись с коммитом) |
|
||||
| `node demo/smoke_summary_dialog_scroll.mjs` (AC1/AC2, прямое совпадение) | `OK` |
|
||||
| `node demo/smoke_summary_panel_polish.mjs` (AC3, прямое совпадение — файл смока не менялся) | `OK` |
|
||||
| `node demo/smoke_dialog_modal_recovery.mjs` (зарегистрированная связь: общий `hp-dialog`) | `OK` |
|
||||
| `node demo/smoke_esc_dialogs.mjs` (зарегистрированная связь) | `OK` |
|
||||
| `node demo/smoke_dialog_footer_width.mjs` (зарегистрированная связь) | `OK` |
|
||||
| `node scripts/mutation-gate.mjs --id=summary-dialog-drops-flex-content` | чистый прогон OK → мутация: «тест покраснел, как обязан» → поймано 1 из 1 |
|
||||
| `node scripts/mutation-gate.mjs --id=hp-dialog-ignores-flex-content` | то же → поймано 1 из 1 |
|
||||
| `node scripts/smoke-select.mjs --base origin/dev --head HEAD` | «НЕОПРЕДЕЛЁННОСТЬ» — 2 файла `src/**`, 0 символов на изменённых строках (тот же результат, что в r1); выбор смоков выше сделан вручную: прямое совпадение (диалог панели) + зарегистрированные связи (общий `hp-dialog`) |
|
||||
| `grep -rn "<hp-dialog" src/` | 10 вызывающих (включая `summary-panel-editor.ts`); ровно список из `test/hp-dialog-contract.test.mjs` AC4, opt-in — один |
|
||||
|
||||
Изначально попытка запустить браузерные смоки провалилась ошибкой окружения
|
||||
(`Failed to fetch dynamically imported module: http://demo.local/...`, `page.waitForFunction` timeout) —
|
||||
это была не регрессия, а отсутствие локальной копии `demo/srv/assets` (она не хранится в репозитории,
|
||||
`scripts/bundle-sync.mjs`: «копий две с половиной», рабочая копия стенда собирается заново). Тот же
|
||||
таймаут воспроизводился на `demo/smoke_summary_panel_polish.mjs`, файл которого этот диф не трогает вовсе
|
||||
— это подтвердило, что причина в окружении ревью-песочницы, а не в коде. После `node
|
||||
scripts/bundle-sync.mjs` (пересборка из уже собранного `dist/`) оба смока пошли зелёными.
|
||||
|
||||
## Закрытие раунда r1
|
||||
|
||||
Код-ревью r1 не имело находок (High 0, Medium 0, Low 0) — блокирующих находок для закрытия нет. Раунд r2
|
||||
открылся не как возврат на правки, а как техническое повторение из-за несработавшей автоматической
|
||||
перестановки метки после зелёного вердикта r1, дополненное последующим ребейзом на ушедший вперёд `dev`
|
||||
(конвейер, не автор). Автор кода/ТЗ с момента r1 не менял — независимо доказано выше диффом
|
||||
`768e1281..e38beed7`.
|
||||
|
||||
| Находка r1 | Статус | Где видно |
|
||||
|---|---|---|
|
||||
| (нет находок) | — | `docs/reviews/CODE-REVIEW-508-r1.md`, раздел «Находки»: «Нет. High: 0, Medium: 0, Low: 0» |
|
||||
|
||||
## Унаследовано из r1
|
||||
|
||||
Без повторного самостоятельного вывода, но с проверкой байт-в-байт идентичности кода (см. «Как
|
||||
проверялось»), наследую из `docs/reviews/CODE-REVIEW-508-r1.md` (материал `768e1281f9119b12d018b416372984ff17eae62d`,
|
||||
дерево `1594677359b610e22fc5886db02f66bc3c943322`):
|
||||
|
||||
- диагноз (scroll chaining обрывается на height-unbound `.summary-editor` под `ha-dialog`, `overflow:
|
||||
auto` + `overscroll-behavior: contain`) — независимо подтверждён автором на живом стенде HA 2026.9.1, не
|
||||
только в стабе смока;
|
||||
- личные прогоны `tsc`, `npm test` (2437/2436 pass+1 skip), `no-new-any`, `bundle:budget` на материале
|
||||
r1 — не переигрывал повторно, т. к. Validate CI зелёный на `6ac513ca` покрывает те же проверки на
|
||||
байт-в-байт идентичном коде;
|
||||
- вывод AC6 (i18n/модель/перф не задеты, трейлеры `Issue:`/`User-Visible: yes` и оба CHANGELOG в одном
|
||||
коммите) — перепроверен построчно, см. «AC → доказательство» ниже, поэтому это скорее «переподтверждено»,
|
||||
чем слепо унаследовано;
|
||||
- трассировку к спек-ревью (`SPEC-REVIEW-508-r1.md` жёлтый → `SPEC-REVIEW-508-r2.md` зелёный на SHA
|
||||
`f02af9330b17a37eea6c8086f4335cbbc7265d36`, M1/M2 закрыты правкой тела issue) — код-ревью r1 её не
|
||||
переоткрывало, r2 тоже не переоткрывает: текст issue с тех пор не менялся.
|
||||
|
||||
## AC → доказательство → чем краснеет (переподтверждено лично на `6ac513ca`)
|
||||
|
||||
| AC | Доказано | Чем краснеет |
|
||||
|---|---|---|
|
||||
| AC1 (HA-ветка: колесо крутит `.summary-editor`, шапка/футер неподвижны) | `demo/smoke_summary_dialog_scroll.mjs` сценарий (a) — `OK`, лично | оба мутанта, лично: «покраснел, как обязан» |
|
||||
| AC2 (touch 390×844 крутит редактор; диалог ≤ вьюпорта; футер доступен) | сценарий (b) — `OK`, лично | те же два мутанта |
|
||||
| AC3 (нативная ветка не меняется) | `smoke_summary_panel_polish` — `OK`, лично; файл смока не в диффе | не защитный AC |
|
||||
| AC4 (прочие 9 `hp-dialog` без `flex-content`) | `test/hp-dialog-contract.test.mjs` — 3/3 pass, лично; `grep` по `src/**` — 10 вызывающих, 1 opt-in | ассерт `=== 1` в тесте (in-memory проба r1 сохраняет силу — код теста не менялся) |
|
||||
| AC5 (оба мутанта пойманы) | оба мутанта лично прогнаны — «поймано 1 из 1» каждый | это и есть доказательство |
|
||||
| AC6 (`User-Visible: yes`, оба changelog, i18n/модель/перф не задеты) | `git show --stat e38beed7`: `docs/CHANGELOG.md`+`docs/CHANGELOG.ru.md` в том же коммите; `git log -1` коммита содержит `Issue: #508` и `User-Visible: yes`; ни один `i18n`/`translations` файл не в диффе; `src/hp-dialog.ts` diff — только проброс булева атрибута, новых обработчиков нет | не защитный AC, доказано чтением |
|
||||
|
||||
## Одно число — один источник
|
||||
|
||||
Диф не вводит и не дублирует ни одну видимую пользователю величину (площадь, значение, подпись): меняется
|
||||
только внутренняя раскладка скролл-контейнера через булев атрибут. `test/single-source-numbers.test.mjs`
|
||||
не затрагивается и не требуется для этой правки.
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- Обе HA-ветки рендера (`describedBy` и без) несут `?flexcontent=${this.flexContent}` — строки
|
||||
`src/hp-dialog.ts:515,531`, подтверждено и тестом, и мутантами лично.
|
||||
- Нативная `<dialog>`-ветка не содержит `flexcontent`/связанных селекторов — регресс на неё исключён и
|
||||
тестом (`smoke_summary_panel_polish`), и построчным чтением.
|
||||
- `docs/TOUCH-SUPPORT.md:48–49` называет «simple settings form» сводной панели гарантированной View-touch-
|
||||
поверхностью — включение touch в скоуп не расширение, а обязательное соответствие контракту.
|
||||
- Терминология CHANGELOG.ru.md («сводной панели», «настроек») совпадает с `docs/USER-GUIDE.ru.md:264`
|
||||
(«Настройки сводной панели»).
|
||||
- `docs/images/screenshots.json`: только `sourceFingerprint`/`sourceSha256`; все 11 `imageSha256`
|
||||
идентичны — докс-скриншоты не изменились по существу.
|
||||
- Один коммит (`e38beed7`), трейлеры `Issue: #508` и `User-Visible: yes` на месте.
|
||||
- После `bundle-sync` рабочая копия чиста (`git status --porcelain` пуст) — три копии бандла (`dist`,
|
||||
`custom_components/houseplan/frontend`, `demo/srv/assets`) согласованы с закоммиченным.
|
||||
- Ребейз сам по себе не внёс никакого продуктового изменения — доказано диффом, а не заявлено.
|
||||
|
||||
## Находки
|
||||
|
||||
Нет. High: 0, Medium: 0, Low: 0.
|
||||
|
||||
## Чего не проверял и почему
|
||||
|
||||
- `npm run golden:verify` — атрибут opt-in, `?flexcontent=` в Lit убирает атрибут целиком при `false`,
|
||||
разметка прочих `hp-dialog` не меняется ни на байт; golden-сцен диалога сводной панели в репозитории нет
|
||||
(снято ещё в `SPEC-REVIEW-508-r1.md` M1). Риск нулевой, решение то же, что в r1, переподтверждено тем же
|
||||
рассуждением на идентичном коде.
|
||||
- `python -m pytest tests_backend` — диф не касается `custom_components/houseplan/**/*.py`.
|
||||
- Полная матрица смоков (237 шт.) и перф-профили — не названы в AC; `smoke-select` вернул
|
||||
«НЕОПРЕДЕЛЁННОСТЬ» (2 файла `src/**`, 0 символов на изменённых строках, порог «широкого» — 47 смоков).
|
||||
Выбор сужен вручную до прямого совпадения (`smoke_summary_dialog_scroll`, `smoke_summary_panel_polish`) и
|
||||
зарегистрированных связей на общий `hp-dialog` (`smoke_dialog_modal_recovery`, `smoke_esc_dialogs`,
|
||||
`smoke_dialog_footer_width`) — все пять прогнаны лично, все зелёные.
|
||||
- `npm run invariants` — диф не трогает геометрию/рёбра комнат/`layout`/`marker.space`/`open_spans`, гейт не
|
||||
применим.
|
||||
- Полный `npm test` (все 2436 юнитов) — не переигрывал повторно вживую: Validate CI уже подтвердил его
|
||||
зелёным на этом самом SHA `6ac513ca` (ссылка выше), а не на другом; вместо повторного полного прогона
|
||||
лично выполнен целевой `test/hp-dialog-contract.test.mjs`.
|
||||
|
||||
## Вердикт
|
||||
|
||||
Зелёный. Разбор — полный (ребейз, §7.2), но не «с нуля»: доказано диффом, что код байт-в-байт идентичен
|
||||
уже одобренному материалу r1, и это доказательство переподтверждено собственными прогонами гейтов, смоков
|
||||
и мутантов на текущем SHA `6ac513ca`, а не принятием чужого вердикта на веру. Находок нет. Раунд не
|
||||
образует цикл (§4) — вердикт зелёный.
|
||||
|
||||
---
|
||||
|
||||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `issue/508-summary-dialog-scroll`, коммит `e23d742cd508` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||
- Дерево материала: `5fc02b5d1de102ed9770f28fc5eb3a41098cbc11`
|
||||
```
|
||||
git log --all --format='%H %T' | grep 5fc02b5d1de1
|
||||
```
|
||||
- Вердикт конвейера: `green` · High 0
|
||||
Reference in New Issue
Block a user