Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/product/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ An audiophile player lives or dies on **library + playback maturity, not on its
|--------|-------|
| S8 | Library spine: scan + persistent DB |
| S9 | Browse & search UI — album grid; Artist/Album/Genre; incremental search; cover art; click-to-queue |
| S10 *(runs as S10.1–S10.5)* | Queue + playlists + macOS control — queue/history, M3U import-export, media keys + Now-Playing/Control Center. Split into five individual sprints — see [sprint-plan.md](../sprints/sprint-plan.md) + [s10 plan](../sprints/s10-queue-playlists-macos-plan.md). |
| S10 *(runs as S10.1–S10.5)* | Queue + playlists + macOS control — queue/history, media keys + Now-Playing/Control Center. Split into five individual sprints — see [sprint-plan.md](../sprints/sprint-plan.md) + [s10 plan](../sprints/s10-queue-playlists-macos-plan.md). *(M3U/M3U8 import-export deferred — see below.)* |
| S11 | CUE sheets + format hardening — CUE→virtual tracks, FLAC fast-seek, WavPack/APE, lossy gapless trim |
| S12 | Tonal parity — parametric EQ + AutoEq/oratory1990 import + A/B LUFS-matched bypass |
| S13 | Headphone + device parity — device-correction EQ auto-load + profile JSON import/export |
Expand Down Expand Up @@ -64,6 +64,7 @@ Built on the mature base, enabler-first, lowest-artifact-risk first. This is the
## Deferred / out-of-window

- **Removed from scope (2026-07-12, founder decision):** **natural-language / conversational tuning** and **hearing personalization** (hearing-test → profile → compensation) were cut from the vision entirely — not deferred, removed. May be re-added later. Prior specs are in git history.
- **Deprioritized (2026-07-14, founder decision):** **drag-from-Library-into-queue** and **playlist file import/export (M3U/M3U8)** — judged not useful enough to plan now. Not removed from the vision; revisit opportunistically post-R1. Add-to-queue is already covered by the Play Next / Add to Queue verbs; playlist portability (M3U) can return if a real need appears. R1 no longer depends on either.
- **DSD playback (DoP + native)** — deferred past R2, gated on acquiring a DSD DAC (keeps every feature by-ear verifiable).
- **"Won't, this horizon"** — kept on the [backlog](backlog.md) as future vision, out of this plan's window:
- **Stem separation / object engine (Phase 1.5)** — high compute/artifact risk; revisit only after the mix-based thesis is validated and loved.
Expand Down
8 changes: 4 additions & 4 deletions docs/sprints/s10-queue-playlists-macos-plan.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# S10 — Queue + playlists + macOS control (five sprints S10.1–S10.5)

**Document ID:** S10-PLAN-001
**Status:** Planning — S10 runs as **five individual done-done sprints** (S10.1–S10.5). Each is a full sprint that runs the **usual development process** (vetted design → multi-SME review panel → architect + the-fool gate → build-enforced gate + commit). Not yet started; start with S10.1.
**Status:** S10.1 ✅ + S10.2 ✅ shipped & merged; **S10.3 next**. S10 runs as **five individual done-done sprints** (S10.1–S10.5), each via the **usual development process** (vetted design → multi-SME review panel → architect + the-fool gate → build-enforced gate + commit). *(Authoritative project status: [sprint-plan.md §Status](sprint-plan.md). Deprioritized 2026-07-14: drag-from-Library-into-queue + M3U/M3U8 import-export.)*
**Relates to:** [sprint-plan.md](sprint-plan.md) — the S10.x sprint series, the last work before **Release R1**.
**Depends on:** S8 (library spine, GRDB store) ✅, S9 (browse/search) ✅.

Expand All @@ -13,9 +13,9 @@

| Sprint | SP | Scope (line item) | Key stories | Depends on |
|---|---|---|---|---|
| **S10.1** | 8 | **Playlist/queue persistence spine** — `playlists` + `playlist_entries` tables (GRDB, delete-rebuild migration; keyed on `tracks.id` with a `position` + own entry id so a track can repeat); DAO for create/rename/delete + ordered add/remove/reorder + loose-file add; the built-in non-deletable **"current"** playlist; `untitled-N` lowest-unused naming; **closes Gate 1** (`unreferencedTrackIDs` gains `AND id NOT IN (SELECT track_id FROM playlist_entries)`). Gated by `VerifyLibraryStore`. | US-PLIST-01, -05, -06 (store), -07; known-issues **SEQ-1 Gate 1** | S8.1 store |
| **S10.2** | 6 | **Queue UX** — the "current" playlist surfaced as the play queue: reorder (drag), play-next, add-to-queue, history; wires to `PlaybackQueueKit`. Lands the **deferred drag-to-queue** from S9 (rides the queue-drag infra). | US-PLIST-06 (UI), US-PLAY reorder/history | S10.1 |
| **S10.3** | 9 | **Playlists UX + M3U/M3U8 import-export** — playlist browse/sidebar (create/edit/rename/delete, scales to hundreds); drag songs → playlist as a **reference-add, never a file move** (separate handler from folder-move); add a single non-library file; **M3U/M3U8** import + export. | US-PLIST-02, -03, -04; + the US-PLIST-08 cross-seam test | S10.1 (+ S8.4 ✅ for -08) |
| **S10.1** | 8 | **Playlist/queue persistence spine** — `playlists` + `playlist_entries` tables (GRDB, delete-rebuild migration; keyed on `tracks.id` with a `position` + own entry id so a track can repeat); DAO for create/rename/delete + ordered add/remove/reorder + loose-file add; the built-in non-deletable **"current"** playlist; `untitled-N` lowest-unused naming; **closes Gate 1** (`unreferencedTrackIDs` gains `AND id NOT IN (SELECT track_id FROM playlist_entries)`). Gated by `VerifyLibraryStore`. | US-PLIST-01, -05, -06 (store), -07; known-issues **SEQ-1 Gate 1** | S8.1 store |
| **S10.2** | 6 | **Queue UX** — persistent play queue (the "current" playlist; survives quit/relaunch, restore-paused); Up Next|History + session history; Clear Queue; reorder (grip-drag + context-menu + keyboard); wires to `PlaybackQueueKit`. *(drag-from-Library-into-queue deprioritized 2026-07-14 — Play Next / Add to Queue verbs cover add.)* | US-PLIST-06 (UI), US-PLAY reorder/history | S10.1 |
| **S10.3** | 6 | **Playlists UX** — playlist browse/sidebar (create/edit/rename/delete, scales to hundreds); add songs → playlist as a **reference-add, never a file move** (separate handler from folder-move); add a single non-library file. *(M3U/M3U8 import-export deprioritized 2026-07-14.)* | US-PLIST-02, -03, -04; + the US-PLIST-08 cross-seam test | S10.1 (+ S8.4 ✅ for -08) |
| **S10.4** | 5 | **macOS system control** — media keys + Now-Playing / Control Center (`MPNowPlayingInfoCenter` + `MPRemoteCommandCenter`); app-wide keyboard shortcuts. Independent of the persistence spine. | (new — trace to sprint-plan S10.4) | S9 |
| **S10.5** | 3 | **Browse polish** — folder-browse mode; the **deferred A–Z jump rail** from S9. *(Polish — not an R1 gate.)* | (S9 carry-overs) | S9 |

Expand Down
10 changes: 5 additions & 5 deletions docs/sprints/sprint-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ The rationale is sound: **an audiophile player lives or dies on library + playba
| **S6** ✅ | Technical architecture review & hardening *(gate — §8.6)* | 8† | Multi-discipline review of the shipped codebase; RT-safety/lifecycle + concurrency consolidation + the Tier-3 DSP spine (`Realizer`, `RtSwappableResource`, steerable equal-power intensity with intensity-0 the bit-exact anchor, `GaplessController`). Confirmed the spine is Phase-2-ready. **Rationale:** [s6-architecture-review-findings.md](s6-architecture-review-findings.md), [s6-tier3-spine-design.md](s6-tier3-spine-design.md). | shipped codebase |
| **S7** ✅ | DSP-gate hardening | 8 | Regression oracles for every shipped DSP stage: libebur128 LUFS/TP, limiter −1 dBTP + ISP accuracy, 31-band EQ FR sweep + bit-transparent bypass, SRC alias/stopband, gapless-seam, RT-allocation soak (US-QA-01..06). **Open follow-up:** THD+N. | S6 |
| **S8** ✅ | Library spine: scan + persistent DB | 9 | Folder scan/watch, metadata + embedded-art, incremental rescan, persistent **GRDB**-backed store, art cache; S8.4 id-preserving move-match. Headless-gated by `VerifyLibraryStore`. **Forward:** Gate 1 (playlist filter, known-issues SEQ-1) stays open until **S10.1** ships the playlist table. | S6 |
| **S9** ✅ | Browse & search UI | 8 | Album grid + detail; Songs (filter-preserves-sort + customizable columns); Artists (tile grid) + Genres; FTS5 incremental search; queue/advance core (`PlaybackQueueKit`); cover art; a11y. *(Years tab cut.)* **Deferred → S10:** true drag-to-queue (→ S10.2) + the A–Z jump rail (→ S10.5). | S8 |
| **S10.1** | Playlist/queue persistence spine | 8 | `playlists` + `playlist_entries` tables (GRDB, keyed on `tracks.id` + position); create/rename/delete + ordered-membership DAO; built-in non-deletable **"current"** queue playlist; `untitled-N` naming. **Closes Gate 1** (SEQ-1). `VerifyLibraryStore`-gated. | S8 |
| **S10.2** | Queue UX | 6 | The "current" playlist surfaced as the play queue: reorder / play-next / add-to-queue / history; lands the deferred **drag-to-queue**. | S10.1 |
| **S10.3** | Playlists UX + **M3U/M3U8** import-export | 9 | Playlist browse/edit (create/rename/delete, scales to hundreds); drag → playlist = **reference-add** (never a file move); add a single non-library file; M3U/M3U8 import+export; the US-PLIST-08 move-survival seam test. | S10.1 |
| **S9** ✅ | Browse & search UI | 8 | Album grid + detail; Songs (filter-preserves-sort + customizable columns); Artists (tile grid) + Genres; FTS5 incremental search; queue/advance core (`PlaybackQueueKit`); cover art; a11y. *(Years tab cut.)* **Deferred → S10:** the A–Z jump rail (→ S10.5). *(drag-to-queue was routed to S10.2, then deprioritized 2026-07-14.)* | S8 |
| **S10.1** | Playlist/queue persistence spine | 8 | `playlists` + `playlist_entries` tables (GRDB, keyed on `tracks.id` + position); create/rename/delete + ordered-membership DAO; built-in non-deletable **"current"** queue playlist; `untitled-N` naming. **Closes Gate 1** (SEQ-1). `VerifyLibraryStore`-gated. | S8 |
| **S10.2** | Queue UX | 6 | Persistent play queue (the "current" playlist; survives quit/relaunch, restore-paused); Up Next|History + session history; Clear Queue; reorder via grip-drag + context-menu + keyboard. *(drag-from-Library-into-queue deprioritized 2026-07-14.)* | S10.1 |
| **S10.3** | Playlists UX | 6 | Playlist browse/edit (create/rename/delete, scales to hundreds); add songs → playlist = **reference-add** (never a file move); add a single non-library file; the US-PLIST-08 move-survival seam test. *(M3U/M3U8 import-export deprioritized 2026-07-14.)* | S10.1 |
| **S10.4** | macOS system control | 5 | **Media keys + Now-Playing/Control Center** (`MPNowPlayingInfoCenter` / `MPRemoteCommandCenter`); app-wide keyboard shortcuts. *(independent of the store)* | S9 |
| **S10.5** | Browse polish | 3 | Folder-browse mode; the deferred **A–Z jump rail** from S9. *(polish — not an R1 gate)* | S9 |

Expand All @@ -68,7 +68,7 @@ The rationale is sound: **an audiophile player lives or dies on library + playba

### Status

**S6–S9 ✅ shipped · S10.1 next → Release R1.** S9 browse is complete (Songs · Albums · Artists · Genres); S10 now runs as five individual sprints S10.1–S10.5 (start with S10.1, the playlist/queue spine). **This line is the single prose status surface for the project** — README/roadmap defer here; everything finer-grained lives in the source + git log (which are authoritative if they disagree with this).
**S6–S9 ✅ + S10.1–S10.2 ✅ shipped · S10.3 next → Release R1.** S9 browse complete; S10.1 (playlist/queue persistence spine) + S10.2 (queue UX — persistent queue, Up Next|History, reorder) shipped & merged. S10 runs as five individual sprints S10.1–S10.5; **R1 gates on S10.1–S10.4**. Deprioritized 2026-07-14 (founder): drag-from-Library-into-queue + M3U/M3U8 import-export (see [roadmap Deferred](../product/roadmap.md)). **This line is the single prose status surface for the project** — README/roadmap defer here; everything finer-grained lives in the source + git log (which are authoritative if they disagree with this).

---

Expand Down
Loading