diff --git a/docs/specs/396-camera-transition-fixes.md b/docs/specs/396-camera-transition-fixes.md index efe74405..ec4bf587 100755 --- a/docs/specs/396-camera-transition-fixes.md +++ b/docs/specs/396-camera-transition-fixes.md @@ -4,7 +4,7 @@ - Приоритет: P1, bug (регресс против v1.69.0); полный трек — класс A, три находки на одной поверхности (камера), плюс правка формулировок принятой спеки #82 (`docs/specs/082-smooth-zoom.md` §10, §13) -- Ревизия: 1 (2026-08-31) +- Ревизия: 2 (2026-08-31) — по SPEC-REVIEW-396-r1 (High-1: перечень мест отмены) ## Сценарий @@ -32,8 +32,28 @@ (`src/houseplan-card.ts:1237`). До перехода на анимацию запись делали сами команды: `_onWheel`, `_stepZoom`, `_resetZoom` (`v1.69.0:6009,6016,6030`). `CameraTransitionController.cancel(false)` (`src/viewport-transition.ts:189`) -`settled` не вызывает, поэтому семь мест отмены — `:1267`, `:1401`, `:1551`, -`:4188`, `:4216`, `:6089`, `:6206` — оставляют показанный масштаб незаписанным. +`settled` не вызывает, поэтому показанный масштаб остаётся незаписанным. + +Полный перечень мест, где переход отменяется, и их классификация (сверено +`grep`'ом по `src/houseplan-card.ts` на HEAD, каждое прочитано): + +| Место | Что это | Класс | +|---|---|---| +| `:6387` `_stagePointerDown` | **буквальный сценарий issue**: касание плана поверх собственного зума | **пользовательская — сохранять** | +| `:6283` `_zoomAt` | немедленный pinch | правки не требует: оба вызывающих контекста сразу зовут `_saveZoom()` | +| `:1267` `_startCameraTransition` | цель совпала с текущим состоянием (no-op) | сохранять нечего — зум уже равен сохранённому | +| `:1159` `_onMotionChange`, `:2363` | `cancel(true)`, цель коммитится | уже сохраняется через `settled` | +| `:1401` `_cancelModeTransition` | смена режима | структурная | +| `:1551` `_commitSpace` | смена пространства | структурная | +| `:4188`, `:4216` `_load` | adoption конфига и layout | структурная | +| `:6089` `_applyView` | программная установка вида | структурная | +| `:6206` resize-обработчик | новая геометрия сцены | структурная | +| `:6360` `_restoreZoom` | восстановление сохранённого зума | структурная (пишет то, что и читает) | +| `:2745` `_cameraTransition.dispose()` | `disconnectedCallback`, минуя обёртку | структурная | + +Правка нужна ровно в одном месте пользовательского класса (`:6387`) плюс сам +механизм различения; остальные строки перечислены, чтобы граница была явной и +следующая правка не расширила её молча. Воспроизведение (исполнением, фейковый клок): переход 1.0 → 1.15 за 220 мс, обрыв на 120 мс → `settled` вызван 0 раз, `presented.zoom = 1.1413`. @@ -100,8 +120,8 @@ pan или анимированный переход. **В скоупе**: `src/viewport-transition.ts`, камера-путь `src/houseplan-card.ts` (`_startCameraTransition`, `_cameraTargetAt`, `_onWheel`, `_stepZoom`, -`_cancelCameraTransition`, glow-гейт), правка §10 и §13 в -`docs/specs/082-smooth-zoom.md`, тесты и мутанты. +`_cancelCameraTransition`, **`_stagePointerDown`**, glow-гейт), правка §10 и §13 +в `docs/specs/082-smooth-zoom.md`, тесты и мутанты. **Не в скоупе**: поведение pinch/pan persistence (свой контракт, §13 #82), длительности и кривые анимации, kiosk double-tap, изменение формата `LS_ZOOM`, @@ -122,13 +142,16 @@ editor zoom (не персистится по решению #82). ## Критерии приёмки -- **AC1**. После пользовательской отмены перехода (pointerdown по сцене, - начало pan/pinch/draw/drag/selection) сохранённый зум пространства равен - показанному на момент отмены. Доказательство: юнит на контроллер + карту, - сравнение сохранённого значения с `presented`. -- **AC2**. Структурная отмена (смена пространства/режима, adoption, restore, - disconnect) не записывает зум вовсе. Доказательство: тот же юнит, обратный - случай — счётчик записей не растёт. +- **AC1**. После пользовательской отмены перехода (`_stagePointerDown` — + касание плана, с которого начинается pan/pinch/draw/drag/selection) + сохранённый зум пространства равен показанному на момент отмены. + Доказательство: юнит на контроллер + карту, сравнение сохранённого значения + с `presented`. +- **AC2**. Структурная отмена (смена пространства/режима, `_applyView`, + resize, adoption, `_restoreZoom`, disconnect — строки таблицы выше) не + записывает зум вовсе. Доказательство: тот же юнит, обратный случай — + счётчик записей не растёт. Отдельно: `_zoomAt` (pinch) остаётся без + изменений и продолжает сохранять через вызывающий контекст. - **AC3**. Серия из шести wheel-событий с интервалом 8 мс оставляет мировую точку под курсором на месте с точностью 1e-9 единиц плана (без clamp). Доказательство: юнит с фейковым клоком; при clamp смещение допускается