Skip to content

fix(api): clef number round-trip#267

Merged
webern merged 2 commits into
mainfrom
clef-number
Jun 30, 2026
Merged

fix(api): clef number round-trip#267
webern merged 2 commits into
mainfrom
clef-number

Conversation

@webern

@webern webern commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

Round-trip added a spurious number="1" to clefs in single-staff parts. The issue frames this as a
dropped attribute, but for the affected corpus files it is the reverse: the source omits the clef
number (1 is implied on a single staff) and mx emitted it anyway on mid-measure clef changes. The
measure-start path already suppressed it; the two mid-measure write paths passed the staff index
straight through.

The fix centralizes the single- vs multi-staff rule in MeasureWriter::clefStaffIndex() so all
three clef write sites agree, and adds ClefData::writeStaffNumber - a ternary where unspecified
applies the rule automatically (omit the implied 1 on a single-staff part, include otherwise) and
yes/no force it. Reading sets yes/no only when the source diverges from the rule, so it
stays unspecified in the common case and most users can ignore it.

Also includes a tooling fix: make dump-api-roundtrip now clears its output directory first. It
only writes pairs for failing files, so a file that flipped to passing left a stale pair that the
classifier re-counted as a current failure.

Testing

  • New MultiStaffClefKeepsNumber test; PropertiesButNoNotes updated (it pinned the old bug)
  • 23 clef files flip FAIL -> PASS, added to the round-trip baseline (96 -> 119 pinned)
  • Regression gate green (119 of 119 pinned)
  • Full impl/api suite passes (4330 assertions in 319 test cases)

References

@github-actions

Copy link
Copy Markdown

gen-quality gen/

gen-quality: 84.5 / 100   (floor 84.5, +0.0)

  structure     86.5  x0.50   [fn 90.5 / file 82.6]
  cyclomatic    88.4  x0.25
  cognitive     76.6  x0.25

  409 functions across 31 files, 7702 lines (largest file 1044)
  max cc 56  max cognitive 44  max fn loc 152

Worst offenders (top 5 per axis; full lists in score.json):
  cyclomatic gen/xsd/analyze.py:311     report                             56
  cyclomatic gen/plates/build.py:956    _validate_config_against_ir        35
  cyclomatic gen/press/context.py:145   plate_context                      34
  cyclomatic gen/__main__.py:46         _ir                                23
  cyclomatic gen/tests/test_ir.py:102   _check_references                  20
  cognitive  gen/xsd/analyze.py:311     report                             44
  cognitive  gen/ir/resolve.py:119      flat_elements                      40
  cognitive  gen/tests/test_ir.py:102   _check_references                  38
  cognitive  gen/press/context.py:145   plate_context                      37
  cognitive  gen/xsd/analyze.py:207     _sccs                              37
  size       gen/xsd/analyze.py:311     report                             152
  size       gen/press/context.py:145   plate_context                      96
  size       gen/plates/build.py:533    _value_plate                       89
  size       gen/plates/build.py:956    _validate_config_against_ir        89
  size       gen/ir/resolve.py:119      flat_elements                      78

Commit 197d31d782b98955ccee9e862c84c7a758a7f6f2.

Base automatically changed from stem-default-y to main June 30, 2026 05:20
@github-actions

Copy link
Copy Markdown

Coverage report

Core-dev coverage src/private/mx/core/

Metric Coverage Covered / Total
Lines 77.8% 28487 / 36624
Functions 74.3% 6349 / 8550
Branches 50.6% 22632 / 44725

API coverage src/private/mx/{api,impl,utility}/

Metric Coverage Covered / Total
Lines 78.5% 6025 / 7679
Functions 63.7% 2045 / 3209
Branches 47.6% 5101 / 10717

Core HTML report | API HTML report

Commit 40ac16f9ce99d45c0edab5d4c2bbcd6e528c079e.

@github-actions

Copy link
Copy Markdown

gen-quality gen/

gen-quality: 84.5 / 100   (floor 84.5, +0.0)

  structure     86.5  x0.50   [fn 90.5 / file 82.6]
  cyclomatic    88.4  x0.25
  cognitive     76.6  x0.25

  409 functions across 31 files, 7702 lines (largest file 1044)
  max cc 56  max cognitive 44  max fn loc 152

Worst offenders (top 5 per axis; full lists in score.json):
  cyclomatic gen/xsd/analyze.py:311     report                             56
  cyclomatic gen/plates/build.py:956    _validate_config_against_ir        35
  cyclomatic gen/press/context.py:145   plate_context                      34
  cyclomatic gen/__main__.py:46         _ir                                23
  cyclomatic gen/tests/test_ir.py:102   _check_references                  20
  cognitive  gen/xsd/analyze.py:311     report                             44
  cognitive  gen/ir/resolve.py:119      flat_elements                      40
  cognitive  gen/tests/test_ir.py:102   _check_references                  38
  cognitive  gen/press/context.py:145   plate_context                      37
  cognitive  gen/xsd/analyze.py:207     _sccs                              37
  size       gen/xsd/analyze.py:311     report                             152
  size       gen/press/context.py:145   plate_context                      96
  size       gen/plates/build.py:533    _value_plate                       89
  size       gen/plates/build.py:956    _validate_config_against_ir        89
  size       gen/ir/resolve.py:119      flat_elements                      78

Commit 40ac16f9ce99d45c0edab5d4c2bbcd6e528c079e.

dump-api-roundtrip only writes pairs for failing files, so a file
that flips to passing leaves a stale pair behind. The classifier
then reads it as a current failure. rm -rf the dump dir, both in
the build volume and the host copy, before each dump.
@github-actions

Copy link
Copy Markdown

Coverage report

Core-dev coverage src/private/mx/core/

Metric Coverage Covered / Total
Lines 77.8% 28487 / 36624
Functions 74.3% 6349 / 8550
Branches 50.6% 22632 / 44725

API coverage src/private/mx/{api,impl,utility}/

Metric Coverage Covered / Total
Lines 78.4% 6025 / 7683
Functions 63.7% 2045 / 3209
Branches 47.6% 5109 / 10729

Core HTML report | API HTML report

Commit 70839ceb60f3c67e93622d59b8be056690b62b28.

@github-actions

Copy link
Copy Markdown

gen-quality gen/

gen-quality: 84.5 / 100   (floor 84.5, +0.0)

  structure     86.5  x0.50   [fn 90.5 / file 82.6]
  cyclomatic    88.4  x0.25
  cognitive     76.6  x0.25

  409 functions across 31 files, 7702 lines (largest file 1044)
  max cc 56  max cognitive 44  max fn loc 152

Worst offenders (top 5 per axis; full lists in score.json):
  cyclomatic gen/xsd/analyze.py:311     report                             56
  cyclomatic gen/plates/build.py:956    _validate_config_against_ir        35
  cyclomatic gen/press/context.py:145   plate_context                      34
  cyclomatic gen/__main__.py:46         _ir                                23
  cyclomatic gen/tests/test_ir.py:102   _check_references                  20
  cognitive  gen/xsd/analyze.py:311     report                             44
  cognitive  gen/ir/resolve.py:119      flat_elements                      40
  cognitive  gen/tests/test_ir.py:102   _check_references                  38
  cognitive  gen/press/context.py:145   plate_context                      37
  cognitive  gen/xsd/analyze.py:207     _sccs                              37
  size       gen/xsd/analyze.py:311     report                             152
  size       gen/press/context.py:145   plate_context                      96
  size       gen/plates/build.py:533    _value_plate                       89
  size       gen/plates/build.py:956    _validate_config_against_ir        89
  size       gen/ir/resolve.py:119      flat_elements                      78

Commit 70839ceb60f3c67e93622d59b8be056690b62b28.

@webern webern changed the title Fix clef @number round-trip (#230a) fix(api): clef number round-trip Jun 30, 2026
Comment thread src/include/mx/api/ClefData.h Outdated
Comment thread src/include/mx/api/ClefData.h Outdated
Comment thread src/private/mxtest/impl/MeasureWriterTest.cpp Outdated
Comment thread src/private/mxtest/api/roundtrip-baseline.txt Outdated
@webern webern added bug software defect breaking fixes or implementation that require breaking changes area/mx::api ai Issues opened by, or through, a coding agent. labels Jun 30, 2026
Stop emitting a spurious number="1" on single-staff parts and
preserve the source's choice to include or omit the attribute.

The writer derived the staff number from position but, for
mid-measure clef changes in single-staff parts, passed the staff
index straight through instead of suppressing it the way the
measure-start path already did. Centralize the single/multi-staff
rule in clefStaffIndex(), and add ClefData::writeStaffNumber - a
ternary defaulting to an automatic rule (omit the implied 1 on a
single-staff part, include otherwise) that round-trip uses to
preserve a source that diverged from it.

Grows the api round-trip baseline by 23 clef files.
@github-actions

Copy link
Copy Markdown

Coverage report

Core-dev coverage src/private/mx/core/

Metric Coverage Covered / Total
Lines 77.8% 28487 / 36624
Functions 74.3% 6349 / 8550
Branches 50.6% 22632 / 44725

API coverage src/private/mx/{api,impl,utility}/

Metric Coverage Covered / Total
Lines 78.4% 6024 / 7682
Functions 63.7% 2045 / 3209
Branches 47.6% 5109 / 10729

Core HTML report | API HTML report

Commit 52794e60a1ac0c1a2fb50c4e43f4f2f3dcf7d2e9.

@github-actions

Copy link
Copy Markdown

gen-quality gen/

gen-quality: 84.5 / 100   (floor 84.5, +0.0)

  structure     86.5  x0.50   [fn 90.5 / file 82.6]
  cyclomatic    88.4  x0.25
  cognitive     76.6  x0.25

  409 functions across 31 files, 7702 lines (largest file 1044)
  max cc 56  max cognitive 44  max fn loc 152

Worst offenders (top 5 per axis; full lists in score.json):
  cyclomatic gen/xsd/analyze.py:311     report                             56
  cyclomatic gen/plates/build.py:956    _validate_config_against_ir        35
  cyclomatic gen/press/context.py:145   plate_context                      34
  cyclomatic gen/__main__.py:46         _ir                                23
  cyclomatic gen/tests/test_ir.py:102   _check_references                  20
  cognitive  gen/xsd/analyze.py:311     report                             44
  cognitive  gen/ir/resolve.py:119      flat_elements                      40
  cognitive  gen/tests/test_ir.py:102   _check_references                  38
  cognitive  gen/press/context.py:145   plate_context                      37
  cognitive  gen/xsd/analyze.py:207     _sccs                              37
  size       gen/xsd/analyze.py:311     report                             152
  size       gen/press/context.py:145   plate_context                      96
  size       gen/plates/build.py:533    _value_plate                       89
  size       gen/plates/build.py:956    _validate_config_against_ir        89
  size       gen/ir/resolve.py:119      flat_elements                      78

Commit 52794e60a1ac0c1a2fb50c4e43f4f2f3dcf7d2e9.

@webern webern merged commit a78aff5 into main Jun 30, 2026
7 checks passed
@webern webern deleted the clef-number branch June 30, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai Issues opened by, or through, a coding agent. area/mx::api breaking fixes or implementation that require breaking changes bug software defect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

api: clef number attribute does not round-trip

1 participant