3.9 KiB
3.9 KiB
Tasks: enterprise-gaming-r3f-audio
Change ID: enterprise-gaming-r3f-audio
Package: @suaveplan/r3f-audio
Target path: packages/gaming/r3f-audio
Prerequisite packages on Verdaccio: @suaveplan/audio-plugins-fx, @suaveplan/react-audio, @suaveplan/audio-transport, @suaveplan/error, @suaveplan/types, @suaveplan/opentelemetry
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 directory tree per
proposal.mdfile layout. - 1.2 Write
package.jsonat0.1.0,"sideEffects": false, fullexportsmap (.,./components,./components/<name>,./hooks,./hooks/<name>,./util). React + R3F + three as peer deps. - 1.3 Write
tsconfig.json,vitest.config.ts(happy-dom).
2. Error codes
- 2.1
src/error-codes.ts—defineCodes("R3F_AUDIO", [...]),R3fAudioError extends AudioError. - 2.2
error-codes.test.ts.
3. Util
- 3.1
src/util/pose-to-ambient/—Vec3/Quatconversions, scratch-vector helpers; no allocation per call. - 3.2
src/util/raycaster-pool/— shared raycaster instance + per-source scoreboard.
4. Hooks
- 4.1
use-audio-listener— binds anObject3Dref toengine.updateAmbient({ listener })per frame. - 4.2
use-positional-audio— acquiresSpatialPositionalPlugin, writes pose per frame, releases on unmount. - 4.3
use-music-layer-weights— writesgameStateintoAmbientState.extension.gameState. - 4.4
use-proximity-voice— acquiresProximityVoicePlugin, attaches stream, writes position per frame. - 4.5
use-occlusion— runs the raycaster pool against occluders, writes smoothedocclusionDb.
5. Components (each: .tsx, .md, .types.ts, .test.tsx, .stories.tsx)
- 5.1
audio-listener/— default target = active camera. - 5.2
positional-audio/. - 5.3
proximity-voice-chat/. - 5.4
music-layer-mixer/. - 5.5
voice-transform/. - 5.6
occlusion-provider/.
6. OTel
- 6.1 Register
r3f_audio_active_sourcesgauge; wire mount/unmount to itsadd/subtract.
7. Benchmarks
- 7.1
src/__benchmarks__/pose-sync.bench.ts— 60 fps pose write loop over 1024 sources. - 7.2
src/__benchmarks__/occlusion.bench.ts— raycast pool over 256 sources against a 5 k-tri scene.
8. Integration + purity + bundle-size
- 8.1
tests/integration.test.tsx— full R3F scene + AudioProvider + listener + 4 positional sources + occlusion + music layer mixer; verify ambient state writes land on chain. - 8.2
tests/purity.test.ts— builtdist/references no audio context. - 8.3
tests/exports.test.ts— every surface has subpath export; noexport *in feature barrels. - 8.4
tests/bundle-size/listener-only.size.test.ts.
9. Docs + verify
- 9.1 All co-located
.mdfiles (≥200 words). - 9.2
README.mdat package root. - 9.3
bunx turbo lint typecheck test --filter=@suaveplan/r3f-audiogreen. - 9.4
bunx turbo test:coverage --filter=@suaveplan/r3f-audio100/100/100/100. - 9.5 Banned-pattern + runner-import + file-size + missing-
.mdsweeps empty.
10. Spec reconciliation + archive
- 10.1 Walk every
### Requirementand**Verified by:**. - 10.2 Fold spec delta into
openspec/specs/r3f-audio/spec.md. - 10.3 Move change folder to archive.