Files
wifi-ruview/archive
rUv 9e7fa83210 feat(signal): ADR-134 CSI→CIR via ISTA + NeumannSolver warm-start (#837)
* feat(signal): ADR-134 — CSI→CIR via ISTA + NeumannSolver warm-start

End-to-end first-class Channel Impulse Response estimation in the Rust
workspace. Bridges CSI (frequency domain) to CIR (delay domain) so
multistatic coherence gating, NLOS/LOS classification, and (at HT40+)
ToF ranging become tractable in `wifi-densepose-signal`.

Algorithm: ISTA L1 sparse recovery over a normalized DFT sub-matrix
sensing operator Φ ∈ ℂ^(K×G) with G = 3K (3× super-resolution). The
Tikhonov-regularised warm start re-uses `ruvector_solver::neumann::
NeumannSolver` — same call pattern as `fresnel.rs:280` and
`train/subcarrier.rs:225` — so no new crate dependencies.

Tiers supported: HT20 / HT40 / HE20 (Tier A-HE, C6) / HE40. The C6
HE-LTF tier is the preferred Tier A target whenever an 11ax AP is in
range; firmware substrate already shipped at v0.7.0-esp32 per ADR-110.

Measured performance (release, single CirEstimator shared across 12
links): HT20 2.72 ms / HE20 3.20 ms / HT40 13.43 ms / HE40 9.71 ms per
estimate(). HT20 12-link multistatic 17.7 ms — fits the 50 ms RuvSense
cycle; HT40 12-link 74 ms exceeds it and is flagged in ADR-134 §2.7 as
requiring Rayon parallelism or G=2K super-res reduction.

Measured Φ conditioning: κ(Φ) ≈ 1.00 identically across all tiers.
ADR-134 §2.3 was corrected — the C6 advantage is statistical SNR gain
(√(242/52) ≈ 2.16×) from more independent measurements, not improved
conditioning.

Witness: bit-deterministic SHA-256 over CirEstimator output on the
synthetic ADR-028 reference signal (100 frames, top-5 taps, 1e-6
quantization). Hash committed to expected_cir_features.sha256;
verify-cir-proof.sh wires the check into the existing witness bundle.

CI: cargo test --features cir + verify-cir-proof.sh added as separate
steps under the Rust Workspace Tests job; regressions are unambiguously
attributable.

Files:
- ADR + WITNESS-LOG-028 row 34 + CLAUDE.md module count (14 → 15)
- src/ruvsense/cir.rs (~540 LOC) + lib.rs re-exports + multistatic.rs
  wire-up (reversible via `use_cir_gate=false`)
- 3 integration tests + Criterion bench + 3 deterministic fixtures
- cir_proof_runner binary + sha256 + verify-cir-proof.sh

Test rate: 395 pass / 6 ignored (P2 ISTA hyperparameter tuning; see
#[ignore] reasons) / 0 fail. cargo check clean; verify-cir-proof.sh
VERDICT: PASS.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(signal): make CIR witness cross-platform-deterministic

The first witness (Windows-generated hash 89704bfd…) failed on Linux CI
with a different hash (b36741bf…). Root cause: hashing `re`/`im` parts of
top-5 taps at 1e-6 precision is too tight against libm differences in
sin/cos/sqrt across glibc, MSVC, and Apple-clang. The previous
"top-5 sorted by magnitude" form also suffered from rank instability when
taps are near-tied — libm jitter could shuffle the ordering even when the
algorithm is unchanged.

New canonical form: full per-tap quantised-magnitude profile in natural
index order, no sort.

  - 156 taps × 2 bytes (u16 le) per frame = 312 bytes/frame.
  - Quantisation 1e-2 — robust to ~1e-3 float drift while still tripping
    on real algorithmic changes (e.g., a 10× lambda shift moves magnitudes
    by >1e-2).
  - No top-K selection — eliminates the unstable magnitude-sort step.

Regenerated expected_cir_features.sha256 — new hash 120bd7b1…

If the next CI run still mismatches, the cause is structural (rustfft SIMD
code path selection or NeumannSolver internal ordering), not magnitudes,
and the witness needs further coarsening or to be made platform-tagged.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-05-28 16:24:37 -04:00
..

Archive

Frozen, no-longer-active components of RuView preserved for historical reference, reproducibility, and load-bearing legacy paths the active codebase still depends on.

What lives here

Path What it is Why it's archived Still load-bearing?
v1/ Original Python implementation of RuView (CSI processing, hardware adapters, services, FastAPI) Superseded by the Rust workspace at v2/; ~810× slower in benchmarks. Kept rather than deleted because the deterministic proof bundle (v1/data/proof/) is part of the pre-merge witness verification process per ADR-011 / ADR-028. Yes — for the proof bundle only. Active code lives in v2/.

What "archived" means

  • Do not add new features here. New work goes in v2/.
  • Do not refactor or modernize the archived code beyond what is strictly necessary to keep the load-bearing paths working. The Python proof bundle is intentionally frozen so that its SHA-256 reproducibility holds across releases (per ADR-028's witness verification requirement).
  • Bug fixes inside archived code are allowed when the bug affects a still-load-bearing path (currently: only the Python proof). All other "bugs" in archived code are out-of-scope — they are part of the historical record and any fix would unnecessarily churn the witness hashes.
  • CI continues to verify the load-bearing paths. .github/workflows/verify-pipeline.yml runs the Python proof on every push and PR; if you change anything inside archive/v1/src/ or archive/v1/data/proof/, expect the determinism check to flag it.

Quick reference for the load-bearing paths

# Run the deterministic Python proof (must print VERDICT: PASS)
python archive/v1/data/proof/verify.py

# Regenerate the expected hash (only if numpy/scipy version legitimately changed)
python archive/v1/data/proof/verify.py --generate-hash

# Run the full Python test suite (legacy, still maintained)
cd archive/v1&& python -m pytest tests/ -x -q

Why we keep v1/ rather than delete it

  1. Trust kill-switch. The proof at v1/data/proof/verify.py feeds a known reference signal through the full pipeline and hashes the output. If the active code's behavior drifts, the hash changes and CI fails. This is what stops accidental regression in the science layer of the codebase.

  2. Witness verification. ADR-028's witness-bundle process bundles the proof, the rust workspace test results, and firmware hashes into a tarball recipients can self-verify. Removing v1 would break that chain.

  3. Historical reference. ADR-011 documents the "no mocks in production code" decision; the original violations and their fixes live in this Python codebase. The ADRs reference these paths.

If the time comes to retire the proof bundle (e.g., a Rust port of the proof exists and the Python version is no longer canonical), the right move is a single follow-up that simultaneously: ports the witness-bundle process, updates verify-pipeline.yml, and either deletes archive/v1/ or moves it to a separate read-only repository. That decision belongs in its own ADR.

See also

  • docs/adr/ADR-011-python-proof-of-reality-mock-elimination.md
  • docs/adr/ADR-028-esp32-capability-audit.md
  • archive/v1/data/proof/README.md (if present)
  • docs/WITNESS-LOG-028.md