Files
2026-05-27 23:29:53 +01:00

5.3 KiB

Capability Spec Delta: audio-ir-room-plugin-club (add-audio-ir-room-plugin-club)

Package: @suaveplan/audio-ir-room-plugin-club Status: PROPOSED

Every requirement carries a **Verified by:** line.

ADDED Requirements

Requirement: Manifest declares both club room IRs with bundle URIs

The package SHALL export manifest: IrManifest with packageSlug: "club", family: "room", AND entries: readonly IrManifestEntry[] containing exactly two entries:

  1. { id: "club-club1", family: "room", uri: "bundle://audio-ir-room-plugin-club/club1.wav", channels: <decoded>, sampleRate: <decoded>, gainDb: 0, license: <see README>, source: "Mountain Duck media library: /media/_/audio/ir/room/club1.wav" }.
  2. { id: "club-club2", family: "room", uri: "bundle://audio-ir-room-plugin-club/club2.wav", channels: <decoded>, sampleRate: <decoded>, gainDb: 0, license: <see README>, source: "Mountain Duck media library: /media/_/audio/ir/room/club2.wav" }.

channels AND sampleRate SHALL be the actual values measured by decoding the bundled files at manifest-authoring time (so the manifest never disagrees with the file). Manifest SHALL parse successfully through IrManifestSchema (id-prefix, family coherence, uri non-empty).

Scenario: manifest parses through IrManifestSchema

  • WHEN IrManifestSchema.parse(manifest) is called
  • THEN the result deep-equals the export AND every entry.id starts with "club-" AND every entry.family === "room"

Scenario: both ids are unique and well-formed

  • WHEN the test enumerates manifest.entries.map(e => e.id)
  • THEN the result is ["club-club1", "club-club2"] (order matches declaration; no duplicates)

Scenario: every URI parses as a bundle:// URI

  • WHEN the test parses every entry.uri through parseUri (from @suaveplan/storage-uri) AND the bundle plugin's parse
  • THEN each parse succeeds AND the parsed meta.packageSlug === "audio-ir-room-plugin-club"

Verified by: src/manifest/manifest.test.ts::"manifest parses through IrManifestSchema" AND src/manifest/manifest.test.ts::"declares exactly club-club1 and club-club2" AND src/manifest/manifest.test.ts::"every URI parses as a well-formed bundle URI"


Requirement: register(registry, resolver) wires the bundle plugin and registers entries

The package SHALL export a register(registry: IrRegistry, resolver: StorageUriResolver): void function that:

  1. Calls resolver.use(bundleUriPlugin({ packageSlug: "audio-ir-room-plugin-club", rootUrl: new URL("../files/", import.meta.url) })) exactly once, idempotently rejected by the resolver if a plugin for bundle is already registered with the same packageSlug value.
  2. Calls registerManifest(registry, manifest).

The function SHALL NOT swallow errors — duplicate registrations against the same resolver/registry SHALL surface the underlying STORAGE_URI.SCHEME_CONFLICT or AUDIO_IR.DUPLICATE_ID codes verbatim. The package SHALL NOT auto-register on import — registration is explicit per the side-effect-free contract.

Scenario: register adds the bundle plugin and the two entries

  • WHEN register(registry, resolver) is called against fresh fixtures
  • THEN the resolver dispatches bundle://audio-ir-room-plugin-club/club1.wav to the package's adapter AND registry.has("club-club1") === true AND registry.has("club-club2") === true

Scenario: double register surfaces the underlying conflict

  • WHEN register(registry, resolver) is called twice against the same fixtures
  • THEN the second call rejects synchronously with AUDIO_IR.DUPLICATE_ID (the registry rejects before the resolver is touched a second time, depending on implementation order; either underlying conflict is acceptable as long as it surfaces verbatim)

Verified by: src/register/register.test.ts::"adds bundle plugin and registers both entries" AND src/register/register.test.ts::"double register surfaces DUPLICATE_ID"


Requirement: Bundled WAV files exist on disk at build time

The package SHALL ship files/club1.wav AND files/club2.wav in its tarball (via the package.json files array). Both files SHALL be non-empty AND SHALL decode successfully through decodeWav from @suaveplan/audio-decode-wav. The integration test SHALL load both files end-to-end through audio-ir-loader and assert non-empty Float32Array channels.

Scenario: both files exist and are non-empty

  • WHEN the test reads <package-root>/files/club1.wav AND <package-root>/files/club2.wav via node:fs
  • THEN both reads succeed AND each file's byte length is > 0

Scenario: end-to-end load returns valid IRs

  • WHEN the test constructs resolver, registry, calls register(registry, resolver), constructs loader = createIrLoader({ registry, resolver, decoders: { wav: decodeWav } }), AND calls await loader.load("club-club1") AND await loader.load("club-club2")
  • THEN both calls resolve to frozen ImpulseResponse objects whose channelData[0].length > 0 AND sampleRate > 0 AND channels >= 1

Verified by: tests/integration/file-presence.test.ts::"club1.wav and club2.wav exist on disk and are non-empty" AND tests/integration/end-to-end.test.ts::"loads both club IRs end-to-end through the loader"