# 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-`. 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-` — one package per concrete FX plugin. ## What changes ### Foundation (1 package) - ADDED: `@suaveplan/audio-fx-plugin-base` — `AudioFxPlugin` contract, `AbstractAudioFxPlugin`, `PluginChain`, `ChainContext`, `AmbientState`, `BusRegistry`, `PluginRegistry`, `ChainSnapshot`, `ChainEventBus`, `ParameterSchedule`, `PresetSnapshot`, shared `AUDIO_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 current `audio-plugins-fx/src/{base,chain,registry}/` trees plus the root `error-codes.ts`. ### Per-plugin packages (24 packages) Each new package owns one folder from `audio-plugins-fx/src/plugins//` 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 mv`s the source folder, and rewrites imports. The script is committed alongside the split so the same scaffold can be reused for future `audio-fx-plugin-*` additions. ### Removals + repo plumbing - REMOVED: `@suaveplan/audio-plugins-fx` — superseded. Package is at `0.1.0`, never published to Verdaccio. Folder `packages/audio/audio-plugins-fx/` is deleted after the moves. - MODIFIED: `MANIFEST.md` — refreshed via `bun scripts/folder-reorg/generate-manifest.ts`. - MODIFIED: `STATUS.md` — replace the single `audio-plugins-fx` ✅ row with 25 new ✅ rows (1 base + 24 per-plugin). Net `Migrated` count 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 new `audio-fx-plugin-*` package maps to the `audio` plugin slot; remove the `audio-plugins-fx` entry. ## Out of scope - New plugins beyond what `audio-plugins-fx` already 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.md` exists. 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//` | Moves verbatim into `audio-fx-plugin-` 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-` | 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-` 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.ts` after the split — `MANIFEST.md` diff shows 25 new packages and no orphaned `audio-plugins-fx` entry. - `rg "@suaveplan/audio-plugins-fx" packages/ apps/ scripts/ docs/ openspec/changes/ openspec/specs/` — zero hits after the migration commit (archive is allowed). - `bunx turbo build` whole 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-browser` and `react-audio` are still `–` in STATUS.md). The split lands before first consumer. - **External consumers**: none — package is `0.1.0` and 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`).