17 KiB
#485 — Presence radars on the plan: common acceptance contract
Issue: #485.
Author: Codex. Baseline: dev at
ed9ee026dc08054e12038b7dbd1b8525e7706d04, 2026-09-08.
This is a specification, not shipped behaviour. Status is exclusively the issue
label. Current owner instruction: obtain independent specification approval,
stop at S5-ready, and do not implement or proceed to S6.
1. Reading order and authority
The acceptance package consists of this common contract and all three documents:
- Stage 1 — source model, calibration and live presence.
- Stage 2 — zones and bounded observations.
- Stage 3 — coverage, aggregation and derived room states.
The stages are dependent implementation increments, not three ways to narrow the issue to its easiest part. The independent S4 review covers all four files; S5 means the complete package is ready. Later implementation/release reports must name exactly the stages delivered. No unfinished stage disappears because the live layer works. Creating follow-up issues, changing the agreed scope or closing this issue before all its AC are met requires an owner decision.
Authority: docs/SCOPE.md, repository process, the issue's owner request,
UX proposal,
analysis,
and accepted defaults,
including the Q5 manual-entry decision.
The numbered specs turn those requirements into testable contracts. Old open
questions in the original issue are superseded by these explicit decisions;
the external field report is evidence, not an instruction to copy a firmware.
2. Product intent and boundaries
Primary job: J1, understand presence now, on a familiar floor plan. The home administrator configures the connection once; household members, phones and wall kiosks see unobtrusive current observations. J4/J6 support safe setup and diagnostics, not a new technical console in ordinary View.
The owner explicitly requested zones, local observations, day/week heat maps and optional derived HA entities in #485. These are a bounded exception to SCOPE's exclusion of general historical analytics: only spatial radar setup and occupancy analysis, local and opt-in. This does not authorize general time-series charts, an automation editor, tracking named people or cloud upload. Original HA entities, automations and existing light Glow/spill remain untouched.
| Accepted decision | Consequence |
|---|---|
| Q1 default | Live marks appear after explicit configuration; global and per-radar switches hide them. No hover prerequisite. |
| Q2 default | Stages 1–2 use one selected room if its polygon exists. Stage 3 permits multiple allowed rooms. No invented room rectangle. |
| Q3 default | Stage-2 raw recording starts manually, defaults to 1 h, each run <=24 h, each point expires after 24 h, works without a browser, editor-only access. |
| Q4 default | Cross-radar consolidation is Stage 3; earlier stages make no global people count or identity claim. |
| Q5 default | Hide the device section until positive radar recognition, an existing saved configuration, or the user's explicit secondary action This is a presence radar. The action opens manual setup; Cancel saves nothing. Keep the global preference unchanged. |
The requested weekly heat map has its own explicit, default-off collection action; it is not enabled by raw recording or live display. Each collection authorization still lasts at most 24 h, without automatic renewal. Stage 3 retains local aggregate bins for at most seven days, not seven days of raw trajectories; a week can contain gaps or separately authorized sessions. This is the bounded engineering interpretation of the owner's day/week requirement, not an assertion that Q3 authorized permanent collection.
3. One feature, several capabilities
There is no new editor mode or separate fleet of person/device markers. Add configuration under the existing device/placed-entity marker in Device editor: Presence on plan, shown only for an eligible presence-radar device as defined by Stage 1 §2. Unsupported ordinary devices get no empty/disabled section. Unknown/custom devices and standalone entities retain an explicit secondary This is a presence radar action under additional device-editor actions; this opens the same manual source wizard without automatic recognition. Until that choice the main section stays hidden; cancelling unsaved setup leaves it hidden and persists nothing. An existing saved radar configuration retains its repair path even when its sources become unavailable. This owner clarification of 2026-09-08 does not condition the global Show presence on the plan preference on device discovery or first setup: that preference stays unchanged. Reuse the primary House Plan panel and full dashboard card's shared editor. The compact Room View card is not a second radar editor; this issue neither replaces its current renderer nor adds historical tools to it.
A device label/manufacturer is never proof of data availability. The backend derives capabilities from exact bound entities and a verified profile:
| Source evidence | Honest presentation | Forbidden inference |
|---|---|---|
| Valid local X/Y or explicitly described polar pair | One dot per current target slot | Stable person identity from a slot index |
| Range without bearing | Arc of possible positions; no claimed angle | Turn two distances into X/Y or two people |
| Occupancy/count for a known zone | Zone outline/state; Stage 2 provides manual polygons | Invent coordinates or remotely editable FP2 geometry |
| Presence only | Existing presence marker and optional diagnostic coverage | A fabricated person position or occupied area from marketing range |
Reference adapters: ESPHome LD2450 (coordinate slots and separately verified zone-number bindings), generic explicit Cartesian/polar/range/occupancy inputs, and exact zone occupancy/count mappings (including FP2-style connections). Named products in the initial issue are examples, not a claim that every firmware is automatically supported. Positively identified radars with unknown connection roles use manual bindings or an unsupported explanation, never guessed axes/units/writable capabilities. Hardware with neither positive radar metadata nor a saved radar configuration gets no automatic setup section, but Q5's explicit manual entry preserves generic numeric/range/occupancy support. An arbitrary pair of numbers or occupancy class is not automatic radar evidence; user declaration is entry consent, not proof of source validity or device-write capability. Exact manually selected sources still pass Stage 1 profile/ACL checks.
4. Shared architecture and authoritative state
Existing seams: src/types.ts, src/config-store.ts,
src/space-geometry.ts, src/houseplan-editor-runtime.ts,
src/houseplan-card.ts, src/render-device-snapshot.ts,
src/houseplan-render-lifecycle.ts, src/live-viewport.ts,
custom_components/houseplan/{__init__,store,auth,validation,websocket_api}.py.
New pure radar modules, a lazy editor and backend coordinator are specified in
the stage documents. Do not duplicate the giant card's rendering/gesture logic.
Backend coordinator owns source normalization, freshness and room/filter classification. One coordinator per integration, not per browser. Stage 2 and 3 consume its frames, never independently infer availability or reparse HA values. Browser projection helpers used for calibration must agree with the backend on shared numeric fixtures. Backend sampling never relies on UI frames.
One persisted optional namespace: marker.radar.version=1 and
settings.radar. Common settings start with show_live (absent => true);
per-radar enabled requires explicit setup, absence means no radar operation.
Stage 2 extends radar with zones/reflectors; Stage 3 extends it with
allowed_room_ids, and settings.radar with fusion/room-output configuration.
Capabilities radar_stage1_api:1, radar_stage2_api:1, radar_stage3_api:1
are additive advertised runtime features, not stored user toggles.
Server-owned runtime identities:
source_generation: opaque fingerprint/version of exact source bindings, mount x/y, installation UUID and coordinate conventions. It changes on a physical move, source/unit/axis change or owner-space change, not decorative icon drag. Explicit Change installation creates a new installation UUID even if the saved position is unchanged. Heading/mirror/reference correction alone changes calibration revision, not source generation.calibration_revision: accepted projection correction within that same installation. Room/filter/zone revisions are separate evaluation epochs.- Frame
seqandserver_session_id: monotonic within one coordinator session; clients discard older/out-of-session deliveries and clear on reconnect.
Runtime ids, consent runs, histories, command tokens and telemetry are not
portable configuration. All config writes keep the existing expected_rev
transaction and may_write policy. New endpoints do not provide a generic
service proxy. HA entity permissions are additionally respected when reading
or controlling entity data; House Plan write access is not permission elevation.
5. Shared lifecycle / compatibility obligations
Optional additions do not change global config version or rewrite old plans on
read. Validate new/changed known blocks; preserve untouched malformed/future
blocks and unknown siblings losslessly, but do not execute them. Never coerce
an invalid radar into a valid-looking coordinate at (0,0).
New frontend/old backend: preserve config, display update-required explanation, make no unsupported calls and hide unsupported layer/tools. Old frontend/new backend: additive fields survive the existing unknown-field path; clients which reconstruct whole markers are not promised safe editing after downgrade. The documentation recommends read-only downgrade or current-version backup first.
The implementation must cover the existing full backup, config import/export, plan-only export, space duplicate/import/remove, room removal, marker movement between spaces and Optimize transactions, not just config/set. Stage documents define which references survive/remap. Full restore must retain exact configured refs but starts no recording, device write or entity provisioning implicitly. Duplicate space does not bind a copied radar to live hardware by accident: the existing duplicate virtualization policy also removes its radar bindings.
Disabled/removed/missing space or room is not permission to choose the first remaining space/room. Invalidated observations disappear; repair UI is explicit. Geometry-preserving Optimize keeps valid projections unchanged. A coordinate frame/physical-scale change invalidates calibration and suspends affected live projection until confirmed recalibration, rather than shifting observations silently. Pure pan, zoom, theme, fit-to-room, plan wallpaper transform and moving the decorative icon do not alter physical calibration. Room shape changes reevaluate membership, invalidate analysis epochs and affected room outputs.
Raw observations, aggregates and radar runtime snapshots are excluded from House Plan support packages/portable exports/logs/browser persistent storage. Full administrator HA backups may independently capture integration storage; the UI discloses that these copies are outside retention/deletion guarantees. No new cloud, telemetry, CSV upload or public download URL is introduced.
6. UX, visual and accessibility invariants
- View is quiet: small marks, no person names, trails, debug sectors, heat maps or editing handles unless explicitly entering setup/analysis. No new pulsing background competes with light Glow. Reduced motion disables interpolation.
- Radar dots/arcs/fills are pointer-transparent. Existing device tap_action, full capsule hit area, room-fit, double-tap fit and pan/pinch retain priority.
- Live layers are hidden in Plan/Background editors. Device setup shows only the selected radar's diagnostic geometry. Stage-3 analysis is a deliberate contextual surface, not a fourth permanently visible editor tab.
- No rewrite of isometric projection: reuse the existing projection seam for floor-level live marks; never render a second unprojected floor layer. Precise calibration/analysis use 2D temporarily and restore the user's view on exit.
- View/kiosk fully support touch (
docs/TOUCH-SUPPORT.md), including resume, orientation changes and no-hover paths. Editors remain desktop-first, with safe cancellation/permissions on touch. Minimum essential action targets 44 px; long labels wrap and dialogs retain visible Close/Cancel controls. - Keys/text are specified en+ru in each stage, escaped as text. Locale number, length and date formatting is reused. No coordinate speech on every frame; meaningful health changes are debounced polite status text.
7. Acceptance map and completion evidence
All stage AC are required in addition to these cross-cutting ones. Test paths named in this package are planned deliverables, not tests claimed as run.
| AC | Required outcome | Proof / negative witness |
|---|---|---|
| C-1 | Four capability classes produce only evidence-supported output | unit/backend state matrix; remove capability gate => invented point test fails |
| C-2 | Setup opt-in; display toggle does not start/stop hidden collection | smoke + backend command spies; auto-start on View/toggle => zero-start assertion fails |
| C-3 | One normalized source authority across clients/recording/entities | backend two-client/recorder fixture; stale or duplicated frame injection changes expected set and fails |
| C-4 | All lifecycle seams in §5 preserve or explicitly invalidate refs without retargeting | backend import/duplicate/Optimize/removal + unit preservation tests; drop guard => wrong-space canary fails |
| C-5 | No regression in devices, Glow, room actions, gestures or isometry | View/kiosk smoke and reviewed golden full scenes light/dark, 2D/isometry; layer hit-test mutation => click/pan failure |
| C-6 | No raw/aggregate leakage or implicit external writes | backend permissions/support/export + browser persistence/network canary checks; include private field/skip permission => failure |
| C-7 | Optional/unknown/future fields and rolling frontend/backend matrix remain safe | unit/backend roundtrip/API trace; remove capability gate/unknown preservation => failure |
| C-8 | Full package is independently reviewed; no implementation under current instruction | review of spec links, exact branch SHA and diff restricted to documentation; S5 label, not author self-approval |
Protective AC require named negative witnesses and failing output at code review,
per PROCESS §2.7. Expensive witnesses belong in scripts/mutation-gate.mjs;
text-regex tests or a single happy-path screenshot cannot prove geometry,
authorization or retention. TS/Python must consume identical coordinate fixtures.
Implementation loop: typecheck, unit, build. Targeted checks may diagnose a failure; complete golden/smoke/performance/security and full HA backend harness are pre-beta evidence on exact SHA in Linux CI/approved WSL, not native Windows claims. Existing initial-bundle gzip ceiling 256,000 bytes remains binding; lazy editors/analysis cannot enter initial View graph. Stage documents add caps.
8. Release, rollback and risks
Future behaviour commits include Issue: #485, User-Visible: yes, both
docs/CHANGELOG.md and docs/CHANGELOG.ru.md, user guide EN/RU, architecture,
compatibility/field registry and status updates. Review complete synthetic
golden scenes, not only crops; include compact phone, wall tablet and desktop,
light/dark and representative live/error states. Record baseline/candidate
performance and security/retention/mutation tables. A beta is issued only on
owner command; current request creates no beta, code or version bump.
Rollback: hide live layers for visual rollback; disable affected radars to stop runtime processing; Stop/Clear private recordings/aggregates with the current version before downgrade. Removing optional derived HA entities is explicit and warns about downstream automations; hardware-zone rollback is another confirmed device operation, never automatic. Keep portable config backups.
Risks: coordinate ambiguity, suppressed unchanged HA reports, optimistic device echoes, overconfident counts, reflection false positives, source reconfiguration, privacy/storage growth and duplicate browser work. No specification can make an uninformative sensor report true position; degraded states are a necessary part of the feature, not defects to conceal.
9. Explicit engineering assumptions
The owner resolved Q1–Q4. Module names, bounded resource/timing constants, protocol version numbers, conservative confidence thresholds and test filenames are reviewable engineering choices. Seven-day aggregate expiry is the minimum window for the explicitly requested weekly view, with independent <=24 h opt-in sessions and visible gaps, not a continuous-history product expansion. Reference adapter firmware evidence is linked in stages; user-supplied private recordings are not prerequisites or public fixtures without contributor permission.