183 lines
8.1 KiB
Markdown
183 lines
8.1 KiB
Markdown
# 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/` with `src/`, `tests/`, `src/__benchmarks__/` and all feature subdirectories per the layout in `proposal.md`.
|
|
- [ ] Write `package.json` at version `0.1.0`:
|
|
- `"type": "module"`, `"sideEffects": false`
|
|
- `exports` map with top-level `"."` plus subpath per feature module
|
|
- `dependencies`: `@suaveplan/error workspace:^`, `@suaveplan/types workspace:^`, `@suaveplan/events workspace:^`, `standardized-audio-context catalog:browser`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`, `tslib catalog:build`
|
|
- `devDependencies`: `vitest catalog:testing`, `@vitest/coverage-istanbul catalog:testing`, `mitata catalog:testing`, `@suaveplan/testing workspace:^`
|
|
- [ ] Write `tsconfig.json` extending `@suaveplan/typescript-config/library-browser.json`.
|
|
- [ ] Write `vitest.config.ts` using `createTestConfig()` from `@suaveplan/testing/config` with `pool: 'forks'`.
|
|
- [ ] Add `lint`, `typecheck`, `test`, `test:coverage`, `build`, `docs:check`, `bench` scripts.
|
|
|
|
---
|
|
|
|
## 2. Error codes (`src/error-codes.ts`)
|
|
|
|
- [ ] Define `AudioEngineErrorCode` union: `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_METADATA` with severity, retryable, httpStatus, userMessageKey, category, description per code.
|
|
- [ ] Export `registerAudioEngineErrorCodes()` calling `ErrorCodes.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 `AudioPlugin` class with full lifecycle: state machine `uninitialized → 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 `EventBus` thin wrapper around `@suaveplan/events` EventEmitter with `AudioEngineEventMap` type 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 `AudioCue` scheduling logic (start time, offset, gain, loop via `AudioBufferSourceNode`).
|
|
- [ ] 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 — throw `AUDIO_WORKLET_URL_REJECTED` on 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` / `onMessage` wiring per processor name.
|
|
- [ ] Write `worklet-messaging.test.ts`, `worklet-messaging.md`.
|
|
|
|
### 8c. `worklet-registry/worklet-registry.ts`
|
|
|
|
- [ ] Track loaded processors and their associated `AudioWorkletNode` factory.
|
|
- [ ] 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; throw `AUDIO_ENGINE_STATE_INVALID` on 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`; histograms `audio.engine_latency_ms`.
|
|
- [ ] Write `engine-metrics.test.ts`, `engine-metrics.md`.
|
|
|
|
### 9c. `engine/engine.ts`
|
|
|
|
- [ ] Implement `AudioEngine`: constructor with injected `BaseAudioContext`, plugin map, load/unload with quarantine, start/stop lifecycle, offline render, expose `AudioGraph`, `AudioQueueEngine`, `AudioWorkletManager` as members.
|
|
- [ ] Wire quarantine: catch plugin errors, mark `ERROR`, disconnect, emit `plugin: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 `AudioEngine` lifecycle: 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 `initialize` does not bring down the engine.
|
|
- [ ] Offline render: `renderOffline()` returns non-empty `AudioBuffer`.
|
|
|
|
---
|
|
|
|
## 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 `.md` for every exported class/type (see layout in `proposal.md`).
|
|
- [ ] Write `browser/audio/audio-engine/README.md` with 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.mock` remain in `src/`.
|
|
- [ ] `"sideEffects": false` set in `package.json`.
|
|
- [ ] `bun scripts/publish.ts --package @suaveplan/audio-engine`.
|
|
- [ ] Update `CLAUDE.md` package listing.
|
|
- [ ] Archive: move to `openspec/archive/2026-04-24-enterprise-browser-audio-engine/` and fold spec delta into `openspec/specs/audio/spec.md`.
|