Files
suaveplan/openspec/archive/2026-05-15-superseded-enterprise-browser-audio-controllers/tasks.md
2026-05-27 23:29:53 +01:00

139 lines
6.4 KiB
Markdown

# Tasks: enterprise-browser-audio-controllers
**Change ID**: enterprise-browser-audio-controllers
**Package**: `@suaveplan/audio-controllers`
**Target path**: `browser/audio/audio-controllers`
**Prerequisite packages on Verdaccio**: `@suaveplan/audio-engine`, `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`
---
## 1. Scaffold
- [ ] Create `browser/audio/audio-controllers/` directory tree per layout in `proposal.md`.
- [ ] Write `package.json` at version `0.1.0`:
- `"sideEffects": false`
- `exports`: top-level `"."` plus subpaths for each controller and sequencer
- `dependencies`: `@suaveplan/audio-engine workspace:^`, `@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`, `@suaveplan/testing workspace:^`, `@playwright/test catalog:testing`
- [ ] Write `tsconfig.json` and `vitest.config.ts` (pool: forks).
---
## 2. Error codes (`src/error-codes.ts`)
- [ ] Define `MidiControllerErrorCode`: `MIDI_UNAVAILABLE`, `MIDI_PERMISSION_DENIED`, `MIDI_DEVICE_DISCONNECTED`, `MIDI_SYSEX_REJECTED`, `CONTROLLER_PRESET_INVALID`, `SAMPLE_LOADER_FAILED`.
- [ ] Export `registerMidiControllerErrorCodes()` and call eagerly.
---
## 3. Base class (`src/base/midi-controller-plugin/`)
- [ ] Implement abstract `MidiControllerPlugin extends AudioPlugin`:
- `requestMIDIAccess(sysex?: boolean)`: calls `navigator.requestMIDIAccess`; throws typed `MIDI_UNAVAILABLE` / `MIDI_PERMISSION_DENIED` on failure.
- `onStateChange(event: MIDIConnectionEvent)`: detects disconnect / reconnect, emits typed events, auto-rebinds.
- `flushLEDs(updates: LEDUpdate[])`: diff engine with per-frame byte budget.
- `defineMappings(mappings: CCMapping[])`: CC-learn DSL storage.
- Protected `EventEmitter<MidiControllerEventMap>` member — all subclasses use it.
- [ ] Write `midi-controller-plugin.test.ts`: permission flow, hot-plug disconnect + reconnect, LED flush budget.
- [ ] Write `midi-controller-plugin.md`.
---
## 4. Shared sequencer (`src/sequencer/sequencer/`)
- [ ] Implement `Sequencer`: audio-clock-synced step grid, tempo (BPM), step on/off, playback start/stop/reset.
- [ ] Clock source: inject via constructor (accepts `AudioContext` for `currentTime`-based scheduling, not `setInterval`).
- [ ] Write `sequencer.test.ts`, `sequencer.md`.
---
## 5. KontrolS88Plugin (`src/plugins/kontrol-s88/`)
- [ ] `mapping.ts`: CC/note-number → parameter map, type-safe DSL.
- [ ] `state.ts`: `KeyState[]`, `TransportState` machine.
- [ ] `arpeggio.ts`: `ArpMode` implementations (up/down/random/chord), clock-synced via shared `Sequencer`.
- [ ] `scale.ts`: `ScaleMode` quantizer (major, minor, chromatic, etc.), chord voicing.
- [ ] `led.ts`: per-key LED feedback, batch flush.
- [ ] `preset.ts`: `KontrolS88Preset` Zod schema, serialize/deserialize.
- [ ] `kontrol-s88.ts`: plugin orchestrator, hooks into `MidiControllerPlugin` base.
- [ ] `kontrol-s88.test.ts`: MIDI byte → state, state → MIDI out, velocity curve, scale transform, arpeggio clock, preset round-trip, hot-plug disconnect + reconnect.
- [ ] `kontrol-s88.md`.
---
## 6. MaschinePlugin (`src/plugins/maschine/`)
- [ ] `mapping.ts`: pad/CC/button mapping.
- [ ] `state.ts`: pad grid state, group states.
- [ ] `sequencer.ts`: 16-step sequencer per pad using shared `Sequencer`.
- [ ] `sample-loader.ts`: real `SampleLoader` interface — no placeholder; loads via `AudioContext.decodeAudioData`.
- [ ] `preset.ts`: `MaschinePreset` Zod schema.
- [ ] `maschine.ts`: plugin orchestrator. Event system wired via `EventEmitter` — no placeholder comments.
- [ ] `maschine.test.ts`: pad velocity, step grid, sample load, preset round-trip.
- [ ] `maschine.md`.
---
## 7. TraktorS4Plugin (`src/plugins/traktor-s4/`)
- [ ] `mapping.ts`: CC/button mapping per channel.
- [ ] `deck.ts`: `DeckState`, load/play/pause/cue/sync, pitch/tempo.
- [ ] `mixer.ts`: channel volumes, EQ per channel, master gain.
- [ ] `led.ts`: LED ring/button feedback.
- [ ] `preset.ts`: `TraktorS4Preset` Zod schema.
- [ ] `traktor-s4.ts`: plugin orchestrator. Event system wired — no placeholder comments.
- [ ] `traktor-s4.test.ts`: crossfader, deck sync, mixer state, preset round-trip.
- [ ] `traktor-s4.md`.
---
## 8. Learn mode (`src/learn/learn-mode/`)
- [ ] Implement `LearnMode`: listens for MIDI CC events, stores custom remapping, persists via injected `StorageAdapter`.
- [ ] Default adapter: in-memory; inject `@suaveplan/storage-browser` for durable persistence.
- [ ] Write `learn-mode.test.ts`, `learn-mode.md`.
---
## 9. SysEx fuzz test (`tests/integration.test.ts`)
- [ ] Write a property-based test (fast-check) that feeds malformed SysEx byte arrays to `onMIDIMessage` on each controller and verifies the plugin does not crash and emits a typed `MIDI_SYSEX_REJECTED` event or safely ignores.
---
## 10. Playwright E2E (`tests/e2e/`)
- [ ] Write E2E spec using a virtual MIDI device (Web MIDI API mock via Playwright page context) for each controller:
- KontrolS88: MIDI note-on → `KeyState` update, arpeggio output, LED feedback.
- Maschine: pad velocity → step sequencer trigger.
- TraktorS4: crossfader CC → mixer state.
- [ ] Verify hot-plug: simulate device disconnect + reconnect event.
---
## 11. OTel metrics
- [ ] Wire in `MidiControllerPlugin` base:
- Counter `midi.messages_in_total{controller}`, `midi.messages_out_total{controller}`
- Counter `led.frames_total{controller}`
- Histogram `midi.input_to_audio_latency_ms{controller}`
---
## 12. Docs
- [ ] Write `.md` for every exported module (≥200 words, API reference, examples).
- [ ] Write `README.md` with controller matrix table (every supported CC/note/pad per device), preset-pack list, MIDI permission guidance.
---
## 13. Verify and publish
- [ ] `bunx turbo lint typecheck test --filter=@suaveplan/audio-controllers` — green.
- [ ] `bunx turbo test:coverage --filter=@suaveplan/audio-controllers` — 100%.
- [ ] `bun run docs:check --filter=@suaveplan/audio-controllers` — zero errors.
- [ ] No `TODO`, placeholder, `any`, `ts-ignore`, `vi.mock`, `.skip` in `src/`.
- [ ] Playwright E2E green for all three controllers.
- [ ] `bun scripts/publish.ts --package @suaveplan/audio-controllers`.
- [ ] Archive to `openspec/archive/2026-04-24-enterprise-browser-audio-controllers/`.