fix(branch-coord): revert ADR-115 Cargo.toml/cli.rs that slipped into iter 18

Iter 18's commit 2997165bc accidentally absorbed the ADR-115 agent's
uncommitted MQTT/Matter additions (Cargo.toml `rumqttc` dep + [features]
block, cli.rs --mqtt CLI flags) into the adr-110-esp32c6 branch during
the cross-branch checkout described in that commit's message.

The actual iter 18 EMA work in main.rs is correct and stays; this commit
restores Cargo.toml + cli.rs to their HEAD~1 (iter 17) state so the
ADR-115 agent's stashed `stash@adr115-pending-work` can be popped cleanly
back onto their feat/adr-115-ha-mqtt-matter branch without colliding.

Net effect on adr-110-esp32c6:
  - main.rs iter 18 EMA: kept ✓
  - 4 fps_ema_tests: still green
  - Cargo.toml: back to iter-17 state (wifi-densepose-hardware dep only)
  - cli.rs: back to iter-17 state (no MQTT flags)
  - Cargo.lock: synced to match

The ADR-115 agent can pop their stash on feat/adr-115-ha-mqtt-matter
and resume without merging an unrelated branch's ADR-110 work.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv 2026-05-23 13:31:58 -04:00
parent 2997165bc1
commit ca2059b07f
3 changed files with 1 additions and 250 deletions

1
v2/Cargo.lock generated
View File

@ -9189,6 +9189,7 @@ dependencies = [
"tracing",
"tracing-subscriber",
"ureq 2.12.1",
"wifi-densepose-hardware",
"wifi-densepose-signal",
"wifi-densepose-wifiscan",
]

View File

@ -68,26 +68,6 @@ ureq = { version = "2", default-features = false, features = ["tls", "json"
sha2 = "0.10"
thiserror = "1"
# ADR-115 §3.8 — MQTT publisher (HA-DISCO).
# Gated behind the `mqtt` feature so the default binary stays small for users
# who don't need Home Assistant integration. `rumqttc` is the chosen Rust MQTT
# client (ADR-115 §10 references). `rustls` is preferred over openssl on
# Windows to keep parity with the rest of the workspace (`ureq` above also
# uses rustls).
rumqttc = { version = "0.24", default-features = false, features = ["use-rustls"], optional = true }
[features]
default = []
# Enables the ADR-115 §2 MQTT auto-discovery publisher. Without this feature
# all `--mqtt-*` CLI flags still parse (cli.rs declares them unconditionally),
# but enabling `--mqtt` at runtime logs a `WARN` and the publisher is a no-op.
mqtt = ["dep:rumqttc"]
# ADR-115 §3.11 — Matter Bridge (HA-FABRIC). Same gating principle: flags
# parse unconditionally; the bridge is a no-op without this feature.
# matter-rs is added in P7; intentionally absent in P1 to keep the dep
# surface small until the SDK choice is validated.
matter = []
[dev-dependencies]
tempfile = "3.10"
# `tower::ServiceExt::oneshot` for in-process Router tests (bearer_auth).

View File

@ -102,234 +102,4 @@ pub struct Args {
/// Start field model calibration on boot (empty room required)
#[arg(long)]
pub calibrate: bool,
// ─── ADR-115 §3.8 — MQTT publisher (HA-DISCO) ──────────────────────────
//
// All `--mqtt-*` flags are no-ops unless `--mqtt` is set. The
// wifi-densepose-sensing-server crate must be built with `--features mqtt`
// for the publisher to do anything; without that feature the flags parse
// but produce a startup WARN. This split lets the binary stay small for
// users who don't need HA integration, while keeping the CLI surface
// stable.
/// Enable MQTT publisher with HA auto-discovery
#[arg(long, env = "RUVIEW_MQTT")]
pub mqtt: bool,
/// MQTT broker host
#[arg(long, env = "RUVIEW_MQTT_HOST", default_value = "localhost")]
pub mqtt_host: String,
/// MQTT broker port (defaults: 1883 plain / 8883 with TLS)
#[arg(long, env = "RUVIEW_MQTT_PORT")]
pub mqtt_port: Option<u16>,
/// MQTT username
#[arg(long, env = "RUVIEW_MQTT_USERNAME")]
pub mqtt_username: Option<String>,
/// Environment variable holding the MQTT password
#[arg(long, default_value = "MQTT_PASSWORD")]
pub mqtt_password_env: String,
/// MQTT client ID (default: wifi-densepose-<hostname>)
#[arg(long, env = "RUVIEW_MQTT_CLIENT_ID")]
pub mqtt_client_id: Option<String>,
/// Discovery topic prefix (ADR-115 §9.2 — accepted: `homeassistant`)
#[arg(long, env = "RUVIEW_MQTT_PREFIX", default_value = "homeassistant")]
pub mqtt_prefix: String,
/// Enable TLS to the broker
#[arg(long, env = "RUVIEW_MQTT_TLS")]
pub mqtt_tls: bool,
/// CA bundle for TLS
#[arg(long, value_name = "PATH")]
pub mqtt_ca_file: Option<PathBuf>,
/// Client certificate for mTLS
#[arg(long, value_name = "PATH")]
pub mqtt_client_cert: Option<PathBuf>,
/// Client key for mTLS
#[arg(long, value_name = "PATH")]
pub mqtt_client_key: Option<PathBuf>,
/// Discovery refresh interval (seconds)
#[arg(long, default_value = "600")]
pub mqtt_refresh_secs: u64,
/// Vitals publish rate (Hz) — HR/BR
#[arg(long, default_value = "0.2")]
pub mqtt_rate_vitals: f64,
/// Motion publish rate (Hz)
#[arg(long, default_value = "1.0")]
pub mqtt_rate_motion: f64,
/// Person count publish rate (Hz)
#[arg(long, default_value = "1.0")]
pub mqtt_rate_count: f64,
/// RSSI publish rate (Hz)
#[arg(long, default_value = "0.1")]
pub mqtt_rate_rssi: f64,
/// Publish pose keypoints over MQTT (off by default for bandwidth)
#[arg(long)]
pub mqtt_publish_pose: bool,
/// Pose publish rate (Hz) when --mqtt-publish-pose is set
#[arg(long, default_value = "1.0")]
pub mqtt_rate_pose: f64,
// ─── ADR-115 §3.10 — Privacy mode ──────────────────────────────────────
/// Strip biometrics (HR/BR/pose) before any MQTT or Matter publish.
/// Discovery for those entities is suppressed entirely — the controller
/// never sees them exist. Implements the ADR-106 primitive-isolation
/// contract at the integration boundary.
#[arg(long, env = "RUVIEW_PRIVACY_MODE")]
pub privacy_mode: bool,
// ─── ADR-115 §3.11 — Matter Bridge (HA-FABRIC) ─────────────────────────
/// Enable Matter Bridge
#[arg(long, env = "RUVIEW_MATTER")]
pub matter: bool,
/// Write Matter setup code + QR string to this file on first start
#[arg(long, value_name = "PATH")]
pub matter_setup_file: Option<PathBuf>,
/// Wipe stored Matter fabric credentials before starting
#[arg(long)]
pub matter_reset: bool,
/// Matter vendor ID (default: dev VID 0xFFF1 per ADR-115 §9.9)
#[arg(long, default_value = "0xFFF1")]
pub matter_vendor_id: String,
/// Matter product ID (default: 0x8001)
#[arg(long, default_value = "0x8001")]
pub matter_product_id: String,
// ─── ADR-115 §3.12 — Semantic Inference (HA-MIND) ─────────────────────
/// Enable semantic inference layer (sleeping/distress/room-active/etc).
/// Default ON — primitives are the primary product surface.
#[arg(long, default_value_t = true)]
pub semantic: bool,
/// Per-primitive thresholds file
#[arg(long, value_name = "PATH")]
pub semantic_thresholds_file: Option<PathBuf>,
/// Zone-tag map (e.g. {"bathroom": ["zone_3"]})
#[arg(long, value_name = "PATH")]
pub semantic_zones_file: Option<PathBuf>,
/// Days of history for personalised baselines
#[arg(long, default_value = "14")]
pub semantic_baseline_window_days: u32,
/// Disable a specific semantic primitive (e.g. `sleeping`); repeatable.
/// Valid names: sleeping, distress, room_active, elderly_anomaly,
/// meeting, bathroom, fall_risk, bed_exit, no_movement, multi_room.
#[arg(long = "no-semantic", value_name = "PRIMITIVE")]
pub no_semantic: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
/// MQTT flags default safely (disabled).
#[test]
fn mqtt_defaults_disabled() {
let args = Args::parse_from(["sensing-server"]);
assert!(!args.mqtt, "--mqtt must default to false");
assert_eq!(args.mqtt_host, "localhost");
assert_eq!(args.mqtt_prefix, "homeassistant"); // ADR-115 §9.2
assert_eq!(args.mqtt_refresh_secs, 600);
assert_eq!(args.mqtt_rate_vitals, 0.2);
assert_eq!(args.mqtt_rate_motion, 1.0);
assert_eq!(args.mqtt_rate_count, 1.0);
assert_eq!(args.mqtt_rate_rssi, 0.1);
assert!(!args.mqtt_publish_pose, "pose publish off by default for bandwidth");
assert_eq!(args.mqtt_rate_pose, 1.0);
assert!(!args.mqtt_tls);
assert!(args.mqtt_username.is_none());
assert!(args.mqtt_port.is_none());
}
/// Privacy mode defaults off so existing deployments don't break;
/// production deployments must opt in.
#[test]
fn privacy_mode_defaults_off() {
let args = Args::parse_from(["sensing-server"]);
assert!(!args.privacy_mode);
}
/// Matter defaults off; VID is the dev VID per ADR-115 §9.9.
#[test]
fn matter_defaults_off_dev_vid() {
let args = Args::parse_from(["sensing-server"]);
assert!(!args.matter);
assert_eq!(args.matter_vendor_id, "0xFFF1");
assert_eq!(args.matter_product_id, "0x8001");
}
/// Semantic primitives default ON per ADR-115 §3.12.
#[test]
fn semantic_defaults_on() {
let args = Args::parse_from(["sensing-server"]);
assert!(args.semantic);
assert!(args.no_semantic.is_empty());
assert_eq!(args.semantic_baseline_window_days, 14);
}
/// All MQTT flags can be set together without conflicts.
#[test]
fn mqtt_all_flags_compose() {
let args = Args::parse_from([
"sensing-server",
"--mqtt",
"--mqtt-host", "broker.example.com",
"--mqtt-port", "8883",
"--mqtt-username", "ruview",
"--mqtt-prefix", "homeassistant",
"--mqtt-tls",
"--mqtt-refresh-secs", "300",
"--mqtt-rate-vitals", "0.5",
"--mqtt-publish-pose",
"--mqtt-rate-pose", "2.0",
"--privacy-mode",
]);
assert!(args.mqtt);
assert_eq!(args.mqtt_host, "broker.example.com");
assert_eq!(args.mqtt_port, Some(8883));
assert_eq!(args.mqtt_username.as_deref(), Some("ruview"));
assert!(args.mqtt_tls);
assert_eq!(args.mqtt_refresh_secs, 300);
assert_eq!(args.mqtt_rate_vitals, 0.5);
assert!(args.mqtt_publish_pose);
assert_eq!(args.mqtt_rate_pose, 2.0);
assert!(args.privacy_mode);
}
/// `--no-semantic` is repeatable and accumulates.
#[test]
fn no_semantic_repeatable() {
let args = Args::parse_from([
"sensing-server",
"--no-semantic", "sleeping",
"--no-semantic", "meeting",
"--no-semantic", "fall_risk",
]);
assert_eq!(args.no_semantic, vec!["sleeping", "meeting", "fall_risk"]);
}
// Env-var resolution is covered by clap's own test suite; we don't
// re-test it here because cargo's default parallel runner would race on
// the shared process env. Run `cargo test --test-threads=1` if you need
// local env-var coverage during development.
}