chore: complete v1.0 Consolidation milestone

Archive milestone artifacts:
- milestones/v1.0-ROADMAP.md (full roadmap archive)
- milestones/v1.0-REQUIREMENTS.md (26/26 requirements complete)
- milestones/v1.0-phases/ (8 phase directories with plans, summaries, verifications)

Updated:
- PROJECT.md: full evolution review, all consolidation requirements validated
- ROADMAP.md: collapsed to milestone summary with archive link
- STATE.md: reset for next milestone
- MILESTONES.md: created with stats and accomplishments
- RETROSPECTIVE.md: created with lessons learned

Deleted:
- REQUIREMENTS.md (archived, fresh for next milestone)

8 phases, 17 plans, 34 tasks, 84 tests added, 6 days
This commit is contained in:
2026-03-05 09:34:43 -05:00
parent 5ef45f91ed
commit 6ce0661fca
58 changed files with 348 additions and 294 deletions
+22
View File
@@ -0,0 +1,22 @@
# Milestones
## v1.0 Consolidation (Shipped: 2026-03-05)
**Phases completed:** 8 phases, 17 plans, 34 tasks
**Timeline:** 6 days (2026-02-27 → 2026-03-05)
**Stats:** 107 commits, 67 source files changed, +5,654/-465 lines, 84 tests added
**Delivered:** Strengthened the existing foundation — correctness, performance, code quality, UX polish, and test coverage — transforming YellowJacket from a working-but-fragile music player into a solid, trustworthy platform for future features.
**Key accomplishments:**
- Eliminated all concurrency races — 4 SetContext methods mutex-protected, app runs clean under `-race` detector
- Closed all error handling gaps — moved startupErr to struct, fixed config permissions, logged MPRIS errors, separated scan warnings from fatals
- Built comprehensive test suite — 84 new unit tests (queue, config, player, FTS5 search, library scan, entity cache) with shared in-memory test DB infrastructure
- Consolidated SQL and enforced code quality — `track_metadata` VIEW eliminating 60 lines of duplicated JOINs, `sqlc.slice()` migration, SAFETY comments on all 12 hand-crafted SQL statements, AST-based Go→TS event codegen
- Optimized backend performance — incremental queue persistence (O(1) add/remove), SetQueue Phase 2 dedup, deferred library loading for instant app shell
- Polished frontend performance and UX — queueMicrotask notification coalescing, design token system, classMap directives, visual consistency audit across all 15 components
**Archive:** [v1.0-ROADMAP.md](milestones/v1.0-ROADMAP.md) | [v1.0-REQUIREMENTS.md](milestones/v1.0-REQUIREMENTS.md)
---
+34 -40
View File
@@ -1,8 +1,8 @@
# YellowJacket — Consolidation Milestone
# YellowJacket
## What This Is
YellowJacket is a cross-platform desktop music player built with Go (Wails v2) and TypeScript (Lit Web Components). It plays local music files (MP3, FLAC, OGG, WAV), manages a music library via SQLite, and provides queue management, playlists, cover art, and MPRIS media controls on Linux. This milestone focuses on strengthening the existing foundation — correctness, performance, code quality, UX polish, and test coverage — before adding new features.
YellowJacket is a cross-platform desktop music player built with Go (Wails v2) and TypeScript (Lit Web Components). It plays local music files (MP3, FLAC, OGG, WAV), manages a music library via SQLite, and provides queue management, playlists, cover art, and MPRIS media controls on Linux. The v1.0 Consolidation milestone strengthened the foundation — all known concurrency races are fixed, error handling is honest, SQL patterns are consolidated, performance bottlenecks are resolved, the frontend follows a consistent design language, and 84 unit tests provide a safety net for future work.
## Core Value
@@ -12,8 +12,6 @@ The music player works reliably and feels solid. Every interaction is correct, r
### Validated
<!-- Existing capabilities confirmed working in the codebase. -->
- ✓ Audio playback (play, pause, stop, seek, volume) for MP3, FLAC, OGG, WAV — existing
- ✓ Library scanning with concurrent metadata extraction pipeline — existing
- ✓ Queue management with shuffle, repeat modes, and auto-advance — existing
@@ -32,54 +30,45 @@ The music player works reliably and feels solid. Every interaction is correct, r
- ✓ TOML-based user configuration with live reload — existing
- ✓ Browse by albums, artists, genres with detail views — existing
- ✓ Virtual scrolling for large lists — existing
- ✓ Concurrency race-free SetContext across Queue, Library, Playlist, Player — v1.0
- ✓ Error handling: startupErr moved to struct, config 0o644, MPRIS errors logged, scan warnings separated — v1.0
- ✓ FTS5 JOIN pattern consolidated into track_metadata VIEW — v1.0
- ✓ Event name codegen (Go→TypeScript) with pre-commit hook enforcement — v1.0
- ✓ Queue batch lookups use sqlc.slice(), all hand-crafted SQL documented with SAFETY comments — v1.0
- ✓ Incremental queue persistence (O(1) add/remove) and SetQueue Phase 2 dedup — v1.0
- ✓ Library store deferred loading for instant app shell — v1.0
- ✓ SQLite performance PRAGMAs (synchronous, cache_size, mmap_size) — v1.0
- ✓ Frontend repeat() with stable keys, queueMicrotask coalescing, classMap directives — v1.0
- ✓ Design token system and visual consistency across all 15 components — v1.0
- ✓ 84 unit tests: queue (29), config/player (10+), FTS5 search (15), library scan (13), entity cache (13+) — v1.0
### Active
<!-- Current scope: consolidation and quality improvements. -->
- [ ] Fix concurrency races in Queue, Library, and Playlist SetContext patterns
- [ ] Fix error handling gaps (swallowed errors in lifecycle callbacks, silent artist credit failures)
- [ ] Eliminate duplicated FTS5 JOIN query patterns across search functions
- [ ] Migrate raw SQL in queue persistence and search to sqlc-generated or type-safe queries
- [ ] Optimize library store to avoid eager full-library fetch on startup
- [ ] Optimize queue persistence to use incremental updates instead of full rewrites
- [ ] Fix SetQueue Phase 2 to skip already-resolved tracks from Phase 1
- [ ] Improve frontend rendering performance for large libraries
- [ ] Polish UI interactions — responsiveness, visual consistency, transitions
- [ ] Add unit tests for queue operations (SetQueue, navigation, shuffle, repeat, persistence)
- [ ] Add unit tests for library scan logic (metadata processing, entity cache, orphan cleanup)
- [ ] Add unit tests for database layer (FTS5 queries, migrations)
- [ ] Add unit tests for config (load/save roundtrip, validation, defaults)
- [ ] Extract testable pure logic from player (volume math, state serialization)
- [ ] Fix config file permissions (0o666 → 0o644)
- [ ] Address package-level startupErr variable (move to struct field)
- [ ] Add event name parity validation between Go and TypeScript
(No active requirements — next milestone not yet scoped. Run `/gsd-new-milestone` to define.)
### Out of Scope
<!-- Explicit boundaries for this milestone. -->
- Tag writing (track metadata editing) — feature work, not consolidation
- Scan cancellation — feature work, deferred to future milestone
- Cross-platform media controls (macOS/Windows) — feature work
- Database health checking / reconnection — low priority, desktop app context
- New features of any kind — this milestone is purely about improving what exists
- File decomposition for its own sake — only extract when it enables reuse or fixes problems
- ORM or query builder — would fight existing sqlc architecture
- Connection pooling for SQLite — meaningless with SetMaxOpenConns(1)
## Context
YellowJacket is a personal project built by a single developer. The core music player functionality is complete and working. The developer uses the app daily and notices quality-of-life issues that accumulate. Before adding new features (which are planned but not yet scoped), the goal is to reach a confidence level where the foundation can be trusted.
**Codebase state (as of 2026-02-26):**
**Current state (v1.0 shipped 2026-03-05):**
- Go 1.25, Wails v2.10.2, Lit 3.2.1, SQLite via modernc.org/sqlite
- ~22,450 Go LOC + ~28,600 TypeScript LOC + ~5,200 Go test LOC
- ~15 backend packages, ~20 frontend components
- Strict linting (golangci-lint v2) and TypeScript strict mode
- No unit tests for queue, library, database, config packages
- Player tests require hardware (skipped in CI)
- No frontend tests
- Several known concurrency races (documented but not fixed)
- Performance bottlenecks identified in library loading and queue persistence
- Large frontend components (1400-2600 lines) with mixed concerns
- 84 unit tests covering queue, config, player, database, library packages
- All concurrency races fixed, app runs clean under `-race`
- SQL consolidated: track_metadata VIEW, sqlc.slice(), SAFETY comments
- Frontend: design token system, virtual scrolling with stable keys, debounced store notifications
- Player tests still require hardware (skipped in CI)
- No frontend unit tests (deferred to v2)
**Codebase analysis available in:**
- `.planning/codebase/ARCHITECTURE.md`
@@ -101,10 +90,15 @@ YellowJacket is a personal project built by a single developer. The core music p
| Decision | Rationale | Outcome |
|----------|-----------|---------|
| Consolidation before features | Technical debt compounds — fixing it now is cheaper than fixing it later under more code | — Pending |
| Tests support refactoring, not standalone goal | Testing is a means to safe refactoring, not a coverage target | — Pending |
| No cosmetic file splitting | Large files are only a problem if they cause real issues; extract only for reuse or correctness | — Pending |
| All improvement areas equal priority | Correctness, performance, code quality, UX, and testing are interdependent | — Pending |
| Consolidation before features | Technical debt compounds — fixing it now is cheaper than fixing it later under more code | ✓ Good — solid foundation established |
| Tests support refactoring, not standalone goal | Testing is a means to safe refactoring, not a coverage target | ✓ Good — 84 tests enabled safe SQL and perf refactoring |
| No cosmetic file splitting | Large files are only a problem if they cause real issues; extract only for reuse or correctness | ✓ Good — avoided unnecessary churn |
| All improvement areas equal priority | Correctness, performance, code quality, UX, and testing are interdependent | ✓ Good — balanced approach worked well |
| Fix races → tests → refactoring order | Can't run `-race`-clean tests with active data races; can't safely refactor without tests | ✓ Good — each phase built on the last |
| SQLite VIEW for JOIN dedup | track_metadata VIEW consolidates 5-table JOIN; migration keeps inline for upgrade | ✓ Good — 60 lines eliminated, tests unchanged |
| AST-based event codegen | Deterministic declaration-order output, no regex fragility | ✓ Good — found LibraryConfigChanged gap automatically |
| queueMicrotask over setTimeout | Synchronous microtask batching is more predictable than macrotask scheduling | ✓ Good — coalesces 8+ notifications per scan |
| Design tokens via :host scope | Component-level token scope matches Lit's shadow DOM encapsulation | ✓ Good — consistent visual language achieved |
---
*Last updated: 2026-02-27 after initialization*
*Last updated: 2026-03-05 after v1.0 milestone*
+76
View File
@@ -0,0 +1,76 @@
# Project Retrospective
*A living document updated after each milestone. Lessons feed forward into future planning.*
## Milestone: v1.0 — Consolidation
**Shipped:** 2026-03-05
**Phases:** 8 | **Plans:** 17 | **Tasks:** 34
**Timeline:** 6 days (2026-02-27 → 2026-03-05)
### What Was Built
- Race-free concurrency across all 4 SetContext entry points
- Honest error handling: startupErr to struct, config permissions, MPRIS logging, scan warning separation
- 84 unit tests covering queue, config, player, FTS5 search, library scan, entity cache
- SQL consolidation: track_metadata VIEW, sqlc.slice() migration, SAFETY comments on 12 hand-crafted queries
- AST-based Go→TypeScript event codegen with pre-commit enforcement
- Incremental queue persistence (O(1) add/remove) and SetQueue Phase 2 dedup
- Deferred library store loading for instant app shell
- Frontend design token system, classMap directives, queueMicrotask coalescing
- Visual consistency audit across all 15 components
### What Worked
- **Dependency-ordered phases:** Fixing races → building test infra → writing tests → refactoring → performance → UX created a clean progression where each phase built on the last
- **Characterization tests before refactoring:** Writing tests in Phase 4-5 before SQL consolidation in Phase 6 caught zero regressions — the tests were accurate safety nets
- **Small, focused plans:** 2-3 tasks per plan kept execution fast and context fresh — most plans completed in under 10 minutes
- **Research phase for SQL consolidation:** Phase 6 research validated sqlc + VIEW + FTS5 compatibility before planning, avoiding mid-execution discovery
- **Internal package tests:** Testing queue/library as package-internal (not `_test` suffix) gave access to unexported fields for thorough state verification
### What Was Inefficient
- **Phase 8 repeat() regression:** Migrating virtualizers to `repeat()` directive in Plan 02 broke virtualization (repeat as child content bypasses lit-virtualizer's DOM management). Required a hotfix (72ef719) reverting to `.renderItem` + `.keyFunction`. Research should have caught this API distinction.
- **Task count tracking:** STATE.md only tracked tasks-per-plan for later phases (5-8), making total task count harder to derive at milestone completion
- **No startup time measurement:** TODO to measure startup time before Phase 7 lazy loading was never done — can't quantify the improvement
### Patterns Established
- **Mutex-protected setter pattern:** Lock → write field → release lock → call callbacks (prevents deadlock from callback re-entry)
- **ScanWarning + addWarning pattern:** Mutex-protected warning collection for non-fatal errors during long-running operations
- **applyPRAGMAs shared function:** Single source of truth for SQLite PRAGMAs, shared between production NewDB and test NewTestDB
- **SAFETY comment convention:** Two-part format (why + safety assurance) for hand-crafted SQL that bypasses sqlc
- **AST-based codegen over regex:** go/ast + go/parser for cross-language constant synchronization
- **Design token CSS custom properties:** `--yj-icon-sm/md/lg`, `--yj-text-xs/sm/md/lg/xl` scoped to `:host` in Lit components
- **queueMicrotask coalescing:** Batch multiple synchronous store notifications into single subscriber update
### Key Lessons
1. **Test the API contract, not the implementation surface:** repeat() inside lit-virtualizer looks correct syntactically but violates the component's rendering contract. Always verify how a library expects to be consumed, not just what compiles.
2. **Research before planning pays off immediately:** Phase 6 research confirmed sqlc + VIEW compatibility, saving mid-execution discovery and potential re-planning.
3. **Incremental persistence is O(complexity) not O(code):** The incremental queue persistence (Phase 7) was conceptually simple but required careful position-shift SQL for insert/remove operations — more thought than code.
4. **Design tokens must precede visual consistency work:** Phase 8 correctly defined tokens in Plan 01 before applying them in Plan 04 — reversing this order would have required double work.
5. **Contentless FTS5 has deletion limitations:** Cannot DELETE from tables with `content=''`. Document this in tests rather than fighting it — stale entries are harmless for the use case.
### Cost Observations
- Model mix: Primarily opus for planning + execution, sonnet for research
- Total commits: 107 across 6 days
- Notable: Plans averaging 2-6 minutes execution time; Phase 8 Plan 04 (visual audit across 15 components) was the longest at 8 minutes
- Efficiency: 17 plans × ~5 min avg = ~85 min total execution time for 34 tasks across 67 source files
---
## Cross-Milestone Trends
### Process Evolution
| Milestone | Days | Phases | Plans | Key Change |
|-----------|------|--------|-------|------------|
| v1.0 | 6 | 8 | 17 | First milestone — established GSD workflow, research-before-plan pattern |
### Cumulative Quality
| Milestone | Tests Added | Total Tests | Key Quality Win |
|-----------|-------------|-------------|-----------------|
| v1.0 | 84 | 84 | From 0 backend tests to comprehensive coverage of queue, config, player, database, library |
### Top Lessons (Verified Across Milestones)
1. Dependency-ordered phases (fix → test → refactor → optimize) prevent rework and ensure each phase builds on a stable foundation
2. Small plans (2-3 tasks, <10 min) maintain consistent quality — no context degradation
3. Research phases for unfamiliar domains (sqlc + VIEW, lit-virtualizer API) prevent mid-execution surprises
+26 -137
View File
@@ -1,149 +1,38 @@
# Roadmap: YellowJacket Consolidation
# Roadmap: YellowJacket
**Created:** 2026-02-27
**Depth:** Comprehensive
**Phases:** 8
**Requirements:** 26/26 mapped
## Milestones
-**v1.0 Consolidation** — Phases 1-8 (shipped 2026-03-05) — [archive](milestones/v1.0-ROADMAP.md)
## Phases
- [x] **Phase 1: Concurrency Race Fixes** — Eliminate all SetContext data races across Queue, Library, Playlist, and Player
- [x] **Phase 2: Backend Correctness** — Fix error handling gaps, file permissions, package-level state, and scan error separation
- [x] **Phase 3: Test Infrastructure** — Create in-memory SQLite test helper and apply production SQLite PRAGMAs
- [x] **Phase 4: Queue, Config & Player Tests** — Write unit tests for queue operations, config roundtrip, and extracted player pure logic
- [x] **Phase 5: Database & Library Tests** — Write unit tests for FTS5 search queries, migrations, library scan, and entity cache
- [x] **Phase 6: SQL Consolidation & Code Quality** — Deduplicate FTS5 queries via VIEW, add event codegen, migrate to sqlc where feasible, document exceptions
- [x] **Phase 7: Backend Performance** — Optimize queue persistence, fix SetQueue Phase 2 redundancy, enable lazy library loading
- [x] **Phase 8: Frontend Performance & UX** — Optimize frontend rendering for large libraries and fix visual inconsistencies
<details>
<summary>✅ v1.0 Consolidation (Phases 1-8) — SHIPPED 2026-03-05</summary>
## Phase Details
- [x] Phase 1: Concurrency Race Fixes (1/1 plans) — completed 2026-02-28
- [x] Phase 2: Backend Correctness (2/2 plans) — completed 2026-03-03
- [x] Phase 3: Test Infrastructure (1/1 plans) — completed 2026-03-04
- [x] Phase 4: Queue, Config & Player Tests (2/2 plans) — completed 2026-03-04
- [x] Phase 5: Database & Library Tests (2/2 plans) — completed 2026-03-04
- [x] Phase 6: SQL Consolidation & Code Quality (3/3 plans) — completed 2026-03-04
- [x] Phase 7: Backend Performance (2/2 plans) — completed 2026-03-05
- [x] Phase 8: Frontend Performance & UX (4/4 plans) — completed 2026-03-05
### Phase 1: Concurrency Race Fixes
**Goal:** All SetContext patterns across the codebase are race-free and the app can run under `-race` without data race reports
**Depends on:** Nothing (first phase)
**Requirements:** CORR-01, CORR-02, CORR-03, CORR-04
**Success Criteria** (what must be TRUE):
1. Running the app with `go test -race` produces zero data race reports for SetContext calls in queue, library, playlist, and player packages
2. Queue.SetContext(), Library.SetContext(), and Playlist.Service.SetContext() each acquire their mutex before writing the ctx field
3. Player.SetContext() uses a single lock acquisition instead of the double-lock pattern
4. Concurrent calls to SetContext from multiple goroutines do not corrupt shared state
**Plans:** 1 plan
Plans:
- [x] 01-01-PLAN.md — Add mutex protection to all SetContext methods and collapse Player double-lock
### Phase 2: Backend Correctness
**Goal:** All known error handling gaps are closed, configuration is secure, and the backend reports problems honestly instead of swallowing them
**Depends on:** Phase 1 (race-free code is prerequisite for reliable error paths)
**Requirements:** CORR-05, CORR-06, CORR-07, CORR-08, CORR-09
**Success Criteria** (what must be TRUE):
1. The package-level `startupErr` variable no longer exists; startup errors are stored in a YellowJacketApp struct field
2. Config files are written with 0o644 permissions (owner read/write, group/other read-only)
3. MPRIS lifecycle callback errors (Pause, Seek) appear in the application log instead of being silently discarded
4. Artist credit link creation checks the actual error — only UNIQUE constraint violations are ignored, all other errors are surfaced
5. Library.Scan() returns warnings (skipped files, partial failures) in ScanMetrics and fatal errors (database failures) in the error return, so callers can distinguish between "scan completed with issues" and "scan failed"
**Plans:** 2 plans
Plans:
- [x] 02-01-PLAN.md — Fix startupErr global state, config permissions, and MPRIS callback error logging
- [x] 02-02-PLAN.md — Add IsUniqueViolation helper, migration 3, and separate scan warnings from fatal errors
### Phase 3: Test Infrastructure
**Goal:** A reliable, production-mirroring test foundation exists so that all subsequent test phases can write database-backed tests with confidence
**Depends on:** Phase 1 (race-free code required for `-race`-clean test runs), Phase 2 (correct error handling needed for accurate test assertions)
**Requirements:** TEST-01, PERF-04
**Success Criteria** (what must be TRUE):
1. `database.NewTestDB(t)` returns a clean in-memory SQLite database that applies the same migrations and PRAGMAs as the production `NewDB()`
2. Production SQLite connection applies `synchronous=NORMAL`, `cache_size=-8000`, and `mmap_size=67108864` PRAGMAs at database open
3. Each test gets an isolated database instance — no shared state between test functions
4. Tests using `NewTestDB` pass with `-race` flag enabled
**Plans:** 1 plan
Plans:
- [x] 03-01-PLAN.md — Extract shared applyPRAGMAs, add production PRAGMAs, and create NewTestDB helper
### Phase 4: Queue, Config & Player Tests
**Goal:** The queue, config, and player packages have comprehensive unit tests that characterize current behavior and serve as a safety net for later refactoring
**Depends on:** Phase 3 (queue tests need NewTestDB for persistence tests)
**Requirements:** TEST-02, TEST-04, TEST-05
**Success Criteria** (what must be TRUE):
1. Queue package has ~15-20 tests covering SetQueue, Next, Previous, shuffle mode, repeat modes (off, one, all), and state persistence across save/load cycles
2. Config package has ~8-10 tests covering load/save roundtrip fidelity, validation rule enforcement, default value application, and graceful handling of missing or empty config files
3. Player pure logic (UserVolume↔Volume conversion, state serialization/deserialization, format detection from file extension) is extracted into standalone functions with ~5-8 unit tests
4. All tests in this phase pass with `-race` flag enabled
**Plans:** 2 plans
Plans:
- [x] 04-01-PLAN.md — Queue package unit tests (core operations, navigation, persistence roundtrip)
- [x] 04-02-PLAN.md — Config + Player tests (sub-config validators, load/save roundtrip, volume conversion, state mapping)
### Phase 5: Database & Library Tests
**Goal:** Database queries (especially FTS5 search) and library scan logic have unit tests that lock down current behavior before SQL consolidation and performance optimization
**Depends on:** Phase 3 (database tests need NewTestDB), Phase 4 (queue tests validate persistence patterns reused here)
**Requirements:** TEST-03, TEST-06
**Success Criteria** (what must be TRUE):
1. Database package has ~10-15 tests covering FTS5 search (basic terms, empty query, special characters, multi-word), search index rebuild, and schema migration application
2. Library scan logic has ~10-15 tests covering metadata extraction processing, entity cache hit/miss behavior, and orphan track cleanup
3. FTS5 search tests verify that search ranking produces consistent, expected ordering for known test data
4. All tests in this phase pass with `-race` flag enabled
**Plans:** 2 plans
Plans:
- [x] 05-01-PLAN.md — FTS5 search tests, pure helper tests, search index operations, migration verification
- [x] 05-02-PLAN.md — Entity cache tests, library pure helpers, orphan cleanup tests
### Phase 6: SQL Consolidation & Code Quality
**Goal:** Duplicated SQL patterns are eliminated, event names are provably synchronized between Go and TypeScript, and intentional SQL exceptions are documented
**Depends on:** Phase 5 (FTS5 search tests verify consolidation doesn't break ranking; database tests verify migration safety)
**Requirements:** QUAL-01, QUAL-02, QUAL-03, QUAL-04
**Success Criteria** (what must be TRUE):
1. The duplicated 5-table FTS5 JOIN pattern is consolidated into a single SQLite VIEW (`track_metadata` or similar), and all search queries use the VIEW instead of inline JOINs
2. A code generator reads Go event constants from `backend/events/events.go` and produces `frontend/src/events.ts`, wired into `go generate` and the pre-commit hook — adding an event in Go without regenerating TypeScript fails the hook
3. Queue batch lookups in `persistence.go` use `sqlc.slice()` for IN clauses where sqlc supports it, replacing `fmt.Sprintf` placeholder construction
4. Every hand-crafted SQL statement that intentionally bypasses sqlc has a `// SAFETY:` comment explaining why (batch INSERT, dynamic IN clauses, etc.)
**Plans:** 3 plans
Plans:
- [x] 06-01-PLAN.md — Create track_metadata VIEW and consolidate search queries
- [x] 06-02-PLAN.md — Event codegen tool (Go→TypeScript) and pre-commit hook wiring
- [x] 06-03-PLAN.md — Migrate lookupChunk to sqlc.slice() and add SAFETY comments to all hand-crafted SQL
### Phase 7: Backend Performance
**Goal:** Queue mutations and library loading are fast — single-track queue changes are O(1) instead of O(n), and the library doesn't block startup with a full data fetch
**Depends on:** Phase 4 (queue tests verify persistence optimization doesn't lose data), Phase 5 (library tests verify lazy loading doesn't break data access)
**Requirements:** PERF-01, PERF-02, PERF-03
**Success Criteria** (what must be TRUE):
1. Adding or removing a single track from the queue uses incremental INSERT/DELETE via existing sqlc queries, not a full table rewrite
2. SetQueue Phase 2 (`resolveRemainingTracks`) skips file paths that were already resolved in Phase 1, eliminating redundant database lookups
3. Library store constructor no longer calls `eagerFetch()` — data loads lazily on first access via the existing `getTracks()`/`getAlbums()`/etc. getters, and the app starts without blocking on a full library load
**Plans:** 2 plans
Plans:
- [x] 07-01-PLAN.md — Incremental queue persistence + SetQueue Phase 2 dedup
- [x] 07-02-PLAN.md — Library store deferred eager loading
### Phase 8: Frontend Performance & UX
**Goal:** The app feels smooth and visually consistent — large libraries render without jank, and the UI follows a coherent visual language
**Depends on:** Phase 7 (backend lazy loading changes the data availability pattern the frontend consumes)
**Requirements:** PERF-05, UX-01, UX-02
**Success Criteria** (what must be TRUE):
1. Track and album lists use Lit `repeat()` directive with stable keys (filePath for tracks, albumId for albums) for efficient DOM reuse during scrolling and filtering
2. Store notifications during rapid updates (e.g., library scan) are debounced via `queueMicrotask()` to prevent layout thrashing
3. Visual inconsistencies (spacing, colors, typography, icon sizing) are audited and follow a consistent pattern across all components
4. Scrolling, view switching, and search filtering in a 10k+ track library are smooth with no visible jank or dropped frames
**Plans:** 4 plans
Plans:
- [x] 08-01-PLAN.md — Store debouncing (queueMicrotask), search debounce, design token definitions
- [x] 08-02-PLAN.md — Virtualizer repeat() directive migration (all 5 components)
- [x] 08-03-PLAN.md — Track-list/queue-panel render optimization (classMap, search highlight short-circuit)
- [x] 08-04-PLAN.md — Visual consistency audit & token application across all components
</details>
## Progress
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Concurrency Race Fixes | 1/1 | Complete | 2026-02-28 |
| 2. Backend Correctness | 2/2 | Complete | 2026-03-03 |
| 3. Test Infrastructure | 1/1 | Complete | 2026-03-04 |
| 4. Queue, Config & Player Tests | 2/2 | Complete | 2026-03-04 |
| 5. Database & Library Tests | 2/2 | Complete | 2026-03-04 |
| 6. SQL Consolidation & Code Quality | 3/3 | Complete | 2026-03-04 |
| 7. Backend Performance | 2/2 | Complete | 2026-03-05 |
| 8. Frontend Performance & UX | 4/4 | Complete | 2026-03-05 |
| Phase | Milestone | Plans Complete | Status | Completed |
|-------|-----------|----------------|--------|-----------|
| 1. Concurrency Race Fixes | v1.0 | 1/1 | Complete | 2026-02-28 |
| 2. Backend Correctness | v1.0 | 2/2 | Complete | 2026-03-03 |
| 3. Test Infrastructure | v1.0 | 1/1 | Complete | 2026-03-04 |
| 4. Queue, Config & Player Tests | v1.0 | 2/2 | Complete | 2026-03-04 |
| 5. Database & Library Tests | v1.0 | 2/2 | Complete | 2026-03-04 |
| 6. SQL Consolidation & Code Quality | v1.0 | 3/3 | Complete | 2026-03-04 |
| 7. Backend Performance | v1.0 | 2/2 | Complete | 2026-03-05 |
| 8. Frontend Performance & UX | v1.0 | 4/4 | Complete | 2026-03-05 |
---
*Roadmap created: 2026-02-27*
*Last updated: 2026-03-05*
*Last updated: 2026-03-05 — v1.0 milestone archived*
+32 -117
View File
@@ -1,9 +1,9 @@
---
gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
status: completed
last_updated: "2026-03-05T14:22:09.168Z"
milestone_name: Consolidation
status: shipped
last_updated: "2026-03-05"
progress:
total_phases: 8
completed_phases: 8
@@ -11,147 +11,62 @@ progress:
completed_plans: 17
---
# YellowJacket — Consolidation Milestone State
# YellowJacket — Project State
## Project Reference
See: .planning/PROJECT.md (updated 2026-03-05)
**Core value:** The music player works reliably and feels solid — every interaction is correct, responsive, and trustworthy.
**Current focus:** All 8 phases complete. All 26 consolidation milestone requirements delivered. Ready for milestone completion.
**Milestone:** Consolidation (correctness, performance, code quality, UX polish, test coverage)
**Current focus:** v1.0 Consolidation shipped. Planning next milestone.
## Current Position
**Phase:** 08-frontend-performance-ux
**Plan:** 4/4 (All plans complete)
**Status:** Milestone complete
```
Phase Progress: [########] 8/8 phases — All phases complete ✓
```
## Performance Metrics
| Metric | Value |
|--------|-------|
| Phases complete | 7/8 |
| Plans complete | 4/4 (Phase 8) |
| Requirements delivered | 26/26 |
| Tests added | 84 |
| Bugs fixed | 9 |
| 01-01 duration | 11 min |
| 02-01 duration | 12 min |
| 02-02 duration | 50 min |
| 03-01 duration | 3 min |
| 04-01 duration | 3 min |
| 04-02 duration | 4 min |
| 05-01 duration | 9 min |
| 05-02 duration | 4 min |
| Phase 05 P01 | 9 min | 2 tasks | 1 files |
| Phase 05 P02 | 4 min | 2 tasks | 1 files |
| Phase 06 P01 | 2 min | 2 tasks | 4 files |
| Phase 06 P02 | 2 min | 2 tasks | 3 files |
| Phase 06 P03 | 6 min | 2 tasks | 7 files |
| Phase 07 P01 | 5 min | 2 tasks | 2 files |
| Phase 07 P02 | 1 min | 1 tasks | 1 files |
| Phase 08 P01 | 1 min | 2 tasks | 3 files |
| Phase 08 P02 | 3 min | 2 tasks | 5 files |
| Phase 08 P03 | 2 min | 2 tasks | 2 files |
| Phase 08 P04 | 8 min | 3 tasks | 15 files |
**Milestone:** v1.0 Consolidation — SHIPPED 2026-03-05
**Next:** Run `/gsd-new-milestone` to define next milestone
## Accumulated Context
### Key Decisions
| Decision | Rationale | Phase |
|----------|-----------|-------|
| Fix races before tests | Can't run `-race`-clean tests with active data races | Phase 1 → 3 |
| PRAGMAs with test infra | NewTestDB must mirror production DB setup; PRAGMAs change production NewDB | Phase 3 |
| Tests before refactoring | Research unanimously recommends characterization tests as safety net | Phase 4-5 → 6-7 |
| SQL consolidation after DB tests | FTS5 search tests verify VIEW doesn't change ranking | Phase 5 → 6 |
| Frontend last | Backend API should be stable before frontend adapts | Phase 8 |
| Release mutex before Wails runtime calls | Library/Playlist SetContext releases lock before registerEventHandlers/migrateExistingPlaylists to avoid blocking | Phase 1 |
| Player SetContext single-lock | Collapsed double-lock to prevent partially-initialized observable state | Phase 1 |
| MPRIS closures inline, Warn level | Non-fatal OS media control failures logged at Warn, kept as inline closures | Phase 2 |
| Pass metrics through cachedLinkArtist | Consistent void-return pattern; warnings collected via addWarning | Phase 2 |
| Fatal vs warning error classification | tx.Commit failures are fatal; all other scan errors are warnings in ScanMetrics | Phase 2 |
| applyPRAGMAs unexported, shared | Package-internal function ensures NewDB and NewTestDB have identical PRAGMA config | Phase 3 |
| NewTestDB uses t.Fatalf not error return | Test DB setup failures are always fatal — no partial test execution | Phase 3 |
| Internal queue tests (package queue) | Access unexported fields (shuffleOrder, mu) for thorough state verification | Phase 4 |
| Persistence roundtrip verifies shuffleOrder JSON | Safety net for Phase 7 incremental persistence refactoring | Phase 4 |
| Volume roundtrip ±1 tolerance | ToUserVolume uses int truncation not rounding, causing up to 1 unit drift | Phase 4 |
| Direct Library construction in tests | Bypasses Config.Validate os.Stat; entity cache functions only need ctx + db | Phase 5 |
| Contentless FTS5 DELETE limitation | DeleteSearchIndex errors on content='' tables; production logs warning, stale entries are harmless | Phase 5 |
| SQLite VIEW for JOIN dedup | track_metadata VIEW consolidates 5-table JOIN; migration2 keeps inline JOIN for upgrade path | Phase 6 |
| AST-based event codegen | Iterate f.Decls directly for deterministic declaration-order output; atomic writes via temp+rename | Phase 6 |
| sqlc.slice() for batch lookups | LookupTrackMetaByPaths uses track_metadata VIEW; chunking preserved at 900 since sqlc.slice() doesn't auto-chunk | Phase 6 |
| SAFETY comment convention | Two-part format (why + safety assurance); cross-references from library.go/rescan.go to search.go | Phase 6 |
| DOMContentLoaded over load event | Fires earlier (after HTML parsed) without waiting for all resources; still defers past module evaluation | Phase 7 |
| Incremental persistence for single-item mutations | Single-track add/remove use INSERT/DELETE + position shift; bulk ops keep full rewrite | Phase 7 |
| Hand-crafted SQL for variable-N position shift | sqlc ShiftQueuePositionsUp only shifts by 1; variable-N needs raw UPDATE with SAFETY comment | Phase 7 |
| queueMicrotask coalescing over setTimeout | Synchronous microtask batching is more predictable and lower latency than macrotask scheduling | Phase 8 |
| 150ms search debounce with instant clear | Balances responsiveness with computation cost; empty clears are immediate for snappy UX | Phase 8 |
| :host scoped design tokens | Component-level token scope matches Lit's shadow DOM encapsulation model | Phase 8 |
| Inline repeat() keys over gridKeyFunction | Dead method removal; key logic is cleaner inline in repeat() calls | Phase 8 |
| classMap over array filter/join | Eliminates per-row array allocation; classMap diffs internally for efficient DOM updates | Phase 8 |
| Hoist search term outside cols.map | Avoids redundant property access per column per row in render hot path | Phase 8 |
| em→px with 16px base for sidebar | Eliminates compound inheritance issues from nested em values | Phase 8 |
| .renderItem+.keyFunction over repeat() for virtualizers | repeat() as child content bypasses virtualization; .renderItem is the proper lit-virtualizer API | Phase 8 |
| Cover-grid dynamic text tiers mapped to type scale | updateSizeProperties() uses --yj-text-xs/sm/md/lg tokens instead of hardcoded px | Phase 8 |
Decisions from v1.0 are archived in PROJECT.md Key Decisions table. Key patterns to carry forward:
### TODOs
- Mutex-protected setter pattern (lock → write → release → callbacks)
- SAFETY comment convention for hand-crafted SQL
- AST-based codegen for cross-language constant sync
- Design tokens via `:host` scoped CSS custom properties
- queueMicrotask coalescing for store notifications
- `.renderItem` + `.keyFunction` (not `repeat()` children) for lit-virtualizer
- [x] Plan Phase 1 (complete)
- [x] Execute Phase 1 Plan 01 (complete)
- [x] Plan Phase 2 (complete)
- [x] Execute Phase 2 Plan 01 (complete)
- [x] Execute Phase 2 Plan 02 (complete)
- [x] Plan Phase 3 (complete)
- [x] Execute Phase 3 Plan 01 (complete)
- [x] Validate sqlc + SQLite VIEW + FTS5 compatibility during Phase 6 planning (validated — sqlc generates TrackMetadatum model, all tests pass)
- [x] Design queue test architecture during Phase 4 planning (complete)
- [x] Determine library scan test fixture strategy during Phase 5 planning (complete — inline construction, setupTestLibrary helper)
- [ ] Measure startup time with large library before Phase 7 lazy loading work
### Blockers
None currently.
### Warnings
### Warnings (carry forward)
- Player lock ordering (`p.mu` before `speaker.Lock()`, goroutine dispatch in beep callback) — do NOT refactor lock-sensitive paths; extract pure logic only
- modernc.org/libc version must match exactly when updating modernc.org/sqlite
- `@lit-labs/signals` is experimental (v0.2.0) — not blocking but noted
### Quick Tasks Completed
### Quick Tasks Completed (v1.0)
| # | Description | Date | Commit | Directory |
|---|-------------|------|--------|-----------|
| 001 | Multi-playlist import support | 2026-02-28 | 50c8a33 | [001-multi-playlist-import-support](./quick/001-multi-playlist-import-support/) |
| 002 | Auto-rename duplicate playlists on import | 2026-02-28 | 8ba8bbe | [002-auto-rename-duplicate-playlists-on-import](./quick/002-auto-rename-duplicate-playlists-on-import/) |
| 003 | Add multi-select to playlist view with context menu delete support | 2026-02-28 | c92ced2 | [3-add-multi-select-to-playlist-view-with-c](./quick/3-add-multi-select-to-playlist-view-with-c/) |
| 004 | Add "set as default playlist" context menu option for single playlist selection | 2026-02-28 | 9971b63 | [4-add-set-as-default-playlist-context-menu](./quick/4-add-set-as-default-playlist-context-menu/) |
| 005 | Add sort dropdown to playlist view | 2026-03-01 | 5c07485 | [5-add-sort-dropdown-to-playlist-view](./quick/5-add-sort-dropdown-to-playlist-view/) |
| 006 | Remove list icon from playlist names, add favorites icon to default | 2026-03-01 | 3c19766 | [6-remove-list-icon-from-playlist-names-and](./quick/6-remove-list-icon-from-playlist-names-and/) |
| 007 | Pin default playlist to top of playlist view | 2026-03-01 | e6378e1 | [7-pin-default-playlist-to-top-of-playlist-](./quick/7-pin-default-playlist-to-top-of-playlist-/) |
| 008 | Add duplicate tracks dialog to playlist | 2026-03-01 | 917a79a | [8-add-duplicate-tracks-dialog-to-playlist](./quick/8-add-duplicate-tracks-dialog-to-playlist/) |
| # | Description | Date | Commit |
|---|-------------|------|--------|
| 001 | Multi-playlist import support | 2026-02-28 | 50c8a33 |
| 002 | Auto-rename duplicate playlists on import | 2026-02-28 | 8ba8bbe |
| 003 | Multi-select playlist view + context menu delete | 2026-02-28 | c92ced2 |
| 004 | Set as default playlist context menu | 2026-02-28 | 9971b63 |
| 005 | Sort dropdown for playlist view | 2026-03-01 | 5c07485 |
| 006 | Remove list icon, add favorites icon | 2026-03-01 | 3c19766 |
| 007 | Pin default playlist to top | 2026-03-01 | e6378e1 |
| 008 | Duplicate tracks dialog | 2026-03-01 | 917a79a |
## Session Continuity
### Last Session
**Date:** 2026-03-05
**What happened:** Executed Phase 8 Plan 04 — visual consistency audit and design token application across 15 components. Also hotfixed repeat() virtualizer regression from Plan 02 (commit 72ef719).
**Where we stopped:** Completed 08-04-PLAN.md (3 tasks, human-verified). All 8 phases complete. All 26 requirements delivered.
**Next action:** Milestone completion
### Context for Next Session
- All 8 phases complete, all 17 plans executed
- All 26 consolidation milestone requirements delivered
- Critical hotfix: repeat() inside lit-virtualizer defeated virtualization (72ef719)
- Ready for `/gsd-complete-milestone`
**What happened:** Completed v1.0 milestone — archived roadmap, requirements, and phase directories to milestones/. Updated PROJECT.md, ROADMAP.md, RETROSPECTIVE.md. Tagged v1.0.
**Where we stopped:** Milestone v1.0 shipped.
**Next action:** `/gsd-new-milestone` to define next milestone
---
*State initialized: 2026-02-27*
Last activity: 2026-03-05 - Completed 08-04: Visual consistency audit & design token application (Phase 8 complete)
Last activity: 2026-03-05 - v1.0 Consolidation milestone shipped
*Last updated: 2026-03-05*
@@ -1,3 +1,12 @@
# Requirements Archive: v1.0 Consolidation
**Archived:** 2026-03-05
**Status:** SHIPPED
For current requirements, see `.planning/REQUIREMENTS.md`.
---
# Requirements: YellowJacket Consolidation
**Defined:** 2026-02-27
+149
View File
@@ -0,0 +1,149 @@
# Roadmap: YellowJacket Consolidation
**Created:** 2026-02-27
**Depth:** Comprehensive
**Phases:** 8
**Requirements:** 26/26 mapped
## Phases
- [x] **Phase 1: Concurrency Race Fixes** — Eliminate all SetContext data races across Queue, Library, Playlist, and Player
- [x] **Phase 2: Backend Correctness** — Fix error handling gaps, file permissions, package-level state, and scan error separation
- [x] **Phase 3: Test Infrastructure** — Create in-memory SQLite test helper and apply production SQLite PRAGMAs
- [x] **Phase 4: Queue, Config & Player Tests** — Write unit tests for queue operations, config roundtrip, and extracted player pure logic
- [x] **Phase 5: Database & Library Tests** — Write unit tests for FTS5 search queries, migrations, library scan, and entity cache
- [x] **Phase 6: SQL Consolidation & Code Quality** — Deduplicate FTS5 queries via VIEW, add event codegen, migrate to sqlc where feasible, document exceptions
- [x] **Phase 7: Backend Performance** — Optimize queue persistence, fix SetQueue Phase 2 redundancy, enable lazy library loading
- [x] **Phase 8: Frontend Performance & UX** — Optimize frontend rendering for large libraries and fix visual inconsistencies
## Phase Details
### Phase 1: Concurrency Race Fixes
**Goal:** All SetContext patterns across the codebase are race-free and the app can run under `-race` without data race reports
**Depends on:** Nothing (first phase)
**Requirements:** CORR-01, CORR-02, CORR-03, CORR-04
**Success Criteria** (what must be TRUE):
1. Running the app with `go test -race` produces zero data race reports for SetContext calls in queue, library, playlist, and player packages
2. Queue.SetContext(), Library.SetContext(), and Playlist.Service.SetContext() each acquire their mutex before writing the ctx field
3. Player.SetContext() uses a single lock acquisition instead of the double-lock pattern
4. Concurrent calls to SetContext from multiple goroutines do not corrupt shared state
**Plans:** 1 plan
Plans:
- [x] 01-01-PLAN.md — Add mutex protection to all SetContext methods and collapse Player double-lock
### Phase 2: Backend Correctness
**Goal:** All known error handling gaps are closed, configuration is secure, and the backend reports problems honestly instead of swallowing them
**Depends on:** Phase 1 (race-free code is prerequisite for reliable error paths)
**Requirements:** CORR-05, CORR-06, CORR-07, CORR-08, CORR-09
**Success Criteria** (what must be TRUE):
1. The package-level `startupErr` variable no longer exists; startup errors are stored in a YellowJacketApp struct field
2. Config files are written with 0o644 permissions (owner read/write, group/other read-only)
3. MPRIS lifecycle callback errors (Pause, Seek) appear in the application log instead of being silently discarded
4. Artist credit link creation checks the actual error — only UNIQUE constraint violations are ignored, all other errors are surfaced
5. Library.Scan() returns warnings (skipped files, partial failures) in ScanMetrics and fatal errors (database failures) in the error return, so callers can distinguish between "scan completed with issues" and "scan failed"
**Plans:** 2 plans
Plans:
- [x] 02-01-PLAN.md — Fix startupErr global state, config permissions, and MPRIS callback error logging
- [x] 02-02-PLAN.md — Add IsUniqueViolation helper, migration 3, and separate scan warnings from fatal errors
### Phase 3: Test Infrastructure
**Goal:** A reliable, production-mirroring test foundation exists so that all subsequent test phases can write database-backed tests with confidence
**Depends on:** Phase 1 (race-free code required for `-race`-clean test runs), Phase 2 (correct error handling needed for accurate test assertions)
**Requirements:** TEST-01, PERF-04
**Success Criteria** (what must be TRUE):
1. `database.NewTestDB(t)` returns a clean in-memory SQLite database that applies the same migrations and PRAGMAs as the production `NewDB()`
2. Production SQLite connection applies `synchronous=NORMAL`, `cache_size=-8000`, and `mmap_size=67108864` PRAGMAs at database open
3. Each test gets an isolated database instance — no shared state between test functions
4. Tests using `NewTestDB` pass with `-race` flag enabled
**Plans:** 1 plan
Plans:
- [x] 03-01-PLAN.md — Extract shared applyPRAGMAs, add production PRAGMAs, and create NewTestDB helper
### Phase 4: Queue, Config & Player Tests
**Goal:** The queue, config, and player packages have comprehensive unit tests that characterize current behavior and serve as a safety net for later refactoring
**Depends on:** Phase 3 (queue tests need NewTestDB for persistence tests)
**Requirements:** TEST-02, TEST-04, TEST-05
**Success Criteria** (what must be TRUE):
1. Queue package has ~15-20 tests covering SetQueue, Next, Previous, shuffle mode, repeat modes (off, one, all), and state persistence across save/load cycles
2. Config package has ~8-10 tests covering load/save roundtrip fidelity, validation rule enforcement, default value application, and graceful handling of missing or empty config files
3. Player pure logic (UserVolume↔Volume conversion, state serialization/deserialization, format detection from file extension) is extracted into standalone functions with ~5-8 unit tests
4. All tests in this phase pass with `-race` flag enabled
**Plans:** 2 plans
Plans:
- [x] 04-01-PLAN.md — Queue package unit tests (core operations, navigation, persistence roundtrip)
- [x] 04-02-PLAN.md — Config + Player tests (sub-config validators, load/save roundtrip, volume conversion, state mapping)
### Phase 5: Database & Library Tests
**Goal:** Database queries (especially FTS5 search) and library scan logic have unit tests that lock down current behavior before SQL consolidation and performance optimization
**Depends on:** Phase 3 (database tests need NewTestDB), Phase 4 (queue tests validate persistence patterns reused here)
**Requirements:** TEST-03, TEST-06
**Success Criteria** (what must be TRUE):
1. Database package has ~10-15 tests covering FTS5 search (basic terms, empty query, special characters, multi-word), search index rebuild, and schema migration application
2. Library scan logic has ~10-15 tests covering metadata extraction processing, entity cache hit/miss behavior, and orphan track cleanup
3. FTS5 search tests verify that search ranking produces consistent, expected ordering for known test data
4. All tests in this phase pass with `-race` flag enabled
**Plans:** 2 plans
Plans:
- [x] 05-01-PLAN.md — FTS5 search tests, pure helper tests, search index operations, migration verification
- [x] 05-02-PLAN.md — Entity cache tests, library pure helpers, orphan cleanup tests
### Phase 6: SQL Consolidation & Code Quality
**Goal:** Duplicated SQL patterns are eliminated, event names are provably synchronized between Go and TypeScript, and intentional SQL exceptions are documented
**Depends on:** Phase 5 (FTS5 search tests verify consolidation doesn't break ranking; database tests verify migration safety)
**Requirements:** QUAL-01, QUAL-02, QUAL-03, QUAL-04
**Success Criteria** (what must be TRUE):
1. The duplicated 5-table FTS5 JOIN pattern is consolidated into a single SQLite VIEW (`track_metadata` or similar), and all search queries use the VIEW instead of inline JOINs
2. A code generator reads Go event constants from `backend/events/events.go` and produces `frontend/src/events.ts`, wired into `go generate` and the pre-commit hook — adding an event in Go without regenerating TypeScript fails the hook
3. Queue batch lookups in `persistence.go` use `sqlc.slice()` for IN clauses where sqlc supports it, replacing `fmt.Sprintf` placeholder construction
4. Every hand-crafted SQL statement that intentionally bypasses sqlc has a `// SAFETY:` comment explaining why (batch INSERT, dynamic IN clauses, etc.)
**Plans:** 3 plans
Plans:
- [x] 06-01-PLAN.md — Create track_metadata VIEW and consolidate search queries
- [x] 06-02-PLAN.md — Event codegen tool (Go→TypeScript) and pre-commit hook wiring
- [x] 06-03-PLAN.md — Migrate lookupChunk to sqlc.slice() and add SAFETY comments to all hand-crafted SQL
### Phase 7: Backend Performance
**Goal:** Queue mutations and library loading are fast — single-track queue changes are O(1) instead of O(n), and the library doesn't block startup with a full data fetch
**Depends on:** Phase 4 (queue tests verify persistence optimization doesn't lose data), Phase 5 (library tests verify lazy loading doesn't break data access)
**Requirements:** PERF-01, PERF-02, PERF-03
**Success Criteria** (what must be TRUE):
1. Adding or removing a single track from the queue uses incremental INSERT/DELETE via existing sqlc queries, not a full table rewrite
2. SetQueue Phase 2 (`resolveRemainingTracks`) skips file paths that were already resolved in Phase 1, eliminating redundant database lookups
3. Library store constructor no longer calls `eagerFetch()` — data loads lazily on first access via the existing `getTracks()`/`getAlbums()`/etc. getters, and the app starts without blocking on a full library load
**Plans:** 2 plans
Plans:
- [x] 07-01-PLAN.md — Incremental queue persistence + SetQueue Phase 2 dedup
- [x] 07-02-PLAN.md — Library store deferred eager loading
### Phase 8: Frontend Performance & UX
**Goal:** The app feels smooth and visually consistent — large libraries render without jank, and the UI follows a coherent visual language
**Depends on:** Phase 7 (backend lazy loading changes the data availability pattern the frontend consumes)
**Requirements:** PERF-05, UX-01, UX-02
**Success Criteria** (what must be TRUE):
1. Track and album lists use Lit `repeat()` directive with stable keys (filePath for tracks, albumId for albums) for efficient DOM reuse during scrolling and filtering
2. Store notifications during rapid updates (e.g., library scan) are debounced via `queueMicrotask()` to prevent layout thrashing
3. Visual inconsistencies (spacing, colors, typography, icon sizing) are audited and follow a consistent pattern across all components
4. Scrolling, view switching, and search filtering in a 10k+ track library are smooth with no visible jank or dropped frames
**Plans:** 4 plans
Plans:
- [x] 08-01-PLAN.md — Store debouncing (queueMicrotask), search debounce, design token definitions
- [x] 08-02-PLAN.md — Virtualizer repeat() directive migration (all 5 components)
- [x] 08-03-PLAN.md — Track-list/queue-panel render optimization (classMap, search highlight short-circuit)
- [x] 08-04-PLAN.md — Visual consistency audit & token application across all components
## Progress
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Concurrency Race Fixes | 1/1 | Complete | 2026-02-28 |
| 2. Backend Correctness | 2/2 | Complete | 2026-03-03 |
| 3. Test Infrastructure | 1/1 | Complete | 2026-03-04 |
| 4. Queue, Config & Player Tests | 2/2 | Complete | 2026-03-04 |
| 5. Database & Library Tests | 2/2 | Complete | 2026-03-04 |
| 6. SQL Consolidation & Code Quality | 3/3 | Complete | 2026-03-04 |
| 7. Backend Performance | 2/2 | Complete | 2026-03-05 |
| 8. Frontend Performance & UX | 4/4 | Complete | 2026-03-05 |
---
*Roadmap created: 2026-02-27*
*Last updated: 2026-03-05*