docs/adr/ADR-065-happiness-scoring-seed-bridge.md
Status: Proposed Date: 2026-03-20 Deciders: @ruvnet Related: ADR-040 (WASM edge modules), ADR-039 (edge intelligence), ADR-042 (CHCI), ADR-064 (multimodal ambient intelligence), ADR-060 (multi-node aggregation)
Hotels lack objective, privacy-preserving methods to measure guest satisfaction in real time. Current approaches (post-stay surveys, NPS scores) are delayed, biased toward extremes, and capture less than 10% of guests. Meanwhile, ambient RF sensing can infer behavioral cues that correlate with comfort and well-being -- without cameras, wearables, or any guest interaction.
Two ESP32-S3 variants are deployed:
| Device | Flash | PSRAM | MAC | Port | Notes |
|---|---|---|---|---|---|
| ESP32-S3 (QFN56 rev 0.2) | 4 MB | 2 MB | 1C:DB:D4:83:D2:40 | COM5 | Budget node, uses sdkconfig.defaults.4mb + partitions_4mb.csv |
| ESP32-S3 | 8 MB | 8 MB | -- | COM7 | Full-featured node, existing deployment |
Both run the Tier 2 DSP firmware with presence detection, vitals extraction, fall detection, and gait analysis.
A Cognitum Seed unit is deployed on the same network segment:
The Seed's 8-dimensional vector store and drift detection engine make it a natural aggregation point for behavioral feature vectors extracted from CSI data.
The following modules already run on-device and produce features relevant to happiness scoring:
| Module | Event IDs | Outputs |
|---|---|---|
exo_emotion_detect.rs | 610-613 | Arousal level, stress index |
med_gait_analysis.rs | 130-134 | Cadence, stride length, regularity |
ret_customer_flow.rs | 410-413 | Entry/exit count, direction |
ret_dwell_heatmap.rs | 420-423 | Dwell time per zone |
exo_happiness_score.rsCreate a new WASM edge module that fuses outputs from existing modules into an 8-dimensional happiness vector, matching the Seed's vector dimensionality (dim=8).
Event ID registry (690-694):
| Event ID | Name | Description |
|---|---|---|
| 690 | HAPPINESS_VECTOR | Full 8-dim happiness vector emitted per scoring window |
| 691 | HAPPINESS_TREND | Windowed trend (rising/falling/stable) over last N vectors |
| 692 | HAPPINESS_ALERT | Score crossed a configured threshold (low satisfaction) |
| 693 | HAPPINESS_GROUP | Aggregate score for multi-person zone |
| 694 | HAPPINESS_CALIBRATION | Baseline recalibration event (new guest check-in) |
Each dimension is normalized to [0.0, 1.0] where 1.0 = maximal positive signal:
| Dim | Name | Source | Derivation |
|---|---|---|---|
| 0 | gait_speed | med_gait_analysis (130) | Normalized walking velocity. Brisk = positive. |
| 1 | stride_regularity | med_gait_analysis (131) | Low stride-to-stride variance = relaxed gait. |
| 2 | movement_fluidity | CSI phase jerk (d3/dt3) | Low jerk = smooth, unhurried movement. |
| 3 | breathing_calm | Vitals BR extraction | BR 12-18 at rest = calm. Deviation penalized. |
| 4 | posture_openness | CSI subcarrier spread | Wide phase spread across subcarriers = open posture. |
| 5 | dwell_comfort | ret_dwell_heatmap (420) | Moderate dwell in amenity zones = engagement. |
| 6 | direction_entropy | ret_customer_flow (410) | Low entropy = purposeful movement. Wandering penalized. |
| 7 | group_energy | Multi-target CSI clustering | Synchronized movement of 2+ people = social engagement. |
The composite scalar happiness score is the weighted L2 norm:
score = sum(w[i] * v[i] for i in 0..7) / sum(w[i])
Default weights are uniform (all 1.0), configurable via NVS or Seed API.
ESP32-S3 (CSI) Cognitum Seed (169.254.42.1)
+------------------+ +----------------------------+
| Tier 2 DSP | | |
| + WASM modules | UDP 5555 | /api/v1/store/ingest |
| exo_happiness |──────────────| (POST, 8-dim vector) |
| _score.rs | | |
| | | /api/v1/drift/check |
| |◄─────────────| (drift alerts via webhook) |
| | | |
| | | /api/v1/witness/append |
| | | (Ed25519 audit trail) |
+------------------+ +----------------------------+
Data flow:
exo_happiness_score.rs collects outputs from emotion, gait, flow, and dwell modules every scoring window (default: 30 seconds)./api/v1/store/ingest with metadata (room ID, timestamp, MAC).The Seed's built-in drift detection compares incoming vectors against a rolling baseline:
ruview_live.py gains a --seed flag:
python ruview_live.py --port COM5 --seed 169.254.42.1 --mode happiness
This mode displays:
+------------------------------------------+
| Hotel Room |
| |
| [ESP32-S3] [Cognitum Seed] |
| COM5 or COM7 169.254.42.1 |
| 4MB or 8MB flash Pi Zero 2 W |
| | | |
| | WiFi CSI | PIR, reed, |
| | 20+ Hz | BME280, |
| v | vibration |
| +-----------+ | |
| | Tier 2 DSP| v |
| | presence | +-------------+ |
| | vitals | | Seed API | |
| | gait | | 98 endpoints| |
| | fall det | | 398 vectors | |
| +-----------+ | dim=8 | |
| | +-------------+ |
| v ^ |
| +-----------+ UDP 5555 | |
| | WASM edge |─────────────┘ |
| | happiness | |
| | score | Drift alerts |
| | (690-694) |◄────────────── |
| +-----------+ /api/v1/drift/check |
| |
+------------------------------------------+
|
| MQTT / HTTP
v
+------------------+
| Hotel Management |
| System / RuView |
| Live Dashboard |
+------------------+
The 4MB ESP32-S3 variant (COM5) is officially supported for happiness scoring. The existing partitions_4mb.csv and sdkconfig.defaults.4mb from ADR-265 provide dual OTA slots (1.856 MB each), sufficient for the full Tier 2 DSP firmware plus exo_happiness_score.wasm (estimated < 40 KB).
Build for 4MB variant:
cp sdkconfig.defaults.4mb sdkconfig.defaults
idf.py build
The WASM module loader selects which modules to instantiate based on available heap. On the 4MB/2MB PSRAM variant, happiness scoring runs with a reduced scoring window (60s instead of 30s) to conserve memory.
Key Cognitum Seed endpoints used:
| Endpoint | Method | Purpose |
|---|---|---|
/api/v1/store/ingest | POST | Ingest 8-dim happiness vector |
/api/v1/store/query | POST | Retrieve vectors by room/time range |
/api/v1/drift/check | GET | Check if current vector drifts from baseline |
/api/v1/drift/configure | PUT | Set drift threshold and window size |
/api/v1/witness/append | POST | Append event to Ed25519 custody chain |
/api/v1/witness/verify | GET | Verify chain integrity |
/api/v1/sensors/bme280 | GET | Room temperature/humidity (comfort correlation) |
/api/v1/sensors/pir | GET | PIR presence (cross-validate with CSI) |