wifi-densepose/v2/crates/wifi-densepose-sensing-server/src
ruv 79cc2d7b22 Merge #491: feat(sensing-server): adaptive person count — RollingP95 + dedup_factor runtime API
Integrating @schwarztim's PR #491 into main on their behalf — their fork has
fallen too far behind for a clean rebase (the PR's commit graph dropped
silently during `git rebase origin/main`), so applying as a merge from the
fork head to preserve the diff cleanly.

What this lands:
- `RollingP95` adaptive normaliser for the person-count feature scaling.
  Streaming P95 over a 600-sample / ~30 s sliding window. Cold-start
  (<60 samples) falls back to the legacy denominators (variance/300,
  motion_band_power/250, spectral_power/500) so day-0 behaviour is
  preserved on every deployment.
- `RuntimeConfig` struct + `load_runtime_config` / `save_runtime_config`
  persisted to `data/config.json`. Exposes `dedup_factor` via REST so
  multi-node deployments can tune cluster-deduplication without a rebuild,
  including an auto-tune endpoint that derives optimal dedup from a known
  person count (calibration mode).
- `compute_person_score()` now takes &AppStateInner alongside &FeatureInfo
  so the adaptive denominators are reachable. All 3 call sites updated.
- New `AppStateInner` fields: `p95_variance`, `p95_motion_band_power`,
  `p95_spectral_power`, `dedup_factor`, `data_dir`.

Closes #491. Directly addresses:
- #499 (double skeletons, multi-node) — the slot-clustering problem this
  PR's adaptive normaliser was designed to fix
- #519 Bug 1 (ghost person detection on edge-tier 1 & 2 multi-node)
- #496 (person count over-reporting on single-room single-person)

Verified locally:
- cargo check -p wifi-densepose-sensing-server --no-default-features: 1.0s
- cargo test -p wifi-densepose-sensing-server --no-default-features --lib:
  233/233 passed in 25.0s

Co-authored-by: @schwarztim
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-05-19 08:25:47 -04:00
..
adaptive_classifier.rs fix(sensing): adaptive_classifier sorts with unwrap_or(Equal) — NaN panic (closes #611) (#613) 2026-05-17 19:29:07 -04:00
bearer_auth.rs feat(docker+sensing-server): refresh Docker publish + opt-in bearer-token API auth 2026-05-13 08:52:25 -04:00
cli.rs v2: pin Rust 1.89 and fix sensing-server UI path when run from v2 (#523) 2026-05-17 18:00:36 -04:00
csi.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
dataset.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
embedding.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
field_bridge.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
graph_transformer.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
host_validation.rs fix(security): host-header allowlist on sensing-server HTTP + WS — DNS rebinding (#580) 2026-05-17 17:27:00 -04:00
introspection.rs feat(introspection): I6 — regime-changed signal + per-frame analyze + honest ADR-099 D8 amendment 2026-05-13 23:29:37 -04:00
lib.rs fix(security): path-traversal guard on 5 sensing-server endpoints (closes #615) (#616) 2026-05-17 19:59:20 -04:00
main.rs Merge #491: feat(sensing-server): adaptive person count — RollingP95 + dedup_factor runtime API 2026-05-19 08:25:47 -04:00
model_manager.rs fix(security): path-traversal guard on 5 sensing-server endpoints (closes #615) (#616) 2026-05-17 19:59:20 -04:00
multistatic_bridge.rs feat(sensing-server): adaptive person count — RollingP95 + dedup_factor runtime API 2026-04-28 15:32:34 -04:00
path_safety.rs fix(security): path-traversal guard on 5 sensing-server endpoints (closes #615) (#616) 2026-05-17 19:59:20 -04:00
pose.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
recording.rs fix(security): path-traversal guard on 5 sensing-server endpoints (closes #615) (#616) 2026-05-17 19:59:20 -04:00
rvf_container.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
rvf_pipeline.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
sona.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
sparse_inference.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
tracker_bridge.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
trainer.rs chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00
training_api.rs fix(security): path-traversal guard on 5 sensing-server endpoints (closes #615) (#616) 2026-05-17 19:59:20 -04:00
types.rs feat(ruvector,signal,sensing-server): ADR-084 Passes 1/1.5/2/3 — RaBitQ similarity sensor implementation (#435) 2026-04-26 02:21:35 -04:00
vital_signs.rs fix(vital_signs): use circular variance for wrapped phases (#595) 2026-05-17 17:02:53 -04:00