Files
ruvnet--RuView/python/Cargo.toml
T
ruv a47bb71b22 fix(adr-185): hoist AETHER compute surface into a std-only leaf crate
ADR-185 §13 flagged the `[aether]` wheel as linking the whole
`wifi-densepose-sensing-server` Axum/tokio/worldgraph/ruvector tree via the
non-optional deps of that crate. Hoist the pure-compute AETHER stack out so the
binding depends only on pure Rust.

New crate `wifi-densepose-aether` (std-only, ZERO external deps) holds the four
self-contained modules the AETHER surface needs — `embedding`, `graph_transformer`,
`sona`, `sparse_inference` (verified: no serde/tokio/axum/crate:: refs outside the
set; the four form a closed dependency graph). `wifi-densepose-sensing-server`
now `pub use`s them from the leaf crate, so its own code (`crate::embedding`, …)
and public API (`wifi_densepose_sensing_server::embedding`, …) are unchanged —
`main.rs`/`trainer.rs` untouched. The Python binding + parity test + `[aether]`
feature repoint at the leaf crate; the sensing-server dep is dropped from python.

MEASURED wheel size (maturin build --release --features aether --strip; each
wheel install-verified to actually contain `AetherConfig`):
  BEFORE (aether -> sensing-server): 369,782 B (~361 KB)
  AFTER  (aether -> leaf crate):     319,719 B (~312 KB)

HONEST CORRECTION to the §9/§13 premise: the pre-hoist wheel was NOT over the
ADR-117 §5.4 5 MB budget — it was ~361 KB, ~14x under. Linker dead-code
elimination (--gc-sections on the pyo3 cdylib) already strips the unreached
server tree because the binding only reaches pure-compute symbols. So this is
"blows the budget" CLAIMED, not MEASURED. The hoist is still worthwhile and
lands the real, measured wins:
  - `[aether]` build time 71s -> 12s (no server tree to compile),
  - python/Cargo.lock -1238 lines (server tree no longer resolved),
  - ~50 KB smaller wheel,
  - honest, minimal declared dependency surface + removes the latent risk that a
    future change makes some server code reachable and *then* bloats the wheel.

Verified this session (real counts):
  - cargo test --features aether --test aether_parity: 2 passed / 0 failed
  - pytest tests/test_aether.py (maturin develop --features aether): 9 passed
  - cargo test -p wifi-densepose-sensing-server --no-default-features: 217 bin +
    388 lib, 0 failed (no regression)
  - cargo test -p wifi-densepose-aether: 96 passed (the relocated unit tests)

The §9/§13 wheel-size narrative in ADR-185 (owned by the ADR author) should be
corrected to reflect the measured reality — flagged to the team lead.
2026-07-21 17:43:32 -07:00

123 lines
6.6 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[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. Binds the std-only
# `wifi-densepose-aether` leaf crate (the pure-compute stack hoisted out of
# `wifi-densepose-sensing-server` per §13), so this extra links no server tree.
aether = ["dep:wifi-densepose-aether"]
# 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` +
# `graph_transformer`/`sona`/`sparse_inference`, ADR-024). Optional +
# gated behind the `aether` feature.
#
# WHEEL-SIZE FIX LANDED (ADR-185 §13): this is now the std-only
# `wifi-densepose-aether` leaf crate — zero external deps, no tokio/axum/
# worldgraph/ruvector — hoisted out of `wifi-densepose-sensing-server`
# (which re-exports it, so the server is unchanged). The `[aether]` wheel
# therefore links only pure compute and stays within the ADR-117 §5.4
# ≤5 MB budget.
wifi-densepose-aether = { version = "0.3.0", path = "../v2/crates/wifi-densepose-aether", optional = true }
# 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"