Commit Graph

2 Commits

Author SHA1 Message Date
ruv cedb28db83 feat(dashboard): App Store runtime — 6 simulated apps emit real events live
Closes the "do the App Store toggles actually do anything?" question:
they now do, for the subset of apps whose algorithms map onto nvsim's
magnetic frame stream as a proxy for their native CSI input.

## New: AppManifest.runtime field

Three values:
- `running`     — algorithm genuinely runs in browser (just nvsim today)
- `simulated`   — pared-down version against nvsim's B-field stream
- `mesh-only`   — needs ESP32-S3 + WS transport (deferred to V2)

Visible in the App Store as a colored badge on every card with hover
tooltip explaining what activation actually does.

## New: appRuntimes.ts — 6 in-browser simulated runtimes

- `vital_trend`     — peak-detect on B_z oscillation → 1 Hz HR/BR
                      events 100/101/102/103/104 + bradycardia/tachypnea
- `occupancy`       — variance threshold on |B| → 300/302
- `intrusion`       — |B| > 1.5× ambient + 0.5 s dwell → 200
- `coherence`       — recent vs baseline z-score → 2
- `adversarial`     — log-jump anomaly in |B| → 3
- `exo_ghost_hunter`— impulsive/drift/random anomaly classification → 651

Each receives an AppRuntimeContext (frame, |B|, history, elapsed-time,
per-app scratch state) and emits real i32 event IDs matching the
event_types mod in wifi-densepose-wasm-edge.

## Runtime dispatcher in main.ts

On every MagFrameBatch from the worker, iterate over activeAppIds.
For each id with a registered runtime, call the runtime fn with the
context, push any returned events into appEvents + the console feed.
mesh-only apps no-op silently (their toggle still persists for the
WS transport).

## App Store UI

- Per-card runtime badge (running / simulated / mesh-only) with tooltip
- "Live runtime feed" panel above the grid: shows last 12 emitted
  events with timestamp, app id, event name + i32 id, detail
- Active simulated-app counter: "5 simulated apps active"
- Per-card event counter " N ev" once events arrive
- Toggle log line includes runtime mode: "live runtime engaged" /
  "queued (needs ESP32 mesh)"

Validated end-to-end on https://ruvnet.github.io/RuView/nvsim/ — toggled
{vital_trend, occupancy, intrusion, coherence}, pressed Run, the feed
filled with real events: COHERENCE_SCORE z=0.87 stable, VITAL_TREND
HR=40 BPM BR=10, BRADYCARDIA, BRADYPNEA. Console log mirrors with
[appId] prefix. Zero browser errors.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-27 11:31:33 -04:00
ruv 39ec05edcb feat(dashboard): nvsim Vite+Lit dashboard with WASM transport + App Store [ADR-092]
End-to-end implementation of the operator dashboard for the nvsim
NV-diamond magnetometer simulator. Vite 5 + TypeScript strict + Lit 3,
~93 KB gzipped JS budget, runs the *real* nvsim Rust crate compiled to
wasm32-unknown-unknown inside a dedicated Web Worker.

Validated end-to-end with `npx agent-browser`:
- WASM module boots, build version + magic 0xC51A_6E70 reported
- Reference witness verifies byte-identical to Proof::EXPECTED_WITNESS_HEX
  cc8de9b01b0ff5bd97a6c17848a3f156c174ea7589d0888164a441584ec593b4
- Pipeline runs at ~1.88 kHz on x86_64 dev hardware (4500x over Cortex-A53)
- Zero browser console errors; only Lit dev-mode warning (expected)

## nvsim crate (additive)
- New `wasm` feature flag with wasm-bindgen 0.2 / serde-wasm-bindgen 0.6
- src/wasm.rs: WasmPipeline wrapper + referenceSceneJson +
  expectedReferenceWitnessHex + referenceWitness + hexWitness exports
- crate-type = ["cdylib", "rlib"] so native + wasm both build
- rand = { default-features = false } drops getrandom OS-entropy path,
  preserving the crate's WASM-ready posture
- Native: 50/50 tests still pass, witness unchanged

## dashboard/ (new package)
- Vite 5 + TypeScript strict, Lit 3 elements, signals-based store
- 12 Lit components mirroring the mockup zones (rail, topbar, sidebar,
  scene SVG with draggable sources + NV crystal, inspector tabs
  Signal/Frame/Witness, console with REPL + filter tabs, settings
  drawer, modals, ⌘K command palette, debug HUD, toast, app-store)
- IndexedDB persistence (theme, density, motion, app activations)
- WasmClient → Web Worker → wasm-pack-built nvsim WASM module
- NvsimClient TS interface — same shape covers future WsClient transport
- MagFrame parser (60-byte LE layout matching nvsim::frame)

## App Store (ADR-092 §14a — added during impl)
- Catalog of all 65 wifi-densepose-wasm-edge modules + nvsim
- 13 categories with event-ID-range labels
- Per-app metadata: id/name/category/crate/summary/events/budget/
  status/adr/tags
- Fuzzy search, category + status filters, IndexedDB-backed activation
- ADR-092 §14a documents the registry contract and per-app schema

## Build pipeline
- wasm-pack build crates/nvsim --target web outputs to
  dashboard/public/nvsim-pkg/ (60 KB pkg, 162 KB unoptimized .wasm)
- npm run build → 93 KB gzip JS, well under 300 KB budget
- ts.config strict, npx tsc --noEmit clean
- Vite worker correctly loads WASM via dynamic import resolving
  against worker origin

## E2E validation
- agent-browser open → 4-zone grid renders correctly in dark theme
- Run button → live B-vector trace, |B| readout updates, FPS counter
- App Store → all 66 apps listed with toggles, fuzzy search filters
  to "Ghost hunter" on "ghost" query
- Witness verify → green check, console logs "determinism gate ✓"
- Console errors: zero (only expected Lit dev-mode warning)

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-26 19:22:04 -04:00