mirror of
https://github.com/ruvnet/RuView
synced 2026-08-11 20:41:44 +00:00
Add per-deployment adaptive optimization + VEIL npm metaharness (ADR-289)
Two additions on top of the hyper-optimized VEIL shield.
1) Adaptive optimization (v2/crates/wifi-densepose-privshield/src/optimize.rs):
- optimal_bits_across_snr / model_optimal_bits_for_snr: the throughput-
optimal feedback resolution shifts with SNR (unconstrained optimum 4 bits
at 5-10 dB, 3 bits at 20-40 dB); within the spec {5,7,9} set it stays 5,
which is why the shipped shield is SNR-stable.
- adaptive_shield / min_passes_for_n: derive a shield for a specific
deployment. Finding: the collapse budget is N-independent in this model
(48 passes collapses N in {8,64} alike) — it is set by the fine-subspace
dimension, not the candidate count. Defaults unchanged, so the proof
witness is untouched. 38 tests + doctest pass; clippy -D warnings clean.
2) npm metaharness harness/wifi-densepose-privshield/ (ADR-289), mirroring
wifi-densepose-sar-harness (ADR-286) with two improvements:
- @metaharness/* imported dynamically inside the commands that need them, so
`guidance` and `--help` run with ZERO dependencies installed (offline / pre
`npm install`).
- a dependency-free VEIL `guidance` command: a source-cited, evidence-
labelled, read-only capability map (topics: overview, threat,
countermeasure, compliance, optimization, experiment).
Standard router + flywheel (SYNTHETIC) + Darwin wiring, tailored to VEIL
task axes and policy levers. Tests: smoke + router + flywheel (need install)
and guidance (offline). .harness manifest generated with real per-file
hashes. Validated offline: cli syntax, --help, guidance topics, exit codes,
graceful degradation when deps are absent.
Docs: research bundle 08 gains a per-deployment adaptivity section; 07 and the
crate README point at the harness; ADR-289 added and indexed.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01WEXNqzs7UsfNFBcP5yW21p
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# ADR-289: `wifi-densepose-privshield-harness` — a MetaHarness for the VEIL privacy shield
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Status** | Proposed — implemented (P1) |
|
||||
| **Date** | 2026-08-09 |
|
||||
| **Parent** | ADR-288 (`wifi-densepose-privshield` / VEIL, the crate this harness assists development on) |
|
||||
| **Relates to** | ADR-286 (`wifi-densepose-sar-harness`, the per-crate harness scaffold this one mirrors), ADR-285 (`harness/homecore/`, the WASM-first `@metaharness/kernel` pattern), ADR-182 (`harness/ruview/`, the first minted harness), ADR-282 (L0–L5 evidence ladder) |
|
||||
| **Location** | `harness/wifi-densepose-privshield/` |
|
||||
|
||||
## 0. PROOF discipline
|
||||
|
||||
Every claim below about what is "real" versus "illustrative"/"SYNTHETIC" is
|
||||
checked by a test in this harness's own suite (router + flywheel + install-smoke
|
||||
+ guidance). The dependency-free `guidance` surface is covered by
|
||||
`__tests__/guidance.test.ts`, which runs even before `npm install`. Nothing here
|
||||
asserts a MEASURED defense result — the harness surfaces the VEIL crate's
|
||||
SYNTHETIC/L0 numbers with that label intact.
|
||||
|
||||
## 1. Context
|
||||
|
||||
`wifi-densepose-privshield` (ADR-288) is the VEIL privacy shield — a new,
|
||||
narrowly-scoped crate. Following the pattern ADR-286 set for
|
||||
`wifi-densepose-sar`, it gets a dedicated per-crate MetaHarness rather than a
|
||||
bespoke setup: the `vertical:coding` scaffold (architect/implementer/reviewer/
|
||||
test-writer, `doctor`) with `@metaharness/router`, `@metaharness/flywheel`, and
|
||||
Darwin Mode wired in, plus a VEIL-specific, dependency-free `guidance` surface.
|
||||
|
||||
## 2. Decision
|
||||
|
||||
Land the harness at `harness/wifi-densepose-privshield/`, mirroring
|
||||
`wifi-densepose-sar-harness`, with two deliberate improvements:
|
||||
|
||||
1. **Dynamic dependency imports.** `bin/cli.js` imports the `@metaharness/*`
|
||||
packages *inside* the commands that need them, not at module top. So
|
||||
`guidance`, `--help`, and the guidance test run with **zero dependencies
|
||||
installed** — useful for offline/air-gapped review and for this repo's CI
|
||||
before `npm install`. Only `init`/`doctor`/`route`/`flywheel` touch the
|
||||
kernel/host/router/flywheel packages.
|
||||
2. **A VEIL `guidance` command.** A self-contained, source-cited, read-only
|
||||
capability map (topics: `overview`, `threat`, `countermeasure`,
|
||||
`compliance`, `optimization`, `experiment`), each entry carrying a summary,
|
||||
repo-relative source citations, focused validation commands, and explicit
|
||||
limitations — the `ruview_guidance` shape, specialized to VEIL. It labels all
|
||||
defense evidence `SYNTHETIC/L0` and states plainly that guidance is
|
||||
navigation, not authority.
|
||||
|
||||
The standard three self-improvement/cost pieces are wired as real npm
|
||||
dependencies (not stubs):
|
||||
|
||||
- **`@metaharness/darwin`** (devDependency) — `npm run evolve` / `evolve:dry`
|
||||
mutates the harness's own operating config, keeping only measurable gains.
|
||||
- **`@metaharness/router`** — `src/router.ts` wires a real cost-optimal `Router`
|
||||
(`qualityBar: 0.8`, k=1) over two model tiers, with four VEIL-shaped task axes
|
||||
(threatModeling / complianceReview / optimizerTuning / docWriting). Labelled
|
||||
examples are illustrative seed data (honesty note in-file).
|
||||
- **`@metaharness/flywheel`** — `src/flywheel.ts` wires the real
|
||||
`runFlywheelGenerations` promotion loop (propose → evaluate → gate → promote,
|
||||
Ed25519-signed, independently replayable) with a SYNTHETIC proposer/evaluator
|
||||
(`dataSource: 'SYNTHETIC'`, no model call), over VEIL policy levers
|
||||
(`complianceReview`, `threatTriage`).
|
||||
|
||||
## 3. What this explicitly is NOT
|
||||
|
||||
- **Not a VEIL runtime.** The harness does not run a radio, emit RF, or jam. It
|
||||
assists *development* on the crate; it cannot execute the shield on hardware.
|
||||
- **Not evolving the crate.** Darwin/Flywheel mutate the harness's own policy
|
||||
(agent prompts, review-checklist depth), not VEIL's Rust code. The crate's
|
||||
actual hyper-optimization (ADR-288 §opt) was done directly, in the crate.
|
||||
- **Not a live routing/promotion system.** The router's examples are seed data;
|
||||
the flywheel's proposer/evaluator are deterministic stand-ins — both honestly
|
||||
labelled in-source and in `CLAUDE.md`.
|
||||
- **Not a replacement for the crate's gates.** The authoritative check for a
|
||||
VEIL change remains `cargo test -p wifi-densepose-privshield`.
|
||||
- **Not a re-labeller.** The harness must never present VEIL's SYNTHETIC results
|
||||
as MEASURED, and never scaffold interference-based ("jamming") defenses — both
|
||||
are hard rules in the harness `CLAUDE.md`.
|
||||
|
||||
## 4. Consequences
|
||||
|
||||
- The harness ships `guidance`/`doctor`/`init`/`route`/`flywheel`; `guidance`
|
||||
and `--help` work offline (validated here via `node bin/cli.js`), the rest
|
||||
after `npm install` + `npm run build` (CI).
|
||||
- `.harness/manifest.json` + `manifest.sha256` are generated with real per-file
|
||||
hashes at creation (unlike ADR-286's scaffold, whose manifest was historical).
|
||||
- Scoped to its own name: its plugin, permissions, and (future) MCP surface only
|
||||
read/assist on `wifi-densepose-privshield`. No risk to other harnesses/crates.
|
||||
|
||||
## 5. Validation
|
||||
|
||||
```bash
|
||||
cd harness/wifi-densepose-privshield
|
||||
node bin/cli.js guidance --topic overview # dependency-free
|
||||
npm ci && npm run build && npm test # full suite (CI; needs registry access)
|
||||
```
|
||||
@@ -146,6 +146,7 @@ Statuses: **Proposed** (under discussion), **Accepted** (approved and/or impleme
|
||||
| [ADR-285](ADR-285-homecore-wasm-first-metaharness.md) | WASM-first Homecore developer metaharness via `npx homecore` | Accepted (implemented and validated) |
|
||||
| [ADR-286](ADR-286-wifi-densepose-sar-harness-via-metaharness.md) | `wifi-densepose-sar-harness` — MetaHarness with darwin/router/flywheel | Accepted (implemented, published) |
|
||||
| [ADR-288](ADR-288-veil-privacy-shield-compliant-waveform.md) | VEIL — compliant-waveform privacy shield against unauthorized WiFi sensing (`wifi-densepose-privshield`) | Proposed (implemented, P1 reference) |
|
||||
| [ADR-289](ADR-289-wifi-densepose-privshield-harness-via-metaharness.md) | `wifi-densepose-privshield-harness` — npm MetaHarness for the VEIL crate (guidance/router/flywheel) | Proposed (implemented, P1) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
- **This research bundle** (`docs/research/privacy-shield/`).
|
||||
- **[ADR-288](../../adr/ADR-288-veil-privacy-shield-compliant-waveform.md)** — the
|
||||
formal decision record.
|
||||
- **npm metaharness** `harness/wifi-densepose-privshield/`
|
||||
([ADR-289](../../adr/ADR-289-wifi-densepose-privshield-harness-via-metaharness.md))
|
||||
— a per-crate contributor harness (architect/implementer/reviewer/test-writer,
|
||||
router, flywheel) with a dependency-free `guidance` surface that serves this
|
||||
bundle's capability map. `npx wifi-densepose-privshield-harness guidance
|
||||
--topic optimization`.
|
||||
|
||||
The crate is intentionally a **leaf with no internal RuView dependencies**
|
||||
(mirrors `wifi-densepose-aether`), so it can be reasoned about, fuzzed, and
|
||||
|
||||
@@ -110,7 +110,29 @@ expected to open up — a hardware study (roadmap P5) will re-measure it.
|
||||
|
||||
---
|
||||
|
||||
## 6. Robustness caveats (unchanged from the threat model)
|
||||
## 6. Per-deployment adaptivity
|
||||
|
||||
The optimum is not one number — `optimize` derives it per deployment:
|
||||
|
||||
- **SNR → feedback resolution.** `optimal_bits_across_snr` shows the
|
||||
*unconstrained* throughput-optimal resolution shifting with SNR: **4 bits at
|
||||
5–10 dB, 3 bits at 20–40 dB** (low SNR values fine resolution more because
|
||||
the Shannon capacity is near-linear there, so the residual costs more). Within
|
||||
the spec-allowed {5,7,9} set the choice is 5 bits across this whole range —
|
||||
the residual is already negligible at 5 bits — which is why the shipped shield
|
||||
is SNR-stable.
|
||||
- **Identity count → mixing.** `adaptive_shield(base, n)` derives the config for
|
||||
a room with `n` expected occupants. A notable finding: in this model the
|
||||
collapse budget is **N-independent** (min 48 passes collapses N∈{8,64}
|
||||
alike), because a well-mixed Haar-like rotation destroys per-identity
|
||||
structure regardless of how many identities there are — the budget is set by
|
||||
the fine-subspace dimension, not the candidate count. So `adaptive_shield`
|
||||
returns the same 96/5 across that range: the default is robust, not a point
|
||||
tuning.
|
||||
|
||||
Both are surfaced through the harness `guidance --topic optimization`.
|
||||
|
||||
## 7. Robustness caveats (unchanged from the threat model)
|
||||
|
||||
- The collapse is verified against two classifiers and two N; a learned
|
||||
attacker on real captures must still be checked (P2/P5).
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "wifi-densepose-privshield-harness",
|
||||
"version": "0.1.0",
|
||||
"description": "Harness for wifi-densepose-privshield (VEIL privacy shield)",
|
||||
"author": {
|
||||
"displayName": "Generated by metaharness",
|
||||
"url": "https://www.npmjs.com/package/metaharness"
|
||||
},
|
||||
"license": "MIT",
|
||||
"categories": [
|
||||
"agent-harness",
|
||||
"metaharness-scaffold",
|
||||
"Engineering",
|
||||
"software-engineering"
|
||||
],
|
||||
"tags": [
|
||||
"metaharness",
|
||||
"agent-harness",
|
||||
"vertical:coding",
|
||||
"software-engineering",
|
||||
"wifi-sensing",
|
||||
"privacy"
|
||||
],
|
||||
"homepage": "https://github.com/ruvnet/agent-harness-generator"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(npx wifi-densepose-privshield-harness*)",
|
||||
"mcp__wifi-densepose-privshield-harness__*",
|
||||
"Bash(npm test*)",
|
||||
"Bash(npm run*)",
|
||||
"Bash(cargo test -p wifi-densepose-privshield*)",
|
||||
"Bash(cargo clippy -p wifi-densepose-privshield*)",
|
||||
"Bash(git diff*)",
|
||||
"Bash(git status*)",
|
||||
"Bash(git log*)"
|
||||
],
|
||||
"deny": [
|
||||
"Read(./.env)",
|
||||
"Read(./.env.*)",
|
||||
"Bash(git push*)",
|
||||
"Bash(rm -rf*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
dist/
|
||||
*.tsbuildinfo
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"generator": "0.1.0",
|
||||
"template": "vertical:coding",
|
||||
"template_version": "0.0.0",
|
||||
"vars": {
|
||||
"name": "wifi-densepose-privshield-harness",
|
||||
"description": "Harness for wifi-densepose-privshield (VEIL privacy shield)",
|
||||
"host": "claude-code"
|
||||
},
|
||||
"hosts": ["claude-code"],
|
||||
"files": {
|
||||
".claude/settings.json": "fedb60921a0e3c78848f43edddd75f448819594c680d48ff2033ef8f1588da3f",
|
||||
".claude-plugin/plugin.json": "7831dc3d1b9b5363130a59ce680794bfe0b6ca09c73d77a7ce78aa6ec3921c5a",
|
||||
"bin/cli.js": "1133e7a47accada1c9b2184873776d8ca0d028f9b76dd55f467dfe38bb9ce609",
|
||||
"CLAUDE.md": "c5bd71bfc0699021a284a54ffa70f4784b8238774c6d6fcfedf836f5e37d10f8",
|
||||
"package.json": "e32acd6e5e630b0db9abccc5f5f58f86f291ccfc23b4c8410b380c01024a23df",
|
||||
"README.md": "be5b0a17cd051dafe8cd825ddf778c91971993419f9e33c0898e21140249f72a",
|
||||
"src/init.ts": "f05d6905d8681f45f610ff5b6e9d425dfa66183acdfe7857248e50e3583e13b8",
|
||||
"src/router.ts": "4545b42d1423db21bcfe6ab6bf132b805ba383937d142997cb7256e835c245e4",
|
||||
"src/flywheel.ts": "aab56d82c4f018ddc83923c877a66acdf9c624214307d0a9c4bf930ddb00599a",
|
||||
"tsconfig.json": "8b4e730a1aa39162ac574455d7a98e1881f5313ca80ffe503b9652dcf0c76b9d",
|
||||
"vitest.config.ts": "021b33ec623593effc3d163020479a91a1179329ee4ed1cb25f2dd9388e19820",
|
||||
"__tests__/smoke.test.ts": "8c5a2acc3a956ea48e60c996c9034224684f6f4110cb3c5885741ff8d18bb82d",
|
||||
"__tests__/router.test.ts": "97c29fc0ff718692ec97a9cd81f92e65ebde996fe1a3d8d2182e66598a583fad",
|
||||
"__tests__/flywheel.test.ts": "87b149f7d68b4cf72fe3dcf6c76e4307b280e9f4ab6e6b1f7ee6689340faf5fb",
|
||||
"__tests__/guidance.test.ts": "66b68615d27671d91b9efcf1eee5f2c7a53b0db7f475cc4ddb17ba8b6ddbff7f",
|
||||
"LICENSE": "07b1a7c2aa25991872e3594de2ecb64ff6b4c5d3dc2376dd5b9e9f77c4b258e8"
|
||||
},
|
||||
"generated_at": "2026-08-09T00:00:00.000Z",
|
||||
"meta": { "surface": "cli" }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
da48afb45d776c10f1841331facf65aa7ba4802f990a2480b91227fc100d4a47
|
||||
@@ -0,0 +1,67 @@
|
||||
# wifi-densepose-privshield-harness
|
||||
|
||||
Harness for [`wifi-densepose-privshield`](../../v2/crates/wifi-densepose-privshield)
|
||||
(VEIL — the compliant-waveform WiFi-sensing privacy shield, ADR-288). This
|
||||
package is defined by ADR-289.
|
||||
|
||||
> Advanced Coding harness · domain: `software-engineering`. Modeled on the
|
||||
> `wifi-densepose-sar-harness` scaffold (ADR-286), generated with
|
||||
> [create-agent-harness](https://github.com/ruvnet/agent-harness-generator).
|
||||
|
||||
## Behavioral rules
|
||||
|
||||
- Use the harness's tools for orchestration; memory and routing are handled by
|
||||
the kernel.
|
||||
- Defer destructive operations to the user.
|
||||
- **Never present WiFi sensing as camera-grade, and never relabel VEIL's
|
||||
SYNTHETIC/L0 results as MEASURED** — a hardware witness is required first
|
||||
(CLAUDE.md hardware rule; ADR-282 ladder). The harness is a development aid;
|
||||
it does not run a radio and cannot emit RF.
|
||||
- VEIL uses compliant waveform controls only — **never jamming.** Do not add,
|
||||
suggest, or scaffold interference-based "defenses."
|
||||
|
||||
## Commands
|
||||
|
||||
- `init` — boot the kernel + host adapter.
|
||||
- `doctor` — verify the install end-to-end (kernel, host, guidance map).
|
||||
- `guidance --topic <t> [--query <q>]` — read-only VEIL capability map
|
||||
(dependency-free; topics: `overview`, `threat`, `countermeasure`,
|
||||
`compliance`, `optimization`, `experiment`). Source-cited and
|
||||
evidence-labelled; navigation only, not authority.
|
||||
- `route <e0> <e1> <e2> <e3>` — cost-optimal model routing via
|
||||
`@metaharness/router` (needs `npm run build`).
|
||||
- `flywheel [generations]` — SYNTHETIC self-improvement demo via
|
||||
`@metaharness/flywheel` (needs `npm run build`).
|
||||
|
||||
## Architecture
|
||||
|
||||
Uses [@metaharness/kernel](https://www.npmjs.com/package/@metaharness/kernel)
|
||||
(Rust-compiled WASM with a NAPI-RS native fallback) so the same code runs on
|
||||
every platform. The `@metaharness/*` packages are imported *dynamically* inside
|
||||
the commands that need them, so `guidance`/`--help` work with no dependencies
|
||||
installed.
|
||||
|
||||
### Darwin, router, flywheel
|
||||
|
||||
- **Darwin Mode** (`@metaharness/darwin`, devDependency) — `npm run evolve` /
|
||||
`evolve:dry` mutates the harness's own config and keeps only measurable
|
||||
improvements.
|
||||
- **Router** (`@metaharness/router`) — `src/router.ts` wires a real cost-optimal
|
||||
`Router` (`qualityBar: 0.8`) over two model tiers. Its labelled examples are
|
||||
illustrative seed data (see the file's honesty note), not measured eval-log
|
||||
observations.
|
||||
- **Flywheel** (`@metaharness/flywheel`) — `src/flywheel.ts` wires the real
|
||||
promotion loop (propose → evaluate → gate → promote, Ed25519-signed,
|
||||
independently replayable) with a SYNTHETIC proposer/evaluator
|
||||
(`dataSource: 'SYNTHETIC'`, no model call). A LIVE run needs a real Proposer
|
||||
and Evaluator supplied by the operator — see the file's comments.
|
||||
|
||||
## Relationship to the crate
|
||||
|
||||
This harness assists development *on* the VEIL crate; it does not replace the
|
||||
crate's own gates. The authoritative validation for a VEIL change is still:
|
||||
|
||||
```bash
|
||||
cargo test -p wifi-densepose-privshield --no-default-features
|
||||
cargo clippy -p wifi-densepose-privshield --all-targets -- -D warnings
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 wifi-densepose-privshield-harness authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,68 @@
|
||||
# wifi-densepose-privshield-harness
|
||||
|
||||
A metaharness (contributor harness) for
|
||||
[`wifi-densepose-privshield`](../../v2/crates/wifi-densepose-privshield) — **VEIL**,
|
||||
the compliant-waveform WiFi-sensing privacy shield (ADR-288). Defined by ADR-289.
|
||||
|
||||
> **Advanced Coding** — architect → implement → review → test, plus a
|
||||
> dependency-free VEIL guidance surface. Modeled on `wifi-densepose-sar-harness`
|
||||
> (ADR-286). Multi-host scaffold with a kernel that resolves native → wasm → js.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install -g wifi-densepose-privshield-harness
|
||||
wifi-densepose-privshield-harness doctor
|
||||
```
|
||||
|
||||
Or run without installing:
|
||||
|
||||
```bash
|
||||
npx wifi-densepose-privshield-harness guidance --topic overview
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Deps needed | Purpose |
|
||||
|---|---|---|
|
||||
| `init` | kernel + host | Boot the kernel + host adapter |
|
||||
| `doctor` | kernel + host | Verify the install end-to-end |
|
||||
| `guidance --topic <t>` | **none** | Read-only VEIL capability map (source-cited, evidence-labelled) |
|
||||
| `route <e0..e3>` | router + `npm run build` | Cost-optimal model routing |
|
||||
| `flywheel [gens]` | flywheel + `npm run build` | SYNTHETIC self-improvement demo |
|
||||
|
||||
`guidance` topics: `overview`, `threat`, `countermeasure`, `compliance`,
|
||||
`optimization`, `experiment`. It needs no dependencies or build step, so it
|
||||
works offline and in CI before `npm install`.
|
||||
|
||||
## What VEIL is
|
||||
|
||||
VEIL shapes a node's **own** beamforming feedback with keyed Givens rotations so
|
||||
a third-party passive sniffer cannot re-identify people, while a keyed receiver
|
||||
sees an essentially unchanged link. **Compliant waveform controls only — never
|
||||
jamming.** Reference results are **SYNTHETIC / evidence level L0** (reproduced by
|
||||
`cargo test`), never MEASURED until a hardware witness exists. See the crate's
|
||||
[ADR-288](../../docs/adr/ADR-288-veil-privacy-shield-compliant-waveform.md) and
|
||||
[research bundle](../../docs/research/privacy-shield/).
|
||||
|
||||
## Darwin, router, flywheel
|
||||
|
||||
- `npm run evolve` / `evolve:dry` — Darwin Mode self-mutation of the harness
|
||||
config (`@metaharness/darwin`).
|
||||
- `npm run route -- <e0> <e1> <e2> <e3>` (after `npm run build`) — cost-optimal
|
||||
model routing (`@metaharness/router`).
|
||||
- `npm run flywheel:dry` — the SYNTHETIC `@metaharness/flywheel` demo
|
||||
(propose → evaluate → gate → promote, signed + independently replayable).
|
||||
|
||||
See `CLAUDE.md` and the honesty notes atop `src/router.ts` / `src/flywheel.ts`
|
||||
for what is real wiring vs. illustrative/synthetic data.
|
||||
|
||||
## Scope
|
||||
|
||||
The harness is a **development aid**. It does not run a VEIL radio, does not
|
||||
emit RF, and cannot jam. It does not replace the crate's own gates — the
|
||||
authoritative check for a VEIL change is `cargo test -p wifi-densepose-privshield`.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Verifies the SYNTHETIC flywheel demo wires end-to-end: a non-empty lift curve
|
||||
// and a replay bundle that verifies independently. Does NOT assert any real
|
||||
// self-improvement — the proposer/evaluator are deterministic stand-ins.
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { runVeilFlywheelDemo, verifyVeilFlywheelDemo } from '../src/flywheel.js';
|
||||
|
||||
describe('wifi-densepose-privshield-harness — flywheel (SYNTHETIC)', () => {
|
||||
it('produces a non-empty lift curve', async () => {
|
||||
const result = await runVeilFlywheelDemo(3);
|
||||
expect(result.liftCurve.length).toBeGreaterThan(0);
|
||||
expect(result.generationsRun).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('produces an independently verifiable replay bundle', async () => {
|
||||
const result = await runVeilFlywheelDemo(3);
|
||||
const verdict = verifyVeilFlywheelDemo(result);
|
||||
expect(verdict.pass).toBe(true);
|
||||
});
|
||||
|
||||
it('stamps the run as SYNTHETIC provenance', async () => {
|
||||
const result = await runVeilFlywheelDemo(2);
|
||||
expect(result.dataSource).toBe('SYNTHETIC');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// The VEIL guidance map is dependency-free (no @metaharness/* import), so this
|
||||
// test runs even before `npm install` resolves the kernel. It guards the
|
||||
// read-only capability map the MCP/CLI `guidance` surface exposes.
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { run, guidanceReport } from '../bin/cli.js';
|
||||
|
||||
describe('wifi-densepose-privshield-harness — guidance', () => {
|
||||
it('returns a source-cited report for a known topic', () => {
|
||||
const r = guidanceReport('optimization');
|
||||
expect(r.ok).toBe(true);
|
||||
expect(r.summary.length).toBeGreaterThan(0);
|
||||
expect(r.sources.some((s: string) => s.includes('optimize.rs'))).toBe(true);
|
||||
expect(r.authority).toContain('read-only');
|
||||
});
|
||||
|
||||
it('labels evidence as SYNTHETIC/L0', () => {
|
||||
const r = guidanceReport('experiment');
|
||||
expect(r.evidence).toContain('SYNTHETIC');
|
||||
});
|
||||
|
||||
it('rejects an unknown topic and lists the valid ones', () => {
|
||||
const r = guidanceReport('not-a-topic');
|
||||
expect(r.ok).toBe(false);
|
||||
expect(r.topics).toContain('overview');
|
||||
expect(r.topics).toContain('compliance');
|
||||
});
|
||||
|
||||
it('CLI `guidance --topic overview` exits 0; unknown topic exits non-zero', async () => {
|
||||
expect(await run(['guidance', '--topic', 'overview'])).toBe(0);
|
||||
expect(await run(['guidance', '--topic', 'nope'])).not.toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Verifies the cost-optimal router mechanism (not its illustrative data): cheap
|
||||
// query shapes route to the cheap tier; hard shapes escalate to the frontier.
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { routeVeilQuery } from '../src/router.js';
|
||||
|
||||
describe('wifi-densepose-privshield-harness — router', () => {
|
||||
it('routes a threat-model query (cheap-tier-capable) to the cheap tier', () => {
|
||||
const pick = routeVeilQuery([1, 0, 0, 0]);
|
||||
expect(pick.id).toBe('cheap-tier');
|
||||
expect(pick.metBar).toBe(true);
|
||||
});
|
||||
|
||||
it('escalates a compliance-review query to the frontier tier', () => {
|
||||
const pick = routeVeilQuery([0, 1, 0, 0]);
|
||||
expect(pick.id).toBe('frontier-tier');
|
||||
});
|
||||
|
||||
it('escalates an optimizer-tuning query to the frontier tier', () => {
|
||||
const pick = routeVeilQuery([0, 0, 1, 0]);
|
||||
expect(pick.id).toBe('frontier-tier');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// A real smoke test for wifi-densepose-privshield-harness: it boots the actual
|
||||
// kernel + host adapter the harness depends on, so `npm test` fails loudly if
|
||||
// @metaharness/kernel or @metaharness/host-claude-code is missing, broken, or
|
||||
// version-skewed. Fastest signal that `npm install` produced a runnable harness.
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { loadKernel } from '@metaharness/kernel';
|
||||
import adapter from '@metaharness/host-claude-code';
|
||||
import { run } from '../bin/cli.js';
|
||||
|
||||
describe('wifi-densepose-privshield-harness — install smoke test', () => {
|
||||
it('loads the kernel and reports a version + a known backend', async () => {
|
||||
const kernel = await loadKernel();
|
||||
const info = kernel.kernelInfo();
|
||||
expect(typeof info.version).toBe('string');
|
||||
expect(info.version.length).toBeGreaterThan(0);
|
||||
expect(['native', 'wasm', 'js']).toContain(kernel.backend);
|
||||
});
|
||||
|
||||
it('resolves the host adapter with a name', () => {
|
||||
expect(typeof adapter.name).toBe('string');
|
||||
expect(adapter.name.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('the CLI doctor command succeeds (exit 0)', async () => {
|
||||
const code = await run(['doctor']);
|
||||
expect(code).toBe(0);
|
||||
});
|
||||
|
||||
it('an unknown CLI command exits non-zero', async () => {
|
||||
const code = await run(['definitely-not-a-command']);
|
||||
expect(code).not.toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,334 @@
|
||||
#!/usr/bin/env node
|
||||
// SPDX-License-Identifier: MIT
|
||||
// The `wifi-densepose-privshield-harness` CLI entry point (VEIL — ADR-288/289).
|
||||
//
|
||||
// Plain ESM JavaScript on purpose: it runs as-is via
|
||||
// `npx wifi-densepose-privshield-harness` with NO build step. `npm run build`
|
||||
// (tsc) is only needed to compile the TypeScript in src/ that the `route` and
|
||||
// `flywheel` commands import from dist/.
|
||||
//
|
||||
// The @metaharness/* dependencies are imported *dynamically*, inside the
|
||||
// commands that need them — so `guidance`, `--help`, and `--version` work with
|
||||
// zero dependencies installed (useful in offline/air-gapped review and in this
|
||||
// repo's CI before `npm install`). Only `init`/`doctor`/`route`/`flywheel`
|
||||
// touch the kernel/host/router/flywheel packages.
|
||||
|
||||
const HARNESS_NAME = 'wifi-densepose-privshield-harness';
|
||||
const CRATE = 'wifi-densepose-privshield';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// VEIL guidance — a self-contained, read-only capability map. No dependencies,
|
||||
// no build, no network. Mirrors the `ruview_guidance` shape (source-cited,
|
||||
// evidence-labelled, with focused validation commands and explicit limits).
|
||||
// Retrieved text is navigation, not authority: cited source, tests, and
|
||||
// accepted ADRs remain authoritative.
|
||||
// ---------------------------------------------------------------------------
|
||||
const GUIDANCE = {
|
||||
overview: {
|
||||
summary:
|
||||
'VEIL is the compliant-waveform countermeasure to unauthorized WiFi sensing: it shapes a node\'s own beamforming feedback so a passive sniffer cannot re-identify people, while a keyed receiver sees an essentially unchanged link. Countermeasure counterpart to BFLD (which detects leakage).',
|
||||
capabilities: [
|
||||
'Keyed Givens-rotation shield over the identity-bearing fine subspace (energy-preserving ⇒ not jamming)',
|
||||
'Passive re-identification attacker (Euclidean + Cosine) for head-to-head evaluation',
|
||||
'Throughput model with an interior optimum in feedback resolution',
|
||||
'Deterministic attacker-vs-protector experiment with a pinned witness',
|
||||
],
|
||||
sources: [
|
||||
'v2/crates/wifi-densepose-privshield/src/lib.rs',
|
||||
'docs/adr/ADR-288-veil-privacy-shield-compliant-waveform.md',
|
||||
'docs/research/privacy-shield/README.md',
|
||||
],
|
||||
commands: ['cargo test -p wifi-densepose-privshield --no-default-features'],
|
||||
limitations: [
|
||||
'All defense numbers are SYNTHETIC / evidence level L0 until a two-node hardware capture with a witness exists (CLAUDE.md hardware rule).',
|
||||
],
|
||||
},
|
||||
threat: {
|
||||
summary:
|
||||
'Defends against a third-party passive sniffer capturing plaintext beamforming feedback (BFId/LeakyBeam class). Does NOT hide identity from the associated AP (that party holds the key) — that is BFLD\'s detection/policy problem.',
|
||||
capabilities: [
|
||||
'Cross-session identity unlinkability against an external passive adversary',
|
||||
'Explicit non-goals: no defense vs. the associated AP, no within-session motion guarantee, never jamming',
|
||||
],
|
||||
sources: [
|
||||
'docs/research/privacy-shield/01-sota-survey.md',
|
||||
'docs/research/privacy-shield/02-threat-model.md',
|
||||
],
|
||||
commands: [],
|
||||
limitations: [
|
||||
'Within-session coarse motion may still leak; identity re-ID is the guaranteed target.',
|
||||
],
|
||||
},
|
||||
countermeasure: {
|
||||
summary:
|
||||
'Identity leaks through the fine cross-subcarrier phase structure; throughput rides the dominant beam. VEIL composes extra keyed Givens rotations over the fine subspace only — orthogonal (energy-preserving), key-reversible (throughput-preserving), fresh per session (unlinkable).',
|
||||
capabilities: [
|
||||
'protector.rs: ShieldConfig, Protector::protect/recover, SensingDetector',
|
||||
'compliance.rs: machine-checkable energy-conservation ("not jamming") audit',
|
||||
],
|
||||
sources: [
|
||||
'v2/crates/wifi-densepose-privshield/src/protector.rs',
|
||||
'v2/crates/wifi-densepose-privshield/src/compliance.rs',
|
||||
'docs/research/privacy-shield/03-countermeasure-design.md',
|
||||
],
|
||||
commands: ['cargo test -p wifi-densepose-privshield protector'],
|
||||
limitations: [
|
||||
'The two-subspace separability is a model abstraction; real hardware is only approximately separable.',
|
||||
],
|
||||
},
|
||||
compliance: {
|
||||
summary:
|
||||
'Compliant waveform controls only, never jamming. The keyed rotation is orthogonal, so it preserves the report energy exactly (ratio ≈ 1.0) — it adds no interfering emission. Jamming (47 U.S.C. §333/§302a) is defined by interfering with OTHERS\' transmissions, not shaping your own.',
|
||||
capabilities: [
|
||||
'ComplianceReport::audit / is_compliant — energy ratio + non-interference verdict',
|
||||
],
|
||||
sources: [
|
||||
'v2/crates/wifi-densepose-privshield/src/compliance.rs',
|
||||
'docs/research/privacy-shield/04-compliance-and-regulatory.md',
|
||||
],
|
||||
commands: ['cargo test -p wifi-densepose-privshield compliance'],
|
||||
limitations: [
|
||||
'Engineering analysis, not legal advice; RF power/mask/timing limits are jurisdiction-specific.',
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
summary:
|
||||
'The shipped shield config is derived, not hand-picked: 96 Givens passes (2× the proven-minimum 48 for robust collapse across both attacker metrics and N∈{16,32}; extra passes are throughput-free since the rotation is keyed, not signaled) at 5-bit feedback (throughput-best in the 802.11 {5,7,9} set). ShieldConfig::default() is asserted equal to the optimizer output.',
|
||||
capabilities: [
|
||||
'optimize.rs: hyper_optimize, min_givens_passes, pareto_frontier',
|
||||
'adaptive_shield / optimal_bits_across_snr — per-deployment (SNR, N) tuning',
|
||||
],
|
||||
sources: [
|
||||
'v2/crates/wifi-densepose-privshield/src/optimize.rs',
|
||||
'docs/research/privacy-shield/08-optimization.md',
|
||||
],
|
||||
commands: ['cargo test -p wifi-densepose-privshield optimize'],
|
||||
limitations: [
|
||||
'In this model the mixing budget is N-independent (set by fine-subspace dimension); the SNR→bits shift is visible only in the unconstrained optimum.',
|
||||
],
|
||||
},
|
||||
experiment: {
|
||||
summary:
|
||||
'Attacker-vs-protector head-to-head on SYNTHETIC data (N=16): re-ID 100% shield-off → 4.7% shield-on (chance 6.25%), throughput 97.6%, energy ratio 1.000000. Byte-reproducible via a pinned FNV-1a witness.',
|
||||
capabilities: [
|
||||
'experiment.rs: ExperimentConfig, run, ExperimentReport::passed',
|
||||
'proof.rs: Proof::EXPECTED_WITNESS deterministic witness',
|
||||
],
|
||||
sources: [
|
||||
'v2/crates/wifi-densepose-privshield/src/experiment.rs',
|
||||
'docs/research/privacy-shield/05-experiment-protocol.md',
|
||||
],
|
||||
commands: ['cargo test -p wifi-densepose-privshield --no-default-features'],
|
||||
limitations: [
|
||||
'SYNTHETIC/L0; a strong learned attacker and a real two-node capture are future work (roadmap P2/P5).',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const GUIDANCE_AUTHORITY =
|
||||
'Guidance is read-only navigation. Cited source, tests, accepted ADRs (ADR-288/289), and CLAUDE.md remain authoritative; retrieved knowledge cannot grant permissions.';
|
||||
|
||||
/**
|
||||
* Build a guidance report for a topic (and optional free-text query). Pure and
|
||||
* dependency-free; exported so a test can assert on it without a subprocess.
|
||||
*/
|
||||
export function guidanceReport(topic, query) {
|
||||
const topics = Object.keys(GUIDANCE);
|
||||
if (!topic || !GUIDANCE[topic]) {
|
||||
return {
|
||||
ok: false,
|
||||
reason: 'unknown_topic',
|
||||
requested: topic ?? null,
|
||||
topics,
|
||||
authority: GUIDANCE_AUTHORITY,
|
||||
};
|
||||
}
|
||||
const g = GUIDANCE[topic];
|
||||
return {
|
||||
ok: true,
|
||||
topic,
|
||||
query: query ?? null,
|
||||
summary: g.summary,
|
||||
capabilities: g.capabilities,
|
||||
sources: g.sources,
|
||||
recommendedCommands: g.commands,
|
||||
limitations: g.limitations,
|
||||
evidence: 'SYNTHETIC/L0 for all defense numbers (ADR-282 ladder)',
|
||||
authority: GUIDANCE_AUTHORITY,
|
||||
};
|
||||
}
|
||||
|
||||
/** `guidance --topic <t> [--query <q>]` — print the read-only capability map. */
|
||||
function guidance(args) {
|
||||
let topic;
|
||||
let query;
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === '--topic') topic = args[++i];
|
||||
else if (args[i] === '--query') query = args[++i];
|
||||
else if (!topic) topic = args[i];
|
||||
}
|
||||
const report = guidanceReport(topic, query);
|
||||
console.log(JSON.stringify(report, null, 2));
|
||||
return report.ok ? 0 : 2;
|
||||
}
|
||||
|
||||
/** `init` — boot the kernel + host adapter and report status. */
|
||||
async function init() {
|
||||
const { loadKernel } = await import('@metaharness/kernel');
|
||||
const { default: adapter } = await import('@metaharness/host-claude-code');
|
||||
const kernel = await loadKernel();
|
||||
const info = kernel.kernelInfo();
|
||||
console.log(`${HARNESS_NAME} — kernel ${info.version} (${kernel.backend})`);
|
||||
console.log(`Host adapter: ${adapter.name}`);
|
||||
console.log(`Assists development on the \`${CRATE}\` crate (VEIL privacy shield).`);
|
||||
console.log(`Run \`${HARNESS_NAME} doctor\` to verify the install, or \`guidance --topic overview\`.`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** `doctor` — verify the install end-to-end (kernel + host resolve). */
|
||||
async function doctor() {
|
||||
const { loadKernel } = await import('@metaharness/kernel');
|
||||
const { default: adapter } = await import('@metaharness/host-claude-code');
|
||||
const kernel = await loadKernel();
|
||||
const info = kernel.kernelInfo();
|
||||
const checks = [
|
||||
['kernel loads', !!kernel],
|
||||
['kernel reports a version', typeof info.version === 'string' && info.version.length > 0],
|
||||
['kernel backend is native|wasm|js', ['native', 'wasm', 'js'].includes(kernel.backend)],
|
||||
['host adapter has a name', typeof adapter?.name === 'string' && adapter.name.length > 0],
|
||||
['guidance map resolves', guidanceReport('overview').ok === true],
|
||||
];
|
||||
let ok = true;
|
||||
for (const [label, pass] of checks) {
|
||||
console.log(`${pass ? 'PASS' : 'FAIL'} ${label}`);
|
||||
if (!pass) ok = false;
|
||||
}
|
||||
console.log(
|
||||
ok
|
||||
? `\n${HARNESS_NAME}: all checks passed (kernel ${info.version}, ${kernel.backend} backend, host ${adapter.name})`
|
||||
: `\n${HARNESS_NAME}: doctor found problems`,
|
||||
);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* `route <e0> <e1> <e2> <e3>` — route a 4-axis task embedding to the
|
||||
* cost-optimal model tier via @metaharness/router. Needs `npm run build`.
|
||||
*/
|
||||
async function route(args) {
|
||||
const embedding = args.map(Number);
|
||||
if (embedding.length !== 4 || embedding.some((n) => Number.isNaN(n))) {
|
||||
console.error(
|
||||
`Usage: ${HARNESS_NAME} route <threatModeling> <complianceReview> <optimizerTuning> <docWriting> (four 0..1 numbers)`,
|
||||
);
|
||||
return 2;
|
||||
}
|
||||
let routeVeilQuery;
|
||||
try {
|
||||
({ routeVeilQuery } = await import('../dist/router.js'));
|
||||
} catch (err) {
|
||||
console.error(`route: dist/router.js not found — run \`npm run build\` first. (${err.message})`);
|
||||
return 1;
|
||||
}
|
||||
const pick = routeVeilQuery(embedding);
|
||||
console.log(
|
||||
`route -> ${pick.id} (predicted quality ${pick.predictedQuality.toFixed(3)}, $${pick.costPerMTok}/MTok, met bar: ${pick.metBar})`,
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* `flywheel [generations]` — run the SYNTHETIC @metaharness/flywheel demo and
|
||||
* print the lift curve + an independent replay-bundle verification. Needs
|
||||
* `npm run build`.
|
||||
*/
|
||||
async function flywheel(args) {
|
||||
const generations = args[0] ? Number(args[0]) : 3;
|
||||
if (Number.isNaN(generations) || generations < 1) {
|
||||
console.error(`Usage: ${HARNESS_NAME} flywheel [generations>=1]`);
|
||||
return 2;
|
||||
}
|
||||
let runVeilFlywheelDemo, verifyVeilFlywheelDemo;
|
||||
try {
|
||||
({ runVeilFlywheelDemo, verifyVeilFlywheelDemo } = await import('../dist/flywheel.js'));
|
||||
} catch (err) {
|
||||
console.error(`flywheel: dist/flywheel.js not found — run \`npm run build\` first. (${err.message})`);
|
||||
return 1;
|
||||
}
|
||||
console.log(`Running ${generations}-generation flywheel demo (dataSource: SYNTHETIC — see src/flywheel.ts)...`);
|
||||
const result = await runVeilFlywheelDemo(generations);
|
||||
for (const point of result.liftCurve) {
|
||||
console.log(` gen ${point.generation}: primary=${point.primary.toFixed(3)} delta=${point.delta.toFixed(3)} anchor=${point.anchor ?? 'n/a'}`);
|
||||
}
|
||||
const verdict = verifyVeilFlywheelDemo(result);
|
||||
console.log(`generations run: ${result.generationsRun} · promotions: ${result.promotions.length} · replay verified: ${verdict.pass}`);
|
||||
return verdict.pass ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch one CLI invocation. Exported (not just run on import) so a test can
|
||||
* drive it without spawning a subprocess. Returns the intended exit code.
|
||||
*/
|
||||
export async function run(argv) {
|
||||
const cmd = argv[0] ?? 'init';
|
||||
switch (cmd) {
|
||||
case 'init':
|
||||
return init();
|
||||
case 'doctor':
|
||||
return doctor();
|
||||
case 'guidance':
|
||||
return guidance(argv.slice(1));
|
||||
case 'route':
|
||||
return route(argv.slice(1));
|
||||
case 'flywheel':
|
||||
return flywheel(argv.slice(1));
|
||||
case '--version':
|
||||
case '-v': {
|
||||
const { loadKernel } = await import('@metaharness/kernel');
|
||||
const kernel = await loadKernel();
|
||||
console.log(kernel.version());
|
||||
return 0;
|
||||
}
|
||||
case '--help':
|
||||
case '-h':
|
||||
console.log(
|
||||
`Usage: ${HARNESS_NAME} <command>\n\n` +
|
||||
` init boot the kernel + host adapter (default)\n` +
|
||||
` doctor verify the install end-to-end\n` +
|
||||
` guidance --topic <t> read-only VEIL capability map (no deps/build)\n` +
|
||||
` topics: overview threat countermeasure compliance optimization experiment\n` +
|
||||
` route <e0..e3> cost-optimal model routing (needs \`npm run build\`)\n` +
|
||||
` flywheel [generations] SYNTHETIC self-improvement demo (needs \`npm run build\`)\n` +
|
||||
` --version print the kernel version`,
|
||||
);
|
||||
return 0;
|
||||
default:
|
||||
console.error(`Unknown command: ${cmd}. Try \`${HARNESS_NAME} --help\`.`);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
// CLI guard: execute only when invoked directly (not when imported by a test).
|
||||
// npm's bin shims pass a NON-normalized argv[1], so realpath BOTH sides before
|
||||
// comparing — a naive string === misses the npx/shim path and the CLI no-ops.
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { realpathSync } from 'node:fs';
|
||||
import { argv } from 'node:process';
|
||||
const invokedDirectly = (() => {
|
||||
if (!argv[1]) return false;
|
||||
try {
|
||||
const a = realpathSync(argv[1]);
|
||||
const b = realpathSync(fileURLToPath(import.meta.url));
|
||||
return process.platform === 'win32' ? a.toLowerCase() === b.toLowerCase() : a === b;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
if (invokedDirectly) {
|
||||
run(argv.slice(2))
|
||||
.then((code) => process.exit(code))
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "wifi-densepose-privshield-harness",
|
||||
"version": "0.1.0",
|
||||
"description": "Harness for wifi-densepose-privshield (VEIL — compliant-waveform WiFi-sensing privacy shield, ADR-288/289)",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"wifi-densepose-privshield-harness": "bin/cli.js"
|
||||
},
|
||||
"files": [
|
||||
"bin/**",
|
||||
"dist/**",
|
||||
"src/**",
|
||||
"tsconfig.json",
|
||||
".claude/**",
|
||||
".claude-plugin/**",
|
||||
"CLAUDE.md",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "vitest run",
|
||||
"init": "node ./bin/cli.js init",
|
||||
"doctor": "node ./bin/cli.js doctor",
|
||||
"guidance": "node ./bin/cli.js guidance",
|
||||
"evolve": "metaharness-darwin evolve . --sandbox real --generations 3 --children 4",
|
||||
"evolve:dry": "metaharness-darwin evolve . --sandbox mock --generations 2 --children 3",
|
||||
"route": "npm run build && node ./bin/cli.js route",
|
||||
"flywheel:dry": "npm run build && node ./bin/cli.js flywheel 3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@metaharness/kernel": "^0.1.0",
|
||||
"@metaharness/host-claude-code": "^0.1.0",
|
||||
"@metaharness/router": "^0.3.2",
|
||||
"@metaharness/flywheel": "^0.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.0.0",
|
||||
"typescript": "^5.4.0",
|
||||
"vitest": "^3.0.0",
|
||||
"@metaharness/darwin": "^0.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// The wifi-densepose-privshield (VEIL) harness's self-improvement loop, via
|
||||
// @metaharness/flywheel: run -> measure -> mutate -> verify -> promote, with a
|
||||
// frozen, conjunctive promotion gate and a signed, replayable lineage.
|
||||
//
|
||||
// HONESTY NOTE (load-bearing): `runVeilFlywheelDemo()` wires the real
|
||||
// @metaharness/flywheel API end-to-end, but its Proposer and Evaluator are
|
||||
// SYNTHETIC stand-ins — a deterministic string mutation and a deterministic
|
||||
// scoring function over that string, with NO model call and NO real benchmark.
|
||||
// It proves the wiring works (see __tests__/flywheel.test.ts: a non-empty lift
|
||||
// curve, a verifiable replay bundle) and gives a `dataSource: 'SYNTHETIC'`-
|
||||
// stamped demo. A LIVE run needs the operator to supply:
|
||||
// - a real Proposer: a model call that improves one policy lever (e.g. the
|
||||
// compliance-review checklist, the threat-model triage prompt);
|
||||
// - a real Evaluator: scores that policy against real tasks (e.g. "did the
|
||||
// compliance reviewer catch a non-energy-preserving perturbation").
|
||||
// Neither exists in this repo — wiring them is a live-API-key decision for the
|
||||
// harness operator, not something to fake here.
|
||||
|
||||
import {
|
||||
runFlywheelGenerations,
|
||||
meetsPromotionRule,
|
||||
makeSigner,
|
||||
verifyReplayBundle,
|
||||
type Policy,
|
||||
type PolicyGenome,
|
||||
type Proposer,
|
||||
type Evaluator,
|
||||
type Suite,
|
||||
type FlywheelResult,
|
||||
} from '@metaharness/flywheel';
|
||||
|
||||
/** The gen-0 operating policy for the VEIL harness's review agents. Opaque
|
||||
* string levers — the flywheel never interprets their meaning, only the
|
||||
* Evaluator does. */
|
||||
export const VEIL_ROOT_POLICY: Policy = {
|
||||
complianceReview: 'energy-ratio-checklist',
|
||||
threatTriage: 'single-pass',
|
||||
};
|
||||
|
||||
/** SYNTHETIC proposer: deterministically varies the target lever's value
|
||||
* rather than calling a model. */
|
||||
const syntheticProposer: Proposer = async (base: PolicyGenome, target: string) => {
|
||||
const current = base.policy[target] ?? '';
|
||||
return `${current}+g${base.generation + 1}`;
|
||||
};
|
||||
|
||||
/** SYNTHETIC evaluator: scores a policy purely as a function of its own string
|
||||
* content — a deterministic stand-in for running the harness's agents against a
|
||||
* real task suite. `noopRate` must move for anything to promote (the default
|
||||
* gate requires it to strictly improve generation over generation). */
|
||||
const syntheticEvaluator: Evaluator = async (policy: Policy, _suite: Suite) => {
|
||||
const totalLength = Object.values(policy).reduce((s, v) => s + v.length, 0);
|
||||
const primary = Math.min(0.5 + totalLength / 200, 0.98);
|
||||
const noopRate = Math.max(0.3 - totalLength / 300, 0.02);
|
||||
return {
|
||||
primary,
|
||||
noopRate,
|
||||
costPerWin: 1 / primary,
|
||||
regressed: false,
|
||||
};
|
||||
};
|
||||
|
||||
const VEIL_HOLDOUT: Suite = {
|
||||
id: 'veil-harness-holdout-synthetic',
|
||||
items: ['seeded-compliance-task-1', 'seeded-threat-task-2', 'seeded-optimizer-task-3'],
|
||||
};
|
||||
|
||||
const VEIL_ANCHOR: Suite = {
|
||||
id: 'veil-harness-anchor-synthetic',
|
||||
items: ['frozen-not-jamming-regression-1'],
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a small, fully SYNTHETIC flywheel demo end-to-end and return the real
|
||||
* @metaharness/flywheel result — a genuine lift curve and a signed,
|
||||
* independently replayable bundle, built from synthetic (not live) evidence.
|
||||
*/
|
||||
export async function runVeilFlywheelDemo(maxGenerations = 3): Promise<FlywheelResult> {
|
||||
return runFlywheelGenerations({
|
||||
rootPolicy: VEIL_ROOT_POLICY,
|
||||
proposer: syntheticProposer,
|
||||
evaluator: syntheticEvaluator,
|
||||
promotionRule: meetsPromotionRule,
|
||||
holdout: VEIL_HOLDOUT,
|
||||
anchor: VEIL_ANCHOR,
|
||||
maxGenerations,
|
||||
signer: makeSigner(),
|
||||
dataSource: 'SYNTHETIC',
|
||||
});
|
||||
}
|
||||
|
||||
/** Independently verify a flywheel demo's replay bundle (no trust in the producer). */
|
||||
export function verifyVeilFlywheelDemo(result: FlywheelResult) {
|
||||
return verifyReplayBundle(result.replayBundle);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// The harness's `wifi-densepose-privshield-harness init` entry (typed mirror of
|
||||
// the JS command in bin/cli.js; the published CLI uses the JS version so no
|
||||
// build is required for `init`).
|
||||
|
||||
import { loadKernel } from '@metaharness/kernel';
|
||||
import adapter from '@metaharness/host-claude-code';
|
||||
|
||||
const HARNESS_NAME = 'wifi-densepose-privshield-harness';
|
||||
|
||||
async function main(): Promise<number> {
|
||||
const kernel = await loadKernel();
|
||||
const info = kernel.kernelInfo();
|
||||
console.log(`${HARNESS_NAME} — kernel ${info.version} (${kernel.backend})`);
|
||||
console.log(`Host adapter: ${adapter.name}`);
|
||||
console.log(`Run \`${HARNESS_NAME} doctor\` to verify the install.`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
main()
|
||||
.then((c) => process.exit(c))
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Cost-optimal task routing for the wifi-densepose-privshield (VEIL) harness,
|
||||
// via @metaharness/router: route each agent query to the cheapest model
|
||||
// predicted to clear a quality bar, instead of defaulting every query to the
|
||||
// frontier tier.
|
||||
//
|
||||
// HONESTY NOTE: the candidate `examples` below are SEED/ILLUSTRATIVE data —
|
||||
// four hand-picked (embedding, quality) points per candidate, not measured
|
||||
// eval-log observations. They exist so `veilTaskRouter` is a real, runnable
|
||||
// k-NN router out of the box (see __tests__/router.test.ts), not so its routing
|
||||
// decisions should be trusted for production cost savings. Replace
|
||||
// `VEIL_ROUTER_CANDIDATES[*].examples` with real (query embedding → quality
|
||||
// achieved) rows from your own eval logs before relying on this.
|
||||
|
||||
import { Router, type RouterCandidate } from '@metaharness/router';
|
||||
|
||||
/**
|
||||
* A 4-axis feature embedding for a harness query (each axis 0..1):
|
||||
* [0] threatModeling — "is this attack in scope / what does VEIL defend"-shaped
|
||||
* [1] complianceReview — "does this stay compliant / not jamming"-shaped
|
||||
* [2] optimizerTuning — "tune passes/bits / re-run the optimizer"-shaped
|
||||
* [3] docWriting — "write/update the research bundle or ADR"-shaped
|
||||
* A caller with a real embedding model should project onto that model's
|
||||
* dimensionality instead — the router only needs consistent vectors.
|
||||
*/
|
||||
export type VeilTaskEmbedding = readonly [number, number, number, number];
|
||||
|
||||
export const VEIL_ROUTER_CANDIDATES: RouterCandidate[] = [
|
||||
{
|
||||
id: 'cheap-tier',
|
||||
costPerMTok: 1,
|
||||
examples: [
|
||||
{ embedding: [1, 0, 0, 0], quality: 0.88 }, // threat-model Q&A: cheap tier is fine
|
||||
{ embedding: [0, 0, 0, 1], quality: 0.85 }, // doc writing: cheap tier is fine
|
||||
{ embedding: [0, 1, 0, 0], quality: 0.55 }, // compliance review: cheap tier is weak
|
||||
{ embedding: [0, 0, 1, 0], quality: 0.5 }, // optimizer tuning: cheap tier is weak
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'frontier-tier',
|
||||
costPerMTok: 15,
|
||||
examples: [
|
||||
{ embedding: [1, 0, 0, 0], quality: 0.95 },
|
||||
{ embedding: [0, 0, 0, 1], quality: 0.93 },
|
||||
{ embedding: [0, 1, 0, 0], quality: 0.93 }, // compliance review: frontier tier needed
|
||||
{ embedding: [0, 0, 1, 0], quality: 0.92 }, // optimizer tuning: frontier tier needed
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Cost-optimal router for the harness's four query shapes above. `qualityBar`
|
||||
* of 0.8: return the cheapest candidate predicted to clear 80% quality, or the
|
||||
* best-predicted candidate if none do. k=1 because each candidate has only 4
|
||||
* orthogonal one-hot examples (see the SAR harness note on why the default k=5
|
||||
* would collapse every query to the same prediction here).
|
||||
*/
|
||||
export const veilTaskRouter = new Router({
|
||||
qualityBar: 0.8,
|
||||
candidates: VEIL_ROUTER_CANDIDATES,
|
||||
k: 1,
|
||||
});
|
||||
|
||||
/** Route one query embedding to the cost-optimal model tier. */
|
||||
export function routeVeilQuery(queryEmbedding: VeilTaskEmbedding) {
|
||||
return veilTaskRouter.route([...queryEmbedding]);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"lib": ["ES2022"],
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist", "__tests__"]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Strips the `#!/usr/bin/env node` shebang from importable entrypoints (e.g.
|
||||
// bin/cli.js) before Vite parses them — Vite/esbuild (used internally by
|
||||
// Vitest) does NOT strip shebangs, so importing a shebanged module throws
|
||||
// `SyntaxError: Invalid or unexpected token`. No effect on direct CLI
|
||||
// execution.
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
{
|
||||
name: 'strip-shebang',
|
||||
enforce: 'pre',
|
||||
transform(code: string) {
|
||||
if (code.startsWith('#!')) {
|
||||
return { code: code.replace(/^#![^\n]*/, ''), map: null };
|
||||
}
|
||||
return null;
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -13,7 +13,10 @@ experiment** — not a radio driver. It never emits RF. Every number it prints i
|
||||
`SYNTHETIC`, reproduced by `cargo test -p wifi-densepose-privshield`.
|
||||
|
||||
See [ADR-288](../../../docs/adr/ADR-288-veil-privacy-shield-compliant-waveform.md)
|
||||
and the [research bundle](../../../docs/research/privacy-shield/).
|
||||
and the [research bundle](../../../docs/research/privacy-shield/). A per-crate npm
|
||||
contributor harness lives at
|
||||
[`harness/wifi-densepose-privshield/`](../../../harness/wifi-densepose-privshield)
|
||||
(ADR-289): `npx wifi-densepose-privshield-harness guidance --topic overview`.
|
||||
|
||||
## The idea
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ pub use attacker::{Metric, NearestCentroidAttacker};
|
||||
pub use compliance::ComplianceReport;
|
||||
pub use experiment::{run, ExperimentConfig, ExperimentReport};
|
||||
pub use identity::{BfiSample, Channel, SceneConfig};
|
||||
pub use optimize::{hyper_optimize, HyperOptimized};
|
||||
pub use optimize::{adaptive_shield, hyper_optimize, HyperOptimized};
|
||||
pub use proof::Proof;
|
||||
pub use protector::{Protector, SensingDetector, ShieldConfig};
|
||||
pub use throughput::LinkModel;
|
||||
|
||||
@@ -242,6 +242,77 @@ pub fn hyper_optimize(base: &ExperimentConfig) -> HyperOptimized {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Adaptive optimization: the optimum is not one config — it depends on the
|
||||
// deployment's SNR (which shifts the throughput-optimal feedback resolution)
|
||||
// and its identity count (which sets how much rotation mixing collapse needs).
|
||||
// These functions derive the right config per deployment rather than assuming
|
||||
// the default scene.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// SNR values (dB) to profile the throughput-optimal feedback resolution over.
|
||||
pub const SNR_PROFILE_DB: [f64; 5] = [5.0, 10.0, 20.0, 30.0, 40.0];
|
||||
|
||||
/// Unconstrained throughput-optimal feedback resolution for a specific SNR,
|
||||
/// holding the rest of `base`. At low SNR the residual matters proportionally
|
||||
/// more (Shannon capacity is near-linear), so higher resolution wins; at high
|
||||
/// SNR the log compresses the residual away and feedback airtime dominates,
|
||||
/// favoring fewer bits. (The *shipped* shield clamps to the 802.11 {5,7,9} set,
|
||||
/// where 5 already zeroes the residual — so this shift is visible only in the
|
||||
/// unconstrained optimum, and is what motivates keeping resolution low.)
|
||||
#[must_use]
|
||||
pub fn model_optimal_bits_for_snr(base: &ExperimentConfig, snr_db: f64) -> (u32, f64) {
|
||||
let mut cfg = base.clone();
|
||||
cfg.link.snr_db = snr_db;
|
||||
optimal_feedback_bits(&cfg, 12)
|
||||
}
|
||||
|
||||
/// Profile the unconstrained throughput-optimal feedback resolution across
|
||||
/// [`SNR_PROFILE_DB`]. Demonstrates the SNR → resolution dependence.
|
||||
#[must_use]
|
||||
pub fn optimal_bits_across_snr(base: &ExperimentConfig) -> Vec<(f64, u32)> {
|
||||
SNR_PROFILE_DB
|
||||
.iter()
|
||||
.map(|&snr| (snr, model_optimal_bits_for_snr(base, snr).0))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Does `passes` collapse re-ID for both metrics at a single identity count?
|
||||
#[must_use]
|
||||
pub fn passes_collapse_at_n(base: &ExperimentConfig, passes: usize, bits: u32, n: usize) -> bool {
|
||||
ROBUSTNESS_METRICS
|
||||
.iter()
|
||||
.all(|&m| run_variant(base, passes, bits, m, n).drives_to_chance())
|
||||
}
|
||||
|
||||
/// Smallest pass budget that collapses re-ID for a *specific* identity count.
|
||||
/// More candidates ⇒ lower chance floor ⇒ generally more mixing required, so
|
||||
/// this grows with `n`.
|
||||
#[must_use]
|
||||
pub fn min_passes_for_n(base: &ExperimentConfig, bits: u32, n: usize) -> Option<usize> {
|
||||
PASS_CANDIDATES
|
||||
.iter()
|
||||
.copied()
|
||||
.find(|&p| passes_collapse_at_n(base, p, bits, n))
|
||||
}
|
||||
|
||||
/// Derive a ready-to-ship shield for a specific deployment: throughput-optimal
|
||||
/// feedback resolution for the deployment SNR, and the minimum mixing budget for
|
||||
/// its identity count grown by the free [`PRIVACY_MARGIN_FACTOR`] margin. This is
|
||||
/// what an operator should call for a room with `n` expected occupants on a link
|
||||
/// with `base.link`'s SNR — the default config is just this at N=16.
|
||||
#[must_use]
|
||||
pub fn adaptive_shield(base: &ExperimentConfig, n: usize) -> ShieldConfig {
|
||||
let (bits, _) = spec_optimal_feedback_bits(base);
|
||||
let min_passes =
|
||||
min_passes_for_n(base, bits, n).unwrap_or_else(|| *PASS_CANDIDATES.last().unwrap());
|
||||
ShieldConfig {
|
||||
givens_passes: ceil_to_candidate(min_passes * PRIVACY_MARGIN_FACTOR),
|
||||
feedback_bits: bits,
|
||||
..base.shield.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -297,6 +368,50 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optimal_bits_shift_with_snr() {
|
||||
// Low-SNR deployments favor higher feedback resolution; high-SNR favor
|
||||
// lower. The (unconstrained) profile is non-increasing in SNR and not
|
||||
// constant across the range.
|
||||
let profile = optimal_bits_across_snr(&ExperimentConfig::default());
|
||||
let low = profile.first().unwrap().1;
|
||||
let high = profile.last().unwrap().1;
|
||||
assert!(
|
||||
low >= high,
|
||||
"low-SNR bits {low} should be >= high-SNR bits {high}"
|
||||
);
|
||||
assert!(low != high, "profile did not shift with SNR: {profile:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn adaptive_shield_mixing_is_nondecreasing_in_n() {
|
||||
// A room with more candidate identities needs at least as much mixing.
|
||||
// In this model the collapse budget is governed by fine-subspace
|
||||
// dimension, so the requirement is flat across N — the invariant we can
|
||||
// assert is non-decreasing, and that it never *under*-provisions.
|
||||
let base = ExperimentConfig::default();
|
||||
let small = adaptive_shield(&base, 8);
|
||||
let large = adaptive_shield(&base, 64);
|
||||
assert!(
|
||||
large.givens_passes >= small.givens_passes,
|
||||
"N=64 passes {} should be >= N=8 passes {}",
|
||||
large.givens_passes,
|
||||
small.givens_passes
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn adaptive_shield_collapses_at_its_target_n() {
|
||||
let base = ExperimentConfig::default();
|
||||
for n in [8usize, 32, 64] {
|
||||
let sh = adaptive_shield(&base, n);
|
||||
assert!(
|
||||
passes_collapse_at_n(&base, sh.givens_passes, sh.feedback_bits, n),
|
||||
"adaptive shield for N={n} does not collapse"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frontier_is_non_empty_and_deterministic() {
|
||||
// Small grid keeps this fast; the frontier logic is grid-size agnostic.
|
||||
|
||||
Reference in New Issue
Block a user