Skip to content

feat(editor): Suggest fret-hand fingers (auto-fingering) - #237

Merged
byrongamatos merged 2 commits into
mainfrom
feat/editor-auto-fingering
Jul 13, 2026
Merged

feat(editor): Suggest fret-hand fingers (auto-fingering)#237
byrongamatos merged 2 commits into
mainfrom
feat/editor-auto-fingering

Conversation

@ChrisBeWithYou

@ChrisBeWithYou ChrisBeWithYou commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

The gap audit's flagship finding: every piece of fret_finger plumbing already existed — the teaching mark, its Guitar-Pro/XML round-trip, the fretboard strip that displays fingers — but nothing ever proposed a finger. It was manual-only. This fills that gap.

What it does

Note ▸ Suggest fret-hand fingers assigns a fingering to every fretted note from its fret relative to the hand anchor covering its time:

  • index (1) at the anchor fret, one finger per fret across the four-fret span, clamped 1–4;
  • open strings → none;
  • notes outside a reachable hand position → left untouched (a different anchor owns them).

It fingers the selection when you have one, otherwise the whole track — in one undoable step.

Implementation

  • Pures in src/position.js: _suggestFingerForFretPure (fret + anchor → finger, reusing the existing _activeAnchorAtPure window model) and _suggestFingersPure.
  • New SetTeachingMarksCmd (src/commands.js): per-note teaching-mark assignment as one undo step — the plural of the existing single-value SetTeachingMarkCmd.
  • Verb editorSuggestFingers (src/anchor-resolve.js, beside editorResolveAnchorWindow); a registry entry + Note-menu item, dispatched through the shared _editorRunEofCommand.

Tests / gates

tests/auto_fingering.test.mjs (6: the finger pure incl. open/refuse/clamp, the map-and-omit, and the SetTeachingMarksCmd per-note exec → undo → redo). 129 JS suites green (menu_model included — the registry/menu wiring is consistent), lint 0 errors (3 pre-existing warnings). routes.py untouched.

Verified live

On AC/DC — Back In Black: Note ▸ Suggest fret-hand fingers"Suggested fret-hand fingers for 1328 notes in the arrangement", one undoable command, no page errors. The assigned fingers display on the fretboard strip (Fret toggle).

Natural follow-ups from the audit: a finger-conflict lint rule (pairs with this), and chord-shape-aware joint resolve.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Note → Suggest fret-hand fingers to automatically propose fingers for selected notes or the entire track.
    • Open strings are marked as requiring no finger; unreachable notes remain unchanged.
    • Suggestions can be undone in a single step.
    • Added menu and shortcut-panel access for the new command.
  • Bug Fixes

    • Added safeguards for unsupported modes and notes without valid hand positions.
  • Tests

    • Added coverage for finger suggestions, unreachable notes, open strings, and undo behavior.

The gap audit's flagship finding: every piece of fret_finger plumbing already
existed — the teaching mark, its Guitar-Pro/XML round-trip, the fretboard strip
that DISPLAYS fingers — but nothing ever PROPOSED a finger. It was manual-only.

Note ▸ Suggest fret-hand fingers now assigns a fingering to every fretted note
from its fret relative to the hand anchor covering its time: index (1) at the
anchor fret, one finger per fret across the four-fret span, clamped 1..4; open
strings → none; notes outside a reachable hand position → left untouched (a
different anchor owns them). Fingers the selection when there is one, else the
whole track, in ONE undoable step.

- Pures in src/position.js: `_suggestFingerForFretPure` (fret+anchor → finger,
  reusing the existing `_activeAnchorAtPure` window model) and `_suggestFingersPure`.
- New `SetTeachingMarksCmd` (src/commands.js): per-note teaching-mark assignment
  in one undo step — the plural of the existing single-value SetTeachingMarkCmd.
- Verb `editorSuggestFingers` (src/anchor-resolve.js, beside editorResolveAnchorWindow);
  registry entry + Note-menu item; dispatched through `_editorRunEofCommand`.

`tests/auto_fingering.test.mjs` (6: the finger pure incl. open/refuse/clamp, the
map-and-omit, and the SetTeachingMarksCmd per-note exec→undo→redo). 129 JS suites
green (menu_model incl.), lint 0-err (3 pre-existing warnings). routes.py untouched.

Verified live on AC/DC — Back In Black: Note ▸ Suggest fret-hand fingers →
"Suggested fret-hand fingers for 1328 notes in the arrangement", one undoable
command, no errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q
@coderabbitai

coderabbitai Bot commented Jul 13, 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: 11 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: ea15a8ee-a142-42d9-89ca-20465679203c

📥 Commits

Reviewing files that changed from the base of the PR and between a38ad98 and d57ba79.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • src/input.js
📝 Walkthrough

Walkthrough

Changes

Fret-hand finger suggestions

Layer / File(s) Summary
Finger suggestion rules
src/position.js, tests/auto_fingering.test.mjs
Pure helpers map reachable frets to fingers 1–4, open strings to -1, and omit invalid or unreachable notes; tests cover these cases.
Undoable teaching-mark updates
src/commands.js, tests/auto_fingering.test.mjs
SetTeachingMarksCmd applies per-note fret_finger values and restores previous values during undo; round-trip behavior is tested.
Editor suggestion flow
src/anchor-resolve.js
editorSuggestFingers() targets the selection or whole arrangement, resolves anchors, applies suggestions in one undoable step, redraws, and reports status.
Command and menu exposure
src/input.js, src/menu-bar.js, src/shortcuts.js, CHANGELOG.md
The suggestFingers command is registered, added to the Note menu, dispatched by the editor, and documented in the changelog.

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

Sequence Diagram(s)

sequenceDiagram
  participant Editor
  participant AnchorResolver
  participant PositionRules
  participant TeachingMarkCommand
  Editor->>AnchorResolver: invoke editorSuggestFingers
  AnchorResolver->>AnchorResolver: resolve active anchors
  AnchorResolver->>PositionRules: calculate finger assignments
  AnchorResolver->>TeachingMarkCommand: apply fret_finger values
  TeachingMarkCommand-->>Editor: update notes and history
  Editor-->>Editor: redraw and show status
Loading

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 summarizes the main editor feature added: automatic fret-hand finger suggestions.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% 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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/editor-auto-fingering

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)
src/anchor-resolve.js (1)

259-287: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Consider integration-level test coverage for editorSuggestFingers.

Current tests cover _suggestFingerForFretPure, _suggestFingersPure, and SetTeachingMarksCmd in isolation, but not this orchestration function itself (selection branching, anchor resolution wiring, status text). A seeded-state test similar to the existing SetTeachingMarksCmd round-trip test (using tests/_history_env.mjs) would catch regressions in how these pieces are wired together.

🤖 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/anchor-resolve.js` around lines 259 - 287, ​​Add an integration-level
test for editorSuggestFingers using the seeded-state setup from
tests/_history_env.mjs. Exercise both selected-note and whole-arrangement paths,
including anchor resolution wiring, SetTeachingMarksCmd history updates, and the
resulting status text, while preserving the existing isolated tests for
_suggestFingerForFretPure, _suggestFingersPure, and SetTeachingMarksCmd.
🤖 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 `@src/anchor-resolve.js`:
- Around line 259-287: ​​Add an integration-level test for editorSuggestFingers
using the seeded-state setup from tests/_history_env.mjs. Exercise both
selected-note and whole-arrangement paths, including anchor resolution wiring,
SetTeachingMarksCmd history updates, and the resulting status text, while
preserving the existing isolated tests for _suggestFingerForFretPure,
_suggestFingersPure, and SetTeachingMarksCmd.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f8334929-72bd-423f-a04d-6fe6f2c79cdb

📥 Commits

Reviewing files that changed from the base of the PR and between 33521a4 and a38ad98.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • src/anchor-resolve.js
  • src/commands.js
  • src/input.js
  • src/menu-bar.js
  • src/position.js
  • src/shortcuts.js
  • tests/auto_fingering.test.mjs

# Conflicts:
#	CHANGELOG.md
#	src/input.js
@byrongamatos
byrongamatos merged commit 2fee858 into main Jul 13, 2026
9 of 13 checks passed
@byrongamatos
byrongamatos deleted the feat/editor-auto-fingering branch July 13, 2026 13:25
byrongamatos added a commit that referenced this pull request Jul 13, 2026
* feat(editor): lint finger conflicts in a grip

Auto-fingering (#237) and the coherent-grip chord resolve (#245) assign
fret-hand fingers, but a grip can still ask ONE finger to hold two different
frets at the same instant — a shape no hand can play. Add a finger-conflict
rule to the advisory playability lint.

_lintFingerConflictPure (playability-lint.js): within a simultaneous cluster
(the shared LINT_CLUSTER_EPSILON), group fretted notes by their fret_finger
(1-4 only; open strings and the -1 unset sentinel carry no fretting finger),
and flag any finger used on more than one distinct fret. A BARRE — the same
finger across strings at the SAME fret — is one fret, so it never flags.

Wired into _playabilityLintPure and the RULE_LABELS map, so it rides the
existing surface: a yellow underline on the flagged notes, the count chip,
and a popover row that seeks + selects. Advisory only — never blocks, never
auto-fixes (the charter answers the physical question), like every rule.

Tests: tests/finger_conflict_lint.test.mjs (10) — conflict vs barre vs
different-fingers vs not-simultaneous, open/unset/out-of-range fingers
ignored, barre-plus-stray, two conflicts in one cluster, aggregation into
the full pass, junk-input degradation. Live-verified in-app: the conflict is
named in the real _lintResults memo and both notes land in the flagged set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q

* fix(editor): count the thumb as a fretting digit in the finger-conflict lint

The rule guarded on `fret_finger` 1-4, so it never saw the THUMB. Per spec
§6.2.2 (and routes.py's `_fret_finger_attr`) the fret-hand digit range is
0-4, where 0 is the thumb — the fretboard strip's `T`, cycled by right-click
and clamped to -1..4 by the inspector. A thumb-over grip frets the low E, so
a thumb assigned to two different frets at one instant is exactly as
impossible as finger 1 in two places, and the lint went blind to it.

Widen the guard to 0-4 and render the thumb as `T` in the popover detail
(the strip's FINGER_LABELS encoding, inlined rather than importing that UI
module into the @pure block). A thumb barre across E+A at one fret stays
legal, as does a normal thumb-over grip — same physics as the other digits.

Also drop the redundant `list.length >= 2` (implied by `frets.length >= 2`).

---------

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