The decided code work behind aff1809, review-hardened (high-effort
multi-agent review; 3 correctness findings fixed pre-commit, all
regression-locked).
epiphany-ops:
- K3: SystemDerivedContentImmutable (12) — modify_event /
modify_identified_pitch refuse intrinsic-content rewrites of
SYSTEM_DERIVED pitches, checked against the system_mints registry
(base-seeded + op mints, so reduce()/reduce_onto() agree).
REVIEW FIX: Transpose now *skips* system-derived targets like
tombstoned ones (an in-place alteration shift desynchronized content
from the derivation registry -> checkpoint-dependent verdicts); an
all-system transpose reduces as the K3 no-op. Catalog Transpose
updated.
- K9: RecreateContentMismatch (13) replaces the TargetMissing misnomer
at both value-retaining re-create sites (CreateStaff, carried
TimeSignature). Catalog corrected: container creates are plain
set-union (no value comparison), not K9 sites.
- C4: ReanchorReason::SameCanvasNearer (6); rank-4 recording routes
through rank_reason. REVIEW FIX: an *unestablished* rank 4
(unresolvable placement fallthrough in containment_rank) keeps the
honest ExplicitFallback — selection order unchanged.
- Filed P13-K1 (pre-existing checkpoint asymmetry for ModifyEvent-
introduced system pitches) in DECISIONS rather than improvising.
epiphany-core (H7, req:pitch:authored-uninferred):
- Authored attachments surface for inference-ineligible targets in
both pre-passes (best_authored_spelling/_decomposition refactor,
candidates-first liveness via the existing Score::live_pitch_ids);
two new taxonomy buckets enter the derivation fingerprint. The old
test locking the pre-decision mirror is flipped to the ratified
behavior.
epiphany-testkit (review fixes):
- prepass_harness: spelling-unavailable pitches may carry *authored*
surfacings (inferred still forbidden); decomposition reconstruction
invariants scoped to algorithm output (authored entries are
invariant-15's graph-level jurisdiction); accounting identity gains
the authored-uninferred bucket.
- generators: the three appended discriminants (12/13/6) now generate.
Full gate green: fmt, clippy -D warnings, rustdoc -D warnings, 30
workspace suites, conformance scale 1 (8/8). Wire goldens + decode
bounds for the appended discriminants; 12 new regression tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
The chosen Phase-3 attack, run as two parallel waves. 829 workspace
tests pass; clippy -D warnings, fmt, and rustdoc clean; all three
spec documents build with zero undefined references.
Casting-off (epiphany-engrave/src/casting.rs, wired into the
Engraver):
- Greedy first-fit system breaking per region at measure-start
barline columns; a measure that would overflow the content width
starts a new system. Hard SystemBreakAt/PageBreakAt always
honoured; soft breaks honoured unless pathological (skipped with
the spec's warning + IrOverride-recorded decision).
- Vertical stacking from real content extents with the inter-system
gap read from the vertical band model; page overflow starts the
next page. World frame: pages stacked vertically, coordinates
baked into glyphs/strokes, so the SVG renderer, hit-testing, and
the GUI viewport are unchanged.
- Real ResolvedPage/ResolvedSystem trees (1-based page numbers,
content bounding boxes, staves from staff-line segments, measures
from barline columns); every chosen break appends an
EngravingDecision with MUSCLOID EngravedBreak provenance,
UserOverride-attributed via the new ConstrainedLayoutIR
break_origins sidecar; staff lines split per system with
synthesized continuation provenance.
- Break-constraint evaluation flips: satisfied iff the layout breaks
at the slot. The two single-system tests invert deliberately
(a hard break is now honoured; a user break is honoured and
attributed instead of warned). Geometric constraints evaluate in
the pre-casting spaced frame (documented).
- Page geometry is engraver-side PageGeometry (A4 portrait at an
8 mm staff: page 105 x 148.5 staff spaces, margins 7.5, content
90 x 133.5; arithmetic documented) — Canvas.layout_defaults has no
graph home and is a schema-major addition (P12-I7).
ENGRAVER_VERSION = 2. Goldens regenerated: ten_measure_single_staff
engraves as 2 systems (viewBox 84x20.6, was 103x11);
valid_score_rich as 3 systems; stub goldens byte-identical.
K1 schema-fill (Operation Catalog 0.4.0 -> 0.5.0, ratified first;
wire discriminants strictly appended):
- CreateStaff (24 / tag InsertStaff 24): set-union mint of a global
Staff; CreateStaffInstance now preconditions that its referenced
staff is live.
- SetTimeSignature (25): value-carrying meter-change LWW keyed by
(region, resolved position); the carried TimeSignature mints
set-union; StructuralFieldCollision on meter_sequence.
- SetTempoSegment (26): LWW keyed by (scope, resolved start) over
the score or region tempo map; a write that would malform the map
refuses with the appended PreconditionFailureReason 11
(TempoMapMalformed).
- SetStaffLayout (27): LWW advisory over the staff instance's three
inline layout fields.
- Create score/canvas remain deliberately unavailable slots: the
root and canvas are inline singletons with no addressable object
model (P12-K8), not force-designed.
Value-restoring undo (P11-C8 narrowed; catalog §UndoTransaction
rewritten and per-primitive undo notes updated):
- Canonical-order write chains (base-seeded) across all eleven LWW
families. StrictInverse restores each written key to its
chain-predecessor value iff the transaction's write is still the
key's last writer, else refuses the whole undo with a
TransactionConflict naming the superseder; BestEffort restores the
still-last keys. Clean compensations are Applied; only minted-
object tombstone repairs ride AppliedWithRepair (no new repair
vocabulary). Mixed mint+overwrite transactions compose; strand
guards refuse tombstoning mints still referenced by live
non-members.
- Undo-of-undo pinned and tested: restorations are chain writes, so
undoing the undo's transaction restores the undone value, and a
second undo of the same transaction conflicts (absence-restores
repeat idempotently — documented asymmetry, P12-K11).
- Permutation invariance pinned across five delivery orders; the
convergence generators gain the new ops and a tx-then-undo flow.
- Still deferred in normative text: delete resurrection (needs a
system-derived tag outside the ratified closed set), Transpose
inversion (P12-K2), Cascade dependent closure.
Trackers: Binary Format companion 0.1.0 -> 0.2.0 (appended wire/tag
tables, PreconditionFailureReason 11, payload layouts, history row —
a schema-minor evolution under its own rules); nine new Pass-12 rows
(C5, K8-K11, I7-I10); core-spec OperationKind listing gains the four
kinds; revision-history rows in core spec and companion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
Two audit pushes whose code edits interleave line-by-line in the same
files (reduce.rs, bundle.rs, the DECISIONS logs), committed together so
the tree at every commit builds. Gate: 784 workspace tests pass, clippy
-D warnings clean, fmt clean.
Push 1 — the true MUST violations, all fixed:
- bundle: zstd read support on both read paths, output bounded by the
declared uncompressed_length, typed decompression errors, explicit
CompressedManifest rejection (zstd 0.13 workspace dep; write path
stays uncompressed per the Phase-3 deferral).
- ops: system-derived counter collision check — mint registry seeded
from the base graph, canonical-order pre-walk, halt via the new
PendingReason::HaltedBySystemCollision (discriminant 4, additive)
with transaction-atomicity and causal-dependent closure; neither
input set occupies a collided counter. canonical_pitch_bytes made
pub in core for the MUSCSPCH preimage.
- ops: Transpose skips tombstoned targets per the catalog; missing
targets still refuse the whole operation.
- ops: marker re-anchoring recorded as a RepairRecord in the
triggering operation's effect; ResolveConflict meta-conflicts name
both resolvers; base-free pitch-id freshness; reserved effect
vocabulary annotated.
- core: decomposition pre-pass honors authored attachments
(resolve_decomposition, spec-default precedence); inversion
tolerance typed as a TempoIntegration-class Tolerance.
- CONFORMANCE.md: the determinism conformance statement required by
Appendix D — all seven declarations.
Push 3 — wiring the types-only machinery:
- layout-ir/engrave: to_constrained emits real constraints (successive
notehead no-collision chains, per-glyph region containment, soft
user-break constraints); ConstraintStrength{Required, Preferred}
with strength-by-rule; Preferred violations surface as warnings, not
failures; StubSolver reworked honest-but-renderable. SVG goldens
byte-identical; snapshot constraint counts regenerated (0->90/15).
- layout-ir: to_logical projects user system/page breaks as anchored
EngravingOverrides with paired UserOverride-sourced decisions
(OverrideKind::SystemBreak/PageBreak carry TimeAnchor, ratified in
the spec alongside).
- layout-ir/ops/editor-core: edit-barrier bridge — decode mirrors for
the whole barrier tree (reject-never-normalize, NFC revalidation,
MAX_CONDITION_DEPTH = 64), golden-locked blob codec for the
ExtensionDeclaration fields, a barrier gate in apply and
apply_transaction backed by a Score oracle and real containment
contexts, and apply_unsafe recording the crossed extensions in
extensions_requiring_tombstone() for the next bundle write.
- ops: ResolveEquivocation meta-operation per the newly ratified
catalog entry — payload discriminant 3 (appended), set-level
earliest-resolve-governs promotion, ResolveConflict-mirrored
meta-conflicts, permutation-invariance fuzz; the missing golden
locks on the OperationKind/OperationPayload wire tables added.
- ops/editor-core: validation modes — ValidationMode + a non-canonical
advisory layer (validate.rs), an authoring gate before minting, and
reduction pinned as replay mode by construction (canonical bytes
untouched).
- bundle: the operation index (opindex.rs) — provisional golden-locked
payload, binary-search locate, staleness defined as full-ChunkRef
set equality against operation_roots, and the reject-and-rebuild
discipline (a defective index is never bundle corruption).
- ops: re-anchoring rule table completed — the four-key "nearest"
ordering computed from base-free ledger indices; markers re-anchor
to the nearest live event in the same staff instance (replacing the
Push-1 region-start stand-in); cue-source cascade; graphic-gesture
Events/Range/Free rows; comment and analytical-annotation orphaning.
Zero appended discriminants.
Spec enablers ratified with Push 3: catalog §ResolveEquivocation
(0.3.0 -> 0.4.0) and anchored break overrides; 16 new Pass-12 rows
filed (C1-C4, K5-K7, I4-I6, D1, E1-E5). The data-model payload
expansion (SlurKind, beam geometry, voltas, instrument bodies,
metadata) is deliberately staged to the Binary Format companion — the
positional graph codec has no value-level versioning, so filling those
structs is a schema-major break that should land once, with J.
Also carries the pre-existing editor-track increment: the atomic
tuplet overwrite (CascadeDeleteTuplets prunes decomposition
attachments naming the cascaded tuplet).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
Fourth broad-K0 subsystem group — three value-typed LWW field-overwrite ops, one
per settings cluster (additive: OperationKind variants 21-23; framework frozen):
- SetMetadata { metadata: ScoreMetadata } — overwrite the score-singleton
metadata (title/composer/copyright); concurrent differing ⇒
StructuralFieldCollision.
- SetMetricGrid { region, grid: Option<MetricGrid> } — overwrite a region's
default metric grid (LWW keyed by region; concurrent differing ⇒ collision).
- SetUserPageBreak { region, anchor, present } — the page-break sibling of
SetUserSystemBreak: a canonical LWW advisory.
- core: expose ScoreMetadata + MetricGrid via CanonicalValue (no new byte layout
— they already have whole-score Codec impls).
- SetMetadata / SetMetricGrid mirror the modify ops: the resolved value lives in
the graph (reduce_onto), with new last_metadata / last_metric_grid LWW working
state for concurrent-differing detection; MaterializedState records only the
effect and conflict.
- SetUserPageBreak mirrors SetUserSystemBreak's canonical advisory: a new
MaterializedState.page_breaks map (encode + decode added, parallel to breaks),
plus the graph's region user_page_breaks.
Migration: v1-native (no lossy v0 predecessor) -> project/migrate by identity;
the round-trip identity test now covers all four M2 groups.
Coverage:
- testkit operation_payload + ops fuzz gen_payload emit the three kinds, so the
convergence / determinism / migration-equivalence and MaterializedState
decode-roundtrip gates exercise them (incl. page_breaks) at scale.
- reduce_onto graph tests: the three settings materialize in graph and ledger
(metadata title, region default metric grid, region user page break +
MaterializedState.page_breaks), invariant-clean; plus a concurrent-differing
SetMetadata conflict test.
Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (519);
conformance_suite scale 1 passes. Catalog sections + DECISIONS for the M2 groups
land in M2e per the staged plan. The unrelated Agent-I working tree is left
uncommitted; this commit stages only core/ops/testkit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Third broad-K0 subsystem group — six new value-typed ops for the score-graph
containers, reusing M1's disciplines (additive: OperationKind variants 15-20,
new apply arms + reduction methods; framework frozen). Per the project lead's
call, container deletes are EMPTY-ONLY (no cascade): a precondition NoOp unless
the container has no live children, so the caller deletes contents first.
- CreateRegion / DeleteRegion, CreateStaffInstance / DeleteStaffInstance,
CreateVoice / DeleteVoice. Creates are value-typed mints of an empty container
(set-union creation); deletes are delete-wins tombstones gated on emptiness.
- core: expose Region / StaffInstance / Voice via CanonicalValue (no new byte
layout — they already have whole-score Codec impls), with round-trip coverage.
- New PreconditionFailureReason::ContainerNotEmpty (additive discriminant 10;
encode + decode), reported when an empty-only delete hits a non-empty container.
Reduction (reduce.rs):
- Two child-existence indices, region_instances and instance_voices, drive the
emptiness checks (a voice's events are read from voice_occupancy), so the
ledger projection and the graph agree on every delete result. Populated by
seed_from_graph, the create ops, and implicit voice creation in insert_event.
- CreateStaffInstance / DeleteStaffInstance maintain the region's staff_extent so
it lists exactly the manifested staves (Chapter 5 RegionExtents); valuegen's
fresh region uses a far-future wall-clock extent so it never overlaps an
existing region in both time and staff.
Migration: v1-native (no lossy v0 predecessor) -> project/migrate by identity;
group1_and_group2_kinds_round_trip_by_identity extended to cover Group 3.
Coverage:
- testkit operation_payload + ops fuzz gen_payload emit the six kinds, so the
convergence / determinism / migration-equivalence gates exercise the
bookkeeping projection at scale.
- A reduce_onto graph test materializes a region -> staff instance -> voice
subtree (invariant-clean), asserts the empty-only delete refuses a non-empty
container with ContainerNotEmpty, and verifies an ordered teardown clears the
subtree from both graph and ledger.
Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (criterion
1 green with the new container objects in the corpus); conformance_suite scale 1
passes. Catalog sections + DECISIONS for these ops land in M2e per the staged
plan. The unrelated Agent-I working tree is left uncommitted; this commit stages
only core/ops/testkit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Foundation milestone for Track B's Operation Catalog: shift epiphany-ops from
the v0 identifier-only payload projections to durable value-typed payloads, and
scaffold the companion spec. Scope: the representative §6.10 set (7 primitives +
2 meta-ops); the slice-driven K0 expansion follows.
Core (the K↔J seam):
- epiphany-core exposes a public `CanonicalValue` trait (canonical_bytes /
decode_canonical) delegating to the existing private `Codec` machinery, for
Event/Rest/PitchSpelling/Tie/Slur/Beam/Spanner/RegionTimeModel/TimeAnchor.
No new byte layout — a value's bytes equal what the whole-score codec emits,
so all goldens / criterion 4 stay byte-identical.
Ops (value-typed payloads, frozen reduction rules):
- InsertEventOp{staff_instance,event:Event}, RespellPitchOp{pitch,spelling:
PitchSpelling}, CreateCrossCuttingOp{structure:CrossCuttingValue},
ChangeRegionTimeModelOp{...,new_time_model:RegionTimeModel},
SetUserSystemBreakOp{...,anchor:TimeAnchor}, ReplaceWithRest{rest:Rest}.
Payloads frame each value's CanonicalValue bytes behind a u32 length prefix.
- reduce.rs: read-sites only moved onto the value (rules, conflicts, ordering,
promotion, re-anchoring, undo, transactions unchanged); reduce_onto now
materializes the real event/structure instead of the C4 placeholder.
MaterializedState.spellings now stores PitchSpelling (encode + decode updated).
- v0.rs: frozen identifier-only shapes (migration regression guard).
- migrate.rs: migrate_v0_envelope(v0, &Score) + project_v1_to_v0 + MigrationError;
deterministic and equivalence-preserving. Respell spelling recovered from the
score context; irreversible case is P12-K1.
- valuegen.rs: shared value-type builders (reused by fuzz, migration, tests,
testkit). Resolves P11-C1; P11-C10 Dismiss recorded.
Testkit (Agent F merge gate):
- migration.rs: reduce(v1)==reduce(migrate(project(v1))) byte-identical, plus
migration determinism and a non-vacuity guard; wired into acceptance.rs as
agent_k_migration_equivalence_gate. Generators/harnesses build v1 payloads.
Spec:
- spec/operation_catalog.{tex,pdf}: new companion (independent semver) — framework
+ per-primitive template, the 7+2 representative primitives, the v0→v1 migration
contract, and K1 framework slots for the remaining K0 primitives. Builds clean.
- PASS12_BATCH.md: P12-K1 (respell fingerprint irreversibility).
Gates: cargo build/fmt/clippy -D warnings clean; cargo test --workspace green
(incl. criteria 1/4/5/6 and the new K gate); conformance_suite scale 1 passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Spec-revision pass (architecture unchanged) converting the v0
implementation's provisional, golden-locked choices into ratified
core_spec.tex text, so durable byte layouts are fixed before the
next-phase build-outs. Worklist: spec/PASS11_WORKLIST.md; per-item
dispositions: spec/PASS11_RATIFICATION_LOG.md.
Adopt-and-pin (bytes): TypedObjectId 16-bit BE discriminant table
0..=27 (added the 5 variants the code carried); promoted-voice
(MUSCSVCE), synthetic-pitch (MUSCSPCH, tuning always in identity),
and integrity-anomaly (MUSCSANM, now a reserved built-in tag)
derivations; ChunkKind/ProfileId/CompressionAlgorithm discriminants;
ManifestId preimage (manifest_id excluded); RationalTime/scalar
layouts + the codec convention baseline the Binary Format companion
inherits.
Decide-and-pin: tempo Linear interpolates speed (not bpm);
StructuralFieldCollision tags the winner Conflicted; lifted the
>2-way / partial-overlap voice-promotion rule to normative; pinned
TransactionCategory and ObjectKind core vocabularies; added
ResolutionAction::Dismiss so the Dismissed state is reachable by an
authored op; pinned the (non-canonical) LayoutObjectId derivation
(MUSCLOID).
Fixes: blob hashing is bare MUSCBLOB||payload (deleted the
contradictory "identically to chunks" phrasing); equal-generation
superblock rule (DivergentSameGeneration); defined ProfileConstraints
with the required RetentionPolicy + first-declared precedence; made
the DVV zero-based floor normative; reconciled the invariant count to
19 and named the three construction-time MUSTs — TupletRatio now
rejects degenerate ratios at construction (zero term or
actual==notated), enforced by a checked constructor + codec decode
validation.
Code changes carry regression tests; byte-layout golden tests now
cite their ratified requirements. Workspace green: cargo test, clippy
-D warnings, fmt; spec builds (lualatex, 253pp). Per-crate DECISIONS
files annotated with the ratification status.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011giSRaHCFCGm1Z2SWv6JHt