From b49b124cc6b6cd60309bd5b1baed9aafa73dd5dd Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 16:15:53 +0000 Subject: [PATCH] docs: review document for #592 Issue: #592 User-Visible: no --- docs/reviews/SPEC-REVIEW-592-r2.md | 155 +++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 docs/reviews/SPEC-REVIEW-592-r2.md diff --git a/docs/reviews/SPEC-REVIEW-592-r2.md b/docs/reviews/SPEC-REVIEW-592-r2.md new file mode 100644 index 00000000..adeb1f9a --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-592-r2.md @@ -0,0 +1,155 @@ +# SPEC-REVIEW-592-r2 — «Вынести четыре диалога настроек из houseplan-editor-runtime.ts в модули (шаг 0 эпика #591)» + +Issue: [#592](https://github.com/Matysh/houseplan-card/issues/592) +Этап: spec +Заход: r2 (блокирующих циклов израсходовано 1 из 4 — израсходован жёлтым вердиктом r1; зелёный вердикт цикла не образует, §4) + +## Вердикт + +**Зелёный.** High: 0. Medium: 0. + +## Скоуп разбора — по дельте (§2.10) + +Предыдущий раунд (r1) — жёлтый, две находки: M1 (в скоупе) и L1 (снята с записью). +Документ: `docs/reviews/SPEC-REVIEW-592-r1.md`. Материал r1 объявлен его блоком +«Материал раунда»: ветка `dev`, коммит `01fe7350791e`, дерево материала +`0054c6622b79256b64b455ed786b46270fec9208`. SHA живой (это предок текущего +`HEAD` — `01fe7350` виден в истории репозитория), ре-резолвить по якорям не +потребовалось. + +Дельта этапа spec — не код, а тело issue #592 (ревизия r2 против r1). По правке +автора в комментарии видно, что изменения локальны: заголовочная строка «Редакция +r2: правки по ревью ТЗ r1», таблица «Мера храповика/Запас» (4→3), формулировка +«трёх строках» вместо «нескольких», список эталонов AC2 (добавлен +`device-ripple-color-popover-mobile-ru`), новый абзац «Почему именно этот список +эталонов (правка по M1)» с таблицей покрытия по диалогам, и список смоков AC1 +(добавлены `smoke_gear_tabs`, `smoke_esc_dialogs`, `smoke_dialog_footer_width`). +Остальные разделы ТЗ (Проблема кроме числа, Контракт К1–К5, Скоуп/не-скоуп, AC3–AC7, +Риски, Откат, Release-артефакты, «Принято предположительно») дельту не задевают — +это подтверждают обе реплики автора («обе находки закрыты», список правок +исчерпывающий) и сверка структуры документа r2 с r1: разделы совпадают дословно +за пределами перечисленных мест. + +Дельта локальна: новый субъект не появился (та же подсистема — редакторский граф +диалогов), контракт поведения (К1–К5) не менялся, объём правки (несколько строк +и одна таблица) несопоставим с объёмом исходной задачи. Условия «разбор остаётся +полным» (ребейз, смена контракта, новая подсистема, сопоставимый объём) не +выполнены — сокращённый разбор оправдан. + +Поскольку код ещё не менялся (шаг не начат, `User-Visible: no`, задача готовит +почву), дешёвые гейты (`typecheck`/`test`/`build`) в этом раунде не гоняю — они +относятся к материалу code-review, а не к телу issue на этапе spec; это не +пропуск, а неприменимость предмета. + +## Закрытие раунда r1 + +| Находка r1 | Чем закрыта | Где это видно | +|---|---|---| +| **M1** (Medium, в скоупе) — AC2 не называет эталон `device-ripple-color-popover-mobile-ru`, хотя он единственный доказывает ветку `display === 'icon_ripple'` в переносимом `_renderMarkerDialog` | Эталон добавлен в список AC2 (выделен жирным в теле issue) | Тело issue, строка AC2: «…**`device-ripple-color-popover-mobile-ru`**…»; проверено независимо: `demo/golden/matrix.mjs:1084` регистрирует сценарий, `demo/golden/harness.mjs:1994-2013` (ветка `dialog === 'device-ripple-color'`) открывает `_openMarkerDialog`, ставит `display: 'icon_ripple'` и раскрывает `hp-color-opacity` с ярлыком `marker.activity_color`; baseline `demo/golden/baselines/device-ripple-color-popover-mobile-ru.png` существует | +| **L1** (Low, снята с записью) — шапка называла запас ядер «4», фактически 3 (`split('\n').length`, не `wc -l`) | Число исправлено на «3» в таблице «Мера храповика/Запас» и в тексте «Проблема» | Тело issue: таблица показывает `Запас: 3 / 3`; текст «Оба ядра стоят в трёх строках от жёсткого потолка»; проверено пересчётом: `src/houseplan-editor-runtime.ts` — 14096 строк по `wc -l`/`awk 'END{print NR}'`, `split('\n').length` даёт 14097 против потолка 14100 в `test/core-file-budget.test.mjs:36` → запас 3; `src/houseplan-card.ts` — 13728 строк, `split.length` = 13729 против потолка 13732 (`:32`) → запас 3 | + +Обе находки закрыты фактом текста/кода, а не заявлением автора — проверено +независимо, не только пересказано. + +## Что проверено в этом раунде (дельта) + +1. **Новый абзац «Почему именно этот список эталонов»** — таблица покрытия по + диалогам (Устройство 7 / Комната 2 / Общие настройки 3 / Пространство 1) + пересчитана и совпадает с фактическим списком AC2: 3 `device-dialog-*` + 1 + `device-help-popover-*` + 1 `device-ripple-color-*` + 2 `toggle-entity-dialog-*` + = 7 для устройства; 2 `room-temperature-dialog-*` для комнаты; `general-color-*` + + 2 `settings-help-zoom-200-*` = 3 для общих настроек; 1 + `space-room-color-popover-desktop-ru` для пространства. Итого 13 эталонов в + AC2 (12 из r1 + добавленный ripple) — сходится с телом issue. +2. **Три новых смока в AC1**, заявленные как компенсация единственного golden-кадра + пространства. Проверено чтением каждого файла: + - `demo/smoke_gear_tabs.mjs` — открывает `_spaceDialog` (строки 23-49), + проверяет режим `create` (`_spaceDialog.mode === 'create'`) — реально + задействует диалог пространства; + - `demo/smoke_esc_dialogs.mjs:67-68` — вызывает + `c._openSpaceDialog('edit', c._space)` и проверяет закрытие по Esc; + - `demo/smoke_dialog_footer_width.mjs` — вызывает `_openSpaceDialog('edit', …)` + дважды (desktop и narrow), измеряет `buttons`, `oneRow`, + `noHorizontalOverflow`, `insideViewport` (строки 87, 139, 201-217) — реально + проверяет структуру диалога пространства (число кнопок, отсутствие + переполнения), а не просто факт открытия. + + Все три файла существуют, все три действительно открывают/используют + `_spaceDialog`/`_openSpaceDialog`, заявление автора подтверждено чтением + кода, а не принято на слово. Важная оговорка (не находка, а точность + формулировки): эти три смока — функциональные/структурные проверки + (число кнопок, переполнение, режим), не побайтовые сравнения кадра. Автор + сам явно не относит их к AC2 (побайтовое совпадение), а держит в AC1 — + формулировка в issue корректна и не выдаёт смок за замену golden-сравнения. + +## Унаследовано из r1 + +Без повторной проверки в этом раунде, со ссылкой на `docs/reviews/SPEC-REVIEW-592-r1.md` +(материал: ветка `dev`, коммит `01fe7350791e`, дерево `0054c6622b79256b64b455ed786b46270fec9208`): + +- Границы всех четырёх методов (`_renderMarkerDialog` 12884–13610, + `_renderSpaceDialog` 13611–13907, `_renderSettingsDialog` 10337–10502, + `_renderRoomDialog` 13984–14097) — дельта их не меняет, номера строк в теле + issue r2 идентичны r1. +- Прецедент `radar-section.ts`/`vacuum-maps-section.ts` (форма экспорта, отсутствие + `@state()`, кто импортирует) — К2 в r2 не менялся. +- Число мутационных патчей (33) с `file: 'src/houseplan-editor-runtime.ts'` и + направление `relocateEditorPatch` — К5 в r2 не менялся. +- Реальность доказательств AC5 (`bundle:budget`, `bundle-assets.test.mjs` разбирают + фактический вывод сборки) и AC6 (`mutation-gate.test.mjs` — уникальность якоря) — + тексты AC3–AC7 в r2 не менялись. +- Полнота обязательных разделов §7.1, отсутствие незаявленных допущений + (раздел «Принято предположительно» ограничен техническими решениями) — + структура документа вне перечисленных мест дельты идентична r1. +- Продуктовая рамка: задача — шаг 0 эпика #591, видимых изменений нет (К1), + сценарий и «что человек увидит» корректно формулируют нулевой видимый эффект + как факт, а не как отсутствие анализа. +- Trailers: `User-Visible: no` корректно, changelog не требуется — задача не + меняет ничего наблюдаемого пользователем. + +## Чего не проверял + +- Не повторял построчный аудит всех ≈1300 строк четырёх методов на предмет других + скрытых веток по образцу ripple, кроме уже закрытой M1 — дельта r2 не расширяла + зону риска (не добавляла новых диалоговых веток), только меняла список + эталонов/смоков; повторный полный аудит не относится к предмету раунда. +- Не проходил построчно содержимое `smoke_general_settings.mjs`/ + `smoke_room_settings.mjs`/`smoke_color_picker_consumers.mjs`/ + `smoke_static_icon.mjs`/`smoke_device_inbox.mjs`/`smoke_room_temperature_thresholds.mjs`/ + `smoke_device_preview_parity.mjs` — эти семь смоков дельту не задели, их + разбор унаследован из r1 неявно (r1 их не проверял построчно и сам отметил + это в «Чего не проверял»; предмет этого раунда — не они). +- Не гонял `npx tsc --noEmit`, `npm test`, `npm run build`, `golden:verify`, + `bundle:budget` — этап spec, продуктовый код ещё не менялся под эту задачу; + единственная числовая проверка (`split('\n').length` против потолков + `test/core-file-budget.test.mjs`) сделана вручную пересчётом, сам тестовый + файл не запускался (не нужен: код диалогов ещё на месте, ratchet не может + измениться). +- Не читал повторно эпик #591 целиком — К1 подготовки к нему в r1 уже + подтверждён, дельта эпика не касается. + +## Материал раунда + +- Issue #592, тело на момент разбора (`gh issue view 592 --json body`), + ревизия r2 (после комментария автора от 2026-09-18T16:11:07Z). +- Заход r2, циклов ревью ТЗ израсходовано 1 из 4 (израсходован жёлтым + вердиктом r1; текущий зелёный вердикт цикла не расходует, §4). +- Предыдущий раунд: `docs/reviews/SPEC-REVIEW-592-r1.md`, материал — + коммит `01fe7350791e`, дерево `0054c6622b79256b64b455ed786b46270fec9208`. +- Код на момент разбора — рабочая копия на `HEAD` = `8ec85ac0f6f62e72f8ac43c95786080e02b3a8bf` + (продуктовый код задачи ещё не менялся; ссылки на строки/потолки относятся к + этому состоянию репозитория). + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `8ec85ac0f6f6` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `d7c95364e09b77282237c26d3917fc86f3a025bd` + ``` + git log --all --format='%H %T' | grep d7c95364e09b + ``` +- Тело issue: `b105f7b3eb3f70575ee5751d1a917940da949981400e342e9cb133153057f673` +- Вердикт конвейера: `green` · High 0