mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 05:08:53 +00:00
docs(spec): define grid-scale visual invariance
Issue: #239 User-Visible: no
This commit is contained in:
@@ -0,0 +1,480 @@
|
||||
# Issue #239 — масштаб сетки не меняет внешний вид плана
|
||||
|
||||
- Дата: 2026-08-22
|
||||
- Тип: bug · приоритет P1 · пользовательская ценность 9/10
|
||||
- Сложность 8/10 · риск 8/10 · обычный трек
|
||||
- Issue: [#239](https://github.com/Matysh/houseplan-card/issues/239)
|
||||
- Ветка: `issue/239-grid-scale-invariance`
|
||||
|
||||
Канонические документы: `docs/SCOPE.md`, `docs/CANVAS.md`,
|
||||
`docs/WALL-THICKNESS.md`, `docs/TOUCH-SUPPORT.md`,
|
||||
`docs/CONFIG-COMPATIBILITY.md`, `docs/USER-GUIDE.ru.md`.
|
||||
|
||||
Связанная реализованная задача: [#230](https://github.com/Matysh/houseplan-card/issues/230)
|
||||
зафиксировала физический шаг штриховки стен и является подмножеством этого
|
||||
контракта.
|
||||
|
||||
## 1. Сценарий и персона
|
||||
|
||||
Администратор дома создаёт новый этаж в desktop-редакторе и выбирает точность
|
||||
сетки. Для подробного плана квартиры ему нужен шаг 1 см, а для старого плана
|
||||
может оставаться 5 см. В имперской системе тот же новый этаж начинается с шага
|
||||
1 дюйм.
|
||||
|
||||
При одинаковых физических размерах комнат, стен, проёмов и объектов человек
|
||||
должен видеть один и тот же план. Выбор более мелкой сетки даёт больше доступных
|
||||
координат для точного редактирования, но не превращает створки дверей, контуры,
|
||||
подсказки или изометрические стены в более тонкие и мелкие элементы.
|
||||
|
||||
Задача поддерживает J4 и J6 из `docs/SCOPE.md`: точный план без внешнего CAD и
|
||||
предсказуемое обслуживание существующей схемы.
|
||||
|
||||
## 2. Что человек увидит до и после
|
||||
|
||||
**До:** на физически одинаковом плане при `cell_cm: 1` часть элементов выглядит
|
||||
в несколько раз тоньше или меньше, чем при `cell_cm: 5`. Особенно заметны
|
||||
створки и дуги проёмов, контуры комнат и часть линий/узлов редактора. Новое
|
||||
пространство всегда предлагает 5 см на клетку, а в имперском интерфейсе поле
|
||||
масштаба всё равно выражено в сантиметрах.
|
||||
|
||||
**После:** физически одинаковые планы при 1 и 5 см на клетку выглядят одинаково
|
||||
во View, Plan, Devices, Background, static/embedded card и скрытой изометрии.
|
||||
Различаются только плотность сетки и точность snap. Новое пространство начинает
|
||||
с 1 см на клетку в metric HA и с 1 дюйма на клетку в imperial HA. Старые
|
||||
пространства и сохранённые значения не переписываются.
|
||||
|
||||
## 3. Подтверждённый диагноз
|
||||
|
||||
### 3.1 Что уже масштабируется правильно
|
||||
|
||||
- Толщина стен, перегородок и колонн переводится из cm через
|
||||
`wallCmToUnits()`.
|
||||
- Размеры decor и мебели проходят через cm↔units helpers.
|
||||
- Glow хранит радиус в физических единицах.
|
||||
- #230 сделал шаг и толщину штриховки физическими.
|
||||
- Узлы привязки #137 имеют физический радиус 5/10 см.
|
||||
- Device markers и room labels получают размер через `iconUnit()` / `iconCqw()`;
|
||||
screen-space trail/chrome использует `vector-effect` или расчёт из текущего
|
||||
`view.w / clientWidth`.
|
||||
|
||||
Эти пути нельзя домножать повторно.
|
||||
|
||||
### 3.2 Где инвариант нарушен
|
||||
|
||||
В старом масштабе `cell_cm: 5` в рендере накопились константы в SVG user units.
|
||||
На физически эквивалентном плане с `cell_cm: 1` координаты и frame в пять раз
|
||||
больше, а константы остаются прежними и после одинакового fit становятся в пять
|
||||
раз мельче на экране.
|
||||
|
||||
Подтверждённые группы:
|
||||
|
||||
1. `src/render/opening-symbol.ts`: толщина створок 3/3.5 units, jamb/glass
|
||||
strokes 1.5/2.5, fallback depth и padding outline/hit 4–12 units.
|
||||
2. `src/houseplan-card.ts`: outline/hit rect проёма, offset lock badge,
|
||||
preview/orphan dots, Plan vertices, alignment dots и отдельные SVG strokes.
|
||||
3. `src/styles.ts`: room/open-boundary/wall outlines, opening arc/outline,
|
||||
hover halo, draft/preview/repair lines, dash patterns и часть editor chrome.
|
||||
4. `src/space-render.ts` / `src/space-card.ts`: статические room/wall/opening
|
||||
counterparts с теми же сырыми units.
|
||||
5. Скрытая изометрия: `ISO_WALL_HEIGHT`, `ISO_FLOOR_EDGE_HEIGHT`, shadow offset
|
||||
и SVG blur заданы в user units. При увеличившемся физически эквивалентном
|
||||
плане высота и тени относительно фасада уменьшаются.
|
||||
|
||||
### 3.3 Default и compatibility
|
||||
|
||||
- Ручной create и floors-import draft отдельно задают `cellCm: 5`.
|
||||
- Поле всегда показывает canonical cm и строку `cm per cell`, даже когда
|
||||
`hass.config.unit_system.length === 'mi'`.
|
||||
- Fallback `5` при чтении отсутствующего/некорректного `cell_cm` встречается в
|
||||
frontend, static renderer, optimizer и backend validation. Это legacy
|
||||
compatibility, а не default создания, и меняться не должно.
|
||||
|
||||
## 4. Термины и эталонная эквивалентность
|
||||
|
||||
- **Эталонный масштаб** — `REFERENCE_CELL_CM = 5`; его внешний вид сохраняется.
|
||||
- **Физически эквивалентные пространства** — все координаты и размеры в plan
|
||||
units второго пространства умножены на `k = 5 / cell_cm`, а физические поля в
|
||||
cm не изменены. Layout-позиции, backdrop/decor geometry и camera centre/extent
|
||||
преобразованы тем же `k`.
|
||||
- **Одинаковый camera state** — одинаковый viewport и одинаковый относительный
|
||||
zoom/pan; world-space view второго пространства преобразован через `k`.
|
||||
- **Разрешённое различие** — число видимых/доступных узлов сетки на физический
|
||||
метр и вызванная этим точность snap.
|
||||
- **Visual unit** — legacy SVG-константа, чей нынешний размер при
|
||||
`cell_cm: 5` является эталоном и должен следовать `k`.
|
||||
|
||||
## 5. Границы задачи
|
||||
|
||||
### 5.1 Входит
|
||||
|
||||
- единый pure helper масштаба visual units;
|
||||
- полный аудит SVG-примитивов full/static/embedded renderers;
|
||||
- проёмы вместе с hover/hit geometry и door/gate lock badge position;
|
||||
- Plan editor: saved outlines, previews, snap/repair/alignment/dimension chrome;
|
||||
- Devices и Background editor chrome как регрессионные поверхности;
|
||||
- скрытая изометрия, включая wall/floor height, openings и shadows;
|
||||
- metric/imperial default и единицы поля при создании/редактировании;
|
||||
- manual create и floors-import;
|
||||
- светлая/тёмная тема, desktop и touch safety floor;
|
||||
- документация, EN/RU i18n, оба changelog и целевые тесты.
|
||||
|
||||
### 5.2 Не входит
|
||||
|
||||
- изменение `GRID_N`, `GRID_PITCH`, координатной модели или snap algorithm;
|
||||
- миграция/перезапись существующих `cell_cm`;
|
||||
- изменение legacy fallback `5` для отсутствующего значения;
|
||||
- изменение физических размеров стен, decor, мебели, Glow или пользовательских
|
||||
icon/label multipliers;
|
||||
- изменение зум-контракта: visual units продолжают масштабироваться вместе с
|
||||
планом так же, как при `cell_cm: 5`, а не становятся screen-fixed;
|
||||
- новый UI включения изометрии;
|
||||
- постоянные размерные подписи из #52;
|
||||
- расширение поддерживаемого диапазона `cell_cm` 0.1…1000.
|
||||
|
||||
## 6. Классификация размеров
|
||||
|
||||
Каждый затронутый размер относится ровно к одному классу.
|
||||
|
||||
| Класс | Примеры | Правило |
|
||||
|---|---|---|
|
||||
| Physical | wall/partition/column cm, decor width/text, furniture, Glow radius, hatch #230, snap-node 5/10 cm | Уже переводится через `cell_cm`; не домножать |
|
||||
| Screen | HTML labels/icons, `vector-effect: non-scaling-stroke`, px-derived hit/handles, vacuum trail | Оставить screen-fixed |
|
||||
| Plan-relative | device/room-label size через `iconUnit`, content padding как доля frame, room corner radius как доля geometry | Масштабируется своей геометрией; не домножать |
|
||||
| Visual unit | legacy raw SVG constants, эталонные при `cell_cm: 5` | Домножить на `visualScale(cell_cm)` |
|
||||
| Grid | pitch, adaptive density, snap quantum | Не домножать; это единственное ожидаемое различие |
|
||||
|
||||
Слепой множитель на весь SVG запрещён: он повторно увеличит physical и
|
||||
plan-relative размеры.
|
||||
|
||||
## 7. Контракт visual units
|
||||
|
||||
Новый pure module, рекомендуемое имя `src/grid-scale.ts`:
|
||||
|
||||
```ts
|
||||
export const GRID_VISUAL_REFERENCE_CELL_CM = 5;
|
||||
|
||||
export function gridVisualScale(cellCm: unknown): number;
|
||||
export function gridVisualUnits(baseUnits: number, cellCm: unknown): number;
|
||||
export function newSpaceCellCm(imperial: boolean): number;
|
||||
```
|
||||
|
||||
### 7.1 `gridVisualScale`
|
||||
|
||||
- валидное положительное `cellCm`: `5 / cellCm`;
|
||||
- `5` возвращает ровно `1` без накопления погрешности;
|
||||
- `NaN`, infinity, `0`, отрицательное и нечисловое значение дают `1`, то есть
|
||||
legacy fallback 5;
|
||||
- отдельного clamp нет: поддерживаемый диапазон уже ограничен 0.1…1000, а clamp
|
||||
нарушил бы эквивалентность на законных значениях.
|
||||
|
||||
### 7.2 Применение в CSS и SVG
|
||||
|
||||
Full card и static card выставляют на корне соответствующего пространства
|
||||
unitless custom property `--hp-cell-visual-scale`. Scale-sensitive CSS lengths
|
||||
используют её; геометрические attributes и TypeScript-расчёты вызывают
|
||||
`gridVisualUnits()`.
|
||||
|
||||
Fallback custom property равен `1`, чтобы отдельный renderer или старый тестовый
|
||||
host без переменной сохранял исторический `cell_cm: 5` вид.
|
||||
|
||||
Фактор вычисляется один раз на пространство/рендер. Запрещено заново обходить
|
||||
геометрию или делать plan-wide polyclip ради визуального масштаба.
|
||||
|
||||
### 7.3 Инвариант `cell_cm: 5`
|
||||
|
||||
При `cell_cm: 5` итоговые численные geometry attributes и computed styles
|
||||
должны совпасть с состоянием до #239. Замена `2.5` на выражение, которое в
|
||||
Chromium вычисляется не в те units, считается регрессией даже при близком
|
||||
внешнем виде.
|
||||
|
||||
## 8. Контракт поверхностей
|
||||
|
||||
### 8.1 Flat View
|
||||
|
||||
- room borders, wall-body outline, open boundaries и room hover сохраняют
|
||||
эталонную толщину/halo;
|
||||
- door/window/gate leaf, arc, glass, jamb и passage boundaries сохраняют
|
||||
геометрию и толщину;
|
||||
- opening lock badge остаётся на том же относительном отступе от стены;
|
||||
- sun/Glow/device/value badge/room label/vacuum сохраняют текущий контракт без
|
||||
повторного scale.
|
||||
|
||||
### 8.2 Opening interaction
|
||||
|
||||
- `openingVisibleMetrics()` масштабирует только fallback/padding visual units;
|
||||
физический `jambHalf` от толщины стены остаётся physical;
|
||||
- outline и hit rectangle масштабируются тем же factor, включая corner radius;
|
||||
- hover появляется и click/double-click/drag срабатывают во всей той же видимой
|
||||
области на экране, что при эквивалентном `cell_cm: 5`;
|
||||
- preview и committed symbol читают один helper и не расходятся.
|
||||
|
||||
### 8.3 Plan editor
|
||||
|
||||
- контуры, active/draft/preview/repair/alignment lines, vertices и orphan/
|
||||
opening-preview markers сохраняют эталонный экранный footprint при одинаковом
|
||||
относительном zoom;
|
||||
- физические 5/10-см snap nodes остаются физическими; их screen-fixed strokes
|
||||
остаются screen-fixed;
|
||||
- dimension lines/ticks с `vector-effect` и HTML labels не получают второй
|
||||
scale;
|
||||
- grid pitch не меняется. При одинаковой физической длине метрический 1-см план
|
||||
содержит в пять раз больше snap intervals, чем 5-см план.
|
||||
|
||||
### 8.4 Devices и Background
|
||||
|
||||
- marker, room label, LQI/value/lock satellites и capsules сохраняют размер и
|
||||
pointer/action area;
|
||||
- decor/furniture physical geometry не домножается;
|
||||
- backdrop/decor/resize/physical selection frames и handles сохраняют текущий
|
||||
screen-space либо px-derived контракт;
|
||||
- ни один editor gesture, pointer capture, pan/pinch/cancel path не меняется.
|
||||
|
||||
### 8.5 Static/embedded card
|
||||
|
||||
`renderSpaceStatic()` выставляет тот же factor и использует те же opening
|
||||
metrics/styles. Одинаковая fixture не может быть правильной в full card и иной
|
||||
в `houseplan-space-card`.
|
||||
|
||||
### 8.6 Скрытая изометрия
|
||||
|
||||
- wall height, floor-edge depth, opening height/basis и geometry-dependent
|
||||
shadow offsets умножаются на factor;
|
||||
- SVG blur/translate в user units масштабируется так же; screen-fixed strokes
|
||||
с `vector-effect` остаются без дополнительного множителя;
|
||||
- factor входит в geometry fingerprint/cache key через фактически переданные
|
||||
высоты; warm remount не может вернуть geometry другого `cell_cm`;
|
||||
- icon/label projection и actions остаются прежними;
|
||||
- Labs-функция остаётся скрытой и публичного переключателя не получает.
|
||||
|
||||
## 9. Новый default и imperial projection
|
||||
|
||||
### 9.1 Хранение
|
||||
|
||||
`cell_cm` остаётся canonical числом сантиметров на клетку.
|
||||
|
||||
- новый metric draft: `1`;
|
||||
- новый imperial draft: `2.54` (ровно 1 inch);
|
||||
- manual create и каждый элемент floors import используют один
|
||||
`newSpaceCellCm(this._imperial)`;
|
||||
- save продолжает записывать canonical cm.
|
||||
|
||||
### 9.2 Поле диалога
|
||||
|
||||
- metric: значение в cm, подпись «см на клетку» / `cm per cell`;
|
||||
- imperial: значение в inches, подпись «дюйм на клетку» / `in per cell`;
|
||||
- ввод inches переводится в canonical cm до validation/save;
|
||||
- min/max в поле также проецируются в текущую систему единиц.
|
||||
|
||||
### 9.3 Lossless edit
|
||||
|
||||
Открытие и сохранение существующего пространства без изменения поля не меняет
|
||||
его canonical `cell_cm`, в том числе в imperial HA. Округлённая строка UI не
|
||||
становится новым значением сама по себе: draft хранит исходное canonical число
|
||||
и отдельный признак/текст пользовательского редактирования либо эквивалентный
|
||||
lossless механизм.
|
||||
|
||||
Отсутствующий `cell_cm` продолжает читаться и при save materialize как 5 см.
|
||||
Новый default нельзя использовать как read fallback.
|
||||
|
||||
## 10. Данные, migration, i18n, a11y, privacy и security
|
||||
|
||||
- Schema и формат данных не меняются; миграции нет.
|
||||
- Новые EN/RU строки нужны для imperial unit label; существующий metric текст
|
||||
сохраняется.
|
||||
- Поле остаётся обычным label+number input; доступное имя и порядок фокуса не
|
||||
меняются.
|
||||
- Никаких новых данных HA, service calls, URL или файловых операций.
|
||||
- Privacy/security без изменений.
|
||||
|
||||
## 11. Touch contract
|
||||
|
||||
View и kiosk остаются полностью поддержанными. Editors остаются desktop-first,
|
||||
но safety floor из `docs/TOUCH-SUPPORT.md` обязателен:
|
||||
|
||||
- opening hit/hover/action area не уменьшается из-за `cell_cm`;
|
||||
- pan, pinch, second pointer, `pointercancel` и suppressed click ничего не
|
||||
сохраняют и не запускают;
|
||||
- screen-derived handles не переводятся ошибочно в physical/visual units;
|
||||
- никаких новых hover-only действий.
|
||||
|
||||
## 12. Performance
|
||||
|
||||
- допустим один scalar factor на пространство и дешёвые умножения при render;
|
||||
- новые plan-wide обходы, boolean geometry, layout reads и HA state dependencies
|
||||
запрещены;
|
||||
- существующие structural caches сохраняются; iso fingerprint различает
|
||||
фактические scaled heights;
|
||||
- large-house benchmark и hidden-iso benchmark проверяются перед бетой по
|
||||
общему release-процессу, не в цикле реализации.
|
||||
|
||||
## 13. Acceptance criteria
|
||||
|
||||
**AC1.** `gridVisualScale(5) === 1`; для 1, 2.54, 10 и 25 результат равен
|
||||
`5 / cell_cm`; invalid input даёт 1. `gridVisualUnits(base, cell)` применяет
|
||||
ровно тот же factor.
|
||||
|
||||
**AC2.** Физически эквивалентная flat View fixture при `cell_cm: 5` и
|
||||
`cell_cm: 1` в одном viewport и camera state имеет одинаковые browser pixels
|
||||
для комнат, masonry, partition/column, door/window/gate/passage, decor,
|
||||
devices/labels, Glow и sun. Grid во View отсутствует.
|
||||
|
||||
**AC3.** Opening leaf/arc/glass/jamb, outline и hit rectangle дают одинаковые
|
||||
screen bounding boxes/stroke widths на эквивалентных планах. Hover, click,
|
||||
double-click и drag срабатывают в одинаковой внешней области; preview и
|
||||
committed symbol совпадают.
|
||||
|
||||
**AC4.** Plan editor после маскирования grid paint даёт одинаковый raster/DOM
|
||||
footprint для saved outlines, active/draft/thick preview, vertices,
|
||||
snap/repair/alignment guides, opening preview и dimensions. При этом raw grid
|
||||
содержит 100 intervals на метр при 1 см и 20 при 5 см.
|
||||
|
||||
**AC5.** Physical snap nodes остаются диаметром 10/20 см, decor/furniture stroke
|
||||
и size остаются заданными cm, hatch остаётся 9.6 см по #230, Glow radius не
|
||||
меняется, а device/room-label size продолжает вычисляться через `iconCqw`.
|
||||
Тест обязан падать при повторном применении visual factor к любому из этих
|
||||
контрольных путей.
|
||||
|
||||
**AC6.** Devices и Background editor selection frames, visible knobs и
|
||||
screen-derived hit handles имеют одинаковый screen footprint на эквивалентных
|
||||
планах; pointer sequence не меняет сохранённую geometry без положенного commit.
|
||||
|
||||
**AC7.** `houseplan-space-card` на тех же двух fixtures совпадает по pixels и
|
||||
critical DOM metrics, включая rooms, wall body и opening symbols.
|
||||
|
||||
**AC8.** Скрытая изометрия при 1 и 5 см совпадает по wall/floor/opening height,
|
||||
shadow extent и raster; projected icons/labels остаются над теми же объектами.
|
||||
Light/dark проверяются отдельно. Isometric toggle остаётся Labs-only.
|
||||
|
||||
**AC9.** Ручное создание нового пространства показывает и сохраняет:
|
||||
metric — `1 cm/cell`, imperial — `1 in/cell` и canonical `cell_cm: 2.54`.
|
||||
|
||||
**AC10.** Floors import использует те же defaults для каждого создаваемого
|
||||
пространства и не возвращается к hardcoded 5.
|
||||
|
||||
**AC11.** Existing `cell_cm: 5`, произвольное дробное значение и legacy space
|
||||
без поля при open→save без редактирования не получают новый default и не
|
||||
дрейфуют при imperial projection. Legacy missing value материализуется как 5.
|
||||
|
||||
**AC12.** Metric/imperial label, input value, min/max и conversion соответствуют
|
||||
системе единиц; переключение языка не меняет canonical draft.
|
||||
|
||||
**AC13.** На `cell_cm: 5` все scale-sensitive geometry attributes и computed
|
||||
styles совпадают с pre-#239 contract; current golden не требует принятия
|
||||
необъяснённых изменений. Изменение screenshot диалога создания из 5 в 1 —
|
||||
ожидаемый отдельный user-visible diff.
|
||||
|
||||
**AC14.** Ни View/kiosk tap, ни editor pan/pinch/pointercancel не получают новых
|
||||
действий; opening action area не меньше эталонной.
|
||||
|
||||
**AC15.** Новых plan-wide geometry passes и state-dependent cache invalidations
|
||||
нет; factor вычисляется O(1) на пространство.
|
||||
|
||||
**AC16.** EN/RU user guide и оба changelog объясняют: внешний вид не зависит от
|
||||
шага сетки, default новых пространств 1 см/1 дюйм, существующие значения не
|
||||
мигрируют.
|
||||
|
||||
## 14. План автотестов
|
||||
|
||||
### 14.1 Unit
|
||||
|
||||
- новый `test/grid-scale.test.mjs`: AC1, AC9–AC12;
|
||||
- opening-symbol tests: scaled leaf/jamb/padding/hit metrics и отсутствие
|
||||
double-scale physical jamb;
|
||||
- iso projection/geometry tests: scaled height/depth/cache fingerprint;
|
||||
- policy assertions на physical/screen control paths из AC5.
|
||||
|
||||
### 14.2 Browser smoke
|
||||
|
||||
Новый `demo/smoke_grid_scale_invariance.mjs` строит пару из одной rich fixture:
|
||||
|
||||
- `cell_cm: 5`, reference coordinates;
|
||||
- `cell_cm: 1`, все plan/layout/camera coordinates ×5, physical cm без изменений.
|
||||
|
||||
Один прогон проверяет flat View light/dark, Plan states с grid mask,
|
||||
Devices/Background selection, static card и hidden iso. Он сравнивает реальные
|
||||
browser pixels через canvas и critical DOM metrics, а не только наличие классов.
|
||||
Разрешённая tolerance должна быть нулевой либо обоснованной только
|
||||
subpixel-antialiasing; она не может скрывать систематическую разницу толщины.
|
||||
|
||||
Отдельный `demo/smoke_space_scale_defaults.mjs` проверяет manual create,
|
||||
floors-import, metric/imperial labels, canonical save и lossless existing edit.
|
||||
|
||||
Существующие целевые smokes запускаются по изменённым символам: opening preview/
|
||||
measure, plan snap, physical editor, decor, static card и isometric Stage 2/3.
|
||||
|
||||
### 14.3 Golden и performance
|
||||
|
||||
В цикле реализации — только typecheck, unit, build и named smokes. Полный golden,
|
||||
smoke suite и performance — перед бетой по каноническому процессу. Golden
|
||||
baseline разработчик не принимает. Public docs capture переснимается в задаче,
|
||||
потому что create-dialog законно меняет default.
|
||||
|
||||
## 15. Mutation gate
|
||||
|
||||
| id | Что ломает | Гвард |
|
||||
|---|---|---|
|
||||
| `grid-scale-visual-factor-constant` | factor всегда 1 | unit + pixel smoke |
|
||||
| `grid-scale-visual-factor-inverted` | `cell/5` вместо `5/cell` | unit + pixel smoke |
|
||||
| `grid-scale-opening-symbol-unscaled` | leaf/jamb visual constants остаются raw | opening unit/smoke |
|
||||
| `grid-scale-opening-hit-unscaled` | outline/hit padding остаётся raw | interaction smoke |
|
||||
| `grid-scale-plan-chrome-unscaled` | Plan line/node visual unit не следует factor | Plan pixel smoke |
|
||||
| `grid-scale-static-factor-missing` | static root не получает factor | static comparison |
|
||||
| `grid-scale-iso-height-unscaled` | iso height/depth остаются constants | iso unit/pixel smoke |
|
||||
| `grid-scale-metric-default-five` | metric create снова 5 | default smoke |
|
||||
| `grid-scale-imperial-default-wrong` | imperial create хранит 1 cm либо 5 cm | unit/default smoke |
|
||||
| `grid-scale-legacy-fallback-one` | read fallback меняется с 5 на новый default | compatibility unit |
|
||||
| `grid-scale-imperial-roundtrip-drift` | rounded UI string перезаписывает canonical value | default smoke |
|
||||
| `grid-scale-physical-double-scaled` | wall/decor/Glow/snap physical path получает второй factor | AC5 unit/smoke |
|
||||
|
||||
## 16. Риски и защита
|
||||
|
||||
| Риск | Вероятность / ущерб | Защита |
|
||||
|---|---|---|
|
||||
| Общий CSS factor повторно масштабирует physical элементы | средняя / высокий | классификация §6, negative controls AC5 |
|
||||
| `px`/unitless `calc()` в SVG вычислится не в user units | средняя / высокий | exact `cell_cm:5` DOM + raster и pair pixel smoke |
|
||||
| Hover визуально совпадёт, а hitbox останется маленьким | высокая / высокий | AC3 проверяет реальные pointer points по краю capsule |
|
||||
| Imperial open/save округлит 5 см в 5.0038 см | высокая / средний | untouched canonical draft + AC11/mutant |
|
||||
| Default поменяется только в одном create path | высокая / средний | manual + floors-import AC9/AC10 |
|
||||
| Изометрический cache вернёт старую высоту | средняя / высокий | scaled input в fingerprint + warm-remount test |
|
||||
| Dynamic grid затруднит pixel comparison Plan | высокая / низкий | grid paint маскируется, density проверяется отдельно |
|
||||
| Широкий CSS audit изменит `cell_cm:5` pixels | средняя / высокий | reference exactness AC13, без baseline acceptance |
|
||||
| Touch target станет physical вместо screen-equivalent | средняя / высокий | edge pointer smoke + TOUCH-SUPPORT safety floor |
|
||||
|
||||
## 17. Release-артефакты
|
||||
|
||||
`User-Visible: yes`:
|
||||
|
||||
- `docs/CHANGELOG.md` и `docs/CHANGELOG.ru.md` в одном продуктовом коммите;
|
||||
- `docs/USER-GUIDE.md` и `docs/USER-GUIDE.ru.md`: scale field/default и
|
||||
визуальный инвариант;
|
||||
- `docs/CANVAS.md`: taxonomy размеров и новый default; убрать утверждения
|
||||
«default 5» там, где речь именно о новых пространствах, сохранив legacy
|
||||
fallback;
|
||||
- `docs/ARCHITECTURE.md`: актуализировать описание `cell_cm` default;
|
||||
- `docs/TESTING.md`: named smoke и ручная матрица 1/5 cm + imperial;
|
||||
- public docs screenshot create-space переснять через `demo/docs/capture.mjs`;
|
||||
- `docs/images/screenshots.json` обновить тем же capture;
|
||||
- golden/performance artifacts — только в предрелизном прогоне.
|
||||
|
||||
Три поставляемых `houseplan-card.js` собираются и коммитятся вместе с
|
||||
реализацией, должны быть побайтно одинаковы.
|
||||
|
||||
## 18. Откат
|
||||
|
||||
Один revert продуктового коммита возвращает прежние visual constants и default
|
||||
5. Миграции данных и обратной миграции нет: пространства, созданные во время
|
||||
действия версии с `cell_cm: 1`/`2.54`, остаются валидными обычными пространствами
|
||||
и после отката.
|
||||
|
||||
## 19. Принятые предположения — технические, менять свободно
|
||||
|
||||
1. Pure helper и CSS property названы `gridVisualScale` и
|
||||
`--hp-cell-visual-scale`; reviewer может предложить другое имя без изменения
|
||||
продукта.
|
||||
2. Lossless imperial edit реализуется через canonical value + touched/display
|
||||
draft. Эквивалентный механизм допустим, если AC11 доказан.
|
||||
3. Pair screenshot smoke использует динамическую вторую fixture вместо новых
|
||||
постоянных golden baselines: это проверяет именно инвариант и не требует
|
||||
принятия эталонов разработчиком.
|
||||
4. Scale-sensitive CSS меняется адресно по таблице §6. Общий transform всего
|
||||
renderer запрещён независимо от удобства реализации.
|
||||
@@ -65,6 +65,7 @@ GitHub Issues и GitHub Projects (v2) остаются единственным
|
||||
| [#226](https://github.com/Matysh/houseplan-card/issues/226) Entity-marker не дублируется родительским HA-устройством | [226-entity-parent-dedup.md](226-entity-parent-dedup.md) |
|
||||
| [#223](https://github.com/Matysh/houseplan-card/issues/223) Optimize канонизирует координаты без floating-point шума | [223-optimize-coordinate-canonicalization.md](223-optimize-coordinate-canonicalization.md) |
|
||||
| [#228](https://github.com/Matysh/houseplan-card/issues/228) Надёжное рисование стен и операции с готовым контуром | [228-plan-drawing-problems.md](228-plan-drawing-problems.md) |
|
||||
| [#239](https://github.com/Matysh/houseplan-card/issues/239) Масштаб сетки не меняет внешний вид плана; default 1 см/1 дюйм | [239-grid-scale-invariance.md](239-grid-scale-invariance.md) |
|
||||
|
||||
## P2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user