Browser: drag tracks onto a favourite; record why ANLZ writes stay unbuilt - #43
Merged
Merged
Conversation
The last Library & browser gap, and the one the Favorite Playlists row had been waiting on — its Notes read "drag-and-drop target not done — no drag source in the table yet". One change, two rows. Three rules, all in `lib/track-drag.ts` rather than inside the handlers, because jsdom does not run drag events and a rule that lives in a handler is a rule nothing tests: - **Dragging a row inside the selection carries the whole selection**; dragging one outside it carries only that row. Always-just-the-row would make a multi-select highlight a lie, and extending the selection to include the dragged row would change state the user did not ask to change. - **The drop reads its payload, not the live selection.** The selection can change between the drag starting and the drop landing, and the payload is the record of what was actually picked up. - **The favourite only accepts a drag carrying our own MIME type.** Without the check the chip lights up for a dragged file and then does nothing, which is worse than never lighting up. Also records a finding rather than code: **ANLZ writing is investigated and deliberately unbuilt**, in `GAPS.md` §Environment blockers. Producing the bytes is mechanical — the format is self-describing and `for_each_section` already walks it. What cannot be answered without a real Rekordbox install is whether Rekordbox accepts a file we wrote: whether anything beyond the length fields is validated, whether `.DAT` and `.EXT` must stay consistent, and whether `master.db` carries state that must change alongside it. Writing it anyway would be untestable production code by the same argument that keeps `crates/enrichment` unwritten, and it would sit unwired, which the definition of done forbids. The four rows that depend on it — Beatgrid editing, the last two cue-point recipes, Don't Touch My Grids, Beatshift correction — now share one recorded reason, and GAPS names the fifteen-minute check on a machine with Rekordbox that resolves all four together. Per docs/lexicon/02-library.md §Browser.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
cole-hackman
marked this pull request as ready for review
August 8, 2026 07:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two things: the last Library & browser gap, and an investigation that closes off four others by saying no.
Track rows are a drag source
The Favorite Playlists row had been sitting on "drag-and-drop target not done — no drag source in the table yet". One change, two rows. Library & browser is now 17 done / 0 partial.
Three rules, all in
lib/track-drag.tsrather than inside the handlers — jsdom does not run drag events, so a rule that lives in a handler is a rule nothing tests:ANLZ writing: investigated, deliberately unbuilt
Four rows depend on it — Beatgrid editing, the last two cue-point recipes, Don't Touch My Grids, Beatshift correction — so it was worth answering once rather than discovering it four times.
Producing the bytes is the easy half and is not the blocker. The format is self-describing (
PMAImagic, big-endian header length, a chain of sections each carrying tag / header length / total length),for_each_sectionalready walks it correctly, and rewritingPQTZin place is mechanical with an obvious round-trip test.What cannot be answered here is whether Rekordbox accepts a file we wrote:
.DATand its.EXTcompanion must stay mutually consistent — we only read one.master.dbcarries state that must change alongside it (AnalysisUpdated,AnalysisDataPath), and what Rekordbox does on next launch if it does not.The failure mode is not data loss, but it is not nothing: a rejected or misparsed ANLZ leaves a track with no waveform and no grid in Rekordbox until it is re-analysed there.
I could have written the writer anyway, round-trip-tested it against our own parser, and called the rows closed. That would be wrong twice over — it is untestable production code by exactly the argument that keeps
crates/enrichmentunwritten, and it would sit unwired, which this project's definition of done forbids ("reachable from the UI, never tests-only").So the deliverable is the finding. The four rows now share one recorded reason instead of four vague ones, and
GAPS.mdnames the specific check that resolves all four at once: extend the disposable-DB smoke harness to write onePQTZsection into a copy of a real ANLZ, then open that copy in Rekordbox. Fifteen minutes on a machine with Rekordbox installed.Verification
Matrix moves to 60 done / 20 partial / 14 missing / 2 blocked / 16 deferred — and the domain rows now sum to the total, which the two concurrent branches had briefly desynced.
Generated by Claude Code