Skip to content

fix: keep tracks without a track_class row in the sequencing pool#7

Open
gnujoow wants to merge 1 commit into
mainfrom
fix/issue-4-sequence-unclassified
Open

fix: keep tracks without a track_class row in the sequencing pool#7
gnujoow wants to merge 1 commit into
mainfrom
fix/issue-4-sequence-unclassified

Conversation

@gnujoow

@gnujoow gnujoow commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #4.

tracks_for_sequence() used an inner JOIN track_class, so a track inserted outside sync (e.g. a playlist-only track) with full enrichment data was silently dropped from the sequencing pool until a separate classify run. resequence on such a playlist sequenced only 1–3 tracks and appended the rest as "no mixing data" despite BPM/camelot/energy being present.

Changes

  • db.py: tracks_for_sequence now LEFT JOINs track_class; unclassified tracks come back with NULL genre_bucket/dj_slots (enrichment/musicae joins unchanged).
  • sequence.py build_pool: NULL bucket/slots parse to empty lists. Semantics: unclassified tracks pass when no slot/bucket filter is active — which covers resequence and the draft-track (--require-track/--from-playlist) pool, both of which run with filters off — while an explicit --slot/--bucket filter still excludes them (unknown never matches a requested value), so the default sequence pool composition is unchanged.
  • sequence.py transition_cost: an empty bucket set now gets the mild adjacent_penalty instead of other_penalty — unknown isn't a genre clash, matching the existing neutral-when-unknown convention for era/genre distance.
  • sequence.py render_report: fixed a latent IndexError on t.buckets[0] for tracks with no buckets and no genres (renders ?).

I went with the LEFT JOIN option from the issue rather than auto-running classify — it removes the hidden ordering dependency entirely instead of adding another implicit step.

Tests

  • DB level: unclassified-but-enriched track appears in tracks_for_sequence with NULL bucket/slots and joined BPM.
  • Pool level: included with filters off, excluded by explicit slot/bucket filters.
  • Cost level: empty bucket set → adjacent_penalty.
  • End to end: a 4-track all-unclassified pool sequences and renders a report without crashing.

150 passed (baseline 145).

🤖 Generated with Claude Code

tracks_for_sequence used an inner JOIN on track_class, so a track
inserted outside sync (e.g. a playlist-only track) that had full
enrichment (BPM/camelot/energy) was silently excluded from the pool
until a separate classify run — resequence then sequenced only a
handful of tracks and dumped the rest as 'no mixing data'.

- tracks_for_sequence: LEFT JOIN track_class (bucket/slots NULL when
  unclassified)
- build_pool: NULL bucket/slots parse to empty lists. Unclassified
  tracks pass when no slot/bucket filter is active (resequence and the
  draft-track pool run with filters off); an explicit filter still
  excludes them — unknown never matches a requested value
- transition_cost: an empty bucket set gets the mild adjacent_penalty
  instead of other_penalty (unknown isn't a clash — same
  neutral-when-unknown convention as era/genre distance)
- render_report: buckets[0] no longer crashes on an empty bucket list

Fixes #4

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sequence: tracks without track_class row are excluded from pool even when enrichment exists

1 participant