Skip to content

feat(editor): make the ruler authoritative for tempo mapping - #211

Merged
byrongamatos merged 1 commit into
mainfrom
feat/editor-tempo-ruler-truth
Jul 11, 2026
Merged

byrongamatos merged 1 commit into
mainfrom
feat/editor-tempo-ruler-truth

Conversation

@ChrisBeWithYou

@ChrisBeWithYou ChrisBeWithYou commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What changed

  • documents the authoritative-musical-ruler model across source, musical, reference/SMPTE, and playback time
  • replaces the ambiguous Insert sync point workflow with Mark barline terminology
  • lets a mark beyond the mapped tail close the open measure and create the next downbeat
  • preserves authored trailing/rubato beats and synthesizes inherited beats only for a terminal-only tail
  • shades audio after the final confirmed downbeat as Unmapped on the consolidated ruler
  • round-trips the selected barline through undo/redo

Why

The prior insert action could only promote an existing interior beat. At the end of a truncated map it failed with nothing to insert, even though users reasonably expected to mark the next measure. This aligns the editor with a beat-mapping workflow: fit the musical ruler to fixed source audio and keep topology edits nondestructive in seconds.

Validation

  • npm test: 104/104 test files pass
  • npm run lint: 0 errors; 3 pre-existing warnings
  • focused coverage: 4/4, 7/8, terminal-only tails, authored rubato tails, minimum-gap refusal, mapped-range display, fixed source seconds, selection/grid undo and redo
  • staged diff public-term guardrail: clean

Summary by CodeRabbit

  • New Features

    • Added authoritative musical ruler documentation covering tempo mapping, barlines, timing domains, assisted mapping, and playback behavior.
    • Tempo Map terminology now consistently uses “barline” instead of “sync point.”
    • Added barline marking behavior that preserves authored timing and supports undo/redo selection restoration.
    • Ruler now shades and labels audio beyond the confirmed mapped range as Unmapped.
  • Documentation

    • Updated the README and changelog with details about the musical ruler and tempo-mapping design.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR documents an authoritative musical ruler, changes tempo-map insertion to append barlines, preserves tempo selection through undo, marks unmapped ruler tails, and updates tempo-map terminology from “sync point” to “barline” across controls, guidance, and tests.

Changes

Tempo mapping and barline editing

Layer / File(s) Summary
Tempo mapping design contract
docs/TEMPO-MAPPING-DESIGN.md, README.md, CHANGELOG.md
Defines musical, source, reference, and playback timing domains, barline authoring rules, assisted mapping, playback transforms, ruler semantics, and related test expectations.
Barline continuation and undo state
src/tempo.js, tests/tempo_barline_append.test.mjs
Adds pure barline-appending logic, preserves authored tails where possible, updates tempo-map insertion, and restores tempo selection during command execution and rollback.
Mapped extent and unmapped ruler display
src/ruler.js, tests/ruler.test.mjs
Computes the final confirmed downbeat and shades and labels the ruler region after the mapped range as “Unmapped”.
Barline terminology and interaction updates
src/input.js, src/menu-bar.js, src/shortcuts.js, src/tempo.js, tests/menu_model.test.mjs, tests/tempo_map_guidance.test.mjs, tests/tempo_sync_inspector.test.mjs
Updates tempo-map prompts, menu items, shortcut labels, inspector actions, context menus, guidance text, status messages, and matching assertions to use barline terminology.

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

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the main change: the editor's ruler becoming authoritative for tempo mapping.
Docstring Coverage ✅ Passed Docstring coverage is 81.25% which is sufficient. The required threshold is 80.00%.
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.
✨ 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 feat/editor-tempo-ruler-truth

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

@ChrisBeWithYou
ChrisBeWithYou force-pushed the feat/editor-tempo-ruler-truth branch from b236206 to a961c89 Compare July 11, 2026 19:29

@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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/tempo.js (2)

286-296: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Complete the user-facing “barline” rename.

The inspector still exposes “sync point” in deleteTitle/hint and the final-measure delete message; the context-menu lock action and lock confirmation also retain that wording. This leaves users with mixed terminology in the same workflow.

Also applies to: 318-323, 701-705, 1428-1440

🤖 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 `@src/tempo.js` around lines 286 - 296, Complete the terminology update in the
inspector state around deleteTitle and hint, replacing user-facing “sync point”
wording with “barline” consistently. Also update the final-measure delete
message and the context-menu lock action and lock confirmation near the
referenced code so this workflow no longer exposes “sync point” to users,
without changing behavior.

829-835: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Pass selection through the in-range topology command.

When an interior beat is promoted, S.tempoSel changes after a TempoGridCmd with no selection snapshots. Undo and redo therefore do not restore the pre-edit and post-edit selections, unlike the append path, and subsequent BPM/delete actions can target the wrong barline.

Proposed fix
-    S.history.exec(new TempoGridCmd(oldBeats, newBeats, 'insert'));
-    S.tempoSel = bestS;
+    S.history.exec(new TempoGridCmd(
+        oldBeats, newBeats, 'insert', S.tempoSel, bestS));
🤖 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 `@src/tempo.js` around lines 829 - 835, Update the in-range beat-promotion flow
around _tempoRenumberMeasures and TempoGridCmd to capture and pass the pre-edit
and post-edit tempo selections in the command, matching the append path. Ensure
undo restores the previous S.tempoSel and redo restores bestS, while retaining
the existing beat updates and selection assignment.
🤖 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.

Inline comments:
In `@README.md`:
- Around line 25-28: Update the Time description’s “sync points” wording in
README.md to use the public UI terminology “barlines” or “Mark barline,” while
preserving the surrounding timing-domain explanation.

In `@tests/tempo_sync_inspector.test.mjs`:
- Line 26: Update the strings returned by _tempoSyncInspectorStatePure in
src/tempo.js from “sync point” to “barline” for the no-selection delete
title/hint and the first/final non-deletable title. Extend tests in
tempo_sync_inspector.test.mjs to cover each updated state and assert the renamed
copy.

---

Outside diff comments:
In `@src/tempo.js`:
- Around line 286-296: Complete the terminology update in the inspector state
around deleteTitle and hint, replacing user-facing “sync point” wording with
“barline” consistently. Also update the final-measure delete message and the
context-menu lock action and lock confirmation near the referenced code so this
workflow no longer exposes “sync point” to users, without changing behavior.
- Around line 829-835: Update the in-range beat-promotion flow around
_tempoRenumberMeasures and TempoGridCmd to capture and pass the pre-edit and
post-edit tempo selections in the command, matching the append path. Ensure undo
restores the previous S.tempoSel and redo restores bestS, while retaining the
existing beat updates and selection assignment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f01160b8-21dc-4ba0-8804-9832b5d52d58

📥 Commits

Reviewing files that changed from the base of the PR and between 999942f and a961c89.

📒 Files selected for processing (13)
  • CHANGELOG.md
  • README.md
  • docs/TEMPO-MAPPING-DESIGN.md
  • src/input.js
  • src/menu-bar.js
  • src/ruler.js
  • src/shortcuts.js
  • src/tempo.js
  • tests/menu_model.test.mjs
  • tests/ruler.test.mjs
  • tests/tempo_barline_append.test.mjs
  • tests/tempo_map_guidance.test.mjs
  • tests/tempo_sync_inspector.test.mjs

Comment thread README.md
Comment on lines +25 to +28
The authoritative musical ruler fits bars and beats to fixed source audio;
authored musical content aligns through that ruler. See
[`docs/TEMPO-MAPPING-DESIGN.md`](docs/TEMPO-MAPPING-DESIGN.md) for the four
timing domains, marker model, assisted mapping, and audition-speed rules.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use barline terminology in the public README.

The existing Time description still refers to “sync points” on Line 22. Update it to “barlines” or “Mark barline” so the public documentation matches the new UI contract.

🤖 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 `@README.md` around lines 25 - 28, Update the Time description’s “sync points”
wording in README.md to use the public UI terminology “barlines” or “Mark
barline,” while preserving the surrounding timing-domain explanation.

t('asks for a selected sync point before enabling edits', () => {
const state = _tempoSyncInspectorStatePure(measures, -1);
assert.strictEqual(state.label, 'No sync point selected');
assert.strictEqual(state.label, 'No barline selected');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the remaining inspector copy to “barline.”

src/tempo.js still returns “sync point” in _tempoSyncInspectorStatePure for the no-selection delete title/hint and the first/final non-deletable title. Those states will contradict this renamed label; update the source strings and add coverage for them here.

🤖 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_sync_inspector.test.mjs` at line 26, Update the strings returned
by _tempoSyncInspectorStatePure in src/tempo.js from “sync point” to “barline”
for the no-selection delete title/hint and the first/final non-deletable title.
Extend tests in tempo_sync_inspector.test.mjs to cover each updated state and
assert the renamed copy.

@byrongamatos
byrongamatos merged commit e02a003 into main Jul 11, 2026
4 checks passed
ChrisBeWithYou pushed a commit that referenced this pull request Jul 12, 2026
Charrette arch 5a / rhythm G5 / trans P6-prep (design slice 2a). Sparse labeled
chips on the ruler show where the tempo and meter change through the song.

ZERO storage — markers are a PURE function of S.beats (the executable truth,
never a second source): _tempoMarkersPure derives tempo-change markers where a
measure's BPM leaves the current run beyond 0.01 (the same constant
_tempoHasMultipleMeasureBpmsPure uses) and meter markers where the numerator /
den changes, with a bar-1 baseline of each and no spurious marker on a trailing
partial bar. Memoized on editGen (+ the S.beats ref). Painted in the ruler band
via timeToX only (the D-T1 invariant); tempo chips (cyan) and meter chips
(violet) stack when they share a barline. Marker fields are never smuggled into
S.beats entries.

Filed feedpak-spec#51 for the AUTHORED markers the grid can't express (tempo
ramps, meter groupings, fermata holds, lock/provenance) — slice 2b,
range-provenance and community maps gate on it; not built here.

tests/tempo_markers.test.mjs (7): baseline-only on a constant map, tempo-change
detection, within-tolerance run behaviour, mid-song meter change + trailing-
partial suppression, denominator change, degenerate inputs, and purity (no
mutation of the input beats). Verified live: the ruler shows per-bar BPM chips
tracking AC/DC's imported tempo drift + a 4/4 meter chip, no errors. npm test
115 green, lint 0 errors.

Independent of the in-review queue (deps only merged ruler #209/#211). Keep-both
seam with #220 on tempo.js.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q
byrongamatos added a commit that referenced this pull request Jul 12, 2026
…10) (#227)

Charrette arch 5a / rhythm G5 / trans P6-prep (design slice 2a). Sparse labeled
chips on the ruler show where the tempo and meter change through the song.

ZERO storage — markers are a PURE function of S.beats (the executable truth,
never a second source): _tempoMarkersPure derives tempo-change markers where a
measure's BPM leaves the current run beyond 0.01 (the same constant
_tempoHasMultipleMeasureBpmsPure uses) and meter markers where the numerator /
den changes, with a bar-1 baseline of each and no spurious marker on a trailing
partial bar. Memoized on editGen (+ the S.beats ref). Painted in the ruler band
via timeToX only (the D-T1 invariant); tempo chips (cyan) and meter chips
(violet) stack when they share a barline. Marker fields are never smuggled into
S.beats entries.

Filed feedpak-spec#51 for the AUTHORED markers the grid can't express (tempo
ramps, meter groupings, fermata holds, lock/provenance) — slice 2b,
range-provenance and community maps gate on it; not built here.

tests/tempo_markers.test.mjs (7): baseline-only on a constant map, tempo-change
detection, within-tolerance run behaviour, mid-song meter change + trailing-
partial suppression, denominator change, degenerate inputs, and purity (no
mutation of the input beats). Verified live: the ruler shows per-bar BPM chips
tracking AC/DC's imported tempo drift + a 4/4 meter chip, no errors. npm test
115 green, lint 0 errors.

Independent of the in-review queue (deps only merged ruler #209/#211). Keep-both
seam with #220 on tempo.js.


Claude-Session: https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q

Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: byrongamatos <xasiklas@gmail.com>
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