Files
suaveplan/openspec/archive/2026-05-19-split-audio-plugins-fx/tasks.md
2026-05-27 23:29:53 +01:00

9.9 KiB

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.