# SPEC-REVIEW — issue #449 · заход r2 - Issue: https://github.com/Matysh/houseplan-card/issues/449 - Этап: ревью ТЗ (PROCESS.md §2.4) - ТЗ: `docs/specs/449-double-fit-all.md` - Материал: ветка `issue/449-double-fit-all`, SHA `e027b2a06d62b79530840a36369651d5eea38839` - Трек: полный (issue не помечен `small`); лимит циклов ревью ТЗ — 4 (§2.4) - Заход r2, блокирующих циклов израсходовано до этого вердикта: 1/4 (r1 — жёлтый) ## Скоуп проверки — по дельте (PROCESS.md §2.10) Предыдущий вердикт: r1, жёлтый, документ `docs/reviews/SPEC-REVIEW-449-r1.md`, зафиксирован в коммите `9206ef64b6e8f344a881db057ecae065833e25db`. Материал того раунда: SHA `5847bf2b1bb6e6168f6727b26470c28f7f2650ec`, дерево `0254c870c60fdf2ba6d000a7c0586607a9bf4e52`, блоб ТЗ `3abb3ba5bb81f1c15be272ddbf1fa858f0e6adb5` — SHA живой, разрешается напрямую (`git log --oneline 9206ef64..e027b2a0` даёт один коммит), ребейза не было (`git merge-base origin/dev e027b2a0` = `89647c10`, тот же база, что и на момент r1). Дельта — один коммит `e027b2a0` поверх `9206ef64`: ``` git diff 9206ef64..e027b2a0 -- docs/specs/449-double-fit-all.md docs/specs/README.md ``` ```diff +- **Touch editor: not exposed** — жест живёт только во View и kiosk; редакторы + Плана, Устройств, Декора и Подложки его не получают, их touch-поведение и + редакторский double-click не меняются (§6 «Режимы», AC7). Правило + `docs/TOUCH-SUPPORT.md` → «Documentation rule». ``` Ровно 4 добавленные строки в шапке ТЗ, `docs/specs/README.md` не менялся (запись issue↔ТЗ уже была на месте с r1). Продуктовый код по-прежнему не тронут: диапазон `git diff origin/dev...HEAD` содержит только `docs/reviews/SPEC-REVIEW-449-r1.md`, `docs/specs/449-double-fit-all.md`, `docs/specs/README.md` — класс C целиком. Дельта локальна: не ребейз, не смена контракта, не новая подсистема, объём — 4 строки против находки в одну строку. Разбор сокращён до дельты плюс всего, до чего эта дельта дотягивается: сама новая строка и разделы, на которые она ссылается (§6 «Режимы», AC7, `docs/TOUCH-SUPPORT.md` → «Documentation rule»). Остальные разделы ТЗ дельта не задевает и не проверялись повторно — см. «Унаследовано из r1». ## Как проверялось 1. Найден вердикт r1 и его материал — комментарий issue `#issuecomment-5542152824` и документ `docs/reviews/SPEC-REVIEW-449-r1.md` (коммит `9206ef64`), включая блок «Материал раунда». 2. `git diff 9206ef64..e027b2a0` — единственная правка, 4 строки. 3. Проверена точная формулировка `docs/TOUCH-SUPPORT.md` → «Documentation rule» (`docs/TOUCH-SUPPORT.md:163-175`): три допустимых значения, `not exposed` — одно из них, выбор соответствует факту (задача не даёт и не отнимает touch-возможностей редакторов, а не вырождает их). 4. Проверена ссылка новой строки на §6 «Режимы» и AC7 внутри самого файла (`docs/specs/449-double-fit-all.md:180-188`, `:279-285`) — обе секции существуют и говорят про **три** редактора: План, Устройства, Подложка. 5. Сверено количество и названия редакторов, перечисленных в новой строке («Плана, Устройств, Декора и Подложки» — четыре существительных), с каноническим списком: `docs/USER-GUIDE.ru.md:201-206` (таблица режимов: Редактор плана / Редактор устройств / Редактор подложки — ровно три), `docs/UX-MODES.md:186` (`## Background — the decor underlay`, то есть «decor» — это содержимое редактора Background/Подложка, не отдельный редактор) и `scripts/check-docs.mjs:115` (`[/\bDecor editor\b/gi, 'Background editor']` — инструмент проекта явно нормализует «Decor editor» в «Background editor» как устаревший синоним одного и того же редактора). Также сверено с внутренним enum режима: `src/houseplan-card.ts:890` (`private _mode: 'view' | 'plan' | 'devices' | 'decor'`) — `decor` здесь и есть код режима редактора Подложки, а не четвёртое отдельное значение. 6. Файлы `docs/specs/README.md` (не изменился) и трейлеры коммита `e027b2a0` (`git show -s --format=full e027b2a0`) — `Issue: #449`, `User-Visible: no`, верно для документационного коммита без изменения поведения. ## Закрытие раунда r1 | Находка r1 | Чем закрыта | Где это видно | |---|---|---| | **M1** (Medium, в скоупе): нет обязательной строки `Touch editor: …` из `docs/TOUCH-SUPPORT.md` → «Documentation rule» | Добавлена строка `Touch editor: not exposed` в шапку ТЗ, с обоснованием и ссылкой на §6/AC7 | `docs/specs/449-double-fit-all.md:9-12` (коммит `e027b2a0`) | | Вне скоупа: расхождение «Показать всё» / «Вписать всё» в `docs/USER-GUIDE.ru.md` | Заведено отдельным issue, как и требовало ревью; в этой ветке не трогается | issue [#452](https://github.com/Matysh/houseplan-card/issues/452) | M1 закрыта формально верно — правило требует именно одну явную строку с одним из трёх значений, строка добавлена в то же место, что и у ранее цитированных прецедентов (#229, #230, #302, #220, #243). Но сама добавленная строка вносит новую фактическую неточность — см. находку ниже. ## Находки ### Medium (в скоупе — чинится в этом ТЗ, без него — жёлтый вердикт) **M2. Строка `Touch editor: not exposed`, закрывающая M1, называет несуществующий четвёртый редактор.** Строка перечисляет «редакторы Плана, Устройств, **Декора** и **Подложки**» (`docs/specs/449-double-fit-all.md:9-10`) — четыре разных существительных, как если бы Декор и Подложка были двумя разными редакторами. Это не так: `docs/USER-GUIDE.ru.md:201-206` называет ровно три редактора (План, Устройства, Подложка); `docs/UX-MODES.md:186` прямо называет декор «the decor underlay» — содержимым редактора Подложки/Background, не отдельным режимом; `scripts/check-docs.mjs:115` normalizes «Decor editor» → «Background editor» именно потому, что в проекте это два имени одного и того же редактора (внутри код называет его `decor`, снаружи — «Подложка» / «Background editor»); и, наконец, сама эта строка ссылается на §6 «Режимы» и AC7 того же файла, которые оба перечисляют ровно три редактора: План, Устройства, Background (`docs/specs/449-double-fit-all.md:180-188,279-285`). **Воспроизведение:** ``` git show e027b2a0:docs/specs/449-double-fit-all.md | sed -n '9,12p' git show e027b2a0:docs/specs/449-double-fit-all.md | sed -n '180,188p' ``` Первая команда даёт четыре редактора, вторая — три. Разночтение внутри одного файла. **Почему это находка, а не придирка к форме:** ровно это M1 из r1 просило устранить — необходимость собирать вывод «какие редакторы затронуты» из нескольких мест. Правка добавила единственную обязательную строку, но эта строка сама разошлась с §6/AC7, на которые ссылается, — и внесла ложную сущность («редактор Декора»), которой не существует ни в UI, ни в коде, ни в каноническом словаре `docs/USER-GUIDE.ru.md`. Оставить как есть значит вернуть ту же двусмысленность, которую M1 просило закрыть, только в обратную сторону (лишний редактор вместо необходимого, но неявного вывода). **Как чинится:** убрать дублирующее существительное, например: «редакторы Плана, Устройств и Подложки (декора) его не получают» — либо просто «Плана, Устройств и Подложки», раз термин «декор» уже пояснён как содержимое Подложки в остальном тексте ТЗ (§2, «Что считается свободным фоном» и другие места файла, не входящие в дельту, декор нигде не называют отдельным редактором). ### High / Low Нет находок этих уровней в дельте r2. ## Что проверено и корректно - **M1 закрыта по существу формы**: строка добавлена, использует ровно одно из трёх разрешённых значений правила (`not exposed`), стоит в шапке рядом с «Решения владельца» — там же, где и у процитированных прецедентов. - **Ссылка на `docs/TOUCH-SUPPORT.md` → «Documentation rule» точна**: раздел существует по названным строкам, формулировка трёх допустимых значений совпадает. - **Ссылки новой строки на §6 и AC7 разрешимы** — оба раздела существуют в том же файле и оба говорят о touch/double-click в редакторах, тема совпадает (расходится только счётный состав — см. M2). - **`docs/specs/README.md` не тронут и не должен был быть**: запись issue↔ТЗ добавлена ещё в r1 и делта её не касается. - **Трейлеры `e027b2a0` корректны**: `Issue: #449`, `User-Visible: no` — верно для чисто документационной правки без изменения поведения продукта. - **Дельта действительно локальна**: не ребейз, не новая подсистема, не смена контракта — полный повторный разбор не требуется (PROCESS.md §2.10). ## Унаследовано из r1 Всё, что документ `docs/reviews/SPEC-REVIEW-449-r1.md` (коммит `9206ef64`, материал — SHA `5847bf2b1bb6`, дерево `0254c870c60f`, блоб ТЗ `3abb3ba5bb81`) проверил и признал корректным, дельта r2 не задевает и принято без повторной проверки: - продуктовая рамка — job J1, персоны Household/Guest (View) и Home admin (kiosk), задача в скоупе `docs/SCOPE.md`; - решения владельца Q1/Q2 корректно перенесены в контракт поведения (§5) и таблицу §6 (сама таблица не менялась дельтой r2, кроме факта, что новая строка теперь на неё ссылается — содержимое таблицы проверено заново в этом раунде, см. «Как проверялось» п.4, и совпадает с тем, что подтвердил r1); - построчная сверка «текущего поведения по коду» (`_lastTap`/`_swipeStart` внутри kiosk-ветки, отсутствие `dblclick` на stage, `_fitAll` сигнатура, `ROOM_FIT_INTERACTIVE_OWNER`, `CameraTransitionReason`, no-op на `sameCameraState`) — код не менялся, повторная сверка не требуется; «Как проверялось» п.5 этого раунда лишь свежо сверил список редакторов и внутренний enum `_mode`, не весь код-контракт заново; — но раз ссылка на исходники была короткой и по конкретному факту, она не расширяет разбор до полного; - существование всех файлов, названных в «Плане автотестов» и AC1–AC11 (smoke/test/mutation-gate) — файлы дельтой не переименовывались и не удалялись; - обязательные разделы §7.1 присутствуют все, AC пронумерованы и каждый несёт способ доказательства; - блок «Принятые предположения» отделяет техническое от продуктового корректно — не менялся; - вне-скоуп находка «Показать всё» / «Вписать всё» верно заведена как #452 и не относится к предмету этого раунда. ## Чего не проверял и почему - **Реализацию** — её по-прежнему нет: диапазон `git diff origin/dev...HEAD` не содержит класса A/B, только `docs/**`. - **`npx tsc --noEmit` / `npm test` / `npm run build`** — не гонял: раунд не меняет ни одной строки кода. - **`node scripts/check-docs.mjs`** — не гонял: диапазон не трогает `src/**`, и сам скрипт нормализует «Decor editor» только в `PUBLIC_DOCS` (README, USER-GUIDE), не в `docs/specs/**`, так что он не поймал бы M2 и не является подменой этой проверки. - **Полный текст ТЗ вне зоны дельты** (сценарий, скоуп/не-скоуп, модель данных, риски, план автотестов, откат, release-артефакты) — не перечитывал заново; ничто из этого не зависит от добавленных четырёх строк, см. «Унаследовано из r1». - **Q1/Q2/Q3 продуктовую историю** — не переоткрывал: решения владельца зафиксированы до r1 и дельта их не касается. ## Вердикт High: 0 · Medium в скоупе: 1 (M2) · Medium вне скоупа: 0 (r1-находка уже заведена как #452, повторно не считается). Без High это жёлтый вердикт (PROCESS.md §2.4, §12): ТЗ возвращается автору на правку M2 — привести добавленную строку `Touch editor: not exposed` к тем же трём редакторам, что называют §6 и AC7 того же файла. Правка локальна (один факт в одной строке), следующий цикл должен разбираться по дельте этой правки. Лимит циклов израсходован 2/4. --- ## Материал раунда - Ветка: `issue/449-double-fit-all`, коммит `e027b2a06d62` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала: `f5db58186a589e659c2bdb9dd9fad3ba88a9e5c6` ``` git log --all --format='%H %T' | grep f5db58186a58 ``` - ТЗ `docs/specs/449-double-fit-all.md`, блоб `a1f7c22a6ad5e028a2fdbc3cfc01a8aa9f6780f0` ``` git log --all --find-object=a1f7c22a6ad5e028a2fdbc3cfc01a8aa9f6780f0 -- docs/specs/449-double-fit-all.md ```