Skip to content

Cues: copy between hot and memory; drop a round-trip we do not need - #41

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

cole-hackman merged 1 commit into
mainfrom
claude/lexicon-cue-destination

Conversation

@cole-hackman

@cole-hackman cole-hackman commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Closes the Cue Destination row — mostly by working out that half of it is a problem decks does not have.

The half that was real

The sync options All to hot cue / All to memory cue / All to hot and memory cue — the spec's "how you copy hot cues into memory cues wholesale". This is the standard Rekordbox workflow, because hot cues do not show on every player and memory cues do.

Now a MirrorCues cue recipe. Both is idempotent: a position that already exists as both kinds is left alone. This is something people run after every session, and a second run doubling the cue list would be a nasty surprise.

The half that is a divergence

The row said "no hidden-duplicate model, so the round-trip guarantee does not hold", which sounds like a gap. Reading the spec properly, it is not one.

Lexicon's internal model has hot cues only. It collapses memory cues into hot cues on import, hides the duplicates rather than deleting them, and restores them on sync back. That whole apparatus exists to undo a lossy conversion Lexicon performs on the way in.

decks performs no such conversion. There is no import step — it reads djmdCue live, and a memory cue stays a memory cue. Nothing is collapsed, so nothing is hidden, so there is nothing to restore. The guarantee holds because the problem never arises. Building a hidden-duplicate ledger to satisfy the row would have been machinery for a problem we do not have, and it would have looked like diligence.

The per-cue M toggle falls out the same way: it marks a Lexicon cue as destined to become a memory cue on the way out, and in decks a cue already is one kind or the other.

Two silent bugs it surfaced

Both in diff_cues, neither reachable before this operation existed:

  • A recipe that added a cue had it dropped. The diff did let Some(orig) = by_id.get(...) else { continue }, so any cue a recipe invented went on the floor. MirrorCues came back with an empty preview — indistinguishable from the recipe not working. Additions now stage as TrackAddCue.
  • A cue that changed kind staged nothing. Nothing diffed the memory flag, so hot→memory conversion silently did nothing either.

Every previous cue recipe only edits, reorders or deletes. This is the first to add a cue or change a kind, and it found both — which is a decent argument for testing the diff against the operation set rather than only per-operation.

Verification

cargo fmt --all -- --check          clean
cargo test --workspace              54 test binaries, 0 failures
cargo clippy --all-targets -D warn  clean
pnpm test                           797 tests, 69 files
pnpm typecheck / pnpm lint          clean
pnpm e2e                            59 passed

Matrix moves to 58 done / 22 partial / 14 missing / 2 blocked / 16 deferred; Interop & sync is now 8 done / 3 partial.


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added cue mirroring between hot cues and memory cues, with options for hot, memory, or both.
    • Added preview support for newly created cues and cue-type conversions.
    • Prevented duplicate mirrored cues when both destinations are selected.
    • Added destination controls and clearer preview counts in the cue recipes interface.
  • Documentation

    • Updated cue destination guidance, feature status, and parity documentation.

… not need

Closes the Cue Destination row, mostly by working out that half of it is a
problem `decks` does not have.

**The half that was real** is the sync options `All to hot cue` /
`All to memory cue` / `All to hot and memory cue` — the spec's "how you copy
hot cues into memory cues wholesale", and the standard Rekordbox workflow,
because hot cues do not show on every player and memory cues do. Now a
`MirrorCues` cue recipe. `Both` is **idempotent**: a position that already
exists as both kinds is left alone, because this is run after every session and
a second run must not double the cue list.

**The half that is a divergence** is the hidden-duplicate round-trip. Lexicon's
internal model has hot cues only, so it collapses memory cues into hot cues on
import and must remember what it hid to restore it on sync back. `decks` never
imports — it reads `djmdCue` live and shows both kinds as they are. Nothing is
collapsed, nothing is hidden, nothing needs restoring; the guarantee holds
because the problem never arises. Building the ledger would be machinery for a
problem we do not have, and it would have looked like diligence. The per-cue
`M` toggle falls out the same way: a cue here already *is* one kind or the
other, so "destined to become a memory cue" is a state that cannot exist.

**Two silent bugs surfaced while wiring it up**, both in `diff_cues`, neither
reachable before:

- **A recipe that added a cue had it dropped.** The diff walked the result and
  skipped anything with no `before` to compare against, so `MirrorCues`
  produced an empty preview and looked like a no-op. Additions now stage as
  `TrackAddCue`.
- **A cue that changed kind staged nothing.** Nothing diffed the `memory` flag,
  so hot→memory conversion silently did nothing either.

Every previous cue recipe only edits, reorders or deletes — this is the first
to add a cue or change a kind, and it found both. An argument for testing the
diff against the operation set rather than only per-operation.

Per docs/lexicon/01-interop.md §Cue Destination.
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 90e1aefc-d405-44a4-80c1-edaff63da7d9

📥 Commits

Reviewing files that changed from the base of the PR and between 22f6d51 and 8e9bc98.

📒 Files selected for processing (10)
  • apps/desktop/src-tauri/src/recipes.rs
  • apps/desktop/src/components/CueRecipesSection.test.tsx
  • apps/desktop/src/components/CueRecipesSection.tsx
  • apps/desktop/src/types.ts
  • crates/recipes/src/cues.rs
  • crates/recipes/src/lib.rs
  • docs/JOURNAL.md
  • docs/STATUS.md
  • docs/lexicon/01-interop.md
  • docs/lexicon/PARITY.md

📝 Walkthrough

Walkthrough

The PR adds MirrorCues for hot, memory, or both cue kinds. It extends cue previews and staging to include created cues and kind changes. The desktop UI configures mirror targets and displays additions. Documentation records cue destination behavior and parity status.

Changes

Cue mirroring

Layer / File(s) Summary
Mirror recipe engine
crates/recipes/src/cues.rs, crates/recipes/src/lib.rs
Adds MirrorCues and MirrorTarget. Hot and memory targets convert cue kinds. The both target creates missing counterparts and remains idempotent.
Cue diff preview and staging
apps/desktop/src-tauri/src/recipes.rs
Reports cue additions, detects cue-kind changes, includes additions in no-op checks, and stages TrackAddCue changes before deletions.
Desktop mirror configuration
apps/desktop/src/types.ts, apps/desktop/src/components/CueRecipesSection.tsx, apps/desktop/src/components/CueRecipesSection.test.tsx
Adds mirror target types, destination selection, request serialization, addition counts, and preview compatibility tests.
Cue destination documentation
docs/JOURNAL.md, docs/STATUS.md, docs/lexicon/01-interop.md, docs/lexicon/PARITY.md
Documents cue destination behavior, mirror handling, diff fixes, and updated parity totals.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DesktopUI
  participant CueRecipePreview
  participant MirrorCues
  participant diff_cues
  participant CueRecipeApply
  DesktopUI->>CueRecipePreview: request mirror preview
  CueRecipePreview->>MirrorCues: apply selected target
  MirrorCues-->>CueRecipePreview: converted and added cues
  CueRecipePreview->>diff_cues: compare original and recipe cues
  diff_cues-->>DesktopUI: edits, deletions, and additions
  DesktopUI->>CueRecipeApply: apply preview
  CueRecipeApply-->>DesktopUI: staged cue changes
Loading

Suggested reviewers: claude

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/lexicon-cue-destination

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 06:33
@cole-hackman
cole-hackman merged commit 6224e20 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