Skip to content

refactor(editor): move the open-string pitch model into src/lanes.js (R2, step 8a) - #154

Merged
byrongamatos merged 1 commit into
mainfrom
refactor/es-module-split-pitch
Jul 9, 2026
Merged

refactor(editor): move the open-string pitch model into src/lanes.js (R2, step 8a)#154
byrongamatos merged 1 commit into
mainfrom
refactor/es-module-split-pitch

Conversation

@byrongamatos

@byrongamatos byrongamatos commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Step 8a of the editor's ES-module split (R2). A small move that unblocks a big one — and it retires the most-sliced @pure: block left in the suite.

What moved

Into src/lanes.js: _GUITAR_OPEN_MIDI / _BASS_OPEN_MIDI (module-private), _openMidiForArr, and the @pure:fret-pitch helper _soundingPitchPure.

They're the string→pitch half of the same model. lanes.js already knows bass-vs-guitar and string counts, and _openMidiForArr's extended-range rules — a perfect fourth below the current lowest string, except a 6-string bass appends a high C — are the very rules laneLabels() encodes as B↓ and C↑. Keeping them in two files was the split.

main.js's entire diff is the deletions plus two more names on its lanes.js import (checked by reconstructing it). Graph unchanged, still acyclic.

Five source-slicers, one block

@pure:fret-pitch had more consumers than any block left in the suite. All five now drive the real function:

  • fret_key_highlight — was slicing fret-pitch and brace-extracting _absolutePitch. Now imports _soundingPitchPure and is down to the single brace-extract.
  • suggest_position, roll_position_cycle, suggest_position_move, view_switcher — hybrids. They still slice what remains in main.js (suggest-position, position-cycle, suggest-marks, noteToMidi, _rollMidiForNote, updatePianoRange), but inject the real _soundingPitchPure into their sandboxes rather than concatenating its source.

That's four more files off the CJS slicer path. suggest_position needed one extra touch: importing the name collided with its own destructure of the sandbox result.

_openMidiForArr had no test at all

Now it does, in tests/lanes.test.mjs:

  • standard guitar [40,45,50,55,59,64] and bass [28,33,38,43]
  • extended low strings a perfect fourth below the lowest — 7-string low B (35), 8-string low F♯ (30), 5-string bass low B (23)
  • the 6-string bass special case: appends high C (48) on top, keeping the low B underneath, rather than extending downward again
  • bass E1 is exactly an octave below guitar E2 — the two tables agreeing
  • capo added exactly once, through _soundingPitchPure

Verification

  • node --test 86/86, pytest 248/248.
  • No unused import; the two open-MIDI constants are module-private, since nothing outside lanes.js reads them. No dangling @pure:fret-pitch reference anywhere.
  • All four headless Chromium harnesses green. Worth noting the draw harness isn't incidental cover here: its 39 (degree-label, colour) pairs run straight through the moved _soundingPitchPure on the real fretted draw path, since the in-key highlight resolves each note to sounding pitch.
  • Codex preflight: NO ISSUES.

Next

This is the prerequisite for step 8bsrc/keys.js, the piano-roll / keys-mode model (isKeysMode, viewFor, pianoLaneCount, midiToY, updatePianoRange, _rollPitchCtx, _rollMidiForNote). Those last two are exactly the callers of what moved here, and updatePianoRange is the sole writer of PIANO_LANE_H/pianoRange — so by the step-5 rule, they go as live bindings with no container. keys.js in turn is what Drawing (1,046 lines) is coupled to.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Improved pitch handling for stringed instruments, including more accurate open-string ranges for guitar and bass.
    • Added support for broader lane/string configurations, including extra-low extensions and 6-string bass behavior.
  • Bug Fixes

    • Corrected capo and fret pitch calculations so notes are computed more consistently.
    • Fixed invalid string/index cases to safely return no pitch instead of incorrect values.
  • Tests

    • Expanded automated coverage for open-string pitch behavior and updated test infrastructure for ES modules.

…(R2, step 8a)

_GUITAR_OPEN_MIDI / _BASS_OPEN_MIDI (module-private), _openMidiForArr, and the
@pure:fret-pitch helper _soundingPitchPure move out of src/main.js into
src/lanes.js. They are the string->pitch half of the same model: lanes.js already
knows bass-vs-guitar and string counts, and _openMidiForArr's extended-range rules
(a perfect fourth below the lowest string; a 6-string bass appending high C) are
the same rules laneLabels() encodes as B↓ / C↑.

main.js's whole diff is the deletions plus two more names on the lanes.js import.
Graph unchanged and still acyclic: lanes -> state.

@pure:fret-pitch was the most-sliced block left in the suite — five consumers. All
five now drive the real function:
  - fret_key_highlight: was slicing fret-pitch + brace-extracting _absolutePitch;
    now imports _soundingPitchPure and is down to the one brace-extract.
  - suggest_position, roll_position_cycle, suggest_position_move, view_switcher:
    hybrids. They still slice the blocks that remain in main.js (suggest-position,
    position-cycle, suggest-marks, noteToMidi, _rollMidiForNote, updatePianoRange)
    but inject the REAL _soundingPitchPure into their sandbox instead of
    concatenating its source text. Four more files off the CJS slicer path.

_openMidiForArr had NO test. tests/lanes.test.mjs now covers it: standard guitar
and bass tunings, extended low strings a perfect fourth below the current lowest,
the 6-string-bass special case (append high C, keep the low B underneath), the
bass-E1-is-an-octave-below-guitar-E2 relationship, and capo-added-exactly-once
through _soundingPitchPure.

Verified: node --test 86/86, pytest 248/248. main.js diff mechanically checked to
be deletions + two import names. No unused import; the two open-MIDI constants are
module-private (nothing outside lanes.js reads them). All four headless Chromium
harnesses green — the draw harness's 39 (degree-label, colour) pairs run straight
through the moved _soundingPitchPure on the real fretted draw path.

This is the prerequisite for step 8b (src/keys.js, the piano-roll / keys-mode
model), whose _rollPitchCtx and _rollMidiForNote are the two callers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 9, 2026 12:07
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e4e6ac8e-95da-4bd7-b0ff-d4adc3739e4c

📥 Commits

Reviewing files that changed from the base of the PR and between b9228e9 and dc94fc1.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • src/lanes.js
  • src/main.js
  • tests/fret_key_highlight.test.mjs
  • tests/lanes.test.mjs
  • tests/roll_position_cycle.test.mjs
  • tests/suggest_position.test.mjs
  • tests/suggest_position_move.test.mjs
  • tests/view_switcher.test.mjs

📝 Walkthrough

Walkthrough

Open-string MIDI pitch and sounding-pitch calculation logic is extracted from src/main.js into new exported functions in src/lanes.js. main.js is updated to import these helpers and its absolute-pitch formula is revised to drop capo. Multiple test files are converted to ESM and updated to import/inject the new helpers directly instead of extracting source blocks.

Changes

Open-string pitch model migration

Layer / File(s) Summary
New pitch helpers in lanes.js
src/lanes.js
Adds exported _openMidiForArr and _soundingPitchPure with open-string MIDI constants and capo/tuning/fret-based pitch computation, including bass/6-string special-casing.
main.js wiring and formula update
src/main.js
Imports the new lanes.js helpers, removes the local _openMidiForArr implementation, and changes the absolute-pitch formula to openMidi + offset + fret (dropping capo).
lanes.js unit tests for new helpers
tests/lanes.test.mjs
Imports _openMidiForArr/_soundingPitchPure and adds tests for guitar/bass open-string arrays and capo/invalid-index sounding-pitch behavior.
fret_key_highlight test update
tests/fret_key_highlight.test.mjs
Switches from source-text extraction to direct imports of _soundingPitchPure and _pcInScalePure, keeping only _absolutePitch extraction from main.js.
roll_position_cycle ESM conversion and injection
tests/roll_position_cycle.test.mjs
Converts to ESM imports/URL-based loading and injects _soundingPitchPure as a parameter to the generated function.
suggest_position ESM conversion and injection
tests/suggest_position.test.mjs
Converts to ESM and injects _soundingPitchPure from lanes.js into the dynamic Function wiring.
suggest_position_move ESM conversion and injection
tests/suggest_position_move.test.mjs
Converts to ESM, removes fret-pitch block extraction, and passes _soundingPitchPure explicitly into the generated environment.
view_switcher ESM conversion and injection
tests/view_switcher.test.mjs
Converts to ESM, rebuilds helper factories to inject _soundingPitchPure, and updates the piano-range test harness accordingly.
Changelog entry
CHANGELOG.md
Documents ES-module migration step 8a for the open-string pitch model.

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

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main refactor: moving the open-string pitch model into src/lanes.js for step 8a.
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 refactor/es-module-split-pitch

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.44.1)
src/main.js

ast-grep timed out on this file


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

@byrongamatos
byrongamatos merged commit 9e5a90d into main Jul 9, 2026
4 checks passed

Copilot AI 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.

Pull request overview

Refactors the editor’s fretted-string pitch model by relocating the open-string MIDI tables and the sounding-pitch pure helper into src/lanes.js, aligning pitch logic with the lane/string model as part of the ongoing ES-module split (R2 step 8a).

Changes:

  • Moved _openMidiForArr plus module-private open-string MIDI constants and _soundingPitchPure from src/main.js into src/lanes.js, and updated main.js imports accordingly.
  • Updated multiple tests that previously source-sliced @pure:fret-pitch to instead import and inject the real _soundingPitchPure from src/lanes.js.
  • Added direct unit coverage for _openMidiForArr and _soundingPitchPure behavior in tests/lanes.test.mjs, and documented the change in CHANGELOG.md.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/view_switcher.test.mjs Switches from slicing @pure:fret-pitch to importing/injecting _soundingPitchPure from src/lanes.js.
tests/suggest_position.test.mjs Injects real _soundingPitchPure into the @pure:suggest-position sandbox instead of concatenating the old block.
tests/suggest_position_move.test.mjs Injects _soundingPitchPure into the move environment to decouple from the removed fret-pitch block.
tests/roll_position_cycle.test.mjs Injects _soundingPitchPure for the position-cycle sandbox after the helper move.
tests/lanes.test.mjs Adds explicit tests for _openMidiForArr edge cases and capo composition via _soundingPitchPure.
tests/fret_key_highlight.test.mjs Replaces fret-pitch block extraction with a real import of _soundingPitchPure, leaving only _absolutePitch brace-extraction.
src/main.js Removes the open-string MIDI tables and @pure:fret-pitch block; imports _openMidiForArr and _soundingPitchPure from lanes.js.
src/lanes.js Adds the open-string MIDI constants, _openMidiForArr, and exports _soundingPitchPure alongside lane model code.
CHANGELOG.md Records ES-module migration step 8a and newly added test coverage for the moved helpers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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