mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
docs: revise isometric stage 1 specification
Issue: #89 User-Visible: no
This commit is contained in:
+6
-2
@@ -98,8 +98,12 @@ the file — and if a future version wants to reclaim that space, it asks.
|
||||
- History, graphs, statistics → recorder/history cards. We show now, not then.
|
||||
- Camera streams, media controls → their own cards; our more-info opens HA's.
|
||||
- Energy monitoring/analytics → HA Energy.
|
||||
- 3D / isometric / photorealistic rendering, furniture drawing → niche tools
|
||||
(easy-floorplan et al.); we are a schematic live map, not an interior editor.
|
||||
- Photorealistic rendering, a free 3D camera, a separate 3D model and 3D
|
||||
furniture/interior editing → niche tools (easy-floorplan et al.); we are a
|
||||
live spatial map, not an interior editor. A narrow exception approved for
|
||||
[#89](https://github.com/Matysh/houseplan-card/issues/89) is a deterministic
|
||||
2.5D presentation of the existing canonical plan: the same J1/J2/J3 state,
|
||||
actions and geometry, with no second model and no free camera.
|
||||
- A general dashboard framework (menus, popups, theming engine) → Bubble Card,
|
||||
Dwains and friends.
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
- Issue: https://github.com/Matysh/houseplan-card/issues/89
|
||||
- Приоритет: **P1**, feature
|
||||
- Статус ТЗ: **готово к реализации** (ревизия 2, ревью 2026-08-11).
|
||||
До ADR (§13.1) задача ведётся как spike/implementation-prep: renderer не
|
||||
считается выбранным, пока решения ADR не записаны.
|
||||
- Статус ТЗ: **на независимом ревью** (ревизия 3, решения владельца 2026-08-13).
|
||||
Ревизия 2 предшествует действующему процессу и новым визуальным референсам;
|
||||
эта редакция обязана получить независимое ревью до `S5-ready`.
|
||||
- Исследование и продуктовое обоснование: [`089-isometric-view.md`](089-isometric-view.md)
|
||||
(контекст; нормативен настоящий файл)
|
||||
- Ревью ревизии 1: `SPEC-REVIEW-089-isometric-view-stage1.md`
|
||||
- Историческое ревью ревизии 1 не является доступным артефактом репозитория и
|
||||
не заменяет новое ревью по `PROCESS.md`.
|
||||
- Связано: #82 (анимация zoom/fit), #73 (визуальная непрерывность), #85 (тесты
|
||||
должны уметь падать), #50 (перенос конфигурации)
|
||||
|
||||
@@ -31,11 +32,11 @@
|
||||
|
||||
| # | Находка | Куда внесено |
|
||||
|---|---|---|
|
||||
| B1 | Проекция точек описана, а три реальные системы координат — нет. `IsoCamera` без pivot и zScale: проекция вокруг `(0,0)` сдвинет план, а `_baseVb()` (`houseplan-card.ts:3995`) не знает про поднятые верхние грани и начнёт их обрезать | §4.4 — plan/scene/client, pivot-константа, `projectedFrame` |
|
||||
| B2 | Нет алгоритма переноса viewport между проекциями. `_view` и `_viewModeSnap` (`:982`) хранят прямоугольник и `cx/cy` в координатах *текущей* сцены; требование «не менять фокус» было недоказуемо | §4.5 — алгоритм из шести шагов |
|
||||
| B3 | Несовместимость с `docs/WARM-REMOUNT.md`: `warmBoot` (`:287`) переносит `_view`/`_viewModeSnap`/mode, а один и тот же `ViewRect` теперь имеет два разных смысла | §7.1 — projection в warm-состоянии, усыновление только при совпадении |
|
||||
| B1 | Проекция точек описана, а три реальные системы координат — нет. `IsoCamera` без pivot и zScale: проекция вокруг `(0,0)` сдвинет план, а `_baseVb()` не знает про поднятые верхние грани и начнёт их обрезать | §4.4 — plan/scene/client, pivot-константа, `projectedFrame` |
|
||||
| B2 | Нет алгоритма переноса viewport между проекциями. `_view` и `_viewModeSnap` хранят прямоугольник и `cx/cy` в координатах *текущей* сцены; требование «не менять фокус» было недоказуемо | §4.5 — алгоритм из шести шагов |
|
||||
| B3 | Несовместимость с `docs/WARM-REMOUNT.md`: `warmBoot` переносит `_view`/`_viewModeSnap`/mode, а один и тот же `ViewRect` теперь имеет два разных смысла | §7.1 — projection в warm-состоянии, усыновление только при совпадении |
|
||||
| B4 | Правило «все попадания через unproject» технически неверно: SVG сам хит-тестит содержимое трансформированного `<g>`, HTML-маркер получает клик как обычный DOM-узел; плюс смок про перетаскивание маркера противоречил «редакторы всегда плоские» | §7.1 — нативный hit-test, смок про drag убран |
|
||||
| B5 | Кнопка «в киоске рядом с шапкой» невозможна: `.hdr.kioskhide { display: none }` (`styles.ts:987`) | §3, §7.1 — кнопка только в обычном View, аварийный выход из киоска через URL |
|
||||
| B5 | Кнопка «в киоске рядом с шапкой» невозможна: `.hdr.kioskhide { display: none }` в `src/styles.ts` | §3, §7.1 — кнопка только в обычном View, аварийный выход из киоска через URL |
|
||||
| B6 | Грамматика Labs противоречива: неясен приоритет query и хэша, смысл `off,iso`, повторного параметра, и §2.2 против §2.3 про очистку URL | §2.2.1 — точный контракт операций |
|
||||
| B7 | Не определена топология граней. `wallBodiesGeometry().geom` — MultiPolygon с внешними и внутренними rings после union и вырезов; «граничных рёбер» недостаточно. Формулировка «без торцов в проёме» запрещала бы корректные jamb faces | §5.1, §12 AC 6 |
|
||||
| B8 | Fallback «вернуться в flat на этом кадре» не отвечает, что будет на следующем рендере и что показывает кнопка | §9 — state machine с latch |
|
||||
@@ -53,6 +54,17 @@
|
||||
| T4 | Не определено поведение при первом запуске и при истёкшем флаге с сохранённым `iso` | §10.2 |
|
||||
| T5 | Issue и файл ТЗ расходились в статусе | §13.2 |
|
||||
|
||||
### 0.3 Решения владельца 2026-08-13
|
||||
|
||||
| # | Решение | Следствие для этапа 1 |
|
||||
|---|---|---|
|
||||
| O1 | Детерминированный 2.5D допускается как узкое исключение из прежнего абсолютного запрета в `docs/SCOPE.md` | Это альтернативное представление J1/J2/J3, не отдельная модель, interior editor или свободная 3D-камера |
|
||||
| O2 | Новые изображения задают обязательное направление Stage 2 | Stage 1 сразу использует почти верхнюю ортографическую камеру без диагонального yaw, но не обещает материал/фотореализм референса |
|
||||
| O3 | Labs — общий переиспользуемый механизм | Одноразовый флаг #89 запрещён; пользовательской настройки Labs нет |
|
||||
| O4 | #89 заканчивается полностью реализованным Stage 1 | Stage 2/public rollout получает отдельную feature issue только после зелёного Stage 1 |
|
||||
| O5 | Вертикальные створки и светлые оконные элементы отложены | Двери, окна и ворота сохраняют текущие символы на плоскости пола; стеновые разрывы полноценны |
|
||||
| O6 | Все текущие live-эффекты пола сохраняются | Glow/spill, солнце, room fills/hover, decor/backdrop и vacuum не заменяются новым оконным светом |
|
||||
|
||||
---
|
||||
|
||||
## 1. Цель и границы этапа
|
||||
@@ -60,6 +72,18 @@
|
||||
Получить работающий объёмный вид на реальных планах, не показывая его никому,
|
||||
кроме тех, кто явно включил флаг.
|
||||
|
||||
**Job и персона.** Этап служит J1 «показать весь дом и происходящее сейчас»;
|
||||
на целевой поверхности View домашний администратор оценивает скрытый прототип,
|
||||
а household member/guest в обычной установке продолжает видеть неизменный
|
||||
плоский план. Touch View и kiosk остаются обязательными поверхностями даже для
|
||||
скрытого режима: включивший Labs администратор не должен получить сломанный
|
||||
ежедневный план на планшете.
|
||||
|
||||
**До → после, без терминов реализации.** До этапа явно включённый
|
||||
экспериментальный режим отсутствует; после этапа тестировщик может одним
|
||||
переключателем увидеть тот же живой дом с низкими объёмными стенами и вернуться
|
||||
к прежнему плоскому виду без потери состояния, фокуса и действий.
|
||||
|
||||
Входит: механизм Labs (§2); системы координат и проекция (§4); объём стен,
|
||||
перегородок, колонн и разрывы в проёмах (§5); поведение слоёв (§6);
|
||||
взаимодействие, непрерывность и киоск (§7); кэш и производительность (§8);
|
||||
@@ -89,9 +113,9 @@ export const LABS_FLAGS: readonly LabsFlag[] = [ /* … */ ];
|
||||
|
||||
### 2.2 Источники активации
|
||||
|
||||
Читаются и query-строка, и хэш. Хэш — потому что карточка уже им владеет
|
||||
(`_hashSpace()`, `houseplan-card.ts:1290`, слушатель `hashchange` на `:1422`) и
|
||||
он реактивен внутри Lovelace; query — потому что его удобно давать тестировщику.
|
||||
Читаются и query-строка, и хэш. Хэш — потому что карточка уже использует его в
|
||||
`_hashSpace()` и реактивно слушает `hashchange` внутри Lovelace; query — потому
|
||||
что его удобно давать тестировщику.
|
||||
|
||||
```
|
||||
?hp-labs=iso #hp-labs=iso включить
|
||||
@@ -184,9 +208,17 @@ YAML-опция карточки (`labs: [iso]`) не вводится: конф
|
||||
|
||||
### 4.2 Камера
|
||||
|
||||
Один зафиксированный ракурс; константы выбираются на spike и после этого
|
||||
меняются только вместе с пересъёмкой golden. Свободное вращение и tilt в этап 1
|
||||
не входят.
|
||||
Один зафиксированный почти верхний ортографический ракурс, следующий новым
|
||||
референсам владельца: исходные горизонтали и вертикали плана остаются
|
||||
параллельны экранным осям, диагонального yaw/поворота плана нет, перспектива и
|
||||
схождение линий отсутствуют, высота стен заметна, но не закрывает комнаты.
|
||||
|
||||
Нормативная семья проекции для spike: `rotDeg = 0`; наклон от вида строго
|
||||
сверху находится в диапазоне **18–22°**; логическая высота и `zScale` должны
|
||||
давать низкую видимую боковую грань. Точное значение внутри диапазона выбирает
|
||||
ADR по golden/performance, после чего оно меняется только вместе с пересъёмкой
|
||||
новых iso-эталонов. Свободное вращение, пользовательский tilt и пресеты камеры
|
||||
в Stage 1 не входят.
|
||||
|
||||
### 4.3 Одна проекция на всё
|
||||
|
||||
@@ -223,9 +255,9 @@ projectedFrame(input: IsoFrameInput, cam: IsoCamera): ViewRect;
|
||||
2. `unprojectFloorPoint` инвертирует **только плоскость `z = 0`**: точке на
|
||||
вертикальной грани не соответствует единственная точка плана.
|
||||
3. **Pivot — фиксированная константа плана**, рекомендуется
|
||||
`[NORM_W / 2, NORM_W / 2]` (`NORM_W = 1000`, `space-geometry.ts:11`).
|
||||
`[NORM_W / 2, NORM_W / 2]` (`NORM_W = 1000` в `space-geometry.ts`).
|
||||
Не центр viewport и не центр содержимого: иначе появление дальнего объекта
|
||||
или переключение `_showFar` (`houseplan-card.ts:806`) сдвинет уже построенные
|
||||
или переключение `_showFar` сдвинет уже построенные
|
||||
стены без изменения их геометрии.
|
||||
4. Высота стены задаётся одной константой, переводится в plan units и только
|
||||
потом умножается на `zScale`. Значения фиксируются ADR.
|
||||
@@ -246,8 +278,8 @@ projectedFrame(input: IsoFrameInput, cam: IsoCamera): ViewRect;
|
||||
плана; в iso — пропустить центр `_view` через `unprojectFloorPoint`.
|
||||
2. Построить целевой `projectedFrame` и целевой fit.
|
||||
3. Сохранить тот же скалярный zoom.
|
||||
4. Спроецировать логический центр в целевую сцену и вызвать `_applyView()`
|
||||
(`:4101`) с этим центром.
|
||||
4. Спроецировать логический центр в целевую сцену и вызвать `_applyView()` с
|
||||
этим центром.
|
||||
5. Сырые `x/y/w/h` между видами не переиспользуются никогда.
|
||||
6. Вход в редактор выполняет тот же переход iso → flat, выход — обратный к
|
||||
предыдущему виду. Смена пространства внутри редактора сбрасывает старый
|
||||
@@ -294,7 +326,23 @@ runtime/warm-состоянием.
|
||||
## 6. Слои
|
||||
|
||||
Поведение слоёв — таблица §6 исследования, она нормативна. Дополнительно как
|
||||
запреты:
|
||||
обязательный контракт Stage 1:
|
||||
|
||||
- floor plane сохраняет **все** нынешние live-слои и их порядок: room
|
||||
fills/hover, Glow/spill, солнце, backdrop/decor, furniture и vacuum
|
||||
path/outline; состояния HA продолжают обновлять их без перестройки граней;
|
||||
- дверь, окно и ворота сохраняют нынешний floor-plane symbol и live state;
|
||||
вертикальные створки, светлые оконные вставки и новый оконный свет не
|
||||
появляются;
|
||||
- room/device actions, badges, live text и screen-facing HTML остаются теми же
|
||||
пользовательскими поверхностями; объёмный renderer не создаёт новых service
|
||||
paths и не ослабляет lock invariant из `docs/SCOPE.md`;
|
||||
- слои пола проецируются одной матрицей с нижними точками стен; HTML overlay
|
||||
использует те же projected anchors, но сам остаётся screen-facing;
|
||||
- `show_borders: false` не рисует top/side faces, но не выключает room fill,
|
||||
Glow/spill, sunlight или их барьерную семантику;
|
||||
|
||||
Запреты:
|
||||
|
||||
- существующее дерево карточки **не оборачивается** в CSS 3D-контекст;
|
||||
`perspective`, `rotateX/Z`, `preserve-3d` не появляются ни на `.zoomwrap`, ни
|
||||
@@ -311,6 +359,12 @@ runtime/warm-состоянием.
|
||||
- **Редакторы всегда плоские.** Вход показывает плоский вид, выход
|
||||
восстанавливает предыдущий; переключение не пишет в command stack и не создаёт
|
||||
записей в сторе.
|
||||
- **Touch editor: не exposed.** Объёмной геометрии внутри Plan/Devices/Backdrop
|
||||
нет; редакторы используют прежний desktop-first flat contract.
|
||||
- **Touch View и kiosk: полностью поддерживаются.** Pan/pinch, space switching,
|
||||
room/device dialogs, безопасные действия, orientation/background/remount и
|
||||
kiosk gestures проходят тот же safety floor, что flat View. Переключение
|
||||
проекции атомарно и само не считается жестом #82.
|
||||
|
||||
### 7.1 Hit-test, непрерывность и киоск (B3, B4, B5)
|
||||
|
||||
@@ -322,7 +376,7 @@ HTML-маркер получает клик как обычный DOM-узел.
|
||||
- цепочка `client → scene → unprojectFloorPoint` применяется только там, где
|
||||
событие сцены действительно должно дать координату плана;
|
||||
- на этапе 1 объёмный вид ничего не создаёт, не редактирует и не перетаскивает,
|
||||
поэтому `_svgPoint()` (`:5018`) остаётся плоским;
|
||||
поэтому `_svgPoint()` остаётся плоским;
|
||||
- тесты кликают реальные DOM-узлы комнат, устройств и проёмов и проверяют
|
||||
действие; отдельный юнит проверяет цепочку `client → scene → floor`.
|
||||
|
||||
@@ -346,6 +400,13 @@ HTML-маркер получает клик как обычный DOM-узел.
|
||||
киоске понадобится, его место — существующий long-press диалог, отдельным
|
||||
решением.
|
||||
|
||||
**Touch/Companion.** На coarse pointer toggle в обычном View остаётся минимум
|
||||
44×44 CSS px; после переключения pinch midpoint и tap/long-press попадают в
|
||||
видимый объект, а не в его flat-позицию. Orientation change, background →
|
||||
foreground и Companion warm-remount используют §4.5/§7.1 и не показывают
|
||||
полуплоский смешанный кадр. Эти случаи release-blocking по
|
||||
`docs/TOUCH-SUPPORT.md`.
|
||||
|
||||
## 8. Производительность и кэш
|
||||
|
||||
### 8.1 Отпечаток (M2)
|
||||
@@ -452,6 +513,12 @@ Pan/zoom меняют только transform/viewBox и ничего не пер
|
||||
порядках, версии §2.4, валидность реестра.
|
||||
- Отсутствие вызова построителя геометрии объёма при выключенном флаге —
|
||||
проверяется шпионом (T1).
|
||||
- Camera contract: `rotDeg = 0`, диапазон tilt 18–22°, отсутствие perspective
|
||||
term и сохранение параллельности plan axes; поднятая высота не меняет floor
|
||||
round-trip.
|
||||
- Layer contract: state-only HA updates не меняют geometry fingerprint/cache;
|
||||
`show_borders: false` убирает только faces, а не floor layers; door/window/gate
|
||||
Stage 1 geometry не содержит вертикальных leaf/window panels.
|
||||
|
||||
### 11.2 Смоки
|
||||
|
||||
@@ -471,12 +538,27 @@ Pan/zoom меняют только transform/viewBox и ничего не пер
|
||||
кадр; iso → снять флаг → remount → плоский кадр без вуали; загрузка киоска с
|
||||
сохранённым `iso` и возврат в плоский через URL.
|
||||
|
||||
Отдельный smoke live-layer parity последовательно меняет room fill/hover,
|
||||
несколько Glow/spill sources, солнце, backdrop/decor, furniture и vacuum state;
|
||||
между flat и iso совпадают resolved source count/state, service-action outcome и
|
||||
логические floor anchors, а geometry build counter не растёт от HA-only update.
|
||||
Проверяются текущие opening symbols/states без vertical leaf/window DOM.
|
||||
|
||||
Touch/Companion smoke: toggle имеет ≥44×44 CSS px; pinch и space switching в
|
||||
iso; tap/long-press по реальному DOM room/device/opening; orientation resize;
|
||||
background/foreground и warm-remount; kiosk с сохранённым iso и аварийным
|
||||
`off`. В каждом случае нет phantom click, unintended edit/service call,
|
||||
смешанного flat/iso frame или permanently stuck View.
|
||||
|
||||
### 11.3 Golden (M7)
|
||||
|
||||
Минимальная матрица этапа: desktop dark (смешанные толщины, проёмы, Glow и
|
||||
солнце, устройства); desktop light (тема, затенение граней, паритет фильтров);
|
||||
узкий мобильный или киоск (fit, совпадение маркеров и подписей, отсутствие
|
||||
обрезки); `show_borders: false` (стены не нарисованы, заливка и Glow на месте).
|
||||
Каждая iso-сцена показывает `rotDeg = 0`: стены, параллельные plan X/Y, не
|
||||
получают диагонального поворота. Референсы владельца не являются baseline
|
||||
Stage 1 и не принимаются как обещание фотореалистичных материалов.
|
||||
Ветка активации флага добавляется в `demo/golden/harness.mjs`,
|
||||
`GOLDEN_MATRIX_VERSION` поднимается. Существующие плоские сцены не принимаются
|
||||
заново: ненулевой diff — регресс. Новые эталоны принимаются только из полного
|
||||
@@ -505,30 +587,67 @@ Linux-артефакта CI по действующему контракту HP-
|
||||
свап атомарный (если анимация появится через #82, `prefers-reduced-motion`
|
||||
делает её мгновенной).
|
||||
|
||||
### 11.6 Матрица доказательств AC
|
||||
|
||||
| AC | Доказательство до code review | Обязательная проверка ревьюера |
|
||||
|---|---|---|
|
||||
| AC1 | unit spy + flat smoke + существующие golden + performance profile | убедиться мутантом, что включение iso без флага краснит smoke |
|
||||
| AC2–AC3 | unit Labs grammar/version + URL smoke | запустить команды и проверить fail-closed malformed/expired |
|
||||
| AC4 | unit camera + desktop/touch smoke + iso golden | проверить чтением отсутствие perspective/free camera и исполнением fixed view |
|
||||
| AC5–AC6 | unit face topology + iso golden | применить один geometry mutant из §11.4 |
|
||||
| AC7 | unit fingerprint/layer contract + live-layer smoke + golden | выполнить HA-only update и проверить cache/source/action parity |
|
||||
| AC8 | projection unit + DOM interaction/touch smoke | внести контролируемый anchor shift и получить красный smoke |
|
||||
| AC9 | editor/warm/touch smoke | проверить View → editor → View и Companion remount исполнением |
|
||||
| AC10 | fallback unit + smoke | инъекция renderer exception, затем повторный HA update |
|
||||
| AC11 | reviewed performance profile на exact SHA | проверить report provenance/environment fail-closed |
|
||||
| AC12 | schema/config source-contract + smoke второй карточки | чтение diff и исполнение flat `houseplan-space-card` |
|
||||
| AC13 | source-contract + opening/live-layer smoke | проверить отсутствие vertical leaf/window и нового window-light layer |
|
||||
| AC14 | touch/Companion smoke + mobile/kiosk golden | исполнить coarse-pointer safety matrix |
|
||||
| AC15 | review документации и provenance | проверить issue ↔ spec ↔ SCOPE и отсутствие user changelog |
|
||||
|
||||
## 12. Acceptance criteria
|
||||
|
||||
1. При выключенном флаге карточка идентична текущей: DOM, запросы, сторы,
|
||||
производительность в пределах допуска на шум, все существующие golden.
|
||||
2. Флаг включается из query и из хэша по грамматике §2.2.1, переживает переход
|
||||
между видами и снимается через `off`.
|
||||
3. Флаг с достигнутым `expires` не включается никаким способом.
|
||||
4. Под флагом в обычном View доступен объёмный вид с фиксированным ракурсом;
|
||||
плоский вид остаётся значением по умолчанию, в том числе при первом запуске.
|
||||
5. Физические стены, перегородки и колонны имеют непрерывные верх и боковые
|
||||
грани; виртуальные границы плоские.
|
||||
6. Проём является разрывом на всю высоту: внутри разрыва нет полосы верха или
|
||||
бока, а две вертикальные грани откосов на границах разрыва — ожидаемая часть
|
||||
объёма.
|
||||
7. Glow, spill, солнце, заливки и hover сохраняют текущую семантику; второго
|
||||
слоя света не появилось.
|
||||
8. Маркеры, подписи и попадания курсора используют одну проекцию и не расходятся
|
||||
с планом; переключение вида не меняет зум и не сдвигает логический центр.
|
||||
9. Редакторы всегда плоские; переключение не пишет в сторы и не создаёт записей
|
||||
в истории; warm-remount не подменяет проекцию.
|
||||
10. Исключение в renderer даёт плоский fallback с защёлкой, кнопка отражает
|
||||
фактический вид, предпочтение не перезаписывается.
|
||||
11. Перф-профиль §8.2 выполнен на полном workflow по точному SHA.
|
||||
12. Формат конфигурации не изменился; `houseplan-space-card` остался плоским.
|
||||
1. **AC1 (`unit` + `smoke` + `golden` + `performance`):** при выключенном
|
||||
флаге карточка сохраняет прежние DOM, запросы, сторы, flat golden и бюджет;
|
||||
geometry/cache объёмного вида не создаются.
|
||||
2. **AC2 (`unit` + `smoke`):** флаг включается query/hash по §2.2.1, реактивно
|
||||
переживает навигацию и снимается через `-iso`/`off` без переписывания URL.
|
||||
3. **AC3 (`unit`):** malformed registry/version и достигнутый `expires`
|
||||
fail-closed; ни URL, ни storage не включают мёртвый флаг.
|
||||
4. **AC4 (`unit` + `smoke` + `golden`):** Labs View использует один почти
|
||||
верхний ортографический ракурс: `rotDeg = 0`, tilt 18–22°, без перспективы;
|
||||
план не повёрнут диагонально, комнаты не перекрыты стенами, flat default.
|
||||
5. **AC5 (`unit` + `golden`):** physical walls, partitions и columns имеют
|
||||
непрерывные top/visible side faces O(E); virtual boundaries остаются flat.
|
||||
6. **AC6 (`unit` + `golden`):** door/window/gate opening — full-height gap без
|
||||
top/side strip внутри; jamb faces присутствуют, независимые extra bodies не
|
||||
вырезаются.
|
||||
7. **AC7 (`unit` + `smoke` + `golden`):** room fills/hover, Glow/spill, солнце,
|
||||
backdrop/decor, furniture и vacuum сохраняют state, source count, порядок,
|
||||
actions и barrier semantics между flat/iso; HA-only update не rebuild-ит
|
||||
geometry; второго light layer нет.
|
||||
8. **AC8 (`unit` + `smoke`):** SVG floor, markers, room labels/cards и native
|
||||
hit targets используют один projection snapshot; anchor error ≤1 CSS px;
|
||||
toggle сохраняет scalar zoom и logical floor center.
|
||||
9. **AC9 (`smoke`):** все редакторы flat; View → editor → View, space change и
|
||||
warm-remount не смешивают projections, не меняют config/history/view intent.
|
||||
10. **AC10 (`unit` + `smoke`):** renderer/projection exception даёт latched flat
|
||||
fallback на fingerprint, отражается кнопкой, не стирает preference и не
|
||||
повторяется на каждом HA update.
|
||||
11. **AC11 (`performance`):** профиль §8.2 зелёный на exact SHA; pan/zoom и HA
|
||||
update не recompute geometry, flat path остаётся в noise budget.
|
||||
12. **AC12 (`unit` + `smoke` + code review):** plan schema/backend/import-export
|
||||
не меняются; `houseplan-space-card` остаётся flat; Labs не создаёт network
|
||||
calls и не гейтит migrations.
|
||||
13. **AC13 (`unit` + `smoke` + code review):** Stage 1 сохраняет нынешние
|
||||
floor-plane opening symbols и states; vertical leaf/window panels, floor
|
||||
edges, new window light и reference-grade materials отсутствуют.
|
||||
14. **AC14 (`smoke` + `golden`):** desktop View, touch View и kiosk полностью
|
||||
работоспособны; toggle ≥44×44, pinch/tap/long-press/space/orientation/
|
||||
background/remount безопасны; touch editors остаются flat/not exposed.
|
||||
15. **AC15 (code review):** `SCOPE`, issue, spec, internal Labs/ISO docs и
|
||||
`STATUS` согласованы; en+ru i18n ключи toggle перечислены; README,
|
||||
User Guide и оба changelog не обещают скрытую функцию.
|
||||
|
||||
## 13. Артефакты этапа
|
||||
|
||||
@@ -545,6 +664,8 @@ WebKit; причины отказа от проигравшего прототи
|
||||
|
||||
### 13.2 Документы
|
||||
|
||||
- `docs/SCOPE.md` — узкое owner-approved исключение для детерминированного
|
||||
2.5D без расширения в photorealistic/free-camera/interior editor;
|
||||
- `docs/ISOMETRIC.md` — внутреннее описание координат, проекции, топологии
|
||||
граней и ограничений;
|
||||
- запись про Labs в `docs/DEVELOPMENT.md` и `AGENTS.md`: как включать, как
|
||||
@@ -553,10 +674,59 @@ WebKit; причины отказа от проигравшего прототи
|
||||
- issue #89: ссылка на это ТЗ как на нормативное, синхронизация scope и
|
||||
acceptance criteria, Project остаётся в `Todo` до фактического старта. Issue
|
||||
не закрывается после ADR — только после всех AC этапа (T5).
|
||||
- После зелёного Stage 1 — отдельная feature issue `S1-new` для Stage 2/public
|
||||
rollout; в ней хранятся новые референсы владельца и решения о vertical
|
||||
doors/windows, materials, shadows/floor edges и публичном UX.
|
||||
|
||||
Не трогаются: `README.md`, `README.ru.md`, `docs/USER-GUIDE.ru.md`,
|
||||
`docs/CHANGELOG.md`, `docs/CHANGELOG.ru.md`.
|
||||
|
||||
### 13.3 Предполагаемые файлы реализации
|
||||
|
||||
Точный список подтверждается ADR, но code review ожидает как минимум:
|
||||
|
||||
- новый pure geometry/projection слой: `src/iso-projection.ts` и
|
||||
`src/iso-walls.ts` либо эквивалентные модули без Lit/HA;
|
||||
- reusable Labs resolver `src/labs.ts`;
|
||||
- интеграцию только в `src/houseplan-card.ts`, `src/styles.ts`,
|
||||
`src/i18n/en.json`, `src/i18n/ru.json`; `src/space-card.ts` и
|
||||
`src/space-render.ts` разрешены только для negative/source-contract tests,
|
||||
не для iso-rendering;
|
||||
- unit: новые `test/iso-*.test.mjs`, `test/labs.test.mjs` и узкие
|
||||
source-contract/regression additions;
|
||||
- browser: целевые `demo/smoke_isometric_*.mjs`, touch/warm/live-layer paths;
|
||||
- golden matrix/harness и **новые** iso baselines, принимаемые отдельно только
|
||||
по reviewed Linux artifact; существующие flat baselines не обновляются;
|
||||
- performance profile/budget `large-house-isometric-v1` и workflow wiring;
|
||||
- `docs/ISOMETRIC.md`, `docs/DEVELOPMENT.md`, `AGENTS.md`, `docs/STATUS.md`.
|
||||
|
||||
Backend Python, manifest/HACS metadata, config schema, import/export и package
|
||||
dependencies не меняются. Новая runtime dependency требует возврата в S3 и
|
||||
отдельного архитектурного решения.
|
||||
|
||||
### 13.4 i18n, compatibility и security
|
||||
|
||||
- Новые ключи только для toggle: `view.volumetric` и `view.flat` либо
|
||||
эквивалентные согласованные имена, одновременно EN/RU. Текст берётся из
|
||||
действующей терминологии: «Объёмный вид» / «Плоский вид» и “Volumetric view” /
|
||||
“Flat view”.
|
||||
- Config/schema migration отсутствует; новые localStorage keys namespaced и
|
||||
fail-soft, удаление keys полностью откатывает пользовательское состояние.
|
||||
- Labs parser принимает только известные registry ids, не исполняет и не
|
||||
логирует произвольный input; diagnostics не содержат entity ids, URLs,
|
||||
config или персональные данные.
|
||||
- Новый renderer не создаёт service calls. Все safe actions и единственная
|
||||
sanctioned lock surface остаются прежними.
|
||||
|
||||
### 13.5 Откат
|
||||
|
||||
Пользовательский аварийный откат без новой сборки: `?hp-labs=-iso` или
|
||||
`?hp-labs=off`; flat View немедленно становится effective, сохранённый iso не
|
||||
воскрешается warm-state. Полный code rollback — revert одного принятого
|
||||
behavior commit/серии #89 и удаление `iso` из Labs registry; plan/config/backend
|
||||
данные не требуют обратной миграции. Если Stage 1 ломает flat path, Labs flag
|
||||
не считается достаточным смягчением: issue возвращается в S6 и beta блокируется.
|
||||
|
||||
## 14. Вне этапа 1
|
||||
|
||||
- Кнопка и любые пользовательские упоминания вне флага.
|
||||
@@ -566,3 +736,15 @@ WebKit; причины отказа от проигравшего прототи
|
||||
- Объёмный вид в `houseplan-space-card`.
|
||||
- Редактирование в перспективе, пользовательская высота, 3D-мебель, WebGL.
|
||||
- YAML-опция карточки для Labs.
|
||||
|
||||
## 15. Принятые предположения — можно изменить без пересмотра продукта
|
||||
|
||||
1. Имена pure modules и i18n keys из §13.3–13.4 предварительные; review может
|
||||
выбрать более согласованные имена без изменения поведения.
|
||||
2. Точная wall height, `zScale`, palette и side-face contrast выбираются ADR
|
||||
внутри ограничений §4.2 и требуют новых iso golden, но не нового owner
|
||||
decision.
|
||||
3. LocalStorage keys версионируются суффиксом `_v1`; внутренняя форма может
|
||||
меняться до публичного Stage 2, если чтение malformed/old данных fail-soft.
|
||||
4. Stage 2 issue создаётся после зелёного code review/интеграции Stage 1, не
|
||||
обязательно после beta; закрытие самой #89 всё равно следует beta-процессу.
|
||||
|
||||
@@ -43,7 +43,7 @@ GitHub Issues и GitHub Projects (v2) остаются единственным
|
||||
| [#50](https://github.com/Matysh/houseplan-card/issues/50) Экспорт и импорт конфигурации | [050-config-export-import.md](050-config-export-import.md) | реализовано локально; проверки на следующем пре-релизе |
|
||||
| [#58](https://github.com/Matysh/houseplan-card/issues/58) Vacuum integration coverage — Stage 1 | [058-vacuum-stage1.md](058-vacuum-stage1.md) | в реализации |
|
||||
| [#89](https://github.com/Matysh/houseplan-card/issues/89) Опциональный объёмный 2.5D/изометрический вид | [089-isometric-view.md](089-isometric-view.md) | исследование завершено; продуктовый контекст |
|
||||
| [#89](https://github.com/Matysh/houseplan-card/issues/89) Этап 1: объёмный вид за флагом Labs | [089-isometric-view-stage1.md](089-isometric-view-stage1.md) | готово к реализации |
|
||||
| [#89](https://github.com/Matysh/houseplan-card/issues/89) Этап 1: объёмный вид за флагом Labs | [089-isometric-view-stage1.md](089-isometric-view-stage1.md) | ТЗ на ревью, ревизия 3 |
|
||||
| [#98](https://github.com/Matysh/houseplan-card/issues/98) Единая система пульсаций и активностей устройства | [098-device-pulse-system.md](098-device-pulse-system.md) | реализовано локально; ожидает prerelease/CI gate |
|
||||
|
||||
## P2
|
||||
|
||||
Reference in New Issue
Block a user