# Tasks: enterprise-audio-sprite-player Ordered implementation checklist. Each task is a discrete, checkable item; an unchecked item at the end means the package is not done. ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] 1.1 Create `packages/media/audio/audio-sprite-player/` with `package.json` (`name: "@suaveplan/audio-sprite-player"`, `version: "0.1.0"`, `private: false`, `sideEffects: false`, `type: "module"`). - [ ] 1.2 Declare runtime deps: `@suaveplan/audio-core workspace:^`, `@suaveplan/audio-sprite-packer workspace:^`, `@suaveplan/error workspace:^`, `@suaveplan/types workspace:^`, `@suaveplan/events workspace:^`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`, `tslib catalog:build`. - [ ] 1.3 Declare dev deps via catalog: `vitest`, `@vitest/coverage-istanbul`, `fast-check`, `mitata`, `tsup`, `typescript`, `@suaveplan/testing workspace:^`. - [ ] 1.4 Add `exports` map for every subpath declared in the proposal module layout, plus the root entry. - [ ] 1.5 Add `tsup.config.ts` (ESM + CJS, dual emit, no minify). - [ ] 1.6 Add `vitest.config.ts` using `createTestConfig()` from `@suaveplan/testing/config`; `provider: 'istanbul'`, `pool: 'forks'`, `fileParallelism: false`. - [ ] 1.7 Add `tsconfig.json` extending `@suaveplan/typescript-config/universal.json`. - [ ] 1.8 Run `bun scripts/folder-reorg/generate-manifest.ts` to refresh `MANIFEST.md`. ## 2. Types, errors, schemas - [ ] 2.1 Author `src/sprite-player/sprite-player.types.ts` — `SpritePlayerOptions`, `PlayOptions`, `SequenceOptions`, `ResolvedPlayOptions`, `SpritePlayHandle`. - [ ] 2.2 Author `src/adapter/adapter.types.ts` — `SpritePlaybackAdapter` interface. - [ ] 2.3 Author `src/error-codes.ts` registering every `AUDIO_SPRITE_PLAYER.*` code via `defineCodes(...)` with i18n keys and severity. - [ ] 2.4 Author `src/schemas.ts` — Zod schemas for `SpritePlayerOptionsSchema`, `PlayOptionsSchema`, `SequenceOptionsSchema`, and a manifest validator re-using shapes from `@suaveplan/audio-sprite-packer` (type-only) by hand-defining the equivalent runtime Zod schema (since we cannot import runtime Zod schemas from the type-only consumer). ## 3. NullSpritePlaybackAdapter - [ ] 3.1 `src/adapter/null/null.ts` — implementation that records every call. - [ ] 3.2 `src/adapter/null/null.test.ts` — verifies `calls` order, handle behaviour, type-only-import compile check. - [ ] 3.3 `src/adapter/null/null.md` and `src/adapter/adapter.md` — documented contract. ## 4. VoiceManager + voice-stealing - [ ] 4.1 `src/voice-manager/voice-manager.ts` — tracks active handles, picks oldest, emits `voice-stolen`, exposes opt-out leading to `VOICE_LIMIT_EXCEEDED`. - [ ] 4.2 `src/voice-manager/voice-manager.test.ts` — covers steal-on-overflow, idempotent stop after steal, opt-out path. - [ ] 4.3 `src/voice-manager/voice-manager.md`. ## 5. SpritePlayer orchestrator - [ ] 5.1 `src/sprite-player/sprite-player.ts` — public class. Wires construction validation, `load`, `play`, `playSequence`, `playRandom`, `stopAll`, `list`, `has`, `dispose`. - [ ] 5.2 `src/sprite-player/sprite-player.test.ts` — covers every spec scenario named in the delta under this module path. - [ ] 5.3 `src/sprite-player/sprite-player.md`. ## 6. Events wiring - [ ] 6.1 `src/events/events.ts` — typed `SpritePlayerEvents` built on `@suaveplan/events` with the five event names. - [ ] 6.2 `src/events/events.test.ts` — covers play→complete, voice-stolen payload, error event on async failure. - [ ] 6.3 `src/events/events.md`. ## 7. OTel wiring - [ ] 7.1 `src/telemetry/telemetry.ts` — span `audio-sprite-player.play`, counter `audio_sprite_player.play_total`, gauge `audio_sprite_player.voices_active`, histogram `audio_sprite_player.play_duration_ms`. - [ ] 7.2 `src/telemetry/telemetry.test.ts` — uses `@opentelemetry/api` in-memory exporter to verify each instrument fires. - [ ] 7.3 `src/telemetry/telemetry.md`. ## 8. AbortSignal wiring - [ ] 8.1 Pre-aborted signal short-circuit on `load`, `play`, `playSequence`, `playRandom`. - [ ] 8.2 Mid-flight abort path stops in-flight voices and rejects with `AUDIO_SPRITE_PLAYER.ABORTED`. - [ ] 8.3 Tests for both paths in `sprite-player.test.ts`. ## 9. Barrel + exports - [ ] 9.1 `src/index.ts` uses explicit named re-exports only (rule 10) — no `export *`. - [ ] 9.2 Every feature folder's `index.ts` is an explicit named barrel. - [ ] 9.3 Smoke test in `sprite-player.test.ts` iterates `package.json#exports` and imports each subpath. ## 10. Tests - [ ] 10.1 All `.test.ts` files import test-runner primitives from `@suaveplan/testing/runner` ONLY (rule 11). - [ ] 10.2 No `vi.mock` / `jest.mock` (rule 2). - [ ] 10.3 Use `FakeClock` from `@suaveplan/testing` for deterministic `clock.now()` and scheduling tests. - [ ] 10.4 `bunx turbo test --filter=@suaveplan/audio-sprite-player` green. - [ ] 10.5 `bunx turbo test:coverage --filter=@suaveplan/audio-sprite-player` shows 100% on touched modules. ## 11. Benchmarks - [ ] 11.1 `bench/play.bench.ts` using `mitata` — measure `play()` overhead with `NullSpritePlaybackAdapter` (target: < 50 µs P50, voice-stealing path < 100 µs P50). - [ ] 11.2 `bench/sequence.bench.ts` — measure `playSequence` scaling at 1, 10, 100 entries. ## 12. Docs - [ ] 12.1 Every `.ts` (excl. `.test.ts`, `.types.ts` inside feature dirs, barrel `index.ts`) has a sibling `.md` meeting `docs:check` thresholds (≥200 words, all required sections, basic + advanced example). - [ ] 12.2 Author `README.md` at the package root (no category-level READMEs). - [ ] 12.3 `bunx turbo docs:check --filter=@suaveplan/audio-sprite-player` green. ## 13. Pre-publish gates - [ ] 13.1 `bunx turbo lint --filter=@suaveplan/audio-sprite-player` green; no `// biome-ignore` comments anywhere in `src/` (rule 9). - [ ] 13.2 `bunx turbo typecheck --filter=@suaveplan/audio-sprite-player` green. - [ ] 13.3 `bun scripts/lint/check-test-runner-imports.ts` green for this package (rule 11 CI gate). - [ ] 13.4 `grep -rn "@deprecated\|TODO\|FIXME\|ts-ignore\|ts-expect-error\|\.skip\|\.only\|\bany\b\|console\.log" packages/media/audio/audio-sprite-player/src/ --include="*.ts"` returns zero matches (§2). - [ ] 13.5 `grep -rnE "from ['\"](vitest|bun:test)['\"]" packages/media/audio/audio-sprite-player/src/` returns zero matches (rule 11 verification). - [ ] 13.6 Dist-purity check: `dist/` references no browser/Node globals (rule: universal-tier purity in the spec delta). - [ ] 13.7 Dependent sweep: run `bunx turbo ls --filter=...@suaveplan/audio-sprite-player` and confirm the proposal's `### Affected dependents` list still matches (see §14a). - [ ] 13.8 Numbered requirement-checklist (built from the spec delta) is fully ticked. ## 14. Fold into canonical spec - [ ] 14.1 Fold `openspec/changes/enterprise-audio-sprite-player/specs/audio-sprite-player/spec.md` into `openspec/specs/audio-sprite-player/spec.md`. This is the **first** time anything is created under `openspec/specs/audio-sprite-player/`. ## 15. Archive - [ ] 15.1 `git mv openspec/changes/enterprise-audio-sprite-player openspec/archive/2026-05-15-enterprise-audio-sprite-player`. - [ ] 15.2 Commit the archival move separately from the implementation commit so the diff is auditable. ## 16. Follow-up notes (NOT in scope for this change) The following work is explicitly **out of scope** and must each open its own OpenSpec change before any code is authored: - `@suaveplan/audio-engine-browser` — add `BrowserSpritePlaybackAdapter` built on `AudioContext` + `decodeAudioData`. Its proposal MUST list `@suaveplan/audio-sprite-player` as an affected dependent and rerun this package's tests. - `@suaveplan/audio-engine-server` — add `ServerSpritePlaybackAdapter` built on a native binding (e.g. `node-speaker`, `@suaveplan/audio-codecs` decode + RtAudio). Same dependent-listing rule applies. - Priority-based voice-stealing (consumer-driven; opens a separate change against this package if/when needed). Do NOT add either engine adapter inside this change. The universal package ships with `NullSpritePlaybackAdapter` only; engines provide real adapters in follow-up changes.