mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-08 07:29:13 +00:00
@@ -45,6 +45,29 @@ centimetres, screen-fixed strokes/handles, plan-relative icon sizes and the
|
||||
grid pitch must not receive that factor again. Full, static and hidden
|
||||
isometric renderers share this classification.
|
||||
|
||||
### Persisted coordinate canonicalisation
|
||||
|
||||
Every current config/layout write removes IEEE-754 representation tails from
|
||||
persisted geometry by rounding an explicit allow-list to nine decimal places.
|
||||
This is not grid snapping: an off-grid or diagonal coordinate stays where the
|
||||
editor put it, with a maximum normalized change of `5e-10`. The contract is
|
||||
mirrored in Python and TypeScript and normalizes negative zero.
|
||||
|
||||
The allow-list covers room outlines/extents, exact wall endpoints, openings
|
||||
(including angle, length and hosted `t`), decor transforms, drafts,
|
||||
partitions, columns, open spans, backdrop transforms, marker angle and layout
|
||||
`x/y`. It deliberately excludes `cell_cm`, `plan_aspect`, `view_box`,
|
||||
physical centimetre fields, colours/opacities/live values, presentation scales
|
||||
and vacuum affine calibration. Unknown/future numeric fields round-trip
|
||||
unchanged.
|
||||
|
||||
Schema validation is the public door; the common config/layout storage helpers
|
||||
repeat the same idempotent operation for internal import, maintenance and
|
||||
startup-recovery writers. A canonical read/write echo is a no-op: optimistic
|
||||
locking is still checked, but the revision, update event and maintenance Undo
|
||||
snapshot do not move. Existing stores are not rewritten on read; Optimize Plans
|
||||
remains the explicit bulk-cleanup path.
|
||||
|
||||
## Model
|
||||
|
||||
| Concept | Before | Now |
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Every config and device-layout write now canonicalizes persisted geometry to
|
||||
nine decimal places without snapping it to the grid. This removes invisible
|
||||
floating-point tails before they can break shared walls, room unions or Glow;
|
||||
import, maintenance recovery and server Undo use the same invariant. Repeating
|
||||
an unchanged canonical Save no longer creates a revision or consumes the
|
||||
one-deep Undo snapshot. Existing noisy plans are cleaned on their next write,
|
||||
or immediately through Optimize Plans
|
||||
([#224](https://github.com/Matysh/houseplan-card/issues/224)).
|
||||
|
||||
- Grid precision no longer changes the appearance of the same physical plan.
|
||||
Room and wall outlines, openings and their hit areas, Plan hints, the static
|
||||
card and hidden isometric geometry now retain the `cell_cm: 5` visual size at
|
||||
|
||||
@@ -8,6 +8,16 @@
|
||||
|
||||
## Не выпущено
|
||||
|
||||
- Каждая запись конфигурации и раскладки устройств теперь приводит геометрию к
|
||||
девяти десятичным знакам, не привязывая её к сетке. Невидимые
|
||||
floating-point-хвосты удаляются до того, как смогут сломать общие стены,
|
||||
объединение комнат или Glow; тот же инвариант действует для импорта,
|
||||
восстановления служебных операций и серверной отмены. Повторное сохранение
|
||||
уже канонических данных больше не создаёт ревизию и не съедает одношаговую
|
||||
отмену. Старый план очищается при следующей записи либо сразу через
|
||||
«Оптимизировать планы»
|
||||
([#224](https://github.com/Matysh/houseplan-card/issues/224)).
|
||||
|
||||
- Точность сетки больше не меняет внешний вид одного и того же физического
|
||||
плана. Контуры комнат и стен, проёмы и их зоны попадания, подсказки редактора,
|
||||
статическая карточка и скрытая изометрия сохраняют эталонный вид
|
||||
|
||||
@@ -48,6 +48,27 @@ Unknown future fields remain outside this report and continue to follow the
|
||||
backend's forward-compatibility policy. Absence from the report is therefore
|
||||
not permission to delete a field.
|
||||
|
||||
## Canonical geometry on write (#224)
|
||||
|
||||
Config and layout schemas canonicalize only named geometry numbers to nine
|
||||
decimal places. The common storage helpers repeat the same idempotent contract
|
||||
for internal writers, while the frontend adopts the exact candidate it sends.
|
||||
This prevents ULP noise without changing the schema, JSON number type,
|
||||
model/store version or any user-visible placement.
|
||||
|
||||
The operation is lossless at the product scale and intentionally narrow.
|
||||
`view_box`, `cell_cm`, `plan_aspect`, physical centimetre values,
|
||||
presentation settings, colours, opacity/brightness/temperature, vacuum
|
||||
calibration and unknown/future numeric fields retain their exact input values.
|
||||
No recursive “round every number” migration is allowed.
|
||||
|
||||
Existing stores remain byte-for-byte untouched on read. Their geometry becomes
|
||||
canonical on the next config/layout write; Optimize Plans is the immediate bulk
|
||||
path. Optimize/Import/repair Undo restores the previous semantic geometry and
|
||||
unknown fields in canonical representation, not the invisible noisy IEEE-754
|
||||
tail. A repeated canonical Save with the current revision is a no-op and does
|
||||
not invalidate the one-deep maintenance backup.
|
||||
|
||||
## Open-passage opening type (#157)
|
||||
|
||||
`space.openings[].type` additionally accepts the literal `passage`. Its
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ metadata). Only an explicit owner-approved emergency hotfix may skip this gate.
|
||||
| Item | State |
|
||||
|---|---|
|
||||
| Version | **v1.66.0** everywhere (manifest, const.py, package.json, CARD_VERSION) — stable promotion of the published v1.66.0-beta.1 product line |
|
||||
| Current local cycle | Post-v1.66.0 Unreleased development includes reliable Plan drawing (#228): exact Shift rays, ambiguous-node blocking, active axis/node chrome, room creation from an existing face with an explicit ≤2 cm repair, and room deletion with Keep/Delete walls consequences. Entity/parent marker deduplication (#226) and exact coordinate maintenance (#223) are also included. |
|
||||
| Current local cycle | Post-v1.66.0 Unreleased development includes reliable Plan drawing (#228): exact Shift rays, ambiguous-node blocking, active axis/node chrome, room creation from an existing face with an explicit ≤2 cm repair, and room deletion with Keep/Delete walls consequences. Entity/parent marker deduplication (#226), explicit coordinate maintenance (#223) and canonical geometry on every write (#224) are also included. |
|
||||
| Hidden Labs Stage | #89 Stage 1 ships in v1.63.0-beta.1. #122 Stage 2 ships in v1.64.0 and evolves the same hidden, expiring `iso` experiment with matte walls, a low exterior floor edge, restrained shared shadows and live vertical door/window/gate panels. Flat remains default; editors and `houseplan-space-card` remain flat; live floor effects and HA actions remain unchanged. Public activation remains a separate task. |
|
||||
| Workflow | Superseded 2026-08-12: the pre-1.62 rule of "local edits without tests or commits" is **dead** — since release 1.62 every product change follows `PROCESS.md` (issue in `S5-ready`+, branch `issue/<NN>-slug`, trailers on every commit, review pipeline; `AGENTS.md` is the summary). Release mechanics below remain current. A requested pre-release gets a production build plus the smallest targeted unit/smoke set covering the changed surfaces, one tested `dev` commit/tag and a GitHub Release with `prerelease=true`; `main` stays untouched. The complete local frontend/backend/smoke gate runs only before a stable release, after which `main` is fast-forwarded to the exact tested `dev` SHA and the GitHub Release uses `prerelease=false`. Release bodies are short and bilingual (Russian first): only significant user changes get individual bullets, while minor/code-only work is grouped as `Мелкие исправления и улучшения` / `Small fixes and improvements`; every body ends with separate links to the Russian and English changelogs. Detailed RU/EN changelog bullets may link the corresponding closed GitHub Issues; open or partially delivered issues are never presented as shipped. Telegram announcements are sent only for stable releases; beta and RC publication is silent. `docs/RELEASE-NOTES.md` is the current canonical body instance; `npm run release:prerelease -- <tag> --issues=… --yes` is the primary local publication path and the manual `Publish prerelease` workflow is its GitHub-only equivalent once present on `main`. Nothing is copied to the home instance by hand |
|
||||
| GitHub | https://github.com/Matysh/houseplan-card — [Issues](https://github.com/Matysh/houseplan-card/issues) are the canonical task records; their labels carry priority and workflow status (`PROCESS.md` §9). GitHub Projects is no longer used. `main` carries stable releases; pre-release tags may point directly at `dev`. Work lands on `dev` and is merged into `main` for a stable release, so `dev` is normally equal to or ahead of `main`, never behind. Push via SSH key `ha_jb` (remote git@github.com:…); API releases via the fine-grained PAT in `~/.git-credentials` (Contents R/W, issued 2026-07-23) |
|
||||
|
||||
+14
-1
@@ -2090,11 +2090,24 @@ require hands on real hardware — they remain for the human pass.
|
||||
`moved: 0` and a positive cleaned-coordinate count. Preview distinguishes
|
||||
updated spaces from removed coordinate noise; Cancel writes nothing;
|
||||
Apply stores exact grid nodes in one transaction; the next run is a no-op
|
||||
and server Undo restores the original noisy bits. A rejected hosted
|
||||
and server Undo restores the original geometry in canonical
|
||||
representation. A rejected hosted
|
||||
partition contributes nothing to the counter
|
||||
[unit: align-grid + plan-optimizer + i18n; auto:
|
||||
smoke_optimize_coordinate_canonicalization; mutation:
|
||||
`snapn-returns-input-near-node`].
|
||||
- [ ] **Every write prevents new ULP coordinate noise (#224)**: config/layout
|
||||
schema, import, direct storage writers, startup recovery and maintenance
|
||||
Undo produce the same nine-decimal allow-listed geometry as the frontend.
|
||||
A first noisy write creates one canonical revision; a repeated canonical
|
||||
write creates no store write/event/revision and preserves the maintenance
|
||||
backup. `view_box`, physical/presentation values, colours and vacuum
|
||||
calibration remain exact; the six-room #218 union and Glow clip stay
|
||||
non-empty [unit: coordinate-canonicalization + physical-geometry;
|
||||
backend: test_coordinate_canonicalization + test_ha_websocket +
|
||||
test_ha_import_export; mutations: `schema-quantization-removed`,
|
||||
`frontend-writes-raw-coords`, `quantization-hits-allowlist`,
|
||||
`import-path-bypasses-schema`; pre-release: golden verify].
|
||||
- [ ] Optimizer migration safety: legacy decor width/text size is clamped to
|
||||
the backend schema, `fill: true` receives explicit fill style, invalid
|
||||
legacy `plan_scale` is preserved for repair, an already canonical plan is
|
||||
|
||||
+12
-1
@@ -1332,6 +1332,17 @@ show_signal: true
|
||||
|
||||
## 19. Обслуживание планов
|
||||
|
||||
Обычное сохранение конфигурации или позиции устройства автоматически убирает
|
||||
из координат невидимый вычислительный шум. Это **не привязка к сетке**:
|
||||
диагональные стены, свободный декор и другие допустимые положения остаются на
|
||||
своих местах. Импорт и серверная отмена используют то же правило. Повторное
|
||||
сохранение уже неизменного плана не создаёт новую ревизию и не отменяет
|
||||
доступность последней служебной отмены.
|
||||
|
||||
Существующий план не переписывается при простом открытии. Его геометрия
|
||||
очистится при следующем изменении; если очистить всё нужно сразу, используйте
|
||||
явную оптимизацию ниже.
|
||||
|
||||
Кнопка **Общие настройки → Оптимизировать планы** запускает явное обслуживание. Сначала показывается точный предпросмотр; данные не меняются до подтверждения.
|
||||
|
||||
### Что делает оптимизация
|
||||
@@ -1365,7 +1376,7 @@ show_signal: true
|
||||
|
||||
### Риск и отмена
|
||||
|
||||
Старые и импортированные объекты между узлами будут привязаны к сетке. Новые редакторы такие координаты не создают. После оптимизации доступна одна серверная отмена, но только до следующего изменения плана. Новый edit делает резервную копию оптимизации устаревшей.
|
||||
Старые и импортированные объекты между узлами будут привязаны к сетке. Новые редакторы такие координаты не создают. После оптимизации доступна одна серверная отмена, но только до следующего изменения плана. Отмена возвращает прежнюю геометрию и неизвестные поля в чистом числовом представлении, не восстанавливая невидимый floating-point шум. Новый edit делает резервную копию оптимизации устаревшей.
|
||||
|
||||
Обычное открытие и редактирование плана не удаляет даже очень короткие точные
|
||||
границы толщины. Описанное схлопывание выполняется только после явного
|
||||
|
||||
Reference in New Issue
Block a user