Releases: ruvnet/RuView
v0.12.0 — HOMECORE web UI is live + 9-phase verify Trust Kill Switch
Five small commits since v0.11.0 — the HOMECORE web UI is no longer an empty shell, and the project's Trust Kill Switch now verifies every layer of the stack with a single command.
What changed
HOMECORE web UI is functional (was: empty shell)
The Lit + Vite frontend shipped in v0.10.0 had registered components but no pages mounted, so operators saw the appbar + nav but nothing in <main>. Browser-driven testing this session caught it; this release fixes it end-to-end.
frontend/src/pages/Dashboard.ts— new<hc-dashboard>Lit component. Reads bearer fromlocalStorage["homecore.token"](or?token=, or<meta>, withdev-tokenfallback). Fetches/api/config+/api/states, renders a.metaline + responsive grid of<hc-state-card>. Polls every 5 s. Surfaces structured backend-unreachable errors instead of a blank page.frontend/src/pages/States.ts— full HA-style table view of every entity (entity_id / state / last_changed / attributes). 5 s auto-refresh.frontend/src/pages/Services.ts— domain-grouped service registry from/api/services. Friendly empty state when no services are registered (matches a vanilla plugin-less boot).frontend/src/pages/Settings.ts— backend config readout (location / version / state / components) + bearer-token editor that writes tolocalStorage["homecore.token"].frontend/src/main.ts— tiny router: AppShell'shc-navigateevents swap the page element. Default first paint = Dashboard.scripts/homecore-seed.sh— populates 10 representative entities (RuView sensing-derived + conventional HA fixtures) so a freshhomecore-serverboot has demo content. Idempotent. Pulls live numbers from the RuView sensing-server whenRUVIEW_URLis reachable.
Browser-verified all 4 nav clicks swap the rendered page correctly. Zero console errors.
Trust Kill Switch covers v1 + v2 + HOMECORE
The original verify script only validated the v1 Python signal-processing proof. After v0.9.0 (ADR-125) and v0.10.0/v0.11.0 (HOMECORE), the stack has six more proof boundaries. verify now runs 9 phases in one command:
PASS Phase 1: v1 pipeline hash matches expected
PASS Phase 2: no random generators in production code
PASS Phase 3: 2,263 Rust workspace tests pass (real number, no agent claim)
PASS Phase 4: wifi-densepose-py PyO3 binding compiles
PASS Phase 5: ADR-125 §2.1.d invariant — identity_risk_score is None
PASS Phase 6: 12/12 crates on crates.io
PASS Phase 7: @ruvnet/rvagent v0.1.0 on npm
PASS Phase 8: multi-arch (amd64 + arm64) Docker manifest live
SKIP Phase 9: docker pull (skip when CLI absent)
Each phase reports PASS / FAIL / SKIP independently. SKIP is honest — no false green when an optional tool (cargo / docker / curl) is absent. Flags: --quick, --rust-only, --docker-only, plus the pre-existing --verbose, --audit, --generate-hash pass-through.
Pydantic + Windows + numpy-drift fixes
archive/v1/src/config/settings.py—extra="ignore"so the v1 proof tolerates unrelated.envkeys (NPM_TOKEN, DOCKER_HUB_TOKEN, etc.) used by other tooling. Closes a real secret-leak path where pydantic's error message echoed the offending token value.archive/v1/data/proof/expected_features.sha256— regenerated per the documentedverify.py --generate-hashprocedure to match the current numpy/scipy combo.verifyPhase 3 — fixed three subtle bugs (pipefail killing the script,0\n0arithmetic poisoning, Windows file-lock on cog-pose-estimation's smoke test) so the 2,263-test pass count actually surfaces.
Reproduce
./verify # full 9-phase proof
./verify --quick # skip slow phases (Rust workspace tests + Docker pull)
Local witness log saved at dist/verify-witness-9a09d186c.log (5.8 KB).
References
- Previous releases: v0.11.0, v0.10.0, v0.9.0
- ADR-125 / ADR-127 / ADR-130 / ADR-132 — the foundations this release builds on
Co-Authored-By: claude-flow ruv@ruv.net
v0.11.0 — HOMECORE in Docker + crate-level READMEs
Polish + packaging release for the v0.10.0 HOMECORE work.
What's new since v0.10.0
homecore-server is now in the published Docker image
docker/Dockerfile.rustbuilds three binaries side-by-side:sensing-server,cog-ha-matter, and nowhomecore-server(HA-wire-compatible REST + WebSocket on port 8123).- Multi-arch (amd64 + arm64) build verified end-to-end on Apple Silicon (
ruv-mac-mini, Darwin arm64). - New image digest:
sha256:ae3fbe2011787e782e75200f09afd1e5c49992d698eaac549b484ce36ff270fb. - Operator usage:
docker run --network host ruvnet/wifi-densepose:latest homecore # serves HA-compat API on :8123, SQLite recorder, automation engine, assist, plugins docker run … cog-ha-matterand the default sensing-server path keep working unchanged — three roles, one image, picked at run-time via the first arg.
Comprehensive READMEs for every HOMECORE crate
Eight new crate READMEs + the server binary's README. Every one carries:
- Tagline + badges (crates.io / MSRV / tests / license / ADR link)
- Honest "what this is" (no marketing fluff)
- Features list — P1 scaffold vs runtime-ready is named at the top, not buried
- Capabilities table mapping primitives → concrete actions
- Comparison vs the Home Assistant Python equivalent
- Performance — measured numbers where they exist, "TBD / no benchmarks yet" where they don't (no invented numbers)
- Runnable usage example (Rust or
cargo run -p …) - Relation-to-other-HOMECORE-crates diagram
- Reference links to the ADR + workspace root
Crates with READMEs:
v2/crates/homecore(ADR-127) — state machine, event bus, registriesv2/crates/homecore-api(ADR-130) — REST + WebSocketv2/crates/homecore-plugins(ADR-128) — Wasmtime + InProcess runtimesv2/crates/homecore-hap(ADR-125 §P2) — P1 scaffold; not a running HAP-1.1 server yetv2/crates/homecore-recorder(ADR-132) — SQLite + ruvectorv2/crates/homecore-automation(ADR-129) — YAML triggers + MiniJinjav2/crates/homecore-assist(ADR-133) — ships NoopRunner; production runner is P2v2/crates/homecore-migrate(ADR-134) — HA.storage/→ HOMECOREv2/crates/homecore-server— the workspace binary tying the above together
Validation
- All 2,263 workspace tests still green on
mainHEAD - Docker workflow
26429908475succeeded for sha8cb8a37dc(the homecore-server inclusion commit) docker run --rm --entrypoint /app/homecore-server ruvnet/wifi-densepose:latest --helpconfirmed in the newly-pulled image
Deferred (still)
- HAP-1.1 server runtime in
homecore-hap(closes ADR-125 §P2) - Production ruflo runner in
homecore-assist - Wasmtime feature-gating is P2 (default-off) per
homecore-pluginsREADME
Release artifacts
- Docker Hub:
ruvnet/wifi-densepose:latest(multi-arch, new digest above) - ghcr.io:
ghcr.io/ruvnet/wifi-densepose:latest(same digest)
References
- ADR-125 / ADR-126 / ADR-127 / ADR-128 / ADR-129 / ADR-130 / ADR-132 / ADR-133 / ADR-134
- Previous release: v0.10.0 (HOMECORE merge)
Co-Authored-By: claude-flow ruv@ruv.net
v0.10.0 — HOMECORE: native Rust port of Home Assistant
RuView v0.10.0 — HOMECORE: native Rust port of Home Assistant
Builds on the v0.9.0 APPLE-FABRIC release. Where v0.9.0 shipped the Python-based Apple Home / HAP bridge as scripts + docs, v0.10.0 lands the native Rust + WASM + TypeScript port of Home Assistant — HOMECORE — covering ADRs 126–134 (and a Rust-native re-implementation path for ADR-125).
Merged via PR #800 (squash). Tracked at #798.
What shipped
8 new Rust crates (v2/crates/homecore*)
| ADR | Crate | Tests | What |
|---|---|---|---|
| 127 | homecore |
20 | State machine (DashMap), event bus, service registry, entity registry |
| 130 | homecore-api |
18 | HA wire-compat Axum REST + WebSocket on :8123 (more than the 4 originally claimed) |
| 128 | homecore-plugins |
10 + 14 integ | Wasmtime 42.0.2 + InProcess runtimes, JSON-over-linear-memory ABI |
| 125 | homecore-hap |
17 | Apple Home HAP bridge — P1 trait surface + 11 accessory types (HAP-1.1 server itself feature-gated to P2 via hap-server feature flag, honestly documented) |
| 132 | homecore-recorder |
(lib + smoke) | SQLite + ruvector semantic index, FNV-1a 64-bit attr dedup bit-exact against HA db_schema.py |
| 129 | homecore-automation |
34 | YAML triggers/conditions/actions + MiniJinja templates (4 HA globals) |
| 133 | homecore-assist |
23 | Intent recognizer + 5 built-in handlers + NoopRunner ruflo stub (real subprocess deferred to P2) |
| 134 | homecore-migrate |
19 | .storage/*.json v13 parser + 6-subcommand clap CLI |
Plus homecore-server integration binary wiring all 8 above (cargo run -p homecore-server --bind 127.0.0.1:8123) and homecore-plugin-example (47 KB cdylib wasm32-unknown-unknown plugin proving the host ABI end-to-end).
Frontend (frontend/)
@ruvnet/homecore-frontend@0.1.0-alpha.0 — Lit + TypeScript + Vite scaffold:
- Builds clean:
dist/index.js25.45 KB (8.92 KB gzip),dist/index.css4.61 KB (1.50 KB gzip) - 11 vitest unit tests
- Design tokens lifted from
cognitum-v0:9000via/browserrecon - Lucide icons, full design system documented in
docs/design/HOMECORE-FRONTEND-design-recon.md
Security
docs/security/HOMECORE-security-audit-iter10.md— 18 findings (4 Critical / 3 High / 5 Med / 4 Low / 2 Info)- Critical CVEs cleared: wasmtime 25.0.3 → 42.0.2 (RUSTSEC-2026-0095/0096, CVSS 9.0 sandbox escape), sqlx 0.7.4 → 0.8.6 (binary protocol misinterpretation)
- HC-05 closed in final iter: CORS allowlist replacing permissive CORS in
homecore-api(commita771ab8aa) - Deferred: HC-01/02 auth bypass (P1 placeholder, lands with real bearer-token store in P3 — see ADR-130 §3)
Verification
- CI: 32 SUCCESS / 5 SKIPPED / 0 FAILED (Code Quality, SAST, Tests 3.10/3.11/3.12, Rust Workspace Tests, Docker Build, Dependency Scan, Security Report, Semgrep, KICS, Secret Scanning all green on both branch and merge-base)
- Workspace tests at merge SHA: 2,263 passed / 0 failed / 11 ignored (
cargo test --workspace --no-default-features) - HOMECORE-only: 155 tests passing / 0 failed across the 8 new crates
cargo check --workspace: clean post-merge- Frontend build: clean, 25 KB JS bundle
Honest reporting
- PR claimed "162 tests (table sum)" and "176+ tests (body)". Measured: 155 passing + 1 ignored across the 8 homecore crates. The discrepancy is a counting methodology difference (the claim conflated lib + integration + doc-tests + smoke tests in inconsistent ways), and
homecore-apiactually has 18 unit tests, not the 4 claimed in the table — under-reported by the PR description, but all green. homecore-hapis P1 scaffold + trait surface + 17 mapping tests, not a running HAP-1.1 server. The Cargo.toml, lib.rs, and bridge.rs all explicitly document thehap-serverfeature flag as the P2 gate for the realhapcrate integration. Apple Home pairing from this build will require enabling that feature once it lands.homecore-assistshipsNoopRunnerfor the ruflo subprocess — the trait + IPC surface compile and test, but no Node.js subprocess is spawned in P1. Honest deferral documented inrunner.rs.- One Windows-only test-runner quirk:
cog-pose-estimation --test smokehitsAccess is denied (os error 5)due to a file lock on the test executable in concurrent runs. This is pre-existing in main, not from this PR, and the CI on Linux is fully green.
No regressions to v0.9.0
PR diff touches only v2/crates/homecore*, frontend/, v2/Cargo.toml, v2/Cargo.lock, and 2 new doc files (docs/adr/ADR-133-*.md, docs/design/HOMECORE-FRONTEND-*.md, docs/security/HOMECORE-security-*.md). Zero changes to scripts/, python/, the v0.9.0 user guide, or any other v0.9.0 release artifact.
Merge metadata
- PR: #800
- Squash commit:
e96ebaea810c20c402f48967c44f12d1d3d9f4ea - Branch deleted:
feat/adr-126-homecore-impl - Audit log:
dist/pr800-test-output-v2.log(workspace) +dist/pr800-homecore-only.log(homecore-focused)
Release v1365
Automated release from CI pipeline
Changes:
docs(readme): link ecosystem badges + move Beta callout to bottom
Three operator-feedback corrections to the README:
-
Every ecosystem badge in the top row now links to a real
destination — Home Assistant -> integrations/home-assistant.md,
Matter -> ADR-122, Apple Home -> user-guide-apple-homepod.md,
Google Home + Alexa -> the HA integration doc (both ecosystems
reach RuView through HA's bridge today). Added an Alexa badge
alongside the existing four so all four major ecosystems are
represented. Dropped the now-redundant separate "HomePod
Integration" badge — the Apple Home badge linking to the same
guide is enough. -
Beta callout moved from line 14 (under the hero image) to a
dedicated## Beta softwaresection immediately before the
License. The callout's content is unchanged; it just no longer
gates the elevator pitch. Readers see the value proposition
first, the caveats at the bottom alongside license + support. -
The intro paragraph ("Turn ordinary WiFi into ...") now ends
with a one-line summary of native ecosystem support naming all
four — Home Assistant, Apple Home & HomePod, Google Home, Alexa —
plus the Matter endpoint, each linked. The previous mention of
ecosystems was buried further down the page; this surfaces it
in the intro where the user reads first.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:baba851a89e8849911b06b7077daf25af187b021
Release v1362
Automated release from CI pipeline
Changes:
ADR-125 APPLE-FABRIC: RuView <-> Apple Home native HAP bridge (e2e on real C6) (#797)
- feat(adr-125 iter 3): BFLD PrivacyGate + semantic-event naming at HAP boundary
Inserts a Python equivalent of wifi-densepose-bfld::PrivacyClass +
PrivacyGate between the rv_feature_state parser and the HAP toggle
file. ADR-125 §2.1.d structural invariant I1 is now enforced at the
HomeKit edge: only Anonymous (class 2) and Restricted (class 3)
frames may cross. Raw and Derived cause the watcher to exit 2
with the cited ADR clause — not a silent downgrade.
Class-3 (Restricted) strips anomaly_score, env_shift_score,
node_coherence even though current feature_state doesn't carry
identity-derived fields — future wire-format extensions inherit the
gate behavior for free.
Operator-facing semantic naming follows ADR-125 §2.1.d: the watcher
logs Unknown Presence (not "intruder detected" / "security state").
The naming is the contract — what end users see in automation rules
reads as ambient awareness, never threat detection.
Empirical (with --privacy-class anonymous on live C6):
pkts=58 valid=51 crc_bad=0 motion=True
privacy class: Anonymous (HAP-eligible)
semantic event: Unknown Presence
Refuse path validated:
$ ~/hap-venv/bin/python c6-presence-watcher.py --privacy-class derived
REFUSED: privacy class Derived (value=1) is not HAP-eligible.
ADR-125 §2.1.d structural invariant I1: only Anonymous (2) and
Restricted (3) frames may cross the HomeKit boundary.
$ echo $?
2
Branch: feat/adr-125-apple-fabric (kept off main while docker build
for sha 9fda90f is still compiling; this commit touches only
scripts/, not any docker workflow path-filter).
Refs ADR-125 §2.1.d, ADR-118 §2.1/§2.2.
Co-Authored-By: claude-flow ruv@ruv.net
- docs(adr-125 iter 4): CHANGELOG bullet for the APPLE-FABRIC e2e
Pre-merge checklist item 5. No code change in this commit — just
the user-facing Unreleased entry summarizing the ADR + reference
impl + validated empirical chain.
Co-Authored-By: claude-flow ruv@ruv.net
- feat(adr-125 tier1 #1): multi-characteristic accessory + JSON-state IPC
The HAP accessory now carries three services on the same paired
entity (HomeKit allows multiple services per accessory; iPhone
refetches /accessories when config_number bumps):
- MotionSensor — short-window motion_score, immediate
- OccupancySensor — rolling-3s avg presence_score, sustained
- StatelessProgrammableSwitch — "Unrecognized Activity Pattern"
event (Restricted-class only; fires on
anomaly_score >= 0.7); ADR-125 §2.1.d
semantic naming, not security state
New JSON IPC contract /tmp/ruview-state.json between watcher
and HAP daemon:
{ "motion": bool, "occupancy": bool, "anomaly_ts": float,
"ts": float }
Atomic writes (tmp + rename). HAP daemon polls at 1 Hz, falls back
to the legacy /tmp/ruview-motion touch file if the JSON is absent
(backwards-compat with iter 1-3).
Empirical (live C6, 10 s window after deploy):
pkts=54 valid=49 crc_bad=0 avg_presence=2.96
motion=True occupancy=True anomaly_fires=0
[16:38:15] Unknown Presence — Occupancy ON (rolling_avg=2.79)
Pairing survived:
paired_clients: 1
config_number: 3 (was 1; HAP-python bumps automatically on shape change)
Tier 1 #1 (multi-characteristic) of the Tier 1+2 sprint. Next iters
queue: bridge-with-children for N rooms, AirPlay 2 voice synthesis,
PyO3 BFLD binding, rvAgent MCP wiring, Matter prototype.
Refs ADR-125 §2.1.c (bridge topology), §2.1.d (semantic events),
ADR-118.
Co-Authored-By: claude-flow ruv@ruv.net
- feat(adr-125 tier1+2 iter 2): sensing-server-equivalent for @ruvnet/rvagent
scripts/ruview-sensing-server.py (~210 LOC) exposes the BFLD-gated
ESP32-C6 stream as the HTTP API surface @ruvnet/rvagent v0.1.0
(ADR-124, npm) expects. Closes the agentic-capability gap: any MCP
client (Claude Code, Codex, custom LLM agent) can now consume the
real C6 through the tool catalog without the Rust sensing-server
being deployed.
Endpoints (mirrors tools/ruview-mcp/src/tools/*.ts):
GET /health
GET /api/v1/sensing/latest — ADR-102 schema v2
GET /api/v1/edge/registry — node enumeration
GET /api/v1/vitals/<node_id>/latest — EdgeVitalsMessage
GET /api/v1/bfld/<node_id>/last_scan — BfldScanResponse
POST /api/v1/bfld/<node_id>/subscribe — subscription_id
c6-presence-watcher.py now writes a companion /tmp/ruview-last- feature.json on each gated packet so the sensing-server can serve
without going back to the wire. Atomic tmp+rename. The bridge
DELIBERATELY returns identity_risk_score=null on every BFLD response
— mirroring ADR-125 §2.1.d at the HTTP boundary even though the
rvagent schema's slot is nullable.
Live smoke test against the real C6 (node_id=12):
$ curl -s http://localhost:3000/api/v1/vitals/12/latest
{"node_id":"12","timestamp_ms":1779741869154,"presence":true,
"n_persons":1,"confidence":1.0,"breathing_rate_bpm":18.75,
"heartrate_bpm":40.0,"motion":1.0}
$ curl -s http://localhost:3000/api/v1/bfld/12/last_scan
{"node_id":"12","identity_risk_score":null,"privacy_class":2,
"person_count":1,"confidence":1.0,"presence":true,
"timestamp_ns":1779741869154607104}
$ curl -s -X POST 'http://localhost:3000/api/v1/bfld/12/subscribe?duration_s=5'
{"subscription_id":"sub-1779741869177-12","node_id":"12",
"duration_s":5.0,"endpoint_hint":"poll GET ..."}
Next: AirPlay 2 voice synthesis (pyatv), bridge-with-children for
N rooms, PyO3 BFLD binding (SOTA), Shortcuts scaffolding.
Refs ADR-124 (@ruvnet/rvagent contract), ADR-125 §2.1.d, ADR-118.
Co-Authored-By: claude-flow ruv@ruv.net
- feat(adr-125 tier1+2 iter 3): production HAP bridge with N child accessories
scripts/ruview-hap-bridge.py (~170 LOC) implements the ADR-125 §2.1.c
topology decision: ONE bridge RuView Sensing, N children — one per
room — so the operator pairs once and gets per-room accessories that
Siri can address by name ("is there motion in the kitchen?").
State per room comes from /tmp/ruview-state..json. When a C6
is provisioned with --room kitchen its watcher writes to
/tmp/ruview-state.kitchen.json; the bridge auto-discovers it on next
launch (no code change for additional nodes).
Legacy /tmp/ruview-state.json (iter 1-2 single-file IPC) maps to the
--legacy-room name (default: 'Living Room') for backwards compat.
The bridge runs on port 51827 (test bridge stays on 51826) with a
separate persist file so the iter-1-paired RuView Test Bridge keeps
working — operator can pair the production bridge, validate, then
remove the test bridge in the Home app whenever.
Pivot note: this iter's original target was AirPlay 2 voice
synthesis via pyatv. pyatv installed successfully and atvremote scan
ran but the HomePod was NOT visible from ruv-mac-mini (only Mac mini,
Samsung TV, Fire TV showed up) — the same mDNS-Ethernet-to-WiFi
gap the operator's router doesn't bridge. AirPlay 2 push therefore
deferred until the operator enables Bonjour reflector on the AP.
Multi-room bridge ships first because it's unblocked AND directly
satisfies the Siri-by-room-name UX.
Empirical (deployed on ruv-mac-mini, prod_bridge_pid=64094):
$ dns-sd -B _hap._tcp local.
Add 3 15 local. _hap._tcp. RuView Test Bridge 224DF9
Add 3 15 local. _hap._tcp. RuView Sensing 0B4FC4
Add 3 15 local. _hap._tcp. Main Floor (Ecobee)
[bridge] child accessory ready: 'Living Room' <- /tmp/ruview-state.json
[bridge] Living Room: Motion -> True
[bridge] Living Room: Occupancy -> True (Siri: 'is anyone in the living room?')
Setup code for pairing the new bridge: 629-88-678.
Tier 1 §2.1.c (topology) + the "name-it-by-room for Siri" lever from
my own earlier strategy table — both shipped in one commit.
Refs ADR-125 §2.1.c.
Co-Authored-By: claude-flow ruv@ruv.net
- feat(adr-125 tier1+2 iter 4): semantic-events MCP endpoint per §2.1.d
GET /api/v1/semantic-events/<node_id>/latest exposes the three
ADR-125 §2.1.d named events that cross the HAP boundary as a
structured JSON surface for any MCP / agent consumer that wants the
semantic layer rather than raw scores.
Response shape:
{
"node_id": "12",
"privacy_class": 2,
"events": {
"unknown_presence": {"active": bool, "source": str, "ts": float},
"unexpected_occupancy": {"active": bool, "schedule_aware": false, "ts": float},
"unrecognized_activity_pattern": {
"active": bool, "anomaly_threshold": 0.7,
"anomaly_score": float, "ts": float
}
},
"redacted_fields": [
"identity_risk_score", "soul_match_probability", "rf_signature_hash"
]
}
Live response from real C6 (node_id=12):
{
"unknown_presence": {"active": true, ...},
"unexpected_occupancy": {"active": true, "schedule_aware": false, ...},
"unrecognized_activity_pattern": {"active": false, "anomaly_score": 0.0, ...}
}
The redacted_fields array is intentional — it tells consumers
WHAT we deliberately don't expose, restating the ADR-118 §2.5 /
ADR-125 §2.1.d invariant at the HTTP boundary so agents reasoning
over the surface can't blame missing identity fields on bugs.
unexpected_occupancy.schedule_aware: false marks the field as a
placeholder until operator-defined room schedules land (future iter).
Agents that branch on this can fall back to raw occupancy until then.
Refs ADR-125 §2.1.d (semantic-events naming contract).
Co-Authored-By: claude-flow ruv@ruv.net
- feat(adr-125 tier1+2 iter 5): rvagent MCP consumer — agentic chain proven
scripts/rvagent-mcp-consumer.py (~155 LOC) is an MCP JSON-RPC 2.0
stdio client that spawns the published @ruvnet/rvagent v0.1.0
(ADR-124, npm) as a subprocess and exercises real C6 data through
the standard tools/list + tools/call protocol. This is the "agentic
...
Release v1339
Automated release from CI pipeline
Changes:
feat(adr-125 iter 2): real C6 feature_state UDP → HAP characteristic
scripts/c6-presence-watcher.py parses the 60-byte
rv_feature_state_t struct (RV_FEATURE_STATE_MAGIC = 0xC5110006)
emitted by firmware/esp32-csi-node/main/rv_feature_state.[ch] at
1-10 Hz from the real ESP32-C6 on ruv.net, validates the IEEE CRC32
over bytes [0..end-4], gates on RV_QFLAG_PRESENCE_VALID, applies
hysteresis (entry 0.40 / release 0.20) plus a 5 s idle-release
fallback, and toggles /tmp/ruview-motion — the same touch-file
contract that the already-paired HAP bridge consumes.
E2E validated against real hardware (no mocks, no simulation):
C6 (192.168.1.179, ch 5, RSSI -38)
└─ UDP/5005 → mac-mini (192.168.1.166)
└─ c6-presence-watcher.py (pid 8276)
└─ /tmp/ruview-motion
└─ hap-test-sensor.py (pid 84602)
└─ HAP-1.1 over mDNS
└─ iPhone Home app: RuView Test Motion = True
10 s sample: pkts=63 valid=51 crc_bad=0 motion -> True
Iter 3 next: insert wifi-densepose-bfld PrivacyGate between the
UDP parse and the threshold so only class-2/3 frames cross the HAP
boundary (ADR-118 §2.2 invariant I1 holds at the HomeKit edge —
ADR-125 §2.1.d).
Refs ADR-125, ADR-118, ADR-081.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:1f13aa96c2261308a2f2b7a5ca7d9f3620284e67
Release v1338
Automated release from CI pipeline
Changes:
chore(adr-125 iter 1): fix C6 COM port + ship HAP-python reference impl
Two changes from the ADR-125 e2e bootstrap session:
-
CLAUDE.md hardware table: COM4 -> COM12 for ESP32-C6 (the C6 +
Seeed MR60BHA2 dev kit now enumerates on COM12 on ruvzen, not
COM4 as previously documented). Same fix applied to the ESP32-S3
row (COM7 -> COM9) which CLAUDE.local.md already covered but the
top-level table had not been updated. -
scripts/hap-test-sensor.py — the ~80 LOC HAP-python sidecar that
ADR-125 §2.1.a names as the reference implementation. Already
running on ruv-mac-mini, already paired with operator's iPhone
(paired_clients: 1), already round-trips a MotionDetected
characteristic from a touch-file toggle through the HomePod (as
Home Hub) to the Home app.
Substrate validated for iter 2+:
- C6 provisioned on ruv.net (IP 192.168.1.179, ch 5, RSSI -38)
- UDP frames: 44 packets in 8s @ mac-mini:5005 (~5.5 pps)
- HAP bridge paired and live
Refs ADR-125, #794.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:19b445f9bb4ede36aa6ae9332944c488cca148ab
Release v1337
Automated release from CI pipeline
Changes:
docs(adr-125): resolve topology + identity-risk questions per review
Two open questions from §5 promoted to decisions in §2:
§2.1.c — Topology: one HAP bridge, N child accessories. Single pairing
flow; child accessories assignable to rooms in the Apple Home
app; matches every reference HomeKit bridge UX (Hue, Eve, ...).
The N-independent-accessories alternative was rejected for the
room-multiplication mess it creates after the second pairing.
§2.1.d — Identity-risk mapping is semantic, not probabilistic. The
raw identity_risk_score and Soul-Signature match probability
NEVER cross the HAP boundary. Instead we expose three thresholded
semantic events: Unknown Presence, Unexpected Occupancy,
Unrecognized Activity Pattern. Naming is the contract — these
read as ambient awareness, not threat detection, so RuView does
not become "RF surveillance with an Apple skin." This is the
decision that determines whether the HomeKit story ages well.
§5 trimmed to two genuinely-open items: setup-code derivation
(deterministic vs random) and ESP32-direct HAP advertisement.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:82fecbb5add1dbd4beb624962127b2c3eedff47d
Release v1336
Automated release from CI pipeline
Changes:
docs(adr-125): RuView <-> Apple Home native HAP bridge (APPLE-FABRIC)
Proposes direct HomeKit Accessory Protocol (HAP-1.1) advertisement
from the Seed runtime so HomePod / Apple Home discovers RuView with
zero Home Assistant intermediary. Two implementation tracks:
P1 (lands first): HAP-python sidecar — a tiny pyhap entrypoint in
the same Docker image, ~80 LOC; fastest to ship; pairing flow
from the Apple Home app.
P2 (follow-up): Rust-native HAP via the hap crate; replaces P1;
closes the ADR-116 P7 stub (matter = [] feature flag becomes
matter = ["dep:hap"]); single binary.
P3 (later): Matter Controller path when matter-rs stabilizes.
Strategic framing: RuView contributes the invisible cognition layer
(passive RF presence, breathing/HR, fall, BFLD identity-risk) the
Apple ecosystem cannot natively sense; Apple Home contributes the
consumer-grade discoverability + Siri + automation graph + trust
that an open sensing stack cannot bootstrap. The structural privacy
gate from ADR-118 (only class-2 and class-3 frames cross the Matter
boundary, per ADR-122 §2.4) is what makes this safe to do at all.
Refs ADR-115, ADR-116, ADR-118, ADR-122.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:d7087a5f9fa1c64e110f879a5576eda4341784a7
Release v1335
Automated release from CI pipeline
Changes:
fix(docker): bump rust:1.85 → 1.89 (matches workspace rust-toolchain.toml)
Build failed on the multi-arch run: time@0.3.47 requires rustc 1.88.0
and the workspace toolchain pin is already 1.89 (needed for ruvector-core's
avx512f target_feature, mmap-rs edition 2024, hnsw_rs is_multiple_of).
Dockerfile lagged on 1.85.
Refs #794.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:9fda90f3e5b4121103d97b1e4ffee419afd72ead