Initial Commit
This commit is contained in:
@@ -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 -->
|
||||
Reference in New Issue
Block a user