- SUMMARY.md updated with checkpoint approval and all bugfix commits - STATE.md updated with Phase 13 completion and new decisions - ROADMAP.md plan checkboxes and milestone status updated - REQUIREMENTS.md coverage updated: 31/31 v1.1 requirements complete
12 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 13-library-views-phantom-tracks | 02 | ui, api |
|
|
|
|
|
|
|
|
|
45min | 2026-03-16 |
Phase 13 Plan 02: Library Filter UI & Phantom Track Resolution Summary
Library filter dropdown in top bar with conditional ByLibrary queries across all views, plus ScanHooks-based phantom track auto-resolution after library re-scan
Performance
- Duration: ~45 min (including checkpoint verification and bugfixes)
- Started: 2026-03-16T13:32:45Z
- Completed: 2026-03-16T14:18:00Z
- Tasks: 2 (1 auto + 1 checkpoint:human-verify — APPROVED)
- Files modified: 33 (across 4 code commits)
Accomplishments
- Created
<library-filter>dropdown component in top bar — shows "All Libraries" default plus all configured libraries - Wired all browse views (tracks, albums, artists, genres) and detail views (artist-details, genre-details, album track expansion) to respect active library filter via conditional ByLibrary Wails binding calls
- Search inherits library filter automatically — client-side rankTracks operates on filtered track data
- Playlists remain unfiltered (cross-library by design) — verified during checkpoint
- Fixed pre-existing virtualizer event delegation race condition from Phase 14-03 optimization
- Added phantom track auto-resolution: ScanHooks callback triggers M3U8-based phantom matching after library scan
- Added
phantom_file_pathcolumn (migration 7) to playlist_tracks for reliable phantom→track matching - All 7 Phase 13 requirements verified end-to-end: VIEW-01 through VIEW-04, PLAY-01 through PLAY-03
Task Commits
Each task was committed atomically:
- Task 1: Add library filter state + dropdown + wire all views -
42b8cf9(feat) - Task 2: Verify library filter, cross-library playlists, and phantom tracks - Checkpoint APPROVED
Bugfix Commits (during checkpoint verification)
- Fix: Defer virtualizer event delegation until element exists -
f05d2bb(fix) - Fix: Auto-resolve phantom playlist tracks after library scan -
93262b9(fix) - Fix: Resolve phantom playlist tracks using M3U8 paths after scan -
9f595b7(fix)
Plan metadata: 70e3814 (docs: complete library filter UI plan)
Files Created/Modified
Frontend — Library filter UI (Task 1)
frontend/src/components/library-filter/library-filter.ts— NEW: Library filter dropdown component (native select, design tokens)frontend/src/store/library-store.ts— selectedLibraryId state, conditional ByLibrary dispatch, getLibraries(), invalidationfrontend/src/store/controllers/library-controller.ts— Pass-through for selectedLibraryId, setSelectedLibrary, getLibrariesfrontend/index.html—<library-filter>element added to top bar headerfrontend/index.ts— Import for library-filter componentfrontend/src/components/cover-grid/cover-grid.ts— GetAlbumTracksByLibrary for album expansion dropdownfrontend/src/components/cover-grid/album-selection.ts— Library-aware fetchAlbumTracks helperfrontend/src/components/artists-view/artists-view.ts— GetAlbumsByArtistByLibrary + GetAlbumTracksByLibraryfrontend/src/components/genres-view/genres-view.ts— GetTracksByGenreByLibrary for context menufrontend/src/components/genre-details/genre-details.ts— GetTracksByGenreByLibrary for track loadingfrontend/wailsjs/go/library/Library.d.ts— Regenerated with ByLibrary bindingsfrontend/wailsjs/go/library/Library.js— Regenerated with ByLibrary bindings
Frontend — Virtualizer race condition fix
frontend/src/components/track-list/track-list.ts— Deferred event delegation with guard flag in updated()frontend/src/components/queue-panel/queue-panel.ts— Deferred event delegation with guard flag in updated()
Backend — Phantom track auto-resolution
backend/database/database.go— Migration 7: phantom_file_path column on playlist_tracksbackend/database/sql/schemas/playlist_tracks.sql— phantom_file_path column definitionbackend/database/sql/sqlcgen/models.go— Generated model with PhantomFilePath fieldbackend/database/sql/sqlcgen/playlists.sql.go— Generated query updatesbackend/library/crud.go— Store file_path as phantom_file_path on RemoveLibrarybackend/library/library.go— ScanHooks registration, phantom resolution trigger after scanbackend/playlist/playlist.go— ResolvePhantomTracksAfterScan: M3U8-based phantom matchingbackend/app.go— ScanHooks wiring at app initializationfrontend/wailsjs/go/models.ts— Updated generated modelsfrontend/wailsjs/go/playlist/Service.d.ts— Updated generated bindingsfrontend/wailsjs/go/playlist/Service.js— Updated generated bindings
Decisions Made
- Client-side search filtering: rankTracks already operates on filtered track data from library store — no separate backend SearchTracksByLibrary call needed
- Native
<select>for library filter: Compact, accessible, 32px height matching search bar, no custom dropdown overhead - getAlbumsByArtistNameCached returns null when filter active: Forces backend query to avoid showing stale cross-library cached albums
- ScanHooks callback for phantom resolution: Mirrors established RemovalHooks/RescanHooks pattern — avoids circular dependency between library and playlist packages
- M3U8-based phantom resolution over SQL-only: Reads playlist files to match phantoms by both position and phantom_file_path — handles pre-existing phantoms (match by position) and new ones (match by stored path)
- phantom_file_path column: Stored at removal time so post-scan resolution can match even when M3U8 position changes
Deviations from Plan
Auto-fixed Issues
1. [Rule 3 - Blocking] Wails bindings not yet generated for ByLibrary methods
- Found during: Task 1 (start)
- Issue: Plan 13-01 added Go methods but Wails bindings weren't regenerated
- Fix: Ran
wails generate modulebefore implementation - Files modified: frontend/wailsjs/go/library/Library.d.ts, Library.js
- Verification: All ByLibrary imports resolve correctly
- Committed in:
42b8cf9
2. [Rule 1 - Bug] Info type uses lowercase property names
- Found during: Task 1 (TypeScript typecheck)
- Issue: library-filter.ts used
lib.IDandlib.Namebut Wails-generated Info type useslib.idandlib.name - Fix: Changed to lowercase property access
- Files modified: frontend/src/components/library-filter/library-filter.ts
- Verification:
tsc --noEmitpasses cleanly - Committed in:
42b8cf9
3. [Rule 1 - Bug] Virtualizer event delegation race condition
- Found during: Checkpoint verification (Task 2)
- Issue: Pre-existing race from Phase 14-03 — event delegation on virtualizer failed when element wasn't rendered yet on firstUpdated()
- Fix: Added retry in updated() with guard flag; delegation happens once virtualizer exists
- Files modified: frontend/src/components/track-list/track-list.ts, frontend/src/components/queue-panel/queue-panel.ts
- Verification: Track list and queue panel click/context-menu events work reliably on app launch
- Committed in:
f05d2bb
4. [Rule 2 - Missing Critical] Phantom track auto-resolution after library scan
- Found during: Checkpoint verification (Task 2)
- Issue: Phantom tracks not auto-resolved when library re-added and scanned — users would need to manually resolve each one
- Fix: Added phantom_file_path column (migration 7), store file_path on removal, ResolvePhantomTracksAfterScan via ScanHooks callback with M3U8 path comparison
- Files modified: backend/database/database.go, backend/database/sql/schemas/playlist_tracks.sql, backend/library/crud.go, backend/library/library.go, backend/playlist/playlist.go, backend/app.go
- Verification: Remove library → re-add → scan → phantoms automatically resolve to real tracks
- Committed in:
93262b9,9f595b7
Total deviations: 4 auto-fixed (2 bugs, 1 blocking, 1 missing critical) Impact on plan: All fixes essential for correctness. Virtualizer fix resolved pre-existing race condition exposed by multi-library testing. Phantom auto-resolution is critical UX — users should not need to manually fix playlist tracks after re-adding a library.
Issues Encountered
None beyond the deviations documented above.
User Setup Required
None - no external service configuration required.
Next Phase Readiness
- Phase 13 complete — All 7 requirements verified (VIEW-01 through VIEW-04, PLAY-01 through PLAY-03)
- v1.1 Multi-Library Support milestone complete — Phases 9-13 all done
- Phase 14 (Performance Optimization) already complete — executed in parallel during v1.1 development
- All browse views, search, playlists, and phantom tracks working correctly in multi-library context
Self-Check: PASSED
- All 10 key files exist on disk
- All 5 commits found in git log (
42b8cf9,f05d2bb,93262b9,9f595b7,70e3814) - SUMMARY.md exists at expected path
Phase: 13-library-views-phantom-tracks Completed: 2026-03-16