Skip to content

fix: stop api round-trip crashes on metronome/tempo marks#223

Merged
webern merged 1 commit into
mainfrom
claude/brave-brahmagupta-qzb80v
Jun 20, 2026
Merged

fix: stop api round-trip crashes on metronome/tempo marks#223
webern merged 1 commit into
mainfrom
claude/brave-brahmagupta-qzb80v

Conversation

@webern

@webern webern commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Summary

The api pipeline crashed outright (no output at all) on 16 corpus metronome/tempo files — 8 GETDATAFAIL on read, 8 CREATEFAIL on write — caused by two long-standing MX_THROW sites in the impl layer (present in the original library too; the round-trip classifier from #217 is what surfaced them).

Read (MetronomeReader):

  • parseNoteRelationNote() threw "wtf is this" on the metronome-note form. The api has no representation for it, so the tempo is now left unspecified instead of crashing the whole document.
  • parseMetronomeModulation() was an empty stub that left the tempo unspecified (which then crashed the writer). Implemented it — the two beat-units are read into api::MetricModulation.

Write (DirectionWriter):

  • The tempo loop threw on any non-beatsPerMinute tempo. Replaced with a switch that writes beatsPerMinute and metricModulation, and skips tempoText / unspecified tempos gracefully.

Result: metric modulation now round-trips through the api. The metronome-note form and a non-numeric per-minute (a legal xs:string, e.g. "ca. 76") no longer crash — their tempo is dropped, producing imperfect output instead of none.

Corpus discovery confirms GETDATAFAIL and CREATEFAIL both drop from 8 to 0. No file reaches a full PASS: all 16 still fail the strict DOM compare on pre-existing, by-design fidelity losses unrelated to metronomes (identification / encoding / part-list reordering), so there are no new live-corpus baseline entries — as the issue anticipated.

Testing

  • New targeted red/green tests cover both former crash sites plus metric-modulation fidelity (*_MetronomeApi: 17 assertions in 4 test cases)
  • Full api test suite passes (4114 assertions in 272 test cases)
  • Corpus discovery: 0 GETDATAFAIL, 0 CREATEFAIL (was 8 + 8)

References

The api pipeline crashed outright (no output) on 16 corpus metronome/tempo
files: 8 GETDATAFAIL on read and 8 CREATEFAIL on write. Two long-standing
MX_THROW sites were responsible.

Read (MetronomeReader):
- parseNoteRelationNote() threw "wtf is this" on the <metronome-note> form.
  The api has no representation for it; leave the tempo unspecified instead
  of crashing, so the rest of the document still round-trips.
- parseMetronomeModulation() was an empty stub that left the tempo
  unspecified (which then crashed the writer). Implement it: read the two
  beat-units into api::MetricModulation.

Write (DirectionWriter):
- The tempo loop threw on any non-beatsPerMinute tempo. Replace with a switch
  that writes beatsPerMinute and metricModulation, and skips tempoText /
  unspecified tempos gracefully rather than throwing.

Metric modulation now round-trips through the api. The metronome-note form
and non-numeric <per-minute> (a legal xs:string, e.g. "ca. 76") no longer
crash; their tempo is dropped, producing imperfect output instead of none.

Adds targeted red/green tests covering both former crash sites and metric
modulation fidelity.

Closes #218
@webern webern added bug software defect area/mx::api area/mx::impl ai Issues opened by, or through, a coding agent. labels Jun 20, 2026 — with Claude
@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 f204033dcbf6a36e622d6bf927e5af2baddb2173.

@github-actions

Copy link
Copy Markdown

Coverage report

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

Metric Coverage Covered / Total
Lines 77.9% 28539 / 36624
Functions 74.4% 6360 / 8550
Branches 50.7% 22672 / 44725

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

Metric Coverage Covered / Total
Lines 72.6% 5406 / 7451
Functions 60.3% 1827 / 3030
Branches 43.5% 4504 / 10347

Core HTML report | API HTML report

Commit f204033dcbf6a36e622d6bf927e5af2baddb2173.

@webern webern merged commit e7592c4 into main Jun 20, 2026
7 checks passed
@webern webern deleted the claude/brave-brahmagupta-qzb80v branch June 20, 2026 17:45
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 area/mx::impl bug software defect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix api round-trip crash on metronome/tempo marks

1 participant