8.6 KiB
Split audio-plugins-fx into audio-fx-plugin-* per-plugin packages
Package: @suaveplan/audio-fx-plugin-* (new), @suaveplan/audio-fx-plugin-base (new), @suaveplan/audio-plugins-fx (removed)
Status: PROPOSED
Type: refactor
Why
audio-plugins-fx currently bundles the contract, PluginChain, PluginRegistry, ChainSnapshot, and 24 concrete plugins into a single package. Subpath exports give bundlers tree-shaking, but consumers still pay the full peer-dep surface, every plugin advances on the same version, and the dep graph in MANIFEST.md cannot distinguish a chain consumer from a reverb consumer.
Every other plugin family in the repo is split per-plugin: network-plugin-*, drive-plugin-chunks, i18n-formatter-*, i18n-backend-*, the recently-shipped audio-ir-{family}-plugin-<name>. Audio FX is the outlier. Splitting now — while still at 0.1.0 and before downstream consumers (audio-engine-browser, react-audio) wire against it — avoids a much larger rename later and matches the established convention.
Naming
The new family uses the audio-fx-plugin-* prefix (fx is the family marker, distinguishing this from future audio-ir-*, audio-synth-*, etc. plugin families):
@suaveplan/audio-fx-plugin-base— foundation (contract + chain + registry + error codes).@suaveplan/audio-fx-plugin-<name>— one package per concrete FX plugin.
What changes
Foundation (1 package)
- ADDED:
@suaveplan/audio-fx-plugin-base—AudioFxPlugincontract,AbstractAudioFxPlugin,PluginChain,ChainContext,AmbientState,BusRegistry,PluginRegistry,ChainSnapshot,ChainEventBus,ParameterSchedule,PresetSnapshot, sharedAUDIO_PLUGIN.*error-code registry. Universal-tier; consumes@suaveplan/{audio-core, audio-transport, error, events, opentelemetry, schema-registry, types}but has zero@suaveplan/audio-fx-plugin-*deps. Owns every file in the currentaudio-plugins-fx/src/{base,chain,registry}/trees plus the rooterror-codes.ts.
Per-plugin packages (24 packages)
Each new package owns one folder from audio-plugins-fx/src/plugins/<source-dir>/ verbatim — no DSP, parameter, or error-code changes.
| New package | Source dir | One-line description |
|---|---|---|
audio-fx-plugin-audio-analyzer |
audio-analyzer/ |
tap-point FFT analyser |
audio-fx-plugin-audio-player |
audio-player/ |
playback source plugin |
audio-fx-plugin-auto-filter |
auto-filter/ |
LFO-driven filter |
audio-fx-plugin-chorus |
chorus/ |
modulated comb / multi-voice chorus |
audio-fx-plugin-compressor |
compressor/ |
feed-forward compressor with sidechain input |
audio-fx-plugin-delay |
delay/ |
stereo delay with ping-pong + BPM sync |
audio-fx-plugin-distortion |
distortion/ |
waveshaping + soft/hard clip |
audio-fx-plugin-eq |
eq/ |
parametric / shelving / high-pass / low-pass EQ |
audio-fx-plugin-filter |
filter/ |
biquad / IIR / state-variable |
audio-fx-plugin-flanger |
flanger/ |
short-delay modulated comb |
audio-fx-plugin-game-audio |
game/ |
game-audio orchestration plugin (impl filename is game-audio.ts) |
audio-fx-plugin-gate |
gate/ |
noise gate with hold + linked envelope |
audio-fx-plugin-glados |
glados/ |
pitch-tracked vocal-style effect |
audio-fx-plugin-limiter |
limiter/ |
look-ahead brick-wall limiter |
audio-fx-plugin-microphone |
microphone/ |
source plugin simulating mic colour |
audio-fx-plugin-mixer |
mixer/ |
bus mixer with per-channel sends |
audio-fx-plugin-phaser |
phaser/ |
all-pass-bank phaser |
audio-fx-plugin-pitch-shifter |
pitch-shifter/ |
phase-vocoder pitch shift |
audio-fx-plugin-reverb |
reverb/ |
engine-pluggable reverb (FDN, Schroeder, convolution) |
audio-fx-plugin-sampler |
sampler/ |
sample-playback source |
audio-fx-plugin-spatial |
spatial/ |
HRTF-based spatial panner |
audio-fx-plugin-synthesizer |
synthesizer/ |
polyphonic subtractive synth |
audio-fx-plugin-tremolo |
tremolo/ |
amplitude-modulated tremolo |
audio-fx-plugin-widener |
widener/ |
stereo width / mid-side processor |
Scaffold script (one new tooling file)
- ADDED:
scripts/split-audio-fx-plugin/scaffold.ts— reusable helper that takes a plugin slug (eq,reverb, …) plus the source dir name, copies a per-plugin template (config files),git mvs the source folder, and rewrites imports. The script is committed alongside the split so the same scaffold can be reused for futureaudio-fx-plugin-*additions.
Removals + repo plumbing
- REMOVED:
@suaveplan/audio-plugins-fx— superseded. Package is at0.1.0, never published to Verdaccio. Folderpackages/audio/audio-plugins-fx/is deleted after the moves. - MODIFIED:
MANIFEST.md— refreshed viabun scripts/folder-reorg/generate-manifest.ts. - MODIFIED:
STATUS.md— replace the singleaudio-plugins-fx✅ row with 25 new ✅ rows (1 base + 24 per-plugin). NetMigratedcount delta: +24. - MODIFIED:
CLAUDE.md§ Packages (audio family subsection) — replace the bundled listing with the per-plugin enumeration. - MODIFIED:
scripts/folder-reorg/assignment.yml— every newaudio-fx-plugin-*package maps to theaudioplugin slot; remove theaudio-plugins-fxentry.
Out of scope
- New plugins beyond what
audio-plugins-fxalready ships — additions land as their own packages directly under the new layout. - React / R3F bindings for plugins — remain in
react-audio-*packages, untouched. - Engine-pluggable backends (e.g. a future
audio-fx-plugin-reverb-convolution) — possible future split, not in this change. - Changing any plugin's runtime behavior, DSP, parameter surface, or error codes. This is a pure relocation + dep-graph refactor.
Source mapping
Genesis-original — no
enterprise/audio-plugins-fx.mdexists. Section retained as a pointer to the in-tree source.
| Requirement | Source path | Notes |
|---|---|---|
| base contract + chain + registry surface | packages/audio/audio-plugins-fx/src/{base,chain,registry}/ |
Moves verbatim into audio-fx-plugin-base |
| each concrete plugin | packages/audio/audio-plugins-fx/src/plugins/<source-dir>/ |
Moves verbatim into audio-fx-plugin-<slug> per the table above |
| shared error codes | packages/audio/audio-plugins-fx/src/error-codes.ts |
Moves into audio-fx-plugin-base/src/error-codes/; concrete plugins import codes from @suaveplan/audio-fx-plugin-base/error-codes |
Requirements with no source line
| Requirement | Justification |
|---|---|
| per-package independent versioning | New constraint introduced by the split; each plugin can graduate to 1.0.0 on its own cadence |
audio-fx-plugin-base cannot depend on any audio-fx-plugin-<name> |
Prevents cycles in the dep graph that the bundled package masked |
scaffold script committed to scripts/split-audio-fx-plugin/ |
Future additions to the FX family use the same template — keeps shape consistent across plugins |
Verification approach
- Per-plugin: each new package keeps its existing test suite intact under the new path.
bunx turbo test --filter=@suaveplan/audio-fx-plugin-<name>green at 100/100/100/100 for every plugin. audio-fx-plugin-base/tests/dep-graph.test.ts— asserts the package has zero@suaveplan/audio-fx-plugin-*deps (other than its own name, which would be a self-dep and is also rejected).scripts/folder-reorg/generate-manifest.tsafter the split —MANIFEST.mddiff shows 25 new packages and no orphanedaudio-plugins-fxentry.rg "@suaveplan/audio-plugins-fx" packages/ apps/ scripts/ docs/ openspec/changes/ openspec/specs/— zero hits after the migration commit (archive is allowed).bunx turbo buildwhole monorepo — green; catches any missed import rewrite.
Migration impact
- In-monorepo consumers:
rg "@suaveplan/audio-plugins-fx" packages/ apps/returns hits only inside the package itself (no downstream package has wired it up yet —audio-engine-browserandreact-audioare still–in STATUS.md). The split lands before first consumer. - External consumers: none — package is
0.1.0and was never published to Verdaccio.
Impact
Affected dependents
Run bunx turbo ls --filter=...@suaveplan/audio-plugins-fx to enumerate. At proposal time, the only dependent is audio-plugins-fx's own test suite — no other live package imports it. The placeholder audio-engine-browser is still status – (not yet ported) and will compose against audio-fx-plugin-* directly when it lands.
- No live dependents (verified by
bunx turbo ls --filter=...@suaveplan/audio-plugins-fx).