Skip to content

feat: add per-staff and mid-measure transposition to mx::api#305

Merged
webern merged 1 commit into
mainfrom
claude/measure-transposition-split
Jul 6, 2026
Merged

feat: add per-staff and mid-measure transposition to mx::api#305
webern merged 1 commit into
mainfrom
claude/measure-transposition-split

Conversation

@webern

@webern webern commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Human Summary

Seems a bit ugly but I think that is a due to the fact that transposition can either be specified at the part level (i.e. start of the score in the part list) or can be changed mid-measure (which is certainly required by real scores). So our ugly semantics mirror that and the a measure 0, tickTime 0 transposition is expressed both at the part level and the measure level (if I understand correctly).

As long as it makes enough sense to use, then It looks like it solves the missing feature of the API. I'm going to call it good and merge it.

Summary

mx::core already fully modeled the transposition shape (Transpose::number()); the gap was entirely in mx::api/mx::impl.

  • TransposeData gains staffIndex (same INDEX_UNSPECIFIED convention as KeyData::staffIndex) and tickTimePosition (mirrors KeyData::tickTimePosition for mid-measure changes).
  • MeasureData gains a transpositions vector: event-based like keys (populated whenever a measure's <attributes> contains <transpose>, at any measure/tick), not carried-forward.
  • The existing PartData::transposition convenience field (first <transpose> at measure 0/tick 0) is unchanged for backward compatibility; the writer only falls back to it when a measure has no explicit transpositions of its own.

Testing

  • New tests: mid-piece and staff-scoped transposition round-trips, equality coverage, and a regression check that PartData::transposition still behaves exactly as before (TranspositionTest.cpp)
  • make test: all pass (4584 assertions in 361 test cases, plus the three examples)
  • make test-api-roundtrip: 124 passed, 0 failed (of 124 pinned; no regressions)
  • make fmt / make check clean

References

Splits the transposition half out of the original combined time-signature
and transposition PR so each can be reviewed and merged independently.

Closes #269
@webern webern added feature new feature request non-breaking fixes or implementation that do not require breaking changes api Affects the mx::api layer impl Affects the mx::impl layer ai Issues opened by, or through, a coding agent. labels Jul 6, 2026 — with Claude
@webern webern changed the title feat: measure-level and staff-scoped transposition changes feat: add per-staff and mid-measure transposition to mx::api Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Coverage report

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

Metric Coverage Covered / Total
Lines 77.8% 28513 / 36640
Functions 74.3% 6352 / 8551
Branches 50.7% 22678 / 44751

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

Metric Coverage Covered / Total
Lines 78.9% 6152 / 7795
Functions 64.3% 2093 / 3254
Branches 48.1% 5247 / 10907

Core HTML report | API HTML report

Commit dc7e231d3979149be61be23a6412145eb3c5c299.

@github-actions

github-actions Bot commented Jul 6, 2026

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 dc7e231d3979149be61be23a6412145eb3c5c299.

@webern webern merged commit c7ebc8f into main Jul 6, 2026
7 checks passed
@webern webern deleted the claude/measure-transposition-split branch July 6, 2026 15:50
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. api Affects the mx::api layer feature new feature request impl Affects the mx::impl layer non-breaking fixes or implementation that do not require breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

api: measure level transposition change

1 participant