8.6 KiB
8.6 KiB
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 statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin 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.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- 1.1 Create
packages/media/audio/audio-sprite-player/withpackage.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
exportsmap 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.tsusingcreateTestConfig()from@suaveplan/testing/config;provider: 'istanbul',pool: 'forks',fileParallelism: false. - 1.7 Add
tsconfig.jsonextending@suaveplan/typescript-config/universal.json. - 1.8 Run
bun scripts/folder-reorg/generate-manifest.tsto refreshMANIFEST.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—SpritePlaybackAdapterinterface. - 2.3 Author
src/error-codes.tsregistering everyAUDIO_SPRITE_PLAYER.*code viadefineCodes(...)with i18n keys and severity. - 2.4 Author
src/schemas.ts— Zod schemas forSpritePlayerOptionsSchema,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— verifiescallsorder, handle behaviour, type-only-import compile check. - 3.3
src/adapter/null/null.mdandsrc/adapter/adapter.md— documented contract.
4. VoiceManager + voice-stealing
- 4.1
src/voice-manager/voice-manager.ts— tracks active handles, picks oldest, emitsvoice-stolen, exposes opt-out leading toVOICE_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— typedSpritePlayerEventsbuilt on@suaveplan/eventswith 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— spanaudio-sprite-player.play, counteraudio_sprite_player.play_total, gaugeaudio_sprite_player.voices_active, histogramaudio_sprite_player.play_duration_ms. - 7.2
src/telemetry/telemetry.test.ts— uses@opentelemetry/apiin-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.tsuses explicit named re-exports only (rule 10) — noexport *. - 9.2 Every feature folder's
index.tsis an explicit named barrel. - 9.3 Smoke test in
sprite-player.test.tsiteratespackage.json#exportsand imports each subpath.
10. Tests
- 10.1 All
.test.tsfiles import test-runner primitives from@suaveplan/testing/runnerONLY (rule 11). - 10.2 No
vi.mock/jest.mock(rule 2). - 10.3 Use
FakeClockfrom@suaveplan/testingfor deterministicclock.now()and scheduling tests. - 10.4
bunx turbo test --filter=@suaveplan/audio-sprite-playergreen. - 10.5
bunx turbo test:coverage --filter=@suaveplan/audio-sprite-playershows 100% on touched modules.
11. Benchmarks
- 11.1
bench/play.bench.tsusingmitata— measureplay()overhead withNullSpritePlaybackAdapter(target: < 50 µs P50, voice-stealing path < 100 µs P50). - 11.2
bench/sequence.bench.ts— measureplaySequencescaling at 1, 10, 100 entries.
12. Docs
- 12.1 Every
.ts(excl..test.ts,.types.tsinside feature dirs, barrelindex.ts) has a sibling.mdmeetingdocs:checkthresholds (≥200 words, all required sections, basic + advanced example). - 12.2 Author
README.mdat the package root (no category-level READMEs). - 12.3
bunx turbo docs:check --filter=@suaveplan/audio-sprite-playergreen.
13. Pre-publish gates
- 13.1
bunx turbo lint --filter=@suaveplan/audio-sprite-playergreen; no// biome-ignorecomments anywhere insrc/(rule 9). - 13.2
bunx turbo typecheck --filter=@suaveplan/audio-sprite-playergreen. - 13.3
bun scripts/lint/check-test-runner-imports.tsgreen 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-playerand confirm the proposal's### Affected dependentslist 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.mdintoopenspec/specs/audio-sprite-player/spec.md. This is the first time anything is created underopenspec/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— addBrowserSpritePlaybackAdapterbuilt onAudioContext+decodeAudioData. Its proposal MUST list@suaveplan/audio-sprite-playeras an affected dependent and rerun this package's tests.@suaveplan/audio-engine-server— addServerSpritePlaybackAdapterbuilt on a native binding (e.g.node-speaker,@suaveplan/audio-codecsdecode + 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.