mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 11:49:16 +00:00
@@ -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 → в задаче**
|
||||
Reference in New Issue
Block a user