Taxonomy is compiled. The alias map in src/domain/classification/taxonomy/aliases.rs cannot be changed at runtime. If the user disagrees with a mapping, the agent works around it by using the user’s preferred genre directly.
No auto-tagging. Every genre change requires explicit human approval.
Cache-first. Classification runs from cached data. If cache is empty for a track, it is flagged as insufficient evidence — do not trigger enrichment mid-classification.
XML export only. No direct DB writes. All changes flow through update_tracks → preview_changes → write_xml.
Per-track reasoning is mandatory for low/insufficient confidence. Do not skip or batch-approve these tracks. Delegate to subagents if the volume is large.
Prerequisites
cache_coverage(has_genre=false)
Use the scoped entries as evidence-quality signals. Discogs readiness is
album-aware: searched includes cached no-matches, has_result counts provider
matches, and usable_genre counts matches that map into the classifier
taxonomy. A searched no-match is operationally complete but not genre-usable;
errors are neither searched nor matched. Fill missing core searches and
Stratum analysis where practical:
Traverse each bounded enrichment or audio scope explicitly: begin at
offset=0, record successes and identity-bearing failures, and call again with
offset=page.next_offset while page.has_more is true. Cached/current tracks
do not spend work slots. After the traversal, retry failed explicit
track_ids, then re-run cache_coverage(has_genre=false). Continue until core
searched and Stratum/Essentia readiness matches the intended classification
mode, or report unresolved failures;
do not turn a searched no-match into a required match. Offsets are valid only
while the selector and library ordering stay unchanged, so restart from zero
after imports, deletions, or reordering. Keep providers, skip_cached, and
force_refresh fixed within each enrichment traversal. If Essentia availability
or skip_cached changes during audio traversal, restart that audio scope at
zero because earlier tracks may become pending.
Full classification requires fresh, valid Stratum and Essentia cache rows for
each track. Missing, stale, or invalid analyzer evidence produces Degraded mode,
caps confidence at Low, requires review, and is never auto-staged—even when Low
is requested. A valid sparse analyzer payload still counts as present; its null
detector fields remain unknown rather than becoming zero. Use
cache_coverage and calibration_coverage to see the remaining work. Explicit
--stratum-only CLI analysis remains supported, but cannot by itself produce
Full classification readiness. Retry actual errors, but do not require a
Discogs match for a legitimately searched release.
All classify_tracks calls support max_tracks (default 50, max 200) and their
own explicit offset pagination. Continue until all tracks are covered; this
classification offset is separate from batch hydration page.next_offset.
Steps
1. Normalize aliases
suggest_normalizations(stage_aliases=true)
This auto-stages all non-debatable alias mappings (e.g. Hip-Hop → Hip Hop, DnB → Drum & Bass) and returns grouped results showing each mapping and its track count.
Review the staged aliases. If any are debatable, unstage them with clear_changes(track_ids=[...]) and ask the user. Store overrides for Step 2.
Unknown genres (non-canonical, no alias mapping) will be classified in Step 2 using the has_unknown_genre filter.
2. Classify and get approval policy
Get the confidence distribution first using format="summary":
The summary format returns genre-grouped counts with top artists per genre — no per-track data. Report the aggregate distribution:
"N tracks classified: X high, Y medium, Z low, W insufficient."
Present the confidence distribution and ask the user which tiers to auto-approve:
“Approve all high-confidence? Approve high and medium? Or review everything?”
Default recommendation: approve high, present medium as summary, full review for low/insufficient.
High confidence requires agreement from at least two independent source
groups: Discogs, a distinct Rekordbox label, or audio. Discogs styles and a
label copied from the same Discogs response are one source group, as are audio
rules and calibrated audio profiles. The current genre is only a normalization
hint or conservative tie-breaker; it never supplies independent confidence.
Low- or insufficient-confidence confirmations therefore remain in review
counts and per-track review surfaces.
3. Stage approved tiers
Re-run classification with auto_stage to stage the approved tiers in one shot:
The response includes a staging field with staged and skipped-Degraded
counts. No separate update_tracks call is needed. Degraded recommendations
remain available for manual review and explicit staging through the normal
ChangeManager/XML path.
For medium-confidence tracks that are NOT auto-approved, use format="compact" to get the per-track list for review:
The dispatch format returns artists sorted by track count descending, with
per-track evidence and flags included. It includes low- or
insufficient-confidence confirmations even though they stage no change.
Partition into subagent batches:
Artists with 10+ tracks → dedicated subagent
Remaining artists → batch into subagents of ~40–50 tracks
4.2 Dispatch review subagents
Launch as many subagents in parallel as possible. Each subagent receives:
A list of tracks from the dispatch roster (including evidence and flags)
The review prompt below
Review subagent prompt:
You are classifying genres for tracks in a Rekordbox library. For each track, produce a genre recommendation and stage it.
Evidence and flags are included with each track in the dispatch data. You do NOT need to call resolve_tracks_data.
Tools available:
get_genre_taxonomy() — canonical genre list and BPM ranges
search_tracks(artist="...", has_genre=true) — artist’s other genred tracks in the library (use when you need more context beyond the dispatch data)
What the decision tree already considered:
BPM range plausibility, Discogs genre tags, label-genre mapping, audio energy profile, same-family depth resolution.
What you add:
Artist reputation beyond this library, label/scene context, remix conventions (e.g. remixer known for a specific genre), title interpretation.
Workflow:
Call get_genre_taxonomy() to load the canonical genre list — only recommend genres from this list
Review the evidence and flags included with each track
Check if the artist has other genred tracks in the library via search_tracks where useful
Consider artist reputation, label identity, and track title
Recommend a canonical genre with one-sentence reasoning
After classifying all tracks, stage your recommendations via update_tracks
Output format:
#N Artist — Title
Evidence: [key signals from the evidence array]
Library: [artist's other genres, or "no other tracks"]
Recommend: GENRE — [why]
Tracks to classify:
[track list here]
4.3 Verify staged results
Once all subagents have completed, verify the aggregate results:
preview_changes(format="summary")
Compare the staged track count against dispatch_stats.total_tracks from Step 4.1 (plus any tracks staged in Step 3). If the staged count is lower than expected, identify which artist batches may have failed and report them to the user.
Present the summary to the user. Report: "Review complete: N tracks staged across M genres."
Ask: “Any genres or artists you want to review before export?”
5. Export
preview_changes(format="summary")
Ask user: “Export these changes to XML?”
write_xml()
Report output path, then walk the user through the Rekordbox import:
Add XML to Rekordbox — Open Preferences → Advanced → rekordbox xml → Imported Library → Browse → select the exported XML file.
Open the XML view — In the sidebar, click the “Display rekordbox xml” icon. The imported tracks appear under “All Tracks”.
Import into collection — Select all tracks (Cmd+A), right-click → Import To Collection. When prompted “Do you want to load information in the tag of the library being imported?”, click Yes (tick “Don’t ask me again” for bulk imports).