Points v2/crates/ruforecast at ruvnet/RuForecast@a802067f, the tip of
fix/governance-and-spend-enforcement (ruvnet/RuForecast PR #2), which closes
14 code-review findings against the training stack merged as #1766 -- most
critically, ADR-349's governance-verification and spend-approval-record
requirements were specified but never actually enforced by the fal.ai
hosted path; they are now.
Adds ADR-354 recording this as a RuView-level integration decision and
pointing to the submodule's own ADR-350 for the full technical record,
since that repository is now the source of truth for the forecast
subsystem's decision history.
Depends on ruvnet/RuForecast#2 merging with green CI first; see that PR for
status before merging this one.
Trains a real fal.ai LoRA fine-tune (fal-ai/flux-lora-fast-training) on
frames extracted from the real fal.ai-generated room-visualization MP4s
already captured this session, so display-layer generation has a specific
trained style target instead of prompt engineering against a stock model.
Architecture boundary: this model only ever produces supplementary
synthetic visual/pixel output. It has no path into measured/derived RF,
pose, vitals, identity, or confidence values, which remain local and
authoritative.
Real run: request 01a060b2-c940-7972-abf9-ea48847eb2ae, 1000 steps, 27
training images, ~$2.04 spend, validated with a real inference call
against the trained LoRA (assets/fal-visual-teacher-sample.png).
Chronos-Bolt (base/small), Chronos-T5-small, and TimesFM-2.5-200M run
zero-shot (no fine-tuning) on the same BIDMC cross-entity test windows,
baselines, and WQL/MAE metrics as the prior from-scratch RuForecast
BIDMC result. Unlike every from-scratch RuForecast configuration tried
this session, all four pretrained checkpoints beat both last-value and
seasonal-naive baselines on WQL, on both independent patient-partition
judges (12-42% margin), consistent with the massive-pretraining-corpus
hypothesis from the prior literature pass.
* feat(forecast): add independent Rust training stack
Signed-off-by: Codex <codex@openai.com>
* docs(forecast): record informal HPO exploration note (unaccepted)
Records an exploratory Darwin Mode numeric-genome hyperparameter search
against the tiny_ci synthetic accuracy protocol: WQL improved 0.257 -> 0.161
-> 0.153 over two search rounds, staying ahead of both baselines throughout.
Explicitly scoped as informal/exploratory (not a frozen leakage-free report,
not eligible for the evidence ledger, not validated for large_linux or any
real dataset) per this doc's own evidence-tagging discipline.
* feat(forecast-core): add per-horizon weighted quantile loss
weighted_quantile_loss collapses the whole horizon into one aggregate
number, hiding whether error grows with lead time. Add a sibling
function using the identical per-cell pinball formula and domain
checks, just reduced per horizon step instead of globally. A unit
test reconstructs the aggregate from the per-step numerators/
denominators to prove the two functions agree exactly, not just
approximately.
* feat(forecast-model): add evaluation-only local activation
Adds activate_for_evaluation and build_eval_input, gated behind the
cpu feature. activate_for_evaluation self-signs an unsigned candidate
with a fixed, publicly-known, non-secret Ed25519 key so a CLI operator
can run inference against their own just-trained candidate without a
real release signature -- explicitly never a production trust path,
documented as such in the module doc comment. The schema-digest check
in ArtifactActivationPolicy still applies in full; only signing is
relaxed. build_eval_input constructs a single-window ModelInput for
CPU inference from raw context-major values/mask arrays, matching the
training batch builders exact time-feature/descriptor encoding.
Six unit tests cover: malformed-candidate rejection, digest-mismatch
rejection (proving the schema check has teeth even on this relaxed
path), getting past the policy gate with a matching digest, and
eval-input shape validation.
* feat(forecast-train): add evaluate and prepare-synthetic-dataset CLI
Turns this sessions throwaway HPO scripts into real, tested CLI
surfaces, replacing two example binaries that bypassed the CLI/TOML
training path entirely.
prepare-synthetic-dataset generates a larger, configurable synthetic
training shard (default 24 windows) plus a matching train-local.toml
with the given OptimizerSpec hyperparameters baked in, and a separate
held-out test.jsonl -- the same synthetic-only, local-validation-only
posture as prepare-local-example, just bigger and configurable.
evaluate scores a trained (unsigned) candidate against held-out
windows and the LastValue/SeasonalNaive baselines: overall weighted
quantile loss, a per-horizon breakdown, 80% interval coverage, and
missingness, for the model and both baselines. Explicitly lists what
docs/benchmarks/ruforecast.mds full accuracy protocol additionally
asks for that this does not cover (abstention coverage, selective
risk, site/device slices, interference regime, RuVector-retrieval
ablation) rather than silently omitting them -- each needs
infrastructure a single-entity synthetic fixture does not have.
Together the three real commands (prepare-synthetic-dataset,
train-local, evaluate) reproduce the exact WQL numbers the old
library-bypassing example scripts produced for the same
hyperparameters, confirmed by re-running the harness/ruview HPO
dry-run end to end against the new CLI path.
New integration test trains a real candidate via smoke, evaluates it
against held-out synthetic windows, and asserts the full report shape
and an empty-input rejection.
* feat(forecast-train): add prepare-synthetic-dataset --seed + Autogenous bridge
--seed (default 0, backward compatible) makes prepare-synthetic-dataset's
generator deterministic per offset: same seed -> byte-identical corpus
across runs (needed to train two genomes on the SAME corpus for a fair
comparison); different seeds -> genuinely independent corpora (needed for
honest multi-seed/multi-judge evaluation upstream, both in
harness/ruview/flywheel/ruforecast/gate.mjs's fitness function and in the
new v2/crates/ruforecast-autogenous-bridge crate added here).
ruforecast-autogenous-bridge is a LOCAL-DEV-ONLY (excluded from the v2
workspace, publish = false) bridge from this crate's real evaluate CLI
into ruvnet/autogenous's new regression-candidate promotion path (separate,
unpushed branch feat/regression-candidate-kind): runs N independent
train+evaluate judges on genuinely distinct synthetic corpora, signs
receipts, and gets a real cryptographically-verified PROMOTE/REJECT
decision -- defense in depth on top of, not a replacement for, Darwin's own
promotion gate. Path-depends on a sibling autogenous checkout that does not
exist in CI; build/run directly via `cargo build --manifest-path
crates/ruforecast-autogenous-bridge/Cargo.toml`.
cargo test -p ruview-forecast-train --no-default-features --features
cpu,cli: all green (unaffected existing tests + this backward-compatible
addition).
* docs(forecast): retract round-2 HPO result, record honest multi-seed finding
The earlier "Informal HPO exploration note" claimed a real improvement
(WQL 0.257 -> 0.153) from a 3-round hyperparameter search. That search
evaluated every candidate against one fixed synthetic corpus (seed 0) for
every round -- textbook overfitting. Independent verification against two
fresh corpora (via the new ruforecast-autogenous-bridge crate) showed the
"winner" losing to the baseline on both.
Fixed the root cause in harness/ruview/flywheel/ruforecast/gate.mjs:
candidates are now scored against three independent corpora, worst-case
across them, not one fixed corpus.
Re-ran the search under the fix. It found a new winner that genuinely beat
baseline on all three of its own search seeds -- and that winner ALSO lost
independent verification on fresh seeds. Two independent search rounds,
pre- and post-fix, both produced an illusory "winner." The honest reading:
at this dataset scale (24 synthetic windows) held-out WQL varies enormously
by which corpus is drawn, regardless of hyperparameters -- confirmed
directly by the baseline genome's own primary swinging from 0.83 to a full
regression across the three fixed search seeds with unchanged
hyperparameters. No RuForecast hyperparameter configuration has been shown
to reliably beat the trivial baselines out-of-sample at this scale.
Also fixes a real design inconsistency surfaced by this exploration: the
Autogenous regression-candidate promotion verifier
(envelope::regression::verify_regression_promotion, separate unpushed
ruvnet/autogenous branch feat/regression-candidate-kind) required all
judges to share one corpus_id, which conflicts with this kind's
intentional cross-corpus judge design. Corrected there (commit bfa4c48);
did not change either REJECT verdict, which were already driven by the
real NotBetterThanParent signal on their own.
Append-only: the original round-2 row is kept, read together with this
new amendment section, per this doc's own evidence-ledger discipline.
* refactor(forecast): extract RuForecast to ruvnet/RuForecast submodule
Mirrors the v2/crates/worldgraph pattern: RuForecast becomes its own
independent public repo/workspace (ruforecast-core/model/train), mounted
at v2/crates/ruforecast as a git submodule, with v2/Cargo.toml path-depping
into its sub-crates and excluding the submodule from the v2 workspace.
Full v2 --workspace check passes; the ruforecast CLI builds and runs
correctly from its new location. Real git history for the extracted
crates (7 commits) was preserved via git-filter-repo, not squashed.
* feat(autogenous-bridge): real-data independent verification tool
real_data_verify.rs: signs two real, temporally-independent judge
measurements (different train/test split boundaries on the same real
household vitals corpus, not synthetic seeds) through the real
Autogenous regression-candidate promotion path, and gets a genuine
cryptographically-checked PROMOTE/REJECT verdict.
Result recorded (see docs/benchmarks/ruforecast.md): REJECT. One judge
nominally beat the trivial baseline but by less than the 0.01
non-inferiority margin; the other judge lost outright. Consistent with
every synthetic-data search this session -- no configuration has yet
been shown to reliably beat trivial baselines out-of-sample, now
including a real 6390-sample household corpus.
Bumps the ruforecast submodule to pick up the evaluate real-gap fix.
* docs(forecast): record real-household-data result (REJECT, signed)
6390 real vital-signs samples, two independent temporal splits,
independently verified via the real Autogenous regression-candidate
promotion path. Signed verdict: REJECT -- neither split cleared the
non-inferiority margin. Same conclusion as every synthetic search this
session, now confirmed with real data too: more real data is the
credible next lever, not further search on this scale of fixture.
* chore(forecast): point ruforecast submodule at published main (post gap-tolerance fix)
* ci(forecast): fix ruforecast-ci.yml for the new v2/crates/ruforecast submodule layout
The RuForecast crates were extracted into a standalone submodule (v2/crates/ruforecast, mirroring the existing v2/crates/worldgraph pattern) and are no longer members of the v2 workspace. The CI workflow still referenced the old in-tree package names/paths (ruview-forecast-core/model/train under v2/), which broke every forecast job with "cannot specify features for packages outside of workspace".
Fixed every job to target the submodule: working-directory -> v2/crates/ruforecast, -p ruview-forecast-* -> -p ruforecast-*, all hardcoded Cargo.toml/source paths in the Python assertion and clean-room-scan blocks, the Swatinem/rust-cache workspaces input, the artifact-tree output paths, and the two levels of relative path (../ -> ../../) in the informational-benchmark steps whose working directory moved one level deeper.
Also collapsed the paths: trigger filters internal-crate globs (v2/crates/ruview-forecast-*/**) down to the single v2/crates/ruforecast path, since GitHub Actions path filters only ever see a submodule gitlink change as one entry in the parent tree, never its internal file paths -- the old globs could never have matched anything.
Includes a real cargo fmt fix (submodule commit d9902f9) for formatting drift left over from the earlier real-data gap-tolerance fix, which the contract job's fmt --check step would otherwise have failed on.
All four forecast CI jobs' real commands verified locally before push: cargo test/check for CPU, CUDA/WGPU compile-check, the contract job's Python assertion block, the hosted-boundaries clean-room scan, and cargo fmt --check.
* docs(forecast): record real BIDMC cross-entity holdout result (REJECT)
Two independent real-patient partitions (34/16 and 24/26 splits, 53 total
ICU patients from PhysioNet BIDMC, Open Data Commons Attribution License
v1.0) both show the model losing to trivial baselines by a decisive margin
(+69% and +601% worse WQL). First genuine cross-entity real-data test this
project has run; same conclusion as every prior synthetic and single-household
test. Full Autogenous signed verification was not run for this entry -
flagged explicitly in the note.
* chore(forecast): point ruforecast submodule at published main (example feature-gate fix)
* chore(forecast): point ruforecast submodule at published main (clippy fix)
---------
Signed-off-by: Codex <codex@openai.com>
ADR-262 §8 question 5 left the second modality open, asking whether it should
be rvcsi. This answers ultrasonic instead, because the cost collapsed:
rufield-adapters now ships UltrasonicReplayAdapter, the first adapter for
Modality::Ultrasonic (registry code 7, empty since v0.1), which parses,
validates and signs BatVu range profiles upstream. RuView only has to decide
what it will put on a wire.
Bumps vendor/rufield 43b1df3 -> 9955672. Two struct literals in bridge.rs gain
fields added upstream (Observation: track_id, attributes, identity_evidence,
channel_sounding_provenance; SensorDescriptor: coordinate_frame, position_m,
orientation_xyzw). All left empty, each for a stated reason rather than a
convenient default — the pose fields in particular, because a CSI link has no
boresight and §6 makes no validated room-coordinate claim. The nine existing
P1 gates pass unchanged.
The decision this module makes is structural rather than a runtime refusal.
The adapter's full per-bin frame is P0 and would be dropped by the egress gate
after all the work of parsing and signing it; its 32-bin coarse reduction is
P1 and egress-safe. So the module does not offer the choice — it configures
the coarse mode, because a consumer cannot un-coarsen a coarse profile whereas
a check can be reordered. The gate still runs and is asserted to drop nothing.
12 gates in tests/ultrasonic_gates.rs, including the honest negative result: an
ultrasonic scan produces no fused inferences at all, and both independent
reasons are pinned. The adapter declines to populate `presence` — one
transducer pair cannot distinguish a person from a coat over the back of a
chair — and the engine's feature vocabulary is entirely statements about a
body, so range_m has nothing to drive.
The fixture is BatVu's own emitter output, byte-identical to the one in
ruvnet/rufield, so schema drift fails a build in one of three repositories
rather than an ingest in a deployment.
Not wired into the running server; P1 shipped as a library before P3 wired it
in, and this follows the same staging.
Use mesh-aligned capture timestamps, remediate Rust advisories, harden the audit gate, and correct deployment claims. Includes the live MQTT subscriber lifetime fix verified against Mosquitto.
New leaf crate v2/crates/ruview-offaxis implementing ADR-324's projection
core from the published math only (Kooima 2008 generalized perspective
projection; Casiez 2012 one-euro filter) — no code from the unlicensed
prior-art repo. Dependency-free native core; wasm-bindgen surface gated to
wasm32 (cdylib+rlib, ~54 KB wasm after bindgen).
- projection: Screen (3 corners, any orientation) + off_axis() -> typed
errors, never NaN matrices; column-major f64 (three.js Matrix4 layout).
Tests pin the defining invariants: screen corners -> NDC corners for a
grid of eye positions and tilted screens; screen-plane points are
eye-invariant; centered eye reduces to the symmetric frustum; near/far
map to NDC -1/+1.
- filter: one-euro with injected timestamps (no clock in crate);
monotonicity/convergence/NaN-rejection tests.
- rf: field-peak extraction mirroring field_localize.rs constants
(X_SCALE 0.6, Z_SCALE 0.5, PEAK_THRESHOLD 0.35) and the Tier B
coarse-parallax stage (deadband, gain, hard clamp) so over-claiming is
impossible at the API level. No accuracy numbers asserted.
- wasm: OffAxisCamera + RfParallax bindgen classes; per-frame updates hold
last good state instead of throwing.
- benches (criterion): full Tier B frame ~598 ns; argmax scan optimized
-18%/-33% (20x20/100x100). MEASURED table + reproducer in README.
- examples/three.js/demos/07-off-axis-window.html: demo with SYNTHETIC
mouse simulator and labeled RF Tier B mode ('coarse body parallax - not
head tracking'), physical calibration panel, /ws/sensing input, and a
build-instructions overlay when the local pkg/ output is missing
(generated artifacts stay uncommitted; .gitignore entry added).
- Validated 23 unit tests + doctest, clippy clean, wasm32 release build,
Node smoke test of the bindgen output, and a headless-Chromium run of
the demo (engine load, eye response, mode labels, ws failure path).
- ADR-324: header + section 2.5 amendment recording the Rust/WASM core.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01BU3NcEgTpAVvu5QGtw4czT
Deep-research ADR answering whether icurtis1/off-axis-sneaker can be used
with RuView. Adopts the head-coupled perspective technique (Kooima
generalized off-axis projection) via a clean-room implementation — the
upstream repo is unlicensed, so no code or assets are reused. Defines a
tiered integration: webcam-fine tracking with RF presence gating and
multi-person arbitration (Tier A), an explicitly labeled RF-only coarse
body-parallax mode (Tier B), and evidence-gated future metric RF head
positioning (Tier C). No server changes; existing /ws/sensing and
/api/v1/stream/pose streams only. Indexed in the ADR README.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01BU3NcEgTpAVvu5QGtw4czT
Fix breathing confidence, Windows desktop launch and clean UI builds, contributor-harness line-ending integrity, runtime secret hygiene, and remove the six ADR-299 CSI/person-data files from the current tree.
Reviews and fixes RuView's 10 most recent substantive issues, plus closes
the wiring gap flagged in the perception-substrate review (docs/adr,
gist, release notes from the PR #1579 review).
## Fixed
- #1526: UI falsely claimed "LIVE — ESP32 Hardware Connected" whenever the
unauthenticated /api/v1/status probe 401'd. Now sends the bearer token
on the probe (the fallback direction was already fixed by ADR-295).
- #1554: top-level `classification` (GET /api/v1/sensing/latest) was the
last UDP packet's single node, not the fused room aggregate, so it
flapped at packet rate with 2+ disagreeing nodes. Now derived from
`RoomInference` (ADR-297's `fuse_room`) at both call sites.
- #1541: per-node MQTT `presence`/`presence_score` read a `classification`
JSON key that does not exist on `NodeInfo` (the real field is
`node_inference`), silently falling back to the room aggregate for
every node — reproducing the exact "lockstep publish" the field report
measured. Also fixed the *existing* regression test for this bug,
which used the same wrong key in its own fixture and so never caught it.
- #1557: pose-fusion's `wsPortMap` only knew port 3000, so a remapped host
port fell through to `localhost:8765` (nothing there for a remote
viewer). WS port is now derived from `location.port` instead of a
2-entry lookup table (the "never render simulated as live" half was
already fixed by ADR-295's `onVerifiedFrame` gate).
- #1525: the no-model pose path already clamps keypoint confidence to a
0.1 floor, but the renderer's own threshold is also 0.1 compared with
`<=`/`>` — a keypoint at exactly the floor was still invisible. Floor
raised to 0.15 to clear the client's gate.
- #1556: `--mqtt-ca-file`/`--mqtt-client-cert`/`--mqtt-client-key` were
parsed and stored but never applied — TLS always used the system trust
store, so a self-signed broker always failed UnknownIssuer. Now builds
`rumqttc::TlsConfiguration::Simple` from the real PEM files (no new TLS
dependency needed). A file that can't be read logs why and falls back
to system trust instead of failing opaquely later.
- #1555: the MQTT availability heartbeat asserted "online" for every known
node on a fixed 30s timer regardless of whether that node's data was
still arriving. Now tracks each node's last-seen broadcast snapshot and
only reports "online" within a 10s freshness window, otherwise
"offline" — a frozen sensor can no longer look available. (The other
half — restarting a publisher that goes permanently silent — needs a
reproduction the reporter themselves weren't certain of; left for a
follow-up rather than guessing at the trigger.)
- #1540: already fixed on main (node-keyed RateLimiter, ADR-297).
- #1521/#1522: not fixable in this repo (published HF model artifact);
replied with the ADR-298 gate status and the exact byte-level fix for
the safetensors header, and corrected the README row that claimed the
file loads with the reference loader.
- #1542, #1527: replied — #1542 is a real, larger firmware+server feature
left open for follow-up; #1527's suggested fixes were already applied,
the one residual sample is an inherent first-frame paint gap.
## Certificate spine wiring (closes the gap flagged in the PR #1579 review)
`ruview-certify` and `ruview-policy` now depend on `ruview-ood` and provide
real `From<ruview_ood::DomainState>` adapters plus a composed entry point,
`ruview_policy::authorize_from_certificate`, matching the adapter contract
`ruview-policy`'s own doc comment already described but that no code
actually implemented. A new cross-crate integration test
(`acceptance_test_b_real_integration`) mints a real signed
`CapabilityCertificate` and proves a real post-drift `ruview_ood::Unknown`
denies a `SafetyCritical` action through the composed pipeline — not two
disconnected unit tests hand-setting the same enum value.
Also:
- Wires `evaluate_linear_head` (ADR-298 model-release gate) into a new CI
job so the checker itself can't silently regress; documents that gating
an actual model publish is still a manual step (no HF automation here).
- Wires `SourceState::export_watermark()` into `start_recording`: a
recording captured while the source is synthetic is now stamped in its
metadata (not the filename or per-line JSON, to avoid breaking
`delete_recording`'s path reconstruction or the training dataset
loader's schema).
- Updates docs/user-guide.md's "Developer Preview" section to describe
what's now genuinely wired vs. still not (no live continuous
calibration/OOD loop in the running server yet).
## Validation
- cargo test --workspace --no-default-features: 4391 passed, 0 failed
- cargo build --release -p wifi-densepose-sensing-server --features mqtt:
clean
- Server smoke-tested end-to-end against the simulator (real startup,
UDP/WS/HTTP listeners, /api/v1/sensing/latest stable across calls)
- Real ESP32-S3 hardware was NOT reachable this session (no COM port
present, zero UDP frames received after 40s bound to 0.0.0.0:5005) —
the multi-node fixes are validated by the new unit/integration tests
and full-workspace regression, not by live hardware.
Co-Authored-By: claude-flow <ruv@ruv.net>
Documents the 9 new spine crates (calibrate -> certify -> govern) as a
composable library, explicit about current status: each crate is tested in
isolation but not yet wired together or into the live sensing-server
request path (DomainState is 3 separate enum types across
ruview-ood/certify/policy with no automatic bridge). Contrasts against the
two ADR-292-296 remediation items that ARE genuinely enforced today: UDP
source allowlisting (checked on every packet) and the CSI data-policy CI
guard.
The higher-ceiling primitives on the fused world state. Six crates, all
deterministic SYNTHETIC/L0 model scaffolds (a twin predicts, it never measures);
70 tests + 6 doctests, verified green independently.
ruview-twin (ADR-312): per-deployment RF twin — radio geometry, a documented
synthetic log-distance + wall-attenuation propagation model, per-link expected
distributions, and the load-bearing delta(observed,expected) that localizes a
physical change (moved node / new reflector) to specific links. 8 tests.
ruview-infogain (ADR-311): Value(sensor) = expected uncertainty reduction /
weighted cost; pure bounded-greedy selection under a multi-dimension budget;
unknown-value candidates handled explicitly (defer/probe, never silent zero). 15.
ruview-active (ADR-306): closed-loop control vocabulary (channel/bandwidth/
cadence/antenna as validated ranges); step() proposes the next measurement to
reduce uncertainty, widening exploration when the last response is UNKNOWN;
emits a plan, never RF. 13.
ruview-placement (ADR-305): floorplan + inventory -> ranked placement via the
twin's propagation model; blind-spot flags; predicted-vs-observed adjustment. 11.
ruview-memory (ADR-309): learns per-zone normal physics; anomalies are
significant deltas vs baseline emitted as evidence records; UNKNOWN before a
baseline exists (no false positives). 14.
ruview-counterfactual (ADR-310): scores hypotheses under the twin — empty-room
vs occupied, one person vs two; UNKNOWN when indistinguishable. 8.
Flips ADR-305/306/309/310/311/312 to implemented. Completes all three phases of
the ADR-297 perception-substrate program. No hardware/MEASURED claims.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
The layer that turns the certificate spine into a modality-agnostic perception
substrate. Four crates, all deterministic and green independently (43 tests).
ruview-hal (ADR-317): one abstraction mapping any modality (CSI/802.11bf/BLE/
UWB/mmWave/acoustic/camera/lidar/IMU/custom) to a canonical ontology Observation.
SensorHal trait + two SYNTHETIC/L0 reference adapters; malformed input yields a
degraded UNKNOWN observation, never a panic; synthetic can never alias measured.
8 tests.
ruview-groundtruth (ADR-300): reference sensors as a formal VALIDATION plane
(never an estimator input, enforced by the type boundary); modality-agnostic
ReferenceSeries, deterministic cross-correlation alignment, AgreementReport with
mandatory SessionScope, emitting per-context ruview-evidence records; Measured
requires reference + coverage + reproducer. 15 tests.
ruview-track (ADR-304): privacy-preserving persistent tracks (opaque person ids,
coarse non-reversible features, no civil-identity binding); ambiguous detections
stay tentative rather than misassigned; cross-zone hand-off. 8 tests.
ruview-fusion (ADR-308): multiple HalObservations -> one probabilistic WorldState,
uncertainty-aware (confidence-weighted, not naive averaging); irreconcilable
conflict or insufficient coverage yields UNKNOWN, not a confident average.
9+ tests incl. irreconcilable_conflict_yields_unknown.
Flips ADR-300/304/308/317 to implemented; registers the four crates as workspace
members. SYNTHETIC/L0 throughout; no hardware/MEASURED claims.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
Completes the phase-1 certificate spine; both acceptance tests now pass as code.
ruview-ood (ADR-299): domain-distance vs the certified fingerprint and a pure
DomainState KNOWN/DEGRADED/UNKNOWN classifier implementing the ADR-297
VALID->DEGRADED->UNKNOWN staleness guard; InferenceGate suppresses the class
(UNKNOWN as a first-class value) when domain is not KNOWN; RecalibrationRequest
signalled on DEGRADED/UNKNOWN. 25 tests.
ruview-witness (ADR-316): ordered, append-only, BLAKE3 hash-linked stage chain
(observation->DSP->inference->corroboration->spatial->policy) rooted in an
attest VerifiedMeasurement; verify() catches mutation/reorder/dropped/broken
links; effective level is the minimum across stages. 19 tests.
ruview-certify (ADR-315): signed CapabilityCertificate minted from a single-
context evidence slice (never pooled), evidence level capped at the slice floor,
valid_until bounded by calibration validity; is_valid(now, domain) returns false
when expired OR domain != KNOWN (certificate conditional on the live domain
signature). 17 tests incl. non_known_domain_invalidates.
ruview-scorecard (ADR-314): multi-domain scorecard with per-domain CIs,
worst_domain(), and a promotion gate that fails when only pooled average
improved while a worst-domain slice regressed. 17 tests.
ruview-policy (ADR-318): fail-closed action gate; Convenience/Security/
SafetyCritical assurance classes; authorize() denies with a named failed
condition; UNKNOWN denies high-assurance actions. Includes
acceptance_test_b_post_drift_unknown_denies_safety_critical. 10 tests.
All five verified green independently (88 tests). Registers the five crates as
workspace members. SYNTHETIC/L0 reference crypto; no hardware claims.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
Four foundational perception-substrate crates (dependency roots of the
certificate spine), each pure/leaf and deterministically tested:
ruview-ontology (ADR-303): canonical Site>Building>Floor>Space>Zone +
Sensor/Person/Object/Observation/Track/Event, typed serde-transparent ids,
WorldGraph registry with dangling-parent/duplicate rejection and containment
resolution, EvidenceLevel L0-L5, and a docs-only migration table for the
per-surface shapes. 8 tests + doctest.
ruview-attest (ADR-302): DeviceId + SignedMeasurement envelope binding
{device, monotonic sequence, timestamp, payload hash, calibration ref};
AttestationVerifier enforces unknown-device, signature, tamper, strict
per-device sequence (replay), and freshness; Signer/Verifier traits with a
blake3-keyed SYNTHETIC-grade reference MAC (Ed25519 is a drop-in). 14 tests.
ruview-evidence (ADR-301): append-only per-(room,device,subject,model) ledger;
immutable records with provenance-gated constructors (synthetic forces L0,
measured needs a reproducer); summarize() never pools across contexts; a slice
reports the floor evidence level, never above its weakest record. 8 tests.
wifi-densepose-calibration (ADR-298): CalibrationCertificate — signed, versioned
room fingerprint minted from existing calibration/bank state, compare/drift, and
invalidate-on-drift/expiry. 78 tests green.
Registers the three new crates as workspace members. All four verified green
independently. SYNTHETIC/L0 reference crypto; no hardware claims.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
ADR-292 (sensing-server): SourceState enum + pure transition (provenance.rs);
auth-error/unknown can never resolve to LiveVerified; synthetic exports
watermarked. Pose-fusion simulator starts SYNTHETIC and only shows LIVE on a
real decoded frame (#1557); sensing client no longer labels an unauthorized
status endpoint as live (#1526).
ADR-294 (sensing-server): NodeInference distinct from RoomInference (inference.rs);
deterministic freshness-weighted fuse_room; RateLimiter re-keyed to
(NodeId,EntityKind) so nodes do not starve each other (#1541); stale nodes go
unavailable not frozen-online (#1555).
ADR-293 (sensing-server): --udp-bind (default 127.0.0.1) + --udp-allow allowlist
+ fail-closed refusal of routable bind without allowlist unless --udp-insecure-lan
(udp_bind.rs); crate SECURITY.md documents the threat model and the deferred
per-device-auth step two.
ADR-295 (train): model_gates.rs — constant-output, unreachable-boundary (the
issue-1521 degenerate presence head), class-balance, baseline, and
metric-name-provenance gates.
ADR-296 (ci): scripts/csi-data-policy-check.sh (+ allowlist) and a workflow that
fails on tracked CSI-format/oversized-JSONL files; 6/6 self-tests pass.
Per-crate suites reported green by the swarm; CSI policy self-test 6/6 and JS
syntax verified here. Full workspace re-verification deferred until the
concurrent phase-1 spine build frees the target dir (disk pressure).
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
Elevates decision policy (action authorization) into phase 1 (ADR-318): a
fail-closed gate that authorizes a governed action only when the capability
certificate class, freshness, uncertainty ceiling, evidence floor, and live
domain state (KNOWN, not DEGRADED/UNKNOWN) all satisfy the action class —
convenience vs security vs safety-critical. UNKNOWN denies high-assurance
actions; every decision is the terminal witness-chain stage.
Amends ADR-297 with: the epistemic-reliability pipeline as the product thesis;
four non-negotiable rules (UNKNOWN first-class; certificates bind
cryptographically; one canonical downstream semantics; benchmarks expose
worst-domain + CIs); the certificate-staleness guard (certificates conditional
on a continuously evaluated domain signature; VALID->DEGRADED->UNKNOWN
auto-degrade triggers recalibration); the three-primitive commercial framing
(Runtime / Certify / Trust-Fleet); and acceptance test B (drift invalidation
before a false inference reaches an actuator).
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
Frames the calibration/evidence/trust/deployment layer as a 20-primitive
phased program with a dependency DAG and phase assignments. Phase 1 is the
certificate spine (spatial ontology, authenticated identity, witness chain,
calibration cert, OOD gating, evidence engine, capability certificate,
multi-domain benchmark scorecard) — the acceptance test decomposed and
buildable without new hardware. Phase 2/3 are integration and research-forward
primitives. Child ADRs 298-317 follow.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS