Initial Commit
This commit is contained in:
113
openspec/archive/2026-05-19-split-audio-plugins-fx/proposal.md
Normal file
113
openspec/archive/2026-05-19-split-audio-plugins-fx/proposal.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# 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` — `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/<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 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/<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.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`).
|
||||
Reference in New Issue
Block a user