docs: review document for #82

Issue: #82
User-Visible: no
This commit is contained in:
claude[bot]
2026-08-30 18:52:54 +03:00
committed by Matysh
parent 7610b32306
commit 486a5d7bc2
+183
View File
@@ -0,0 +1,183 @@
# SPEC-REVIEW-82-r1 — Плавное масштабирование плана (issue #82)
- **Issue:** https://github.com/Matysh/houseplan-card/issues/82
- **Артефакт ТЗ:** `docs/specs/082-smooth-zoom.md`, коммит `141d79a923f5703eb3beceebdabbd5508821f0fe`
- **Заход:** r1 · блокирующих циклов израсходовано 0 из 4 (полный трек, лимит 4)
- **Ревьюер:** Claude, роль «Ревьюер ТЗ» (PROCESS.md §2.4, §6)
## Скоуп ревью
Задача полного трека (нет метки `small`), поэтому ТЗ живёт файлом
`docs/specs/082-smooth-zoom.md`, а не в теле issue. Это первый заход
ревью на этом ТЗ (r1), поэтому §2.10 (разбор по дельте) не применяется —
разбор полный. Диф на пути к текущему SHA:
```
git diff 453c3e3d..141d79a9 -- docs/specs/082-smooth-zoom.md # 352+/232- строк, актуализация ТЗ
```
Диф не трогает `src/**`, `custom_components/**`, `test/**`, `demo/**` —
только `docs/specs/082-smooth-zoom.md`. Класс C (документация), гейты
типа `typecheck`/`test`/`build`/`check-docs` к этому диффу неприменимы:
менять нечего, кода не существует. См. «Чего не проверял».
## Как проверялось
1. Прочитан `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` (§1, §2.3–2.10, §4,
§5, §7, §12).
2. Прочитано тело issue #82 и все три комментария (аналитика 2026-08-14,
заведение ТЗ 2026-08-15, актуализация 2026-08-30).
3. Прочитан полный текущий текст `docs/specs/082-smooth-zoom.md` (24
раздела).
4. Прочитан канонический `docs/CANVAS.md` (§5 Zoom and pan, «View/editor
camera handoff», §4 content frame) и `docs/TOUCH-SUPPORT.md` (raздел
про View/editor visual transition, deliberate degradation rule).
5. Проверены фактические утверждения ТЗ о текущем коде против
`src/houseplan-card.ts` (`_zoomAt`, `_onWheel`, `_stepZoom`,
`_resetZoom`, `_fitAll`, `_fitFar`, `_baseVb`, `_clampView`,
`ZOOM_MAX`/`ZOOM_MIN`, `LS_ZOOM`, `_saveZoom`, lazy `import('./houseplan-editor-runtime')`)
и `src/mode-transition.ts` (`ModeTransitionController`,
`interpolateModeVisualState` — уже интерполирует `pixelsPerUnit` в
log-space и center линейно тем же easing, что подтверждает
реализуемость предложенного §9 механизма).
6. Проверена терминология кнопок/подсказок против `src/i18n/ru.json`
(`title.zoom_fit` = «Вписать всё», `canvas.show_far` = «Показать») —
совпадает с матрицей §6 ТЗ.
7. Проверено существование смоков, на которые ссылается план тестов
(`demo/smoke_mode_transition.mjs`, `demo/smoke_visual_continuity.mjs`,
`demo/smoke_zoom_out.mjs`, `demo/smoke_pan_any_zoom.mjs`,
`demo/screencast_visual_continuity.mjs`, `npm run continuity:screencast`
в `docs/TESTING.md`) — не изобретены, это существующий инструментарий
#73.
8. Проверены обязательные разделы ТЗ по PROCESS.md §7.1 построчно
(список ниже).
## Проверка обязательных разделов (§7.1)
| Раздел §7.1 | Есть в ТЗ | Где |
| --- | --- | --- |
| Сценарий (персона/поверхность/момент) | ✅ | §1 |
| Что человек увидит до/после | ✅ | §2 |
| Проблема | ✅ | §3 |
| Скоуп и не-скоуп | ✅ | §4 (цели) + §5 (не входит) |
| Контракт поведения / UX | ✅ | §6–§13 |
| Модель данных и миграция | ✅ | §14 — «не меняется, миграции нет» |
| i18n | ✅ | §20 — новых ключей нет |
| AC1…ACn с доказательством | ✅ | §17, 14 критериев, у каждого назван способ |
| План автотестов | ✅ | §18 (unit / browser smoke / golden-perf) |
| Риски | ✅ | §22, 8 рисков с мерой |
| Откат | ✅ | §23 |
| Release-артефакты | ✅ | §21 |
Все обязательные разделы присутствуют и содержательны, не переписывают
issue дословно.
## Находки
Блокирующих (High) находок нет. В скоупе-Medium находок нет. Вне
скоупа — нет.
Ниже — три Low-наблюдения; ни одно не требует правки ТЗ, оставлены с
записью решения ревьюера (не блокируют переход в `S5-ready`).
### Low-1 — AC13 частично доказывается гейтом, недоступным на этой стадии цикла
`AC13` называет доказательством «Performance profile + screencast
smoke». Per `docs/STATUS.md`, CDP-скриншот-профиль (`continuity:screencast`)
— **stable-release-only** гейт, а не гейт код-ревью или даже бета-гейта;
то есть формально AC13 не может быть закрыт автотестом до промоушена в
стабильный релиз. Это не изобретение автора ТЗ: тот же паттерн уже
принят для #73 (`docs/superpowers/specs/2026-08-10-plan-visual-continuity-design.md`
явно делит проверку на обязательный CI rAF sampler и pre-stable CDP
screencast). Решение ревьюера: не блокировать — прецедент уже
принят продуктом, а перформанс-часть AC13 (RAF/rebuild-счётчики) всё
равно доказывается раньше, в pre-beta профиле (§8). Отметить только,
что на код-ревью AC13 будет разобран по коду плюс перформанс-профиль,
а screencast-часть закроется не раньше стабильного гейта — это стоит
явно писать в хендоффе, а не подразумевать.
### Low-2 — общий easing-хелпер между `ModeTransitionController` и новым camera controller не специфицирован технически
§24 помечает разделение camera/mode-контроллеров с общим easing как
«принято предположительно, поменять свободно» — формально корректно
по PROCESS.md §7.1 (технический вопрос, не продуктовый). Замечание
чисто наблюдательное: `interpolateModeVisualState` в
`src/mode-transition.ts:124-156` уже реализует ровно ту же схему
(log-space для масштаба, линейно для центра, общий `ease()`), так что
риск, который §22 таблицы называет «Wheel ощущается медленным» /
«SVG и HTML расходятся», технически прецедентно снят — эта же формула
уже работает в проде для перехода режимов. Не требует правки ТЗ.
### Low-3 — «дальний hint «Показать»» добавлен в матрицу §6, не упомянутый в исходном тексте issue
Матрица §6 ТЗ добавляет девятую строку («Far hint «Показать»»)
относительно восьми строк в исходном issue. Проверено по коду:
`_fitFar()` (`src/houseplan-card.ts:5879`) сам вызывает `_resetZoom()`
— тот же примитив, что и «Вписать всё»/home-arrow/double-tap, так что
это не новая функциональность, а актуализация того, что «Вписать всё» в
issue уже подразумевало устройство разных источников одного и того же
действия. Не расширение скоупа, не требует нового вопроса владельцу.
## Что проверено и корректно
- Все фактические утверждения раздела 3 «Актуальность и проблема» о
текущем коде (`_zoomAt`, `_onWheel`, `_stepZoom`, `_resetZoom`,
`_fitAll`/`_fitFar`, lazy editor runtime, общий `_view` для
flat/isometric) — сверены с исходным кодом и точны.
- Константы `MIN_ZOOM = 1/3`, `ZOOM_MAX = 8`, easing
`cubic-bezier(0.2, 0.7, 0.2, 1)` — совпадают с `docs/CANVAS.md` §5 и
`src/mode-transition.ts`.
- Persistence-контракт §13 («editor zoom не пишется в View intent»,
«`_saveZoom()` работает только в `mode === 'view'`») сверен с
`src/houseplan-card.ts:6212-6228` — комментарий в коде подтверждает
тот же инвариант дословно.
- Терминология кнопок («Вписать всё», «Показать») сверена с
`src/i18n/ru.json` — совпадает буквально.
- `docs/TOUCH-SUPPORT.md` не противоречит требованию §12 «stage не
получает overlay/inert» во время camera-only tween: канонический
`inert` относится к отдельному, другому контракту View/editor
mode-перехода (#101), а не к zoom-действию внутри режима — ТЗ
корректно разграничивает эти два случая в §8.
- AC1–AC14 однозначны, у каждого указан способ доказательства; ни
одна формулировка не читается как два разных критерия одновременно.
- Раздел 24 «Принятые технические предположения» корректно отделяет
технические решения от продуктовых; продуктовых вопросов к
владельцу действительно не осталось — сценарии из issue (interruption
matrix, accessibility, no-op) уже были фактами, подтверждёнными
комментарием владельца 2026-08-14 («вопросы: нет»).
- Раздел «Не входит в задачу» корректно исключает inertia/kinetic pan,
анимацию mode/space/projection-переходов, новый storage-формат,
что не даёт скоупу расползтись на смежные issue (#101, #73, #89/122).
- Двунаправленные ссылки issue ↔ ТЗ на месте (`docs/specs/README.md`
строка 115, тело ТЗ строка 3).
## Чего не проверял
- **Код-гейты `typecheck`/`test`/`build`/`check-docs` не прогонялись** —
диф этого раунда состоит только из `docs/specs/082-smooth-zoom.md`
(класс C), продуктового кода/тестов нет, прогонять нечего. Это
сознательное решение по объёму, а не пропуск: `git diff --stat`
выше подтверждает единственный изменённый файл.
- Не проверялась реализуемость точной wheel-anchor математики
(0.5 CSS px) на реальном RAF-цикле — это вопрос будущей реализации
и код-ревью («тест умеет падать»), не спецификации: ТЗ формулирует
требование измеримо (AC4, unit на presented-state retarget), способ
доказательства назван.
- Не запускал browser/perf/golden-смоки — на этой стадии кода нет,
им неоткуда взяться; они будут частью реализации (§18) и предметом
код-ревью.
- Не проверял детально `iso-projection.ts` построчно на предмет
скрытых зависимостей от zoom помимо общего `_view`/`_zoom`
состояния — ограничился подтверждением, что модуль не содержит
собственных ссылок на `viewBox`/`zoom` (grep пуст), что достаточно
для вывода «камера едина для flat/iso» из §9/AC10.
## Вердикт
ТЗ полное, разделы §7.1 закрыты, критерии приёмки однозначны и
снабжены способом доказательства, продуктовых вопросов к владельцу не
осталось, фактические утверждения о текущем коде и канонических
документах проверены и точны. Блокирующих находок нет.
**Вердикт: зелёный · заход r1 · блокирующих циклов 0/4 · High: 0 ·
Medium: 0 → в задаче**