Files
2026-05-27 23:29:53 +01:00

96 lines
6.0 KiB
Markdown

# Enterprise Migration: @suaveplan/audio-engine
**Package**: `@suaveplan/audio-engine`
**Status**: PROPOSED
**Type**: new-package (migration from suaveplan)
## Why
`@suaveplan/audio-engine` is the core browser-side Web Audio engine used by every audio surface in the monorepo. It owns the `AudioContext` lifecycle, typed plugin system (`AudioPlugin` + `PluginRegistry`), `AudioGraph` node-routing, `AudioWorkletManager`, `AudioQueueEngine`, and `EventBus`. Migrating it to genesis is a prerequisite for `audio-plugins-fx`, `audio-controllers`, and all `react-audio*` packages. The upstream version lacks tests for graph / queue / worklet / registry, exceeds file-size caps, uses plain `Error` throws, and has no OTel or Zod boundaries.
## What changes
- ADDED: `AudioEngine` class with `AudioContext` injection seam — initialize, resume, suspend, destroy, plugin lifecycle, metrics.
- ADDED: `AudioGraph` class — node add/remove, connect/disconnect with cycle detection, topological sort, BFS path finding, serialization.
- ADDED: `AudioQueueEngine` class — extends `AudioEngine` with `@suaveplan/queue`-based serial/parallel plugin chains, retry, rate limiting.
- ADDED: `AudioWorkletManager` class — module loading, node creation, messaging, statistics.
- ADDED: `PluginRegistry` class — constructor + descriptor registration, dependency validation, search, instantiation.
- ADDED: `EventBus` class — typed wrapper around `@suaveplan/events` with per-listener error isolation.
- ADDED: `AudioPlugin` abstract base class — state machine, metadata, parameters, node accessors.
- ADDED: Error codes via `@suaveplan/error` (`AUDIO_ENGINE_STATE_INVALID`, `PLUGIN_NOT_FOUND`, `GRAPH_CYCLE_DETECTED`, `WORKLET_LOAD_FAILED`, etc.).
- ADDED: Zod boundary schemas for `AudioEngineConfig`, `PluginMetadata`, `AudioPluginDescriptor`.
- ADDED: OTel counters/histograms for plugin loads, engine latency, worklet round-trip, graph connect duration.
- ADDED: Plugin quarantine — a crashing plugin is marked `ERROR` without tearing down the engine or other plugins.
- ADDED: Worklet module URL allow-list gate.
- ADDED: Co-located `.md` docs for every exported symbol.
- ADDED: Benchmarks for graph traversal and worklet messaging.
## Out of scope
- Plugin hot-swap with crossfade ramp — new feature, not in upstream; deferred to follow-up change.
- Latency budget enforcement / watchdog — new feature; deferred.
- MIDI clock source transport — new feature; deferred.
- Sample-accurate parameter automation curves — new feature; deferred.
- `SharedArrayBuffer`-backed meter/analyser — new feature; deferred.
- Worklet hot-reload for dev-time — new feature; deferred.
- `OfflineAudioContext` render-on-demand mode — new feature; deferred.
- `ScriptProcessorNode` fallback for non-worklet browsers — upstream uses `standardized-audio-context` which handles this; we retain the upstream abstraction level without adding a new fallback layer.
## Source mapping
This change derives from `../suaveplan/enterprise/audio-engine.md`.
| Requirement | Source lines | Notes |
|---|---|---|
| Split files over 300-line cap | L46 | engine → engine + state + metrics; graph → graph + connect + traverse; queue → queue + cue + scheduler; worklet → loader + messaging + registry |
| Unit tests for every module | L47 | graph, queue, worklet, registry, plugin base, event-bus |
| AudioContext injection seam | L48 | constructor accepts pre-built context |
| Typed event map | L49 | replaces `AudioEngineEvents` enum |
| OTel metrics | L50 | counters + histograms |
| Worklet URL allow-list | L52 | security gate |
| Plugin lifecycle docs | L53 | state diagram in README + per-symbol `.md` |
| Coverage ≥ 95 % | L57 | genesis policy is 100 % |
| File budget 250/300/500 | L59 | enforced |
| No `any` / `ts-ignore` | L64 | enforced |
| Zod schemas at boundaries | L65 | `PluginMetadata`, `AudioPluginDescriptor` |
| Error hierarchy | L66 | via `@suaveplan/error` |
| Plugin quarantine | L111 | error isolation per plugin |
### Requirements with no source line
| Requirement | Justification |
|---|---|
| 100 % Istanbul coverage threshold | Genesis-wide policy (AGENTS.md §5, §13) |
| No direct `vitest` imports | Genesis-wide policy (AGENTS.md §7) |
| `export *` banned in feature barrels | Genesis-wide policy (AGENTS.md §6a) |
| `sideEffects: false` retained | Genesis-wide policy |
## Verification approach
- `src/engine/engine.test.ts` — AudioEngine lifecycle, state transitions, plugin load/unload, metrics, destruction.
- `src/engine/engine.spec-conformance.test.ts` — OTel instrument assertions, Zod boundary rejection, typed event map.
- `src/graph/graph.test.ts` — node management, connect/disconnect, cycle detection, topological sort, path finding, serialization.
- `src/graph/graph.spec-conformance.test.ts` — strict-mode error paths, graph stats, clone round-trip.
- `src/queue-engine/queue-engine.test.ts` — serial/parallel chain processing, retry, rate limit, queue status.
- `src/worklet/worklet-manager.test.ts` — module load/unload, node create/destroy, messaging, statistics.
- `src/worklet/worklet-manager.spec-conformance.test.ts` — URL allow-list rejection, OTel round-trip histogram.
- `src/registry/plugin-registry.test.ts` — constructor/descriptor registration, dependency validation, search, instantiation.
- `src/event-bus/event-bus.test.ts` — subscribe/unsubscribe, emit, listener error isolation.
- `src/plugin/plugin-base.test.ts` — AudioPlugin abstract class, state machine, parameter get/set.
- `tests/purity.test.ts` — zero import-time side effects, no global mutation.
- `tests/integration.test.ts` — full engine + graph + registry round-trip.
- `src/__benchmarks__/graph.bench.ts` — graph traversal performance.
- `src/__benchmarks__/worklet.bench.ts` — worklet messaging round-trip.
## Migration impact
Packages awaiting this dependency:
- `@suaveplan/audio-plugins-fx`
- `@suaveplan/audio-controllers`
- `@suaveplan/react-audio`
- `@suaveplan/react-audio-player`
- `@suaveplan/react-audio-stream`
- `@suaveplan/r3f-audio`
None are yet migrated, so impact is sequencing-only.