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`).
|
||||
@@ -0,0 +1,103 @@
|
||||
<!-- markdownlint-disable MD024 -->
|
||||
|
||||
# Capability Spec Delta: audio-plugins-fx (split-audio-plugins-fx)
|
||||
|
||||
**Package**: `@suaveplan/audio-fx-plugin-base`, `@suaveplan/audio-fx-plugin-*`
|
||||
**Status**: PROPOSED
|
||||
|
||||
> Every requirement below carries a `**Verified by:**` line at authoring time. No exceptions. (See `openspec/AGENTS.md` Section 13.)
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Per-plugin package layout
|
||||
|
||||
The audio FX capability SHALL be distributed as one foundation package (`@suaveplan/audio-fx-plugin-base`) plus one package per concrete plugin (`@suaveplan/audio-fx-plugin-<name>`). No package SHALL bundle more than one plugin's DSP, parameter surface, or registry entry.
|
||||
|
||||
#### Scenario: each plugin is independently installable
|
||||
|
||||
- **WHEN** a consumer adds only `@suaveplan/audio-fx-plugin-eq` to its `package.json`
|
||||
- **THEN** `bun install` resolves `audio-fx-plugin-eq` + `audio-fx-plugin-base` + their transitive deps only, and no other `audio-plugin-*` package appears in the lockfile
|
||||
|
||||
#### Scenario: each plugin advances independently
|
||||
|
||||
- **WHEN** `audio-fx-plugin-eq` graduates to `1.0.0` while `audio-fx-plugin-reverb` remains at `0.1.0`
|
||||
- **THEN** both packages publish from the same monorepo commit without forcing the other to bump
|
||||
|
||||
**Verified by:** `packages/audio-fx/audio-fx-plugin-base/tests/dep-graph.test.ts::"audio-fx-plugin-base declares no @suaveplan/audio-fx-plugin-* deps"` AND `packages/audio-fx/audio-fx-plugin-eq/tests/dep-graph.test.ts::"audio-fx-plugin-eq depends on audio-fx-plugin-base only among audio-plugin-* packages"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: `audio-fx-plugin-base` owns the shared contract surface
|
||||
|
||||
`@suaveplan/audio-fx-plugin-base` SHALL export the `AudioPlugin` contract, `PluginChain`, `ChainContext`, `AmbientState`, `BusRegistry`, `PluginRegistry`, `ChainSnapshot`, and the shared `error-codes.ts` registry. No concrete plugin SHALL re-implement these primitives.
|
||||
|
||||
#### Scenario: contract is the single source of truth
|
||||
|
||||
- **WHEN** a new plugin package is authored
|
||||
- **THEN** it imports `AudioPlugin` from `@suaveplan/audio-fx-plugin-base/base` and never declares its own variant
|
||||
|
||||
#### Scenario: chain composition stays in base
|
||||
|
||||
- **WHEN** a consumer composes `audio-fx-plugin-eq`, `audio-fx-plugin-compressor`, and `audio-fx-plugin-reverb` into a chain
|
||||
- **THEN** it imports `PluginChain` from `@suaveplan/audio-fx-plugin-base/chain` and the chain accepts every plugin without per-plugin glue
|
||||
|
||||
**Verified by:** `packages/audio-fx/audio-fx-plugin-base/src/chain/chain.test.ts::"PluginChain accepts any AudioPlugin implementation"` AND `packages/audio-fx/audio-fx-plugin-base/src/registry/registry.spec-conformance.test.ts::"PluginRegistry register/has/create/list invariants"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: `audio-fx-plugin-base` is dep-graph-isolated from concrete plugins
|
||||
|
||||
`@suaveplan/audio-fx-plugin-base` SHALL declare zero dependencies on any `@suaveplan/audio-fx-plugin-*` package. The dependency arrow MUST point only from concrete plugins to base, never base to plugins.
|
||||
|
||||
#### Scenario: no upward dep
|
||||
|
||||
- **WHEN** CI runs `tests/dep-graph.test.ts` in `audio-fx-plugin-base`
|
||||
- **THEN** the test fails if `package.json` contains any `@suaveplan/audio-fx-plugin-*` entry other than `audio-fx-plugin-base` itself (which would be a self-dep and is also rejected)
|
||||
|
||||
**Verified by:** `packages/audio-fx/audio-fx-plugin-base/tests/dep-graph.test.ts::"audio-fx-plugin-base declares no @suaveplan/audio-fx-plugin-* deps"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Error-code namespace preserved across the split
|
||||
|
||||
Every error code that existed in `@suaveplan/audio-plugins-fx` SHALL remain reachable under the same `AUDIO_PLUGIN.*` namespace from either `@suaveplan/audio-fx-plugin-base/error-codes` (shared codes) or the relevant `@suaveplan/audio-fx-plugin-<name>/error-codes` (plugin-specific codes). No code SHALL be renamed, removed, or re-numbered by this change.
|
||||
|
||||
#### Scenario: shared codes resolve from base
|
||||
|
||||
- **WHEN** a caller imports `AUDIO_PLUGIN.CHAIN_SLOT_NOT_FOUND` from `@suaveplan/audio-fx-plugin-base/error-codes`
|
||||
- **THEN** the code value is byte-identical to the value previously exported from `@suaveplan/audio-plugins-fx/error-codes`
|
||||
|
||||
#### Scenario: plugin-specific codes resolve from the plugin
|
||||
|
||||
- **WHEN** a caller imports an EQ-specific code from `@suaveplan/audio-fx-plugin-eq/error-codes`
|
||||
- **THEN** the code is in the `AUDIO_PLUGIN.EQ.*` namespace and is thrown by at least one production path in `audio-fx-plugin-eq`
|
||||
|
||||
**Verified by:** `packages/audio-fx/audio-fx-plugin-base/src/error-codes.test.ts::"every shared AUDIO_PLUGIN.* code preserved across split"` AND `packages/audio-fx/audio-fx-plugin-eq/src/error-codes.test.ts::"every AUDIO_PLUGIN.EQ.* code thrown by a production path"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Migration leaves zero references to the old package
|
||||
|
||||
After this change ships, no file under `packages/`, `apps/`, `scripts/`, or `docs/` SHALL import from `@suaveplan/audio-plugins-fx`. The old package directory SHALL be deleted.
|
||||
|
||||
#### Scenario: no stale imports
|
||||
|
||||
- **WHEN** CI runs `rg "@suaveplan/audio-plugins-fx" packages/ apps/ scripts/ docs/`
|
||||
- **THEN** the command exits with status 1 (no matches found)
|
||||
|
||||
#### Scenario: old package directory removed
|
||||
|
||||
- **WHEN** the post-archive tree is inspected
|
||||
- **THEN** `packages/audio/audio-plugins-fx/` does not exist
|
||||
|
||||
**Verified by:** `scripts/openspec-conformance.ts` audit for change `split-audio-plugins-fx` AND `bunx turbo build` whole-monorepo green
|
||||
|
||||
## REMOVED Requirements
|
||||
|
||||
### Requirement: Single bundled FX package
|
||||
|
||||
**Reason:** Superseded by per-plugin packaging — see ADDED requirement "Per-plugin package layout" above.
|
||||
|
||||
**Migration:** Replace `import { Eq } from "@suaveplan/audio-plugins-fx/eq"` with `import { Eq } from "@suaveplan/audio-fx-plugin-eq"`. Replace `import { PluginChain } from "@suaveplan/audio-plugins-fx/chain"` with `import { PluginChain } from "@suaveplan/audio-fx-plugin-base/chain"`. No runtime behavior changes.
|
||||
|
||||
<!-- markdownlint-enable MD024 -->
|
||||
94
openspec/archive/2026-05-19-split-audio-plugins-fx/tasks.md
Normal file
94
openspec/archive/2026-05-19-split-audio-plugins-fx/tasks.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Tasks — Split `audio-plugins-fx` into `audio-fx-plugin-*` per-plugin packages
|
||||
|
||||
> Every checkbox MUST reflect work actually done in this change. Strategy: build a real foundation + one canonical plugin, then a scaffold script replicates the per-plugin shape across the remaining 23.
|
||||
|
||||
## 1. Spec authoring
|
||||
|
||||
- [ ] 1.1 Read `openspec/AGENTS.md` §§ 13, 14, 14a, 2c, 6a, 7, 193
|
||||
- [ ] 1.2 Read `openspec/specs/audio-core/spec.md` and `openspec/specs/audio-transport/spec.md` for surrounding capability shape
|
||||
- [ ] 1.3 `proposal.md` (this change) — 25 packages enumerated, `audio-fx-plugin-*` naming
|
||||
- [ ] 1.4 `specs/audio-plugins-fx/spec.md` — 5 ADDED + 1 REMOVED requirements, each with `**Verified by:**`
|
||||
- [ ] 1.5 Working-notes checklist of every `### Requirement` and `#### Scenario`
|
||||
|
||||
## 2. Phase A — Build `audio-fx-plugin-base`
|
||||
|
||||
- [ ] 2.1 `mkdir -p packages/audio-fx/audio-fx-plugin-base/{src,tests}`
|
||||
- [ ] 2.2 `git mv` every file from `packages/audio/audio-plugins-fx/src/{base,chain,registry}/` into `packages/audio-fx/audio-fx-plugin-base/src/` preserving directory structure
|
||||
- [ ] 2.3 `git mv` `packages/audio/audio-plugins-fx/src/error-codes.{ts,md,test.ts}` into `packages/audio-fx/audio-fx-plugin-base/src/error-codes/`. Rename to `error-codes/error-codes.{ts,md,test.ts}` so the feature-folder convention holds.
|
||||
- [ ] 2.4 Author `packages/audio-fx/audio-fx-plugin-base/package.json` — `version: 0.1.0`, `sideEffects: false`, deps `@suaveplan/{audio-core, audio-transport, error, events, opentelemetry, schema-registry, types}` + `tslib` + `zod` (all from catalog/workspace). Zero `@suaveplan/audio-fx-plugin-*` deps. Subpath exports: `.`, `./base`, `./chain`, `./registry`, `./error-codes`. `files: ["dist", "README.md"]`.
|
||||
- [ ] 2.5 Author `tsconfig.json`, `tsconfig.lib.json`, `vite.config.ts` (multi-entry, `preserveModules: true`), `vitest.config.ts`, `README.md`. Copy from `packages/audio-ir/audio-ir-core/` and adjust names.
|
||||
- [ ] 2.6 Author root barrel `src/index.ts` — explicit named re-exports (rule 10). Drop every `export *` from sub-barrels in the moved code; convert to named re-exports.
|
||||
- [ ] 2.7 Rewrite internal imports inside moved files: `from "../base"` → `from "./base"`, etc. (verify with `rg "\.\./" packages/audio-fx/audio-fx-plugin-base/src`)
|
||||
- [ ] 2.8 Add `tests/dep-graph.test.ts`: reads own `package.json`, asserts zero `@suaveplan/audio-fx-plugin-*` deps (including self).
|
||||
- [ ] 2.9 Run `bun install && bunx turbo lint typecheck test build --filter=@suaveplan/audio-fx-plugin-base`. Must reach 100/100/100/100.
|
||||
|
||||
## 3. Phase B — Build `audio-fx-plugin-eq` as the canonical template
|
||||
|
||||
- [ ] 3.1 `mkdir -p packages/audio-fx/audio-fx-plugin-eq/src`
|
||||
- [ ] 3.2 `git mv packages/audio/audio-plugins-fx/src/plugins/eq/* packages/audio-fx/audio-fx-plugin-eq/src/`
|
||||
- [ ] 3.3 Author `package.json`, `tsconfig.json`, `tsconfig.lib.json`, `vite.config.ts`, `vitest.config.ts`, `README.md` for `audio-fx-plugin-eq`. Deps: `@suaveplan/audio-fx-plugin-base` (workspace:^) + whatever non-plugin `@suaveplan/*` packages the moved eq code imports (enumerate via `rg "@suaveplan/" packages/audio-fx/audio-fx-plugin-eq/src`).
|
||||
- [ ] 3.4 Rewrite eq imports: `from "../../base"` → `from "@suaveplan/audio-fx-plugin-base/base"`, `from "../../chain"` → `from "@suaveplan/audio-fx-plugin-base/chain"`, etc.
|
||||
- [ ] 3.5 Root barrel `src/index.ts` — explicit named re-exports; convert any `export *` to named.
|
||||
- [ ] 3.6 `bunx turbo lint typecheck test build --filter=@suaveplan/audio-fx-plugin-eq` — green at 100/100/100/100.
|
||||
- [ ] 3.7 Designate `audio-fx-plugin-eq`'s config files (`package.json`, `tsconfig.*`, `vite.config.ts`, `vitest.config.ts`, `README.md`) as the canonical per-plugin template. Save the rendered versions with `{PLUGIN_NAME}` markers re-introduced as `scripts/split-audio-fx-plugin/template/*.template` for the scaffold script to consume.
|
||||
|
||||
## 4. Phase C — Scaffold script + replicate across 23 remaining plugins
|
||||
|
||||
- [ ] 4.1 Author `scripts/split-audio-fx-plugin/scaffold.ts` (Bun-runnable TypeScript). Arguments: `--name <slug>` (e.g. `compressor`), `--source-dir <name>` (defaults to `<slug>`; used for the `game/` → `game-audio` rename).
|
||||
- [ ] 4.2 Script steps:
|
||||
1. Validate slug matches `/^[a-z][a-z0-9-]*$/`. Refuse if a folder already exists at `packages/audio-fx/audio-fx-plugin-<slug>/`.
|
||||
2. Create `packages/audio-fx/audio-fx-plugin-<slug>/src/`.
|
||||
3. Copy every `scripts/split-audio-fx-plugin/template/*.template` to the new package root, replacing `{PLUGIN_NAME}` markers with `<slug>`. Strip the `.template` suffix.
|
||||
4. `git mv packages/audio/audio-plugins-fx/src/plugins/<source-dir>/* packages/audio-fx/audio-fx-plugin-<slug>/src/`.
|
||||
5. Walk every `.ts` / `.tsx` / `.md` file inside the new `src/` and rewrite relative imports: `../../base` → `@suaveplan/audio-fx-plugin-base/base`, `../../chain` → `@suaveplan/audio-fx-plugin-base/chain`, `../../registry` → `@suaveplan/audio-fx-plugin-base/registry`, `../../error-codes` → `@suaveplan/audio-fx-plugin-base/error-codes`. Also rewrite cross-plugin imports if any (`../<other-plugin>` should not exist; abort with an error if found).
|
||||
6. Convert every `export *` in the new package's barrels to explicit named re-exports (read the source's actual exports via a minimal AST walk or fallback to grep + manual fix-list).
|
||||
7. Author `src/index.ts` root barrel with explicit named re-exports of the plugin's public surface.
|
||||
- [ ] 4.3 Run the script for each of the 23 remaining plugins, in alphabetical order: `audio-analyzer`, `audio-player`, `auto-filter`, `chorus`, `compressor`, `delay`, `distortion`, `filter`, `flanger`, `game-audio` (source dir `game`), `gate`, `glados`, `limiter`, `microphone`, `mixer`, `phaser`, `pitch-shifter`, `reverb`, `sampler`, `spatial`, `synthesizer`, `tremolo`, `widener`.
|
||||
- [ ] 4.4 After every 5 plugins, run `bunx turbo lint typecheck test --filter='@suaveplan/audio-fx-plugin-*'` to catch regressions early.
|
||||
|
||||
## 5. Phase D — Repo plumbing
|
||||
|
||||
- [ ] 5.1 Delete `packages/audio/audio-plugins-fx/` (`git rm -rf`).
|
||||
- [ ] 5.2 `rg "@suaveplan/audio-plugins-fx" packages/ apps/ scripts/ docs/ openspec/changes/ openspec/specs/` — zero hits. Hits in `openspec/archive/` are immutable history; ignore.
|
||||
- [ ] 5.3 Update `scripts/folder-reorg/assignment.yml`: remove `audio-plugins-fx`; add 25 entries mapping every new `audio-fx-plugin-*` package to the `audio` plugin slot.
|
||||
- [ ] 5.4 Update `CLAUDE.md` § Packages — replace `audio-plugins-fx` listing with `audio-fx-plugin-base` + 24 per-plugin entries (alphabetical).
|
||||
- [ ] 5.5 Update `STATUS.md` — replace the `@suaveplan/audio-plugins-fx` row with 25 ✅ rows; update `## Counts` (`Migrated` +24).
|
||||
- [ ] 5.6 `bun scripts/folder-reorg/generate-manifest.ts` — regenerate `MANIFEST.md`.
|
||||
|
||||
## 6. Phase E — Final verification (5-gate triple across the family)
|
||||
|
||||
- [ ] 6.1 `bun run check` — Biome 0/0/0/0 monorepo-wide
|
||||
- [ ] 6.2 `bunx turbo lint typecheck test --filter='@suaveplan/audio-fx-plugin-*'` — green across all 25
|
||||
- [ ] 6.3 `bunx turbo test:coverage --filter='@suaveplan/audio-fx-plugin-*'` — 100/100/100/100 on every package
|
||||
- [ ] 6.4 `bunx turbo build --filter='@suaveplan/audio-fx-plugin-*'` — green
|
||||
- [ ] 6.5 `bun scripts/openspec-conformance.ts @suaveplan/audio-fx-plugin-base` and `@suaveplan/audio-fx-plugin-eq` — both PASS
|
||||
- [ ] 6.6 `bunx turbo build` (whole monorepo) — green; no downstream consumer breakage
|
||||
- [ ] 6.7 `test ! -d packages/audio/audio-plugins-fx` — exit 0
|
||||
- [ ] 6.8 `rg "@suaveplan/audio-plugins-fx" packages/ apps/ scripts/ docs/ openspec/changes/ openspec/specs/` — zero hits
|
||||
|
||||
## 7. Phase F — 7-row checklist (AGENTS §13)
|
||||
|
||||
- [ ] 7.1 Generics threaded; `expectTypeOf` assertions preserved on every literal-type claim
|
||||
- [ ] 7.2 Zod schemas wired at every declared boundary — preserved by move
|
||||
- [ ] 7.3 Every error code in each `error-codes.ts` thrown by at least one production path
|
||||
- [ ] 7.4 Strict-mode behaviors tested both on and off — preserved
|
||||
- [ ] 7.5 OTel instruments asserted with a real in-memory `MeterProvider` — preserved
|
||||
- [ ] 7.6 Lifecycle dedup tests preserved (in-flight Promise, idempotent set/load)
|
||||
- [ ] 7.7 No retroactive tick — every box reflects work done in this change
|
||||
|
||||
## 8. Phase G — Archive + commit
|
||||
|
||||
> Commit strategy: 3 commits scoped narrowly via explicit `git add <path>` — never `git add -A`.
|
||||
> Touch ONLY these path families: `packages/audio-fx/audio-fx-plugin-*`, `packages/audio/audio-plugins-fx` (deletion), `scripts/split-audio-fx-plugin/`, `openspec/changes/split-audio-plugins-fx/`, `openspec/archive/2026-05-19-split-audio-plugins-fx/`, `openspec/specs/audio-plugins-fx/`, `STATUS.md`, `CLAUDE.md`, `scripts/folder-reorg/assignment.yml`, `MANIFEST.md`.
|
||||
> DO NOT touch any file under `packages/react/`, `openspec/changes/add-react-auth-core/`, `openspec/changes/extend-react-ui-runtime-theme-mutation/`, or `bun.lock` — those belong to unrelated in-flight work.
|
||||
|
||||
- [ ] 8.1 Commit 1: `feat(audio-fx): extract audio-fx-plugin-base from audio-plugins-fx`. Body: base package shipped; eq shipped as the canonical template; scaffold script committed.
|
||||
- [ ] 8.2 Commit 2: `feat(audio-fx): split 23 remaining FX plugins into audio-fx-plugin-* packages`. Body: lists every new package; notes the `game/` → `game-audio` rename; references Commit 1.
|
||||
- [ ] 8.3 Fold spec delta into NEW `openspec/specs/audio-plugins-fx/spec.md`. The 5 ADDED requirements become the body; the REMOVED requirement is appended as a `## Historical: bundled package` note with a pointer to the archive.
|
||||
- [ ] 8.4 `git mv openspec/changes/split-audio-plugins-fx openspec/archive/2026-05-19-split-audio-plugins-fx`.
|
||||
- [ ] 8.5 Commit 3: `chore(audio-fx): delete audio-plugins-fx + archive split-audio-plugins-fx + refresh root docs`. Body: cites the deletion of the old folder, the STATUS / CLAUDE / MANIFEST / assignment.yml updates, and the archive move.
|
||||
- [ ] 8.6 Every commit message ends with the standard trailer:
|
||||
```
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
```
|
||||
- [ ] 8.7 DO NOT push.
|
||||
Reference in New Issue
Block a user