mirror of
https://github.com/ruvnet/RuView
synced 2026-07-22 17:23:19 +00:00
1c9727f9cf
Bind the ADR-024 MAT (Mass Casualty Assessment Tool) disaster-survivor detection + START triage surface into the wheel behind a gated [mat] extra / Cargo `mat` feature, mirroring the upstream disaster/ML gating. Also adds the [sota] superset extra (aether+meridian+mat). Surface (bound against the REAL code at HEAD, not the ADR wishlist): - DisasterType (9 variants) / TriageStatus (5, START) enums - DisasterConfig (builder-backed, continuous_monitoring forced off) - DisasterResponse: initialize_event / add_zone / push_csi_data / scan_once / survivors / survivors_by_triage - Survivor (id, triage_status, confidence, location, latest_vitals) - VitalSignsReading (breathing/heartbeat rate, movement, confidence) - ScanZone.rectangle / ScanZone.circle push_csi_data + scan_once are GIL-released. Honest deviations from ADR section 3.4 (documented in module header): - ADR proposed adding a Rust-side sync scan_once() (section 11.3). That was UNNECESSARY: the public async start_scanning() runs exactly one scan_cycle and returns when continuous_monitoring == false. The binding forces that flag off and drives one cycle on a private current-thread tokio runtime -- NO change to wifi-densepose-mat. - scan_cycle requires an active event + Active zone, which the ADR surface omitted; initialize_event + add_zone are bound as required additions. - Survivor.vital_signs is a *history* in the real code; bound as Survivor.latest_vitals -> Optional[VitalSignsReading]. - DisasterType has 9 variants at HEAD (adds Landslide/MineCollapse/ Industrial/TunnelCollapse); all bound. Parity (section 4.1, release-blocking): committed fixture mat_input.json (synthetic breathing-modulated CSI stream) -> native Rust reference (tests/mat_parity.rs, drives DisasterResponse directly) locks tests/golden/mat_result.sha256 over a canonical `count=<K>;triage_priorities=<sorted>` string (survivor UUIDs/timestamps excluded as non-deterministic); pytest (tests/test_mat.py) runs the same stream through the binding and asserts the identical hash. Both detect exactly 1 survivor, triage Delayed. Honest: synthetic fixture proves binding==native path equality, NOT live detection accuracy. Verified: cargo test --features mat --test mat_parity -> 2/2 pass maturin develop --features mat + pytest tests/test_mat.py -> 7/7 pass default cargo build clean, 0 mat/tokio refs in the default dep graph. WHEEL-SIZE FINDING (ADR-185 section 9): default-features=false drops MAT's `api` (axum) and `ruvector` features, but MAT still carries NON-optional tokio (rt/sync/time), wifi-densepose-nn (ort/ONNX + reqwest/hyper), rustfft, geo, ndarray. So a [mat] wheel exceeds the ADR-117 section 5.4 <=5 MB budget -- same leaf-crate-hoist follow-up as AETHER/MERIDIAN. The default wheel is untouched (feature-gated).
127 lines
6.9 KiB
TOML
127 lines
6.9 KiB
TOML
[package]
|
||
name = "wifi-densepose-py"
|
||
version = "2.0.0-alpha.1"
|
||
# The `python/` crate is intentionally OUTSIDE the `v2/` Cargo
|
||
# workspace (ADR-117 §5.2) so maturin's `python-source` + `module-name`
|
||
# config stays self-contained and `cargo test --workspace` in v2/
|
||
# doesn't have to compile pyo3. Hence no `*.workspace = true`
|
||
# inheritance here — every field is local.
|
||
edition = "2021"
|
||
license = "MIT"
|
||
authors = ["rUv <ruv@ruv.net>", "WiFi-DensePose Contributors"]
|
||
description = "PyO3 bindings for the WiFi-DensePose Rust core — ships as the `wifi-densepose` PyPI wheel (ADR-117)"
|
||
repository = "https://github.com/ruvnet/RuView"
|
||
|
||
# ADR-117 §5.2: the Python wheel's compiled module name is
|
||
# `wifi_densepose._native` (the leading underscore marks it as an internal
|
||
# implementation detail re-exported by the pure-Python facade in
|
||
# `wifi_densepose/__init__.py`). Keeping the name distinct from the crate
|
||
# avoids the maturin gotcha where `wifi_densepose-py` would collide with
|
||
# the user-facing `wifi_densepose` package on import.
|
||
[lib]
|
||
name = "wifi_densepose_native"
|
||
crate-type = ["cdylib", "rlib"]
|
||
path = "src/lib.rs"
|
||
|
||
# ADR-185 §3.1 — optional pip extras map to Cargo features so the
|
||
# default wheel links none of the SOTA subsystems. P1 wires `aether`.
|
||
[features]
|
||
default = []
|
||
# ADR-185 P1 — AETHER contrastive CSI embeddings. Pulls the backing
|
||
# `wifi-densepose-sensing-server` crate (see the honest wheel-size note
|
||
# on that dep below).
|
||
aether = ["dep:wifi-densepose-sensing-server"]
|
||
# ADR-185 P2 — MERIDIAN domain generalization. Binds the tch-free
|
||
# inference/adaptation path only (see the wheel-size note on the deps
|
||
# below). `wifi-densepose-train` is depended on WITHOUT `tch-backend`,
|
||
# so no libtorch is linked.
|
||
meridian = ["dep:wifi-densepose-train", "dep:wifi-densepose-signal"]
|
||
# ADR-185 P3 — MAT disaster-survivor detection. Mirrors the upstream
|
||
# disaster/ML gating: bound only under this extra so the default wheel
|
||
# never carries the detection stack. `tokio`/`geo` are pulled to drive a
|
||
# single-shot scan (see the wheel-size note on the deps below).
|
||
mat = ["dep:wifi-densepose-mat", "dep:tokio", "dep:geo"]
|
||
# ADR-185 §3 — convenience superset: all three SOTA subsystems.
|
||
sota = ["aether", "meridian", "mat"]
|
||
|
||
[dependencies]
|
||
# PyO3 with abi3-py310 — one compiled binary covers Python 3.10, 3.11,
|
||
# 3.12, 3.13, and any future 3.x that keeps the stable ABI (ADR-117 §5.4).
|
||
# Without abi3 we'd need a separate wheel per Python minor version × OS
|
||
# × arch, blowing up the cibuildwheel matrix.
|
||
pyo3 = { version = "0.22", features = ["extension-module", "abi3-py310"] }
|
||
|
||
# Re-export the Rust core types through PyO3 #[pyclass] wrappers in P2.
|
||
# Default-features-off keeps the wheel size below the 5 MB ADR-117 §5.4
|
||
# budget by avoiding optional BLAS/openssl chains.
|
||
wifi-densepose-core = { version = "0.3.0", path = "../v2/crates/wifi-densepose-core" }
|
||
|
||
# P3 — vitals extraction (HR/BR via the 4-stage pipeline). Pure-sync;
|
||
# no tokio (Q5 audited 2026-05-24); safe to wrap in py.allow_threads.
|
||
wifi-densepose-vitals = { version = "0.3.0", path = "../v2/crates/wifi-densepose-vitals" }
|
||
|
||
# ADR-118 BFLD core — PrivacyClass enum + identity_risk scoring +
|
||
# privacy gate. Exposed to Python via bindings/privacy_gate.rs so the
|
||
# c6-presence-watcher.py runtime (currently using a Python port of the
|
||
# same semantics) can switch to the canonical Rust implementation when
|
||
# the wheel ships. ADR-125 §2.1.d invariant enforcement lives here.
|
||
wifi-densepose-bfld = { version = "0.3.0", path = "../v2/crates/wifi-densepose-bfld" }
|
||
|
||
# numpy bridge — needed for P3.5 BfldFrame (Complex64 ndarray) and for
|
||
# the future P3 CsiFrame numpy round-trip.
|
||
numpy = "0.22"
|
||
|
||
# ADR-185 P1 — AETHER backing crate (contrastive `embedding` module,
|
||
# ADR-024). Optional + gated behind the `aether` feature.
|
||
#
|
||
# HONEST WHEEL-SIZE NOTE (ADR-185 §9 / Open Q §11.1): this crate is an
|
||
# Axum/tokio server crate. `default-features = false` does NOT drop
|
||
# tokio/axum here — they are non-optional deps (only `mqtt`/`matter`
|
||
# are features). So an `[aether]` wheel currently links the full
|
||
# sensing-server dependency tree, breaking the ADR-117 §5.4 ≤5 MB
|
||
# budget. The ADR-sanctioned fix is to hoist `embedding.rs` (+ its
|
||
# `graph_transformer`/`sona` siblings) into a leaf crate so the wheel
|
||
# links only pure compute — a Rust-side refactor inside
|
||
# `wifi-densepose-sensing-server`, owned by another agent this session.
|
||
# P1 binds against the real code and proves parity; the leaf-crate
|
||
# hoist is the required pre-release follow-up.
|
||
wifi-densepose-sensing-server = { version = "0.3.0", path = "../v2/crates/wifi-densepose-sensing-server", optional = true, default-features = false }
|
||
|
||
# ADR-185 P2 — MERIDIAN backing crates (optional, `meridian`-gated).
|
||
#
|
||
# HONEST WHEEL-SIZE NOTE (ADR-185 §9 / §1.2): unlike AETHER, the libtorch
|
||
# risk is AVOIDED here — `wifi-densepose-train`'s `tch` dep is properly
|
||
# optional (feature `tch-backend`, OFF by default), so no libtorch links.
|
||
# BUT `wifi-densepose-train` still carries NON-optional deps: `tokio` (rt
|
||
# subset), the five `ruvector-*` crates, `wifi-densepose-nn`, petgraph,
|
||
# memmap2, indicatif, ndarray-npy, csv, toml, clap. So a `[meridian]`
|
||
# wheel is heavier than the ≤5 MB ADR-117 §5.4 budget (though far lighter
|
||
# than AETHER's axum/tokio server tree). The clean fix is the same
|
||
# leaf-crate hoist: move the pure inference modules (geometry,
|
||
# rapid_adapt, eval, hardware_norm) into a tch/tokio-free leaf crate.
|
||
# `wifi-densepose-signal` is depended on `default-features = false` to
|
||
# drop the optional ndarray-linalg/BLAS chain (Windows-friendly).
|
||
wifi-densepose-train = { version = "0.3.0", path = "../v2/crates/wifi-densepose-train", optional = true, default-features = false }
|
||
wifi-densepose-signal = { version = "0.3.0", path = "../v2/crates/wifi-densepose-signal", optional = true, default-features = false }
|
||
|
||
# ADR-185 P3 — MAT backing crate + the tokio/geo needed to drive one scan.
|
||
#
|
||
# HONEST WHEEL-SIZE NOTE (ADR-185 §9 / §1.3): `default-features = false`
|
||
# drops MAT's `api` (axum) and `ruvector` features from the wheel, but MAT
|
||
# still carries NON-optional `tokio` (rt/sync/time), `wifi-densepose-nn`
|
||
# (which pulls `ort` / ONNX Runtime + reqwest/hyper), `rustfft`, `geo`,
|
||
# and `ndarray`. So a `[mat]` wheel exceeds the ADR-117 §5.4 ≤5 MB budget
|
||
# — same leaf-crate-hoist story as AETHER/MERIDIAN, gated the same way so
|
||
# the DEFAULT wheel is untouched. `tokio` (rt+time) and `geo` are depended
|
||
# on directly (version-matched to MAT) to build the single-shot scan
|
||
# runtime and construct the event `geo::Point` in the binding.
|
||
wifi-densepose-mat = { version = "0.3.0", path = "../v2/crates/wifi-densepose-mat", optional = true, default-features = false, features = ["std"] }
|
||
tokio = { version = "1.35", features = ["rt", "time"], optional = true }
|
||
geo = { version = "0.27", optional = true }
|
||
|
||
[dev-dependencies]
|
||
# ADR-185 §4.1 parity harness — SHA-256 the native-Rust reference
|
||
# embedding and read the committed golden fixture.
|
||
sha2 = "0.10"
|
||
serde_json = "1"
|