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

119 lines
8.6 KiB
Markdown

# 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.