Root cause of the flaky pytest segfault (exit 139): the background scan and enrichment daemon threads (_scan_runner/_enrich_runner) use the shared MetadataDB connection, but test fixtures closed that connection in teardown without stopping them. A daemon thread mid-query on a freed SQLite conn is a native use-after-free → SIGSEGV. The app's startup kicks a scan, so almost any app-booting fixture was vulnerable. It only surfaced now because got-feedback/feedBack#728 added a push trigger, so ci/test runs on every push to main.
Fix: server.py retains the scan/enrich thread handles and adds _join_background_db_threads(); every test fixture now joins the workers before conn.close(). Verified: the full suite runs to completion (no segfault) where it previously crashed at ~25%.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* v3 library: Albums view — the client half of the album-condense work
Follow-up to the query_albums endpoint: the UI that consumes it, plus the
track-order plumbing the endpoint's track list needs.
- Albums view (a fourth view toggle next to grid/tree/folder): album cards
(cover / title / artist / track count) from /api/library/albums,
respecting the active filter drawer; clicking one opens the track list
with per-track play and a Play-album button that feeds the play queue
(falls back to plain playSong when the queue plugin is absent).
- Track order: the scanner now reads the feedpak `track`/`disc` fields
(spec 1.12.0) into new nullable songs columns (idempotent ALTERs), and
the album track list orders by the new `track` sort — disc, then track
number, unauthored charts to the bottom by title. Charts without
authored numbers keep working; they just sort alphabetically.
- The albums view persists like the other view choices.
3 new tests: manifest track/disc extraction (and unauthored -> None),
the disc->track->title sort order over /api/library, and the put()
round-trip. Full-suite failure set matches the known env baseline (one
tuner-config name swapped inside the suite-ordering flake family — the
file passes 25/25 in isolation on clean main).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nm7tHs1Yvjjtnnu4nzJgdN
* v3 albums: honour Genre/Match filters in album grid + detail (review fixes)
The Albums view only partially respected the filter drawer:
- /api/library/albums silently dropped the `genre` and `match` params the
client sends via queryParams(), so with a Genre or Match filter active the
album grid surfaced albums with zero matching tracks. Thread match_states/
genre through the endpoint -> query_albums -> _build_where, mirroring the
/api/library grid route. (SmartCollection/pass-through providers keep their
existing kwarg handling.)
- The album-detail track list built its own params (provider/artist/album/
sort only), so it ignored ALL active filters — the track list and the
Play-album queue could include songs the user had filtered out. Reuse
queryParams({...}, {catalog: true}) so detail honours the same filters as
the grid while pinning this album's artist/album and track order.
+1 regression test (albums endpoint honours the Genre filter).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: byrongamatos <xasiklas@gmail.com>