Advances SPARC Phase 4 (Refinement): implements the first two ADR-124 §4.1
sensing tools, which also serve as integration tests for the schema-validation
gate wired in Phase 3 (iter 3).
New files:
src/tools/bfld-last-scan.ts
- bfldLastScanSchema: z.object with optional node_id (min 1) + optional
sensing_server_url — enforces the ADR-124 §4.1 input contract
- bfldLastScan(): proxies GET /api/v1/bfld/<node_id>/last_scan from the
sensing-server; returns BfldLastScanResult{ok,node_id,identity_risk_score,
privacy_class,n_frames,timestamp_ms} on success
- Converts BfldEvent.timestamp_ns (ns) → timestamp_ms (ms)
- Uses person_count as n_frames proxy per ADR-118 BfldEvent shape
- Returns {ok:false,warn:true} when server unreachable (soft-failure convention)
src/tools/bfld-subscribe.ts
- bfldSubscribeSchema: z.object with required duration_s (positive, max 3600)
- bfldSubscribe(): POST /api/v1/bfld/<node_id>/subscribe?duration_s=<n>
- Synthetic envelope fallback: when server unreachable, synthesises a valid
{subscription_id (UUID v4), expires_at, topic} locally so the schema gate
is always exercised and the caller can track the intent
- topic format: ruview/<node_id>/bfld/* (ADR-122 §2.2 wildcard)
src/index.ts:
- Import bfldLastScan + bfldSubscribe
- Two new TOOLS entries: ruview.bfld.last_scan + ruview.bfld.subscribe
- Both go through the TOOL_INPUT_SCHEMAS schema-validation gate (iter 3)
New test: tests/bfld-tools.test.ts (14 assertions):
- bfldLastScan: unreachable → ok:false+warn:true, malformed path,
ns→ms arithmetic, null identity_risk_score coalescing
- BfldLastScanInputSchema: empty object accepted, empty node_id rejected
- bfldSubscribe: subscription_id defined + future expires_at, UUID v4 format,
expires_at timing accuracy (±50ms), topic pattern match
- BfldSubscribeInputSchema: duration_s > 3600 rejected, duration_s=0 rejected
Test results: 75/75 PASS (+14). Build: tsc clean.
ACs touched: ADR-124 §4.1 ruview.bfld.last_scan + ruview.bfld.subscribe.
SPARC Phase 4 gate: acceptance criteria have passing tests; code review
against spec complete; no critical issues.
Next iter target: Phase 4 continued — ruview.presence.now + ruview.vitals.*
tool handlers (4 tools), following the same pattern; then Phase 5 (Completion)
with package metadata, CHANGELOG, and witness-bundle extension.
Co-Authored-By: claude-flow <ruv@ruv.net>
* research(R9): RSSI fingerprint K-NN — 2.18x lift (MODERATE); surfaces counting-vs-localization asymmetry
Hypothesis: if temporal proximity correlates with RSSI-feature
proximity in the existing single-session data, RSSI fingerprinting is
viable. If K-NN of each query is random in time, RSSI sequences are
too noisy for fingerprint localization.
Test: 1077 samples, 20-dim RSSI proxy (band-mean across 56
subcarriers), cosine-NN with K=5, measure fraction of K-NN within
plus/minus 60s of each query timestamp. Compare to random baseline.
Result (honest):
5-NN within +/-60s 0.169
Random baseline 0.077
Lift over random 2.18x (verdict: MODERATE)
Per-query stdev 0.183
Below the >=3x STRONG-fingerprint threshold but well above 1x random.
Real signal, but weaker than R8 counting result on the same data.
Important asymmetry surfaced (publishable distinction):
Task RSSI vs CSI retention Verdict
------- ----- -----
Counting 94.82% (R8) RSSI works well
Localization ~2x random (R9) RSSI struggles in this regime
This is consistent with R5's band-spread observation: the count signal
integrates across the band, but localization may require per-subcarrier
shape that the band-mean discards.
Three actionable explanations for the MODERATE result:
1. 20-frame windows (~2s) too short for stable fingerprint while operator
moves — longer windows might lift to 3-4x.
2. Within-room fingerprint space too narrow — multi-room data would
show categorical lift jump (5-10x).
3. Band-mean discards the per-subcarrier shape needed for localization.
Once multi-room data lands (#645), this test should be re-run; if
hypothesis (2) is right, the lift will jump categorically.
Files:
* examples/research-sota/r9_rssi_fingerprint_knn.py
* examples/research-sota/r9_rssi_fingerprint_results.json
* docs/research/sota-2026-05-22/R9-rssi-fingerprint-knn.md
* docs/research/sota-2026-05-22/PROGRESS.md updated
* feat(tools/ruview-mcp): M2 — wire real inference via cog health subcommand
ruview_pose_infer and ruview_count_infer now run the cog binary's `health`
subcommand (ADR-100 contract) which performs real Candle forward-pass
inference on a synthetic CSI window and emits a structured health.ok JSON
event containing backend, confidence (pose) or count/confidence/p95_range
(count). The MCP tools parse this event and return typed inference results.
This satisfies the ADR-104 acceptance gate: "ruview_pose_infer returns a
finite output for a synthetic CSI window" when the cog binary is installed.
On machines without the binary, both tools still fail-open with {ok:false,
warn:true} and actionable install hints.
Also updates PROGRESS.md with cross-links: R7 (Stoer-Wagner) and R8
(RSSI-only 94.82% retained) marked done with cron-originated findings
distilled into the research vectors section.
Co-Authored-By: claude-flow <ruv@ruv.net>
Adds two new npm packages that expose RuView's WiFi-DensePose
sensing capabilities outside the Cognitum appliance ecosystem:
- tools/ruview-mcp/ (@ruv/ruview-mcp) — MCP server with 6 tools:
ruview_csi_latest, ruview_pose_infer, ruview_count_infer,
ruview_registry_list, ruview_train_count, ruview_job_status.
Uses @modelcontextprotocol/sdk with stdio transport.
6/6 smoke tests pass. TypeScript strict mode, Node 20.
- tools/ruview-cli/ (@ruv/ruview-cli) — Yargs CLI with matching
subcommands: csi tail, pose infer, count infer, cogs list,
train count, job status. Same fail-open pattern as the cog
binaries (WARN to stderr, exit 0 on unavailable sensing-server).
- docs/adr/ADR-104-ruview-mcp-cli-distribution.md — design rationale,
6-row threat table, packaging plan, acceptance gates, failure modes.
- docs/research/sota-2026-05-22/HORIZON.md — 12-hour horizon plan
with 7 milestones tracked (M1 complete in this commit).
Both packages are private:true pending the user's publish decision.
Inference is via subprocess to the signed cog binaries (ADR-100/101/103)
— no JS/WASM ML engine bundled.