Skip to content

Epic 7: Track Matcher done, store search links, and an honest scope for the rest - #46

Merged
cole-hackman merged 1 commit into
mainfrom
claude/lexicon-streaming
Aug 8, 2026
Merged

cole-hackman merged 1 commit into
mainfrom
claude/lexicon-streaming

Conversation

@cole-hackman

Copy link
Copy Markdown
Owner

The instruction was "integrate all the ones you can". Most of the value here is in working out what can actually means and writing the boundary down — GAPS.md §Epic 7 has the full table.

Built, because it needs no account

Track Matcher is done. .txt and .m3u8 through one reader, since an .m3u8 is a text file whose non-track lines start with #. #EXTINF titles are preferred over the path lines beneath them — a path is a location, and matching a library by path is what Relocate is for.

The separator is selectable as the manual specifies rather than guessed: hyphen, en dash, em dash, Title by Artist (the one form where the sides swap), none, or custom. Mis-splitting produces confident wrong matches, which is worse than an obvious failure. Matches become a playlist through the create_playlist_from_tracks that already existed.

Store Links and onward search, as generated search URLs across Beatport, Bandcamp, Discogs, Spotify, Tidal, SoundCloud and YouTube. Constructing the right search URL per store per track is the tedious part of both features, and a search link is honest: it claims nothing about whether the track exists or what it costs, and cannot be wrong in a way that costs the user anything. The UI says plainly this is search-only.

Two bugs my own tests caught

Neither was foresight — both were failing tests, and both now have regression tests naming the tension:

  1. #3 C - D was swallowed. I had is_noise treat every #-prefixed line as an m3u8 directive — true for .m3u8, false for a hand-written setlist where #3 is a list index. Resolved on what follows the #: letters mean directive, digits mean index.
  2. Fixing that broke 99 Problems. Allowing a bare space after digits made the leading number an index. Resolved by letting only the # license a space delimiter; without it, punctuation is required. 1979 and 2001. A Space Odyssey are covered too.

The underlying rule — numbered indices must be stripped, because 1. Daft Punk is not an artist and normalisation won't fix it — is real: it pushes genuine matches under the fuzzy threshold on exactly the request lists this feature exists for.

Not built, and the two reasons are different

Needs a registered application and a per-user token per service — Beatport catalog / cart / purchase-replacement, Charts, Send To, SoundCloud playback, Track Discovery, and Store Links price comparison. That's an account action with terms attached, so it's yours to take, not something I should do on your behalf. Once an app exists the client work is small; the keychain plumbing already exists from ADR-0016.

Needs a verified place to store a streaming reference — streaming tracks, Transfer Streaming To Local. This one is worth flagging separately because it needs no API at all: the spec's own claim is that the reference survives even for sources that can't be played. It's unbuilt because decks is Rekordbox-first and read-only on master.db, the synthetic schema models no streaming columns, and no real master.db is available here to see what Rekordbox 7 uses. Putting the reference in cache.sqlite3 would make it decks-only — defeating the one guarantee the feature exists to give. GAPS.md carries the one sqlite3 ".schema djmdContent" that settles it.

A process fix

rust-toolchain.toml pins stable = 1.97.1 on CI, while this container's image shipped 1.94.1. So every "clippy is clean" I reported earlier this session was checked against an older lint set than the gate — which is why #45 failed on both platforms for a lint I couldn't see locally. I've installed current stable and now run the whole definition of done against it. It has caught two lints since (while_let_loop, and a derivable Default in this PR).

Verification

cargo +stable fmt --all -- --check
cargo +stable test --workspace
cargo +stable clippy --workspace --all-targets -- -D warnings   # clean, incl. decks-desktop
pnpm test        # 837 passed
pnpm typecheck
pnpm lint
pnpm e2e         # 59 passed

28 new Rust tests (tracklist + store_links) and 7 new frontend tests.

Parity: 62 done / 21 partial / 11 missing / 2 blocked / 16 deferred.


Generated by Claude Code

Closes the Track Matcher row and the honest half of Store Links, per
`docs/lexicon/08-streaming.md`. Scoping for the rest of Epic 7 is recorded in
`GAPS.md` rather than guessed at.

Track Matcher:
- `.txt` and `.m3u8` through one reader, since an `.m3u8` is a text file whose
  non-track lines start with `#`. `#EXTINF` titles are preferred over the path
  lines beneath them — a path is a location, and matching by path is what
  Relocate is for.
- Selectable separator as the manual specifies rather than a guess: hyphen, en
  dash, em dash, `Title by Artist` (the one form where the sides swap), none, or
  custom. Mis-splitting produces confident wrong matches, not obvious failures.
- Numbered setlist indices stripped, because `1. Daft Punk` is not an artist and
  normalisation will not fix it. A digit alone is never an index — `99 Problems`
  and `1979` are titles — so it needs punctuation after it, or a leading `#`.
- `#` is ambiguous between the formats: directive in `.m3u8`, index in a
  hand-written list. Letters after it mean directive, digits mean index. Both of
  these came out of failing tests and both now have regression tests.
- Playlist creation from matches, wired to the existing command.

Store Links / onward search, as generated search URLs across Beatport,
Bandcamp, Discogs, Spotify, Tidal, SoundCloud and YouTube. This is the tedious
part of both features and it is honest: a search link claims nothing about
whether a track exists or what it costs. Price comparison and playlist push are
NOT built — both need a registered application and a per-user token per service
— and the UI says so rather than implying a comparison that is not happening.

Not built, with the reasons kept distinct in GAPS.md: Beatport catalog/cart,
Charts, Send To, SoundCloud playback and Track Discovery need credentials only
the account owner can obtain; streaming tracks and Transfer Streaming To Local
need a verified place to store a streaming reference, which `master.db` does not
appear to offer and which no real database is available here to check.

Parity: 62 done / 21 partial / 11 missing / 2 blocked / 16 deferred.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Gn43w2xFL3JRBRkMv3vRo
@coderabbitai

coderabbitai Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@cole-hackman, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d6d36988-6e02-4f6b-9495-df3fdad4b0d0

📥 Commits

Reviewing files that changed from the base of the PR and between 30e4f11 and 89fe26c.

📒 Files selected for processing (13)
  • apps/desktop/src-tauri/src/lib.rs
  • apps/desktop/src/components/TrackMatcherView.test.tsx
  • apps/desktop/src/components/TrackMatcherView.tsx
  • apps/desktop/src/ipc.ts
  • apps/desktop/src/types.ts
  • crates/track-matcher/src/lib.rs
  • crates/track-matcher/src/store_links.rs
  • crates/track-matcher/src/tracklist.rs
  • docs/JOURNAL.md
  • docs/STATUS.md
  • docs/lexicon/08-streaming.md
  • docs/lexicon/GAPS.md
  • docs/lexicon/PARITY.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cole-hackman
cole-hackman marked this pull request as ready for review August 8, 2026 23:39
@cole-hackman
cole-hackman merged commit 8ee0110 into main Aug 8, 2026
7 checks passed
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.

2 participants