Why
WrzDJSet's per-track energy (set_pool.energy / track_vibe.energy, 0–10) is currently
LLM-inferred (vibe_enrichment.py, #391) — a guess, not a measurement. LexiconDJ runs a
real audio energy analyzer. For DJs who subscribe to Lexicon and keep a local library, we
can offer Lexicon's measured energy as an optional source of truth for WrzDJSet, plus
bidirectional library/playlist sync.
Hard boundary: this is WrzDJSet-only. Normal WrzDJ (the guest request pipeline) is
cloud SaaS and must stay on cloud sources — it cannot depend on a DJ's locally-running app.
This is a research/decision issue (no ADR system here; closest prior records are the #401
spec/plan under docs/superpowers/).
Verified current state
LexiconDJ surfaces
| Surface |
Locality / auth |
Capability |
Local REST API http://localhost:48624 |
localhost-only, off by default, no auth (vendor: "coming"), app must be running |
read GET /v1/tracks (tracks/playlists/cues/beatgrids/tags) |
| Plugin (JS, sandboxed) |
runs inside Lexicon, DJ-installed from Documents/Lexicon/Plugins |
full CRUD tracks+playlists; reads all fields; outbound HTTP POST to whitelisted domains, ignores CORS (_network) |
Plugin globals: _library (CRUD), _vars (selected/all tracks), _network, _storage,
_ui, _musicplayer, _helpers, _files. Sandbox: no require/import/window/document.
Analyzer + the constraint
Lexicon measures energy (absolute scale), BPM/beatgrid (~3ms), key (built-in or free
OpenKeyScan), cue points (ML). Analysis runs on local audio files ("tracks imported from a
DJ app are not auto-analyzed"). WrzDJ tracks are Tidal-backed (no file), so Lexicon data is
available only when the DJ owns + analyzed that track locally — a match-and-enrich keyed
on ISRC (which WrzDJ already carries end-to-end).
Use-case mapping
| Use case |
Verdict |
| Measured energy → WrzDJSet |
🎯 primary goal — ISRC-match a pool track to the DJ's local Lexicon track, pull measured energy, normalize to 0–10, prefer over the LLM guess. Subscriber/opt-in. |
| Library/playlist sync (import Lexicon → WrzDJ pool) |
🆕 plugin reads tracks → POST to WrzDJ ingest; slots into epic #442 Family 4 as import_from_lexicon (cf. #524). |
| key/BPM |
already cloud-covered (Beatport/Tidal). Lexicon only as a WrzDJSet fallback-primary if cloud misses — not a normal-WrzDJ path. |
| cue points |
⏭️ deprioritized (no pool/set consumer today). |
| export WrzDJ → Lexicon |
✅ exists (#401 Rekordbox XML); optional CSV-merge-on-ISRC polish later. |
Architecture + distribution
Primary — WrzDJ-authored Lexicon plugin. Whitelists the WrzDJ API domain, reads tracks
(+ measured energy), POSTs to a new DJ-scoped WrzDJ ingest endpoint. Outbound HTTPS, so
topology-agnostic — works wherever Lexicon runs, including a Windows DJ VM today (no
co-located bridge needed). Can also _library.playlist.create from a WrzDJ set (improves on
the #401 relink flow).
Distribution: the bridge-app installer optionally bundles the plugin installer (drops
the plugin ZIP into Documents/Lexicon/Plugins). Plugin source lives in the WrzDJ monorepo
(lexicon-plugin/), packaged by the bridge-app build — versioned in lockstep with the ingest
contract.
Alt — bridge polls the Local API (read-only). Lighter (no Lexicon-side install) but can't
write playlists, no auth today, and the bridge-app must run on the same host as Lexicon.
Phase 2 (optional) — ISRC match-rate aid via SonoVault. SonoVault
(api.sonovault.now, x-api-key) is an identity/ISRC↔platform-ID resolver — verified to
return id/title/artists/releases/isrc/duration/genre/subgenre + cross-platform links
(Spotify/Beatport/Apple/Tidal/Discogs/MusicBrainz), no BPM/key/energy. Useful to resolve a
Tidal ISRC → Beatport ID (feeding cloud key/BPM) and to raise local-match hit-rates. Pure
matching infra, not an analysis source.
Licensing posture
Lexicon = Rekordcloud B.V., commercial (free + Basic/Pro + Lifetime); conversions/imports are
free-tier. Published Terms are silent on API/plugins (neither grant nor forbid) and the
surfaces are officially documented. Posture: DJ owns + runs + opts into their own licensed
Lexicon; WrzDJ never bundles/redistributes Lexicon or its data; documented surfaces only
(no reverse engineering, no DB writes); treat capability as best-effort/revocable and
degrade gracefully.
Risks & caveats
- Local-file analysis ⇒ energy available only for tracks the DJ has locally (ISRC-gated, opt-in).
- Local API has no auth today (vendor intends to add it) ⇒ the read-only bridge path is
fragile; the plugin path is more durable.
- Subscriber/paid-software dependency + must-be-running + opt-in friction.
- Thin public plugin ecosystem (early-adopter).
Open questions to resolve before building
- Lexicon energy scale → exact normalization to WrzDJ's
0–10.
- Does
GET /v1/tracks expose ISRC + energy fields directly (needed to match + enrich)?
- Do the API/plugins require a paid Lexicon tier (imports are free; API/plugin tier unconfirmed)?
- DJ-scoped WrzDJ token delivery into the plugin (config field vs bridge-style pairing).
- Bridge-app installer mechanics for optionally writing the plugin ZIP into
Documents/Lexicon/Plugins.
Proposed follow-up implementation issue
Child under #442: feat(setbuilder): import_from_lexicon + measured-energy enrichment
(owner-scoped, rationale on mutation, never writes requests, additive/undoable; mirrors #524).
References
#442 (epic), #401 + PR #453, #396, #524 (Family-4 import pattern); enrichment-pipeline
audit #527; docs/superpowers/specs/2026-06-17-issue-401-design.md,
docs/superpowers/plans/2026-06-17-issue-401-engine-lexicon-export.md.
Why
WrzDJSet's per-track energy (
set_pool.energy/track_vibe.energy,0–10) is currentlyLLM-inferred (
vibe_enrichment.py, #391) — a guess, not a measurement. LexiconDJ runs areal audio energy analyzer. For DJs who subscribe to Lexicon and keep a local library, we
can offer Lexicon's measured energy as an optional source of truth for WrzDJSet, plus
bidirectional library/playlist sync.
Hard boundary: this is WrzDJSet-only. Normal WrzDJ (the guest request pipeline) is
cloud SaaS and must stay on cloud sources — it cannot depend on a DJ's locally-running app.
This is a research/decision issue (no ADR system here; closest prior records are the #401
spec/plan under
docs/superpowers/).Verified current state
services/sync/enrichment_pipeline.py): BPM/key = Beatport →Tidal (Spotify only as an ISRC→Tidal bridge; MusicBrainz for genre). Cloud-only.
(Broader pipeline cleanup tracked separately — see research/refactor: audit & document the metadata enrichment-source pipeline #527.)
LexiconDJ surfaces
http://localhost:48624GET /v1/tracks(tracks/playlists/cues/beatgrids/tags)Documents/Lexicon/Plugins_network)Plugin globals:
_library(CRUD),_vars(selected/all tracks),_network,_storage,_ui,_musicplayer,_helpers,_files. Sandbox: norequire/import/window/document.Analyzer + the constraint
Lexicon measures energy (absolute scale), BPM/beatgrid (~3ms), key (built-in or free
OpenKeyScan), cue points (ML). Analysis runs on local audio files ("tracks imported from a
DJ app are not auto-analyzed"). WrzDJ tracks are Tidal-backed (no file), so Lexicon data is
available only when the DJ owns + analyzed that track locally — a match-and-enrich keyed
on ISRC (which WrzDJ already carries end-to-end).
Use-case mapping
0–10, prefer over the LLM guess. Subscriber/opt-in.import_from_lexicon(cf. #524).Architecture + distribution
Primary — WrzDJ-authored Lexicon plugin. Whitelists the WrzDJ API domain, reads tracks
(+ measured energy), POSTs to a new DJ-scoped WrzDJ ingest endpoint. Outbound HTTPS, so
topology-agnostic — works wherever Lexicon runs, including a Windows DJ VM today (no
co-located bridge needed). Can also
_library.playlist.createfrom a WrzDJ set (improves onthe #401 relink flow).
Distribution: the bridge-app installer optionally bundles the plugin installer (drops
the plugin ZIP into
Documents/Lexicon/Plugins). Plugin source lives in the WrzDJ monorepo(
lexicon-plugin/), packaged by the bridge-app build — versioned in lockstep with the ingestcontract.
Alt — bridge polls the Local API (read-only). Lighter (no Lexicon-side install) but can't
write playlists, no auth today, and the bridge-app must run on the same host as Lexicon.
Phase 2 (optional) — ISRC match-rate aid via SonoVault. SonoVault
(
api.sonovault.now,x-api-key) is an identity/ISRC↔platform-ID resolver — verified toreturn
id/title/artists/releases/isrc/duration/genre/subgenre+ cross-platform links(Spotify/Beatport/Apple/Tidal/Discogs/MusicBrainz), no BPM/key/energy. Useful to resolve a
Tidal ISRC → Beatport ID (feeding cloud key/BPM) and to raise local-match hit-rates. Pure
matching infra, not an analysis source.
Licensing posture
Lexicon = Rekordcloud B.V., commercial (free + Basic/Pro + Lifetime); conversions/imports are
free-tier. Published Terms are silent on API/plugins (neither grant nor forbid) and the
surfaces are officially documented. Posture: DJ owns + runs + opts into their own licensed
Lexicon; WrzDJ never bundles/redistributes Lexicon or its data; documented surfaces only
(no reverse engineering, no DB writes); treat capability as best-effort/revocable and
degrade gracefully.
Risks & caveats
fragile; the plugin path is more durable.
Open questions to resolve before building
0–10.GET /v1/tracksexpose ISRC + energy fields directly (needed to match + enrich)?Documents/Lexicon/Plugins.Proposed follow-up implementation issue
Child under #442:
feat(setbuilder): import_from_lexicon+ measured-energy enrichment(owner-scoped,
rationaleon mutation, never writesrequests, additive/undoable; mirrors #524).References
#442 (epic), #401 + PR #453, #396, #524 (Family-4 import pattern); enrichment-pipeline
audit #527;
docs/superpowers/specs/2026-06-17-issue-401-design.md,docs/superpowers/plans/2026-06-17-issue-401-engine-lexicon-export.md.