docs: ADR-298..317 — 20 child ADRs of the perception-substrate program

Phase 1 (certificate spine, initial implementation planned): ADR-298 calibration
certificate, ADR-299 OOD KNOWN/DEGRADED/UNKNOWN gating, ADR-301 evidence engine,
ADR-302 authenticated sensor identity, ADR-303 canonical spatial ontology,
ADR-314 multi-domain benchmark scorecard, ADR-315 capability certificates,
ADR-316 witness chain.
Phase 2 (Proposed): ADR-300 ground truth, ADR-304 tracking, ADR-307 802.11bf-native,
ADR-308 fusion, ADR-313 fleet, ADR-317 HAL.
Phase 3 (Proposed): ADR-305 placement, ADR-306 active sensing, ADR-309 spatial
memory, ADR-310 counterfactual, ADR-311 info-gain, ADR-312 RF twin.

Each references ADR-297 and cross-references its dependencies; phase-1 ADRs carry
implementation intent, phase-2/3 are design-intent Proposed.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
This commit is contained in:
Claude
2026-08-11 00:30:00 +00:00
parent ca1f0b9e8a
commit 559ad56aa4
21 changed files with 2862 additions and 0 deletions
@@ -0,0 +1,149 @@
# ADR-298: Automatic domain calibration — signed, versioned, invalidatable room fingerprint
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: calibration, provenance, drift, evidence, honesty, substrate
## Context
This ADR is primitive 1 of the perception-substrate program (ADR-297) and the
first brick of that program's "certificate spine" (ADR-297 phase 1). It depends
on the canonical spatial ontology (ADR-303) to name *which space* it
characterizes, on authenticated sensor identity (ADR-302) to bind a fingerprint
to *which signed device* produced it, and on the witness chain (ADR-316) to
anchor the resulting artifact. Its output is consumed directly by
out-of-distribution detection (ADR-299).
WiFi sensing is only reproducible inside the environment it was tuned for.
Multipath, furniture geometry, transceiver placement, and AP channel all shape
the CSI distribution, so a model that reads a room correctly one week can drift
silently the next. RuView already has the raw ingredients for room-aware
sensing but not a single portable, signed, expiring artifact that says "this is
the room, here is when it was measured, and here is the evidence that it is
still the same room."
Existing scaffolding to build on, not rebuild (`v2/crates/wifi-densepose-calibration`):
- `enrollment` / `anchor` — guided human anchors with an adaptive quality gate.
- `bank` / `specialist` / `runtime` — a versioned bank of small specialist
models and a confidence-gated mixture runtime (`RoomState`), including the
crate's existing honest `STALE` degradation when the ADR-135 empty-room
baseline drifts.
- `geometry` / `geometry_embedding` — transceiver-geometry record and its
fixed-length conditioning featurization (ADR-152).
What is missing is (a) an *automatic* observe-only characterization phase that
does not require a human enrollment ritual, (b) empty-vs-occupied baseline
separation as a first-class pair, (c) a signed, versioned, comparable
`CalibrationCertificate` artifact, and (d) explicit invalidation on drift rather
than a soft `STALE` flag buried in the runtime.
## Options considered
1. **Keep calibration internal to the runtime (status quo).** Rejected: the
room characterization exists only as in-process state; it cannot be signed,
shipped, compared across time, or presented as evidence to ADR-299/ADR-315.
2. **Build a new calibration crate.** Rejected: `wifi-densepose-calibration`
already owns enrollment, the specialist bank, geometry embedding, and the
baseline-drift concept. A parallel crate would fork the room model.
3. **Extend `wifi-densepose-calibration` with an automatic characterization
phase and a signed certificate artifact.** Chosen.
## Decision
Extend `v2/crates/wifi-densepose-calibration` with an `autocal` characterization
phase and a `certificate` artifact module. The target UX is:
> install → observe (~10 min) → room fingerprint → calibration certificate →
> sensing.
### 1. Automatic characterization (`autocal`)
- An observe-only pass (default ~10 minutes, configurable) that collects CSI
without requiring guided human anchors, reusing the `anchor` quality gate to
reject frames it cannot trust. It layers on the existing ADR-135 empty-room
baseline rather than replacing it.
- Produces a `RoomFingerprint`: a bounded, fixed-length statistical summary of
the room's CSI distribution (subcarrier amplitude/phase moments, multipath
structure, occupancy-band energy), plus the `geometry_embedding` when a
geometry record is present. The fingerprint is the distance-comparable object
ADR-299 measures against; its schema is versioned.
### 2. Empty / occupied baseline pair
- Characterization establishes a paired baseline: an **empty** distribution
(no occupant motion) and an **occupied** distribution (motion present),
separated by the existing occupancy signal rather than a manual label. Both
are stored on the fingerprint so downstream OOD gating can distinguish "the
empty room changed" (furniture/geometry drift) from "occupancy statistics
changed" (different subject dynamics).
### 3. `CalibrationCertificate` artifact
- A serializable `CalibrationCertificate` binding: the `RoomFingerprint`; a
space identifier from the ADR-303 ontology; the signing sensor identity from
ADR-302; `captured_at_unix_s`; a monotonic `version`; a schema version; the
calibration `tier`; and an `EvidenceLevel` (L0L5, ADR-282) — an automatic
characterization on real captured CSI is at most L1/L2 and is labelled as
such, never L3+.
- The certificate is **signed** using RuField provenance/signature types
(ADR-260/262/277/279) and anchored in the witness chain (ADR-316). Signature
and witness anchoring are mandatory: an unsigned certificate is not a valid
certificate.
- Two certificates for the same space are **comparable**: `distance(a, b)`
returns a bounded fingerprint distance, which is the primitive ADR-299 uses
to gate KNOWN → DEGRADED → UNKNOWN.
### 4. Invalidation and continuous drift compensation
- A certificate carries an explicit validity policy: it is invalidated when
fingerprint distance against live traffic exceeds a threshold, when the AP
channel or transceiver geometry changes, when the signing device identity
changes, or on age expiry. Invalidation is an explicit state transition that
emits a witness record (ADR-316), not a silent `STALE` flag.
- Continuous drift compensation runs as a bounded online update of the
fingerprint within a **compatibility envelope**: small drift is absorbed and
logged; drift beyond the envelope invalidates the certificate and forces
re-characterization. Compensation never silently rewrites a signed
certificate — it produces a new version, preserving the append-only history.
### Provenance and honesty discipline
- No accuracy number is claimed by this ADR; it delivers the artifact and the
distance/invalidation machinery. Any certificate produced from generated CSI
is L0/`Synthetic` by construction; the constructor rejects labelling
synthetic characterization as measured (ADR-279 invariant 6, ADR-282 ladder).
- Certificates never leave the edge except through the governed control plane
(ADR-277); a room fingerprint is treated as potentially sensitive spatial
data, not free telemetry.
## Consequences
- Room characterization becomes a portable, signed, versioned artifact that
ADR-299 (OOD), ADR-315 (capability certificates), and ADR-314 (benchmark)
can consume without re-deriving room state.
- The automatic observe-only path lowers deployment friction (no mandatory
enrollment ritual) but yields a weaker evidence level than guided enrollment;
the certificate states which path produced it so consumers can weight it.
- Explicit invalidation means RuView will sometimes refuse to sense a changed
room until re-characterization. That refusal is the intended honest behavior,
surfaced by ADR-299, not a regression.
- The existing enrollment/bank/runtime path is preserved; `autocal` is an
additional entry point that produces the same `RoomFingerprint` object the
guided path can also emit.
## Validation
- `cargo test -p wifi-densepose-calibration` — fingerprint determinism from
fixed synthetic CSI; empty/occupied separation on synthetic occupancy;
certificate signing/verification round-trip and tamper rejection;
`distance()` monotonicity on progressively perturbed fixtures; invalidation
transitions (channel change, geometry change, age, drift-envelope breach)
each emit the expected witness record; constructor rejects synthetic→measured
mislabeling.
- Cross-ADR: an ADR-299 test consumes a certificate and asserts the gating
state transitions on a drifted fingerprint.
- Real-silicon characterization (ESP32 capture over a real 10-minute window)
remains a follow-up requiring hardware evidence per CLAUDE.md; a successful
build or synthetic run is not hardware evidence.
@@ -0,0 +1,135 @@
# ADR-299: Out-of-distribution detection — KNOWN / DEGRADED / UNKNOWN gating
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: ood, calibration, uncertainty, quality, evidence, honesty, substrate
## Context
This ADR is primitive 2 of the perception-substrate program (ADR-297) and part
of the phase-1 certificate spine. It sits directly downstream of automatic
domain calibration (ADR-298): the `CalibrationCertificate` and its
`RoomFingerprint` are the reference distribution this ADR measures against. It
reuses fusion-layer quality scoring (ADR-137) as one of its inputs and feeds
its state into the evidence engine (ADR-301) and capability certificates
(ADR-315).
The central unsolved problem of WiFi sensing is cross-domain generalization: a
model trained (or calibrated) in one room degrades unpredictably in another, or
in the same room after furniture moves, the AP changes channel, or the radio
hardware is swapped. A model that keeps returning confident classifications
under these conditions is the single most misleading failure mode in the field,
and it is the failure the strategic assessment (ADR-297) named explicitly.
Confidence alone is insufficient: a softmax head is perfectly capable of being
confidently wrong on out-of-distribution input. RuView must be able to say
"I do not recognize this situation" instead of guessing.
Today RuView has partial signals but no unified gate:
- ADR-298 produces a comparable `RoomFingerprint` and a `distance()` metric.
- ADR-137 `QualityScore` carries fusion coherence, evidence references, and
contradiction flags per fused frame.
- Model heads emit confidence/uncertainty, but nothing combines domain
distance, signal quality, calibration compatibility, and uncertainty into a
single decision, and nothing forces a model to stop emitting confident labels
when it leaves its calibrated domain.
## Options considered
1. **Threshold on model confidence alone.** Rejected: confidently-wrong OOD
predictions are exactly the failure mode; confidence is necessary but not
sufficient.
2. **A per-model bespoke OOD check inside each task head.** Rejected:
duplicates logic, cannot be audited uniformly, and does not compose with the
calibration certificate or the evidence engine.
3. **A shared OOD gate that every inference passes through, fusing four signals
against the ADR-298 certificate.** Chosen.
## Decision
Add an out-of-distribution gate — implemented in a shared crate consumed by the
task-head runtime (`wifi-densepose-calibration::runtime` and the model serving
path) — that attaches a `DomainState` to **every** inference.
### 1. Four inputs, one decision
Each inference carries four measured quantities:
1. **Domain distance** — fingerprint distance (ADR-298 `distance()`) between
live traffic and the active `CalibrationCertificate`, split into the
empty-baseline and occupied-baseline components so geometry drift and
occupancy-statistics drift are distinguishable.
2. **Signal quality** — reuse the ADR-137 quality scoring signals (fusion
coherence, contradiction flags) plus per-frame SNR/validity.
3. **Calibration compatibility** — is a valid, non-invalidated certificate
present for this space (ADR-303) and this signed device (ADR-302)? An
expired, invalidated, or device-mismatched certificate is itself a
compatibility failure.
4. **Uncertainty** — the model head's own predictive uncertainty.
### 2. State machine: KNOWN → DEGRADED → UNKNOWN
- **KNOWN** — domain distance within the certificate's compatibility envelope,
quality above threshold, certificate valid and compatible, uncertainty low.
Confident classifications are returned.
- **DEGRADED** — one or more signals crossed a soft threshold (e.g. moderate
fingerprint drift within the envelope, elevated uncertainty, a tolerated
ADR-137 contradiction flag). Classifications are returned but flagged
degraded with the specific reason; downstream consumers must treat them as
lower-evidence.
- **UNKNOWN** — the room changed materially (empty-baseline drift beyond the
envelope, AP channel change, transceiver-geometry change, hardware/device
change, or an invalidated/absent certificate). RuView **stops returning
confident classifications** and returns UNKNOWN with the triggering cause.
This is the required behavior, not an error.
State transitions are hysteretic (separate enter/exit thresholds) so the gate
does not flap on noise. The state, the four input values, and the triggering
cause are all reported — never a bare label.
### 3. Certificate-bound, honest by construction
- The gate is meaningless without a certificate: with no valid ADR-298
certificate for the current space/device, the default state is UNKNOWN, not
KNOWN. Absence of evidence is treated as absence of capability.
- The `DomainState` and its inputs are emitted to the evidence engine
(ADR-301) as part of every inference record, and are an input to the ADR-315
capability certificate (a model's capability is bounded by the domain it can
hold KNOWN in).
- No accuracy number is claimed here; the ADR delivers the gating machinery.
The gate's own thresholds are calibration parameters, reported with each
decision.
## Consequences
- RuView gains a uniform, auditable answer to "should I trust this inference?"
that combines domain, quality, calibration, and uncertainty rather than
confidence alone.
- Deployments will see more DEGRADED/UNKNOWN results than a
confidence-only system, especially right after a room changes. That increase
is the product working: it is the difference between honest RF perception and
confidently-wrong output.
- Every task head that opts into the substrate must route through the gate;
heads that bypass it cannot claim a KNOWN state or earn an ADR-315
certificate.
- The gate couples model serving to the presence of a live calibration
certificate, making ADR-298 a hard dependency of confident inference — the
intended coupling.
## Validation
- `cargo test` on the OOD crate — state-machine transitions on synthetic
fixtures: in-envelope drift stays KNOWN; soft-threshold breach → DEGRADED;
empty-baseline drift beyond envelope, channel change, geometry change,
device mismatch, and invalidated/absent certificate each → UNKNOWN;
hysteresis prevents flapping under injected noise; missing certificate
defaults to UNKNOWN.
- Cross-ADR: consumes an ADR-298 certificate and asserts a drifted fingerprint
drives the expected transition; asserts the `DomainState` is present on every
emitted inference record consumed by ADR-301.
- No confident classification is emitted in the UNKNOWN state in any test —
enforced as an assertion, not a convention.
- Real-silicon OOD behavior (moving furniture / changing AP channel on a live
ESP32 capture and observing the transition) remains a follow-up requiring
hardware evidence per CLAUDE.md.
@@ -0,0 +1,125 @@
# ADR-300: Ground-truth synchronization — reference sensors as a formal validation plane
- **Status**: Proposed (ADR-297 phase 2)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: ground-truth, validation, fusion, evidence, benchmark, honesty, substrate
## Context
This ADR is primitive 3 of the perception-substrate program (ADR-297), authored
as **Proposed** in phase 2: it is design intent and a validation plan, not
implemented by the phase-1 swarm. It sits on top of the phase-1 certificate
spine and feeds the evidence engine (ADR-301) and the real benchmark service
(ADR-314). It generalizes the vitals ground-truth rig (ADR-290) from a single
measurand to a modality-agnostic plane.
RuView's evidence discipline (CLAUDE.md; ADR-282 ladder) requires MEASURED
accuracy claims to be backed by an independent reference. ADR-290 built exactly
this for vitals: reference-series ingest, time alignment (cross-correlation
lag + optional clock-drift fit), and agreement statistics (MAE/RMSE/bias/
BlandAltman/within-tolerance), with an `EvidenceGrade` that is only
constructible as `Measured` when a real reference, non-zero paired samples,
minimum coverage, and a reproducer are present. That machinery is measurand- and
device-shaped: it knows about heart rate and breathing rate.
The substrate needs the same discipline for *every* phenomenon RuView senses —
presence, count, localization, pose, posture, activity — and for reference
sources of many modalities (cameras, mmWave, pressure mats, wearables, pulse
oximeters, microphones, manual labels). The critical design decision is that
these reference sensors form a **validation plane**, not additional inference
inputs.
## Options considered
1. **Fuse reference sensors as extra inference inputs.** Rejected on principle:
folding cameras/mmWave into the estimator would make RuView's RF claims
unfalsifiable — the reference would be training the thing it is meant to
check, and a camera-fed result is no longer a camera-free RF result. It
would also violate the ADR-282 layering (RuView is probabilistic
exteroception, never ground truth) and the honesty rule against presenting
fused-with-camera output as WiFi sensing.
2. **One-off rigs per measurand (extend ADR-290 ad hoc each time).** Rejected:
duplicates alignment/agreement code per phenomenon and never yields a shared
validation surface for the benchmark.
3. **A first-class, modality-agnostic `GroundTruth` API that is strictly a
validation plane.** Chosen.
## Decision
Introduce a `GroundTruth` API — a modality-agnostic validation plane that
compares RF inference against independent observation and never feeds it.
### 1. Modality-agnostic reference ingest
- A `ReferenceObservation` generalizing ADR-290's `ReferenceSeries`: a
timestamped, typed observation of a `Phenomenon` (presence, count,
localization, pose keypoints, posture, activity, heart rate, breathing rate)
from a `ReferenceModality` (camera, mmWave, pressure, wearable, pulse
oximeter, microphone, manual label), with device/source metadata and the
measurement principle recorded.
- Untrusted reference files are validated at the boundary (row-numbered
rejections, non-monotonic timestamps are errors), reusing ADR-290's ingest
discipline. Camera/mmWave references arrive as exported label/keypoint
streams, not live model feeds.
### 2. Synchronization
- Generalize ADR-290's time alignment (bounded-lag normalized cross-correlation
+ optional linear clock-drift fit) to arbitrary measurands on a common
resampled grid, with no interpolation across gaps beyond a configurable
limit. Alignment parameters are always reported, never silently applied.
- Spatial synchronization where relevant: reference observations are expressed
in the ADR-303 spatial ontology so an RF localization/pose result and a
camera/mmWave observation are compared in one coordinate frame.
### 3. Agreement as validation, not fusion
- A modality-appropriate `AgreementReport` per phenomenon: continuous
measurands reuse ADR-290's MAE/RMSE/bias/BlandAltman/within-tolerance;
categorical/detection phenomena (presence, activity) report confusion-matrix
metrics; spatial phenomena report localization error percentiles and pose
PCK **with the mandatory mean-pose baseline and leakage-free split**
(CLAUDE.md; ADR-288).
- Session scope is mandatory metadata (subject count, motion state, LOS/NLOS/
through-wall, distance band) — a report without scope cannot be constructed,
as in ADR-290.
### 4. Evidence and isolation guarantees
- The plane is one-directional by type: the inference path has no read access
to `GroundTruth` at runtime. A build/test-time isolation check (and the type
boundary) prevents a reference observation from becoming an estimator input.
- Reports carry an `EvidenceLevel` (ADR-282) and an `EvidenceGrade`
constructible as `Measured` only with a real reference, paired samples,
coverage, and a reproducer (ADR-290 rule). Reports feed the ADR-301 evidence
engine and are the substrate ADR-314 scores against.
## Consequences
- Every phenomenon RuView senses gets the same MEASURED-vs-independent-observer
discipline vitals already has, in one shared surface.
- Keeping references strictly as validation preserves the falsifiability and
the camera-free identity of RF results; it costs the (tempting) accuracy a
camera-fused estimator would show, which is the correct trade.
- Reference capture is an operational burden (a camera/mmWave rig per validated
session); acceptable because it is a validation activity, not a runtime
requirement, and it is what turns CLAIMED into MEASURED.
- Because this is Proposed (phase 2), the API shape may be revised once the
phase-1 spine (ADR-298/299/301/303) lands and the benchmark (ADR-314)
exercises it.
## Validation
- Unit tests (planned): modality-agnostic ingest rejection cases; alignment
recovery of known synthetic offsets/drifts across measurands; agreement math
per phenomenon against hand-computed fixtures; pose PCK path requires a
mean-pose baseline and rejects leaky splits; evidence-grade constructibility;
the isolation check fails a build that wires a reference into the inference
path.
- Cross-ADR: an ADR-314 benchmark scenario consumes `GroundTruth` reports as
its scored reference; ADR-301 ingests the agreement reports as evidence
records.
- Real-session validation (RF capture synchronized with a real camera/mmWave/
pressure/wearable reference) is the phase-2 exit and requires hardware
evidence per CLAUDE.md; a synthetic run is not hardware evidence.
+117
View File
@@ -0,0 +1,117 @@
# ADR-301: Evidence engine — MLflow for physical sensing
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: evidence, provenance, ledger, accuracy, drift, benchmark, honesty, substrate
## Context
This ADR is primitive 4 of the perception-substrate program (ADR-297) and a
central pillar of the phase-1 certificate spine. It consumes the domain state
from out-of-distribution detection (ADR-299) and the calibration age from the
calibration certificate (ADR-298), it is the store that capability certificates
(ADR-315) are minted from, and it is the accuracy source the real benchmark
service (ADR-314) reads. In phase 2 it ingests agreement reports from the
ground-truth plane (ADR-300).
The strategic assessment (ADR-297) judged this primitive **more commercially
important than another pose architecture**: what unblocks OEM and integrator
conversations is not a higher headline number but a defensible, auditable record
of how a model actually performs, per room, per device, per subject, over time.
MLflow made ML experiments trackable; physical sensing needs the equivalent for
deployed accuracy, drift, and evidence level — an append-only ledger, not a
dashboard that overwrites yesterday's number.
RuView already has the constituent evidence types; what is missing is the ledger
that unifies them per deployment context:
- RuField provenance/signature types (ADR-260/262/277/279) — the signed,
provenance-bearing record types to reuse rather than reinvent.
- The AetherArena witness-ledger pattern (ADR-149) — an append-only,
witness-anchored ledger of scored results, the structural template here.
- `frame::EvidenceLevel` L0L5 (ADR-282) — the mandatory evidence tag every
record carries.
- ADR-299 `DomainState`, ADR-137 `QualityScore`, ADR-298 certificate version
and age — the per-inference signals to accumulate.
## Options considered
1. **Log accuracy to flat files / metrics dashboards.** Rejected: mutable,
un-signed, un-scoped, and not comparable over time — the exact gap.
2. **Reuse a general experiment tracker (MLflow itself).** Rejected: it is
experiment-time, not deployment-time; it has no notion of room/device/
subject context, calibration age, evidence level, or signed provenance, and
it would add an external service dependency contrary to the substrate's
edge-first, dependency-light direction.
3. **A native append-only evidence ledger reusing RuField record types and the
AetherArena ledger pattern.** Chosen.
## Decision
Build an **evidence engine**: a per-`(room, device, subject)` append-only
accuracy ledger that every model automatically writes to.
### 1. The evidence record
- An `EvidenceRecord` keyed by context — space id (ADR-303), signed device id
(ADR-302), and subject id where consented and available — carrying: model
version; calibration certificate version and **age** (ADR-298); the ADR-299
`DomainState` (KNOWN/DEGRADED/UNKNOWN) and its four inputs; the ADR-137
quality signals; predictive uncertainty; and, when a reference is present
(ADR-300), the agreement result (accuracy, false-positive rate). Each record
carries exactly one `EvidenceLevel` (L0L5, ADR-282).
- Records are **append-only** and signed with RuField signature types
(ADR-260/262/277/279); the ledger is anchored in the witness chain (ADR-316),
following the AetherArena witness-ledger pattern (ADR-149). No record is ever
mutated in place — a correction is a new record.
### 2. Per-context accuracy accounting
- The engine maintains, per `(room, device, subject)` context: measured
accuracy (only where an ADR-300 reference backs it — otherwise the record is
CLAIMED/SYNTHETIC, never MEASURED), false-positive rate, drift trajectory
(fingerprint distance over time from ADR-298), the fraction of inferences in
each domain state, calibration age distribution, and model-version history.
- Aggregation is a pure function over the append-only log at a queried time —
the ledger is the source of truth; summaries are derived, never authoritative
(mirroring CLAUDE.md's "source over summaries" rule).
### 3. Honesty enforced in the record
- The engine cannot upgrade an evidence level; a level is set by the record's
provenance at write time (synthetic input → L0/`Synthetic`; no reference →
CLAIMED; reference + reproducer → MEASURED), reusing the ADR-282/ADR-288/
ADR-290 constructor discipline. A benchmark or certificate reading the ledger
gets the honest level, not an optimistic rollup.
- No benchmark numbers are invented by this ADR; it delivers the ledger and the
accounting. Empty contexts report "no evidence," which downstream (ADR-315)
must treat as no capability.
## Consequences
- RuView gains a single auditable answer to "how well does this model actually
work, here, on this device, for this subject, and how fresh is the
calibration?" — the artifact OEM/integrator diligence actually asks for.
- ADR-315 capability certificates become derivable (a certificate is a signed
attestation over a slice of the ledger) and ADR-314 gains a real accuracy
source per PR instead of self-reported numbers.
- The append-only, signed design has storage and key-management cost; bounded
by per-context retention policy and by reusing the existing RuField/witness
infrastructure rather than a new store.
- Some contexts will show sparse or unflattering evidence. Surfacing that is the
point; the engine must never paper over a thin context with a global average.
## Validation
- `cargo test` on the evidence-engine crate — append-only invariant (no
in-place mutation; corrections are new records); per-context aggregation math
against fixtures; evidence-level is set by provenance and cannot be upgraded;
signature round-trip and tamper rejection; witness anchoring; empty-context
queries return "no evidence" not a fabricated number.
- Cross-ADR: ingests ADR-299 `DomainState` and (phase 2) ADR-300 agreement
reports; an ADR-315 test mints a certificate from a ledger slice and an
ADR-314 test reads accuracy from the ledger.
- Real-deployment evidence (a populated ledger from live ESP32 captures with
ADR-300 references) is the maturity milestone and requires hardware evidence
per CLAUDE.md; a synthetic ledger is L0 by construction.
@@ -0,0 +1,147 @@
# ADR-302: Authenticated sensor identity — RF chain of custody
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: security, identity, provenance, sensor-ingest, attestation, phase-1
## Context
This ADR is a child of **ADR-297** (perception substrate program) and owns
primitive #5, *authenticated sensor identity*. In the ADR-297 dependency DAG it
is a spine root that, together with **ADR-303** (canonical spatial ontology),
feeds **ADR-298** (calibration certificate) and **ADR-316** (witness chain).
RuView's inference outputs are only as trustworthy as the measurements that
produced them, yet today a measurement's origin is essentially assertional. The
UDP data plane accepts frames from any reachable host: **ADR-293** shipped step
one — a loopback-default bind (`--udp-bind`) and an optional source
IP/CIDR allowlist — and explicitly deferred to a follow-up ADR "per-device
provisioned keys, MAC/AEAD, device identifiers, monotonic sequence numbers,
freshness window, and replay rejection." **This ADR is that step two.** ADR-293
correctly documented that an IP allowlist does not stop LAN spoofing; a
cryptographic device identity is what closes that gap.
Foundations already exist in the tree and must be reused rather than rebuilt:
- `wifi-densepose-rufield` provides `DeviceId`, `Signature`, `SignatureBlock`,
`FrameProvenance`, `ProvenanceClass`, and `SignatureVerifyError` — the type
vocabulary for a signed frame.
- `wifi-densepose-bfld` provides `CapabilityAttestation` and
`PrivacyAttestationProof` (BFLD attestation, ADR-141) — the device-side
attestation surface.
- **ADR-292** defines the source-provenance state machine and freshness
(`SpatialStateFreshness`); a monotonic sequence and freshness window slot
into that machine rather than duplicating it.
The gap is not new primitives but an **end-to-end chain of custody**: a frame
must be traceable as `device → signed measurement → sequence → timestamp →
calibration → inference → signed event`, with every link verified at the
ingest boundary per CLAUDE.md ("validate untrusted input at every network,
hardware, and FFI boundary; default to least authority").
## Options considered
1. **Stop at ADR-293 (bind + IP allowlist).** Rejected: ADR-293 itself names
this insufficient on a trusted LAN; any on-subnet host can still spoof a
device.
2. **TLS/DTLS transport authentication only.** Rejected: authenticates the
*channel*, not the *measurement*. It does not survive store-and-forward,
does not bind a sequence number into the signed object, and gives the
downstream evidence/witness layers nothing to re-verify offline.
3. **Per-device signing keys with a signed measurement envelope, monotonic
sequence, and freshness window, reusing the RuField/BFLD types.** Chosen.
## Decision
Introduce an **authenticated frame envelope** carried through the sensing
server, built from existing RuField/BFLD types.
### 1. Per-device provisioned identity
- Each radio (ESP32-S3/C6 node or adapter) is provisioned with a keypair; the
device holds the private key, the server holds the enrolled public key bound
to a `DeviceId`. Provisioning is an explicit, authorized enrollment step — a
device is untrusted until an operator enrolls its public key. Private keys are
never logged or committed (CLAUDE.md credential rule); the ESP32 side follows
`firmware/esp32-csi-node` key-handling notes.
- The enrollment record binds `DeviceId → public key → capabilities`
(via `CapabilityAttestation`, ADR-141), so a device can only assert
measurements for phenomena it is attested to sense. This is what **ADR-315**
(capability certificate) later consumes.
### 2. Signed measurement envelope
- A frame on the wire becomes a `SignatureBlock` over the canonical
serialization of `{DeviceId, sequence, timestamp, measurement-hash}`. The
measurement itself (CSI/CIR payload) is covered by the hash so tampering is
detectable without embedding the whole payload twice.
- Verification uses `Signature`/`SignatureVerifyError` from
`wifi-densepose-rufield`. A frame that fails signature verification is
dropped and counted, exactly as ADR-293 drops disallowed sources — an `Err`
at the boundary, never a warning that proceeds.
### 3. Monotonic sequence + freshness (replay defense)
- Each device maintains a strictly monotonic per-device sequence number. The
server tracks the last accepted sequence per `DeviceId`; a non-increasing
sequence is rejected as a replay.
- A freshness window bounds `timestamp` against the server clock skew budget;
stale frames are rejected. This reuses ADR-292's `SpatialStateFreshness`
rather than inventing a parallel notion of staleness, and composes with
ADR-294's stale-node handling.
### 4. Chain of custody into the event
- On successful verification the frame's `FrameProvenance` records the verified
`DeviceId`, sequence, and timestamp. Calibration (ADR-298) and inference
annotate their transforms, and the emitted spatial event (ADR-303 ontology)
carries a signed provenance lineage. `ProvenanceClass` still enforces the
synthetic/measured invariant from ADR-282/ADR-279 (invariant 6): a measured
chain of custody can never be aliased to synthetic and vice-versa.
- This end-to-end signed lineage is the substrate the **ADR-316** witness chain
serializes and the **ADR-315** capability certificate points at as evidence.
### Compatibility
- The envelope is **opt-in per deployment** and negotiated at enrollment. An
un-enrolled single-node desktop deployment keeps working unauthenticated
behind ADR-293's loopback default; a routable, multi-node, or fleet
deployment (ADR-313) requires enrolled identities. The startup security log
(ADR-293) is extended to state whether frame authentication is active.
## Consequences
- LAN spoofing and replay — the residual risks ADR-293 named plainly — are
closed for enrolled deployments. The measurement, not merely the channel, is
authenticated, so the guarantee survives store-and-forward into the witness
chain.
- Enrollment/key-management is now an operational responsibility (provisioning,
rotation, revocation). This is documented as a deployment step; key rotation
and revocation lists are specified here but their fleet distribution is
owned by ADR-313.
- Signature verification adds per-frame CPU cost at ingest; bounded and
measured in validation below. It is a deliberate cost for a verifiable chain
of custody.
- A schema addition to the frame contract; un-enrolled deployments are
unaffected, and the migration accessor mirrors ADR-294's approach.
- **No spoof-resistance claim is MEASURED until validated on real silicon**
(CLAUDE.md hardware rule): a passing unit/integration suite demonstrates the
logic, not the fielded device path.
## Validation
- Unit tests (`cargo test -p wifi-densepose-sensing-server`,
`-p wifi-densepose-rufield`): valid envelope accepted; bad signature
rejected and counted; non-monotonic sequence rejected as replay; out-of-
window timestamp rejected; un-enrolled `DeviceId` rejected; measured/synthetic
provenance aliasing rejected (ADR-279 invariant 6).
- Integration test: a captured/synthesized multi-frame stream produces a
verifiable `device → … → signed event` lineage that ADR-316 can serialize and
re-verify offline.
- Benchmark (`cargo bench`): per-frame verification cost, to bound ingest
overhead.
- **Real-silicon evidence required** before any deployment-grade
authentication claim: a captured boot/runtime log from an enrolled ESP32 node
signing frames end-to-end. A successful build or simulator run is not
hardware evidence.
@@ -0,0 +1,142 @@
# ADR-303: Canonical spatial ontology — one Site→…→Event model for every surface
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: ontology, worldgraph, schema, mqtt, matter, rufield, phase-1
## Context
This ADR is a child of **ADR-297** and owns primitive #6, *canonical spatial
ontology*. In the ADR-297 DAG it is a spine root alongside **ADR-302**
(authenticated identity) and feeds every downstream primitive that must speak
about *where* and *what*: **ADR-298** (calibration), **ADR-304** (tracking,
consumes `Track`/`Person`), **ADR-316** (witness chain), and every external
surface named in the ADR-297 consequences (MQTT, REST, WebSocket, RuField,
Matter, agents).
RuView currently expresses "where something is" in several overlapping,
per-surface schemas: the MQTT/Home-Assistant mapper has its own node/room
shapes (**ADR-294** just introduced `NodeInference`/`RoomInference` to
disambiguate node vs. room state); the `worldgraph` crate models a spatial
graph; RuField carries `SemanticProvenance`; Matter/HomeKit has its own area
model. The same physical fact — "a person is in the kitchen" — is re-encoded
differently on each surface, and the review called for "one canonical
`NodeInference`/`RoomInference` contract" (ADR-294 consequences). Without a
single semantic model, every new surface multiplies the translation matrix and
each translation is a place where provenance and evidence level (ADR-282) can
be silently dropped.
Substantial scaffolding already exists and must be **reused/extended, not
rebuilt**. `v2/crates/worldgraph/wifi-densepose-worldgraph` already defines:
- `WorldNode` variants including `Room { area_id, name, bounds_enu, floor }`,
`Zone { parent_room, … }`, `Wall { rf_attenuation_db }`, and `Doorway`.
- `WorldEdge` variants including `Observes { quality, last_seen_unix_ms }`,
`LocatedIn { since_unix_ms }`, `AdjacentTo { via_doorway }`, and `Supports`.
- `WorldGraph`, `WorldGraphSnapshot`, `WorldId`, `SemanticProvenance`,
`PersonPosition`, and a HomeCore `area_id` linkage join key (ADR-127).
The `worldgraph` crate is therefore the natural home for the canonical model.
What is missing is (a) the full `Site → Building → Floor → Space → Zone`
containment spine above `Room`, (b) first-class `Sensor`, `Object`,
`Observation`, `Track`, and `Event` node types, (c) one canonical serialization
that every surface consumes, and (d) a documented migration path from the
existing per-surface schemas.
## Options considered
1. **Leave each surface with its own schema; add adapters pairwise.** Rejected:
O(surfaces²) translations, and provenance/evidence loss at each hop.
2. **Invent a new top-level ontology crate.** Rejected: `worldgraph` already
models rooms, zones, walls, doorways, observation edges, and HomeCore
linkage; a parallel crate would fork the world model.
3. **Extend `worldgraph` into the canonical ontology and make every surface a
projection of it.** Chosen.
## Decision
Adopt **one canonical spatial ontology**, hosted in the `worldgraph` crate,
that every RuView surface reads from and writes to.
### 1. The containment spine and entity types
Define the full node taxonomy as an extension of the existing `WorldNode`:
```
Site ▸ Building ▸ Floor ▸ Space ▸ Zone
└─▸ { Sensor, Person, Object,
Observation, Track, Event }
```
- `Site`, `Building`, `Floor`, `Space` are new containment `WorldNode`
variants above the existing `Room` (mapped to `Space`, keeping its `area_id`
and `bounds_enu`) and `Zone`. `Wall`/`Doorway` remain as topological
elements. Containment reuses the existing `LocatedIn`/`AdjacentTo` edge
vocabulary; a new `PartOf` edge expresses the pure hierarchy
(Zone `PartOf` Space `PartOf` Floor …).
- `Sensor` is the entity **ADR-302** authenticates (`DeviceId` as its stable
identity) and **ADR-317** (HAL, phase 2) describes the hardware of. `Person`,
`Object`, `Observation`, `Track`, and `Event` are first-class nodes.
`Observes`/`LocatedIn` edges already carry quality and dwell timestamps.
- `Track` and `Person` are defined **here** as the ontology contract that
**ADR-304** (persistent tracking) produces and updates. `Observation` is what
an authenticated frame (ADR-302) becomes after calibration (ADR-298), and
`Event` is the governed output that ADR-315 certifies and ADR-316 witnesses.
### 2. Canonical serialization
- A single, versioned serialization (serde-based, stable field names) is the
one wire/at-rest representation. Every surface — MQTT/Home-Assistant, REST,
WebSocket, RuField observations, Matter/HomeKit, agent queries — is a
**projection** of this model, not an independent schema. `NodeInference` and
`RoomInference` (ADR-294) become projections of `Sensor→Observes` and the
`Space`-level fused inference respectively, so ADR-294's node/room separation
is preserved by construction rather than re-encoded per surface.
- Every node and edge carries `SemanticProvenance` and exactly one
`EvidenceLevel` (L0L5, ADR-282 policy): the evidence ladder travels *with*
the fact across every projection, so no surface can silently upgrade or drop
it.
### 3. Migration path
- Each existing per-surface schema gets a documented, tested bidirectional
mapping to/from the canonical model, plus a migration accessor for consumers
reading the old shape (mirroring ADR-294's migration accessor). Surfaces are
cut over one at a time; a surface is "canonical" once its projection is the
only encoder it uses. Until cutover, the mapping layer is authoritative and
round-trip-tested so no fact is lost in translation.
- The `worldgraph` HomeCore `area_id` linkage (ADR-127) remains the join key
between the ontology's `Space` and external area registries.
## Consequences
- The translation matrix collapses from O(surfaces²) to O(surfaces): each
surface implements one projection. New surfaces (ROS 2, OpenUSD, OPC UA per
ADR-282's roadmap) plug in as additional projections.
- Provenance and evidence level are carried uniformly; a fact cannot cross a
surface boundary and lose its lineage or its L-level.
- A schema change reaching every surface; managed by the versioned
serialization and per-surface migration accessors. Single-node deployments
keep working (one `Sensor`, one `Space`).
- The ontology is a *representation*, not an inference engine: it says nothing
about *how* a `Track` or `Event` is produced — that is owned by ADR-304,
ADR-298, ADR-299, and the model layer. This ADR does not itself make any
accuracy claim to grade.
- Extending `worldgraph` grows one crate's surface rather than forking a second
world model; the geo/worldmodel sub-crates continue to build on the same node
vocabulary.
## Validation
- Unit tests (`cargo test -p wifi-densepose-worldgraph`): containment-spine
construction and invariants (a `Zone` is `PartOf` exactly one `Space`, a
`Space` on exactly one `Floor`, etc.); round-trip serialization of every node
and edge type; every node/edge carries exactly one `EvidenceLevel`.
- Migration tests: each per-surface schema maps to the canonical model and back
with no loss of provenance or evidence level; `NodeInference`/`RoomInference`
(ADR-294) project and re-project identically.
- Contract test: a single canonical `Event` renders correctly through the MQTT,
REST, and WebSocket projections from one source of truth.
- No accuracy numbers are claimed; this ADR delivers the shared representation
the rest of the phase-1 spine writes into.
@@ -0,0 +1,135 @@
# ADR-304: Persistent identity & tracking — privacy-preserving probabilistic tracks
- **Status**: Proposed (ADR-297 phase 2)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: tracking, identity, privacy, fusion, worldgraph, phase-2
## Context
This ADR is a child of **ADR-297** and owns primitive #7, *persistent identity
& tracking*. In the ADR-297 DAG it is a phase-2 primitive sitting on the
phase-1 spine: it **consumes the ADR-303 ontology** (producing and updating the
`Track` and `Person` node types defined there), it relies on **ADR-302**
authenticated identity so that the observations it associates have a verified
origin, and its outputs are governed `Event`s that ADR-315/ADR-316 can certify
and witness.
The product need is to reason about *persistent entities* — "person_7 entered
the kitchen, then the hallway, then the bedroom" — across radios, modalities,
rooms, and time. The hard constraint is that this must happen **without
establishing civil identity**. RuView is camera-free (ADR-282), and a
persistent pseudonymous track must never become, or be joinable to, a real-
world named individual. This is a privacy property to be enforced *by
construction*, not a policy footnote.
Substantial scaffolding already exists in
`v2/crates/wifi-densepose-mat/src/tracking` and must be **reused/extended, not
rebuilt**:
- `SurvivorTracker`, `TrackedSurvivor`, `TrackId`, `TrackerConfig`,
`TrackLifecycle`, and `TrackState` — a multi-target tracker with lifecycle
(tentative/active/lost/terminal) and a `TrackId` backed by a UUID
(`as_uuid`).
- `KalmanState` with `predict`/`update`, `position`, `velocity`,
`position_uncertainty`, and `mahalanobis_distance_sq` — the motion model and
gating distance.
- `CsiFingerprint`, `DetectionObservation`, `AssociationResult`, and the
`can_reidentify`/`matches`/`mark_rescued`/`rescue` re-identification surface —
the appearance/fingerprint channel for track continuity.
What is missing is (a) continuity **across radios, modalities, and rooms** (the
tracker today reasons within a node/room context), (b) a **persistent** entity
that survives track loss and hand-off between spaces, and (c) an explicit
**privacy boundary** that guarantees no civil-identity binding.
## Options considered
1. **Per-room independent trackers, no cross-room identity.** Rejected: cannot
express "person_7 moved kitchen → hallway → bedroom"; loses the entity at
every room boundary.
2. **Global identity keyed on a strong biometric fingerprint.** Rejected: a
fingerprint strong enough to re-identify across long gaps trends toward a
civil-identity-grade biometric — exactly what the privacy constraint
forbids.
3. **Probabilistic persistent tracks with bounded, decaying pseudonymous
association, built on the existing MAT tracker.** Chosen.
## Decision
Extend `wifi-densepose-mat/tracking` into a **cross-domain persistent track
layer** that produces ADR-303 `Track`/`Person` nodes.
### 1. Persistent probabilistic entity
- A persistent entity is a pseudonymous `Person` node (ADR-303) with a stable
synthetic id (e.g. `person_7`) backed by the existing `TrackId`/UUID. It
aggregates one or more `SurvivorTracker` tracks over time and space and holds
a **probabilistic** continuity belief — association is never asserted as
certain, and every hand-off carries a confidence.
- Continuity across a track-loss gap reuses the existing re-identification
surface (`can_reidentify`, `CsiFingerprint`, `AssociationResult`), extended
with a **time- and distance-decayed** association prior so that confidence in
"same entity" falls with the size of the gap. Beyond a bounded horizon the
association is dropped and a new pseudonym is minted rather than forcing a
join — under-linking is the privacy-safe failure mode.
### 2. Cross-radio / cross-modality / cross-room continuity
- Association operates over the ADR-303 ontology graph: `Observes` edges from
multiple `Sensor`s and `AdjacentTo`/`Doorway` topology constrain plausible
hand-offs (a person can only move between adjacent spaces). The existing
`mahalanobis_distance_sq` gating extends to a fused observation across
modalities rather than a single node's detections.
- Fusion here is track-level association; the underlying multi-modality fusion
(radar/mmWave per ADR-063, multistatic per ADR-029, and real sensor fusion
per ADR-308) supplies the observations. This ADR depends on those for the raw
cross-modality evidence and does not re-implement sensor fusion.
### 3. Privacy boundary (by construction)
- **No civil-identity binding.** The persistent id is a synthetic pseudonym
with no field, edge, or join key to any name, account, phone, MAC, or other
civil identifier. The type carries no such field, so binding is impossible in
the schema, not merely discouraged.
- The `CsiFingerprint` used for re-identification is **bounded and decaying**:
it is scoped to short-horizon continuity, is not persisted as a long-term
biometric template, and expires. This keeps re-identification useful for
"same person across the hallway" while structurally unable to serve "this is
the same person who visited last month."
- Every `Track`/`Person`/`Event` produced carries `SemanticProvenance` and an
`EvidenceLevel` (ADR-282), and honors the ADR-277/ADR-280 edge governance and
ADR-141 attestation — a pseudonymous track is still governed P-class data.
Tracking accuracy is a per-domain claim to be tagged MEASURED/CLAIMED/
SYNTHETIC with a reproducer; **this ADR claims no accuracy number.**
## Consequences
- RuView can express persistent, cross-room trajectories for automation and
analytics while remaining camera-free and civil-identity-free.
- The privacy-safe failure mode is **under-linking** (mint a fresh pseudonym
when unsure), which will fragment a trajectory across long gaps or sparse
coverage. This is a deliberate trade: a fragmented pseudonym is safe, a
wrong civil-identity join is not.
- Extends an existing tracker rather than forking one; single-room single-radio
deployments keep the current behavior (one entity = one track).
- Cross-modality quality depends on ADR-308/ADR-063/ADR-029 landing; until then
continuity is WiFi-primary and its limits are stated, not hidden.
- Being phase 2, this ADR is design intent; it will be revised as the ADR-303
ontology and ADR-302 identity spine finalize.
## Validation
- Unit tests (`cargo test -p wifi-densepose-mat`): decayed association prior
(confidence falls with gap; drops beyond horizon → new pseudonym);
topology-constrained hand-off (no association across non-adjacent spaces);
schema check that a `Person`/`Track` carries no civil-identifier field.
- Integration test against a synthetic multi-room, multi-radio scenario:
a scripted walk kitchen → hallway → bedroom yields one persistent pseudonym
with per-hand-off confidence, and a deliberately ambiguous crossing produces
two pseudonyms rather than a false join.
- Evidence discipline: any tracking-continuity accuracy is reported only with
the ADR-288 leakage-free protocol and an evidence tag; no number is asserted
here.
- Privacy review: confirm no persisted long-term biometric template and no
civil-identity join path, as an explicit checklist item before any pilot.
@@ -0,0 +1,138 @@
# ADR-305: Sensor placement optimizer — floorplan + inventory → recommended positions
- **Status**: Proposed (ADR-297 phase 3)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: placement, planning, rf-twin, coverage, worldgraph, phase-3
## Context
This ADR is a child of **ADR-297** and owns primitive #8, *sensor placement
optimizer*. In the ADR-297 DAG it is a phase-3, research-forward primitive that
sits on top of the fused world state and is tightly coupled to **ADR-312**
(digital RF twin): the twin provides the propagation simulation this optimizer
plans against. It reads the **ADR-303** canonical ontology for the physical
scene and, after install, compares its predictions against ADR-299 observability
and the ADR-315 capability certificate.
The problem it solves is the single most common cause of a bad RuView
deployment: sensors placed by guesswork. Whether a room can be reliably sensed
depends on AP/sensor geometry relative to walls, Fresnel-zone clearance,
multipath structure, and where people actually move. Today an installer has no
principled way to answer "where do I put the two nodes I have so the kitchen is
observable?" — and no way, after install, to know whether reality matched the
plan. This is a genuine **differentiator**: it turns RuView from "sense
whatever the given placement happens to allow" into "recommend the placement
that makes the requested sensing feasible."
Relevant existing assets to build on rather than duplicate:
- The `worldgraph` crate models the physical scene the optimizer plans over:
`Room`/`Space` with `bounds_enu`, `Wall { rf_attenuation_db }` (drywall ≈ 3
dB, brick ≈ 12 dB), `Doorway`, and `Zone` — enough geometry and coarse RF
attenuation to seed a coverage model, plus `Sensor` nodes (ADR-303) for
candidate positions.
- **ADR-312** (RF twin, phase 3) is the propagation/multipath simulator; this
optimizer is a *consumer* of the twin, not a second simulator.
- **ADR-299** (OOD/observability) and **ADR-315** (capability certificate)
define what "reliably sense the requested phenomenon" means, so the optimizer
can optimize against the same observability metric the runtime later gates on.
- **ADR-029** (multistatic) and **ADR-063** (mmWave fusion) inform which link
geometries are useful for which phenomena.
## Options considered
1. **Static placement guidelines in docs (e.g. "one node per room, opposite
the door").** Rejected: ignores the specific floorplan, wall materials, and
the actual hardware inventory; gives no uncertainty and no post-install
feedback.
2. **Full electromagnetic solver per site.** Rejected for the default path:
too heavy for an installer workflow and overkill relative to the coarse
`rf_attenuation_db` scene RuView actually has; reserved as an optional
high-fidelity backend inside ADR-312.
3. **A coverage optimizer that consumes the ADR-312 RF twin over the ADR-303
scene, then validates predicted vs. measured observability after install.**
Chosen.
## Decision
Define a **placement optimizer** that takes a floor plan (ADR-303 scene) and a
hardware inventory and recommends sensor positions, then closes the loop after
install.
### 1. Inputs
- The ADR-303 canonical scene: `Space`/`Zone` bounds, `Wall` segments with
`rf_attenuation_db`, `Doorway` topology, and any already-placed `Sensor`
nodes.
- A hardware inventory: the count and type of available radios (ESP32-S3/C6
nodes, mmWave, adapters) with their capability envelopes (what each can
sense, per ADR-315 / ADR-317 HAL descriptors).
- A sensing objective: which phenomenon must be observable in which
`Space`/`Zone` (presence, vitals, pose), expressed against the ADR-299
observability metric.
### 2. Prediction
- For a candidate placement, query the **ADR-312 RF twin** for simulated RF
coverage: path loss through `Wall` attenuation, **Fresnel-zone clearance**
between link endpoints, and coarse **multipath** structure. From that derive
an **expected observability** and an **uncertainty** for each objective in
each space — reusing the same observability definition ADR-299 gates on so the
plan and the runtime speak one language.
- Search over candidate positions (the inventory bounds the count; the scene
bounds the geometry) to recommend the placement that maximizes objective
observability, reporting expected observability **and its uncertainty** per
space — never a single confident number for a simulated result.
### 3. Post-install loop
- After install, compare **predicted vs. measured** observability using the
ADR-299 runtime observability signal from the freshly enrolled (ADR-302),
calibrated (ADR-298) sensors. Where measurement disagrees with prediction,
recommend adjustments (move, re-aim, add a node) and feed the residual back
to improve the ADR-312 twin's scene parameters (e.g. a wall's effective
attenuation).
### Evidence discipline
- Predicted coverage is a **simulation** (evidence level L0 per ADR-282) and is
labelled `SYNTHETIC`; it is a *recommendation*, never a sensing claim.
- The predicted-vs-measured comparison is the only place a `MEASURED` statement
appears, and only with a reproducer and real-silicon observability data
(CLAUDE.md hardware rule). The optimizer never presents a simulated coverage
map as evidence that a room *is* being sensed.
## Consequences
- Installers get a principled, floorplan-specific placement plan and, crucially,
a post-install check that says whether reality matched the plan — a
differentiating capability over guess-and-check deployment.
- Quality is bounded by the fidelity of the ADR-312 RF twin and the coarseness
of the `worldgraph` scene (2D walls, coarse attenuation). The optimizer
reports uncertainty rather than overstating a coarse model; higher fidelity
is an ADR-312 concern.
- Hard dependency on ADR-312 (twin), ADR-299 (observability metric), and
ADR-303 (scene); this ADR does not build a simulator or an observability
metric of its own.
- Being phase 3, this is design intent sitting on the fused world state; it is
expected to be revised as ADR-312 and the phase-1 spine land.
- No claim that recommended placement *guarantees* sensing — it maximizes
modelled observability subject to inventory and geometry, with explicit
uncertainty.
## Validation
- Unit tests: coverage/observability prediction is a deterministic function of
scene + placement + twin parameters; Fresnel-zone and wall-attenuation math
against known analytic cases; search returns the modelled-optimal placement on
small synthetic scenes.
- Integration test: on a synthetic floorplan with a known-good and a
known-bad placement, the optimizer ranks them correctly and reports higher
uncertainty for the marginal case.
- Post-install loop test: injected predicted-vs-measured disagreement produces a
sensible adjustment recommendation and a twin-parameter residual.
- Field validation (deferred, real-silicon): predicted vs. measured
observability on an instrumented real site, reported as `MEASURED` with a
reproducer. Until then all coverage output is `SYNTHETIC`/L0. No coverage or
accuracy number is asserted by this ADR.
+152
View File
@@ -0,0 +1,152 @@
# ADR-306: Active sensing — closed-loop RF experiment control
- **Status**: Proposed (ADR-297 phase 3)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: active-sensing, control-plane, closed-loop, information-gain, actuation, phase-3
## Context
This ADR is a child of **ADR-297** and owns primitive #9, *active sensing*. In
the ADR-297 phasing it is a phase-3 primitive that sits on top of the fused
world state produced by **ADR-308** (real sensor fusion) and is driven by the
information budget of **ADR-311** (information-gain scheduler). It is authored
as **Proposed**: design intent and validation plan, not a phase-1 build.
The default posture of every current RuView path is **passive**: RF traffic
happens for its own reasons (a device transmits, a beacon fires), RuView
observes whatever CSI/CIR arrives, and the pipeline extracts what it can from
that incidental signal. The strategic assessment behind ADR-297 named the next
step: move from *RF-happens → observe* to **RuView-controls-RF → observe the
response → optimize the next measurement**. That turns sensing into a
closed-loop experiment — the system chooses what to measure to resolve the
uncertainty it currently has, rather than accepting the measurements the
environment happens to offer.
Substantial control-plane scaffolding already exists and must be
**reused/extended, not rebuilt**:
- **ADR-280** (active sensing / programmable perception, *implemented* in
`ruview-unified/src/control.rs`) already defines the governed control surface
this ADR closes the loop over: `SensingTask` (evidence-aware, fail-closed
admission), `SensingAction` + `InformationGoal` (a deliberate act of
evidence-gathering against a stated hypothesis, bounded by a `PrivacyClass`
P0P5 ceiling), `ActiveSensingPlanner` (age-of-information scheduler),
`CoherentSensorGroup` (coherent fusion fails closed), and `request_actuation`
`ActuationReceipt` for governed RIS/movable/fluid-antenna actuation.
- ADR-280 explicitly recorded that **information-gain *estimation* is not
implemented** — "the planner uses staleness heuristics, not mutual
information; RIS drivers, actual multi-AP coherence measurement, and OTFS
waveform control are hardware-dependent roadmap items." ADR-306 is the ADR
that closes exactly those gaps, in coordination with ADR-311.
The missing piece is not the actuation surface — ADR-280 built that and made it
fail closed — but the **loop**: a controller that reads the current fused-state
uncertainty, selects a *controllable measurement configuration* expected to
reduce it most, requests it through the ADR-280 governed surface, observes the
response, and updates its belief before choosing the next measurement.
## Options considered
1. **Stay passive; only schedule which incidental observations to keep.** This
is roughly today's `ActiveSensingPlanner` (staleness-priority over regions).
Rejected as the endpoint: it optimizes *attention* over uncontrolled RF, not
the *measurement* itself. It remains the fallback when nothing is
controllable.
2. **Open-loop measurement scripting** (a fixed sweep of channels/bandwidths).
Rejected: a fixed sweep spends the RF/energy/privacy budget the same way
regardless of what is already known; it cannot concentrate measurement where
uncertainty actually is.
3. **Closed-loop experiment control** — read uncertainty, pick the controllable
configuration with highest expected information gain per unit cost/privacy,
actuate through the ADR-280 governed surface, observe, update, repeat.
Chosen.
## Decision
Adopt **closed-loop RF experiment control** as a phase-3 controller layered on
the ADR-280 surface. RuView selects and drives the controllable degrees of
freedom of the RF measurement, then optimizes the next measurement from the
observed response.
### 1. Controllable degrees of freedom
Define an `ExperimentControl` vocabulary over the configuration axes RuView can
influence on hardware that exposes them (each axis is optional and
capability-gated by ADR-317's HAL, so an ESP32-only deployment simply has an
empty controllable set and degrades to the passive planner):
- **Channel / band** and **bandwidth** (which spectrum to probe; reuses the
ADR-289 wideband subcarrier-agnostic metadata).
- **Packet timing / cadence** (when to solicit a sounding, and at what rate).
- **Antenna / chain selection** (which subset of a distributed aperture to
activate — bounded by the ADR-280 `CoherentSensorGroup` compatibility proof).
- **Beam / RIS configuration** (which rooms and people become observable —
governed exactly as ADR-280 §6 requires, via `request_actuation` and an
`ActuationReceipt`).
- **802.11bf measurement parameters** (TB/non-TB, reporting config) once
ADR-307 exposes standardized sensing as a native measurement type.
### 2. The loop
```
fused-state uncertainty (ADR-308)
info-gain ranking of ExperimentControl options (ADR-311)
│ select argmax E[ΔI] / (cost, energy, privacy ceiling)
governed request (ADR-280 admit_task / request_actuation, fail-closed)
observe response → update belief (ADR-308) → repeat
```
The controller never bypasses the ADR-280 admission and actuation gates: every
solicited measurement is a `SensingTask`/`SensingAction`, every environment
change is an `ActuationReceipt`, and every step composes with the ADR-277
policy engine. Information gain is what **ADR-311** supplies (the mutual-
information estimate ADR-280 deferred); ADR-306 owns the *control loop* that
consumes that estimate and drives the hardware.
### 3. Governance and honesty boundary
- Actuation and solicitation stay fail-closed and privacy-ceilinged: a
closed-loop experiment cannot widen the P0P5 ceiling of the task it serves,
and cannot steer a beam into a zone that does not grant the purpose (ADR-280
`actuation_requires_policy_authorization`).
- Any accuracy or "traffic-reduction" claim from the closed loop is tagged
**MEASURED** only with a named reproducer over a stated scenario, **SYNTHETIC**
for simulated apertures, and **CLAIMED** otherwise. Real multi-AP coherent
measurement and RIS actuation remain **hardware-dependent** and require
real-silicon evidence (a captured runtime log) before any hardware claim, per
CLAUDE.md. No number is invented here.
## Consequences
- Sensing becomes an experiment: RuView spends its RF/energy/privacy budget on
the measurements that most reduce current uncertainty, instead of processing
whatever incidental traffic arrives.
- The loop is only as strong as its two dependencies: ADR-308 must expose a
usable uncertainty surface and ADR-311 must produce trustworthy information-
gain estimates. Where either is absent, the controller degrades to the
ADR-280 staleness planner rather than acting on a fabricated gain estimate.
- Controllability is hardware-bounded. On commodity ESP32 sensors the
controllable set may be limited to cadence; the full loop (bandwidth, antenna,
beam) needs NICs/RIS that expose those axes, surfaced through ADR-317.
- This ADR adds a controller; it does not re-open ADR-280's raw-export or
actuation-governance decisions, which remain authoritative and fail-closed.
## Validation
- Design-level acceptance (phase 3): a simulated closed loop over a synthetic
scene reduces terminal fused-state uncertainty faster than (a) the passive
ADR-280 staleness planner and (b) an open-loop fixed sweep, at equal
measurement budget — reported **SYNTHETIC**, with the scenario and seed named.
- Governance tests: every solicited measurement and actuation in the loop is
admitted through the ADR-280 fail-closed path; a loop step that would exceed
the task's privacy ceiling or steer into an ungranted zone is denied.
- Degradation test: with an empty controllable set (ESP32-only), the controller
falls back to the staleness planner with no error and no fabricated gain.
- Hardware validation of bandwidth/antenna/beam actuation is explicitly out of
scope until real silicon exposes those axes and produces a captured log.
@@ -0,0 +1,147 @@
# ADR-307: 802.11bf-native architecture — standardized WLAN sensing as native measurement types
- **Status**: Proposed (ADR-297 phase 2)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: 80211bf, wlan-sensing, standards, measurement-types, hal, phase-2
## Context
This ADR is a child of **ADR-297** and owns primitive #10, *802.11bf-native
architecture*. In the ADR-297 phasing it is a phase-2 integration primitive: it
sits on the phase-1 spine (authenticated identity ADR-302, spatial ontology
ADR-303, evidence engine ADR-301) and **feeds ADR-317** (the RuView sensor HAL),
which is the clause of the acceptance test that "identifies the hardware." It is
authored as **Proposed**.
**IEEE 802.11bf-2025 ("WLAN Sensing") was published 2025-09-26** — verified
against the IEEE SA record in `wifi-densepose-hardware` (`ieee80211bf/mod.rs`
header, "evidence grade MEASURED", ADR-152 §1.1). Standardization is complete
for sub-7 GHz and >45 GHz (DMG) bands: formal sensing measurement setup,
measurement instances, feedback/reporting, and sensing-by-proxy (SBP). This
changes RuView's strategic frame: rather than treating every WiFi measurement as
an *opportunistic* extraction from incidental traffic, RuView can be the **open
reference sensing stack around the standard** — the day commodity silicon
exposes it.
Substantial scaffolding already exists and must be **reused/extended, not
rebuilt**. `v2/crates/wifi-densepose-hardware/src/ieee80211bf/` already models
the standardized procedure surface as forward-compatible types (ADR-152/153):
- `types``SpecProfile` version gates, `SensingRole`/`TransceiverRole`,
`MeasurementSetupParams`, `SensingCapabilities` negotiation, and required
`ConsentMode` governance metadata on every setup.
- `messages``SensingMeasurementSetupRequest/Response`,
`SensingMeasurementInstance`, `SensingMeasurementReport`, `CsiReportPayload`,
`SbpRequest/Response`, `SensingSessionTermination`.
- `session` — a deterministic FSM (`Idle → SetupNegotiating → Active →
Terminating → Idle`) with rejection paths, single-role enforcement, and SBP
proxy mode; `table` (responder-side setup registry); `transport` (the
`SensingTransport` seam, a `SimTransport` test double, and an
`OpportunisticCsiBridge` that maps today's opportunistic CSI onto the
standardized report path).
The module's own honesty note is authoritative and carried forward here: it is
**not a certified 802.11bf implementation**, and **no commodity silicon — ESP32
included — implements the standard yet**; the OTA frame binding lands when a
chipset exposes it. Wideband ingest plumbing is already in place too: **ADR-289**
(FeitCSI/AX210) carries native subcarrier dimensionality end-to-end and records
the native→pipeline mapping, and noted that "truncated CIR is a natural
extension of the same plumbing."
What is missing is architectural, not protocol scaffolding: normalized CSI is
still treated as *the* WiFi input. The standardized sensing measurements
(TB/non-TB soundings, truncated CIR / PDP reports) are modeled as protocol
messages but are **not yet first-class native measurement types** that flow
through calibration (ADR-298), fusion (ADR-308), and the ontology (ADR-303) on
equal footing with normalized CSI.
## Options considered
1. **Keep 802.11bf as a protocol model only; always down-convert its reports to
normalized CSI at ingest.** Rejected: truncated CIR/PDP carry range-resolved
multipath structure that flattening to a CSI matrix discards; it also wastes
the standard's native report semantics.
2. **Fork a parallel "bf pipeline" alongside the CSI pipeline.** Rejected:
duplicates calibration, fusion, ontology, and evidence plumbing, and re-opens
the O(surfaces²) translation problem ADR-303 exists to close.
3. **Promote standardized sensing measurements to native measurement types
inside the existing pipeline**, with normalized CSI as one measurement type
among several. Chosen.
## Decision
Adopt an **802.11bf-native architecture**: standardized WLAN sensing
measurements become **additional native measurement types**, alongside — not
replacing — normalized CSI.
### 1. Native measurement types
- Define the standardized reports the `ieee80211bf` module already models
(TB and non-TB soundings; truncated CIR; PDP) as first-class
`MeasurementType` variants that the pipeline carries end-to-end, each tagged
with its `SpecProfile` and band. Normalized CSI remains one such type; the
`OpportunisticCsiBridge` remains the path for silicon that only offers
incidental CSI.
- Truncated CIR/PDP reuse the **ADR-289** subcarrier-agnostic / native-
dimensionality plumbing (truncated CIR is the stated natural extension); the
native→pipeline mapping is recorded in frame metadata so downstream stages
know the true range/spectral resolution of a bf report vs. an interpolated CSI
frame.
### 2. Ontology and governance binding
- Each standardized measurement becomes an ADR-303 `Observation` node from an
ADR-302-authenticated `Sensor`, carrying `SemanticProvenance` and exactly one
`EvidenceLevel` (L0L5, ADR-282). The `ieee80211bf` `ConsentMode` metadata —
required on every setup — composes with the ADR-277 policy engine, so a
standardized session is admitted under the same governance as any other
sensing task (ADR-280).
- SBP (sensing-by-proxy) sessions attribute the report to the proxying and the
sensing entities distinctly, so provenance is not laundered through the proxy.
### 3. HAL feed (ADR-317)
- The capability set a device advertises — which `MeasurementType`s, bands,
bandwidths, roles, and `SpecProfile` it supports — is exactly the descriptor
**ADR-317** (HAL) needs to "identify the hardware." ADR-307 defines that
capability descriptor as the projection of `SensingCapabilities`; ADR-317
consumes it. A device that implements no bf profile advertises only the
opportunistic-CSI capability.
## Consequences
- RuView is positioned as the open reference stack *around* the standard: when a
chipset exposes 802.11bf, its native reports flow through calibration, fusion,
ontology, and evidence with no bespoke pipeline — the plumbing is already
tested against `SimTransport` and synthetic fixtures.
- Normalized CSI is demoted from "the WiFi input" to "one measurement type,"
which is the correct framing for a multi-measurement future and prevents the
bf path from being a second-class citizen.
- **No hardware claim is made or implied.** No commodity silicon implements
802.11bf yet; this ADR wires the *types and flow*, tested in simulation. Any
OTA/native-report accuracy claim requires real silicon evidence (a captured
log) per CLAUDE.md, and any wideband number must be tagged with the capture
hardware (ADR-289). No benchmark number is invented here.
- This ADR does not re-open ADR-152/153's decision to avoid OTA frame binding
until silicon exists; it consumes that surface and adds the pipeline
integration.
## Validation
- `cargo test -p wifi-densepose-hardware` — existing `ieee80211bf` FSM,
table, and transport tests continue to pass; new tests assert that a
`SensingMeasurementReport` (TB and non-TB) and a truncated-CIR/PDP report
round-trip through the pipeline as native `MeasurementType`s.
- `cargo test -p wifi-densepose-mat` — truncated CIR ingest reuses the ADR-289
subcarrier-agnostic path and records the native→pipeline mapping; dimension/
version validation on standardized reports mirrors the FeitCSI parser gates.
- Ontology/governance tests: each standardized measurement becomes an ADR-303
`Observation` from an ADR-302-authenticated `Sensor` with one `EvidenceLevel`;
`ConsentMode` composes with ADR-277 admission; SBP attributes proxy vs. sensor
provenance distinctly.
- HAL contract test: the ADR-317 capability descriptor is derivable from
`SensingCapabilities`; a bf-less device advertises only opportunistic CSI.
- All measurement-type flows are simulation-tested (`SimTransport`, synthetic
fixtures); OTA binding and any hardware accuracy claim remain out of scope
until real silicon exposes the standard.
+140
View File
@@ -0,0 +1,140 @@
# ADR-308: Real sensor fusion — uncertainty-aware, multiple observations → one world state
- **Status**: Proposed (ADR-297 phase 2)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: fusion, uncertainty, multimodal, world-state, ontology, phase-2
## Context
This ADR is a child of **ADR-297** and owns primitive #11, *real sensor fusion*.
In the ADR-297 DAG it is a phase-2 integration primitive: it **consumes ADR-303**
(canonical spatial ontology) and **produces the single fused world state** that
the phase-3 primitives build on — **ADR-309** (long-term spatial memory),
**ADR-310** (counterfactual inference), and **ADR-312** (digital RF twin). It is
authored as **Proposed**.
The defining invariant is not "support more modalities" but the *shape of the
output*: **multiple observations must resolve to one probabilistic world state,
not many feeds into a visualization.** A dashboard that shows a WiFi layer, a
mmWave layer, and a BLE layer side by side is not fusion; it pushes the
reconciliation onto the human. Real fusion produces one uncertainty-aware state
that every downstream consumer reads, with each contributing observation's
provenance and confidence still recoverable.
Substantial scaffolding already exists and must be **reused/extended, not
rebuilt**:
- **ADR-063** (60 GHz mmWave ↔ WiFi CSI fusion, *Proposed*) established the
first cross-modal fusion case: pairing noisy CSI-derived vitals with clinical-
grade mmWave FMCW radar (Seeed MR60BHA2 over UART, with a **live hardware
capture** logged on 2026-03-15). ADR-308 generalizes that pairwise case into
an N-modality, uncertainty-aware fusion.
- **ADR-137** (fusion-engine quality scoring, *Accepted — partial*) already
built the auditable-quality building block: it identified that the multistatic
fusers (`wifi-densepose-signal/src/ruvsense/multistatic.rs`,
`wifi-densepose-ruvector/src/viewpoint/fusion.rs`) discarded the evidence they
used, and specified a single auditable record — "this fused output is
trustworthy because X, Y, Z, but be aware of contradiction C" — with evidence
references and contradiction flags. ADR-308 reuses that record as the
provenance/quality carrier of the fused state.
- **ADR-280** `CoherentSensorGroup` (fail-closed coherent fusion) and
**ADR-303** `Observation`/`Track`/`Event` node types are the input and output
vocabulary respectively.
What is missing is the **uncertainty-aware combiner across heterogeneous
modalities**: a fusion stage that takes authenticated observations from WiFi,
BLE, UWB, mmWave, acoustic, IMU, lidar, and cameras (only where policy permits),
each with its own uncertainty, and emits one probabilistic `WorldState` — with
per-observation contradiction flags, not a stack of independent feeds.
## Options considered
1. **Per-modality feeds rendered together** (today's implicit model on some
surfaces). Rejected: it is visualization, not fusion; contradictions are
never reconciled and there is no single state to reason over.
2. **Hard-switch "best modality wins"** (e.g., always prefer mmWave vitals over
CSI vitals). Rejected: throws away corroborating evidence and cannot express
*disagreement* — the very thing ADR-137's contradiction flags exist to
surface — and degrades badly when the preferred modality is absent or OOD.
3. **Uncertainty-weighted probabilistic fusion into one world state**, reusing
ADR-137's auditable quality record and ADR-280's fail-closed coherence gate.
Chosen.
## Decision
Adopt **uncertainty-aware multimodal fusion** whose invariant output is one
probabilistic world state.
### 1. Inputs: authenticated, ontology-typed observations
- Inputs are ADR-303 `Observation` nodes from **ADR-302-authenticated** sensors.
Supported modalities: WiFi (CSI / 802.11bf native reports via ADR-307), BLE,
UWB, mmWave (ADR-063), acoustic, IMU, lidar, and cameras. Cameras and any
higher privacy-class modality enter fusion **only where the ADR-277 policy
engine permits** — camera-free coverage is a RuView invariant (ADR-282), so
cameras are an opt-in, policy-gated input, never assumed present.
- Each observation carries its own uncertainty and exactly one `EvidenceLevel`
(ADR-282). An observation flagged out-of-distribution by **ADR-299** is
down-weighted or excluded per its OOD verdict rather than silently averaged in.
### 2. Combiner: uncertainty-weighted, contradiction-aware
- Observations are combined by their uncertainty into one probabilistic
`WorldState` over the ADR-303 entities (`Person`, `Object`, `Track`, and the
per-`Space` inference). The combiner does **not** collapse disagreement: when
modalities conflict beyond their stated uncertainty, the fused output carries
ADR-137 **contradiction flags** and the evidence references that produced
them, so a consumer can see *that* WiFi and mmWave disagree and *why*.
- Coherent multi-node fusion inherits ADR-280's fail-closed
`CoherentSensorGroup` gate: no coherent combination unless sync, phase, and
geometry compatibility are proven; otherwise the group degrades to incoherent
combination rather than producing confident nonsense.
### 3. Output: one world state, provenance preserved
- The output is a single `WorldState` written into the ADR-303 ontology, with
every fused value retaining recoverable per-observation provenance and the
ADR-137 quality record. This is the state ADR-309/310/312 consume; they read
one probabilistic world, not a modality stack.
- The fused state carries an aggregate uncertainty and an evidence level derived
from its inputs (never upgraded above the weakest contributing L-level for a
given claim).
## Consequences
- Downstream primitives (spatial memory, counterfactual, RF twin) build on one
probabilistic world state with uniform uncertainty and provenance, instead of
re-implementing reconciliation per consumer.
- Contradictions become first-class signal, not noise: ADR-137's record means a
disagreement between mmWave and CSI is surfaced and auditable, which is also
what lets ADR-299 and the evidence engine (ADR-301) reason about reliability.
- Fusion is uncertainty-honest: an OOD or low-evidence observation is
down-weighted, not averaged in as if trustworthy; a fused claim never presents
a stronger evidence level than its weakest necessary input.
- **No accuracy or "camera-grade" claim is made.** ADR-063's mmWave path has a
real-silicon capture; the multimodal combiner's accuracy is not asserted here.
Any fused-accuracy number requires a named reproducer tagged MEASURED /
SYNTHETIC / CLAIMED, and WiFi sensing is never presented as camera-grade
(CLAUDE.md, ADR-282). No number is invented.
- Cameras remain a governed, opt-in input; enabling them does not weaken the
camera-free coverage guarantee for deployments that exclude them.
## Validation
- `cargo test -p wifi-densepose-ruvector` / `-p wifi-densepose-signal` — the
ADR-137 quality record and contradiction flags travel with the fused output;
the ADR-280 `CoherentSensorGroup` gate still fails closed under
clock/phase/geometry violation.
- Fusion invariant test: N modality observations over one scene resolve to a
single `WorldState` node in the ADR-303 ontology (not N feeds), with
per-observation provenance recoverable and one aggregate evidence level.
- Uncertainty tests: a high-uncertainty or ADR-299-flagged-OOD observation is
down-weighted/excluded; conflicting modalities produce a contradiction flag
rather than a silently averaged value; the fused evidence level never exceeds
the weakest necessary input.
- Governance test: a camera or higher-privacy modality is admitted into fusion
only when the ADR-277 policy engine permits; otherwise it is excluded and the
fused state notes the exclusion.
- Any accuracy comparison (e.g., fused vitals vs. mmWave-only) is reported with
its evidence tag and reproducer; none is asserted in this ADR.
@@ -0,0 +1,146 @@
# ADR-309: Long-term spatial memory — learn the normal physics of a location
- **Status**: Proposed (ADR-297 phase 3)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: spatial-memory, ruvector, anomaly-detection, temporal, world-state, phase-3
## Context
This ADR is a child of **ADR-297** and owns primitive #12, *long-term spatial
memory*. In the ADR-297 phasing it is a phase-3 primitive that sits on the fused
world state produced by **ADR-308** (real sensor fusion) and **ties to ADR-312**
(digital RF twin): spatial memory is the *learned normal* that a twin can
simulate against and that anomaly detection compares against. It is authored as
**Proposed**.
The capability is to **learn the normal physics of a location** so anomalies
surface *without training a detector for every anomaly*. Concretely, the system
should learn statements like: "a chair is normally here"; "this bedroom is
usually occupied between these hours"; "the RF propagation of this space
changed"; "this machine's vibration signature changed"; "a new reflector
appeared." None of these is a labeled anomaly class — they are *deviations from
a learned baseline of normality*. This is the difference between supervised
anomaly detection (which needs examples of every failure) and **baseline-relative
anomaly detection** (which needs only a well-characterized normal).
Substantial substrate already exists and must be **reused/extended, not
rebuilt**:
- **RuVector** (`v2/crates/wifi-densepose-ruvector`) is the designated substrate
in the ADR-282 layer stack ("persistent objects, Gaussian fields, scene
graphs, temporal memory"). It already provides the vector/temporal machinery
this ADR needs — HNSW indexing (`hnsw.rs`, `hnsw_quantized.rs`), an event log
(`event_log.rs`), coverage and estimator surfaces, and the `crv`/`mat`
temporal sub-modules — so long-term spatial memory is a *consumer and
organizer* of RuVector primitives, not a new store.
- **ADR-303** supplies the entity vocabulary the memory is indexed by (`Space`,
`Object`, `Sensor`, `Track`, `Event`); **ADR-308** supplies the fused,
uncertainty-carrying `WorldState` snapshots that memory accumulates over time.
- **ADR-135** (empty-room baseline calibration) and **ADR-298** (automatic
domain calibration) already establish a *calibration-time* baseline of a
space; ADR-309 extends that from a one-shot baseline to a **continuously
learned, time-of-day-aware** model of normal.
What is missing is the **temporal normality model**: a per-`Space` learned
distribution of fused world states over time (including periodicity — hour of
day, day of week), plus RF-propagation and modality-signature baselines, against
which a live fused state is scored for deviation.
## Options considered
1. **Supervised anomaly classifiers per anomaly type.** Rejected: it needs
labeled examples of every anomaly (fall, intrusion, machine fault, moved
furniture), which do not exist for most spaces and do not transfer between
rooms; it also cannot catch a *novel* anomaly it was never trained on.
2. **Single static baseline** (the ADR-135 empty-room snapshot, used forever).
Rejected as the endpoint: it cannot express *when* a space is normally
occupied, cannot track slow legitimate drift (furniture rearranged on
purpose), and flags every diurnal change as anomalous.
3. **Continuously learned, time-aware normality model on the RuVector
substrate**, scoring live fused state against learned normal. Chosen.
## Decision
Adopt a **long-term spatial memory** that learns each location's normal physics
on the RuVector substrate and scores live fused state against it.
### 1. What "normal" is learned over
Per ADR-303 `Space` (and the entities within it), accumulate the ADR-308 fused
`WorldState` over time into a learned normality model covering:
- **Occupancy / activity periodicity** — the distribution of presence and
activity by hour-of-day and day-of-week (the "bedroom usually occupied certain
hours" case).
- **Static scene layout** — persistent `Object` positions and the expected
reflector set (the "chair normally here" / "new reflector appeared" cases),
building on the ADR-135/298 baseline.
- **RF-propagation baseline** — the space's normal multipath/propagation
signature (the "RF propagation changed" case).
- **Per-modality signatures** — e.g., a machine's normal vibration/acoustic/IMU
signature (the "vibration signature changed" case).
Each learned baseline carries its own uncertainty and an `EvidenceLevel`
(ADR-282); a baseline learned from replay is L1, from a field pilot L4, and is
never presented above the evidence of the observations it was learned from.
### 2. Substrate: RuVector, temporally compressed
- The memory is stored and indexed on RuVector (HNSW for nearest-normal recall,
the event log for the temporal stream, the temporal sub-modules for
compression). Long-horizon history is temporally compressed — recent detail
retained, older history summarized — so memory cost is bounded rather than
growing linearly forever.
- The memory is *keyed by* the ADR-303 ontology, so "normal for this `Space` at
this hour" is a first-class query, and slow legitimate drift updates the
baseline (with provenance) instead of accumulating as permanent anomaly.
### 3. Anomaly = deviation from learned normal
- A live fused `WorldState` is scored against the applicable learned baseline
(matched by space and time context). A deviation beyond the baseline's
uncertainty is surfaced as an ADR-303 `Event`*without* a per-anomaly
detector — carrying the baseline it deviated from, the deviation magnitude,
and its evidence level. Whether that event is actionable is a policy/consumer
decision (ADR-277), not this layer's.
- The learned normal is exactly what **ADR-312** (RF twin) can simulate against:
the twin proposes an expected state, spatial memory supplies the learned
actual-normal, and their divergence is a physically grounded anomaly signal.
## Consequences
- Anomaly detection generalizes: a space gets deviation detection from its own
learned normal, so a novel anomaly (never labeled anywhere) still registers as
a deviation, and the model transfers to a new room by *learning that room's*
normal rather than importing a foreign detector.
- Bounded memory: temporal compression keeps long-horizon memory finite; the
trade-off is that fine detail of old history is summarized, which is acceptable
for a normality baseline.
- Legitimate change is not a permanent false positive: slow drift updates the
baseline with provenance, distinguishing "furniture deliberately rearranged"
(baseline shifts) from "reflector appeared unexpectedly" (deviation event).
- **No accuracy claim is made.** Deviation-detection quality is not asserted
here; any detection-rate or false-positive number requires a named reproducer
tagged MEASURED / SYNTHETIC / CLAIMED, and a health/safety framing stays within
the ADR-282 bounded-claims discipline (decision support, not diagnosis). No
number is invented.
- The memory is governed: learned baselines are observations of a space, subject
to the same ADR-277 retention/privacy policy as the fused state they summarize;
no raw P0 RF is retained to build a baseline.
## Validation
- `cargo test -p wifi-densepose-ruvector` — the normality model builds on the
existing HNSW/event-log/temporal primitives; nearest-normal recall and
temporal-compression bounds are exercised on synthetic streams.
- Baseline/deviation tests: a synthetic scene with a known injected change (moved
`Object`, altered propagation, altered modality signature) produces a deviation
`Event` against the learned normal *without* a per-anomaly detector; an
unchanged diurnal cycle produces none (no false positive on normal periodicity).
- Drift test: a slow legitimate change updates the baseline (with provenance)
rather than emitting a persistent anomaly; an abrupt change does emit one.
- Evidence test: a learned baseline carries the evidence level of its source
observations and is never presented above it; retention honors ADR-277.
- Twin-linkage design check (with ADR-312): divergence between a twin-simulated
expected state and the learned normal is expressible as a deviation signal.
@@ -0,0 +1,142 @@
# ADR-310: Counterfactual inference — generative spatial reasoning
- **Status**: Proposed (ADR-297 phase 3)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: inference, generative, counterfactual, rf-twin, fusion, uncertainty, phase-3
## Context
This ADR is a child of **ADR-297** (perception substrate program) and owns
primitive #13, *counterfactual inference*. In the ADR-297 DAG it is a phase-3,
research-forward primitive that sits on top of the fused world state: it
**consumes ADR-308** (real sensor fusion) for the current fused estimate and
**ADR-312** (digital RF twin) for the twin's expected measurement
distributions. It is design intent, authored as Proposed, and is expected to be
revised as the phase-1 spine and the phase-2 fusion layer land.
RuView today reasons discriminatively: a task head maps measurements to a label
or a pose. That answers "what does the classifier say?" but not the questions an
operator actually asks — *would these RF measurements still make sense if nobody
were present? Does one person explain the observation better than two?* Those
are counterfactual questions, and a classifier cannot answer them because it has
no model of what a measurement *should* look like under a hypothesized world
state. A discriminative head asked about an empty room simply emits its
best-effort label; it cannot say "the observation is better explained by
absence."
The step this ADR proposes is toward a **generative spatial model**: given a
hypothesized scene state (occupancy, count, coarse positions) and the ADR-312
twin's propagation model for the deployment, predict the *expected* measurement
distribution, then score how well each hypothesis explains the observed
measurement. The best-explaining hypothesis — including the *nobody-present*
null hypothesis — is the answer, and the margin between hypotheses is a
first-class uncertainty signal.
Relevant existing assets to build on rather than duplicate:
- **ADR-308** (fusion) already produces the fused world estimate and its
covariance; the counterfactual layer scores hypotheses *relative to* that
estimate rather than re-fusing raw measurements.
- **ADR-312** (RF twin) is the generative forward model — per-deployment
geometry, radio locations, and expected measurement distributions. This ADR
is a *consumer* of the twin's forward simulator, not a second simulator.
- **ADR-299** (OOD/observability) already owns the `UNKNOWN` verdict; the
null-hypothesis ("nobody present better explains this than any occupancy
hypothesis") and the "no hypothesis explains this" case route through ADR-299,
not a parallel gate.
- `frame::EvidenceLevel` L0L5 (ADR-282) and the ADR-301 evidence engine
account for the resulting confidence.
## Options considered
1. **Keep only discriminative heads.** Rejected: cannot express absence,
cannot compare "one person vs. two" as competing explanations, and gives a
confident label even when no world state explains the data.
2. **A second, independently trained generative network with its own forward
model.** Rejected for the default path: duplicates the ADR-312 twin's
propagation model, invites the two models to disagree, and multiplies the
surface that must be validated. Reserved only if the twin's analytic forward
model proves insufficient for a phenomenon.
3. **A hypothesis-scoring layer that uses the ADR-312 twin as the forward model
and the ADR-308 fused state as the hypothesis prior, routing low-margin and
null-dominant cases to the ADR-299 UNKNOWN verdict.** Chosen.
## Decision
Define a **counterfactual inference layer** that scores a small set of scene
hypotheses against observed measurements using the digital RF twin as the
generative forward model.
### 1. Hypothesis set
- Hypotheses are drawn from the ADR-308 fused state and its neighbourhood: the
current estimate, the **null hypothesis** (nobody present), and a bounded set
of nearby alternatives (±1 occupant, shifted position). The fused estimate
supplies the prior so the search stays small and grounded rather than
enumerating an open world.
- The hypothesis space is expressed over the **ADR-303** canonical ontology
(`Space`/`Zone`, occupant count, coarse position), so a counterfactual result
is a governed spatial statement, not an opaque score.
### 2. Forward model and scoring
- For each hypothesis, query the **ADR-312 twin** for the expected measurement
distribution given that scene state and the deployment's propagation model.
Score the observed measurement's likelihood under each hypothesis's expected
distribution.
- The answer is the maximum-likelihood hypothesis; the **margin** between the
top hypotheses (and between the top hypothesis and the null) is the
confidence signal, carried into the ADR-301 evidence engine.
### 3. Routing to UNKNOWN
- When the null hypothesis dominates, the layer reports *absence*, not a
low-confidence occupancy label.
- When **no** hypothesis explains the observation well (all likelihoods low, or
the winning margin below threshold), the result routes to the **ADR-299**
`UNKNOWN` verdict — the observation is outside what the twin can explain, and
the honest output is "I cannot account for this," never a forced label.
### Evidence discipline
- Twin-predicted distributions are a **simulation** (evidence level L0 per
ADR-282) labelled `SYNTHETIC`; a counterfactual verdict inherits the evidence
level of its weakest input and is never presented as camera-grade ground
truth (CLAUDE.md honesty rule).
- Any accuracy statement about counterfactual discrimination (e.g. "distinguishes
one occupant from two") requires the mean-pose-style baseline discipline of
CLAUDE.md, a leakage-free held-out split, and a reproducer before it may be
tagged `MEASURED`. This ADR asserts **no** such number.
## Consequences
- RuView gains the ability to answer absence and "which explanation is better"
questions that discriminative heads structurally cannot — a step toward
generative spatial reasoning and a differentiator for security and
facility-monitoring applications where *absence* is the valuable signal.
- Quality is bounded by the fidelity of the ADR-312 twin's forward model and the
ADR-308 fused prior; the layer reports margins and defers to ADR-299 UNKNOWN
rather than overstating a coarse model.
- Hard dependency on ADR-308 (fused state and covariance) and ADR-312 (forward
model); this ADR builds neither a fusion engine nor a propagation simulator of
its own.
- Being phase 3, this is design intent sitting on the fused world state; it is
expected to be revised as ADR-308 and ADR-312 land, and it is not implemented
by the phase-1 swarm.
## Validation
- Unit tests: hypothesis likelihood scoring is a deterministic function of
observed measurement + hypothesis + twin parameters; the null hypothesis wins
on a synthesized empty-room measurement; a two-occupant measurement scores the
two-occupant hypothesis above the one-occupant hypothesis on a controlled
synthetic case.
- Integration test: measurements the twin cannot explain (out-of-model
scattering) drive the layer to the ADR-299 UNKNOWN verdict rather than a
forced occupancy label; margins propagate into the ADR-301 evidence engine.
- Held-out discrimination (deferred, real-silicon): one-vs-two and
presence-vs-absence discrimination on a leakage-free held-out split with a
mean-pose baseline, reported as `MEASURED` with a reproducer. Until then all
counterfactual output is `SYNTHETIC`/L0. No discrimination accuracy number is
asserted by this ADR.
@@ -0,0 +1,138 @@
# ADR-311: Information-gain scheduler — sample the most informative radios
- **Status**: Proposed (ADR-297 phase 3)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: scheduling, active-sensing, information-gain, edge, energy, fusion, phase-3
## Context
This ADR is a child of **ADR-297** (perception substrate program) and owns
primitive #14, *information-gain scheduler*. In the ADR-297 DAG it is a phase-3,
research-forward primitive that sits on top of the fused world state and
**pairs with ADR-306** (active sensing): ADR-306 decides *what to probe*
(waveform, sensing task); this ADR decides *which radios/modalities to spend
budget on next*. It is authored as Proposed and is not implemented by the
phase-1 swarm.
With multiple sensors, processing every stream at full rate is wasteful: many
radios are, at any moment, contributing little to the current estimate while
consuming compute, energy, and bandwidth — the three scarce resources on the
edge nodes RuView targets (ESP32-S3/C6 and small gateways). Treating all sensors
equally is precisely the design that does not survive a real deployment of
"hundreds of sensors."
The scheduler assigns each candidate sensor/modality a value
```
Value(sensor) ≈ expected uncertainty reduction / (compute + energy + bandwidth)
```
and spends the next sampling/processing budget on the highest-value sensors.
Expected uncertainty reduction is estimated *before* paying for the measurement,
which is why the scheduler needs a model of what each sensor is likely to tell
it — supplied by the fused state's covariance and the RF twin's forward model,
not by actually sampling.
Relevant existing assets to build on rather than duplicate:
- **ADR-308** (fusion) maintains the fused state and its covariance — the
current uncertainty the scheduler is trying to reduce. Expected uncertainty
reduction is computed against that covariance, not a private one.
- **ADR-312** (RF twin) provides the per-sensor forward model used to predict a
candidate measurement's expected informativeness before sampling.
- **ADR-317** (RuView sensor HAL, phase 2) exposes each radio's real
compute/energy/bandwidth cost descriptors; the denominator is read from the
HAL, not guessed per platform.
- **ADR-306** (active sensing) is the paired actuator: the scheduler ranks
sensors, ADR-306 chooses the probe on the chosen sensor.
- **ADR-299** (observability) defines the phenomenon the estimate is *for*, so
the scheduler prioritizes uncertainty reduction on the objective that matters,
not on nuisance dimensions.
## Options considered
1. **Round-robin / process-everything scheduling.** Rejected: burns edge
compute and energy on redundant streams and does not scale to large fleets;
the strategic and external reviews named exactly this as an edge-deployment
blocker.
2. **Static priority per sensor type (e.g. always prefer mmWave).** Rejected:
ignores that a sensor's *current* informativeness depends on the scene and
the present uncertainty — a well-placed WiFi link can dominate an occluded
mmWave node in a given moment.
3. **A value-of-information scheduler that ranks sensors by expected uncertainty
reduction per unit cost, using the ADR-308 covariance and ADR-312 forward
model, with costs from the ADR-317 HAL.** Chosen.
## Decision
Define an **information-gain scheduler** that allocates the next
sampling/processing budget across available radios by value of information.
### 1. Value function
- For each candidate sensor/modality, estimate **expected uncertainty
reduction** on the ADR-299 objective by evaluating how much a predicted
measurement (via the **ADR-312** forward model) would shrink the **ADR-308**
fused-state covariance — a value-of-information estimate made *before* paying
for the measurement.
- Divide by the sensor's **cost** — compute + energy + bandwidth — read from the
**ADR-317** HAL descriptors. The exact weighting of the three cost terms is a
deployment policy (a battery node weights energy heavily; a wired gateway
weights bandwidth), configured, not hardcoded.
### 2. Allocation
- Rank candidates by value and spend the budget on the top set, subject to a
configurable floor that guarantees each sensor is sampled at least
occasionally (so a sensor whose value is currently low is not starved into
permanent blindness and can be re-evaluated as the scene changes).
- The scheduler emits an allocation, not a measurement; **ADR-306** active
sensing chooses the probe/waveform on each selected sensor, and the fusion
layer (ADR-308) incorporates the result.
### 3. Governance and honesty
- Skipping a sensor for a cycle is a *deliberate* reduction in coverage; the
scheduler records which sensors were sampled so downstream evidence (ADR-301)
reflects the actual sensing that occurred, and observability (ADR-299) can
raise `UNKNOWN` for a zone that went under-sampled rather than reporting a
stale estimate as current.
### Evidence discipline
- Expected-uncertainty-reduction estimates are model predictions from the
ADR-312 twin (simulation, L0 per ADR-282, `SYNTHETIC`); a scheduling decision
is a resource choice, never a sensing claim.
- Any energy/latency/throughput improvement figure requires real-silicon
measurement with a reproducer before it is tagged `MEASURED` (CLAUDE.md
hardware rule). This ADR asserts **no** efficiency number.
## Consequences
- Edge deployments spend scarce compute, energy, and bandwidth where they buy
the most certainty, making "hundreds of sensors" operationally tractable — a
capability the reviews flagged as critical for edge deployment.
- Quality is bounded by the accuracy of the ADR-312 forward model (informativeness
prediction) and ADR-317 cost descriptors; a poor forward model degrades to
near-round-robin, which is safe but not optimal. The sampling floor bounds the
worst case.
- Hard dependency on ADR-308 (covariance), ADR-312 (forward model), and ADR-317
(cost descriptors), and paired with ADR-306; this ADR builds none of those.
- Being phase 3, this is design intent sitting on the fused world state and is
expected to be revised as ADR-306, ADR-308, ADR-312, and the ADR-317 HAL land.
## Validation
- Unit tests: the value function is a deterministic function of covariance +
forward model + cost descriptors; a sensor predicted to reduce objective
uncertainty more per unit cost ranks above one that reduces it less; the
sampling floor guarantees eventual re-evaluation of a low-value sensor.
- Integration test: on a synthetic multi-sensor scene, the scheduler reduces
objective uncertainty faster per unit modelled cost than round-robin, and
raises ADR-299 UNKNOWN for a deliberately starved zone rather than reporting a
stale estimate.
- Field validation (deferred, real-silicon): energy/latency/throughput on an
instrumented multi-node deployment, reported as `MEASURED` with a reproducer.
Until then all informativeness and cost figures are `SYNTHETIC`/L0. No
efficiency number is asserted by this ADR.
+159
View File
@@ -0,0 +1,159 @@
# ADR-312: Digital RF twin — persistent per-deployment RF model
- **Status**: Proposed (ADR-297 phase 3)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: rf-twin, digital-twin, propagation, calibration, spatial-memory, worldgraph, phase-3
## Context
This ADR is a child of **ADR-297** (perception substrate program) and owns
primitive #15, *digital RF twin*. In the ADR-297 DAG it is a phase-3,
research-forward primitive that underpins several other phase-3 primitives:
**ADR-305** (placement optimizer) plans against the twin's propagation model,
**ADR-310** (counterfactual inference) uses it as the generative forward model,
and **ADR-311** (information-gain scheduler) uses it to predict per-sensor
informativeness. It ties directly to **ADR-298** (calibration), **ADR-305**
(placement), and **ADR-309** (long-term spatial memory). It is authored as
Proposed and is not implemented by the phase-1 swarm.
RuView today has no persistent, per-deployment model of the RF environment.
Calibration state, observed multipath, and radio geometry exist transiently
inside a running session; when the process restarts or a change happens
overnight, there is nothing that says "this is what this room's RF looked like
yesterday." Without a persistent baseline, a physical change — furniture moved,
a wall opened, a machine relocated, an intruder present — has nothing to be a
*delta against*. It is just a different measurement, indistinguishable from
noise or drift.
The **digital RF twin** is that persistent baseline: a per-deployment model
holding
- **geometry and radio locations** (from the ADR-303 scene / worldgraph),
- **propagation history** and **observed multipath** structure,
- **calibration state** (from ADR-298),
- **expected measurement distributions** for each link and phenomenon.
Once the twin exists, a physical change becomes a **measurable delta against the
twin** rather than an unexplained measurement. This is what connects RuView to
facility management (what changed in this space?), security (is there an
unexplained presence?), robotics (has the map drifted?), and industrial
monitoring (did the plant layout change?) — the applications the strategic
assessment named as the value beyond a single detector.
Relevant existing assets to build on rather than duplicate:
- The `worldgraph` crate already models the physical scene — `Room`/`Space`
with `bounds_enu`, `Wall { rf_attenuation_db }`, `Doorway`, `Zone`, and
`Sensor` nodes (ADR-303). The twin *annotates and persists* this scene with RF
state; it does not invent a second geometry.
- `wifi-densepose-calibration` (enrollment, bank, anchor, runtime, specialist)
holds the calibration state the twin persists; the twin references and
versions calibration records, it does not reimplement calibration.
- **ADR-309** (long-term spatial memory, phase 3) is the persistence and
temporal-history substrate; the twin is a *structured occupant* of that
memory, not a separate database.
- **ADR-302** (authenticated identity) and **ADR-292** (provenance) mean the
measurements that update the twin carry verified lineage, so a delta is
attributable rather than anonymous.
## Options considered
1. **No persistent RF model (status quo).** Rejected: every change looks like
noise; nothing supports "what changed since yesterday?", which is the
question the facility/security/industrial applications actually ask.
2. **A full electromagnetic digital twin (per-site ray-tracing / FDTD kept in
sync in real time).** Rejected for the default path: far heavier than the
coarse `rf_attenuation_db` scene RuView actually has and impractical on edge
hardware. A high-fidelity solver is retained as an *optional backend* the
twin can call, not the baseline.
3. **A persistent, per-deployment RF model layered over the ADR-303 scene and
ADR-309 memory: geometry + radio locations + calibration state + observed
multipath + expected measurement distributions, updated by verified
measurements, exposing changes as deltas.** Chosen.
## Decision
Define the **digital RF twin** as a persistent, versioned, per-deployment model
of the RF environment, layered over existing scene, calibration, and memory
assets.
### 1. State the twin holds
- **Geometry and radio locations** referenced from the ADR-303 / worldgraph
scene (not copied).
- **Calibration state** referenced and versioned from
`wifi-densepose-calibration` (ADR-298), so the twin knows *which* calibration
a stored distribution was captured under.
- **Observed multipath and propagation history** — a bounded temporal summary
of per-link channel structure, stored in ADR-309 spatial memory.
- **Expected measurement distributions** per link and phenomenon — the forward
model ADR-305, ADR-310, and ADR-311 consume.
### 2. Update and delta
- Verified measurements (ADR-302 identity, ADR-292 provenance) update the twin's
distributions online, bounded by ADR-298 calibration validity. A new
observation is compared to the twin's expected distribution; the **delta**
and its statistical significance against the twin's own variance — is the
primary output. A change large relative to the twin's modelled variance is a
*detected physical change*, not noise.
- The twin is **versioned**: a calibration event, a deliberate geometry edit, or
an accepted physical change advances the twin version, so history is
auditable and a delta is always relative to a named baseline.
### 3. Consumers
- **ADR-305** queries the twin's propagation model to plan placements.
- **ADR-310** uses the twin's expected distributions as the generative forward
model for hypothesis scoring.
- **ADR-311** uses per-sensor expected informativeness from the twin.
- Facility/security/robotics/industrial integrations read the twin's change
deltas as governed ADR-303 spatial events.
### Evidence discipline
- The twin's expected distributions and any propagation simulation are
**simulation** (evidence level L0 per ADR-282), labelled `SYNTHETIC`. A delta
computed against them is a model-relative statement.
- A change/anomaly detection *claim* (e.g. "detects furniture-scale changes")
requires real-silicon measurement against a leakage-free protocol with a
reproducer before it is tagged `MEASURED` (CLAUDE.md hardware rule). The twin
never presents a modelled expected distribution as evidence that a physical
state *is* the case; it presents a *delta and its significance*. This ADR
asserts **no** detection-accuracy number.
## Consequences
- RuView gains a persistent per-deployment baseline, turning "a different
measurement" into "a measurable, attributable, versioned change" — the bridge
from a sensing runtime to facility management, security, robotics, and
industrial monitoring.
- The twin is the shared forward model for ADR-305/310/311, so those primitives
speak one propagation model rather than three inconsistent ones — a
deliberate reason to build the twin before its consumers mature.
- Quality is bounded by the coarseness of the worldgraph scene and the fidelity
of the forward model; the twin reports deltas *with significance against its
own variance* rather than asserting confident change detection on a coarse
model. The optional high-fidelity backend is where higher accuracy lives.
- Hard dependency on ADR-303 (scene), ADR-298 (calibration state), and ADR-309
(persistence); it reuses `worldgraph` and `wifi-densepose-calibration` rather
than rebuilding geometry or calibration.
- Being phase 3, this is design intent; it is expected to be revised as the
phase-1 spine, ADR-308 fusion, and ADR-309 memory land.
## Validation
- Unit tests: the twin's expected distribution is a deterministic function of
scene + calibration + propagation history; delta computation and its
significance against stored variance are correct on synthetic distributions;
versioning advances on calibration/geometry/accepted-change events and history
is retained.
- Integration test: on a synthetic deployment, an injected physical change (a
wall attenuation shift) produces a significant delta against the twin while
ordinary noise does not; the delta surfaces as a governed ADR-303 event with
provenance (ADR-302/292).
- Field validation (deferred, real-silicon): change detection on an instrumented
real deployment with a controlled physical-change protocol, reported as
`MEASURED` with a reproducer. Until then all twin distributions and deltas are
`SYNTHETIC`/L0. No detection-accuracy number is asserted by this ADR.
+156
View File
@@ -0,0 +1,156 @@
# ADR-313: Fleet control plane — provisioning to audit trails
- **Status**: Proposed (ADR-297 phase 2)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: fleet, operations, provisioning, firmware, updates, audit, identity, phase-2
## Context
This ADR is a child of **ADR-297** (perception substrate program) and owns
primitive #16, *fleet control plane*. In the ADR-297 DAG it is a phase-2
integration-and-operations primitive that sits on the phase-1 spine: it
**consumes ADR-302** (authenticated sensor identity) for per-device identity and
enrollment, and **ADR-315** (capability certificate) for the signed models,
calibration validity, and capability envelopes a device is allowed to run. It is
authored as Proposed and is not implemented by the phase-1 swarm.
The external and internal reviews both named the same operational gap: RuView
has strong per-device primitives but no **release identity** and no **bill of
materials** binding a fielded sensor to the exact firmware, model, and
calibration it is running — and no plane to manage that across many devices.
Without this, a handful of nodes is fine but *hundreds* of sensors become an
operational nightmare: no coherent way to provision, roll certificates, verify
firmware compatibility, distribute signed models, track calibration lifecycle,
watch health, stage updates, roll back, diagnose remotely, enforce data
retention, or produce an audit trail. This ADR addresses that release-identity /
BOM gap directly.
The scope is deliberately the **control plane**, not the data plane. The
authenticated measurement path is **ADR-293** (bind + allowlist) plus **ADR-302**
(signed envelope); this ADR governs the *devices and artifacts*, not the
per-frame stream.
Relevant existing assets to build on rather than duplicate:
- **ADR-302** already defines per-device keypairs, the `DeviceId → public key →
capabilities` enrollment record, key rotation and revocation *semantics* — and
explicitly deferred their **fleet distribution** to this ADR. The control
plane is the distribution and lifecycle layer over ADR-302 identity, not a new
identity scheme.
- **ADR-315** (capability certificate) defines the signed, expiring artifact a
device is authorized to run; the fleet plane is what *distributes, stages, and
revokes* those certificates and the signed models they point at.
- **ADR-298** (calibration) owns calibration validity/expiry; the fleet plane
tracks calibration *lifecycle* across the fleet (which nodes are due, which are
stale) rather than redefining calibration.
- **ADR-316** (witness chain) provides the append-only, re-verifiable record;
fleet audit trails are witness-chain entries, not a parallel log format.
- **ADR-317** (RuView sensor HAL, phase 2) provides hardware/firmware capability
descriptors used for firmware-compatibility checks before staging an update.
- `wifi-densepose-bfld` `CapabilityAttestation` (ADR-141) is the device-side
attestation the plane checks against declared cohort capabilities.
## Options considered
1. **Manual per-device operations (SSH/flash by hand).** Rejected: does not
scale past a handful of nodes, produces no release identity, no audit trail,
and no safe rollback — exactly the operational nightmare the reviews named.
2. **Adopt a generic third-party IoT device-management platform wholesale.**
Rejected as the core: generic platforms do not understand RuView's signed
capability certificate, calibration validity, or witness chain, and would
fork trust away from the phase-1 spine. A generic transport/agent *may* be a
backend, but identity, certificates, and audit remain RuView's.
3. **A RuView-native control plane layered on ADR-302 identity, ADR-315
certificates, ADR-298 calibration lifecycle, and ADR-316 audit — covering
provisioning through rollback and retention.** Chosen.
## Decision
Define a **fleet control plane** that manages RuView sensors and their signed
artifacts across their lifecycle, built on the phase-1 identity/certificate
spine.
### 1. Release identity and bill of materials
- Each fielded device has a **BOM record** binding `DeviceId` (ADR-302) → exact
firmware version → signed model set → active capability certificate (ADR-315)
→ current calibration record (ADR-298) → HAL/hardware descriptor (ADR-317).
This *is* the release identity the reviews found missing: given a device you
can state precisely what it is running and prove it is signed.
### 2. Provisioning, certificates, firmware compatibility
- **Provisioning** is the authorized ADR-302 enrollment step at fleet scale:
minting a keypair, registering the public key and capabilities, and issuing
the initial ADR-315 certificate. A device is untrusted until provisioned.
- **Certificate lifecycle**: issue, rotate, expire, and **revoke** ADR-315
certificates and the ADR-302 keys behind them; revocation lists are
distributed here (the distribution ADR-302 deferred).
- **Firmware compatibility**: before staging a firmware or model, check the
target's ADR-317 HAL descriptor and ADR-141 capability attestation so an
incompatible or under-capable device is never sent an artifact it cannot
honestly run.
### 3. Cohorts, staged updates, rollback
- Devices group into **cohorts** (by site, hardware, capability). Updates —
signed models and firmware — roll out **staged** (canary → cohort → fleet)
with health gates between stages, and **roll back** to the previously recorded
BOM on a failed health check. Only signed artifacts are ever staged.
### 4. Health telemetry, remote diagnostics, retention, audit
- **Health telemetry** and **remote diagnostics** report device liveness,
calibration staleness (ADR-298), certificate expiry (ADR-315), and error
state — read-only diagnostics by default, mutations authorized explicitly.
- **Data retention** policy is enforced per cohort, and P0/CSI/person data never
leaves the edge except under the ADR-277/280 governance already in force
(CLAUDE.md: never commit or exfiltrate CSI/person data).
- Every lifecycle action — provision, rotate, revoke, stage, roll back — is
written as an **ADR-316 witness-chain** entry, giving a re-verifiable **audit
trail** rather than a mutable log.
### Authority and least privilege
- The control plane is default-deny (CLAUDE.md: default to least authority).
Provisioning, key rotation, revocation, staging, and rollback are each
separately authorized operations; no fleet action is implied by another.
Credentials and private keys are never logged or committed.
## Consequences
- Hundreds of sensors become operable: coherent release identity, signed-artifact
distribution, staged updates with rollback, and a re-verifiable audit trail —
closing the release-identity / BOM gap the reviews raised.
- The plane concentrates operational authority; that is mitigated by
default-deny, per-action authorization, signed-only artifacts, and
witness-chained audit. A compromised plane must still forge signatures the
phase-1 spine verifies.
- Hard dependency on ADR-302 (identity), ADR-315 (certificate), ADR-298
(calibration lifecycle), ADR-316 (audit), and ADR-317 (firmware/HAL
compatibility). This ADR distributes and sequences those artifacts; it does
not redefine identity, certificates, calibration, or the witness format.
- Being phase 2, this is design intent depending on the spine; it is expected to
be revised as ADR-315, ADR-316, and ADR-317 land.
- **No fielded fleet-operation claim is MEASURED without real-silicon evidence**
(CLAUDE.md hardware rule): staged update and rollback on real nodes require a
captured runtime log. A passing simulation is not fleet evidence.
## Validation
- Unit tests: BOM records bind identity/firmware/model/certificate/calibration
consistently and reject inconsistent bindings; certificate issue/rotate/revoke
transitions are correct; a firmware-incompatible target is refused staging;
every lifecycle action emits a well-formed ADR-316 witness entry.
- Integration test: a synthetic cohort undergoes a canary→cohort→fleet staged
update; an injected health failure triggers rollback to the prior BOM; the
full sequence is re-verifiable from the witness chain offline; a revoked
certificate is rejected fleet-wide.
- Security test (`npm run test:security` analogue for the plane): default-deny
is enforced; unauthorized provision/rotate/revoke/stage is rejected and
counted; no credential or P0 data appears in telemetry or audit output.
- Field validation (deferred, real-silicon): a real multi-node staged update and
rollback with a captured boot/runtime log, reported as `MEASURED` with a
reproducer. Until then all fleet-operation results are simulator-level. No
fielded reliability number is asserted by this ADR.
@@ -0,0 +1,140 @@
# ADR-314: Multi-domain benchmark scorecard — regressions cannot hide behind pooled accuracy
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: benchmark, aetherarena, ci-gate, evidence, honesty, domain-generalization, substrate
## Context
This ADR is primitive 17 of the perception-substrate program (ADR-297) and the
per-PR enforcement edge of the phase-1 certificate spine. In the ADR-297
dependency DAG it reads accuracy from the evidence engine (ADR-301), consumes
the domain state produced by out-of-distribution detection (ADR-299), scores
against calibration certificates (ADR-298), and is anchored in the witness chain
(ADR-316). It is the surface that makes the rest of the spine testable on every
change to sensing code.
A single pooled accuracy number is the classic way a domain-generalization
regression hides. A model can raise mean PCK or mean presence accuracy while
quietly collapsing on unseen rooms, unseen devices, or stationary subjects —
exactly the conditions WiFi sensing fails in and exactly the conditions a
pooled average washes out. The strategic assessment (ADR-297) named this: what
distinguishes infrastructure from a demo is that a regression on *any* operating
domain is caught before merge, not discovered in the field.
RuView does not need a new benchmark to do this. AetherArena is already
**v0-complete infrastructure** (ADR-149): a deterministic scoring engine
reusing `wifi-densepose-train` (`src/ruview_metrics.rs`, `src/ablation.rs`,
`src/eval.rs`, `src/proof.rs`), a `PROOF_SEED=42` determinism substrate that
SHA-256-hashes outputs against an expected hash, an append-only witness ledger,
and a live Hugging Face Space. ADR-145's ablation harness already computes
presence accuracy, localization error, FP/FN, latency percentiles, a
privacy-leakage score, and **cross-room degradation**. The board is
intentionally empty (benchmark-first). What is missing is not a scorer but a
**scorecard format** that reports per-domain rather than pooled, and a
**sensing-crate CI gate** that runs it on every PR.
## Options considered
1. **Keep the single pooled score / `RuViewTier`.** Rejected: it is exactly the
surface a per-domain regression hides behind; a Gold tier can coexist with a
broken unseen-room slice.
2. **Add a new benchmark repo/harness for domains.** Rejected: AetherArena's
scorer, determinism binding, and witness ledger already exist and are the
right engine; a parallel harness would fork the scoring substrate and its
anti-gaming/leakage discipline.
3. **Extend the AetherArena scorer with a per-domain scorecard and wire it as a
per-PR sensing-crate gate.** Chosen.
## Decision
Reuse the AetherArena scorer and witness ledger (ADR-149) and add two things: a
**multi-domain scorecard** format and a **sensing-crate PR gate** that produces
it.
### 1. The multi-domain scorecard
The scorecard reports each capability broken out by operating domain, never
pooled into one figure. The v0 domain axes:
- **Presence**: `room-known`, `room-unseen`, `device-unseen`, `stationary-10m`
(a stationary subject at range — the canonical WiFi failure case).
- **Pose**: `matched`, `subject-unseen`, `room-unseen`.
- **OOD rejection**: the rate at which genuinely out-of-distribution input is
correctly returned as UNKNOWN by ADR-299 (a capability, not a failure) and
the false-UNKNOWN rate on in-distribution input.
- **Calibration drift**: fingerprint-distance trajectory against the ADR-298
certificate over the scored window, and the fraction of inferences in each
ADR-299 `DomainState` (KNOWN / DEGRADED / UNKNOWN).
Each cell carries exactly one `EvidenceLevel` (L0L5, ADR-282). A slice scored
on synthetic input is L0/`Synthetic` by construction; a slice on a leakage-free
held-out real split is graded higher and only then may a per-domain number be
labelled MEASURED. Pose PCK cells additionally require the mean-pose baseline
and a leakage-free held-out split (CLAUDE.md) or they are not reported as pose
accuracy at all.
### 2. Per-domain regression gate
- The gate compares each scorecard cell against the merged-baseline scorecard
stored in the AetherArena witness ledger. A regression **in any single
domain** beyond its configured threshold fails the PR, even if the pooled
average improved. Improvement on `room-known` cannot buy a regression on
`room-unseen`.
- Thresholds are per-domain and per-capability; the unseen/stationary/OOD
domains carry the strictest budgets because they are the ones a pooled score
hides. The baseline is append-only and witness-anchored — a new baseline is a
new signed ledger entry, never an in-place overwrite (ADR-149 ledger pattern,
ADR-316 anchoring).
### 3. Sensing-crate CI wiring
- Every PR that touches a sensing crate runs the scorecard across all domains
under the ADR-011/ADR-149 determinism binding (`PROOF_SEED=42`), so the run
is reproducible and tamper-evident. The gate is added to
`.github/workflows/` as an authoritative check.
- The held-out real split remains private and is never accessible to synthetic
generation, augmentation, or calibration (ADR-149 leakage constraint, ADR-282
rule d). Submitters/PRs provide a model, not predictions on data they hold.
### Provenance and honesty discipline
- No benchmark numbers are invented by this ADR. It delivers the scorecard
format, the per-domain gate, and the CI wiring; the numbers come from the
ADR-301 evidence ledger and the AetherArena scorer on real data, labelled at
the honest evidence level. Empty domains report "no evidence," which the gate
treats as no coverage — never as a pass.
## Consequences
- A domain-generalization regression can no longer merge behind a flattering
pooled average; the failure mode that most distinguishes fielded sensing from
a demo is caught at PR time.
- Every PR touching sensing pays a per-domain scoring cost. Bounded by reusing
the existing deterministic scorer and by tiered compute (CPU smoke vs full
score, ADR-149), but it is a deliberate cost for per-domain safety.
- The empty AetherArena board fills with honest, per-domain, evidence-labelled
results rather than a single headline tier — consistent with the
benchmark-first posture and with ADR-282's ecosystem positioning.
- Some domains will show weak or absent coverage. Surfacing that per-domain is
the point; the scorecard must never paper over a thin domain with a pooled
number.
- The program-level acceptance test (ADR-297) is encoded here as an AetherArena
scenario, closing the loop once the phase-1 spine lands.
## Validation
- `cargo test` on the AetherArena scorer extension — per-domain slicing math
against fixtures; per-domain regression gate fails on a single-domain
regression while pooled improves, and passes when all domains hold; empty
domains report "no evidence," not a pass; every cell carries exactly one
`EvidenceLevel`; synthetic slices are L0 by construction.
- Determinism: a scored run reproduces its SHA-256 hash under `PROOF_SEED=42`
(ADR-011/ADR-149 binding); the baseline scorecard is append-only and
witness-anchored (ADR-316), never mutated in place.
- CI: the sensing-crate gate runs on a PR touching a sensing crate and blocks a
planted single-domain regression.
- Real-data scorecards (a leakage-free held-out split with ADR-300 references)
are the maturity milestone; a synthetic scorecard is L0 and no per-domain
number is MEASURED without a reproducer per CLAUDE.md.
+138
View File
@@ -0,0 +1,138 @@
# ADR-315: Capability certificates — validated-for-this-environment claims
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: capability, certificate, evidence, provenance, signature, honesty, substrate
## Context
This ADR is primitive 18 of the perception-substrate program (ADR-297) and,
per the strategic assessment, among the strongest ideas in the program: it is
where the whole certificate spine becomes a consumable contract. In the ADR-297
dependency DAG it **consumes the evidence engine (ADR-301)** — a capability
certificate is a signed attestation minted over a slice of that ledger — the
**calibration certificate (ADR-298)** for the environment it is validated
against, and the **RuField signature types (ADR-302 / ADR-260/262/277/279)** to
sign it. It reports domain state via ADR-299 and is anchored in the witness
chain (ADR-316).
RuView must stop making unconditional capability claims. "Supports presence" is
not a true statement — presence detection works in some rooms, on some hardware,
for some subject dynamics, and fails on a stationary subject at range in an
uncalibrated room. A capability is only ever *validated for a specific
environment*, and the honest unit of that claim is a signed, expiring
certificate, not a feature flag in a README.
The ingredients now exist across the phase-1 spine: ADR-301 accumulates
per-`(room, device, subject)` accuracy, false-positive rate, drift, and domain
state; ADR-298 produces the signed room fingerprint the environment is keyed to;
ADR-302 provides the authenticated device identity and `CapabilityAttestation`
(BFLD, ADR-141) that bounds *what a device is even attested to sense*; ADR-282
provides the mandatory `EvidenceLevel`. What is missing is the artifact that
binds them into a single, verifiable "validated here, until then" claim and the
consumer-side rule that refuses capabilities lacking one.
## Options considered
1. **Static capability flags / a `supports_presence` boolean.** Rejected: it is
the exact dishonest claim — environment-independent, unsigned, non-expiring,
and false the moment the room, device, or subject dynamics differ.
2. **Report raw ledger accuracy to consumers directly.** Rejected: the ledger
(ADR-301) is the source of truth but not a portable, signed, bounded contract;
handing consumers raw records pushes evidence-weighting and expiry logic into
every consumer and drops the single verifiable object.
3. **Mint a signed, expiring `CapabilityCertificate` over an ADR-301 ledger
slice, and make consumers refuse capabilities without a valid one.** Chosen.
## Decision
Introduce a signed **`CapabilityCertificate`**: a bounded attestation that a
specific capability has been validated for a specific environment, for a bounded
time.
### 1. The certificate
A serializable `CapabilityCertificate` binding:
- `capability` — the phenomenon (e.g. `presence`, `pose`), which must be within
the device's ADR-302/ADR-141 `CapabilityAttestation` (a device cannot be
certified for something it is not even attested to sense).
- `room` — the ADR-303 space identifier, tied to the ADR-298 calibration
certificate version the validation was performed against.
- `hardware` — the ADR-302 authenticated `DeviceId` (and, in phase 2, the
ADR-317 HAL descriptor of the sensor).
- `model` — the model version scored.
- `calibrated_date` — the calibration certificate age at validation time.
- `moving_recall`, `stationary_recall`, `false_presence_per_24h` — the measured
operating metrics, sliced from the ADR-301 ledger for this exact context (not
a global average), each honestly labelled. These are per-capability; a pose
certificate carries pose metrics with the mean-pose baseline and a
leakage-free split (CLAUDE.md) or it is not issued.
- `valid_until` — an explicit expiry; a certificate is never open-ended.
- `evidence_level` — exactly one L0L5 (ADR-282). A certificate minted from a
synthetic ledger slice is L0/`Synthetic`; a MEASURED metric requires an
ADR-300 reference and a reproducer. The certificate cannot upgrade the level
of the ledger it is minted from (ADR-301 honesty rule).
- `signature` — a RuField `SignatureBlock` (ADR-302 / ADR-260/262/277/279) over
the canonical serialization; an unsigned certificate is not a valid
certificate. The certificate is anchored in the witness chain (ADR-316).
### 2. Minting
- A certificate is minted from a slice of the ADR-301 evidence ledger for one
`(room, device, subject-class, model)` context. If the ledger reports "no
evidence" for that context, **no certificate is issued** — absence of evidence
is never a capability. Minting is a pure function over the append-only ledger
at mint time; the metrics are frozen into the signed object.
- Expiry (`valid_until`) is derived from calibration validity (ADR-298) and an
evidence-freshness policy: a certificate cannot outlive the calibration it was
validated against, and drift beyond the ADR-298 envelope invalidates both.
### 3. Consumer refusal rule
- Applications and surfaces **refuse to consume a capability that lacks a valid
certificate for the current environment**. "Valid" means: signature verifies,
`room`/`hardware`/`model` match the running context, `valid_until` is in the
future, and the referenced calibration certificate is itself still valid
(ADR-298 not invalidated). A failed check yields UNKNOWN via ADR-299, not a
best-effort guess.
- This makes the ADR-297 acceptance clause "quantify whether it can reliably
sense the requested phenomenon → generate a signed capability certificate"
a hard gate rather than a hope.
## Consequences
- RuView can no longer claim a capability it has not validated for the caller's
environment; the honest failure — "not certified here" → UNKNOWN — is
surfaced by construction rather than by discipline.
- OEM/integrator diligence gets a single verifiable artifact ("presence,
validated in *this* room, on *this* device, with *these* recall/false-alarm
numbers, until *this* date, at *this* evidence level, signed") — the strongest
commercial output of the spine.
- Certificates expire and get refused; some environments will have no
certificate and therefore no capability until validated. That refusal is the
intended honest behavior, not a regression.
- Key management and expiry policy are operational responsibilities, reusing the
ADR-302 enrollment/rotation and ADR-298 validity machinery rather than new
infrastructure; fleet distribution of certificates is owned by ADR-313.
- No capability number is invented here; every metric on a certificate is sliced
from the ADR-301 ledger at its honest evidence level.
## Validation
- `cargo test` on the certificate crate — mint from a ledger slice produces the
frozen metrics; "no evidence" context yields no certificate; signature
round-trip and tamper rejection; `valid_until` and calibration-linked expiry
enforced; consumer refusal on room/hardware/model mismatch, expiry, or
invalidated calibration resolves to UNKNOWN (ADR-299), not a guess; evidence
level is inherited from the ledger and cannot be upgraded; a certificate
cannot be issued for a capability outside the device's ADR-302/ADR-141
attestation.
- Cross-ADR: an ADR-301 ledger fixture mints a certificate; an ADR-299 test
asserts an expired/mismatched certificate gates to UNKNOWN; the ADR-297
acceptance test consumes a minted certificate end-to-end.
- Real-deployment certificates (minted from a populated ledger with ADR-300
references on live ESP32 captures) are the maturity milestone and require
hardware evidence per CLAUDE.md; a certificate minted from a synthetic ledger
is L0 by construction.
+146
View File
@@ -0,0 +1,146 @@
# ADR-316: Witness chain — epistemic infrastructure for physical AI
- **Status**: Accepted — initial implementation planned (ADR-297 phase 1)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: provenance, witness, evidence, signature, epistemics, ontology, substrate
## Context
This ADR is primitive 19 of the perception-substrate program (ADR-297) and a
spine root of its phase-1 certificate stack. In the ADR-297 dependency DAG it
**extends the source-provenance state machine (ADR-292)** and the RuField
provenance types, **ties to the signature machinery (ADR-302 /
ADR-260/262/277/279)**, and anchors the artifacts produced by ADR-298
(calibration certificates), ADR-301 (evidence records), ADR-314 (benchmark
scorecards), and ADR-315 (capability certificates). In phase 2 it carries the
independent-corroboration link from ADR-300.
The strategic assessment (ADR-297) framed RuView's real product as **epistemic
infrastructure for physical AI**: the value is not the claim "a person is
present" but the *auditable reasoning* behind it. A bare boolean output discards
everything a downstream system needs to trust or contest it — which radio
observed it, what DSP evidence supported it, which model inferred it, whether an
independent sensor agreed, what spatial state it updated, and what policy acted
on it. Once the answer is a boolean, "why do you believe that?" has no answer.
RuView already has the pieces of a chain but not the chain itself. ADR-292
defines a canonical `SourceState` (`Synthetic` / `LiveVerified` /
`LiveUnverified` / `Stale` / `Disconnected`) with `Unknown` structurally
forbidden from collapsing to live. ADR-302 defines the signed
`device → measurement → sequence → timestamp → … → signed event` chain of
custody. RuField carries `FrameProvenance`, `SemanticProvenance`, and signature
types; the AetherArena witness ledger (ADR-149) demonstrates an append-only,
witness-anchored ledger. What is missing is a single **staged, signed envelope**
that travels the whole pipeline and records, at each stage, the confidence and
provenance of that stage.
## Options considered
1. **Keep provenance as scattered per-stage fields (status quo).** Rejected:
`FrameProvenance`, `SourceState`, calibration state, and model uncertainty
live in different structures and are re-encoded per surface; there is no
single object a consumer can re-verify offline to answer "why."
2. **Log a free-form audit trail alongside the output.** Rejected: mutable,
unsigned, and not structurally tied to the output — the classic
dashboard-that-overwrites-yesterday failure the evidence engine (ADR-301)
already rejects.
3. **A staged, signed witness envelope carried through the pipeline, each stage
appended and signed, anchored in an append-only ledger.** Chosen.
## Decision
Define the **witness chain**: a staged, append-only, signed envelope that
accompanies an observation from radio to policy decision. Instead of emitting
"person present," RuView emits a chain whose stages are:
```
RF observation ▸ DSP evidence ▸ model inference ▸ independent corroboration
▸ spatial state ▸ policy decision
```
### 1. The staged envelope
- Each stage is a signed record carrying its **confidence** and its
**provenance**:
- **RF observation** — the ADR-302 authenticated frame envelope
(`DeviceId`, sequence, timestamp, measurement hash) and its ADR-292
`SourceState`. This is the root link; a `Synthetic` root can never present
as a `LiveVerified` one (ADR-292 invariant).
- **DSP evidence** — the deterministic signal features and the ADR-137
quality signals that support (or fail to support) an inference.
- **model inference** — the model version, its raw output, and its predictive
uncertainty; the ADR-299 `DomainState` (KNOWN / DEGRADED / UNKNOWN) gate
result, so a low-confidence or out-of-distribution inference is recorded as
such, not silently promoted.
- **independent corroboration** — the phase-2 ADR-300 agreement link
(a reference/second modality that agreed or disagreed); absent in phase 1,
the stage records "no corroboration," never a fabricated one.
- **spatial state** — the ADR-303 ontology `Observation`/`Track`/`Event` the
inference updated, carrying `SemanticProvenance` and its `EvidenceLevel`.
- **policy decision** — the governed action taken (or withheld), with the
certificate (ADR-315) it relied on.
- Each stage carries exactly one `EvidenceLevel` (L0L5, ADR-282); the envelope's
effective level is the **minimum** across its stages — a synthetic root or an
unreferenced inference caps the whole chain, so the chain cannot claim more
than its weakest link.
### 2. Signing and anchoring
- Each stage is signed with RuField signature types (ADR-302 /
ADR-260/262/277/279) over the canonical serialization of that stage plus the
hash of the prior stage, so the chain is tamper-evident end to end and any
broken link is detectable. The completed chain is anchored in an append-only,
witness-anchored ledger following the AetherArena pattern (ADR-149); it is the
same anchoring ADR-298/ADR-301/ADR-314/ADR-315 write into.
- The chain is **append-only**: a correction is a new chain referencing the
prior one, never an in-place edit (mirroring ADR-301 and CLAUDE.md's "source
over summaries").
### 3. Offline re-verification
- A consumer with the enrolled public keys (ADR-302) can re-verify a chain
offline: check each stage signature, check each prior-stage hash, and read the
per-stage confidence and evidence level — answering "why do you believe this?"
without trusting the emitting host. This is the property store-and-forward
channel authentication (rejected in ADR-302) cannot provide.
### Provenance and honesty discipline
- The witness chain never manufactures confidence: a stage that lacks evidence
records the absence. A `Synthetic` root, a missing corroboration, or an
UNKNOWN gate is carried faithfully and caps the chain's evidence level. No
accuracy number is invented here; the chain records the numbers the other
primitives produce at their honest level.
## Consequences
- Every RuView output becomes contestable and auditable: a downstream physical-AI
system can inspect the reasoning, weight it by per-stage confidence, and reject
a chain whose weakest link is too weak — the defining property of epistemic
infrastructure the strategic assessment asked for.
- The certificate spine (ADR-298/301/314/315) gains a single anchoring substrate;
each of those artifacts is a specialization of a witness record rather than a
bespoke signed blob.
- Carrying and signing a staged envelope adds per-observation size and CPU cost;
bounded by reusing RuField signatures and the existing ledger, and by the
minimum-level rule keeping the object honest rather than exhaustive.
- The chain will frequently reveal weak links (synthetic root, no corroboration,
DEGRADED gate). Surfacing that is the point; the envelope must never smooth a
weak stage into a confident summary.
## Validation
- `cargo test` on the witness-chain crate — stage-by-stage signature round-trip
and tamper rejection (a mutated stage or a broken prior-stage hash fails
verification); effective evidence level equals the minimum across stages; a
`Synthetic` root caps the chain and cannot present as `LiveVerified`
(ADR-292 invariant); an UNKNOWN gate (ADR-299) and a "no corroboration" stage
are recorded faithfully; append-only correction produces a new chain
referencing the prior one.
- Cross-ADR: an ADR-302 signed frame lineage serializes into a chain that
re-verifies offline with only the enrolled public keys; ADR-298/301/314/315
artifacts anchor into the same ledger.
- Real-deployment chains (from live ESP32 captures with ADR-300 corroboration)
are the maturity milestone and require hardware evidence per CLAUDE.md; a
chain rooted in synthetic input is L0 by construction.
+150
View File
@@ -0,0 +1,150 @@
# ADR-317: RuView sensor HAL — abstract all sensing hardware to one Observation type
- **Status**: Proposed (ADR-297 phase 2)
- **Date**: 2026-08-11
- **Deciders**: ruv
- **Tags**: hal, sensor-abstraction, ontology, fusion, adapters, category, phase-2
## Context
This ADR is primitive 20 of the perception-substrate program (ADR-297) and a
phase-2 integration primitive; it is authored as **Proposed**. In the ADR-297
DAG it **consumes the canonical spatial ontology (ADR-303)** — its output is an
ontology `Observation` bound to a `Sensor` entity — and **feeds real sensor
fusion (ADR-308)**, which resolves many observations into one world state. It
closes the "identify the hardware" clause of the ADR-297 acceptance test that
phase 1 leaves open.
RuView's strategic ceiling is set by how tightly it is coupled to WiFi CSI.
Every new modality today lands as a bespoke ingest path with its own frame
shape, its own provenance handling, and its own place in the pipeline. That is
the difference between "a WiFi-DensePose project" and "an open
spatial-intelligence operating layer": the category changes the moment *any*
sensing hardware — {CSI, 802.11bf, BLE, UWB, mmWave, acoustic, camera, lidar,
IMU, custom} — enters through one abstraction and becomes one `Observation`
feeding one world model.
Crucially this is a *unification*, not a green field. Adapters already exist and
must be reused, not rebuilt:
- ADR-279's native RF frame contract (`RfFrameV2`) already unifies ESP32,
Intel, Atheros, PicoScenes, Realtek radar, and 320 MHz 802.11bk producers as
`RfFrameV2` producers into a shared latent — "lightweight per-device adapters
into a shared latent, not a shared tensor." The HAL generalizes that lesson
beyond RF.
- Existing CSI adapters (ESP32/Nexmon/FeitCSI paths), the mmWave fusion path
(ADR-063), and the multistatic WiFi path (ADR-029) are concrete producers to
bring under one trait.
- ADR-302 already authenticates a `Sensor`/`DeviceId`; ADR-303 already defines
`Sensor`, `Observation`, `Track`, and `Event` as first-class node types. The
HAL is the trait that turns a heterogeneous device into that authenticated
`Sensor` emitting those `Observation`s.
The gap is a single **`SensorHal` trait and one `Observation` type** that every
modality implements, so the world model never sees a modality-specific frame —
only a provenance-bearing, evidence-labelled `Observation`.
## Options considered
1. **Continue adding per-modality ingest paths.** Rejected: O(modalities) bespoke
pipelines, each re-encoding provenance and evidence, each a place the ladder
can be dropped — and it keeps RuView categorically a WiFi project.
2. **Force every modality into the ADR-274/279 RF tensor/frame.** Rejected: the
ADR-279 lesson is precisely that premature canonicalization discards
information (bandwidth, antenna structure, phase). A camera, lidar, or IMU
has no meaningful `RfFrameV2` projection; forcing one is the same mistake at a
larger scale.
3. **Define a `SensorHal` trait producing one `Observation` type, with existing
adapters as implementations feeding a shared latent and the ADR-303
ontology.** Chosen.
## Decision
Introduce a **`SensorHal` trait** and a single **`Observation`** type. Every
sensing modality is an implementation of the trait; the world model consumes
only `Observation`s.
### 1. The `SensorHal` trait
- A `SensorHal` describes a device's **capabilities** (which phenomena it can
sense — reusing the ADR-302/ADR-141 `CapabilityAttestation`), its **native
frame** (kept native, not canonicalized, per the ADR-279 shared-latent
lesson), and a method that lifts a native frame into an `Observation`.
- Implementations wrap the existing producers: CSI (ESP32/Nexmon/FeitCSI via the
ADR-279 `RfFrameV2` path), 802.11bf (ADR-307, phase 2), BLE, UWB, mmWave
(ADR-063), acoustic, camera, lidar, IMU, and `custom`. RF modalities reuse the
ADR-279 per-device latent adapters wholesale; the HAL adds the non-RF and
ranging modalities under the same trait.
- The trait is the boundary where untrusted hardware input is validated
(CLAUDE.md: validate at every hardware/FFI boundary; default to least
authority). A device is authenticated as an ADR-302 `Sensor` before its
observations are trusted.
### 2. The `Observation` type
- One provenance-bearing `Observation`: a measurement plus its `SensorHal`
source descriptor, its ADR-302 authenticated `DeviceId`, its ADR-292
`SourceState`, its native-frame reference (not a lossy projection), and
exactly one `EvidenceLevel` (L0L5, ADR-282). A camera-derived `Observation`
and a CSI-derived `Observation` are the same type with different provenance —
and a camera observation never lifts WiFi output to camera-grade; each carries
its own honest evidence level (CLAUDE.md: never present WiFi sensing as
camera-grade).
- The `Observation` maps directly onto the ADR-303 ontology `Observation` node
attached to its `Sensor`, so the ontology is the one representation and the
HAL is its ingest funnel.
### 3. Feeding fusion
- Observations from any set of modalities flow into ADR-308 fusion, which
resolves them into one probabilistic world state. The HAL guarantees fusion
never sees a modality-specific frame — only `Observation`s with uniform
provenance and evidence — which is what makes ADR-308's "many observations →
one world state" invariant implementable across heterogeneous hardware.
### Category and honesty discipline
- This ADR changes RuView's category from a WiFi-DensePose pipeline to an open
spatial-intelligence operating layer, but it makes **no accuracy claim**: the
HAL delivers a uniform ingest boundary, not a detector. Any capability of a
newly-connected sensor is still gated by ADR-299 and certified by ADR-315 for
its specific environment — connecting a camera does not grant a validated
capability by itself.
- Hardware support for a given modality is CLAIMED until demonstrated on real
silicon with captured evidence per CLAUDE.md; a passing trait test proves the
abstraction, not a fielded device.
## Consequences
- New sensing hardware lands as one `SensorHal` implementation instead of a
bespoke pipeline; the translation matrix stays O(modalities), mirroring how
ADR-303 collapsed the surface matrix.
- The ADR-297 acceptance clause "identify the hardware" becomes implementable:
a new sensor type is described by its HAL, authenticated as an ADR-302
`Sensor`, calibrated (ADR-298), gated (ADR-299), and certified (ADR-315)
through the same phase-1 spine, closing the last open clause.
- A trait boundary and an `Observation` type are added; existing RF adapters
are re-expressed as implementations rather than rewritten, preserving the
ADR-279 native-frame/shared-latent design.
- Non-RF modalities (camera, lidar, acoustic) enter the governed plane with the
same provenance and privacy discipline as RF; a camera is not a privacy-free
shortcut — it inherits the ADR-277 governance and its own evidence level.
- As a phase-2 Proposed ADR, the trait shape may be revised as ADR-308 fusion
and ADR-307 802.11bf land; that revision is expected for a phased program.
## Validation
- `cargo test` on the HAL crate (design-time, Proposed) — a fixture `SensorHal`
for each of at least two modalities (CSI via ADR-279, plus one non-RF)
produces uniform `Observation`s; every `Observation` carries a `DeviceId`,
`SourceState`, native-frame reference, and exactly one `EvidenceLevel`; a
synthetic source yields L0/`Synthetic` and cannot alias to measured
(ADR-279 invariant 6); an unauthenticated device's observations are rejected
at the trait boundary (ADR-302).
- Cross-ADR: an `Observation` maps round-trip to an ADR-303 ontology
`Observation` node with no provenance loss, and a set of `Observation`s from
distinct modalities is accepted by an ADR-308 fusion fixture.
- Real-silicon evidence is required before any modality's hardware support is
claimed beyond CLAIMED: a captured boot/runtime log from the real device
emitting `Observation`s. A successful build or simulator run is not hardware
evidence (CLAUDE.md).
+20
View File
@@ -155,6 +155,26 @@ Statuses: **Proposed** (under discussion), **Accepted** (approved and/or impleme
| [ADR-295](ADR-295-model-release-sanity-gates.md) | Model release sanity gates — block degenerate and mislabeled model artifacts | Accepted (initial implementation) |
| [ADR-296](ADR-296-csi-data-incident-repo-controls.md) | Repository CSI data-incident controls — ignore rules and pre-commit/CI policy check | Accepted (controls implemented; tree remediation gated) |
| [ADR-297](ADR-297-perception-substrate-program.md) | RuView perception substrate — phased 20-primitive program (calibration, evidence, trust, deployment) | Accepted (program; children ADR-298..317) |
| [ADR-298](ADR-298-automatic-domain-calibration.md) | Automatic domain calibration — signed, versioned, invalidatable room fingerprint | Accepted (phase 1) |
| [ADR-299](ADR-299-out-of-distribution-detection.md) | Out-of-distribution detection — KNOWN / DEGRADED / UNKNOWN gating | Accepted (phase 1) |
| [ADR-300](ADR-300-ground-truth-synchronization.md) | Ground-truth synchronization — reference sensors as a formal validation plane | Proposed (phase 2) |
| [ADR-301](ADR-301-evidence-engine.md) | Evidence engine — per-(room,device,subject) accuracy ledger | Accepted (phase 1) |
| [ADR-302](ADR-302-authenticated-sensor-identity.md) | Authenticated sensor identity — RF chain of custody | Accepted (phase 1) |
| [ADR-303](ADR-303-canonical-spatial-ontology.md) | Canonical spatial ontology — one Site→…→Event model for every surface | Accepted (phase 1) |
| [ADR-304](ADR-304-persistent-identity-tracking.md) | Persistent identity & tracking — privacy-preserving probabilistic tracks | Proposed (phase 2) |
| [ADR-305](ADR-305-sensor-placement-optimizer.md) | Sensor placement optimizer — floorplan + inventory → recommended positions | Proposed (phase 3) |
| [ADR-306](ADR-306-active-sensing.md) | Active sensing — closed-loop RF experiment control | Proposed (phase 3) |
| [ADR-307](ADR-307-80211bf-native-architecture.md) | 802.11bf-native architecture — standardized WLAN sensing as native measurement types | Proposed (phase 2) |
| [ADR-308](ADR-308-real-sensor-fusion.md) | Real sensor fusion — uncertainty-aware, multiple observations → one world state | Proposed (phase 2) |
| [ADR-309](ADR-309-long-term-spatial-memory.md) | Long-term spatial memory — learn the normal physics of a location | Proposed (phase 3) |
| [ADR-310](ADR-310-counterfactual-inference.md) | Counterfactual inference — generative spatial reasoning | Proposed (phase 3) |
| [ADR-311](ADR-311-information-gain-scheduler.md) | Information-gain scheduler — sample the most informative radios | Proposed (phase 3) |
| [ADR-312](ADR-312-digital-rf-twin.md) | Digital RF twin — persistent per-deployment RF model | Proposed (phase 3) |
| [ADR-313](ADR-313-fleet-control-plane.md) | Fleet control plane — provisioning to audit trails | Proposed (phase 2) |
| [ADR-314](ADR-314-benchmark-multi-domain-scorecard.md) | Multi-domain benchmark scorecard — regressions cannot hide behind pooled accuracy | Accepted (phase 1) |
| [ADR-315](ADR-315-capability-certificates.md) | Capability certificates — validated-for-this-environment claims | Accepted (phase 1) |
| [ADR-316](ADR-316-witness-chain.md) | Witness chain — staged, signed epistemic envelope | Accepted (phase 1) |
| [ADR-317](ADR-317-sensor-hal.md) | RuView sensor HAL — abstract all sensing hardware to one Observation type | Proposed (phase 2) |
---