You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Progression.Parse silently drops beat slashes after a Chord@n/d cell: "4/4 C@1/2 / / | G" parses as C for 2 beats with G on beat 3 #328
In the chart format, each whole-token / extends the current chord by one beat (design spec docs/superpowers/specs/2026-07-02-music-type-safe-factories-design.md §Progression). Progression.TryReadChordEvents (Semantics.Music/Progression.Parse.cs:117-125) increments currentBeats for every /. But when the chord cell carried an explicit @n/d duration, FlushChord (Progression.Parse.cs:169) uses explicitDuration ?? Duration.Create(currentBeats, beatUnit), so every slash after it is counted and then thrown away. The input is accepted and its timing is changed without any error.
The input puts G on the downbeat of bar 2. The parsed progression puts it on beat 3 of bar 1, and TotalDuration is 3/4 rather than the 5/4 the text reads as. The same path is reached through Section.Parse and Arrangement.Parse, which parse their chart lines with Progression.TryParse.
Related to this: the spec says Parse "treats | as validation", but the loop skips | tokens unconditionally (Progression.Parse.cs:111-114). A bar line in the wrong place is therefore never caught, and this timing shift goes unnoticed as well.
Suggested fix / acceptance criteria
Reject a / token that follows a Chord@n/d cell, so TryParse returns false and Parse throws FormatException. The alternative is to define and document additive semantics (explicit duration plus N beats). Rejecting is the smaller change and keeps ToString()→Parse total, because ToString never emits a slash after an @ cell.
Optionally, as the spec describes, validate that each | lands on a bar boundary for whole-beat content.
Tests: "4/4 C@1/2 / | G" is rejected (or parses to the documented duration), and the existing ProgressionRoundTripTests still pass.
Priority: Medium. The parser accepts the input and silently changes its timing: chords shift by beats, and TotalDuration is wrong. The error also flows into Section.Parse and Arrangement.Parse. The input form (a slash after an @n/d cell) is uncommon, which keeps this below High.
Area / suggested assignment:Progression.TryReadChordEvents / FlushChord (Semantics.Music/Progression.Parse.cs:111-125,169). The | bar-line validation the spec promises is a natural follow-up in the same loop.
Activity
matt-edmondson commentedon Sep 29, 2026
Triage
TotalDurationis wrong. The error also flows intoSection.ParseandArrangement.Parse. The input form (a slash after an@n/dcell) is uncommon, which keeps this below High.Progression.TryReadChordEvents/FlushChord(Semantics.Music/Progression.Parse.cs:111-125,169). The|bar-line validation the spec promises is a natural follow-up in the same loop.Generated by Claude Code