Skip to content

feat(editor): per-part tempo-ride scope — the drums/all toggle becomes a checklist - #110

Merged
byrongamatos merged 5 commits into
mainfrom
feat/editor-tempo-ride-parts
Jul 7, 2026
Merged

feat(editor): per-part tempo-ride scope — the drums/all toggle becomes a checklist#110
byrongamatos merged 5 commits into
mainfrom
feat/editor-tempo-ride-parts

Conversation

@ChrisBeWithYou

@ChrisBeWithYou ChrisBeWithYou commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Roadmap 2.5 (Phase 2). The Tempo Map ride toggle's binary "Drum tab / All instruments" choice becomes a per-part checklist — the prerequisite slice the design doc flags as "must land before multitrack import makes the binary switch corrupting."

What

  • The "Notes that ride the grid" control (bottom-right in Tempo Map mode) gains a third Per part… mode: one checkbox per arrangement plus the drum tab itself. A hand-verified part can now sit out a grid re-warp while everything else rides — including the drum tab, which was previously impossible to exclude.
  • Presets unchanged: drum / all behave and persist exactly as before; Ctrl+T still cycles the two presets (a custom checklist steps back to the conservative drum). The checklist is session-only — its indices are song-shaped — and resets on song load.
  • Undo correctness: TempoMapCmd now freezes the full ride set (drum flag + the exact arrangement objects) at construction, so flipping the checklist between an edit and its undo can never desync capture / remap / restore. Previously only the arrangement list was frozen; the scope string was re-read.
  • Plumbing: _applyTempoRemap / _captureScopedTimes take the resolved ride set; _restoreScopedTimes restores whatever the snapshot captured. Sections still ride in every scope; archive saves still limit re-timing to the active arrangement.

Tests

tests/tempo_ride_parts.test.js (10 cases) runs the real resolver + TempoMapCmd pipeline over a two-arrangement + drum-tab song: preset semantics, custom rides (unchecked part/drums keep times verbatim), exact undo restore, construction-time freezing, and the archive limit. The per-part and unchecked-drums assertions fail on main. loop_undo_mode.test.js harness updated for the new frozen-ride injection. Full JS suite: 42 files green; node --check clean.

Fresh region vs the open queue (#101#108) — Tempo Map scope plumbing + its toggle UI only.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JEoFeTPSnz4NpwwCG52hnu

Summary by CodeRabbit

  • New Features

    • Added a “Per part…” tempo-ride mode with a per-part checklist (“Notes that ride the grid”) for the Tempo Map ride toggle.
    • The ride toggle now supports a custom checklist preset; Ctrl+T continues cycling presets (drum tab ↔ all instruments).
  • Bug Fixes

    • Tempo-ride timing is now kept consistent through edit/undo by freezing the ride set for the command.
    • Custom checklist selections are session-only and reset on song load; invalid checklist indices are safely ignored.
  • Tests / Documentation

    • Added automated tests covering per-part behavior, undo/rollback integrity, and checklist/index rebasing.
    • Updated the changelog entry under [Unreleased].

…s a checklist

Roadmap 2.5. The Tempo Map "Notes that ride the grid" control gains a
third "Per part..." mode: a checklist with one row per arrangement plus
the drum tab itself, so a hand-verified part can sit out a grid re-warp
while everything else rides. This must land before multitrack MIDI import
makes the binary switch corrupting.

- Presets ('drum'/'all') behave exactly as before and still persist; the
  checklist is session-only (indices are song-shaped) and resets to the
  conservative drum-only preset on song load. Ctrl+T cycles the presets.
- TempoMapCmd now freezes the full ride set (drum flag + exact arrangement
  objects) at CONSTRUCTION, so flipping the checklist between an edit and
  its undo can never desync capture/remap/restore.
- _applyTempoRemap/_captureScopedTimes take the ride set; _restoreScopedTimes
  restores whatever the snapshot captured (no scope param). Sections still
  ride in every scope; archive saves still limit to the active arrangement.

Tests: tests/tempo_ride_parts.test.js (10 cases) drives the real resolver +
TempoMapCmd pipeline — the unchecked-drums and per-part assertions fail on
main. loop_undo_mode.test.js harness updated for the frozen-ride injection.

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

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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: 9de8329c-dd88-4c14-8fe9-52b8d0b4bed4

📥 Commits

Reviewing files that changed from the base of the PR and between 4394c8e and be78aed.

📒 Files selected for processing (1)
  • tests/tempo_ride_parts.test.js
📝 Walkthrough

Walkthrough

This PR adds a per-part checklist mode to the Tempo Map ride toggle in screen.js, freezes ride selection at TempoMapCmd construction, and updates undo/redo, rebasing, tests, and the changelog to use the new ride-set flow.

Changes

Tempo ride per-part checklist

Layer / File(s) Summary
State initialization and reset
screen.js
tempoRideCustom is added, Ctrl+T cycling stays on 'drum'/'all', song load clears custom checklist state, and arrangement removal rebases checklist indices.
Custom checklist UI
screen.js
The tempo scope UI gains a custom mode, vertical layout, first-use checklist seeding, and rendering of per-part checklist rows from tempoRideCustom.
Ride set resolution and remap application
screen.js
_tempoRideResolvePure and _tempoRideSet compute a frozen ride set from scope and candidate arrangements, and _applyTempoRemap retimes rides using ride.arrs plus section markers.
Snapshot/restore and TempoMapCmd freezing
screen.js
_captureScopedTimes and _restoreScopedTimes now work from the frozen ride set, and TempoMapCmd stores this.ride at construction for exec and rollback.
Test updates and changelog
tests/loop_undo_mode.test.js, tests/tempo_ride_parts.test.js, CHANGELOG.md
Test harness stubs and new regression coverage follow the ride-set flow, and the changelog records the new custom checklist behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: the tempo-ride scope becomes a per-part checklist in the editor.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/editor-tempo-ride-parts

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
screen.js (1)

13296-13323: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Checkbox toggles tear down and rebuild the whole list, dropping keyboard focus.

Each onChange calls commit(), which resets _tempoScopeToggleState = '' and re-renders, so _renderTempoScopeParts runs listEl.replaceChildren() and destroys the row the user just interacted with. Mouse users don't notice, but keyboard users lose focus after every space-toggle, breaking navigation through the checklist. The checkbox already reflects its new state, so the full teardown isn't needed to keep the UI correct here — consider refreshing only the inspector/draw and reserving row rebuilds for roster/name changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@screen.js` around lines 13296 - 13323, The tempo scope checklist is being
fully rebuilt on every checkbox toggle, which drops keyboard focus after each
change. Update the commit path in the tempo scope rendering logic (the commit
helper used by the Drum tab and arrangement rows in the tempo scope list) so
checkbox onChange only refreshes the inspector/draw state without resetting
_tempoScopeToggleState or calling the list rebuild path; keep the full row
teardown only for roster/name changes that actually affect the list structure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@screen.js`:
- Around line 13296-13323: The tempo scope checklist is being fully rebuilt on
every checkbox toggle, which drops keyboard focus after each change. Update the
commit path in the tempo scope rendering logic (the commit helper used by the
Drum tab and arrangement rows in the tempo scope list) so checkbox onChange only
refreshes the inspector/draw state without resetting _tempoScopeToggleState or
calling the list rebuild path; keep the full row teardown only for roster/name
changes that actually affect the list structure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 318531bb-f5b1-4aa9-b12e-36f7fa31dd07

📥 Commits

Reviewing files that changed from the base of the PR and between 2222c59 and 05d583b.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • screen.js
  • tests/loop_undo_mode.test.js
  • tests/tempo_ride_parts.test.js

Rebase the per-part tempo-ride checklist when an arrangement is removed:
editorRemoveArrangement splices S.arrangements (renumbering every later
part) but left tempoRideCustom.arrs holding stale indices, so a
hand-unchecked part could ride the next tempo edit — the out-of-scope
corruption the scope exists to prevent. Added pure _rebaseTempoRideForRemoval
+ regression test that fails on pre-fix code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@byrongamatos

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

CodeRabbit: each checkbox onChange forced a full row rebuild (commit()
reset the memo signature; check-state was in the signature), dropping
keyboard focus off the box being toggled. Drop check-state from the memo
signature and stop forcing a rebuild — the DOM already reflects the flip
and the model is updated to match; structural changes (mode/scope/roster)
still rebuild.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@byrongamatos

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/tempo_ride_parts.test.js (1)

272-280: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comment text is slightly misleading about the input set.

The assertion message says '0 stays, 1 (removed) dropped, 2→1, 3→2', but index 1 was never in the input set {0, 2, 3} to begin with — removeIdx=1 just happens to coincide with an index absent from the set. The math is correct, but the phrasing implies 1 was checked and got dropped.

✏️ Suggested wording tweak
-    assert.deepStrictEqual([...out.arrs].sort((a, b) => a - b), [0, 1, 2],
-        '0 stays, 1 (removed) dropped, 2→1, 3→2');
+    assert.deepStrictEqual([...out.arrs].sort((a, b) => a - b), [0, 1, 2],
+        '0 (below removeIdx) stays, 2→1, 3→2 (above removeIdx shift down)');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/tempo_ride_parts.test.js` around lines 272 - 280, The failing assertion
message in the tempo ride parts test is misleading because it implies index 1
was present in the input Set when it was not. Update the wording in the
_rebaseTempoRideForRemoval test so it describes the actual rebasing behavior of
env._rebaseTempoRideForRemoval: 0 stays, 2 shifts to 1, and 3 shifts to 2, while
noting that the removed index is absent from the input set. Keep the assertion
itself unchanged and adjust only the descriptive message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/tempo_ride_parts.test.js`:
- Around line 272-280: The failing assertion message in the tempo ride parts
test is misleading because it implies index 1 was present in the input Set when
it was not. Update the wording in the _rebaseTempoRideForRemoval test so it
describes the actual rebasing behavior of env._rebaseTempoRideForRemoval: 0
stays, 2 shifts to 1, and 3 shifts to 2, while noting that the removed index is
absent from the input set. Keep the assertion itself unchanged and adjust only
the descriptive message.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 13aa1792-911d-4692-8ebd-a734ef25e4f8

📥 Commits

Reviewing files that changed from the base of the PR and between 05d583b and b952e7f.

📒 Files selected for processing (2)
  • screen.js
  • tests/tempo_ride_parts.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • screen.js

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@byrongamatos

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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