Commit Graph

980 Commits

Author SHA1 Message Date
rUv 29e937ef52
Merge pull request #1044 from ruvnet/feat/edge-skills-synthetic-validation
feat(wasm-edge): unified EdgePipeline (all ~64 skills) + honest synthetic validation harness
2026-06-13 00:46:29 -04:00
ruv 41665d3de9 test(wasm-edge): synthetic-ground-truth validation harness for edge skills (ADR-160)
Plant signals with known answers, run the real detector, MEASURE detection
accuracy / precision / recall / rate-error — synthetic-ground-truth ONLY, not
field accuracy.

MEASURED-on-synthetic (12 tests, all green):
- vital_trend, exo_ghost_hunter(hidden breathing), occupancy, intrusion,
  exo_rain_detect, sig_optimal_transport: acc 1.000
- exo_time_crystal: 1.000 on periodic-vs-aperiodic (its sub-harmonic-vs-clean-
  period claim is NOT separable by autocorrelation — recorded honestly)
- sig_flash_attention: 8/8 peak localization; spt_spiking_tracker: 4/4 zone
  localization (sparse plant); sig_mincut_person_match: 0 id-swaps/40 frames
- lrn_dtw_gesture_learn: enrollment validated (replay-match reported, not asserted)
- sig_sparse_recovery: trigger validated; recovery accuracy reported NEGATIVE
  (-2.2% vs unrecovered baseline) — only its detect/trigger path is validated

DATA-GATED (listed, NOT faked): med_seizure/apnea/cardiac/respiratory/gait,
sec_weapon_detect, exo_emotion/happiness/dream_stage/gesture_language — each
needs real labelled clinical/affect/ASL/metal-object data; no number claimed.

benchmarks/edge-skills/RESULTS.md documents every result + reproduce command and
the explicit honesty boundary. ADR-160 deferred 'per-skill accuracy validation'
item updated to PARTIALLY MEASURED-on-synthetic + DATA-GATED.

Suite: 631 passed default / 669 medical, 0 failed.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-13 00:33:51 -04:00
ruv c6eacb7ff8 feat(wasm-edge): unified EdgePipeline wiring all ~64 edge skills (ADR-160)
Register every runtime skill module behind one uniform EdgeSkill trait and
run them all per CSI frame, aggregating (skill, event_id, value) triples.

- src/pipeline_all.rs: CsiFrameView (borrowed per-frame inputs), EdgeSkill
  trait, EdgePipeline (Box<dyn> dispatch over all skills), SkillEvent/SkillInfo
  introspection. Host-only (std); the wasm no_std build keeps the flagship
  lib.rs pipeline.
- src/skill_registry.rs: per-skill adapters (fwd_skill! direct-forward +
  synth_skill! for non-tuple returns). No skill DSP changed — only call wiring.
  gesture/coherence/adversarial synthesize one event; sig_sparse_recovery gets
  an owned mutable amplitude scratch; timer skills driven once per frame.
- med_* tier registered only under --features medical-experimental (preserves
  the ADR-160 safety gate). Default tier = 59 skills; +medical = 64.
- tests/pipeline_all.rs: 4 tests — all skills run without panic over 300
  deterministic synthetic frames, every emitted id is declared by its skill,
  introspection well-formed, default tier excludes medical (59) / medical adds 5 (64).
- examples/run_all_skills.rs: runnable demo printing per-skill event totals.

Full suite: 619 passed default (615 M6 baseline + 4 new), 0 failed.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-13 00:20:29 -04:00
rUv 153bc0595b
Merge pull request #1043 from ruvnet/docs/adr-gap-remediation-1
docs(adr): Gap Register remediation — write phantom ADR-132/165, fix ADR-134 collision, correct statuses
2026-06-12 23:11:10 -04:00
ruv 8fd4ee917d docs(adr): mark ADR-164 Gap Register items resolved (G3, G5) + correct G2
Records the remediation done in this branch:
- G3 (homecore-recorder/migrate phantom ADRs) → RESOLVED: ADR-132 + ADR-165 written.
- G5 (10 streaming-engine Proposed-while-built) → RESOLVED: 136-145 flipped to
  "Accepted — partial", with the honest caveat that the notes describe building
  blocks built+tested, not live-path integration.
- G2 (missing Status headers) → corrected: ADR-134-CIR was mislabeled as missing
  (it has a Status row); the 2 genuine misses (147-benchmark-proof, 052-ddd) are
  both inside owner-gated duplicate-number collisions, so left untouched. Early
  ADRs using "| Status |" vs "| **Status** |" are different-format-but-present.
  Net: 0 status headers added.
- Updated Coverage-Gaps bullets for recorder/migrate.

Renumbering/dedup of the 6 collisions left owner-gated, as instructed.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 23:01:10 -04:00
ruv 5c5112db0e docs(adr): correct streaming-engine statuses 136-145 Proposed→Accepted — ADR-164 G5
All 10 streaming-engine ADRs (136-145) carried Status: Proposed while each has a
concrete commit-pinned "Built -- tested building block" Implementation-Status note
(136: 11f89727f; 137: 4fa3847ac; 138: fc7674bde; 139: 521a012d8; 140: 169a355bd;
141: 7d88eb84c; 142: 1f8e180d6; 143: 2d4f3dea5; 144: b10bc2e9a; 145: 0f336b7d3),
each with a test count.

Flipped each to "Accepted — partial (built + tested building block; integration
glue pending — see Implementation Status, commit <hash>)". Honest "partial", not
full Accepted: the notes themselves state the blocks are tested+compiling but
"mostly not yet on the live 20 Hz path". 143 (v2 dataset-gated) and 144 (no UWB
radio in fleet) carry their specific residual gates inline.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 23:00:54 -04:00
ruv e3696da8d8 docs(adr): write ADR-165 (HOMECORE-MIGRATE), repoint migrate 134→165 — ADR-164 G3
homecore-migrate cited "ADR-134 (HOMECORE-MIGRATE)", but on-disk ADR-134 is
"First-Class CIR Support" — a different decision. The migrate crate was governed
by a phantom identity (ADR-164 Gap G3).

- New ADR-165-homecore-migrate-from-home-assistant.md (next free number),
  reverse-documented from the shipped P1 scaffold: HA .storage reader, versioned
  format gate (unknown minor_version = hard error), per-artifact parsers, inspect
  CLI, structured errors. Status: Accepted — P1 scaffold (full conversion P2).
  Trust-boundary rationale for the untrusted .storage import is the centerpiece.
- Repointed every ADR-134 governing reference in v2/crates/homecore-migrate/
  (Cargo.toml, README.md, src/lib.rs, src/config_entries.rs,
  src/storage_format/mod.rs) → ADR-165. Left the ADR-132 (recorder-feature)
  refs intact. Explanatory renumber notes retained.
- On-disk ADR-134 (CIR) untouched. ADR-126 series-map registry row owner-gated.

Docs/comments only — cargo build -p homecore-migrate --no-default-features
still compiles.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 23:00:33 -04:00
ruv 9457d441b2 docs(adr): write missing ADR-132 (HOMECORE-RECORDER) — resolves ADR-164 G3
homecore-recorder cites "ADR-132" in Cargo.toml/README/lib.rs/schema.rs/
semantic.rs, but no ADR-132 file existed — the durable-state backbone was
ungoverned (ADR-164 Gap G3 / Coverage-Gaps Lens A).

Reverse-documented from the shipped, tested crate (not invented): SQLite
HA-compatible recorder schema v48 (P1, 14 tests), ruvector HNSW semantic
index (P2, feature-gated, 20 tests), hash-embedding honesty note, P3 real
embeddings planned. Status: Accepted (shipped). Filename matches the link
the crate README already pointed at. Documented retroactively; honest about
hash-embedding limits and unbenchmarked latency targets.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 23:00:15 -04:00
rUv 626b4b2e97
Merge pull request #1042 from ruvnet/docs/adr-164-gap-analysis
docs(adr): ADR-164 — ADR corpus gap analysis & remediation backlog (162 ADRs)
2026-06-12 22:47:21 -04:00
ruv 260fceefe9 docs(adr): ADR-164 corpus gap analysis + research notes (162 ADRs)
Parallel gap analysis of all 162 ADRs (14-agent workflow): status distribution,
prioritized Gap Register, supersession integrity, contradictions/retractions
(anti-slop centerpiece), coverage gaps, and the honestly-gated backlog.

Key findings: 6 duplicate ADR numbers + 3 missing Status headers (breaks the
index); shipped crates citing phantom governing ADRs (homecore-recorder->ADR-132
nonexistent, homecore-migrate->ADR-134 mis-identified); streaming-engine ADRs
136-145 marked Proposed but actually Built; open ADR-080 sensing-server security
findings never closed; ~64 proposed-only ADRs; pre-ADR-155 accuracy claims are
CLAIMED not MEASURED. Detail in docs/adr/gap-analysis/{census,lens-findings}.md.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 22:40:32 -04:00
rUv e063de5970
Merge pull request #1039 from ruvnet/release/patch-1009-1004
release: patch-bump signal/sensing-server/cli for #1009+#1004 fixes (+ first-publish calibration)
2026-06-12 17:09:29 -04:00
ruv 53b327e649 release: bump signal 0.3.4 / sensing-server 0.3.3 / cli 0.3.1 (fixes #1009, #1004)
HE20 calibration baseline fix (signal), sensing-server --source auto simulate-latch
fix (sensing-server), HE20 calibrate parser/asserts (cli). See PR #1038.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 16:55:27 -04:00
rUv ad3908bd9e
Merge pull request #1038 from ruvnet/fix/issues-1009-1004-real-csi-ingest
fix: real CSI-ingest bugs — HE20 baseline corruption (#1009) + sensing-server simulate-latch (#1004)
2026-06-12 16:47:25 -04:00
ruv a27ee6f6cd fix(csi-ingest): real HE20 CSI no longer dropped or replaced with simulated data (#1009, #1004)
Two ingest bugs caused real ESP32-C6 HE20 CSI to be silently discarded or
never received — the "real data silently lost" failure class. Each fix is
pinned by a test that fails on the old code.

#1009 §1b — HE20 baseline recorder trimmed 256->242 bins by sequential index.
ESP-IDF v5.5.2 delivers all 256 FFT bins for an HE20 frame, but
CalibrationConfig::he20() carried num_active: 242, so the recorder (no HE20
tone map — extract_first_stream takes the first num_active columns
sequentially) kept bins 0..242 = the lower guard band + DC, NOT the 242 active
tones, silently corrupting the empty-room baseline. Now num_active: 256 records
every delivered bin, aligned 1:1 with the live deviation() path. The exact-242
tone map stays only in cir.rs (HE20_ACTIVE), where the Phi sensing matrix needs
it. HE20 synthetic/bench fixtures updated to feed 256-bin frames.

#1009 §1a/§1c — u8->u16 n_subcarriers truncation, regression-pinned.
The ADR-018 wire format carries n_subcarriers as u16 LE at bytes 6-7; a 256-bin
HE20 frame (byte6=0x00) read as one byte decodes to 0 subcarriers -> every
frame skipped. The CLI parser and the sensing-server parse_esp32_frame were
already corrected to u16 under #1005/ADR-110; added regression tests that fail
on the old single-byte read so the truncation cannot silently return.

#1004 — --source auto latched on simulate forever, never binding UDP :5005.
A one-shot boot probe resolved the source once; with no CSI flowing at boot
(the normal firmware/server startup race) it served simulated poses for the
whole process and ignored real CSI arriving seconds later (the prior #937 fix
hard-exited instead — equally wrong). New plan_source() state machine: in auto
mode ALWAYS bind the UDP receiver and serve simulated only until the first real
frame, then udp_receiver_task promotes source -> esp32 (mirroring the existing
esp32 -> esp32:offline reversion). simulated_data_task self-suspends once
promoted. Explicit --source simulated stays a hard, UDP-free offline override.

Validation: 3-crate tests 1118 passed / 0 failed; workspace 3166 passed /
0 failed; Python proof VERDICT: PASS (bit-exact, unaffected). cir.rs untouched.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 16:37:55 -04:00
rUv 3d7530f08d
Merge pull request #1033 from ruvnet/feat/v2-zero-warnings-hygiene
chore: zero-warnings hygiene — clear 13 build warnings across v2/crates
2026-06-12 09:09:18 -04:00
ruv d4170ad159 fix: revert config-dependent cargo-fix changes (kept only always-safe edits)
cargo fix ran under --no-default-features and removed an import/mut that are
'unused' ONLY in the minimal build but genuinely USED in CI's full build
(error[E0596]: cannot borrow result as mutable in desktop discovery.rs). Those
are false-positive warnings in the minimal config. Reverted bridge.rs/
commissioning.rs/discovery.rs to origin/main; kept the always-safe edits
(dead-code #[allow] notes + ClockGateDecision doc fields + camera macOS-only
allow). Full-features build of all four crates: Finished, 0 errors.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 08:56:26 -04:00
ruv 0d6c20c278 chore(v2): zero-warnings hygiene — clear 13 build warnings across 4 crates
Removed unused Matter imports (sensing-server bridge/commissioning), dropped
needless mut (bridge, desktop discovery), documented ClockGateDecision variant
fields (ruvector coherence), and marked deferred-P2/platform-only helpers
#[allow(dead_code)] with honest notes (entity_on_matter/next_endpoint =
Matter-publisher API deferred per ADR-159 §A5; decode_jpeg_to_rgb = macOS-only).
Behavior-neutral; touched-crate tests green. Remaining 1 warning is a benign
Windows .pdb filename collision inherent to the Tauri lib+bin desktop crate
(renaming the bin would break Tauri bundling — won't-fix for a cosmetic warning).

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 08:44:42 -04:00
rUv 3fb40a9deb
Merge pull request #1030 from ruvnet/feat/v2-beyond-sota-sweep-m9
Beyond-SOTA sweep M9 (ADR-163): edge-latency measurement debt → MEASURED-on-host benches
2026-06-12 08:14:57 -04:00
ruv 1a17cc5b06 docs(ADR-163): edge-latency RESULTS + PROOF/prove.sh wiring (T3)
Adds benchmarks/edge-latency/RESULTS.md (wiflow-std RESULTS style: each
measured number with reproduce command, machine, MEASURED-on-host grade,
and the honest host-vs-ESP32 / steady-state-vs-cold-start caveats) and
ADR-163 (HEADLINE: CLAIMED latency budgets -> MEASURED-on-host, closing
M5/M6 measurement debt; ESP32-on-hardware still pending).

- ADR-160 deferred 'criterion benches for process_frame budget claims'
  line updated to DONE (host) with the ESP32-pending note.
- PROOF.md performance table gains the two edge-latency reproduce rows;
  provenance ADR range extended to ADR-163.
- prove.sh gated section gains the edge-latency bench note (host proxy
  only; not asserted, never claims the ESP32 figure).

Benches/docs only; no crate republishes.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 08:02:07 -04:00
ruv 7c13ec6a00 bench(cogs): steady-state CPU infer latency benches (ADR-163 T2)
Criterion benches over InferenceEngine::infer for cog-person-count and
cog-pose-estimation, on Device::Cpu with the real shipped safetensors
weights (asserts candle backend so the stub is never silently benched),
over a fixed CSI window after a warm-up forward.

HOST-MEASURED steady-state medians (idle box): ~305us each. This is the
recurring per-frame cost and is explicitly NOT the pose manifest's
cold_start_ms_avg=5.4 (a different measurement, weight-load included, taken
on ruvultra/RTX 5080) -- the two are labelled and not conflated.

Closes the ADR-159/160 deferred cog inference-latency item. No production-
code behavior change.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 08:01:50 -04:00
ruv d3606d51a7 bench(wasm-edge): host process_frame latency benches (ADR-163 T1)
Criterion benches over the M6-audit-named heaviest hot paths:
exo_time_crystal 256x128 autocorrelation, exo_ghost_hunter periodicity,
sec_weapon_detect per-subcarrier Welford, med_seizure_detect clonic rhythm
(medical-experimental-gated). Drives each through the public process_frame
on a fixed synthetic CSI frame after warming the relevant buffers.

Crate is workspace-excluded: run from the crate dir with --features std.
Set lib bench=false so libtest does not intercept criterion CLI flags.

HOST-MEASURED medians (Intel Core Ultra 9 285H, native --release), NOT the
ESP32/WASM3 doc budget (that needs hardware): time_crystal 17.3us,
ghost_hunter 1.44us, weapon 0.42us, seizure 0.10us.

Closes the ADR-160 deferred 'criterion benches for process_frame budget
claims' item on host. No production-code behavior change.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 08:01:29 -04:00
rUv 48db9d37a6
Merge pull request #1026 from ruvnet/feat/v2-beyond-sota-sweep-m8
Beyond-SOTA sweep M8 (ADR-162): enforce plugin Ed25519 signatures + capability isolation + bounded RunModes
2026-06-12 02:04:24 -04:00
ruv e7b1b66f74 docs(adr): ADR-162 — plugin security + bounded RunModes; mark ADR-161 P4/P5/§A5 DONE
ADR-162 records the M8 work that makes ADR-161's honestly-deferred plugin
security claims TRUE: P4 (Ed25519 signature + SHA-256 integrity verification,
secure-default trust policy), P5 (capability/authority isolation on
hc_state_set), and §A5 (bounded Restart/Queued/max RunModes). Each fix MEASURED
with a failing-on-old test; threat model table (tampered module, untrusted
publisher, over-privileged write, run-mode exhaustion); cog-ha-matter Ed25519
reuse cited; remaining honest deferral (key provisioning/rotation, native
in-process plugins, HAP pairing).

ADR-161 deferred-backlog lines for P4/P5/RunModes struck through and marked
DONE → ADR-162; §B5 note points forward to the now-implemented P4 gate.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 01:47:30 -04:00
ruv 3292bd2c5d feat(homecore-automation): implement bounded RunModes Restart/Queued/max (ADR-162, completes ADR-161 §A5)
ADR-161 implemented RunMode::Single (AtomicBool re-entrancy guard) + Parallel
but honestly left Restart/Queued/max as "ACCEPTED-FUTURE / unbounded parallel" —
every non-Single mode spawned an unbounded task. This makes them real.

New `runmode` module — per-automation RunState owns the machinery:
- Restart: aborts the in-flight action task (tokio::task::AbortHandle) and
  starts a fresh one.
- Queued: serializes runs in arrival order via a per-automation async Mutex —
  sequential, never concurrent, nothing dropped.
- max: N: caps concurrency at N via a per-automation Semaphore; triggers beyond
  N queue (await a permit) rather than running concurrently (HA bounded
  semantics). Documented in the module table.
- Single/IgnoreFirst/Parallel preserved.

engine.rs now holds a RunState per registration and calls run_state.dispatch()
at all three trigger sites (event loop, timer, fire_time_for_test); the old
spawn_run is removed. engine.rs trimmed to 433 lines.

Tests (tests/engine_behaviors.rs) — verified to FAIL on the old unbounded-
parallel dispatch (simulated and confirmed each panics), pass on the new:
- restart_mode_cancels_prior_run (old: both runs complete → 2; new: 1)
- queued_mode_runs_sequentially_not_concurrently (old: max concurrency 3; new:
  all 3 run, max concurrency 1)
- max_two_caps_concurrency_at_two (old: 4 concurrent; new: all 4 run, max 2)

homecore-automation --no-default-features: 45 passed (lib 37, engine_behaviors
8), 0 failed.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 01:40:23 -04:00
ruv 0ca903b497 feat(homecore-plugins): enforce plugin signature + capability isolation (ADR-162 P4/P5)
ADR-161 honestly relabelled the manifest's wasm_module_hash / wasm_module_sig /
publisher_key as "(P4 — not yet enforced)" and the homecore_permissions claims
as deferred P5 authority isolation. This makes both real and tested.

P4 (signature/integrity verification, SECURITY):
- New `verify` module: SHA-256 module-hash check + Ed25519 signature
  verification over the digest against publisher_key, with a PluginPolicy
  trust allowlist and an explicit AllowUnsigned dev escape hatch (loud warn).
  Secure default rejects unsigned / unknown-publisher / tampered modules.
- Reuses the in-repo cog-ha-matter::witness_signing Ed25519 pattern; sha2 is a
  workspace dep, ed25519-dalek/hex/base64 already in the lock — no new external
  dep tree (only new edges in homecore-plugins).
- WasmtimeRuntime::load_plugin verifies before instantiation; legacy load_wasm
  retained for trusted/test modules.

P5 (authority/capability isolation, SECURITY):
- New `permissions` module: PermissionSet distilled from homecore_permissions
  (state:write:<glob> or bare entity glob). hc_state_set now consults it and
  returns a typed -3 to the guest on an undeclared write (no host panic).

Tests (fail on old code, which had no load_plugin/verify and an unchecked
hc_state_set): tampered module rejected; valid sig from trusted key loads;
valid sig from untrusted key rejected; unsigned rejected by default and loads
only under AllowUnsigned; light.* plugin writes light.kitchen but is denied
lock.front_door; no-permission plugin can write nothing. Real deterministic
keypair signs real bytes.

Manifest doc updated: P4/P5 now ENFORCED (was "not yet enforced").

homecore-plugins --features wasmtime: 32 passed (lib 23, integration 9), 0 failed.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 01:33:52 -04:00
rUv b8e870b314
Merge pull request #1025 from ruvnet/feat/v2-beyond-sota-sweep-m7
Beyond-SOTA sweep M7 (ADR-161): HOMECORE WS auth-bypass fix + automation engine + security
2026-06-12 01:15:42 -04:00
ruv d1328b0299 test(homecore-api): serialize HOMECORE_CORS_ORIGINS env tests (fix parallel race)
env_override_* and env_empty_* both set_var/remove_var the same process-global
HOMECORE_CORS_ORIGINS; under full-workspace parallelism they raced (one's
remove_var wiped the other's value mid-assert). Serialize via a poison-tolerant
module Mutex. Test-only.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 01:00:58 -04:00
ruv d0da5888e3 docs(adr): ADR-161 — HOMECORE server-layer security & honest-labeling sweep (M7)
Records the Milestone 7 audit: library cores are real (anti-slop positive) but
the network boundary had a CRITICAL WS auth bypass (A1) + reply-theater (A2) +
documented-but-no-op automation (A3-A7) + a network-exposed dev bin (A8), all
fixed and graded MEASURED with failing-on-old tests. Cites the NO-ACTION
security positives (uuid::v4 CSPRNG refuted-suspicion, hardened CORS,
no-traversal migrate, no-secrets-in-logs, honest HAP stub) and the deferred
backlog (plugin authority-isolation P5, sig-verification P4, HAP real pairing
P2, bounded run-modes, YAML load-at-boot).

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 00:55:52 -04:00
ruv e51704cd25 docs(homecore-plugins): label sig/hash fields '(P4 - not yet enforced)' (ADR-161 B5)
manifest.rs documented wasm_module_hash as 'verified before execution' but
wasm_module_hash/wasm_module_sig/publisher_key are never read for verification
(only set to None in tests). Re-doc'd the three fields as P4-not-yet-enforced
so the doc matches the code. No verification code added (that is P4); no false
capability claimed.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 00:55:51 -04:00
ruv dff75a479e fix(homecore-automation): start engine + implement time/run-mode/choose/template (ADR-161 A3-A7)
A3 (HIGH): homecore-server constructed AutomationEngine then dropped it
immediately while the doc claimed automation was active. Now .start()s the
engine into a long-lived binding (event loop + timer task).

A4 (HIGH): Trigger::Time was hard-coded false with no timer. Added a 1 Hz
wall-clock timer task that fires time: automations when local HH:MM:SS matches
'at' (HH:MM or HH:MM:SS); matches_sync(Time)=false is now correct + documented.

A5 (HIGH): RunMode was documented as AtomicBool-enforced but every trigger
spawned unbounded parallel. Each automation now carries a running AtomicBool;
Single/IgnoreFirst skip re-entrant triggers, Parallel fires every time.
(Bounded Queued/Restart/max → ACCEPTED-FUTURE, honestly stated in the doc.)

A6 (HIGH): Action::Choose discarded choices and always ran default. Now
deserialises each branch's conditions, evaluates them, and runs the first
matching branch; default only if none match.

A7 (MEDIUM): template: conditions were always false in the engine path
(EvalContext built with template_env: None). The engine now builds a
TemplateEnvironment over the state machine and threads it into every
EvalContext (event loop, timer, Choose).

Tests (fail on old source):
- engine_behaviors::time_trigger_fires_via_timer_path (A4)
- engine_behaviors::single_mode_does_not_double_fire_on_rapid_triggers (A5; old fired 2x)
- engine_behaviors::parallel_mode_does_fire_concurrently (A5)
- action::choose_runs_matching_branch_not_default (A6; old ran default)
- engine_behaviors::template_condition_evaluates_true_in_engine (A7; old always false)

engine.rs kept <500 lines; behavioral tests moved to tests/engine_behaviors.rs.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 00:55:34 -04:00
ruv 9d52d49c0b fix(homecore-api): close WS auth bypass + reply-theater, harden dev bin (ADR-161 A1/A2/A8)
A1 (CRITICAL): the /api/websocket handshake accepted any non-empty token,
ignoring the LongLivedTokenStore whitelist the REST path enforces — a full
WS auth bypass. Now validates via state.tokens().is_valid() before auth_ok;
wrong tokens get auth_invalid + close.

A2 (HIGH): WS command replies were pushed into an mpsc whose only consumer
logged and discarded them — no result/pong/event reached the client. Split
the socket with futures StreamExt::split; a dedicated writer task drains the
response channel onto the wire.

A8 (HIGH): the homecore-api dev bin bound 0.0.0.0 with unconditional
allow-any auth and no env path. Wired the HOMECORE_TOKENS env path (dev
fallback warn-logged when unset) and defaulted the bind to 127.0.0.1
(HOMECORE_BIND to opt into LAN).

Tests (fail on old source):
- ws_handshake::wrong_token_is_rejected (old → auth_ok)
- ws_handshake::result_reply_is_received / ping_pong_reply_is_received (old → timeout)
- server_bin_auth::provisioned_bin_rejects_wrong_bearer / from_env_path_enforces_whitelist

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-12 00:55:16 -04:00
rUv d0a7690f8f
Merge pull request #1024 from ruvnet/feat/v2-beyond-sota-sweep-m5
Beyond-SOTA sweep M5–M6 (ADR-159/160): appliance + edge-skill honesty + crates.io publish
2026-06-12 00:39:21 -04:00
ruv 8487192d0f docs(proof): PROOF.md capstone + scripts/prove.sh reproduction harness
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>
2026-06-12 00:19:43 -04:00
ruv d120cc2278 test(sensing-server): unique per-process temp dirs (deterministic under concurrent runs)
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>
2026-06-12 00:11:24 -04:00
ruv 8ad0d0f91c test+docs(wasm-edge): honest-labeling presence tests + ADR-160 (ADR-159 backlog now TRUE)
- 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>
2026-06-12 00:01:22 -04:00
ruv 36af09a4a8 feat(wasm-edge): honest labeling + static-mut soundness for edge skills (ADR-160)
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>
2026-06-12 00:01:04 -04:00
ruv 772ece4568 docs(adr): ADR-159 Cognitum appliance beyond-SOTA sweep
Records the anti-AI-slop sweep over cog-person-count, cog-pose-estimation,
cog-ha-matter, ruview-swarm. HEADLINE: the "never identified anyone"
accusation is REFUTED (real SHA-pinned Ed25519-signed trained Candle
models, honest 34%/3% accuracy in manifests). Documents claim-surface
fixes A1-A5 (MEASURED), NO-ACTION positives (witness chain, fusion, PPO +
randn audit), graded SOTA landscape (counting/pose DATA-GATED, swarm MARL
untrained-at-runtime by design), and the deferred backlog (benches,
Location/Vector, Matter v0.8, wasm-edge accuracy).

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-11 23:10:03 -04:00
ruv 48b002fa7e docs(cog-ha-matter): stop claiming Matter until it exists (ADR-159 A5)
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>
2026-06-11 23:10:02 -04:00
ruv 8d9c5994db fix(ruview-swarm): honest NED metres in Remote ID, not WGS84 (ADR-159 A3)
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>
2026-06-11 23:10:02 -04:00
ruv 6b5fd3cf25 fix(cog-person-count): emit real signed manifest from CLI (ADR-159 A4)
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>
2026-06-11 23:10:01 -04:00
ruv 2400216920 fix(cog-person-count): flag untrained-class counts low_confidence (ADR-159 A2)
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>
2026-06-11 23:10:01 -04:00
ruv 98bf8c4726 fix(cog-pose-estimation): emit frames under default config (ADR-159 A1)
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>
2026-06-11 23:10:00 -04:00
ruv 2e4461d64d release: bump 9 crates changed in the beyond-SOTA sweep for crates.io
vitals/wifiscan/hardware/nn 0.3.0->0.3.1, ruvector 0.3.1->0.3.2,
signal 0.3.2->0.3.3, train 0.3.1->0.3.2, mat 0.3.0->0.3.1,
sensing-server 0.3.1->0.3.2.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-11 22:41:21 -04:00
rUv 427c56881b
Merge pull request #1023 from ruvnet/feat/v2-beyond-sota-sweep
Beyond-SOTA v2/crates sweep (ADR-154–158) + implement every stub for real (no AI-slop)
2026-06-11 22:27:59 -04:00
ruv 97fae198d1 docs(changelog): beyond-SOTA sweep ADR-154–158 + stub-implementation push
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-11 22:16:05 -04:00
ruv 156323564a docs(readme): correct person-identification claims to measured reality (#1021)
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>
2026-06-11 22:13:05 -04:00
ruv d79c22e03a fix(homecore-assist): exact in-memory cosine k-NN, drop fragile :memory: HNSW
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>
2026-06-11 22:13:04 -04:00
ruv 3d96789475 docs(adr): ADR-158 MAT/world-model beyond-SOTA sweep (graded, MEASURED)
Records the cluster sweep: §1 triage unification, §2 real RSSI + dedup, §3 real
ESP32/UDP/PCAP ingest with honest typed errors, §4 parabolic interpolation,
§5 real GDOP, §6 occworld-prior fail-safe (mat consumes none). Graded SOTA table
(RF-through-rubble DATA-GATED; worldgraph NO-ACTION already-SOTA; worldmodel
clamp-proven; pointcloud cited), confirmed negative results, deferred backlog
(nothing dropped), and reproduction commands.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-11 21:54:04 -04:00
ruv e1dc6e05ab feat(mat): wire real ESP32/UDP/PCAP CSI ingest; honest typed errors for gated adapters (ADR-158 §3)
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>
2026-06-11 21:54:04 -04:00
ruv 982994ca3c fix(mat): real dimensionless GDOP = sqrt(trace((HtH)^-1)), not ad-hoc angle factor (ADR-158 §5)
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>
2026-06-11 21:54:04 -04:00