What's wrong
AppendQualityAndSeventh writes 7/maj7 first (Chord.cs#L590-L624). AppendTensions then appends the natural extension number after it (Chord.cs#L645-L688). The resulting "canonical symbol" is not something any chart uses:
| Parsed from |
ToString() |
C9 / Cm9 / Cmaj9 / Caug9 |
C79 / Cm79 / Cmaj79 / Caug79 |
C11 / C13 / Cmaj13 |
C711 / C713 / Cmaj713 |
C7sus4 / C9sus4 |
Csus47 / Csus479 |
C6/9 / Cm6/9 |
C6add9 / Cm6add9 |
Progression.Parse("4/4 Dm9 | G13 | Cmaj9 | G7sus4").ToString() gives "4/4 Dm79 G713 Cmaj79 Gsus47". Section.ToString() and Arrangement.ToString() inherit the same output.
Parse(ToString()) still round-trips, and the round-trip corpus (ChordRoundTripTests.cs) compares only the parsed structure. Because no test pins the text, this was never caught. The type-safe factories spec calls the output a "canonical symbol (e.g. Cmaj7, C/G)" (spec L95-L153).`` A chart format meant for people should print what a musician writes.
Suggested fix
- When a natural extension number is emitted for a seventh chord, let it replace the
7: dominant 7+9 becomes 9, and maj7+9 becomes maj9.
- Put
sus after the number: 7sus4, 9sus4.
- Write a 6 with an added 9 as
6/9, which Chord.Parse already accepts.
Coordinate with #300, which reworks the same AppendTensions branch for 7add13. That issue is about losing the round-trip; this one is the ordinary C9 → C79 case.
Acceptance criteria
ToString() returns C9, Cm9, Cmaj9, C11, C13, Cmaj13, C7sus4, C9sus4, C6/9 and Cm6/9 for the inputs in the table.
- The round-trip corpus gains a text assertion,
Parse(s).ToString() == s for canonical inputs, alongside the structural one.
What's wrong
AppendQualityAndSeventhwrites7/maj7first (Chord.cs#L590-L624).AppendTensionsthen appends the natural extension number after it (Chord.cs#L645-L688). The resulting "canonical symbol" is not something any chart uses:ToString()C9/Cm9/Cmaj9/Caug9C79/Cm79/Cmaj79/Caug79C11/C13/Cmaj13C711/C713/Cmaj713C7sus4/C9sus4Csus47/Csus479C6/9/Cm6/9C6add9/Cm6add9Progression.Parse("4/4 Dm9 | G13 | Cmaj9 | G7sus4").ToString()gives"4/4 Dm79 G713 Cmaj79 Gsus47".Section.ToString()andArrangement.ToString()inherit the same output.Parse(ToString())still round-trips, and the round-trip corpus (ChordRoundTripTests.cs) compares only the parsed structure. Because no test pins the text, this was never caught. The type-safe factories spec calls the output a "canonical symbol (e.g.Cmaj7,C/G)" (spec L95-L153).`` A chart format meant for people should print what a musician writes.Suggested fix
7: dominant7+9becomes9, andmaj7+9becomesmaj9.susafter the number:7sus4,9sus4.6/9, whichChord.Parsealready accepts.Coordinate with #300, which reworks the same
AppendTensionsbranch for7add13. That issue is about losing the round-trip; this one is the ordinaryC9→C79case.Acceptance criteria
ToString()returnsC9,Cm9,Cmaj9,C11,C13,Cmaj13,C7sus4,C9sus4,C6/9andCm6/9for the inputs in the table.Parse(s).ToString() == sfor canonical inputs, alongside the structural one.