One-command harness: clone, run scripts/prove.sh, and every headline claim is
either verified on your machine (re-runs the bug-catching tests) or printed as
'CLAIMED — not reproduced here' with the exact prerequisite. Hard gate =
workspace tests + deterministic Python proof; section 3 re-runs 7 anti-slop
assertion tests (each fails on pre-fix code); gated claims (GPU/dataset/hardware/
trained-checkpoint/named-identity) are honestly listed, never faked.
Co-Authored-By: claude-flow <ruv@ruv.net>
checkpoint_round_trip / rvf_test / rvf_pipeline_test shared fixed temp_dir paths
and remove_dir at teardown, so two concurrent/repeated test runs raced (one's
teardown wiped the other's file -> NotFound). Make each dir process-unique.
Test-only; no public API change.
Co-Authored-By: claude-flow <ruv@ruv.net>
- tests/honest_labeling.rs: 10 source-presence tests asserting the A1-A5 claim
invariants (disclaimers present, uncited stat removed, WEAPON_ALERT no longer
exported, med_* feature-gated, no static-mut event buffers). Each is designed to
FAIL on the pre-fix source (ADR-159 A5 manifest-roundtrip style).
- ADR-160: records the headline (0 stubs/0 theater, all real DSP -> claim-surface
honesty debt), the graded A1-A5 fixes, NO-ACTION positives, per-prefix
classification, and the DATA-GATED deferred backlog (criterion benches,
per-skill accuracy validation, wasm32 static_mut_refs CI confirmation).
- ADR-159: its deferred-backlog line "wasm-edge ... honestly labelled, not claimed"
is now actually TRUE.
Validation (all 0 failed, host --features std):
DEFAULT 615 | MEDICAL (+medical-experimental) 653 | NO-DEFAULT 615; 0 warnings.
Co-Authored-By: claude-flow <ruv@ruv.net>
The wasm-edge skill library runs real DSP with 0 stubs / 0 theater; the exposure
is an over-confident claim surface on unvalidated skills plus a latent static-mut
soundness issue. Make the labels TRUE (do not pretend to validate the capability)
and fix the soundness mechanically:
- A1 (HIGH): med_seizure/cardiac/respiratory/sleep_apnea/gait -- add mandatory
"EXPERIMENTAL / NOT VALIDATED AGAINST CLINICAL DATA / NOT A MEDICAL DEVICE"
disclaimers, soften assertive verbs to "flags candidate <X>-like signatures",
and gate all 5 behind a NON-default medical-experimental cargo feature so they
cannot be silently shipped. DSP kept.
- A2 (HIGH): exo_happiness_score/exo_emotion_detect -- delete the uncited
"~12% faster" stat, add "speculative, unvalidated affect heuristic; outputs are
NOT measurements of emotion" disclaimers, reframe HAPPINESS_SCORE as a
gait-energy proxy. Math kept.
- A3 (MEDIUM): sec_weapon_detect -- rename EVENT_WEAPON_ALERT ->
EVENT_HIGH_METAL_REFLECTIVITY and WEAPON_RATIO_THRESH -> HIGH_REFLECTIVITY_THRESH
(a variance ratio measures reflectivity, not weapons). Registry updated.
- A4 (MEDIUM): exo_dream_stage/exo_gesture_language -- add experimental
disclaimers, promote the Exotic/Research tag into the header.
- A5 (MEDIUM, soundness): replace ~61 `static mut EVENTS`/EV/TE/EMPTY per-call
scratch buffers (60 modules) with owned per-instance `events` fields returned as
`&self.events[..n]`. Public signature unchanged; behavior preserved. Only the
two legitimate single-threaded WASM module singletons (lib.rs STATE,
ghost_hunter DETECTOR) remain as static mut. Removes the static_mut_refs source.
NO-ACTION positives (cited, labels untouched): qnt_* (quantum-/Grover-inspired,
disclosed), exo_time_crystal, exo_ghost_hunter, sig_*/lrn_* algorithm-named skills.
Co-Authored-By: claude-flow <ruv@ruv.net>
Matter commissioning is deferred to v0.8 (TlsConfig::Off, LAN-only, per
tls_defaults_to_off_for_v1_lan_only). Soften the Cargo.toml description
from "Home Assistant + Matter integration" to "Home Assistant (MQTT)
integration ... Matter Bridge commissioning is deferred to v0.8 and not
yet implemented" (honest-absence, ADR-158 pattern). No code change.
Co-Authored-By: claude-flow <ruv@ruv.net>
RemoteIdBroadcast::update stored NED metres (state.position.x/.y) into
drone_lat/drone_lon, so the ASTM F3411 broadcast would carry physically
-impossible coordinates ("latitude = 37.5 m"). The module doc claimed a
Location/Vector message but only encode_basic_id() exists.
- Rename drone_lat/drone_lon -> drone_north_m/drone_east_m (NED metres
relative to the operator/takeoff datum), documented as non-geodetic.
operator_lat/lon stay true WGS84.
- Correct the module doc to claim Basic ID only; Location/Vector encoding
is deferred until a datum-anchored NED->WGS84 transform lands.
Never broadcast physically-impossible coordinates.
Failing-on-old test:
security::remote_id::tests::test_ned_offset_stored_as_metres_not_latlon.
Co-Authored-By: claude-flow <ruv@ruv.net>
cmd_manifest emitted a null skeleton (binary_sha256: null) while the
real signed manifest existed on disk at
cog/artifacts/manifests/<arch>/manifest.json.
- New manifest module include_str!-embeds the real signed manifests
(x86_64 + arm), selected by build target arch.
- cmd_manifest parses-then-emits the embedded signed manifest, mirroring
cog-pose-estimation manifest_roundtrips. CLI now reports the real
binary_sha256, weights_sha256, Ed25519 signature, and honest
build_metadata (training_class1_accuracy = 0.343).
Failing-on-old test:
manifest::tests::embedded_manifest_has_non_null_binary_sha256 (+
embedded_manifest_is_signed, embedded_manifest_id_matches_cog).
Verified end-to-end: cog-person-count manifest -> non-null sha256.
Co-Authored-By: claude-flow <ruv@ruv.net>
The count head has 8 classes but count_train_results.json only has
support for classes 0/1 (presence, not multi-occupant counting). An
argmax on classes 2..=7 is out-of-distribution, yet the cog emitted it
as a confident headcount and the crate billed itself a "multi-person
counter".
- Add MAX_TRAINED_CLASS=1, CountPrediction::is_low_confidence() and
clamped_count().
- person.count events now carry low_confidence + raw_count, downgrade to
level "warn" when OOD, and clamp the reported count to the trained
range (no fabricated headcount).
- run.started discloses count_max_trained_class / count_classes.
- Cargo.toml description: "multi-person counter" ->
"presence detector + (data-gated) person count".
Multi-occupant accuracy stays DATA-GATED (not fabricated).
Failing-on-old test: untrained_class_argmax_is_flagged_low_confidence.
Co-Authored-By: claude-flow <ruv@ruv.net>
pose_v1 has no confidence head, so infer() emits a constant 0.185 per
frame. The config default_min_confidence was 0.3 and the runtime gates
on confidence >= min_confidence, so a default install silently emitted
ZERO pose.frame events while health reported healthy.
- Add inference::MODEL_TYPICAL_CONFIDENCE (0.185, the validation PCK@50)
as the single published per-frame confidence.
- Pin default_min_confidence() to MODEL_TYPICAL_CONFIDENCE so a default
install clears its own gate and emits.
- Warn at run.started when min_confidence exceeds the model typical
confidence (disclosed, not silent); document the trade-off in the
config field, the JSON schema, and inference.rs.
Failing-on-old test: default_config_emits_frames_with_real_model
(with old 0.3 it panics: "default install would emit zero pose.frame
events").
Co-Authored-By: claude-flow <ruv@ruv.net>
An external audit correctly found the person-ID/Soul-Signature capability was
spec-only with a no-op oracle. The §3.6 matcher is now real (wifi-densepose-bfld)
but WiFi-only channels are MEASURED not-separable (cardiac+respiratory gap ~0.0005);
named identity is data-gated on enrollment with the decisive AETHER/body-resonance
channel. README now frames person re-id as experimental research, not a shipped feature.
Co-Authored-By: claude-flow <ruv@ruv.net>
The semantic recognizer built a ruvector-core VectorDB at ":memory:"; under
full-workspace feature unification the file-storage backend is enabled and
":memory:" is an invalid Windows filename (os error 123), panicking via
.expect(). Replace the external index with an exact in-memory cosine k-NN over
the enrolled exemplars (embeddings are L2-normalised, so cosine = dot product).
For HOMECORE's small intent vocabularies this is faster, fully deterministic,
and removes the storage backend + cross-crate feature coupling entirely.
ruvector-core dropped from the crate (only used here). Workspace 3122 passed/0 failed.
Co-Authored-By: claude-flow <ruv@ruv.net>
hardware_adapter read_esp32_csi/read_udp_csi/read_pcap_csi returned 'not yet
implemented'. Wired them to the real CsiParser/PcapCsiReader that already live in
csi_receiver:
- UDP: bind + recv + parse (auto-detect) -> CsiReadings. End-to-end test sends a
real JSON datagram on the wire and parses it.
- PCAP: load + read_next + parse. End-to-end test writes a real little-endian
.pcap with one record and reads it back.
- ESP32: parse CSI_DATA CSV via the real parser; live serial byte I/O behind an
optional feature (native serialport gated off the default/appliance
build) — without it, live reads return a typed UnsupportedAdapter while the
byte parser still works (tested).
Intel5300/Atheros/PicoScenes now return typed HardwareUnavailable/UnsupportedAdapter
(no device/driver/validatable-format here) instead of fake CSI — added
AdapterError::HardwareUnavailable and ::UnsupportedAdapter. Test asserts the gated
adapters error honestly.
Co-Authored-By: claude-flow <ruv@ruv.net>
estimate_gdop returned an average-pair-angle factor merely labelled GDOP (the same
class of defect ADR-156 §2.3 fixed). Replaced with the genuine Geometric Dilution
of Precision computed from the range-measurement Jacobian H (unit target->sensor
bearings): GDOP = sqrt(trace((HtH)^-1)), dimensionless, returning None for singular
(collinear) geometry which the caller treats as factor 1.0. Tests assert a
well-spread array yields lower GDOP than a near-collinear one, cross-check the
closed form, and confirm singular geometry returns None.
Co-Authored-By: claude-flow <ruv@ruv.net>
The comment claimed interpolation but the function returned the bin center,
capping breathing-rate resolution at +/-half a bin. Implemented quadratic
(3-point parabolic) peak interpolation: delta = 0.5*(yL-yR)/(yL-2y0+yR), clamped
to [-0.5,0.5], with an edge fallback to bin center. For a parabola-shaped peak the
recovery is exact (delta=0.4 for a true peak at bin 10.4). Test asserts the result
lands within half a bin of truth and strictly beats the old bin-center estimate.
Co-Authored-By: claude-flow <ruv@ruv.net>
simulate_rssi_measurements always returned vec![], so every survivor got
location: None, which disabled spatial dedup — one person re-detected across N
scan cycles became N survivors, fabricating a mass-casualty event. Two fixes:
1. Real RSSI source: SensorPosition gains an optional last_rssi (populated by the
hardware layer from actual signal-strength readings). collect_rssi_measurements
reads only real per-sensor RSSI and feeds the existing triangulator; it NEVER
fabricates a value. <min_sensors real readings -> None location (honest).
2. Zone + vitals-signature dedup: when no usable location exists, record_detection
matches an existing active, un-located survivor in the same zone whose latest
vital signature (breathing presence + START rate band, heartbeat presence,
movement class) is compatible — collapsing repeat detections of one person while
keeping genuinely distinct survivors (different rate bands) separate.
Tests (fail on old code): 3x identical-vitals/None-location -> 1 survivor (was 3);
distinct vitals stay 2; real-RSSI path yields a position; no-RSSI path yields None.
Co-Authored-By: claude-flow <ruv@ruv.net>
The ensemble gate (EnsembleClassifier::determine_triage) and the survivor
record (Survivor::new -> TriageCalculator::calculate) used two different
START-protocol approximations with different rate bands and movement handling.
The pipeline gated on the ensemble triage then discarded it and recomputed via
TriageCalculator, so a survivor could be admitted as one priority and recorded
as another (e.g. 28 bpm + Tremor: gate said Delayed, record said Immediate).
In a mass-casualty tool that divergence is a life-safety defect.
determine_triage now delegates to TriageCalculator (the single source of truth),
retaining only the ensemble confidence gate (low confidence -> Unknown, except
Immediate which is never suppressed). Updated unit + integration tests to the
canonical expectations and added a divergent-boundary regression asserting
gate triage == survivor-record triage.
Co-Authored-By: claude-flow <ruv@ruv.net>
Realistic depth backprojection is dense (many points per 8 cm voxel). Sweep
points-per-cell {4,16,64,256} at n=50k instead of point-count, so the
measurement reflects where the 9-pass→2-pass reduction actually applies.
Parity guard (old≡new, bit-for-bit) holds at every density.
Co-Authored-By: claude-flow <ruv@ruv.net>
Replace the `Tensor::randn` stubs in occworld-candle's VQVAE encoder
(`encode_occupancy`) and decoder (`decode_to_logits`) with a real,
deterministic, input-dependent convolutional forward pass. Previously
`predict()` emitted trajectory waypoints + confidence that were a function
of RANDOM NOISE, independent of the input and silently presented as model
output — the exact "AI slop" the project must eliminate.
occworld-candle:
- New `cnn.rs`: `Encoder2D` (3× Conv2d + GELU, interpolate2d to pin the
token grid) and `Decoder2D` (upsample_nearest2d + Conv2d + 1×1 head).
Both are deterministic functions of the input — same input → identical
output; different input → different output. No randn in any forward path.
- Deterministic weight init (`det_fill`, seeded xorshift64*) across all
`dummy()` constructors (encoder/decoder, VQ codebook, quant-convs,
transformer), so untrained engines are bit-for-bit reproducible.
- `InferenceOutput.weights_trained: bool` — honest disclosure flag. `false`
for `dummy()` (real but untrained net), `true` only after `load()` reads a
real checkpoint. Priors are always from the real forward pass, never faked.
- VQ codebook + quant/post-quant convs kept and wired encoder→VQ→decoder.
- Centerpiece tests in `tests/predict_honesty.rs` (input-dependence,
run-to-run + cross-engine determinism, untrained flag). All three FAIL on
the old randn stub (verified by temporarily reinstating randn).
pointcloud:
- Optimize `to_gaussian_splats` hot path: 9 separate `.iter().sum()` passes
per voxel → 2 fused accumulation passes. Bit-identical output.
- `benches/splats_bench.rs` (criterion) measures old 9-pass vs new 2-pass
with a parity guard. ~1.3× faster on representative cloud sizes.
- Confirmed: no `randn`/placeholder in any claimed production path. The
remaining synthetic generators (`send_test_frames`, `demo_depth_cloud`)
and honestly-flagged heuristics (`heuristic_pose_from_amplitude`,
luminance pseudo-depth fallback) are explicitly disclosed, not faked output.
DATA-GATED: a trained checkpoint. An untrained-but-real net is the honest
deliverable; accuracy is flagged via `weights_trained`, never claimed.
Tests: occworld 16 unit + 3 integration + 2 doc, pointcloud 18 — all pass
(CPU `Device::Cpu`; CUDA feature is GPU-gated and untouched).
Co-Authored-By: claude-flow <ruv@ruv.net>
Implements the three placeholder paths with real, tested behaviour and an
honest typed result wherever a capability is genuinely data-gated.
homecore-assist:
- runner.rs: add LocalRunner — runs the real IntentRecognizer pipeline and
returns a fully-formed RufloResponse (resolved intent + speech). NoopRunner
is now honest: typed NotStarted before spawn, explicit empty after (never a
silent fabricated response). A live ruflo-agent.js subprocess remains the
data-gated future path.
- recognizer.rs / semantic_recognizer.rs: real SemanticIntentRecognizer — embeds
the utterance (deterministic feature-hash embedding, new embedding.rs) and runs
ruvector-core HNSW nearest-neighbour search over enrolled exemplars, accepting
matches above a configurable cosine-similarity threshold (default 0.75) and
falling back to regex below it. Measured: paraphrase "turn on the kitchen
light" vs exemplar "turn on the light" -> sim 0.855 (match); "schedule a
dentist appointment" -> sim 0.106 (no-match). `semantic` feature on by default.
homecore-recorder:
- db.rs: search_states_by_text — real SQL LIKE query over entity_id/state/attrs
returning real rows (newest-first, k-capped, LIKE-escaped). search_semantic now
falls back to it when the vector index yields no hits, so it is no longer
always-empty under the default NullSemanticIndex.
Tests (real behaviour; each fails on the old always-empty stub, verified):
- homecore-assist: 39 passed / 0 failed
- homecore-recorder (P1, no features): 19 passed / 0 failed
- homecore-recorder (P2, --features ruvector): 25 passed / 0 failed
All files < 500 lines; homecore-server consumer still builds.
Co-Authored-By: claude-flow <ruv@ruv.net>
wifiscan (Tier 2 wlanapi adapter ONLY):
- Real native wlanapi.dll BSS-list FFI (new adapter/wlanapi_native.rs):
WlanOpenHandle -> WlanEnumInterfaces -> WlanGetNetworkBssList ->
WlanFreeMemory/WlanCloseHandle via windows-sys 0.59 (already in lock
tree). Per-BSSID RSSI(dBm)/channel/band/radio-type/SSID + CSI-capable
filter. #[cfg(windows)] real path; #[cfg(not(windows))] returns typed
WifiScanError::Unsupported (honest, never fabricated).
- wlanapi_scanner now native-first with documented netsh fallback,
native_scans metric, scan_native()/scan_native_csi_capable(), and a
benchmark() that MEASURES real Hz (no hardcoded "10x" claim).
- MEASURED 9.74 Hz native on ruvzen (30 iters, Native backend) vs netsh
~2 Hz baseline. Live measurement kept as an #[ignore] test.
- Cargo.toml: unsafe_code forbid->deny so only the audited wlan_ffi
module opts into unsafe; all unsafe confined + null-checked + freed.
sensing-server (Matter commissioning):
- Replaced the lossy modulo placeholder in matter/commissioning.rs with
the real Matter Core Spec 1.3 §5.1.4.1.1 field-packing. Canonical
vector (20202021, 3840) now encodes to the published 34970112332.
- Added ManualPairingCode::decode + DecodedManualCode proving the code
is real/lossless (passcode round-trips bit-for-bit; short
discriminator = top 4 bits) with Verhoeff integrity, incl. proptest.
Tests: wifi-densepose-wifiscan 145 passed (real FFI exercised on
Windows); wifi-densepose-sensing-server 614 passed. 0 failed.
Co-Authored-By: claude-flow <ruv@ruv.net>
Update specification.md §3.6 ONLY with an honest implementation-status note:
the matching algorithm is now implemented and tested in
v2/crates/wifi-densepose-bfld/, weights remain unvalidated design intent, and
named-identity locking is data-gated (cardiac+respiratory alone are not
separable — measured gap ~0.0005). The broader Soul Signature system remains
Pre-Implementation.
Co-Authored-By: claude-flow <ruv@ruv.net>
First running implementation of the spec's §3.6 per-channel weighted-cosine
matcher (docs/research/soul/specification.md). Replaces reliance on NullOracle
(which always returns NotEnrolled) with a real EnrolledMatcher oracle.
- soul_channels.rs: 8-channel SoulChannels container (AETHER reuses
IdentityEmbedding, preserving invariant I2 — no Clone/Serialize, zeroized on
Drop), MatchWeights with the §3.6 default table (unvalidated design intent),
heapless FeatureVector. no_std-compatible.
- soul_match.rs: match_score() implementing the exact formula
Σ w·cos / Σ w·availability, with graceful degradation, zero-norm/NaN safety,
and a typed 'insufficient channels' result (never a default-high score).
EnrolledMatcher (std) satisfies the existing SoulMatchOracle trait, gated on
a score threshold AND a minimum shared-channel count (so a single low-weight
channel can never lock identity). NullOracle retained as the disabled default.
Named-identity locking remains data-gated: it requires real AETHER enrollment +
body-resonance data, which has not been provided.
Co-Authored-By: claude-flow <ruv@ruv.net>
Documents Milestone 3 across the four acquisition crates (vitals, hardware,
wifiscan, calibration). Honest headline: this layer was already well-hardened,
so the real work is small.
- §A1 (perf, MEASURED): Vec::remove(0) O(n^2) sliding windows -> VecDeque.
End-to-end win is NULL within noise at realistic window sizes (DSP dominates);
the win is the algorithmic O(n^2)->O(n) shown in isolation. Claimed nothing
more -- the committed bench proves the null.
- §A2 (correctness): breathing partial-weights scale-mixing -> normalized by
Sigma(effective weights). Pinned by two fail-on-old tests.
- §A3 (stability): IIR resonator divergence. Corrected the research report's
physically-inaccurate trigger (divergence needs |r|>=1, i.e. bw>=4, not "r
negative"); clamp + finite-guard. Pinned by two fail-on-old tests.
- §B1 hardening on an unreachable (already-gated) truncation path -- disclosed.
- §B4 (constant-time HMAC compare) DEFERRED: not worth a new direct `subtle`
dependency for an 8-byte LAN sync-beacon tag.
- MEASURED negative-results section (the centerpiece): esp32_parser length gate,
sync_packet infallible slices, the whole ieee80211bf validate-on-deserialize /
no-panic-FSM / single-role / SBP-single-evaluate model, secure_tdm HMAC+replay,
netsh_scanner fixed-argv + Option parse, geometry_embedding MAX_COORD_M -- each
cited file:line, all NO-ACTION.
- SOTA landscape: deep-CSI vitals (DATA-GATED), 802.11bf conformance (CLAIMED,
non-public suite), per-room calibration (CLAIMED on numbers), native wlanapi
FFI multi-BSSID (CLAIMED-unmeasured -- explicitly NOT claiming the 10x). Mostly
NO-ACTION / ACCEPTED-FUTURE.
- Deferred backlog (§8): nothing silently dropped.
Validation: cargo test --workspace --no-default-features = 3054 passed / 0
failed; python verify.py = VERDICT PASS (hash unchanged, Rust-only changes).
Co-Authored-By: claude-flow <ruv@ruv.net>
OpportunisticCsiBridge::ingest built CsiReportPayload.n_subcarriers via
`self.amp_accum.len() as u16`, which would silently wrap a count above 65_535.
Replace with `u16::try_from(...).ok()?` (drop-instead-of-truncate). Disclosed
honestly as defense-in-depth on an UNREACHABLE path: ingest already gates
subcarrier_count > MAX_REPORT_SUBCARRIERS (484) at entry and report.validate()
rejects oversized counts downstream, so the cast can never wrap in practice.
Correct-by-construction rather than gate-dependent; no behavior change, no new
test (the gate prevents the input that would exercise it).
Co-Authored-By: claude-flow <ruv@ruv.net>
§A2 (correctness): BreathingExtractor weighted fusion was an un-normalized sum.
When `weights` was supplied shorter than n, supplied entries were used raw while
the missing tail defaulted to uniform 1/n -- two scales summed with no
renormalization, silently mis-scaling the breathing signal by a factor of
weights.len(). Extract to fuse_weighted_residuals() and normalize by
Sigma(effective weights), mirroring heartrate::compute_phase_coherence_signal.
Tests: partial_weights_are_renormalized_not_scale_mixed,
partial_weights_fusion_is_weighted_average (both fail on old code).
§A3 (stability): the IIR resonator pole radius r = 1 - bw/2 diverges when the
pole MAGNITUDE |r| >= 1 (i.e. bw >= 4: a very low fs relative to band width) --
NOT merely when r is negative, as the research report stated (a negative r with
|r| < 1 is still stable; the comments/tests are corrected accordingly). On
divergence the filter overflows to +/-inf within ~600 frames, NaN-poisons acf0,
and the extractor stalls permanently. Clamp r to [0, 0.9999] AND finite-guard
the filter output before the history push (defense-in-depth, mirrors ADR-154 §3).
Applied to both heartrate.rs and breathing.rs. Tests:
{heartrate,breathing}::low_sample_rate_filter_stays_finite (fs=0.5, 0.1-0.9 Hz
band, 600-frame unit step -> all-finite; both panic on old code).
These files also carry the §A1 VecDeque window conversion (bit-identical).
Co-Authored-By: claude-flow <ruv@ruv.net>
Replace Vec::remove(0) (O(n) per-sample buffer shift -> O(n^2) full-window
sweep) with VecDeque push_back/pop_front (O(1) eviction) in the fixed-length
sliding/ring buffers of the vital-sign and wifiscan extractors. Where the
autocorrelation / zero-crossing / Pearson loop needs a contiguous slice,
make_contiguous() is called once per extract(), matching the idiom already used
in wifiscan/pipeline/orchestrator.rs. Output is bit-identical.
Sites: anomaly.rs (rr/hr history), store.rs (readings ring; history() now takes
&mut self to hand back a contiguous slice, no external callers), wifiscan
breathing_extractor.rs (filtered history), wifiscan correlator.rs (per-BSSID
histories -> Vec<VecDeque<f32>>). (heartrate.rs/breathing.rs windows land with
the §A2/§A3 fixes in a separate commit.)
New criterion bench crates/wifi-densepose-vitals/benches/vitals_bench.rs drives
each extractor over a full-window fill. Honest MEASURED result: end-to-end win
is NULL within noise at realistic ESP32 window sizes (1500-3000) because the
per-frame DSP dominates the eviction (heartrate 42.8ms->44.4ms, breathing
7.95ms->7.86ms, overlapping CIs). In isolation the eviction collapses O(n^2)
-> O(n) (34.6x at window=3000, 3158x at window=100000); A1 lands as the correct
data structure removing a latent O(n^2), NOT a claimed hot-path speedup.
Reproduce: cargo bench -p wifi-densepose-vitals --bench vitals_bench
Co-Authored-By: claude-flow <ruv@ruv.net>
MultistaticArray::fuse / fuse_ungated cloned every viewpoint embedding twice per
fusion (once into `extracted`, again when building the attention input). Now the
embeddings are MOVED out of `extracted` (one clone per viewpoint instead of two),
capturing geometry/ids by Copy in the same pass. Correctness-neutral — all 100
viewpoint/mat lib tests pass unchanged.
MEASURED (new benches/fusion_bench.rs, embedding_extract A/B, 8 vp x 128-d):
before_double_clone 1.0029 us -> after_single_clone 461.6 ns (~2.17x)
End-to-end fusion_pipeline (8 vp): 202 us — marshalling is <1% of fusion
(n*n attention dominates), so end-to-end win is modest; the A/B isolates the
clone elimination. Reproduce:
cargo bench -p wifi-densepose-ruvector --bench fusion_bench
Co-Authored-By: claude-flow <ruv@ruv.net>
Security fix: two functions on a fusion/localisation path that can carry
network-sourced multistatic frames panicked on crafted input (remote DoS).
- triangulation::solve_triangulation indexed ap_positions[0] (empty table) and
ap_positions[i]/[j] (crafted out-of-range AP index in a TDoA tuple). Now uses
.first()? / .get(i)? / .get(j)? — returns None, never panics.
- heartbeat::band_power computed n_freq_bins-1 (usize underflow on a zero-bin
spectrogram) and did not clamp low_bin. Now guards n_freq_bins==0 and clamps
both bounds into [0,last]; returns 0.0 for empty/inverted ranges.
Tests (each panics on old code, verified by revert):
triangulation_out_of_range_index_returns_none_no_panic,
triangulation_empty_ap_positions_returns_none_no_panic,
heartbeat_band_power_zero_bins_no_panic,
heartbeat_band_power_out_of_range_bounds_no_panic.
Co-Authored-By: claude-flow <ruv@ruv.net>
Two correctness/integrity fixes on the cross-viewpoint fusion geometry path,
each pinned by a regression test that fails on the old code.
- GDOP mislabel (§2.3): CramerRaoBound.gdop was `sqrt(crb_x+crb_y)` — identical
to rmse_lower_bound (metres, noise-dependent), NOT a dimensionless GDOP. Now
computes true GDOP = sqrt(trace(G^-1)) on the unit-variance bearing geometry,
in both estimate() and estimate_regularised(); INFINITY (not NaN) for
degenerate collinear geometry. Test gdop_is_dimensionless_and_noise_independent
asserts GDOP is unchanged under 10x noise while RMSE scales 10x (old code
failed: it scaled with noise, proving it was RMSE).
- Angular wrap (§2.1): GeometricBias::build_matrix used raw |delta-azimuth|
(can exceed pi, mis-states the 0/2pi seam) instead of the wrapped distance.
angular_distance made pub and reused as the single canonical helper. HONEST:
under the current cos() kernel this is a NUMERIC NO-OP (cos is even/periodic,
cos(raw)==cos(wrapped)); landed for contract correctness + single-source-of-
truth + future non-even kernels, not as a behaviour change. Tests pin the
contract (wrapped value in [0,pi], seam symmetry).
ruvector lib tests: 100 passed / 0 failed (+ new tests).
Co-Authored-By: claude-flow <ruv@ruv.net>
Records the integrity-critical fixes (unified canonical metric, leak-free
subject-disjoint split + synthetic-val disclosure, rapid_adapt real gradients,
proof margin + committed-hash rigor), the Tier-2 correctness/security fixes, the
measured Tier-3 perf win, the NN SOTA landscape graded MEASURED/CLAIMED/
THEORETICAL (GraphPose-Fi as top ACCEPTED-future candidate; INT4; CSI-JEPA-vs-MAE
with the honest "no JEPA/MAE-on-WiFi-pose yet" caveat; "Mamba-CSI-pose does not
exist"), and the ~45-finding deferred backlog. Discloses the libtorch/tch-gating
limitation and that the Rust proof is honestly in SKIP until a baseline is
committed.
Co-Authored-By: claude-flow <ruv@ruv.net>
- onnx.rs ORT input: arr.as_slice() single-memcpy fast path with iterator
fallback for strided views. MEASURED [1,256,64,64]: 1.972ms -> 1.336ms
(~1.48x). Repro: cargo bench -p wifi-densepose-nn --no-default-features
--features onnx --bench onnx_bench -- onnx_input_copy
- onnx.rs checked_output_dims: reject ONNX dim <= 0 (incl. unresolved -1) before
allocation (config-OOM class) + test.
- onnx_concurrency bench: empirically proves the per-inference write lock
serializes (throughput drops with more threads). The intended read-lock win is
NOT landable on ort 2.0.0-rc.11 (safe Session::run is &mut self, verified) and
is deferred to the backlog with the upgrade path documented in-code.
New committed fixture tests/fixtures/tiny_conv.onnx (666 B, not gitignored).
Co-Authored-By: claude-flow <ruv@ruv.net>
Each fix ships a test that would have caught the bug:
- ruview_metrics OKS: derive scale from GT extent (no s=1.0 fake-Gold), reject
s<=0, bound the loop to array extents (no panic on short/adversarial input).
- config.validate(): UPPER bounds on window_frames/subcarriers/backbone_channels/
heatmap_size/keypoints/body_parts/batch_size + reject negative gpu_device_id
(closes the config-OOM class); defaults+presets still validate.
- subcarrier.rs: graceful fallback instead of panic on non-contiguous input.
- ablation.rs latency_percentiles: total_cmp + NaN guard (no partial_cmp unwrap).
- tensor.rs softmax(axis): normalize per-lane along the given axis (was whole-
tensor), out-of-range axis -> NnError; fixes densepose per-pixel probs.
- translator.rs apply_attention: real scaled-dot-product attention (was a
uniform 1/seq_len stub that made any "with attention" ablation == without);
mis-shaped checkpoint projections rejected.
Co-Authored-By: claude-flow <ruv@ruv.net>
The deterministic proof self-certified: PASS on any loss decrease (incl. 1e-9
noise) and a missing expected hash defaulted to PASS.
- MIN_LOSS_DECREASE=1e-4: a run counts as learning only above float noise; a
noise-only pipeline now FAILS.
- is_pass() requires hash_matches==Some(true); no-hash -> SKIP (exit 2), never
PASS. verify-training fails fast on a sub-margin loss before the hash compare,
so a missing baseline cannot mask a non-learning pipeline.
Documented honestly: the proof certifies reproducibility/determinism on a
synthetic dataset, NOT that real data produced the weights nor that any accuracy
claim is met. Tests: no_committed_hash_is_skip_not_pass,
submargin_loss_change_fails_even_without_hash,
committed_matching_hash_with_real_decrease_passes.
Co-Authored-By: claude-flow <ruv@ruv.net>
contrastive_step/entropy_step wrote a fake gradient (grad += v*0.01) unrelated
to the stated objective, so any "TTA improves the metric" was unsupported. The
*_loss functions are now pure evaluators of the real objective; adapt() descends
them with a central finite-difference gradient of that exact loss, so "the
adaptation loss decreases" is now a real, reproducible measurement.
Honest scope caveat (documented): this minimizes a self-supervised proxy over a
LoRA bottleneck on raw CSI; it is NOT wired to the pose model and there is NO
measured end-to-end PCK gain on WiFi pose from this path.
Tests: contrastive_loss_decreases, entropy_loss_decreases (real gradient steps
don't increase the loss), reported_loss_is_the_real_objective_not_a_placeholder.
Co-Authored-By: claude-flow <ruv@ruv.net>
MM-Fi windows are stride-1 (~99% overlap), so an index-level split leaks; and
bin/train.rs validated real training against a SYNTHETIC val set, making any
printed PCK meaningless on two counts.
- MmFiDataset::subject_disjoint_split partitions whole subjects -> the two views
share no subject and no window (leak-free by construction, deterministic per
seed). assert_split_leak_free verifies subject- AND window-disjointness and is
called inside the split so a leaky split is never handed out.
- bin/train.rs now prefers the real split; the synthetic path is a labelled
run_smoke_test ("[SMOKE-TEST] DO NOT REPORT") reachable only as a fallback.
- New DatasetError::InvalidSplit.
Tests prove disjointness, determinism, single-subject/bad-fraction rejection,
and that the validator catches an injected subject leak.
Co-Authored-By: claude-flow <ruv@ruv.net>
Collapse the four PCK and three OKS implementations into a single source of
truth — pck_canonical (torso hip↔hip, COCO/ADR-152 convention validated at
~96% PCK@20 in benchmarks/wiflow-std) and oks_canonical (scale from GT pose
extent). MetricsAccumulator, compute_pck/_per_joint/_oks, aggregate_metrics and
the deprecated *_v2 path all route through them, so Trainer::evaluate() and the
bench definition agree.
Fixes two claim-inflating bugs, each pinned by a regression test:
- zero-visible-joint PCK was 1.0 (false-perfect) -> now 0.0
- OKS s=1.0 on normalized coords made OKS~=1.0 for any pose ("fake Gold tier")
-> scale now derived from the pose; a 3x-torso-wrong pose yields OKS<0.2
Divergent local kernels (training_bench raw-threshold, sensing-server
torso-height) annotated "DO NOT USE for reported metrics". Legitimately changed
test expectations (all-coincident "perfect" fixtures are correctly unscoreable;
all-invisible -> 0.0) updated with comments citing the finding.
Co-Authored-By: claude-flow <ruv@ruv.net>
Records Milestone-0 of the signal/DSP beyond-SOTA sweep with full PROOF
discipline (MEASURED vs CLAIMED vs THEORETICAL grading throughout):
- §2 discloses the headline anti-slop finding: the ADR-134 CIR coherence gate
was DEAD in production (canonical-56 frames -> SubcarrierMismatch -> silent
freq-domain fallback for every frame). Documents the canonical56() fix + the
4 committed proof tests.
- §3 NaN/inf adversarial bypass; §4 divide-by-(n-1) window trio.
- §5 the two MEASURED perf wins with before/after medians + reproduce commands.
- §6 per-module SOTA landscape, evidence-graded: deep-unfolded ISTA/LISTA for
CSI->CIR (~3 dB NMSE, MEASURED, arXiv 2211.15440 + 2502.05952), diffusion CIR
prior (public weights, MEASURED), Wi-Spoof adversarial eval (MEASURED, arXiv
2511.20456), Bayesian multi-AP fusion (CLAIMED, no code, 2512.02462),
coherence gating + RF intention-lead (THEORETICAL).
- §7 roadmap: LISTA-for-CIR as the top ACCEPTED-future item (M effort; the ISTA
+ Phi already exist in cir.rs) — proposed, NOT implemented this milestone —
plus the explicit deferred-findings backlog (the ~45 review findings not
fixed here, graded P1/P2/P3) so nothing is silently dropped, with a
horizon-ledger DONE-vs-DEFERRED one-liner.
Co-Authored-By: claude-flow <ruv@ruv.net>
Two measured, bit-equivalent perf wins. Each ships a criterion bench
(benches/features_bench.rs, new) with before/after numbers and a committed
bit-identity test — no perf claim without a measured before/after.
PSD FFT-planner caching (features.rs)
PowerSpectralDensity::from_csi_data re-planned a FftPlanner on EVERY frame,
and FeatureExtractor::extract calls it per frame on the hot path. New
from_csi_data_with_fft(csi, n, &Arc<dyn Fft>) reuses a plan cached in
FeatureExtractor (built once in new()). Bit-identical output
(psd_cached_fft_bit_identical_to_fresh, f64::to_bits over 6 sizes).
MEASURED (median ns/frame, criterion):
fft=64 5.84µs -> 1.89µs (3.09x)
fft=128 9.31µs -> 3.61µs (2.58x)
fft=256 13.77µs -> 6.73µs (2.04x)
DTW Sakoe-Chiba band (gesture.rs)
dtw_distance computed j_start/j_end but iterated the FULL 1..=m row,
continue-ing out-of-band — band constrained the path, not the work (O(n*m)).
Now iterates j_start..=j_end (O(n*band)), resetting only the two boundary
guard cells the recurrence reads, with endpoint reachability (|n-m|<=band)
at the return. Bit-identical across 12 shapes x 8 bands
(dtw_banded_bit_identical_to_fullrow).
MEASURED (median, criterion):
n=m=100 band=5 33.45µs -> 13.77µs (2.43x)
n=m=200 band=5 122.32µs -> 29.55µs (4.14x)
n=m=200 band=10 159.98µs -> 60.19µs (2.66x)
Reproduce:
cd v2 && cargo bench -p wifi-densepose-signal --no-default-features \
--bench features_bench
Co-Authored-By: claude-flow <ruv@ruv.net>
Milestone-0 correctness/security fixes for the beyond-SOTA signal/DSP sweep.
Every fix ships with a committed regression test (proof, not adjectives).
CRITICAL — ADR-134 CIR coherence gate was DEAD in production
MultistaticFuser fuses canonical-56 frames (hardware_norm.rs resamples every
chipset onto a 56-tone grid), but the gate was wired to CirConfig::ht20()
which expects 64/52. Every estimate() returned SubcarrierMismatch and
cir_gate_coherence silently fell back to freq-domain coherence — use_cir_gate
was indistinguishable from false. Fixes:
- new CirConfig::canonical56() (64-bin HT20 framing, 56 active tones, 168 taps)
- new MultistaticFuser::with_cir_canonical56() (correct default); ht20 kept,
now doc-warned
- active_indices() handles (64,56) + length-matched fallback (no silent
fall-through to the 52-index slice)
- SubcarrierMismatch in the gate now debug_assert!s loudly (config error can
no longer hide as a graceful degrade)
- cir_estimate_first() exposes the Ok/Err verdict for tests
PROOF (ruvsense::multistatic::tests): ht20 → 8/8 Err (dead); canonical56 →
8/8 Ok (alive); coherence(gate on) != coherence(gate off).
CRITICAL — adversarial.rs NaN/inf detector bypass
One non-finite link energy bypassed the whole detector (every `e>thresh`
false on NaN; score clamp returns NaN). A non-finite input is itself the
strongest spoof — now short-circuits to a definite anomaly (score 1.0,
affected link reported) and does not poison the temporal-continuity state.
PROOF: nan_link_energy_flags_anomaly, inf_link_energy_flags_anomaly.
CORRECTNESS — divide-by-(n-1) window trio
csi_processor hamming_window (n=0 usize underflow, n=1 div0), bvp Hann,
spectrogram make_window all guarded for n<=1 (empty / constant-1.0 window).
Python deterministic proof still PASS, same pipeline hash (reference uses n>=2).
PROOF: *_degenerate_sizes / *_size_one_is_finite / make_window_size_0_and_1.
CLARITY — calibration.rs subtract_in_place
Removed the vacuous `if active_input {ki} else {ki}` branch that implied a
full-FFT->bin remap that never existed; documented the sequential
active-index convention (matches sibling extract_first_stream). No behavior
change.
Tests: cargo test -p wifi-densepose-signal --no-default-features (+--features cir)
green; full workspace green; verify.py VERDICT: PASS.
Co-Authored-By: claude-flow <ruv@ruv.net>
The 12-crate brain-topology analysis ecosystem (v2/crates/ruv-neural) was a
self-contained nested workspace with no inbound deps from the v2 workspace
(verified: zero path references outside its own tree). Published standalone
at github.com/ruvnet/ruv-neural and re-attached here as a submodule at the
same path, so the build layout is unchanged while the project gets its own
repo/CI/release cadence.
* docs(research): add RuView beyond-SOTA system review (00)
First document of the beyond-SOTA research series: capability audit of
the current RuView engine with role-to-crate maturity matrix, ruvsense
module inventory, gap analysis, and risk register.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* docs(research): add beyond-SOTA architecture design (02, in progress)
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* docs(research): finalize beyond-SOTA architecture (02)
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* docs(research): add benchmark/validation methodology snapshot (03)
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* docs(research): add beyond-SOTA series index with validation results; changelog
README index ties the 5 research docs together with the session's
measured validation evidence: 2,797 workspace tests / 0 failed, Python
proof PASS (bit-exact), and paired pre/post criterion CIR benchmarks.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* perf(signal): precompute CIR warm-start system; hoist tomography solver allocs
Exact, determinism-safe optimizations (bit-identical float results):
- cir.rs: diag(PhiH Phi)+lambda*I and its CSR matrix depend only on Phi
and lambda (fixed at CirEstimator::new) but were rebuilt every frame
(O(K*G) pass + CSR allocation). Now built once in new() via
build_warm_start_system; summation order unchanged.
- tomography.rs: ISTA gradient buffer hoisted out of the 100-iteration
loop (fill(0.0) reset) and the Frobenius Lipschitz bound moved from
per-reconstruct to construction.
Verified: signal 456 tests green; engine 11/11 green including
cycle_is_deterministic and witness-stability tests. Criterion paired
pre/post: cir_estimate/he40 -3.9% (p<0.01), multiband -1.2/-1.4%.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* fix(worldgraph): bound SemanticState growth with deterministic retention
StreamingEngine::process_cycle appended one SemanticState belief per cycle
with no eviction — ~1.7M nodes/day at 20 Hz (beyond-SOTA roadmap finding #6).
Add WorldGraph::prune_semantic_states(max): deterministic eviction of the
oldest beliefs by (valid_from_unix_ms, id); structural nodes (rooms, zones,
sensors, anchors, tracks, events) are never eligible. Wire it into the
engine after each belief append (DEFAULT_SEMANTIC_RETENTION = 7,200, ~6 min
at 20 Hz; set_semantic_retention to tune). The WorldGraph holds current
beliefs; durable history is the recorder's job, so no audit data is lost.
3 new tests: end-to-end bounded growth, oldest-only eviction, deterministic
equal-timestamp tie-break. Workspace gate: 2,865 passed, 0 failed.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* feat(sensing-server): route live frames through the governed StreamingEngine
Closes the live-trust-path gap (ADR-136 section 8, beyond-SOTA system review):
the running server fused live CSI with the bare MultistaticFuser, while the
privacy/provenance/witness control plane (ADR-135..146) only ever ran on
synthetic in-test frames. The privacy control plane was therefore bypassable
on the real path.
New engine_bridge module drives StreamingEngine::process_cycle from the
server's live NodeState map, reusing the existing NodeState -> MultiBandCsiFrame
conversion. It lazily wires each contributing node as a WorldGraph sensor
(idempotent), bounds belief growth via the retention cap, and forwards explicit
timestamps/calibration ids so the path stays deterministic and replayable.
Wired additively into both live ESP32/WiFi fusion sites in main.rs via a
split-borrow off the write guard, so person-count behavior is unchanged; the
latest BLAKE3 witness is stored on AppState. Every published belief now carries
evidence + model + calibration + privacy decision and a deterministic witness.
Adds wifi-densepose-engine/-worldgraph/-bfld/-geo deps. 6 new bridge tests
(witnessed belief with full provenance, cross-run determinism, idempotent node
registration, retention bound, privacy-mode propagation). sensing-server suite
430+128 green; workspace gate 2,904 passed / 0 failed.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* feat(train): falsifiable occupancy benchmark with anti-overfitting gate
Makes the presence/person-count "beyond SOTA" claim falsifiable in code
instead of aspirational (the unfalsifiability gap from the beyond-SOTA system
review). occupancy_bench grades predictions vs ground truth and gates a SOTA
claim behind one claim_allowed invariant requiring ALL of:
- DataProvenance::Measured — synthetic/mock data is scorable for regression
but never claimable (anti-mock-contamination; the CLAUDE.md Kconfig-bug
lesson made structural).
- A leak-free EvalSplit — validate() refuses any split where a subject OR
environment id appears in both train and test (subject leakage /
per-environment overfitting).
- n_test >= min_test_samples (small-N guard).
- Presence F1 whose bootstrap-CI lower bound (deterministic seeded splitmix64)
clears the threshold — not the point estimate.
- Count MAE within threshold.
The claim string is unreadable except through the gate (NO_CLAIM otherwise),
same discipline as the ruview-gamma acceptance gate. What remains is data, not
method: a frozen, SHA-pinned, subject/environment-disjoint measured replay set
turns the claim into a passing/failing test.
Lives in wifi-densepose-train (the eval bounded context, alongside ablation/
eval/metrics). 10 tests cover each refusal path; warning-clean under the
crate's missing_docs lint. Workspace gate 2,914 passed / 0 failed. Doc 03
updated.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* feat(engine): per-room adapter provenance + drift-to-recalibration advisor
Closes the trust-chain gap where an ~11 KB per-room LoRA adapter (ADR-150
section 3.4) could silently change inference without the witness noticing:
provenance carried only "rfenc-v<N>" with no notion of adapter identity.
- StreamingEngine::set_room_adapter(AdapterInfo): pins the adapter's
content-derived id into provenance model_version
("rfenc-v1+adapter:<id>") — and therefore into the BLAKE3 witness — so
swapping or clearing adapter weights always shifts the witness. Engine test
proves base -> adapter -> other-adapter -> cleared all witness differently
and cleared == base.
- RecalibrationAdvisor: recommends re-running the ADR-135 empty-room baseline
/ refitting the room adapter on sustained low fusion coherence (streak
threshold, default 60 cycles ~ 3 s at 20 Hz) or an ADR-142 change-point.
Surfaced as TrustedOutput::recalibration_recommended, stored on the
sensing-server AppState alongside the witness at both live fusion sites.
- Bridge plumbing: EngineBridge::{set_room_adapter, clear_room_adapter} +
live-path test that the adapter id flows into the live witness.
Scope note (honest): this is the deployable provenance/trigger half of the
"retrained model" roadmap item. Fitting the adapter itself runs in the
existing external calibration service (aether-arena/calibration/); a trained
RF-encoder checkpoint still does not exist in-tree.
Engine 15 tests, bridge 7 tests. Workspace gate: 2,918 passed / 0 failed.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* fix(mat): gate api module behind its feature — standalone no-default-features builds
pub mod api was unconditional while its only dependency, serde, is optional
behind the 'api' feature, so any build without default features failed with
101 unresolved-serde errors (masked in --workspace runs by feature
unification). The api module and its create_router/AppState re-export are now
cfg(feature = "api")-gated with docsrs annotations.
All combos compile: bare --no-default-features (was 101 errors, now 0),
--no-default-features --features api, and full default (177 tests pass).
Workspace gate: 2,918 passed / 0 failed.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* perf(signal): opt-in FFT operator for the CIR ISTA solver (8-14x measured)
Phi is a sub-DFT, so each ISTA mat-vec can run as one length-G FFT
(O(G log G)) instead of a dense O(K*G) product — the dominant-latency-hazard
finding from the beyond-SOTA optimization roadmap.
New CirConfig::fft_operator, default FALSE: the dense path stays the
bit-exact witness default. The FFT evaluates the same sums in a different
order, so enabling it shifts float results in the last bits and requires
regenerating any pinned witness — strictly opt-in per deployment.
FftOperator (rustfft, planned once at CirEstimator::new, scratch buffers
reused across the ISTA loop) dispatches inside ista_solve:
Phi x = scale * forward-FFT(x) sampled at bins (k_idx mod G)
Phi^H v = scale * unnormalised inverse-FFT of v scattered into those bins
Warm-start and Lipschitz estimation stay dense at construction.
Measured (criterion, same run, same machine):
ht20: 2.22 ms -> 265 us (8.4x)
ht40: 10.26 ms -> 717 us (14.3x)
The real HE40 grid (K=484, G=1452) scales further per the O(K*G)/O(G log G)
ratio.
3 new tests: FFT<->dense matvec equivalence to float tolerance on ht20 and
he40 grids; end-to-end dominant-tap agreement on a single-path frame; all
default configs keep FFT off. New cir_estimate_fft bench group.
Workspace gate: 2,921 passed / 0 failed (default path bit-exact, witnesses
unchanged).
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* feat(core): canonical frame decoder — capture-to-claim replay (ADR-136)
The encode half of the ADR-136 frame contract existed (ComplexSample,
to_canonical_bytes, witness_hash) but there was no decoder: a captured
canonical frame could be witnessed but never reconstructed, blocking
replay-from-capture.
CsiFrame::from_canonical_bytes is the exact inverse: same id, metadata,
complex payload, and witness hash (tested as the round-trip law AC7 — the
replayed frame re-encodes byte-identically). Amplitude/phase are recomputed
from the payload (projections, not independent state). Every malformed-input
class fails closed (AC8): header truncation -> Truncated, payload truncation
-> PayloadMismatch, unknown discriminants, non-UTF-8 device id, trailing
bytes. Nil calibration uuid decodes as None per the documented encoding.
Core: 36 tests pass. Workspace gate: 2,937 passed / 0 failed.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* feat(engine): dynamic min-cut mesh partition guard (ruvector-mincut)
Maintains an exact min-cut over the live mesh coupling graph — nodes are
sensing nodes, coupling is the product of fusion attention weights — and
surfaces per cycle, as TrustedOutput::mesh:
- cut value: the global "how close is the array to partitioning" number,
a structural measure per-node heuristics miss;
- weak side: which specific nodes would split off (failure/jamming triage,
feeds ADR-032 posture);
- at-risk flag: counts as a structural event for the drift->recalibration
advisor (alongside ADR-142 change-points).
Degenerate cases fail toward risk: a node with zero coupling is reported as
already partitioned (cut 0, that node as the weak side).
Measured cost policy (criterion, 12-node mesh — the honest part):
- weights quantized (1/64) + change-gated: steady-state cycles do ZERO graph
work and reuse the cached cut (~7.3 us, ~23x cheaper than building);
- on any real change a full exact rebuild (~171 us) is used, because ONE
DynamicMinCut delete+insert measured ~240 us — the subpolynomial machinery
amortizes on much larger graphs, so rebuild-on-change is the measured
optimum at mesh scale (one-edge case -28% after switching policy);
- full process_cycle with the guard: ~33 us for 4 nodes vs the 50 ms budget.
9 mesh_guard tests (weak-node detection, steady-state zero updates,
sub-quantum gating, join/drop rebuild, determinism, disconnection) + an
engine-level wiring test (down-weighted node -> weak side -> recalibration).
Engine 24 tests; workspace gate 2,946 passed / 0 failed.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* feat(engine): mesh partition risk demotes privacy + enters the witness (ADR-032)
Completes the mesh-guard integration: its at_risk signal was advisory-only
(fed the recalibration advisor). It now also contributes to the ADR-141
privacy demotion alongside fusion- and array-level contradictions — a mesh
close to partitioning makes the fused belief less trustworthy, so the cycle
emits at a more restricted class (monotonic; information only removed).
Because effective_class feeds the BLAKE3 witness, a fragmenting array now
shifts the witness: partition risk is auditable, not just logged. The mesh
computation moved ahead of the demotion step in process_cycle; mesh_guard_mut
exposes risk-threshold tuning.
Test: a forced-risk 3-node cycle demotes PrivateHome Anonymous->Restricted
and shifts the witness vs a clean baseline. Engine 25 tests; workspace gate
2,947 passed / 0 failed.
https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
* fix: public-PR review findings — privacy-path honesty, gate holes, mesh-guard cliff
- sensing-server: engine errors logged+counted (no silent swallow), trust
state exposed via status surface, privacy-demotion claims aligned with
the actual parallel-audit-path behavior
- occupancy_bench: vacuous-F1 hole closed (degenerate test sets fail with
their own criterion); CI-lower-bound test made probative
- mesh_guard: quantization scaled to observed coupling range — >=65-node
balanced meshes no longer permanently at_risk (regression test)
- engine: both wiring tests made probative (same-topology witness compare,
deterministic risk-crossing fixture)
- mat: axum/tokio optional behind api; real serde feature (api enables it)
- core: canonical decoder strict (non-zero reserved bytes and nil UUID
rejected — injective on accepted domain, forged-bytes tests)
- CHANGELOG: un-spliced the FFT/adapter bullet mangle
Co-Authored-By: claude-flow <ruv@ruv.net>
* chore: strip private-track references for public PR
Reword the occupancy-benchmark changelog bullet to drop a cross-reference
to the private research track, and restore the WorldGraph retention bullet
header that was glued onto the preceding MAT bullet.
Co-Authored-By: claude-flow <ruv@ruv.net>
* chore: lockfile refresh for cherry-picked feature set
Co-Authored-By: claude-flow <ruv@ruv.net>
---------
Co-authored-by: Claude <noreply@anthropic.com>