Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
acddd77
Add gated active evidence loop, KGE proposals and predictive CSI expe…
ruvnet Oct 13, 2026
5a97ebe
Add frozen predictive transfer experiment and record failed utility gate
ruvnet Oct 13, 2026
721a094
Add independent confirmation metadata preflight and adversarial tests
ruvnet Oct 13, 2026
606de9f
Bind CSI intake checks to file descriptors and enforce actual byte bu…
ruvnet Oct 13, 2026
47589e0
Add bounded Zenodo CSI sample intake and native format diagnostics
ruvnet Oct 13, 2026
34eb522
Add streaming whole-recording CSI quality diagnostics
ruvnet Oct 13, 2026
93538be
Locate CSI coverage minima by frame and native antenna
ruvnet Oct 13, 2026
4a893e4
Update quinn-proto to remediate Rust advisories
ruvnet Oct 13, 2026
8c77729
Add Windows and Android dependency checks
ruvnet Oct 13, 2026
464cc3b
Enforce hash-pinned confirmation training gate
ruvnet Oct 13, 2026
accaf7f
Exercise confirmation hash mismatch path
ruvnet Oct 13, 2026
4a6e76b
Bind confirmation plans to dataset records
ruvnet Oct 13, 2026
8ee9978
Reject changed manifests before dataset decode
ruvnet Oct 13, 2026
353c3ed
fix(training): bind confirmed NPZ decode to one descriptor
ruvnet Oct 13, 2026
ac9ea02
security: snapshot confirmed CSI bundles before decode
ruvnet Oct 13, 2026
b47c165
security: cap confirmed CSI snapshots at 200 MB
ruvnet Oct 13, 2026
0d790ef
security: pin inference artifact descriptors
ruvnet Oct 13, 2026
b710fdb
docs: clarify bounded artifact read
ruvnet Oct 13, 2026
2f6191b
security: detect inference artifact mutation
ruvnet Oct 13, 2026
d3586c9
security: pin inference artifact directory
ruvnet Oct 13, 2026
8282a6b
security: bind inference artifact generations
ruvnet Oct 13, 2026
56b0085
fix(training): bind compact parent lineage to validated bytes
ruvnet Oct 13, 2026
9fe3207
feat(evaluation): gate transition behavior
ruvnet Oct 13, 2026
20a0f65
feat(evaluation): enforce overall gate in CLI
ruvnet Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/csi-encoder-training.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ on:
paths:
- 'scripts/csi_training/**'
- 'scripts/field-context-probe/**'
- 'scripts/active-kge/**'
- 'scripts/pretrain-csi-predictive.py'
- 'scripts/pretrain-csi-transfer.py'
- 'scripts/benchmark-csi-intake.py'
- 'scripts/evaluate-active-evidence.py'
- 'scripts/verify-active-replay.py'
- 'scripts/train-csi-encoder.py'
- 'scripts/train-espfi.py'
- 'scripts/improve-espfi.py'
Expand All @@ -13,6 +19,7 @@ on:
- 'scripts/requirements-espfi-training.txt'
- 'scripts/requirements-espfi-inference.txt'
- 'scripts/requirements-csi-training.txt'
- 'scripts/requirements-zenodo-intake.txt'
- 'scripts/tests/test_csi_training*.py'
- 'scripts/tests/test_espfi*.py'
- '.github/workflows/csi-encoder-training.yml'
Expand All @@ -37,6 +44,7 @@ jobs:
python -m pip install torch==2.11.0 --index-url https://download.pytorch.org/whl/cpu
python -m pip install -r scripts/requirements-csi-training.txt
python -m pip install -r scripts/requirements-espfi-training.txt
python -m pip install -r scripts/requirements-zenodo-intake.txt
- name: Validate real training code using temporary synthetic data
env:
PYTHONPATH: scripts
Expand Down Expand Up @@ -76,3 +84,30 @@ jobs:
run: cargo +1.90.0 test --locked
- name: Exercise synthetic evidence pipeline
run: cargo +1.90.0 run --locked --quiet --bin ruview-field-context-probe
- name: Exercise active evidence lifecycle
run: cargo +1.90.0 run --locked --quiet --bin ruview-field-context-probe -- --active-loop

active-kge-contract:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: '22'
- name: Install exact KGE experiment dependency
working-directory: scripts/active-kge
run: npm ci --ignore-scripts --no-audit --no-fund
- name: Validate actual trained KGE and bounded artifact contract
working-directory: scripts/active-kge
run: npm test
- name: Install fixed Rust toolchain
run: rustup toolchain install 1.90.0 --profile minimal
- name: Feed actual KGE proposals through Rust authority boundary
run: |
node scripts/active-kge/cli.mjs --train "$RUNNER_TEMP/kge" --context context_1_8 > "$RUNNER_TEMP/ranking.json"
cargo +1.90.0 run --locked --quiet --manifest-path scripts/field-context-probe/Cargo.toml -- --active-loop > "$RUNNER_TEMP/reference.json"
cargo +1.90.0 run --locked --quiet --manifest-path scripts/field-context-probe/Cargo.toml -- --active-loop --ranking "$RUNNER_TEMP/ranking.json" > "$RUNNER_TEMP/candidate.json"
python scripts/verify-active-replay.py "$RUNNER_TEMP/reference.json" "$RUNNER_TEMP/candidate.json"
73 changes: 73 additions & 0 deletions .github/workflows/rust-cross-target.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Rust cross-target dependency check

on:
push:
branches: [main, develop, 'feature/*', 'feat/*', 'hotfix/*']
paths:
- 'v2/Cargo.lock'
- 'v2/Cargo.toml'
- 'v2/rust-toolchain.toml'
- 'v2/crates/wifi-densepose-hardware/**'
- '.github/workflows/rust-cross-target.yml'
pull_request:
branches: [main, develop]
paths:
- 'v2/Cargo.lock'
- 'v2/Cargo.toml'
- 'v2/rust-toolchain.toml'
- 'v2/crates/wifi-densepose-hardware/**'
- '.github/workflows/rust-cross-target.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
dependency-path:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- name: Windows MSVC dependency path
os: windows-2025
target: x86_64-pc-windows-msvc
- name: Android ARM64 dependency path
os: ubuntu-24.04
target: aarch64-linux-android
steps:
- name: Checkout code and path dependencies
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
persist-credentials: false
submodules: recursive

- name: Install fixed Rust toolchain and target
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4
with:
toolchain: 1.89.0
targets: ${{ matrix.target }}

- name: Configure the preinstalled Android NDK linker
if: matrix.target == 'aarch64-linux-android'
shell: bash
run: |
ndk_bin="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
linker="$ndk_bin/aarch64-linux-android24-clang"
archiver="$ndk_bin/llvm-ar"
ranlib="$ndk_bin/llvm-ranlib"
test -x "$linker"
test -x "$archiver"
test -x "$ranlib"
echo "$ndk_bin" >> "$GITHUB_PATH"
echo "CC_aarch64_linux_android=$linker" >> "$GITHUB_ENV"
echo "AR_aarch64_linux_android=$archiver" >> "$GITHUB_ENV"
echo "RANLIB_aarch64_linux_android=$ranlib" >> "$GITHUB_ENV"
echo "CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$linker" >> "$GITHUB_ENV"
echo "CARGO_TARGET_AARCH64_LINUX_ANDROID_AR=$archiver" >> "$GITHUB_ENV"

- name: Check hardware transport dependency path
working-directory: v2
run: cargo +1.89.0 check --locked -p wifi-densepose-hardware --lib --target ${{ matrix.target }}
176 changes: 176 additions & 0 deletions docs/active-evidence-experiment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# Active evidence, KGE proposals and predictive CSI experiment

Research implementation, measured on October 13, 2026 UTC. No field accuracy or
production readiness claim. Keep the existing sensing runtime and model defaults.

## Implemented outcome

The actual pinned RuField and WorldGraph libraries now run an authored sequence
that transitions through empty, occupied, unknown, occupied and unknown. A
conflicting observation creates uncertainty. Expired observations cannot keep an
occupancy belief alive. Historical graph nodes remain provenance, not a current
occupancy API. Repeated, derived, invalid, stale or future evidence is rejected.

The separately trained actual `@ruvector/kge` package emits bounded ranking JSON.
Rust accepts only three registered logical sensor names and finite scores. It
reserves an authored packet, airtime and energy budget for proposals, never
actuates. An integrated verifier compares the default and KGE replays and requires
identical evidence and belief fields. Only the proposal can differ.

The logical radar and door sources currently use signed WiFi feature fixtures to
exercise the pinned rule. They are not implemented physical radar or door
drivers. All replay observations, costs, relevance labels and thresholds are
SYNTHETIC. KGE scores and fusion heuristics are not calibrated probabilities.

## Decisions

* [ADR 421: evidence lifecycle](adr/ADR-421-active-evidence-loop.md)
* [ADR 422: KGE proposal authority](adr/ADR-422-kge-measurement-proposals.md)
* [ADR 423: predictive representation experiment](adr/ADR-423-predictive-csi-representation-experiment.md)

## Measured results

| Experiment | Result | Decision |
| --- | --- | --- |
| Rust active loop, three rounds of 1,000 alternating pairs | Median 0.0771 to 0.0853 ms; p95 0.1187 to 0.1377 ms | Retain bounded research implementation |
| Added Rust cost over signed single root fusion | Paired extra p95 0.0412 to 0.0576 ms | Small measured software overhead, no sensing benefit claim |
| Actual KGE, six authored held out target links | Hits@1 6/6; frequency and shuffled graph controls 2/6 each | Retain synthetic integration test, not real utility evidence |
| KGE reference ranking, three rounds of 1,000 calls | Median 0.0345 to 0.0349 ms; p95 0.0506 to 0.0577 ms | Retain original default |
| Cached KGE validation experiment | Fails lower median and p95 in every round gate | Reject optimization; preserve initial failure receipt |
| Predictive CSI, fixed five epochs on original training data only | Latent MSE 0.9740 versus global constant 0.9413 | Reject utility/promotion claim |
| Predictive frozen encoder timing | Median 0.919 to 1.175 ms; p95 1.326 to 1.478 ms | Timing only; not a sensing model improvement |

Rust and Python ran on the existing ruOS Linux x86_64 AMD EPYC environment.
Rust 1.90.0 used the release profile and exact existing lockfile. Python used
Torch 2.11.0+cpu and NumPy 2.4.4 with one compute thread. Node KGE ran separately
on local Linux x64 Node 24.19.0, native backend. Do not add these timings to claim
a measured end to end latency across machines. Rust excludes signing, acquisition,
ranking transport and hardware. KGE excludes training and loading. Encoder timing
includes input validation, log normalization, token encoding and pooling but
excludes acquisition and file loading. This is not ESP32 timing or peak RAM.

The predictive experiment fit 280 recordings and evaluated 139 inner development
recordings from the original training partition. The remaining 418 training
recordings were unused. No original validation or final test arrays were decoded.
These development groups have been reused in previous research and are not a new
independent confirmation set. Training took 7.34 seconds in the recorded scope.
The same final teacher targets and masks were used for every loss comparator:
untrained 1.1399, global constant 0.9413, per position constant 1.0487, trained
0.9740. Effective recording rank was 1.4055 and triggered the collapse warning.
Reloaded embeddings were bit identical. A loss improvement against an untrained
network is insufficient when a constant predictor performs better.

No candidate from this experiment replaces the activity classifier, the published
eight feature encoder or any production model. No paid compute or hardware
operation was performed. Existing ruOS CPU resources were used.

## Reproduce the software acceptance test

From the repository root, with Node, Python and Rust 1.90.0 installed:

```sh
cd scripts/active-kge
npm ci --ignore-scripts --no-audit --no-fund
npm test
cd ../..
cargo +1.90.0 test --locked --manifest-path scripts/field-context-probe/Cargo.toml
node scripts/active-kge/cli.mjs --train /tmp/ruview-kge-new --context context_1_8 > /tmp/ruview-ranking.json
cargo +1.90.0 run --release --locked --manifest-path scripts/field-context-probe/Cargo.toml -- --active-loop > /tmp/ruview-reference.json
cargo +1.90.0 run --release --locked --manifest-path scripts/field-context-probe/Cargo.toml -- --active-loop --ranking /tmp/ruview-ranking.json > /tmp/ruview-candidate.json
python scripts/verify-active-replay.py /tmp/ruview-reference.json /tmp/ruview-candidate.json
```

Use a new output directory for each KGE training run. The Linux file reader
supports x86_64 and AArch64; other platforms must explicitly supply ranking JSON
on stdin using `--ranking -`. Built replay executables perform no network or
hardware activity. Initial npm/Cargo installation requires package access.

Python training requires `scripts/requirements-csi-training.txt`. Run:

```sh
PYTHONPATH=scripts OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 python -m unittest discover -s scripts/tests -p 'test_csi_training*.py' -q
python scripts/pretrain-csi-predictive.py --synthetic --output /tmp/ruview-predictive-new --epochs 5 --max-seconds 120
```

For the public run, replace `--synthetic` with `--manifest` pointing to the
existing ADR 420 verified prepared manifest, with five sample temporal pooling.
Do not reinterpret different input axes or change splits to obtain a favorable
result. See [predictive harness contract](../scripts/csi_training/PREDICTIVE.md).

## Validation and security

The completed focused suites passed 41 Python tests, 14 Rust tests and 5 KGE
tests. The integrated replay verifier passed. An independent review found no
remaining source blocker after fixes. The first remote Python run lacked the
unchanged collector helper; restoring that test dependency produced the passing
run. A KGE test initially depended on the current directory; its CLI path now
resolves relative to the test file and passes from the repository root.

| Boundary | Check and residual limit |
| --- | --- |
| Observation admission | Signature, unique root/hash, monotonic source and application clocks, explicit expiry, derived root rejection; public fixture keys are not production enrollment |
| Rejected observation | Does not advance the accepted clock or mutate the graph; exhausted capacity intentionally sets a sticky safety state |
| Ranking file | Open once with nofollow and nonblocking flags, validate the opened regular descriptor, bound bytes, reject duplicate JSON keys, unknown fields and nonfinite scores |
| KGE artifact | Bound file reads and native dimensions; exact authored vocabulary, relations, indexed triples, training splits and training receipt binding; checksums are not signer authentication |
| Predictive artifact | Bound descriptor reads, strict JSON, exact finite tensor shape/dtype checks, safetensors, source hash before/after and reload parity; local artifact trust still required |
| Authority | No hardware, network endpoint or executable supplied by ranking; proposals cannot modify roots or promote models |
| Evaluation | Unknown counts as an occupied miss; separate unknown coverage limits prevent abstention from manufacturing gains; bootstrap by room |

Scoped npm audit of the exact KGE lockfile returned zero reported vulnerabilities
on October 13, 2026 UTC. This is not a security audit of all RuView dependencies,
the native binary internals or external device firmware. Rust pins and its lockfile
were unchanged. No fresh Rust advisory database audit was performed.

## Field measurement contract

`python scripts/evaluate-active-evidence.py /path/to/aligned-intervals.json`
computes aggregate duration metrics and seeded room clustered percentile
intervals. It accepts schema version 1, declared evidence, and sessions with
room/session IDs, matching baseline/candidate packets, airtime, energy and sensor
availability, and contiguous aligned intervals with independently supplied empty
or occupied truth plus empty/occupied/unknown predictions. Input is a bounded
regular JSON file. See `test_csi_training_active_evaluation.py` for the minimal
synthetic input generator.

The default CLI remains report-only for interactive analysis. Automation can add
`--require-pass`: a valid report still prints in full, then exits 3 when
`overallGate` is `fail` or `inconclusive`; a passing report exits 0 and malformed
input exits 2. This process status enforces only the frozen software gate. It does
not change `fieldAcceptance`, authorize promotion or authenticate supplied labels.

The numerical gate requires at least 20% lower false occupied duration, a 95%
room clustered interval supporting reduction, recall delta lower bound at least
minus one percentage point, and unknown duration delta upper bound at most one
percentage point separately for empty and occupied intervals. Zero baseline
false alarms or inadequate bootstrap exposure produce inconclusive results.
Two rooms are a computational minimum, not a claim of sufficient statistical
power. Pilot data must size a separate confirmation study.

Labels, actual costs, fresh splits and capture completeness require independent
verification. Consequently even a numerical pass always returns
`fieldAcceptance: not_established` and `promotionAuthorized: false`. The paired
transition gate requires empty-to-occupied and occupied-to-empty events in at
least two rooms. Room-clustered upper confidence bounds must show no increase in
interval-aligned delay, unresolved transitions or false-occupied episodes per
empty hour. Unknown predictions extend delay; a transition that never resolves
within its truth run is retained with that run's full duration. `overallGate`
passes only when both duration and transition gates pass. Stationary occupant
sensitivity and sub-interval acquisition latency still require field analysis.
Replay cannot compare an action for which no eligible measurement was captured.

## Receipts and rollback

Receipts contain aggregate results and hashes, not captures or learned tensors:

* `validation/active-loop-benchmark-20261013.json`
* `validation/active-kge-field-replay-20261013.json`
* `validation/active-kge-20261013.json`
* `validation/active-kge-cache-rejected-20261013.json`
* `validation/active-predictive-public-20261013.json`
* `validation/active-evidence-verification-20261013.json`

Rollback is removal of the isolated experiment and its CI additions. Existing
production paths and published weights are unchanged. The next useful investment
is independently annotated continuous capture, followed by frozen room/session
confirmation and an inductive sensor utility experiment, not promotion of the
rejected predictive checkpoint.
Loading
Loading