wifi-densepose/v2
ruv 8e416af203 feat(adr-115): P4.5a — semantic inference layer (HA-MIND) — 4 primitives + bus (34 tests)
ADR-115 §3.12 keystone. Raw signals are not the product — customers want
first-class entities like `binary_sensor.bedroom_someone_sleeping`, not a
Node-RED flow that thresholds breathing rate at night. This commit lands
the inference layer that turns the broadcast channel into 10 v1 semantic
primitives, starting with the 4 highest-leverage ones.

Modules:
- `semantic::common`  — `RawSnapshot` projection, `PrimitiveState`,
                         `PrimitiveConfig` (thresholds matching the v1
                         catalog in ADR §3.12), `in_window` for time-gated
                         primitives, `Reason` explainability struct.
- `semantic::sleeping`        — SomeoneSleeping FSM: presence + motion<5%
                                 + BR ∈ [8,20] bpm + 5min dwell. Exit on
                                 presence-drop (immediate) or motion>15%
                                 for 30s.
- `semantic::room_active`     — motion >10% in 30s window → ON. Exit on
                                 presence-drop or 10min idle.
- `semantic::bathroom`        — presence + zone tagged as bathroom. Safe
                                 in privacy mode (no biometrics in the
                                 derivation).
- `semantic::no_movement`     — presence + motion<1% for 30min → ON.
                                 Safety-check primitive for aging-in-place.
- `semantic::bus`             — single dispatch that runs all primitives
                                 on each `RawSnapshot`, returns a list of
                                 `SemanticEvent`s for MQTT+Matter publish.

Every primitive has:
- Warmup suppression (60s default, §3.12.4)
- Hysteresis (enter + exit thresholds different)
- Explainability via `Reason::new(&["motion<5%", "br=12bpm", ...])`
- Configurable thresholds via `PrimitiveConfig`

Test coverage (34 tests, all passing under `--no-default-features`):
- common: in_window simple + wrap-around midnight, default thresholds
  match ADR catalog, Reason struct.
- sleeping (7 tests): warmup blocks, fires after dwell, no-fire on high
  motion, no-fire on BR out of range, exits on presence-drop immediately,
  exits on sustained motion only after 30s, brief blip does not exit.
- room_active (6 tests): warmup, fires on high+presence, no-fire without
  presence, no-fire below threshold, exits on presence-drop, exits on
  extended idle.
- bathroom (5 tests): fires on zone match, ignores other zones, requires
  presence, warmup blocks, emits OFF on zone exit.
- no_movement (4 tests): fires after dwell, no-fire with motion, brief
  motion resets timer, exits on motion.
- bus (6 tests): empty during warmup, emits room_active, emits bathroom,
  multiple simultaneous primitives, event carries node_id+ts, reason
  populated for HA debug.

Total cargo test count now:
  cli: 6 + mqtt: 45 + semantic: 34 = 85 tests passing

P4.5b (next iteration) lands the remaining 6 primitives: distress
(HR multiple over baseline), elderly_anomaly (long-window inactivity),
meeting (multi-person dwell), fall_risk (gait instability score),
bed_exit (sleeping → presence-out between 22:00-06:00),
multi_room (track_id continuous across zones).

Refs #776.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-05-23 14:01:51 -04:00
..
.cargo fix(security): audit — fix RUSTSEC vulns, clippy warnings, dead code (#769) 2026-05-23 05:36:13 -04:00
.claude-flow chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
crates feat(adr-115): P4.5a — semantic inference layer (HA-MIND) — 4 primitives + bus (34 tests) 2026-05-23 14:01:51 -04:00
data chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
docs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
examples chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
patches/ruvector-crv chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
Cargo.lock fix(security): audit — fix RUSTSEC vulns, clippy warnings, dead code (#769) 2026-05-23 05:36:13 -04:00
Cargo.toml fix(security): audit — fix RUSTSEC vulns, clippy warnings, dead code (#769) 2026-05-23 05:36:13 -04:00
rust-toolchain.toml v2: pin Rust 1.89 and fix sensing-server UI path when run from v2 (#523) 2026-05-17 18:00:36 -04:00