core/tests/test_audio_pack_manifest.py
Shay 7f619d44e5
feat(adr-0181-p3): audio_core_v1 pack + AudioProjectionHead (gate-closed) (#467)
PR-3 of ADR-0181. Externalises the PR-2 in-code operator registry to a
versioned, checksum-locked pack and wires the sensorium adapter. Mounts
gate-closed until the PR-4 eval gates pass. No core mutation (ADR-0013).

Pack (packs/audio/audio_core_v1/):
- manifest.json   canonical params, resampling config, gating defaults, ordering
- operators.jsonl the 8 elliptic operators (byte-equivalent to DEFAULT_OPERATOR_REGISTRY)
- basis_map.json  alias→index over the six elliptic planes {6,7,8,10,11,13}
- resample_fir_v1.npy  pinned odd-length symmetric windowed-sinc low-pass (unit DC)
- checksums.json  sha256 of every artifact

Loader (packs/audio/loader.py) — trust boundary (ADR-0051 / CLAUDE.md §Security):
- _validate_pack_id rejects traversal/separators/dotfiles before any path join
- fail-closed checksum verification: every file re-hashed vs checksums.json
- resolved path must stay under the packs root (defense in depth)
- JSON format (matches every other CORE pack loader; spec §6.1 TOML was
  illustrative; no tomllib dependency added)

Adapter (sensorium/adapters/audio.py):
- AudioProjectionHead wraps AudioCompiler; project(AudioSignal)->(32,) f32
- make_audio_pack loads+verifies the pack, builds a gate-closed ModalityPack

Tests (19): PR-2↔PR-3 registry byte-parity via manifest_sha256, elliptic-only
operators, FIR integrity, fail-closed checksum mismatch, path-traversal guard,
gate-closed refusal, mount-time unitarity (+ bad-unitarity blocks mount),
gate-engage requires checksum_verified, engaged pack projects (32,) f32.

All audio 32 + arch-invariants 40 + smoke 67 green.
2026-05-29 11:05:57 -07:00

71 lines
2.7 KiB
Python

"""
ADR-0181 PR-3 — audio pack manifest + loader trust boundary.
Covers:
- the loaded operator registry is byte-equivalent to the in-code
DEFAULT_OPERATOR_REGISTRY (PR-2 ↔ PR-3 parity, via manifest_sha256);
- fail-closed checksum verification (tampered artifact blocks load);
- the ADR-0051 path-traversal guard;
- the pinned FIR artifact integrity.
"""
from __future__ import annotations
import shutil
import pytest
from packs.audio.loader import AudioPackError, load_audio_pack
from sensorium.audio.operators import DEFAULT_OPERATOR_REGISTRY, ELLIPTIC_PLANES
def test_pack_loads_and_verifies():
pack = load_audio_pack("audio_core_v1")
assert pack.pack_id == "audio_core_v1"
assert pack.manifest["cl41_dim"] == 32
assert pack.manifest["gating"]["gate_engaged"] is False # ships gate-closed
def test_loaded_registry_is_byte_equivalent_to_in_code_default():
"""The pack artifact and the in-code DEFAULT_OPERATOR_REGISTRY must produce
the identical content hash — PR-3 externalises PR-2 without drift."""
pack = load_audio_pack("audio_core_v1")
assert pack.registry.manifest_sha256() == DEFAULT_OPERATOR_REGISTRY.manifest_sha256()
assert set(pack.registry.specs) == set(DEFAULT_OPERATOR_REGISTRY.specs)
def test_all_loaded_operators_are_elliptic():
pack = load_audio_pack("audio_core_v1")
for spec in pack.registry.specs.values():
assert spec.blade_index in ELLIPTIC_PLANES
def test_fir_artifact_is_odd_length_and_matches_manifest():
pack = load_audio_pack("audio_core_v1")
assert pack.fir is not None
assert pack.fir.ndim == 1 and pack.fir.size % 2 == 1 # zero-phase symmetric
assert pack.fir_sha256.endswith(pack.manifest["resampling"]["fir_sha256"])
# --- trust boundary -------------------------------------------------------
def test_checksum_mismatch_fails_closed(tmp_path):
"""A tampered artifact must block the load (eval-plan §2 mount validation)."""
from packs.audio.loader import _PACKS_ROOT
dst = tmp_path / "audio_core_v1"
shutil.copytree(_PACKS_ROOT / "audio_core_v1", dst)
# Corrupt operators.jsonl without updating checksums.json.
(dst / "operators.jsonl").write_text((dst / "operators.jsonl").read_text() + "\n")
with pytest.raises(AudioPackError, match="checksum mismatch"):
load_audio_pack("audio_core_v1", packs_root=tmp_path)
@pytest.mark.parametrize("bad_id", ["..", "../secrets", "a/b", "a\\b", ".hidden", ""])
def test_path_traversal_rejected(bad_id):
with pytest.raises(AudioPackError):
load_audio_pack(bad_id)
def test_missing_pack_fails_closed(tmp_path):
with pytest.raises(AudioPackError, match="no audio pack"):
load_audio_pack("audio_core_v1", packs_root=tmp_path)