|
| 1 | +# ADR-160: Edge Skill Library (`wifi-densepose-wasm-edge`) — Honest Labeling & Soundness Cleanup |
| 2 | + |
| 3 | +- **Status**: accepted |
| 4 | +- **Date**: 2026-06-11 |
| 5 | +- **Deciders**: ruv |
| 6 | +- **Tags**: wasm-edge, esp32, edge-skills, claim-surface, medical-overclaim, affect, prove-everything, soundness, static-mut |
| 7 | +- **Amends**: ADR-159 (deferred-backlog line for wasm-edge now TRUE) |
| 8 | + |
| 9 | +## Context |
| 10 | + |
| 11 | +Beyond-SOTA sweep Milestone 6, over `v2/crates/wifi-densepose-wasm-edge` only, |
| 12 | +executed under the project's **prove-everything / anti-"AI-slop"** directive. |
| 13 | + |
| 14 | +### Headline — 0 stubs, 0 theater, all real DSP (REFUTES the slop accusation) |
| 15 | + |
| 16 | +A read-only audit found this crate has **zero stubs and zero fake-output theater: |
| 17 | +every one of the ~70 edge skills runs real DSP** (Welford statistics, |
| 18 | +autocorrelation, DTW, sliced-Wasserstein, ISTA-style recovery, Kalman/HNSW, etc.). |
| 19 | +The forward paths are genuine signal processing on real CSI-derived inputs. That |
| 20 | +is the anti-slop win and it is cited here as a positive, not a fabrication. |
| 21 | + |
| 22 | +What the audit correctly found was **not fake code but an over-confident claim |
| 23 | +surface**: skill *names* and doc-comments asserting clinical/affective/security |
| 24 | +capabilities that the **unvalidated** code cannot back, concentrated in the |
| 25 | +medical (`med_*`) and affect (`exo_happiness`/`exo_emotion`) skills. The fix is |
| 26 | +**honest labeling — making the labels TRUE — NOT making the claimed capability |
| 27 | +real.** You cannot validate seizure detection, affect inference, or weapon |
| 28 | +discrimination without clinical/labelled data and reference standards; this ADR |
| 29 | +does not pretend to. It disclaims, renames, softens, and feature-gates so the |
| 30 | +surface matches what the DSP actually delivers. |
| 31 | + |
| 32 | +Grading vocabulary follows ADR-152 / ADR-158 / ADR-159: |
| 33 | +- **MEASURED** — reproduced in this worktree, command + failing-on-old test recorded. |
| 34 | +- **DATA-GATED** — real code path present; honestly flagged where data is absent. |
| 35 | +- **NO-ACTION (already-honest)** — audited, found correct, cited as a positive. |
| 36 | +- **ACCEPTED-FUTURE** — deliberately deferred, nothing dropped. |
| 37 | + |
| 38 | +## Per-prefix classification |
| 39 | + |
| 40 | +| Prefix | Class | Note | |
| 41 | +|--------|-------|------| |
| 42 | +| `sig_*` (signal intelligence) | **REAL-DSP, honest** | Algorithm-named (flash-attention, sparse-recovery, optimal-transport, temporal-compress, mincut). Names describe the math, not an overclaimed outcome. NO-ACTION on labels; A5 soundness applied. | |
| 43 | +| `lrn_*` (adaptive learning) | **REAL-DSP, honest** | DTW/EWC/meta-adapt/attractor — algorithm-named. NO-ACTION on labels; A5 applied. | |
| 44 | +| `spt_*` / `tmp_*` | **REAL-DSP, honest** | PageRank/HNSW/spiking-tracker; LTL-guard/GOAP/pattern-sequence. Algorithm-named. NO-ACTION on labels; A5 applied. | |
| 45 | +| `qnt_*` | **REAL-DSP, honest (disclosed analogy)** | "quantum-**inspired**" / Grover-**inspired** are already disclosed analogies. NO-ACTION (DO-NOT-touch); A5 applied (mechanical, no label/behavior change). | |
| 46 | +| `bld_*` / `ret_*` / `ind_*` / `occupancy`/`intrusion` | **REAL-DSP, honest** | Occupancy/queue/forklift/clean-room etc. describe physical observables. NO-ACTION on labels; A5 applied. | |
| 47 | +| `sec_weapon_detect` | **REAL-DSP, overclaiming NAME** → fixed (A3) | Variance-ratio reflectivity renamed off "weapon". | |
| 48 | +| `med_*` (5) | **REAL-DSP, overclaiming NAME/DOC** → fixed (A1) | Clinical detection asserted as fact; now disclaimed + softened + feature-gated. | |
| 49 | +| `exo_happiness` / `exo_emotion` | **REAL-DSP, overclaiming NAME/DOC** → fixed (A2) | Affect outputs reframed as proxies; uncited stat removed. | |
| 50 | +| `exo_dream_stage` / `exo_gesture_language` | **REAL-DSP, quasi-medical/over-named** → fixed (A4) | Disclaimers added; Research tag promoted to header. | |
| 51 | +| `exo_time_crystal` / `exo_ghost_hunter` | **REAL-DSP, honest novelty** | Disclosed exploratory/novelty skills. NO-ACTION (DO-NOT-touch); A5 applied. | |
| 52 | +| `nvsim` | out of scope | Disclaimer gold standard; copied its tone. | |
| 53 | + |
| 54 | +## Decision — Fixes Landed |
| 55 | + |
| 56 | +### §A1 Medical overclaim (HIGH) — MEASURED |
| 57 | + |
| 58 | +The five `med_*` modules (`med_seizure_detect`, `med_cardiac_arrhythmia`, |
| 59 | +`med_respiratory_distress`, `med_sleep_apnea`, `med_gait_analysis`) stated clinical |
| 60 | +detection as fact with no disclaimer ("Detects tonic-clonic seizures…"). |
| 61 | + |
| 62 | +**Real fix (honest labeling — the DSP is kept, untouched):** |
| 63 | +- **(a)** Every module's `//!` header now carries a mandatory disclaimer block, |
| 64 | + modelled on `sec_weapon_detect.rs` and `nvsim/src/lib.rs`: *"EXPERIMENTAL |
| 65 | + RESEARCH MODULE — NOT VALIDATED AGAINST CLINICAL DATA. NOT A MEDICAL DEVICE. |
| 66 | + Flags candidate <X>-like signatures only,"* citing ADR-160. |
| 67 | +- **(b)** Doc verbs softened: *"Detects tonic-clonic seizures"* → |
| 68 | + *"Flags candidate tonic-clonic-seizure-like motion signatures (experimental)"*; |
| 69 | + similarly for cardiac/respiratory/apnea/gait. |
| 70 | +- **(c)** All five gated behind a new **non-default** cargo feature |
| 71 | + `medical-experimental` (`#[cfg(feature = "medical-experimental")]` in `lib.rs`, |
| 72 | + `medical-experimental = []` in `Cargo.toml`, **not** in `default`) so they cannot |
| 73 | + be silently built into a shipping artifact. |
| 74 | + |
| 75 | +**Failing-on-old tests** (`tests/honest_labeling.rs`): |
| 76 | +`a1_med_modules_have_clinical_disclaimer`, |
| 77 | +`a1_med_modules_gated_behind_medical_experimental`, |
| 78 | +`a1_seizure_verbs_softened`. All fail on the old, undisclaimed, ungated source. |
| 79 | +**Grade: MEASURED (label); per-skill clinical accuracy DATA-GATED.** |
| 80 | + |
| 81 | +### §A2 Affect overclaim (HIGH) — MEASURED |
| 82 | + |
| 83 | +`exo_happiness_score.rs` carried an **uncited** "Happy people walk ~12% faster" |
| 84 | +statistic and emits `HAPPINESS_SCORE`; `exo_emotion_detect.rs` emits |
| 85 | +`STRESS_INDEX`/`CALM_DETECTED`/`AGITATION_DETECTED`. |
| 86 | + |
| 87 | +**Real fix (honest labeling — math kept):** |
| 88 | +- Deleted the uncited "12% faster" / "~12% above" / "Happy people walk" statements. |
| 89 | +- Added a prominent *"speculative, unvalidated affect heuristic; outputs are NOT |
| 90 | + measurements of emotion"* disclaimer to both `//!` headers, citing ADR-160. |
| 91 | +- Reframed `HAPPINESS_SCORE` in the docs as a **"gait-energy proxy, not a validated |
| 92 | + affect measure."** |
| 93 | + |
| 94 | +**Failing-on-old tests:** `a2_affect_modules_have_unvalidated_disclaimer`, |
| 95 | +`a2_uncited_12_percent_stat_removed`, `a2_happiness_reframed_as_proxy`. |
| 96 | +**Grade: MEASURED (label); affect validity DATA-GATED.** |
| 97 | + |
| 98 | +### §A3 Security event-name overclaim (MEDIUM) — MEASURED |
| 99 | + |
| 100 | +`sec_weapon_detect.rs`'s module doc was already honest (research-grade, |
| 101 | +calibration-required), but the event/const names claimed weapon-grade |
| 102 | +discrimination a variance ratio cannot deliver. |
| 103 | + |
| 104 | +**Real fix (honest physical-quantity naming — behavior unchanged):** |
| 105 | +- `EVENT_WEAPON_ALERT` → `EVENT_HIGH_METAL_REFLECTIVITY` (event id 221 unchanged). |
| 106 | +- `WEAPON_RATIO_THRESH` → `HIGH_REFLECTIVITY_THRESH`. |
| 107 | +- Internal fields/consts renamed (`weapon_run`→`high_refl_run`, |
| 108 | + `cd_weapon`→`cd_high_refl`, `WEAPON_DEBOUNCE`→`HIGH_REFLECTIVITY_DEBOUNCE`). |
| 109 | +- `lib.rs` `event_types` registry: `WEAPON_ALERT` → `HIGH_METAL_REFLECTIVITY`. |
| 110 | +- A reflectivity-vs-weapons honest-naming note added to the header. |
| 111 | +The detector still flags a high amplitude-variance/phase-variance ratio (real RF |
| 112 | +reflectivity); it just no longer *names* that "weapon". |
| 113 | + |
| 114 | +**Failing-on-old tests:** `a3_weapon_names_renamed_to_reflectivity`, |
| 115 | +`a3_registry_no_longer_exports_weapon_alert` (registry no longer exports a |
| 116 | +`WEAPON_ALERT` name). **Grade: MEASURED.** |
| 117 | + |
| 118 | +### §A4 Quasi-medical / sign-language exotic modules (MEDIUM) — MEASURED |
| 119 | + |
| 120 | +`exo_dream_stage.rs` ("sleep stage classification", quasi-medical) and |
| 121 | +`exo_gesture_language.rs` ("sign language letter recognition"). |
| 122 | + |
| 123 | +**Real fix (honest labeling — DSP kept):** added an experimental "NOT VALIDATED" |
| 124 | +disclaimer to each `//!` header (citing ADR-160) and promoted the |
| 125 | +**Exotic/Research** registry tag into the header where a reader sees it. |
| 126 | +`exo_gesture_language` additionally states it is a coarse gesture-cluster |
| 127 | +classifier that **does not recognize true sign language** (never evaluated on a |
| 128 | +labelled ASL set). |
| 129 | + |
| 130 | +**Failing-on-old test:** `a4_exotic_modules_have_experimental_disclaimer`. |
| 131 | +**Grade: MEASURED (label); accuracy DATA-GATED.** |
| 132 | + |
| 133 | +### §A5 `static mut` event-buffer soundness (MEDIUM) — the one real code fix — MEASURED |
| 134 | + |
| 135 | +~61 per-call event scratch buffers across the crate used a module-level |
| 136 | +`static mut EVENTS: [(i32,f32); N]` (a handful named `EV`/`TE`/`EMPTY`) and returned |
| 137 | +`&EVENTS[..n]`. On a `cdylib`+`rlib` linkable into multithreaded/reentrant host |
| 138 | +code this is latent aliasing UB, and `static_mut_refs` is deny-by-default on newer |
| 139 | +Rust. |
| 140 | + |
| 141 | +**Real fix (mechanical, behavior-preserving):** moved each scratch buffer off |
| 142 | +`static mut` into an **owned per-instance field** (`events: [(i32,f32); N]` on the |
| 143 | +detector struct, written via `&mut self` and returned as `&self.events[..n]`). The |
| 144 | +public `-> &[(i32, f32)]` signature is **unchanged**, so no caller (in-module |
| 145 | +tests, `ghost_hunter` bin, `budget_compliance`) needed editing. Two helper methods |
| 146 | +that built events under `&self` (`spt_pagerank_influence::build_events`, |
| 147 | +`spt_spiking_tracker::build_events`) and `sig_temporal_compress::on_timer` were |
| 148 | +promoted to `&mut self`. Leftover now-redundant `unsafe { }` wrappers were removed. |
| 149 | + |
| 150 | +**Count: 61 scratch buffers across 60 module files fixed** (the only `static mut` |
| 151 | +left in `src/` are the two **legitimate WASM module singletons** — `lib.rs STATE` |
| 152 | +and `bin/ghost_hunter.rs DETECTOR` — `#[cfg(target_arch="wasm32")]`, |
| 153 | +`#[no_mangle]`, accessed via `core::ptr::addr_of_mut!`, single-threaded by the |
| 154 | +wasm runtime contract; these are *not* the aliasing-UB scratch pattern and are |
| 155 | +left as-is). |
| 156 | + |
| 157 | +**Verification:** the full host build (`--features std` and |
| 158 | +`std,medical-experimental`) compiles with **0 warnings** — there is no longer any |
| 159 | +`static mut <name>` + `&<name>` source for `static_mut_refs` to fire on in the 60 |
| 160 | +fixed modules. (The pure-`wasm32-unknown-unknown` build, where the lint is |
| 161 | +deny-by-default, could not be run in this worktree because the `wasm32` target is |
| 162 | +not installed on the build toolchain; the source-level elimination is the |
| 163 | +evidence, asserted per-module by `a5_claim_bearing_modules_have_no_static_mut_event_buffer`.) |
| 164 | +**Grade: MEASURED (source-eliminated; residual = 2 legitimate singletons).** |
| 165 | + |
| 166 | +## Negative Results (NO-ACTION positives — cited, not edited for labels) |
| 167 | + |
| 168 | +Audited and found genuinely honest; cited as positives: |
| 169 | +- **`qnt_quantum_coherence.rs`** — discloses "quantum-**inspired**" analogy. |
| 170 | +- **`exo_time_crystal.rs`**, **`exo_ghost_hunter.rs`** — disclosed exploratory/novelty. |
| 171 | +- **`qnt_interference_search.rs`** — disclosed "Grover-**inspired**". |
| 172 | +- **`sig_*` / `lrn_*`** algorithm-named skills — names describe the DSP, not an outcome. |
| 173 | +- **`nvsim`** — out of scope; the project's disclaimer gold standard (its tone was |
| 174 | + copied into the A1/A2/A4 disclaimers). |
| 175 | + |
| 176 | +(These were A5-soundness-fixed mechanically where they used `static mut`, with no |
| 177 | +label or behavior change, consistent with leaving their claim surface intact.) |
| 178 | + |
| 179 | +## Deferred Backlog (Nothing Dropped) |
| 180 | + |
| 181 | +- **Per-skill accuracy validation** — **DATA-GATED**. Validating any med_*/affect/ |
| 182 | + sign-language claim requires labelled clinical/affective/ASL data and reference |
| 183 | + standards that do not exist in this repo. The disclaimers + feature gate are the |
| 184 | + honest stand-in. Nothing is claimed that is not measured. |
| 185 | +- **Criterion benches for `process_frame` budget claims** — **ACCEPTED-FUTURE**. |
| 186 | + `tests/budget_compliance.rs` asserts L/S/H tier wall-clock budgets (25 tests, |
| 187 | + passing), but a regression-grade criterion bench is not yet wired. |
| 188 | +- **`wasm32-unknown-unknown` `static_mut_refs` confirmation** — **ACCEPTED-FUTURE** |
| 189 | + (toolchain): the source pattern is eliminated; a CI job on the wasm target should |
| 190 | + assert zero `static_mut_refs` once the target is added to the build image. |
| 191 | +- **The 2 residual `static mut` singletons** (`lib.rs STATE`, `ghost_hunter DETECTOR`) |
| 192 | + — **ACCEPTED-FUTURE**: these are the canonical wasm module-state pattern; migrating |
| 193 | + them to a safe cell is a separate, larger change with no current UB (single-threaded |
| 194 | + wasm runtime, `addr_of_mut!` access). |
| 195 | + |
| 196 | +## Reproduction (MEASURED) |
| 197 | + |
| 198 | +```bash |
| 199 | +cd v2/crates/wifi-densepose-wasm-edge # excluded from the v2 workspace; build here |
| 200 | +cargo test --features std # default |
| 201 | +cargo test --features std,medical-experimental # med_* skills enabled |
| 202 | +cargo test --no-default-features --features std # no default-pipeline |
| 203 | +cargo test --features std --test honest_labeling # A1–A5 label invariants |
| 204 | +``` |
| 205 | + |
| 206 | +(`std` is required for host tests — the crate is `no_std` for `wasm32`; pure |
| 207 | +`--no-default-features` builds only on `wasm32-unknown-unknown`, where it |
| 208 | +intentionally has no panic handler on the host.) |
| 209 | + |
| 210 | +Result at time of writing (all 0 failed): |
| 211 | +- **DEFAULT** (`--features std`) — **615 passed** (lib 504; budget 25; honest_labeling 10; bench 1; vendor 75) |
| 212 | +- **MEDICAL** (`--features std,medical-experimental`) — **653 passed** (lib 542; +38 med_* tests; others unchanged) |
| 213 | +- **NO-DEFAULT** (`--no-default-features --features std`) — **615 passed** |
| 214 | +- Full host build emits **0 warnings**; **61** `static mut` scratch buffers eliminated, **2** legitimate wasm singletons remain. |
| 215 | + |
| 216 | +## Consequences |
| 217 | + |
| 218 | +- No edge skill's name or doc-comment claims a clinical, affective, security, or |
| 219 | + sign-language capability the unvalidated DSP cannot back. |
| 220 | +- The five medical skills cannot be silently compiled into a shipping artifact |
| 221 | + (non-default `medical-experimental` gate). |
| 222 | +- The security skill can never emit a "weapon alert" — it reports |
| 223 | + `HIGH_METAL_REFLECTIVITY`, the physical quantity it actually measures. |
| 224 | +- The latent `static mut` aliasing-UB / `static_mut_refs` exposure is removed from |
| 225 | + 60 modules; the public API and all runtime behavior are unchanged (615/653 tests |
| 226 | + prove behavior preservation). |
| 227 | +- ADR-159's deferred-backlog statement *"wasm-edge … honestly labelled, not |
| 228 | + claimed"* is now actually TRUE. |
0 commit comments