mirror of
https://github.com/ruvnet/RuView
synced 2026-07-22 17:23:19 +00:00
feat(adr-185): P1 AETHER bindings (wifi_densepose.aether) + parity harness
Bind the ADR-024 contrastive CSI embedding surface into the wheel behind
a gated [aether] extra / Cargo `aether` feature, per ADR-185 section 3.2.
Surface (bound against the REAL code at HEAD, not the ADR wishlist):
- AetherConfig -> EmbeddingConfig {d_model,d_proj,temperature,normalize}
- CsiAugmenter -> augment_pair(window, seed)
- EmbeddingExtractor -> embed(csi): 128-dim L2-normed, GIL-released
- info_nce_loss, cosine_similarity (module fns)
ADR-185 section 3.2 also names aether_loss/VICReg components,
alignment_metric, uniformity_metric, forward_dual, and vicreg_* config
fields. None exist in embedding.rs at HEAD, so they are intentionally NOT
bound (a Rust-side gap, not a binding gap) rather than fabricated.
Parity (section 4.1, release-blocking): committed fixture
aether_input.json -> native Rust reference (tests/aether_parity.rs, calls
sensing-server EmbeddingExtractor directly) locks
tests/golden/aether_embedding.sha256; pytest (tests/test_aether.py) runs
the same fixture through the binding and asserts the identical SHA-256 of
the LE f32 bytes. Both pass.
Verified: cargo test --features aether --test aether_parity -> 2/2 pass;
maturin develop --features aether + pytest tests/test_aether.py -> 9/9
pass; default cargo build clean with 0 sensing-server refs in the dep
graph (gate keeps the base wheel lean).
HONEST WHEEL-SIZE FINDING (ADR-185 section 9 / Open Q 11.1, unresolved):
wifi-densepose-sensing-server is an Axum/tokio crate whose tokio/axum/
worldgraph/ruvector deps are NON-optional (only mqtt/matter are
features), so default-features=false does NOT drop them. An [aether]
wheel therefore links the full server tree and BREAKS the ADR-117 section
5.4 <=5 MB budget. The fix is the ADR-sanctioned hoist of embedding.rs
(+ its graph_transformer/sona siblings) into a leaf crate so the wheel
links pure compute only -- a change INSIDE wifi-densepose-sensing-server,
owned by another agent this session, so deferred as a required
pre-release follow-up. P1 binds real code and proves parity today; the
hoist is a wheel-size optimization, not a functional blocker.
Note: building required initializing the worldgraph/rufield/ruvector
submodules (absent in the fresh worktree).
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
"""ADR-185 P1 — AETHER binding tests, incl. the §4.1 bit-for-bit parity gate.
|
||||
|
||||
The parity test packs the binding's embedding to little-endian f32 bytes
|
||||
and asserts its SHA-256 equals the committed golden produced by the
|
||||
native-Rust reference (`tests/aether_parity.rs`). A mismatch is a
|
||||
release blocker, not a warning.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import struct
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from wifi_densepose import aether
|
||||
|
||||
GOLDEN = Path(__file__).parent / "golden"
|
||||
|
||||
|
||||
def load_input() -> list[list[float]]:
|
||||
return json.loads((GOLDEN / "aether_input.json").read_text())
|
||||
|
||||
|
||||
def build_extractor() -> aether.EmbeddingExtractor:
|
||||
# Must match the native-Rust reference construction exactly.
|
||||
cfg = aether.AetherConfig(d_model=64, d_proj=128, temperature=0.07, normalize=True)
|
||||
return aether.EmbeddingExtractor(n_subcarriers=56, config=cfg)
|
||||
|
||||
|
||||
def test_config_roundtrips_fields() -> None:
|
||||
cfg = aether.AetherConfig(d_model=64, d_proj=128, temperature=0.07, normalize=True)
|
||||
assert cfg.d_model == 64
|
||||
assert cfg.d_proj == 128
|
||||
assert abs(cfg.temperature - 0.07) < 1e-6
|
||||
assert cfg.normalize is True
|
||||
|
||||
|
||||
def test_embedding_shape_and_unit_norm() -> None:
|
||||
emb = build_extractor().embed(load_input())
|
||||
assert len(emb) == 128
|
||||
norm = math.sqrt(sum(x * x for x in emb))
|
||||
assert abs(norm - 1.0) < 1e-4, f"expected unit-norm embedding, got {norm}"
|
||||
|
||||
|
||||
def test_bit_for_bit_parity_with_native_rust() -> None:
|
||||
"""The release-blocking §4.1 gate: binding output == native Rust, byte-for-byte."""
|
||||
emb = build_extractor().embed(load_input())
|
||||
packed = b"".join(struct.pack("<f", x) for x in emb)
|
||||
got = hashlib.sha256(packed).hexdigest()
|
||||
expected = (GOLDEN / "aether_embedding.sha256").read_text().strip()
|
||||
assert got == expected, (
|
||||
"Python binding embedding diverged from the native-Rust golden "
|
||||
f"({got} != {expected}) — PyO3 marshalling is not byte-identical."
|
||||
)
|
||||
|
||||
|
||||
def test_embedding_is_deterministic() -> None:
|
||||
ext = build_extractor()
|
||||
inp = load_input()
|
||||
assert ext.embed(inp) == ext.embed(inp)
|
||||
|
||||
|
||||
def test_cosine_similarity_self_is_one() -> None:
|
||||
v = [0.1 * i - 0.5 for i in range(32)]
|
||||
assert abs(aether.cosine_similarity(v, v) - 1.0) < 1e-5
|
||||
|
||||
|
||||
def test_cosine_similarity_orthogonal_is_zero() -> None:
|
||||
a = [1.0, 0.0, 0.0, 0.0]
|
||||
b = [0.0, 1.0, 0.0, 0.0]
|
||||
assert abs(aether.cosine_similarity(a, b)) < 1e-6
|
||||
|
||||
|
||||
def test_info_nce_loss_identical_batch_is_log_n() -> None:
|
||||
# Identical embeddings → all similarities equal → loss == ln(N).
|
||||
emb = [[1.0, 0.0, 0.0]] * 4
|
||||
loss = aether.info_nce_loss(emb, emb, 0.07)
|
||||
assert abs(loss - math.log(4)) < 0.1
|
||||
|
||||
|
||||
def test_augment_pair_preserves_shape_and_differs() -> None:
|
||||
window = load_input()
|
||||
view_a, view_b = aether.CsiAugmenter().augment_pair(window, seed=42)
|
||||
assert len(view_a) == len(window)
|
||||
assert len(view_b) == len(window)
|
||||
assert len(view_a[0]) == len(window[0])
|
||||
differs = any(
|
||||
abs(x - y) > 1e-6
|
||||
for ra, rb in zip(view_a, view_b)
|
||||
for x, y in zip(ra, rb)
|
||||
)
|
||||
assert differs, "augment_pair should return two distinct views"
|
||||
|
||||
|
||||
def test_base_wheel_import_error_message() -> None:
|
||||
# This wheel HAS the extra, so the import succeeds; assert the guard
|
||||
# message is present in source so the base-wheel path stays honest.
|
||||
src = (Path(aether.__file__)).read_text()
|
||||
assert "pip install wifi-densepose[aether]" in src
|
||||
Reference in New Issue
Block a user