Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/memory/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ Project-shared agent memory for music21. One file per fact; see frontmatter for
- [sortedcontainers for streams](sortedcontainers-for-streams.md) — tried twice to make streams always-sorted via SortedList; abandoned, too slow for tiny streams
- [Stream subclass generic defaults](stream-subclass-generic-defaults.md) — how `inherit-generics` should work once PEP 696 default type params land; maybe add typing_extensions
- [BFS-flatten-iterator](bfs-flatten-iterator.md) — lazy breadth-first flatten is writable (maybe for tree first), but must not reuse the flat/flatten name tied to offsetInHierarchy
- [Meter immutability re-apply](meter-immutability-reapply.md) — meter-speed is too stale to merge; re-apply FrozenDuration + immutable MeterTerminal + tuple NumDenom fresh on master
34 changes: 34 additions & 0 deletions .agents/memory/meter-immutability-reapply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: meter-immutability-reapply
description: Plan to re-apply the meter-speed immutability rewrite fresh on master instead of merging the stale branch
metadata:
type: project
---

The `origin/meter-speed` branch (16 commits, Oct 2022) is a two-part meter rewrite:

1. **Representation change** — meter's internal form goes from strings (`'1/4'`,
`f'1/{d}'`) to tuples: `NumDenom = tuple[int, int]` (i.e. `(1, 4)`), with
`NumDenomTuple` / `MeterOptions` aliases in `meter/tools.py`.
2. **Immutability** — `MeterTerminal` / `MeterSequence` become slotted and
immutable (`SlottedObjectMixin` / `common.FrozenObject`, `FrozenDuration`,
`_durationFromNumeratorDenominator` cached with `lru_cache`). Immutable meter
terminals can be shared/cached with no defensive copies.

**Why not just merge master in (decided 2026-06-30):** the branch is 879 commits
behind. Merging `master` produced deep *semantic* conflicts — 31 hunks in
`meter/core.py`, 8 in `meter/tools.py` — because master independently evolved the
*string-based, mutable* code for a year+ (added typing like `-> None`, a `weight`
property, parse fast-paths, and a public→private rename `addTerminal` →
`_addTerminal`). Almost every hunk is two different implementations of the same
method, and the str→tuple change ripples into callers. Resolving that merge would
mean finishing+rebasing the rewrite through hundreds of collisions — not worth it.

**How to apply:** treat `origin/meter-speed` as a *reference*, not a mergeable
branch. Start a clean branch off current `master` and re-apply only the wanted
pieces as a fresh, reviewable change: `FrozenDuration`, slotted/immutable
`MeterTerminal` & `MeterSequence`, and the tuple `NumDenom` internal
representation. Note `common.FrozenObject` is **already in master** (typed for
3.12+), so only the meter-specific immutability needs porting. Validate against the
full `music21/meter` test suite and fix downstream callers. Keep `origin/meter-speed`
until the re-apply lands; delete it afterward.
Loading