diff --git a/.changeset/clear-validation-warnings.md b/.changeset/clear-validation-warnings.md new file mode 100644 index 000000000..55ccbbf21 --- /dev/null +++ b/.changeset/clear-validation-warnings.md @@ -0,0 +1,22 @@ +--- +"catalog": patch +--- + +Clear the validation warning backlog (62 warnings across 51 files). + +I/O connectors: Black Lion preamps and patchbays had port names copied +into the `connection` field ("AC Power", "TT/Bantam slot inputs"), now +real connectors. Added `tt`, `4-pin din`, `db15`, and `digilink` to the +connection vocabulary. Patchbay rows are aggregates by nature, so +`patch-bay` entries no longer trip the collapsed-jack heuristic (W128). + +Search: added expansions for RAH (Royal Albert Hall), CJ (Collings +Jumbo), SJ (Small Jumbo), and SPA (grandPa Expander); recorded the +researched dead ends (Brauner VMA/VMX, Dangerous MQ, Burl BCLK, +Catalinbread SFT, Collings MF/MT) and the names that only look like +acronyms (URLA, CROM, LOL, BOB, BOBEK, MIXER, OR). + +Also dropped `url` where it merely repeated the manufacturer homepage +(AIR Music, Artiphon, Forgotten Keys, Sonic Sirius, none of which +publish a live product page for those entries) and removed the +duplicated brand prefix from "Drumforge Djent Grooves: Vol. 1". diff --git a/CLAUDE.md b/CLAUDE.md index 9e3930954..7fec4fd81 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -196,6 +196,11 @@ pair into one stereo entry with `maxConnections: 2`, and do not split one jack i two — bulk imports get this wrong. E.g. the Eventide H90 has 14 discrete jacks (Inputs 1–4, Outputs 1–4, Exp/Ctl 1–2, MIDI In, MIDI Out/Thru, USB-C, Power). +**Patchbays are the exception.** A `patch-bay` entry models each row as one `io` +entry with `maxConnections` set to the point count (a 48-point TRS row, not 48 +entries), so W128 skips that category. TT/Bantam patch points use +`connection: tt`. + ## Content Entries Content entries (presets, sample packs, expansions) live in `data/content/` as a separate collection. Content `primaryCategory` values include `preset`, `preset-pack`, `sample-pack`, `drum-sample-pack`, `loop-pack`, `sound-library`, `soundfont`, `impulse-response`, and `multisample`. diff --git a/data/content/air-music-ambient-illusions-for-ignite.yaml b/data/content/air-music-ambient-illusions-for-ignite.yaml index 9311bfbc7..3389916dc 100644 --- a/data/content/air-music-ambient-illusions-for-ignite.yaml +++ b/data/content/air-music-ambient-illusions-for-ignite.yaml @@ -44,4 +44,3 @@ links: - type: product url: https://www.plugivery.com/products/p2570-Ambient-Illusions-for-Ignite/ title: Ambient Illusions for Ignite -url: https://www.airmusictech.com/ diff --git a/data/content/air-music-analog-trap.yaml b/data/content/air-music-analog-trap.yaml index 9142b0b0d..ee15de058 100644 --- a/data/content/air-music-analog-trap.yaml +++ b/data/content/air-music-analog-trap.yaml @@ -35,6 +35,5 @@ links: - type: product url: https://www.airmusictech.com/expansions/view/analog-trap-expansion-for-hybrid-3 title: Analog Trap Expansion Pack -url: https://www.airmusictech.com/ categories: - synthesizer diff --git a/data/content/drumforge-drumforge-djent-grooves-vol-1.yaml b/data/content/drumforge-drumforge-djent-grooves-vol-1.yaml index 1bd6c0e12..706a1d9c8 100644 --- a/data/content/drumforge-drumforge-djent-grooves-vol-1.yaml +++ b/data/content/drumforge-drumforge-djent-grooves-vol-1.yaml @@ -1,5 +1,5 @@ id: kvfS50L_IJIZNPmR4T3zj -name: "Drumforge Djent Grooves: Vol. 1" +name: "Djent Grooves: Vol. 1" manufacturer: drumforge primaryCategory: loop-pack categories: diff --git a/data/content/forgotten-keys-ace-3.yaml b/data/content/forgotten-keys-ace-3.yaml index 970b523e1..06903fd3a 100644 --- a/data/content/forgotten-keys-ace-3.yaml +++ b/data/content/forgotten-keys-ace-3.yaml @@ -2,7 +2,6 @@ id: dutnPz9K737dswa3j3cGK name: ACE-3 manufacturer: forgotten-keys primaryCategory: sound-library -url: https://www.forgottenkeys.co.uk/ description: All the internal sounds have been carefully sampled and the rhythms re-created. details: |- All the internal sounds have been carefully sampled and the rhythms re-created. diff --git a/data/content/sonic-sirius-10-free-largo-soundbanks.yaml b/data/content/sonic-sirius-10-free-largo-soundbanks.yaml index 0de54db01..a8d3b0fec 100644 --- a/data/content/sonic-sirius-10-free-largo-soundbanks.yaml +++ b/data/content/sonic-sirius-10-free-largo-soundbanks.yaml @@ -29,5 +29,4 @@ prices: currency: USD videos: - videoId: 2LIJbu232G8 -url: https://ohlenbostelhelge.wixsite.com/sonic-sirius-sound-d releaseDate: "2013" diff --git a/data/hardware/artiphon-chorda.yaml b/data/hardware/artiphon-chorda.yaml index a85baf289..1ee7f38a3 100644 --- a/data/hardware/artiphon-chorda.yaml +++ b/data/hardware/artiphon-chorda.yaml @@ -5,7 +5,6 @@ primaryCategory: midi-controller categories: - looper - discontinued -url: https://www.artiphon.com/ description: A next-gen, smart instrument that strums, taps, and loops with expressive ease. details: |- Chorda is a portable, all-in-one smart instrument that combines a synthesizer, diff --git a/data/hardware/artiphon-instrument-1.yaml b/data/hardware/artiphon-instrument-1.yaml index f0bc5803e..efdac81f1 100644 --- a/data/hardware/artiphon-instrument-1.yaml +++ b/data/hardware/artiphon-instrument-1.yaml @@ -4,7 +4,6 @@ manufacturer: artiphon primaryCategory: midi-controller categories: - discontinued -url: https://www.artiphon.com/ description: The award-winning, all-in-one instrument that plays like guitar, violin, piano, and drums. details: |- diff --git a/data/hardware/artiphon-orba-3.yaml b/data/hardware/artiphon-orba-3.yaml index bfcff0bc5..20aa9cb8a 100644 --- a/data/hardware/artiphon-orba-3.yaml +++ b/data/hardware/artiphon-orba-3.yaml @@ -7,7 +7,6 @@ categories: - looper - sampler - discontinued -url: https://www.artiphon.com/ description: A palm-sized synth, looper, and MIDI controller that lets anyone make music, anywhere. details: |- diff --git a/data/hardware/bastl-instruments-spa.yaml b/data/hardware/bastl-instruments-spa.yaml index 4f0a0d611..6e120918e 100644 --- a/data/hardware/bastl-instruments-spa.yaml +++ b/data/hardware/bastl-instruments-spa.yaml @@ -5,6 +5,8 @@ primaryCategory: utility categories: - granular - discontinued +searchTerms: + - grandPa Expander url: https://bastl-instruments.com/eurorack/modules/spa description: SPA is a discontinued Eurorack expander for the Bastl Instruments grandPA granular sampler, adding CV inputs for grain size, shift speed, diff --git a/data/hardware/black-lion-audio-auteur-dt.yaml b/data/hardware/black-lion-audio-auteur-dt.yaml index ebebfbc97..efc6ab6d3 100644 --- a/data/hardware/black-lion-audio-auteur-dt.yaml +++ b/data/hardware/black-lion-audio-auteur-dt.yaml @@ -59,7 +59,7 @@ io: signalFlow: input category: power type: power - connection: AC Power + connection: barrel maxConnections: 1 position: Bottom links: diff --git a/data/hardware/black-lion-audio-auteur-mkii.yaml b/data/hardware/black-lion-audio-auteur-mkii.yaml index 54fea9121..34b6c9603 100644 --- a/data/hardware/black-lion-audio-auteur-mkii.yaml +++ b/data/hardware/black-lion-audio-auteur-mkii.yaml @@ -65,7 +65,7 @@ io: signalFlow: input category: power type: power - connection: AC Power + connection: barrel maxConnections: 1 position: Bottom links: diff --git a/data/hardware/black-lion-audio-auteur-mkiii.yaml b/data/hardware/black-lion-audio-auteur-mkiii.yaml index 49b56fc79..885e1f30d 100644 --- a/data/hardware/black-lion-audio-auteur-mkiii.yaml +++ b/data/hardware/black-lion-audio-auteur-mkiii.yaml @@ -69,7 +69,7 @@ io: signalFlow: input category: power type: power - connection: AC Power + connection: barrel maxConnections: 1 position: Bottom links: diff --git a/data/hardware/black-lion-audio-auteur-quad.yaml b/data/hardware/black-lion-audio-auteur-quad.yaml index af88fdd89..d65419d6b 100644 --- a/data/hardware/black-lion-audio-auteur-quad.yaml +++ b/data/hardware/black-lion-audio-auteur-quad.yaml @@ -145,7 +145,7 @@ io: signalFlow: input category: power type: power - connection: 4-pin DIN + connection: 4-pin din maxConnections: 1 position: Bottom links: diff --git a/data/hardware/black-lion-audio-b12a-mkiii.yaml b/data/hardware/black-lion-audio-b12a-mkiii.yaml index 3e56a6753..77ad29050 100644 --- a/data/hardware/black-lion-audio-b12a-mkiii.yaml +++ b/data/hardware/black-lion-audio-b12a-mkiii.yaml @@ -62,7 +62,7 @@ io: signalFlow: input category: power type: power - connection: AC Power + connection: barrel maxConnections: 1 position: Bottom links: diff --git a/data/hardware/black-lion-audio-b173-mkii.yaml b/data/hardware/black-lion-audio-b173-mkii.yaml index 3566f95e2..1cc9949d8 100644 --- a/data/hardware/black-lion-audio-b173-mkii.yaml +++ b/data/hardware/black-lion-audio-b173-mkii.yaml @@ -59,7 +59,7 @@ io: signalFlow: input category: power type: power - connection: AC Power + connection: barrel maxConnections: 1 position: Bottom links: diff --git a/data/hardware/black-lion-audio-pbr-8-500.yaml b/data/hardware/black-lion-audio-pbr-8-500.yaml index c2384b7f9..658cd0113 100644 --- a/data/hardware/black-lion-audio-pbr-8-500.yaml +++ b/data/hardware/black-lion-audio-pbr-8-500.yaml @@ -30,7 +30,7 @@ io: signalFlow: input category: audio type: line - connection: TT/Bantam slot inputs + connection: tt maxConnections: 8 position: Left - key: QsOyVCw1 @@ -38,7 +38,7 @@ io: signalFlow: output category: audio type: line - connection: TT/Bantam slot outputs + connection: tt maxConnections: 8 position: Right - key: FCPXEMJW @@ -46,7 +46,7 @@ io: signalFlow: input category: audio type: line - connection: TT/Bantam Mult inputs + connection: tt maxConnections: 2 position: Left - key: NH3tWZ1y @@ -54,7 +54,7 @@ io: signalFlow: output category: audio type: line - connection: TT/Bantam Mult outputs + connection: tt maxConnections: 4 position: Right - key: VfXGoDii diff --git a/data/hardware/black-lion-audio-pbr-8.yaml b/data/hardware/black-lion-audio-pbr-8.yaml index b69aab418..17ecff8b4 100644 --- a/data/hardware/black-lion-audio-pbr-8.yaml +++ b/data/hardware/black-lion-audio-pbr-8.yaml @@ -25,14 +25,16 @@ io: signalFlow: bidirectional category: audio type: line - connection: TT/Bantam front patchbay — top row + connection: tt maxConnections: 8 position: Top + rowPosition: 1 - key: 4VjRf667 name: TT/Bantam front patchbay — bottom row signalFlow: bidirectional category: audio type: line - connection: TT/Bantam front patchbay — bottom row + connection: tt maxConnections: 8 position: Top + rowPosition: 2 diff --git a/data/hardware/black-lion-audio-pbr-tt-lit.yaml b/data/hardware/black-lion-audio-pbr-tt-lit.yaml index dcf889b53..abb9cd096 100644 --- a/data/hardware/black-lion-audio-pbr-tt-lit.yaml +++ b/data/hardware/black-lion-audio-pbr-tt-lit.yaml @@ -28,13 +28,23 @@ specs: |- - Connectivity: USB (keyboard input and firmware updates) io: - key: 7x5bmMlr - name: TT (Bantam) — front panel + name: TT (Bantam) — front panel, top row signalFlow: bidirectional category: audio type: line - connection: TT (Bantam) — front panel - maxConnections: 96 + connection: tt + maxConnections: 48 position: Top + rowPosition: 1 + - key: Ke2xKnlo + name: TT (Bantam) — front panel, bottom row + signalFlow: bidirectional + category: audio + type: line + connection: tt + maxConnections: 48 + position: Top + rowPosition: 2 - key: A52iMuHs name: DB25 — rear panel signalFlow: bidirectional diff --git a/data/hardware/black-lion-audio-pbr-tt.yaml b/data/hardware/black-lion-audio-pbr-tt.yaml index c69fb847f..d22e4eb0f 100644 --- a/data/hardware/black-lion-audio-pbr-tt.yaml +++ b/data/hardware/black-lion-audio-pbr-tt.yaml @@ -27,13 +27,23 @@ specs: |- - Form Factor: 1U rack-mount io: - key: JiTSSPdM - name: TT/Bantam front panel (2 rows of 48) + name: TT/Bantam front panel — top row signalFlow: bidirectional category: audio type: line - connection: TT/Bantam front panel (2 rows of 48) - maxConnections: 96 + connection: tt + maxConnections: 48 position: Top + rowPosition: 1 + - key: LKkqOXrb + name: TT/Bantam front panel — bottom row + signalFlow: bidirectional + category: audio + type: line + connection: tt + maxConnections: 48 + position: Top + rowPosition: 2 - key: n42WskyA name: DB25 rear panel signalFlow: bidirectional diff --git a/data/hardware/catalinbread-rah.yaml b/data/hardware/catalinbread-rah.yaml index 78a622ade..093604d42 100644 --- a/data/hardware/catalinbread-rah.yaml +++ b/data/hardware/catalinbread-rah.yaml @@ -4,6 +4,8 @@ manufacturer: catalinbread primaryCategory: overdrive categories: - amp-sim +searchTerms: + - Royal Albert Hall url: https://catalinbread.com/products/rah prices: - amount: 199.99 diff --git a/data/hardware/collings-cj.yaml b/data/hardware/collings-cj.yaml index 7ff76ccb5..8936b1891 100644 --- a/data/hardware/collings-cj.yaml +++ b/data/hardware/collings-cj.yaml @@ -4,6 +4,8 @@ manufacturer: collings primaryCategory: acoustic-guitar categories: - guitar +searchTerms: + - Collings Jumbo url: https://collingsguitars.com/acoustics/cj/ description: The CJ is a slope-shouldered jumbo acoustic guitar that draws on classic American guitar design while incorporating Collings' hallmark diff --git a/data/hardware/collings-sj.yaml b/data/hardware/collings-sj.yaml index c24136df0..261497cfd 100644 --- a/data/hardware/collings-sj.yaml +++ b/data/hardware/collings-sj.yaml @@ -4,6 +4,8 @@ manufacturer: collings primaryCategory: acoustic-guitar categories: - guitar +searchTerms: + - Small Jumbo url: https://collingsguitars.com/acoustics/sj/ description: The SJ is a Small Jumbo acoustic guitar featuring a 16-inch lower bout with deep sides and a tight waist curve that creates a distinctive sound diff --git a/data/software/air-music-air-expansion-pack-3.yaml b/data/software/air-music-air-expansion-pack-3.yaml index 2ee21a105..0ad63a39a 100644 --- a/data/software/air-music-air-expansion-pack-3.yaml +++ b/data/software/air-music-air-expansion-pack-3.yaml @@ -52,4 +52,3 @@ specs: |- prices: - amount: 249 currency: USD -url: https://www.airmusictech.com/ diff --git a/data/software/air-music-creative-collection.yaml b/data/software/air-music-creative-collection.yaml index 9fa75a767..22c5ea74f 100644 --- a/data/software/air-music-creative-collection.yaml +++ b/data/software/air-music-creative-collection.yaml @@ -94,7 +94,6 @@ specs: |- prices: - amount: 499 currency: USD -url: https://www.airmusictech.com/ links: - type: product url: https://www.airmusictech.com/virtual-instruments/creative-collection.html diff --git a/data/software/air-music-drum-machine-pack.yaml b/data/software/air-music-drum-machine-pack.yaml index fcea3d74e..74152945f 100644 --- a/data/software/air-music-drum-machine-pack.yaml +++ b/data/software/air-music-drum-machine-pack.yaml @@ -67,7 +67,6 @@ specs: |- prices: - amount: 249 currency: USD -url: https://www.airmusictech.com/ links: - type: product url: https://www.airmusictech.com/virtual-instruments/drum-synth-500.html diff --git a/data/software/air-music-essential-pianos-pack.yaml b/data/software/air-music-essential-pianos-pack.yaml index f8443ca2b..c834cce18 100644 --- a/data/software/air-music-essential-pianos-pack.yaml +++ b/data/software/air-music-essential-pianos-pack.yaml @@ -71,4 +71,3 @@ links: - type: support url: https://www.sonivoxmi.com/ title: SONiVOX -url: https://www.airmusictech.com/ diff --git a/data/software/air-music-instrument-expansion-pack-3-premier.yaml b/data/software/air-music-instrument-expansion-pack-3-premier.yaml index 963143564..987154f7a 100644 --- a/data/software/air-music-instrument-expansion-pack-3-premier.yaml +++ b/data/software/air-music-instrument-expansion-pack-3-premier.yaml @@ -74,4 +74,3 @@ links: - type: product url: https://www.plugivery.com/products/p4166-AIR-Instrument-Expansion-Pack-3-Premier/ title: AIR Instrument Expansion Pack 3 Premier -url: https://www.airmusictech.com/ diff --git a/data/software/air-music-super-synth-pack.yaml b/data/software/air-music-super-synth-pack.yaml index 08c0b5625..5f97453a0 100644 --- a/data/software/air-music-super-synth-pack.yaml +++ b/data/software/air-music-super-synth-pack.yaml @@ -94,4 +94,3 @@ videos: title: AIR Super Synth Pack Demo - videoId: j5jempHilX4 title: AIR Super Synth Pack Demo -url: https://www.airmusictech.com/ diff --git a/docs/VALIDATION_ERRORS.md b/docs/VALIDATION_ERRORS.md index 9ca13de5d..488df7313 100644 --- a/docs/VALIDATION_ERRORS.md +++ b/docs/VALIDATION_ERRORS.md @@ -546,6 +546,10 @@ An IO entry sets `maxConnections` greater than 1 on a single-jack connection typ **Fix:** Model each physical jack as its own `io` entry with `maxConnections: 1` (see the Eventide H90 for an example). If the entry really is an intentional aggregate for a connector that carries multiple links (e.g., a D-sub snake), use the correct `connection` type instead. Names containing words like "all", "slots", or "bank" are treated as aggregates and not flagged. +Not flagged: entries whose `primaryCategory` is `patch-bay`. A patchbay row is a +run of identical points that users patch into as one group, so a 48-point row +stays a single `io` entry rather than 48 near-identical ones. + **Triage tip:** Run `pnpm io-quality` to see the full I/O data-quality worklist (combine candidates, collapsed-pair names, missing I/O, and column/row coverage gaps). --- diff --git a/schema/CONTEXT.md b/schema/CONTEXT.md index 16c8a4ee2..5a455d0ec 100644 --- a/schema/CONTEXT.md +++ b/schema/CONTEXT.md @@ -834,11 +834,13 @@ rear-panel diagram — assign them with `pnpm enrich-io `, not during bulk ### IO Connections (advisory — unknown values produce warnings) - `1/4-inch` +- `tt` - `1/8-inch` - `2.5mm` - `xlr` - `mini-xlr` - `combo jack` +- `4-pin din` - `5-pin din` - `7-pin din` - `mini-din` @@ -859,8 +861,10 @@ rear-panel diagram — assign them with `pnpm enrich-io `, not during bulk - `hdmi` - `lightning` - `aes/ebu` +- `digilink` - `2-pin` - `db9` +- `db15` - `db25` - `dt12 37-pin` - `edac` diff --git a/schema/io-connections.yaml b/schema/io-connections.yaml index 8ccc24c43..1b99702c8 100644 --- a/schema/io-connections.yaml +++ b/schema/io-connections.yaml @@ -7,6 +7,9 @@ connections: # Quarter-inch jacks - 1/4-inch + # Bantam / TT jacks (patchbays) + - tt + # Eighth-inch / 3.5mm jacks - 1/8-inch @@ -19,6 +22,7 @@ connections: - combo jack # DIN connectors + - 4-pin din # external analogue PSU (e.g. Black Lion Auteur Quad) - 5-pin din - 7-pin din # powered MIDI (e.g. remote foot controllers) - mini-din @@ -45,10 +49,12 @@ connections: - hdmi - lightning - aes/ebu + - digilink # Avid DigiLink (Pro Tools HD/HDX interface ports) # Multi-pin connectors - 2-pin - db9 # 9-pin D-sub (RS-232C serial control) + - db15 # 15-pin D-sub (e.g. Crane Song STC-8 side chain insert) - db25 - dt12 37-pin - edac diff --git a/scripts/__tests__/acronym-exclusions.test.ts b/scripts/__tests__/acronym-exclusions.test.ts index 8714caa4e..8b0c41421 100644 --- a/scripts/__tests__/acronym-exclusions.test.ts +++ b/scripts/__tests__/acronym-exclusions.test.ts @@ -23,6 +23,20 @@ describe("looksLikeAcronymName", () => { } ); + it.each(["MIXER", "OR", "URLA", "BOB", "BOBEK", "CROM", "LOL"])( + "skips stylized or borrowed name '%s' (exclusion list)", + (name) => { + expect(looksLikeAcronymName(name)).toBe(false); + } + ); + + it.each(["VMA", "VMX", "BCLK", "SFT", "MQ", "MF", "MT"])( + "skips researched letter-name '%s' with no published expansion", + (name) => { + expect(looksLikeAcronymName(name)).toBe(false); + } + ); + it.each(["DR-110", "SM-7B", "OB-Xa", "CS-80 V4", "Pro-Q 3"])( "skips model number '%s' (brandVariants handles these at build time)", (name) => { diff --git a/scripts/__tests__/io-heuristics.test.ts b/scripts/__tests__/io-heuristics.test.ts new file mode 100644 index 000000000..b1dd20d2c --- /dev/null +++ b/scripts/__tests__/io-heuristics.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from "vitest"; +import { isIoCombineCandidate } from "../lib/io-heuristics.js"; + +describe("isIoCombineCandidate", () => { + it("flags several single jacks collapsed into one entry", () => { + expect( + isIoCombineCandidate({ name: "Line Output", connection: "1/4-inch", maxConnections: 4 }) + ).toBe(true); + }); + + it("ignores a single jack", () => { + expect( + isIoCombineCandidate({ name: "Line Output", connection: "1/4-inch", maxConnections: 1 }) + ).toBe(false); + }); + + it("ignores multi-link connectors that carry several channels by design", () => { + expect( + isIoCombineCandidate({ name: "Analog Out", connection: "db25", maxConnections: 8 }) + ).toBe(false); + }); + + it("ignores names that describe an intentional aggregate", () => { + expect( + isIoCombineCandidate({ name: "All Slot Outputs", connection: "1/4-inch", maxConnections: 8 }) + ).toBe(false); + }); + + it("ignores patchbay rows, which are aggregates by category", () => { + const row = { name: 'TRS 1/4" front row', connection: "1/4-inch", maxConnections: 48 }; + expect(isIoCombineCandidate(row)).toBe(true); + expect(isIoCombineCandidate(row, { primaryCategory: "patch-bay" })).toBe(false); + }); + + it("still flags collapsed jacks on non-patchbay categories", () => { + expect( + isIoCombineCandidate( + { name: "Mic Input", connection: "xlr", maxConnections: 8 }, + { primaryCategory: "preamp" } + ) + ).toBe(true); + }); +}); diff --git a/scripts/io-quality.ts b/scripts/io-quality.ts index 8a692b393..5cbcece8b 100644 --- a/scripts/io-quality.ts +++ b/scripts/io-quality.ts @@ -97,7 +97,9 @@ function analyze(filePath: string, data: Hardware, positionExempt: Set): const category = data.primaryCategory ?? ""; const exempt = positionExempt.has(category); - const combineCandidates = io.filter(isIoCombineCandidate).length; + const combineCandidates = io.filter((p) => + isIoCombineCandidate(p, { primaryCategory: category }) + ).length; const collapsedNames = io.filter((p) => p.name && COLLAPSED_PAIR_NAME.test(p.name)).length; const positions = io.map((p) => p.position).filter(Boolean); diff --git a/scripts/lib/acronym-exclusions.ts b/scripts/lib/acronym-exclusions.ts index 25c7d6819..d48bcbc1d 100644 --- a/scripts/lib/acronym-exclusions.ts +++ b/scripts/lib/acronym-exclusions.ts @@ -46,8 +46,10 @@ const ACRONYM_FALSE_POSITIVES: ReadonlySet = new Set([ "lion", "lofi", // "lo-fi" (JST LOFI) "map", + "mixer", // Dangerous Music MIXER, an 8x2 summing mixer "mood", "one", + "or", // logic OR gate (Intellijel OR) "peel", "polar", "silo", @@ -61,9 +63,14 @@ const ACRONYM_FALSE_POSITIVES: ReadonlySet = new Set([ "aum", // Sanskrit syllable (Kymatica AUM) "ciao", // Italian greeting (Bastl CIAO!) "mahi", // mahi-mahi fish (Manley Mahi) + "urla", // Italian for "scream" (AC Noises URLA) "zhega", // Bulgarian for "scorching heat" (Antelope ZHEGA) // Personal names / stylized brand names "abc", // Bastl ABC — named for its A–F channel letters + "bob", // Czech cartoon rabbit (Bastl's Bob a Bobek systems) + "bobek", // sibling of Bastl's Bob, same cartoon pair + "crom", // Conan the Barbarian's deity (Caroline CROM, with Sword/Mountain knobs) + "lol", // Bastl styles it "Lol", not an initialism "crbn", // Audeze CRBN — vowel-less "carbon" "iroi", // Befaco IROI — tail of "Oneiroi" "ivgi", // Klanghelm coinage @@ -87,6 +94,7 @@ const ACRONYM_FALSE_POSITIVES: ReadonlySet = new Set([ const RESEARCHED_NO_EXPANSION: ReadonlySet = new Set([ "adm", // Avantone Pro ADM snare mic "afeq", // Inferior Sound AFEQ + "bclk", // Burl Audio clock daughter card, "B" series part number "bcg", // Code Audio BCG "djs", // Pioneer DJS software "dmx", // Oberheim DMX @@ -94,12 +102,18 @@ const RESEARCHED_NO_EXPANSION: ReadonlySet = new Set([ "dsx", // Oberheim DSX "dx", // Oberheim DX "iieq", // DDMF IIEQ + "mf", // Collings mandolin, M + F-style body; no expansion published "mfd", // ALM Busy Circuits MFD "mfx", // ALM Busy Circuits MFX + "mq", // Dangerous Music MQ + "mt", // Collings mandolin, sibling of the MF; no expansion published "nv", // Numark NV + "sft", // Catalinbread SFT, Ampeg-inspired overdrive "src", // Antelope Audio SRC "stvc", // Waldorf STVC "vfx", // Ensoniq VFX + "vma", // Brauner VM-family tube mic + "vmx", // Brauner VM-family tube mic "vumt", // Klanghelm VUMT ]); diff --git a/scripts/lib/io-heuristics.ts b/scripts/lib/io-heuristics.ts index f9ec59a8c..eadc061c1 100644 --- a/scripts/lib/io-heuristics.ts +++ b/scripts/lib/io-heuristics.ts @@ -20,6 +20,14 @@ export const SINGLE_JACK_CONNECTIONS = new Set([ /** Names that describe an intentional aggregate, not a single jack. */ const AGGREGATE_NAME = /\b(all|slots?|bank|banks|combined|total|each)\b/i; +/** + * Categories whose entries are rows of identical points by definition, so a + * high maxConnections is the intended modelling rather than collapsed jacks. + * A 48-point patchbay row is one port group users patch into, never 48 + * separately named io entries. + */ +const AGGREGATE_CATEGORIES = new Set(["patch-bay"]); + /** Minimal shape needed to evaluate the combine heuristic. */ export interface IoLike { name?: string; @@ -27,15 +35,22 @@ export interface IoLike { maxConnections?: number; } +/** Entry-level context that can exempt an io entry from the heuristic. */ +export interface IoOwner { + primaryCategory?: string; +} + /** * True when an io entry represents a single-jack connection but claims more than * one connection — i.e. several physical jacks likely collapsed into one entry. - * Intentional aggregates ("All Slots", "Bank A") are excluded. + * Intentional aggregates ("All Slots", "Bank A") and whole categories that are + * aggregates by nature (patchbays) are excluded. */ -export function isIoCombineCandidate(io: IoLike): boolean { +export function isIoCombineCandidate(io: IoLike, owner?: IoOwner): boolean { const conn = io.connection?.toLowerCase(); if (!conn || !SINGLE_JACK_CONNECTIONS.has(conn)) return false; if ((io.maxConnections ?? 1) <= 1) return false; if (io.name && AGGREGATE_NAME.test(io.name)) return false; + if (owner?.primaryCategory && AGGREGATE_CATEGORIES.has(owner.primaryCategory)) return false; return true; } diff --git a/scripts/validate.ts b/scripts/validate.ts index 9d86b9820..2a18f8360 100644 --- a/scripts/validate.ts +++ b/scripts/validate.ts @@ -1107,6 +1107,7 @@ function detectSupersedeCycle( interface WarningContext { name?: string; + primaryCategory?: string; io?: Array<{ name: string; type: string; connection: string; maxConnections?: number }>; compatibleWith?: string[]; url?: string; @@ -1154,7 +1155,7 @@ function collectWarnings( // A single-jack connection carries one physical link; maxConnections>1 // usually means several jacks were collapsed into one entry (aggregates // like "All Slots" are excluded). - if (isIoCombineCandidate(io)) { + if (isIoCombineCandidate(io, { primaryCategory: data.primaryCategory })) { const line = getLineForPath(document, lineCounter, ["io", i, "maxConnections"]); warnings.push({ code: ValidationErrorCode.W128_IO_COMBINE_CANDIDATE,