core/sensorium/audio/checksum.py
Shay 4d59e66043
feat(adr-0181-p2): deterministic audio compiler substrate (sensorium/audio) (#466)
PR-2 of ADR-0181. Lands the deterministic substrate only — no pack artifacts
(PR-3), no evals (PR-4), no Delta-CRDT wiring (PR-5), no teachers (PR-6).

Pipeline (spec §1): canonical signal → frame grid → acoustic lexer →
typed AudioIR → canonical event ordering → elliptic rotor lowering →
versor composition → AudioCompilationUnit (the future CRDT delta).

Modules (sensorium/audio/):
- types.py      frozen AudioSignal/Token/Event/IR + AudioCompilationUnit.merge_key
- checksum.py   layered sha256 chain (source→canonical→token→ir→manifest→projection)
- resample.py   pure-numpy polyphase FIR (scipy absent; FIR taps are a PR-3 artifact)
- canonical.py  mono/24kHz canonicalisation + provenance hashes
- frames.py     20ms/10ms deterministic frame grid (zero-padded tail)
- lexer.py      quantized per-frame descriptors (energy/voicing/zcr/centroid/pYIN-style F0)
- parser.py     runs → typed spans/events (pause/speech/prosody/turn/non-speech)
- operators.py  elliptic-ONLY rotor registry; planes {6,7,8,10,11,13} square to -1
- compiler.py   compile_events serialization barrier (ADR-0181 §2.1) + checksum chain
- trace.py      trace-safe audio evidence (no PCM)

Correctness: v1 restricts to the six elliptic grade-2 planes (e_i e_j, i,j∈{1..4})
so every rotor and every composition is a unit versor — versor_condition < 1e-6
holds without weakening the threshold (CLAUDE.md §Non-Negotiable Field Invariant).
Non-elliptic blades (those touching e5) are rejected at OperatorSpec construction.

Tests (tests/test_audio_compiler.py, 13 passed): A-1 determinism, A-4 serialization
barrier order-sensitivity, A-5 versor condition, A-6 trace hygiene, IR-replay,
shape/dtype, elliptic-plane lawfulness. Smoke 67 + arch-invariants 40 green.

No core mutation: ingest/field/generate/vault/vocab untouched (ADR-0013).
unitize_versor is the only normalization, algebra-owned (CLAUDE.md §Normalization).
2026-05-29 10:50:28 -07:00

38 lines
1.4 KiB
Python

"""
sensorium/audio/checksum.py — the layered checksum chain (ADR-0181 §2.2, spec §6).
source_sha256 → canonical_sha256 → token_stream_sha256 → ir_sha256
→ pack_manifest_sha256 → projection_sha256
Every link is content-addressed. The merge key
(canonical_sha256, ir_sha256, projection_sha256) is derived from these and is
what makes audio deltas idempotent under the Delta-CRDT join (ADR-0181 §2.2).
Hashing arrays uses the *exact bytes that would be written to disk* — the same
discipline CLAUDE.md §Semantic Pack Discipline requires of manifest checksums.
Floats are hashed as canonical float32 bytes so the hash is stable across the
float64 internal compute path (spec §7: cast to float32 only at the boundary).
"""
from __future__ import annotations
import hashlib
import json
from typing import Any
import numpy as np
def sha256_bytes(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def sha256_array(arr: np.ndarray) -> str:
"""Hash an array by its canonical float32 byte image."""
return sha256_bytes(np.ascontiguousarray(arr, dtype=np.float32).tobytes())
def sha256_json(obj: Any) -> str:
"""Hash a JSON-serialisable object with sorted keys / stable separators."""
serialized = json.dumps(obj, sort_keys=True, ensure_ascii=False, separators=(",", ":"))
return sha256_bytes(serialized.encode("utf-8"))