Skip to content

fix: use full chord type for roman-numeral sevenths in Add harmony dialog#552

Open
FelipeDefensor wants to merge 1 commit into
TimeLineAnnotator:devfrom
FelipeDefensor:fix/harmony-roman-seventh-quality
Open

fix: use full chord type for roman-numeral sevenths in Add harmony dialog#552
FelipeDefensor wants to merge 1 commit into
TimeLineAnnotator:devfrom
FelipeDefensor:fix/harmony-roman-seventh-quality

Conversation

@FelipeDefensor

Copy link
Copy Markdown
Collaborator

Warning

AI-generated — needs verifying. This investigation, fix, and tests were produced by an AI agent (Claude Code) and have not been independently verified by a human. Please review carefully before merging — see the checklist at the bottom.

Summary

Typing a roman-numeral seventh chord (e.g. V7) in the Add harmony dialog selected the triad quality (Major) instead of the seventh quality (Dominant seventh). Reported against v0.6.3.

Root cause

The roman-numeral parse path in _get_params_from_music21_object (tilia/timelines/harmony/components/harmony.py) read music21's RomanNumeral.impliedQuality, which only reflects the triad quality (major/minor/diminished/augmented) and ignores the seventh/extension. So V7 resolved to major, and the dialog's quality combobox selected "Major".

This is a regression from commit 7a76fdc ("chore: more accurate naming"), a chord_* → letter_* rename. It correctly renamed the set side (roman_numeral.chord_typeroman_numeral.letter_type), but on the read side changed obj.chord_type to obj.impliedQuality instead of obj.letter_type. That left letter_type set-but-never-read, and the reader silently picked up music21's triad-only attribute.

letter_type is computed from the chord's actual pitches (Chord(roman.pitches).commonNameCHORD_COMMON_NAME_TO_TYPE), so it carries the correct full chord type.

Fix

One line:

-        quality = obj.impliedQuality
+        quality = obj.letter_type

Tests

Adds TestRomanNumeralParsing to tests/ui/dialogs/test_select_harmony_params.py. It drives the dialog the way a user types (char-by-char into the line edit via the existing parse_text helper) and asserts on the resulting combobox selection — i.e. it exercises the exact reported symptom, not just the parse function.

Cases: V (triad, unchanged), V7, V65, V43, V42, ii7, viio7, and the applied chord V7/V. Confirmed these fail on the buggy code (assert 'major' == 'dominant-seventh') and pass with the fix. Full harmony suite (171 tests) green; ruff clean.

Reviewer checklist (AI output — please verify)

  • Music-theory correctness of the expected qualities/inversions for the parametrized roman numerals.
  • letter_type is always set whenever the parse path returns kind == "roman" (it is assigned inside the try block in _get_music21_object_from_text).
  • No other reader relies on the previous impliedQuality behavior for roman numerals.

Typing a roman-numeral seventh (e.g. "V7") in the Add harmony dialog
selected the triad quality ("Major") instead of the seventh quality
("Dominant seventh").

The roman-numeral parse path read music21's RomanNumeral.impliedQuality,
which only reflects the triad. Commit 7a76fdc ("more accurate naming")
renamed the attribute holding the full chord type from chord_type to
letter_type, but changed the reader to impliedQuality instead of
letter_type, leaving letter_type set-but-unread. Read letter_type so the
full chord type (derived from the chord's pitches) is used.

Adds regression tests covering V/V7/V65/V43/V42, ii7, viio7, and V7/V.
@FelipeDefensor FelipeDefensor added this to the 0.6.4 milestone Jun 25, 2026
@FelipeDefensor FelipeDefensor requested a review from azfoo June 25, 2026 13:17
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.

1 participant