# OpenSpec Change: audio-shipped-file-size-cleanup - **Change ID**: audio-shipped-file-size-cleanup - **Packages**: `@suaveplan/audio-timeline`, `@suaveplan/audio-transport`, `@suaveplan/audio-metadata` - **Category**: maintenance (refactor — no behavior change) - **Status**: PROPOSED - **Date**: 2026-05-15 - **Design**: `./design.md` - **Spec deltas**: `./specs/audio-timeline/spec.md`, `./specs/audio-transport/spec.md`, `./specs/audio-metadata/spec.md` --- ## Why A post-ship audit of the three universal audio packages flagged source and test files exceeding `CLAUDE.md` Rule §3 / `openspec/AGENTS.md` §3 (300-line hard cap on source, 500-line cap on tests): | Package | File | Lines | Cap | Over | |---|---|---|---|---| | audio-timeline | `src/engine/engine.ts` | 548 | 300 | +248 | | audio-timeline | `src/engine/engine.test.ts` | 819 | 500 | +319 | | audio-transport | `src/transport/transport.ts` | 419 | 300 | +119 | | audio-metadata | `src/parsers/id3v2/id3v2.ts` | 536 | 300 | +236 | | audio-metadata | `src/parsers/id3v2/id3v2.test.ts` | 1340 | 500 | +840 | | audio-metadata | `src/parsers/mp4-atom/mp4-atom.ts` | 351 | 300 | +51 | | audio-metadata | `src/parsers/mp4-atom/mp4-atom.test.ts` | 670 | 500 | +170 | | audio-metadata | `src/parsers/ogg-vorbis/ogg-vorbis.test.ts` | 803 | 500 | +303 | The 1340-line `id3v2.test.ts` (more than 2.6× the cap) is the most egregious. All eight files passed their own gates because the size budget is currently enforced by manual audit rather than a CI check. In parallel, the audit found a §7 / Rule 11 violation that was already migrated as a separate change (audio-timeline test files importing directly from `vitest` — the `bench` import was wrong-framework too and is now migrated to mitata). That work is out of scope for this proposal. ## What changes - REFACTOR: Split each oversized source file at natural responsibility boundaries while preserving the **exact public API surface** (every existing `export` keeps its name, signature, and semantics). - REFACTOR: Split each oversized test file into co-located sibling `*.test.ts` modules, one per cohesive behavior cluster (e.g. `id3v2/frames.test.ts`, `id3v2/text-encoding.test.ts`, `id3v2/extended-header.test.ts`). - ADDED: Per-package barrel updates if new sub-modules are created — explicit named re-exports only (§6a). - ADDED: Sibling `.md` docs for any new implementation files; the original file's `.md` stays as the surface-level overview. - NO BEHAVIOR CHANGE. Test counts must not decrease. Coverage must remain 100/100/100/100. ## Out of scope - API redesigns or new features. - The runner-import migration (already done in audio-timeline). - File-size cleanups in other packages (handled separately if needed). - Introducing a new CI gate for the 300/500 caps — recommended as a follow-up. ## Source mapping This is a pure-genesis maintenance change; no upstream reference. The size caps come from `CLAUDE.md` (§Quality) and `openspec/AGENTS.md` §3. ## Impact **Breaking changes**: none. Public API surface, package exports, and `package.json` `exports` entries are preserved verbatim. Internal sub-module paths may shift, but they were never part of the public contract. ### Affected dependents The three packages are universal-tier and currently have **no published consumers** on genesis (`bunx turbo ls --filter=...@suaveplan/audio-timeline` / `audio-transport` / `audio-metadata` returns empty). Future consumers (`audio-engine-browser`, `audio-engine-server`, react-audio*) consume the public surface, which this change does not touch. - No dependents (verified by `bunx turbo ls --filter=...@suaveplan/audio-timeline`). - No dependents (verified by `bunx turbo ls --filter=...@suaveplan/audio-transport`). - No dependents (verified by `bunx turbo ls --filter=...@suaveplan/audio-metadata`). ## Verification approach For each touched package: 1. `bunx turbo lint typecheck test --filter=@suaveplan/` — green. 2. `bunx turbo test:coverage --filter=@suaveplan/` — 100/100/100/100. 3. `bunx turbo build --filter=@suaveplan/` — green. 4. `find packages/audio//src -name "*.ts" ! -name "*.test.ts" | xargs awk 'END { if (NR > 300) print FILENAME, NR " lines" }'` — empty. 5. `find packages/audio//src packages/audio//tests -name "*.test.ts" | xargs awk 'END { if (NR > 500) print FILENAME, NR " lines" }'` — empty. 6. Diff the public `exports` map in `package.json` before/after — identical. 7. Diff `dist/` `.d.ts` files before/after — only path / source-map changes; no type-shape changes. ## Follow-up Once this change archives, add a `scripts/lint/check-file-sizes.ts` CI gate so the caps are enforced automatically. That belongs in its own change — out of scope here.