Skip to content

Chord round-trip breaks for a seventh with add11/add13: "C7add13" prints as "C713", which reparses as C13 with a 9th and 11th #300

Description

@matt-edmondson

What's wrong

Since #293 (ad24784), Chord.Parse accepts add11 and add13 after a seventh. For example, "C7add13" parses as a dominant seventh with tensions {13} only, and a check gives tones [0,4,7,10,21].

The formatter can't write that chord back. AppendTensions (Semantics.Music/Chord.cs:598-622) writes addN only when there is no seventh. With a seventh it writes the highest natural tension as a bare stacked number ("13", "11", "9"). On reparse, ApplyExtensions expands 13 into 9 + 11 + 13.

Observed (scratch app referencing Semantics.Music)

Input ToString() Reparsed tones Equal
C7add13 C713 [0,4,7,10,14,17,21] vs original [0,4,7,10,21] False
C7add11 C711 gains a 9th False
C9add13 C713 gains an 11th False
Cmaj7add13 Cmaj713 gains a 9th and 11th False

The round-trip corpus (ChordRoundTripTests.cs:12-18) has no seventh+addN case, so the tests don't catch this.

Suggested fix

When there is a seventh:

  1. Write the highest contiguous natural stack as a number: 9 → 9, 9+11 → 11, 9+11+13 → 13.
  2. Write each remaining natural tension that isn't implied by that number as addN. For example, {13} gives 7add13 and {9,13} gives 9add13.

The alternative is to reject addN after a seventh in the parser again, but that would undo #293.

Acceptance criteria

C7add13, C7add11, C9add13 and Cmaj7add13 are added to the round-trip corpus, and each one round-trips to equal tones.

Activity

  1. matt-edmondson commented on Sep 28, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    • Category: Bug
    • Priority: Medium. It breaks the parse/format round-trip. ToString() of a valid chord reparses as a different chord with extra tones, so any caller that stores chords as text silently corrupts them. Only seventh chords with add11 or add13 are affected.
    • Area / suggested assignment: Semantics.Music/Chord.cs (AppendTensions, lines 598-622) and ChordRoundTripTests.cs
    • Duplicates: none found among open issues in the org. It is a regression surface from Read C69, Cadd11 and Cadd13 as added tones, and reject leftover text [patch] #293.
    • In progress: no matching open PR

    Notes: The suggested fix is right: emit the highest contiguous natural stack as a number, then addN for the rest. Keeping #293 is better than rejecting addN again. Add the four failing inputs to the round-trip corpus first, so the fix is test-driven.


    Generated by Claude Code

  2. matt-edmondson commented on Sep 30, 2026

    @matt-edmondson
    ContributorAuthor

    Covered by #360, which redesigns this bug cluster as a whole. Implement it through that issue rather than individually.


    Generated by Claude Code

  3. added a commit that references this issue on Oct 1, 2026
    d6116b6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions