8.1 KiB
8.1 KiB
Tasks: enterprise-browser-audio-engine
Change ID: enterprise-browser-audio-engine
Package: @suaveplan/audio-engine
Target path: browser/audio/audio-engine
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/events
1. Scaffold
- Create
browser/audio/audio-engine/withsrc/,tests/,src/__benchmarks__/and all feature subdirectories per the layout inproposal.md. - Write
package.jsonat version0.1.0:"type": "module","sideEffects": falseexportsmap with top-level"."plus subpath per feature moduledependencies:@suaveplan/error workspace:^,@suaveplan/types workspace:^,@suaveplan/events workspace:^,standardized-audio-context catalog:browser,zod catalog:forms,@opentelemetry/api catalog:observability,tslib catalog:builddevDependencies:vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,mitata catalog:testing,@suaveplan/testing workspace:^
- Write
tsconfig.jsonextending@suaveplan/typescript-config/library-browser.json. - Write
vitest.config.tsusingcreateTestConfig()from@suaveplan/testing/configwithpool: 'forks'. - Add
lint,typecheck,test,test:coverage,build,docs:check,benchscripts.
2. Error codes (src/error-codes.ts)
- Define
AudioEngineErrorCodeunion:AUDIO_ENGINE_STATE_INVALID,AUDIO_PLUGIN_NOT_FOUND,AUDIO_PLUGIN_LOAD_FAILED,AUDIO_WORKLET_LOAD_FAILED,AUDIO_WORKLET_URL_REJECTED,AUDIO_GRAPH_CONNECT_FAILED,AUDIO_CONTEXT_UNAVAILABLE. - Define
AUDIO_ENGINE_ERROR_METADATAwith severity, retryable, httpStatus, userMessageKey, category, description per code. - Export
registerAudioEngineErrorCodes()callingErrorCodes.registerMany(...). Call it eagerly at module scope. - Re-export
AudioEngineError extends SuaveplanError(not a local subclass).
3. Types (src/types/common.ts + common.md)
- Define all shared interfaces:
AudioEngineConfig,AudioEngineState,AudioEngineStateInfo,AudioEngineMetrics,AudioEngineEventMap,AudioGraphSnapshot,ParameterCurve,PerformanceMetrics. - Write
common.md(≥200 words, simple + advanced examples, API reference).
4. Plugin system (src/plugin/)
4a. plugin/plugin.ts
- Implement abstract
AudioPluginclass with full lifecycle: state machineuninitialized → initializing → initialized → active ↔ inactive → destroyed, quarantine on error. - Implement parameter get/set with automatable support.
- Write
plugin.test.ts: state transitions, quarantine on thrown init, parameter CRUD. - Write
plugin.md,plugin.types.ts.
4b. plugin-registry/plugin-registry.ts
- Implement
PluginRegistry: register, unregister, get, list, instantiate. - Add Zod schema
AudioPluginDescriptorSchema; validate descriptor on register. - Write
plugin-registry.test.ts,plugin-registry.md,plugin-registry.types.ts.
5. EventBus (src/event-bus/event-bus/)
- Implement
EventBusthin wrapper around@suaveplan/eventsEventEmitter withAudioEngineEventMaptype parameter. - Write
event-bus.test.ts,event-bus.md,event-bus.types.ts.
6. Audio graph (src/graph/)
6a. graph/graph.ts
- Implement
AudioGraph: add/remove/get nodes, connect/disconnect, traverse DFS, snapshot/restore. - Write
graph.test.ts,graph.md,graph.types.ts.
6b. graph-connect/graph-connect.ts
- Extract connection management logic (connect/disconnect with index params, validation,
AUDIO_GRAPH_CONNECT_FAILED). - OTel histogram
audio.graph_connect_ms. - Write
graph-connect.test.ts,graph-connect.md.
6c. graph-traverse/graph-traverse.ts
- Extract DFS traversal with cycle detection.
- Write
graph-traverse.test.ts,graph-traverse.md.
7. Queue engine (src/queue-engine/)
7a. queue-engine/queue-engine.ts
- Implement
AudioQueueEngine: enqueue/dequeue/play/stop, manage cue and sequence collections. - Write
queue-engine.test.ts,queue-engine.md,queue-engine.types.ts.
7b. cue/cue.ts
- Implement
AudioCuescheduling logic (start time, offset, gain, loop viaAudioBufferSourceNode). - Write
cue.test.ts,cue.md.
7c. scheduler/scheduler.ts
- Implement sequence scheduling with tempo and loop support.
- Write
scheduler.test.ts,scheduler.md.
8. Worklet manager (src/worklet/)
8a. worklet-loader/worklet-loader.ts
- Implement
addModule(url, options)with allow-list gate — throwAUDIO_WORKLET_URL_REJECTEDon non-allowed URLs. - Cache loaded module URLs; avoid double-load.
- OTel histogram
audio.worklet_roundtrip_ms. - Write
worklet-loader.test.ts,worklet-loader.md.
8b. worklet-messaging/worklet-messaging.ts
- Implement
postMessage/onMessagewiring per processor name. - Write
worklet-messaging.test.ts,worklet-messaging.md.
8c. worklet-registry/worklet-registry.ts
- Track loaded processors and their associated
AudioWorkletNodefactory. - Write
worklet-registry.test.ts,worklet-registry.md.
9. Engine (src/engine/)
9a. engine-state/engine-state.ts
- Implement state machine:
uninitialized → starting → running → suspended → stopping → stopped → error. Validate transitions; throwAUDIO_ENGINE_STATE_INVALIDon illegal transition. - Write
engine-state.test.ts,engine-state.md.
9b. engine-metrics/engine-metrics.ts
- Collect CPU load estimate via
BaseAudioContext.baseLatency+ analyzer node. - Wire OTel counters
audio.plugin_loaded_total,audio.plugin_failed_total; histogramsaudio.engine_latency_ms. - Write
engine-metrics.test.ts,engine-metrics.md.
9c. engine/engine.ts
- Implement
AudioEngine: constructor with injectedBaseAudioContext, plugin map, load/unload with quarantine, start/stop lifecycle, offline render, exposeAudioGraph,AudioQueueEngine,AudioWorkletManageras members. - Wire quarantine: catch plugin errors, mark
ERROR, disconnect, emitplugin:error, continue. - Write
engine.test.ts(no globalThis touch — use injected context),engine.md,engine.types.ts.
10. Integration tests (tests/integration.test.ts)
- Full
AudioEnginelifecycle: start → load plugin → active → unload → stop using standardized-audio-context. - Graph: connect/disconnect, snapshot/restore, traverse.
- Queue: enqueue → play sequence → loop → stop.
- Worklet: addModule with allow-list passes; rejected URL throws typed error.
- Quarantine: a plugin that throws in
initializedoes not bring down the engine. - Offline render:
renderOffline()returns non-emptyAudioBuffer.
11. Benchmarks (src/__benchmarks__/)
graph.bench.ts: connect/disconnect 100 nodes, traverse 50-node graph.queue.bench.ts: enqueue 1000 cues, dequeue all.worklet.bench.ts: postMessage round-trip latency.
12. Docs
- Write
.mdfor every exported class/type (see layout inproposal.md). - Write
browser/audio/audio-engine/README.mdwith purpose, install, quick-start, subpath table, benchmarks table, dependencies table.
13. Verify and publish
bunx turbo lint --filter=@suaveplan/audio-engine— zero errors.bunx turbo typecheck --filter=@suaveplan/audio-engine— zero errors.bunx turbo test --filter=@suaveplan/audio-engine— all tests pass.bunx turbo test:coverage --filter=@suaveplan/audio-engine— 100% on all touched modules.bun run docs:check --filter=@suaveplan/audio-engine— zero errors.- Confirm no
TODO,FIXME,any,ts-ignore,.skip,vi.mockremain insrc/. "sideEffects": falseset inpackage.json.bun scripts/publish.ts --package @suaveplan/audio-engine.- Update
CLAUDE.mdpackage listing. - Archive: move to
openspec/archive/2026-04-24-enterprise-browser-audio-engine/and fold spec delta intoopenspec/specs/audio/spec.md.