From a4667562470dee913dfdc14b57adb7644eeafa07 Mon Sep 17 00:00:00 2001
From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com>
Date: Sun, 20 Sep 2026 19:31:02 +0000
Subject: [PATCH] docs: review document for #602
Issue: #602
User-Visible: no
---
docs/reviews/SPEC-REVIEW-602-r1.md | 283 +++++++++++++++++++++++++++++
1 file changed, 283 insertions(+)
create mode 100644 docs/reviews/SPEC-REVIEW-602-r1.md
diff --git a/docs/reviews/SPEC-REVIEW-602-r1.md b/docs/reviews/SPEC-REVIEW-602-r1.md
new file mode 100644
index 00000000..a3d5621a
--- /dev/null
+++ b/docs/reviews/SPEC-REVIEW-602-r1.md
@@ -0,0 +1,283 @@
+# SPEC-REVIEW-602-r1
+
+**Issue:** [#602](https://github.com/Matysh/houseplan-card/issues/602) — «Полировка редизайна диалогов пространства и устройства»
+**Этап:** ТЗ на ревью (PROCESS.md §2.4)
+**Трек:** full (аналитика #602 называет нарушенные критерии `small`: больше одной поверхности, новый UX-контракт radar-toggle, отдельная touch/mobile проверка — обоснование корректно)
+**Заход:** r1 · блокирующих циклов израсходовано 0 из 4
+
+Ревьюер работает без контекста реализации, материал — тело issue (раздел `## ТЗ`) и три комментария (аналитика, вопросы владельцу, решения владельца).
+
+---
+
+## Скоуп проверки
+
+ТЗ описывает точечную полировку четырёх диалогов на общем form-kit («Настройки
+пространства», «Общие настройки», «Настройки комнаты», «Настройки устройства»):
+удаление избыточных подписей/статусов, выравнивание переключателя и числовых
+полей шкал, однострочные футеры с icon-only деградацией на узких экранах,
+перенос настройки climate-температуры и замену кнопки объявления radar на
+form-kit toggle с раскрытием настроек под ним.
+
+Проверялось:
+
+1. Соответствие `docs/SCOPE.md` (персона/job) — task служит J4/J6, поверхность
+ редакторская, персона — Home admin.
+2. Полнота обязательных разделов ТЗ по PROCESS.md §7.1.
+3. Однозначность и проверяемость AC1–AC16.
+4. Заземление фактических утверждений ТЗ (аналитика + §6) в реальном коде —
+ не выданы ли догадки за факты.
+5. Согласованность с `docs/USER-GUIDE.ru.md` (терминология, уже
+ задокументированное поведение) и с `docs/TOUCH-SUPPORT.md` (мобильный
+ контракт редакторов).
+6. Процесс: корректно снятый `blocked`, зафиксированные решения владельца по
+ Q1/Q2, метки (`bug`, `P2`, `polish`, `S4-spec-review`, без `small`/`trivial`
+ — согласуется с выбором полного трека).
+
+## Как проверялось
+
+Ревью велось состязательно: каждое фактическое утверждение ТЗ и аналитики
+сверялось с исходником, а не принималось на веру.
+
+- `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` (§1–§9) — прочитаны целиком.
+- `docs/TOUCH-SUPPORT.md` — прочитан целиком (мобильный контракт редакторов,
+ правило «Touch editor: …» из раздела Documentation rule).
+- `docs/USER-GUIDE.ru.md` — прочитаны разделы про футер/`dialog.unsaved`
+ (строки 395–414), про radar (1158–1179), про climate-бейдж (1365–1383).
+- i18n: подтверждено существование и точный текст ключей
+ `space.title_hint`, `space.scale_hint`, `marker.name_hint`,
+ `dialog.unsaved`, `dialog.review_fields`, `radar.declare`,
+ `dialog.discard_title/confirm/keep` в `src/i18n/settings/ru.json` и
+ `src/i18n/ru.json`.
+- Код диалогов: `src/styles/form-kit.styles.ts` (геометрия тумблера, `4em`/
+ `5.8em` полей, `padding-right: 122px`/`125px` подписей шкалы),
+ `src/editors/marker-dialog.ts`, `src/editors/radar-section.ts`,
+ `src/radar-editor.ts`, `src/editors/room-settings-dialog.ts`,
+ `src/editors/general-settings-dialog.ts`, `src/hp-confirm.ts` — прочитаны
+ целиком/выборочно по каждому пункту §6 ТЗ.
+- Предшественники: тела issue #591, #600 (через `gh issue view`) — сверка,
+ что мобильный контракт диалогов (320/390/480/560/768/1280/1920,
+ «touch остаётся best effort по SCOPE») уже установлен в #600 и не вводится
+ заново.
+- Поиск прецедентов формулировки «Touch editor: …» по корпусу
+ `docs/reviews/*` (`SPEC-REVIEW-563-r1.md`, `SPEC-REVIEW-454-r1.md`) —
+ чтобы откалибровать, когда эта метка обязательна.
+- Файловая проверка: `docs/CHANGELOG.md`, `docs/CHANGELOG.ru.md`,
+ `docs/USER-GUIDE.md` существуют; корневого `CHANGELOG.md` в репозитории
+ нет (`ls` вернул «No such file or directory»).
+- Гейты кода в этом раунде не гонялись: этап — ревью ТЗ, продуктовый код не
+ менялся, для стадии `S4-spec-review` PROCESS.md §8/§10.4 не требует
+ прогона `typecheck`/`test`/`build` — они относятся к код-ревью (§2.7) и
+ реализации (§2.6). Это явное решение, а не пропуск: гонять их не по чему,
+ диапазон коммитов на ветке кода не менялся.
+
+## Находки
+
+### Medium (в скоупе) — неоднозначность «уже настроенного» radar-toggle
+
+**Файл:** тело issue #602, раздел `## ТЗ` §6.6 (радар toggle).
+
+**Формулировка ТЗ:** «Включение создаёт/возвращает radar draft и сразу
+раскрывает radar-настройки непосредственно под тумблером в «Дополнительных
+действиях»… **Для уже настроенного радара тумблер отображается включённым.**
+Выключение сворачивает настройки и ставит `radarRemove=true`; фактическое
+удаление происходит только после Save.»
+
+**Что проверено по коду.** `renderRadarSection` (`src/editors/radar-section.ts`)
+рендерит toggle/кнопку `radar.declare` только при
+`manualEntry = !savedUnsupported && bindingMode !== 'virtual' && (!d.radar || d.radarRemove) && !recognition.eligible`
+(строка 77). `recognizeRadar()` (`src/radar-editor.ts:105-127`) для ЛЮБОГО
+валидного сохранённого radar-конфига (независимо от того, был ли он объявлен
+вручную через `radar.declare` или распознан по модели устройства) возвращает
+`eligible: true, reason: 'saved'` — единственный признак, отличающий
+auto-recognized от manually-declared, это **значение профиля** (`profile`),
+а не отдельное поле происхождения: в схеме `MarkerRadar`/`RadarEditorDraft`
+такого поля нет (`src/radar-editor.ts:7-49`, `src/radar-model.ts`).
+
+Следствие: как только у устройства **уже есть сохранённый** radar-конфиг
+(любого происхождения), `recognition.eligible` = `true` → `manualEntry` = `false`
+→ ветка `placement === 'additional'` возвращает `html\`\`` (ничего) → диалог
+показывает не toggle, а старую карточку `