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

6.0 KiB

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.