From 92aaccf7e24d593417b6c1bd1c836c196085a64a Mon Sep 17 00:00:00 2001 From: Levi Neuwirth Date: Thu, 2 Jul 2026 17:10:50 -0400 Subject: [PATCH] Pushes 1+3: fix the MUST-level violations, wire the types-only machinery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd --- CONFORMANCE.md | 127 + Cargo.lock | 29 + Cargo.toml | 7 + crates/epiphany-bundle/Cargo.toml | 5 + crates/epiphany-bundle/DECISIONS.md | 117 + crates/epiphany-bundle/README.md | 6 +- crates/epiphany-bundle/src/block.rs | 88 +- crates/epiphany-bundle/src/bundle.rs | 484 +++- crates/epiphany-bundle/src/chunk.rs | 13 +- crates/epiphany-bundle/src/codec.rs | 18 +- crates/epiphany-bundle/src/error.rs | 29 +- crates/epiphany-bundle/src/lib.rs | 17 +- crates/epiphany-bundle/src/opindex.rs | 504 ++++ crates/epiphany-core/DECISIONS.md | 71 + crates/epiphany-core/src/lib.rs | 22 +- crates/epiphany-core/src/pitch.rs | 8 +- crates/epiphany-core/src/prepass.rs | 105 +- crates/epiphany-core/src/prepass/tests.rs | 221 ++ crates/epiphany-core/src/tempo.rs | 45 +- crates/epiphany-editor-core/src/barriers.rs | 423 ++++ crates/epiphany-editor-core/src/lib.rs | 865 ++++++- crates/epiphany-editor-gui/src/main.rs | 1 + crates/epiphany-engrave/src/lib.rs | 243 +- crates/epiphany-layout-ir/DECISIONS.md | 121 + crates/epiphany-layout-ir/src/barrier.rs | 677 ++++- crates/epiphany-layout-ir/src/constrained.rs | 419 ++- crates/epiphany-layout-ir/src/engraving.rs | 118 +- crates/epiphany-layout-ir/src/lib.rs | 16 +- crates/epiphany-layout-ir/src/logical.rs | 152 +- crates/epiphany-layout-ir/src/roundtrip.rs | 45 +- crates/epiphany-layout-ir/src/solver.rs | 91 +- crates/epiphany-ops/DECISIONS.md | 299 +++ crates/epiphany-ops/src/decode.rs | 1 + crates/epiphany-ops/src/effect.rs | 20 + crates/epiphany-ops/src/envelope.rs | 35 +- crates/epiphany-ops/src/fuzz.rs | 138 +- crates/epiphany-ops/src/lib.rs | 12 +- crates/epiphany-ops/src/migrate.rs | 5 + crates/epiphany-ops/src/payload.rs | 377 ++- crates/epiphany-ops/src/reduce.rs | 2245 ++++++++++++++++- crates/epiphany-ops/src/v0.rs | 6 +- crates/epiphany-ops/src/validate.rs | 451 ++++ crates/epiphany-ops/tests/graph_reduction.rs | 937 ++++++- ..._measure_single_staff.engrave.snapshot.txt | 2 +- ...ten_measure_single_staff.stub.snapshot.txt | 2 +- .../valid_score_rich.engrave.snapshot.txt | 2 +- .../golden/valid_score_rich.stub.snapshot.txt | 2 +- crates/epiphany-testkit/src/bundle_harness.rs | 432 +++- crates/epiphany-testkit/src/layout_stub.rs | 83 +- .../epiphany-testkit/src/prepass_harness.rs | 9 +- spec/PASS12_BATCH.md | 29 +- spec/PASS12_RATIFICATION_LOG.md | 11 + spec/core_spec.pdf | Bin 1269813 -> 1273973 bytes spec/core_spec.tex | 39 +- spec/operation_catalog.pdf | Bin 94732 -> 98975 bytes spec/operation_catalog.tex | 50 +- 56 files changed, 9936 insertions(+), 338 deletions(-) create mode 100644 CONFORMANCE.md create mode 100644 crates/epiphany-bundle/src/opindex.rs create mode 100644 crates/epiphany-editor-core/src/barriers.rs create mode 100644 crates/epiphany-ops/src/validate.rs diff --git a/CONFORMANCE.md b/CONFORMANCE.md new file mode 100644 index 0000000..ce4cf6c --- /dev/null +++ b/CONFORMANCE.md @@ -0,0 +1,127 @@ +# Determinism Conformance Statement + +This is the published conformance statement required by the core +specification's Determinism Contract (`core_spec` Appendix D, +§"Conformance Statement", `sec:det:conformance`). It covers the reference +implementation in this repository — the `epiphany-*` workspace crates — as of +the tree that carries this file. Every claim below is anchored by a test named +in the Canonical Byte-Layout Reference (Appendix E) or cited inline. + +## Platform and floating-point library + +The reference build and CI platform is Linux on x86-64, compiled with stable +Rust (MSRV pinned in `Cargo.toml`, `rust-version = "1.77"`), default target +options — no `fast-math`-class flags anywhere in the workspace. + +Canonical state contains no *computed* floating-point values. Every float that +enters canonical state is a stored `CanonicalF64` (finite by construction, +`-0.0` canonicalized) serialized as its 8 little-endian IEEE 754 bytes +(`epiphany-determinism/src/float.rs`); no canonical algorithm derives new +float values into canonical state. + +**Transcendental functions.** The only transcendentals in the workspace are +`f64::ln`/`f64::exp` from the platform's `std`/libm, used exclusively by tempo +integration (`epiphany-core/src/tempo.rs`, speed-linear and exponential +segments). Per the contract's required disposition, those conversion outputs +are declared **advisory and non-canonical**: musical time is the exact +rational, wall-clock time is exact integer nanoseconds, and no tempo-derived +float is stored in canonical chunks or hashed into canonical identity. If a +future feature promotes tempo-derived values into canonical state, adopting a +documented portable math library (or quantizing at the canonical boundary) is +a precondition, not an afterthought. + +Content hashing is BLAKE3 (the `blake3` crate, workspace-pinned), which is +bit-exact by specification on all platforms. + +## Parallel execution strategy + +None. Every canonical algorithm — reduction, materialization, pre-passes, +encoding, hashing, layout solving — is single-threaded by construction; the +workspace contains no `rayon`, `std::thread::spawn`, or other concurrency in +any canonical path. The implementation *is* the single-threaded baseline, so +equivalence to that baseline holds by identity. Any future parallel execution +must demonstrate byte-identical output against this baseline before it ships. + +## `-0.0` canonicalization and NaN/infinity rejection + +`CanonicalF64::new` rejects NaN and ±infinity at runtime in **all build +profiles** (not just debug assertions) and canonicalizes `-0.0` to `+0.0` +before storage, so both are unrepresentable in canonical state. Decoding +treats non-finite float bytes as corruption (typed error, never silent +acceptance), and hash preimages accept only `CanonicalF64` values. Locked by +the unit tests in `epiphany-determinism/src/float.rs` and +`src/serialize.rs`. + +## Rounding + +Round-to-nearest-ties-to-even is used at every canonical quantization +boundary: `QuantizedCoord` (1/1024 staff space) quantizes via +`round_ties_even` and rejects NaN/infinity/overflow rather than saturating +(`epiphany-determinism/src/coord.rs`), and `ResolvedLayoutIR` quantizes its +f32 working coordinates through the same type at canonical emission. + +Declared deviation, inside the advisory surface only: the non-canonical +wall-clock conversion in `tempo.rs` rounds nanoseconds with `f64::round` +(half-away-from-zero). It shares the tempo-integration surface declared +non-canonical above; it must be converted to ties-to-even if that surface is +ever promoted. + +## Canonical iteration orders + +All canonically-serialized collections iterate in the contract's orders +(§`sec:det:ordering`): + +- Generic containers are `BTreeMap`/`BTreeSet` or explicitly sorted through + `CanonicalMap`/`CanonicalSet`/`sort_canonical`, whose element types must + implement the `CanonicalByteOrder` marker — a type whose `Ord` does not + match its canonical byte order is rejected at compile time + (`epiphany-determinism/src/order.rs`). +- Operation envelopes reduce in the canonical order: causal (Kahn topological + over DVV coverage), then the HLC tuple + (`epiphany-ops/src/reduce.rs::canonical_reduction_order`), property-tested + for permutation invariance at 1,000 envelopes × 10 orders plus a + 10,000-set fuzz gate. +- Conflicts serialize ascending by `ConflictId`; integrity anomalies ascending + by `IntegrityAnomalyId`; chunk references by `(kind, hash, offset)`; + extension declarations by `(ExtensionId, SemVer)` as numeric tuples — + each rejected (not normalized) on decode when out of order. + +`HashMap`/`HashSet` appear only in non-canonical lookup indexes, caches, and +diagnostics, or are projected through a sort before any canonical output. + +## NFC normalization + +Unicode normalization uses the `unicode-normalization` crate +(workspace-pinned, `0.1.x`). Catalog identifiers NFC-normalize at +construction (`epiphany-core/src/pitch.rs`); envelope string fields +NFC-normalize before hashing (`epiphany-ops/src/encode.rs`, test +`nfc_normalizes_before_hashing`); system-derived pitch identity NFC-normalizes +at the derivation boundary. Free-text fields are raw UTF-8 by the ratified +codec convention (`req:format:codec-conventions`) and are not folded. + +## Declared open-question algorithms + +Per §"Open Algorithm Hooks", every open-question area is either +profile-declared with a versioned identifier or errors rather than +substituting a vendor heuristic: + +- **Spelling**: `SpellingAlgorithmId` `"default"` — a Temperley-style + line-of-fifths preference algorithm, v1 (`epiphany-core/src/prepass.rs`). + The identifier is the crate's proposal pending ratification (P12-H1). A + profile requesting any other id errors; nothing is silently substituted. +- **Notational decomposition**: `DecompositionAlgorithmId` `"default"` — the + integer-grid metric splitter, v1, with its scope bounds recorded as + P12-H4 (single governing meter, `MAX_DOTS = 1`, tuplet-nesting deferred). + Same no-substitution rule. +- Both pre-pass outputs are **canonical derived annotations**: deterministic + functions of `(materialized graph, profile, algorithm id)` recomputed on + materialization, never stored canonical state — so an algorithm version + change deterministically invalidates derived output without state + migration. +- **Tempo curves**: `TempoShape::Curve` integration is unimplemented and + declared as such — conversion returns `CurveIntegrationUnsupported` + rather than a wrong or vendor-specific answer. The linear/exponential + segment integration and the `wallclock_to_musical` inverse (deterministic + continued-fraction with documented iteration/denominator bounds and a + typed `TempoIntegration`-class tolerance) are advisory, per the + floating-point declaration above. diff --git a/Cargo.lock b/Cargo.lock index a449985..72a3b56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1061,6 +1061,7 @@ name = "epiphany-bundle" version = "0.0.0" dependencies = [ "epiphany-determinism", + "zstd", ] [[package]] @@ -4540,6 +4541,34 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "zune-core" version = "0.4.12" diff --git a/Cargo.toml b/Cargo.toml index 35aef9c..446ab7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,6 +81,13 @@ num-traits = { version = "0.2", default-features = false } # Unicode": canonical text fields MUST be NFC). Used to normalize registry / # catalog names so canonically-equivalent spellings compare equal. unicode-normalization = "0.1" +# Zstandard, for the bundle's chunk *read* path (Chapter 8 §"Compression": +# conforming implementations MUST support reading zstd-compressed chunks; the +# write path deliberately stays uncompressed in v0). epiphany-bundle only ever +# calls the decoder in production code; the encoder is used by its tests to +# produce compressed fixtures. Default features (legacy formats, dictionary +# building) are off — none are needed to decode standard frames. +zstd = { version = "0.13", default-features = false } # Determinism-sensitive: never enable fast-math-style codegen on canonical # numerical paths (Appendix D, "Rounding and CPU Behavior"). The default diff --git a/crates/epiphany-bundle/Cargo.toml b/crates/epiphany-bundle/Cargo.toml index b3b363b..33625a9 100644 --- a/crates/epiphany-bundle/Cargo.toml +++ b/crates/epiphany-bundle/Cargo.toml @@ -9,6 +9,11 @@ description = "The Epiphany .musc bundle file format (spec Chapter 8): fixed hea [dependencies] epiphany-determinism.workspace = true +# Decode-only in production code: the read path MUST support zstd-compressed +# chunks (spec Chapter 8 §"Compression"); the writer still emits every chunk +# uncompressed (the documented Phase-3 deferral). See DECISIONS.md for why the +# libzstd binding was chosen over a pure-Rust decoder. +zstd.workspace = true [[example]] name = "fuzz_crash" diff --git a/crates/epiphany-bundle/DECISIONS.md b/crates/epiphany-bundle/DECISIONS.md index 9dc4a23..893053b 100644 --- a/crates/epiphany-bundle/DECISIONS.md +++ b/crates/epiphany-bundle/DECISIONS.md @@ -148,6 +148,123 @@ items batched."*). - **Generation exhaustion** returns `BundleError::GenerationExhausted` rather than overflow-panicking at `u64::MAX`. +- **Zstd chunk *reading* is supported; the write path stays uncompressed + (2026-07-01 spec-audit fix).** A spec audit flagged the read paths as the + file-format chapter's only exercised-path MUST violation: Chapter 8 + §"Compression" requires conforming implementations to support *reading* + chunks "compressed with Zstandard at any level zstd defines", but + `read_and_verify_chunk`/`read_and_verify_blob` returned + `UnsupportedCompression` for anything but `None`. They now decompress + `Zstd` payloads (`Reserved` remains `UnsupportedCompression`; the writer + still emits only `None` — the QUICKSTART's compression deferral is about + the *write* path, which the spec leaves as MAY). Decisions taken: + - **Dependency: the `zstd` crate (libzstd bindings), not pure-Rust + `ruzstd`.** (1) `zstd::bulk::decompress_to_buffer` writes into a + caller-allocated buffer sized *exactly* from the declared + `uncompressed_length` — which is validated against the reader's + resource limits *before* allocation — so a hostile stream has a hard + output bound, and libzstd's decoding window is capped internally; + (2) libzstd is the reference implementation, battle-tested against + malformed frames, matching this crate's hostile-input posture; + (3) the workspace already requires a C toolchain (`blake3`'s `cc` + build), so pure Rust bought nothing here; (4) tests need an *encoder* + to produce fixtures and `ruzstd` is decode-only, so picking it would + have pulled `zstd` in anyway as a dev-dependency — two zstd + implementations in one build graph. The read-only mandate is enforced + at the call sites instead: production code never calls the encoder. + - **Length rule (spec: "reject chunks whose decompressed size + disagrees").** The output buffer is sized exactly by the declared + length: a stream that ends short yields a precise + `ChunkLengthMismatch`; one that would exceed the declaration hits + libzstd's destination-full error; malformed, truncated, and + trailing-garbage streams all fail — the latter three as the new typed + `BundleError::Decompression`. No path panics or allocates past the + declaration. Hashing (including the `id == hash` redundancy) is + unchanged and runs strictly *after* decompression, over the + uncompressed bytes — compression stays outside content identity. + - **The manifest stays mandatorily uncompressed** (§"Manifest + Encoding"). The superblock deliberately has no compression field, so + stored manifest bytes are the payload; an image whose manifest bytes + are compressed anyway fails to open (hash mismatch → + `NoValidSuperblock`, or, with a colluding hash over the compressed + bytes, a manifest decode failure). A `ChunkKind::Manifest` *chunk + reference* declaring compression is additionally refused outright with + the new typed `BundleError::CompressedManifest`, before any bytes are + read. + - `CompressionAlgorithm`'s golden-locked two-byte encoding + (`req:format:chunkkind-discriminants`) is untouched; the ratified + discriminants already modeled `Zstd { level } = 1`. + +- **The operation index is implemented with a provisional, golden-locked + payload (Push-3).** Chapter 8 §"The Operation Index" defines the semantics — + an *optional, non-canonical* accelerator mapping each `OperationId` to the + `ChunkRef` of its enclosing block plus an offset within the block, O(log n) + lookup, absent → rebuild by scanning, present-but-corrupt-or-stale → MUST + reject and rebuild — but defers the byte format to the Binary Format + companion (P11-D2). Until that lands, `OperationIndex` encodes under this + crate's fixed codec conventions and the exact bytes are **golden-locked** + (`opindex::tests::payload_encoding_is_golden`), so a layout change breaks + deliberately: + + ```text + u32 block_count + block_count × ChunkRef — strictly ascending canonical order + (kind discriminant, hash, offset) + u32 entry_count + entry_count × { id: [u8;16], block: u32 LE, offset: u32 LE } + — strictly ascending by id bytes + ``` + + `block` is an ordinal into the block vector; `offset` is the byte offset of + the envelope's **first content byte** within the block's *decoded* + (uncompressed) payload — exactly the coordinate `envelope_offsets` reports + (its `u32` length prefix sits at `offset - 4`). Decisions taken: + - **Layering: raw id bytes in the bundle, the peek in ops.** The bundle + stays semantics-free — entries key on the opaque 16 canonical id bytes. + That a canonical envelope *leads* with those bytes is an `epiphany-ops` + invariant, vouched for by ops' `peek_operation_id` (tested against + `encode_canonical`); builders pair it with the bundle's + `envelope_offsets` (which shares `decode_block`'s exact validation) to + produce index entries. The same "ops computes, bundle carries" split as + the block-summary metadata. + - **Reject, never normalize.** `OperationIndex::decode` rejects unsorted or + duplicated blocks or ids, a non-`OperationEnvelopeBlock` reference, an + out-of-range ordinal, and trailing bytes — the manifest decoder's + discipline, so accepted bytes are byte-stable. `build` rejects duplicate + ids (an `OperationId` occupies exactly one slot in one block) and + duplicate blocks at construction. + - **Staleness is coverage equality over full `ChunkRef`s.** + `OperationIndex::covers` is true iff the index's block set equals the + manifest's `operation_roots` set as *full references*, not just chunk + ids: `locate` hands out the index's stored refs for reading, so a ref + agreeing in hash but differing in any locator field (offset, lengths, + compression) is not the manifest's block and must count as stale rather + than steering reads elsewhere. `false` = stale → reject and rebuild. + - **A defective index is never bundle corruption** (Chapter 8 §"Canonical + and Non-Canonical Manifest Roots"). `Bundle::usable_operation_index` + packages the whole discipline: `Some` only for a declared, readable, + hash-intact, well-formed index covering the current operation roots; + `None` on *any* defect, meaning "rebuild by scanning all blocks". + `Bundle::read_operation_index` exposes the underlying failure for + diagnostics only. The testkit proves the boundary: a garbage or + byte-flipped index chunk leaves the bundle opening cleanly with all + canonical reads intact + (`bundle_harness::assert_corrupt_operation_index_is_not_bundle_corruption`). + - **The commit-time SHOULD is a builder, not a policy.** The spec says + writers SHOULD rebuild/update the index at commit when the operation set + has grown significantly. v0 deliberately ships the *mechanism* — + `OperationIndex::build` from per-block `(id bytes, offset)` lists, + `StagedChunk::operation_index`, and the testkit's commit-time + rebuild-and-wire demonstration + (`bundle_harness::assert_operation_index_end_to_end` / + `scan_rebuild_operation_index`) — and no automatic "grown significantly" + heuristic; when/how often to refresh is editor policy layered above this + crate. + - **The write path stays uncompressed.** The spec's *MAY* compress + operation indexes is honored on the read side (an index chunk reads + through the same zstd-capable `read_chunk` path as any chunk); writing + compressed indexes is deferred with the rest of write-path compression. + ## Known v0 limitations (deliberately deferred, not defects) These are bounded by v0 scope (QUICKSTART "Don't do these" / "decisions you'll diff --git a/crates/epiphany-bundle/README.md b/crates/epiphany-bundle/README.md index 822e745..61d6852 100644 --- a/crates/epiphany-bundle/README.md +++ b/crates/epiphany-bundle/README.md @@ -88,8 +88,10 @@ cargo run --release --example fuzz_crash -- 1000000 # extended crash soak ## Scope boundaries (per QUICKSTART "Don't do these") -v0 writes only uncompressed chunks (zstd is deferred; the manifest is -mandatory-uncompressed regardless). It carries the text-projection *root* but does +v0 writes only uncompressed chunks (compression on the *write* path is deferred), +but *reading* zstd-compressed chunks and blobs is supported, per the spec's +§Compression MUST (the manifest is mandatory-uncompressed regardless, and a +compressed manifest is rejected). It carries the text-projection *root* but does not implement the s-expression projection content, and it *preserves* extension declarations and chunks but does not *evaluate* edit barriers — barrier operands (`OperationKindTag`, `ObjectKind`, `EditBarrier`) are owned by Agents C and E. diff --git a/crates/epiphany-bundle/src/block.rs b/crates/epiphany-bundle/src/block.rs index 00b434d..43a30f6 100644 --- a/crates/epiphany-bundle/src/block.rs +++ b/crates/epiphany-bundle/src/block.rs @@ -46,11 +46,53 @@ pub fn encode_block(envelopes: &[Vec]) -> Vec { /// Splits a block payload back into its opaque envelope byte strings. Total and /// bounds-checked: a corrupt payload yields a [`DecodeError`], never a panic. +/// Implemented over [`envelope_offsets`], so the two apply *identical* +/// validation. pub fn decode_block(payload: &[u8]) -> Result>, DecodeError> { + Ok(envelope_offsets(payload)? + .into_iter() + .map(|(_, bytes)| bytes.to_vec()) + .collect()) +} + +/// Splits a block payload into each envelope's `(offset, bytes)` pair, under +/// exactly the validation [`decode_block`] applies (they share one code path). +/// +/// The offset is the byte offset of the envelope's **first content byte** +/// within the uncompressed (decoded) block payload — that is, +/// `payload[offset .. offset + bytes.len()]` *is* the envelope's encoded +/// bytes, and the envelope's `u32` length prefix sits at `offset - 4`. This is +/// the coordinate the operation index records (Chapter 8 §"The Operation +/// Index": the `ChunkRef` of the enclosing block plus an offset within it), +/// deterministically recoverable from the block framing alone. +pub fn envelope_offsets(payload: &[u8]) -> Result, DecodeError> { + // Offsets are recorded as `u32`; a payload past that range is far beyond + // every profile's block bound and unrepresentable in the index. + if payload.len() > u32::MAX as usize { + return Err(DecodeError::Malformed( + "block payload exceeds the u32 offset range", + )); + } let mut r = Reader::new(payload); - let envelopes = r.get_seq(|r| r.get_var_bytes())?; + // Mirror `Reader::get_seq`'s pre-allocation guards: the declared count is + // checked against the bytes remaining (each envelope costs at least its + // length prefix), and the reservation is capped. + const MAX_RESERVE: usize = 1024; + let count = r.get_u32()? as usize; + if count > r.remaining() { + return Err(DecodeError::LengthOverflow { + declared: count as u64, + remaining: r.remaining(), + }); + } + let mut out = Vec::with_capacity(count.min(MAX_RESERVE)); + for _ in 0..count { + let prefix_at = payload.len() - r.remaining(); + let bytes = r.get_var_slice()?; + out.push((prefix_at as u32 + ENVELOPE_FRAMING as u32, bytes)); + } r.finish()?; - Ok(envelopes) + Ok(out) } /// Packs opaque envelope byte strings into block payloads at the 1 MiB soft @@ -109,6 +151,48 @@ mod tests { assert_eq!(decode_block(&payload).unwrap(), envs); } + #[test] + fn envelope_offsets_address_each_first_content_byte() { + let envs = vec![b"aa".to_vec(), b"b".to_vec(), b"cccc".to_vec()]; + let payload = encode_block(&envs); + let got = envelope_offsets(&payload).unwrap(); + assert_eq!(got.len(), 3); + // The first envelope's content begins after the u32 count and its own + // u32 length prefix: offset 8. Each subsequent offset advances by the + // previous content plus the next 4-byte prefix. + assert_eq!(got[0].0, 8); + assert_eq!(got[1].0, 8 + 2 + 4); + assert_eq!(got[2].0, 8 + 2 + 4 + 1 + 4); + for ((off, bytes), env) in got.iter().zip(&envs) { + assert_eq!(bytes, env, "the returned slice is the envelope"); + // The offset definition: payload[offset .. offset+len] IS the + // envelope's encoded bytes within the decoded block payload. + let start = *off as usize; + assert_eq!(&payload[start..start + env.len()], &env[..]); + } + } + + #[test] + fn envelope_offsets_validate_like_decode_block() { + let payload = encode_block(&[b"xyz".to_vec()]); + // Truncation fails both, with the same verdict. + let cut = &payload[..payload.len() - 1]; + assert!(envelope_offsets(cut).is_err()); + assert!(decode_block(cut).is_err()); + // Trailing garbage fails both. + let mut long = payload.clone(); + long.push(0); + assert!(envelope_offsets(&long).is_err()); + assert!(decode_block(&long).is_err()); + // A corrupt count cannot over-allocate in either. + let mut bytes = u32::MAX.to_le_bytes().to_vec(); + bytes.push(0); + assert!(matches!( + envelope_offsets(&bytes), + Err(DecodeError::LengthOverflow { .. }) + )); + } + #[test] fn small_envelopes_share_one_block_and_preserve_order() { let envs: Vec> = (0..100).map(|i| vec![i as u8; 8]).collect(); diff --git a/crates/epiphany-bundle/src/bundle.rs b/crates/epiphany-bundle/src/bundle.rs index fdad198..74bfc7f 100644 --- a/crates/epiphany-bundle/src/bundle.rs +++ b/crates/epiphany-bundle/src/bundle.rs @@ -21,6 +21,7 @@ use crate::error::{BundleError, IntegrityAnomaly}; use crate::header::{FixedHeader, SLOT_A_OFFSET, SLOT_B_OFFSET}; use crate::ids::{BlobId, FileUuid, ReductionAlgorithmVersion, SchemaVersion, WallClockTime}; use crate::manifest::{BlobRef, Manifest, ProfileDeclaration}; +use crate::opindex::OperationIndex; use crate::store::{read_vec, BlockStore, MemStore}; use crate::superblock::{ select_active, CommitState, ProfileId, Slot, SlotParse, SlotReject, Superblock, SUPERBLOCK_LEN, @@ -78,6 +79,19 @@ impl StagedChunk { payload, } } + + /// A staged operation-index chunk at the current schema version (Chapter 8 + /// §"The Operation Index") — a non-canonical accelerator; the payload is an + /// [`OperationIndex::encode`](crate::OperationIndex::encode). v0 writes it + /// uncompressed, like every chunk (the spec's *MAY* compress indexes is a + /// write-path option this version defers). + pub fn operation_index(payload: Vec) -> Self { + StagedChunk { + kind: ChunkKind::OperationIndex, + schema_version: SchemaVersion::V0, + payload, + } + } } /// Context handed to a commit's manifest builder: the previous manifest, the @@ -409,6 +423,47 @@ impl Bundle { block::decode_block(&payload).map_err(BundleError::Decode) } + /// Reads and decodes an operation-index chunk (Chapter 8 §"The Operation + /// Index"). Rejects a reference of the wrong kind; the read itself is + /// bounded by the reader's [`MAX_CHUNK_BYTES`] policy and hash-verified + /// like any chunk read. + /// + /// **The index is not canonical**: a failure here — corrupt bytes, a + /// malformed payload, even an I/O error on the index region — must NOT be + /// treated as bundle corruption. The spec's discipline is *reject and + /// rebuild from blocks*; [`Bundle::usable_operation_index`] packages it + /// (including the staleness check). Call this directly only when the + /// underlying failure itself is wanted, e.g. for diagnostics. + pub fn read_operation_index(&self, r: &ChunkRef) -> Result { + if r.kind != ChunkKind::OperationIndex { + return Err(BundleError::Decode(DecodeError::Malformed( + "chunk reference is not an operation index", + ))); + } + let payload = self.read_chunk(r)?; + OperationIndex::decode(&payload).map_err(BundleError::Decode) + } + + /// The manifest's operation index, if — and only if — it is *usable*: + /// declared, readable, hash-intact, well-formed, and covering exactly the + /// manifest's current `operation_roots` ([`OperationIndex::covers`]). + /// `None` on **any** defect: absent, stale (its block set differs from the + /// operation roots), corrupt, malformed, or unreadable. + /// + /// `None` always means "rebuild by scanning all blocks", never "the bundle + /// is corrupt": the operation index is an acceleration structure, not + /// canonical (Chapter 8 §"The Operation Index"), and failed verification + /// of a non-canonical chunk MUST NOT be surfaced as bundle corruption + /// (Chapter 8 §"Canonical and Non-Canonical Manifest Roots") — the reader + /// discards the index and rebuilds it from the blocks. + pub fn usable_operation_index(&self) -> Option { + let root = self.manifest.operation_index_root.as_ref()?; + let index = self.read_operation_index(root).ok()?; + index + .covers(&self.manifest.operation_roots) + .then_some(index) + } + /// The active profile's maximum uncompressed operation-block size /// (Chapter 8 §"Operation Envelope Blocks"). The *active* profile is the one /// the selected superblock names — a bundle opened under `Lite` must read @@ -753,10 +808,17 @@ fn reduction_version_for(manifest: &Manifest) -> ReductionAlgorithmVersion { /// Reads and fully verifies a chunk against its reference — the shared core of /// [`Bundle::read_chunk`] and the commit-time canonical-root validation. Checks -/// body-placement, schema-major support, declared length, the content hash, and -/// the `id == hash` redundancy (Chapter 8 §"Chunks"). +/// compression support (decompressing zstd payloads), body-placement, +/// schema-major support, declared length, the content hash, and the +/// `id == hash` redundancy (Chapter 8 §"Chunks"). fn read_and_verify_chunk(store: &dyn BlockStore, r: &ChunkRef) -> Result, BundleError> { - if r.compression != CompressionAlgorithm::None { + // The manifest chunk is mandatorily uncompressed in this format version + // (Chapter 8 §"Manifest Encoding"): a compressed manifest reference is + // rejected outright, before any bytes are read. + if r.kind == ChunkKind::Manifest && r.compression != CompressionAlgorithm::None { + return Err(BundleError::CompressedManifest); + } + if let CompressionAlgorithm::Reserved(_) = r.compression { return Err(BundleError::UnsupportedCompression); } // A chunk reference must point into the body, never the fixed prelude. @@ -773,16 +835,11 @@ fn read_and_verify_chunk(store: &dyn BlockStore, r: &ChunkRef) -> Result version: r.schema_version, }); } - // Bound the allocation by the reader's policy before touching the length. + // Bound both allocations by the reader's policy before touching a length. enforce_limit(r.compressed_length, MAX_CHUNK_BYTES)?; enforce_limit(r.uncompressed_length, MAX_CHUNK_BYTES)?; - let payload = read_chunk_bytes(store, r.offset, r.compressed_length)?; - if payload.len() as u64 != r.uncompressed_length { - return Err(BundleError::ChunkLengthMismatch { - expected: r.uncompressed_length, - actual: payload.len() as u64, - }); - } + let stored = read_chunk_bytes(store, r.offset, r.compressed_length)?; + let payload = decode_stored_payload(stored, r.compression, r.uncompressed_length)?; let actual = content_hash_for(r.kind, r.schema_version, &payload); if actual != r.hash { return Err(BundleError::ChunkHashMismatch { @@ -809,13 +866,16 @@ fn read_and_verify_blob( b: &BlobRef, max_bytes: u64, ) -> Result, BundleError> { - if b.compression != CompressionAlgorithm::None { + if let CompressionAlgorithm::Reserved(_) = b.compression { return Err(BundleError::UnsupportedCompression); } let limit = b .declared_max_uncompressed_length .unwrap_or(u64::MAX) .min(max_bytes); + // Chapter 8 §"Blobs": the declared uncompressed length is checked against + // the reader's policy *before decompression begins* (and before any + // allocation keyed on it). enforce_limit(b.uncompressed_length, limit)?; enforce_limit(b.compressed_length, max_bytes)?; if b.offset < BODY_START { @@ -825,13 +885,8 @@ fn read_and_verify_blob( file_len: store.len(), }); } - let payload = read_chunk_bytes(store, b.offset, b.compressed_length)?; - if payload.len() as u64 != b.uncompressed_length { - return Err(BundleError::ChunkLengthMismatch { - expected: b.uncompressed_length, - actual: payload.len() as u64, - }); - } + let stored = read_chunk_bytes(store, b.offset, b.compressed_length)?; + let payload = decode_stored_payload(stored, b.compression, b.uncompressed_length)?; let actual = BlobId::of_payload(&payload).0; if actual != b.hash || b.blob_id.0 != b.hash { return Err(BundleError::ChunkHashMismatch { @@ -851,6 +906,70 @@ fn enforce_limit(length: u64, limit: u64) -> Result<(), BundleError> { } } +/// Recovers a chunk's uncompressed payload from its stored (possibly +/// compressed) bytes, verifying it is *exactly* `declared_len` bytes long +/// (Chapter 8 §"Compression" / §"Chunks": a decompressed size that disagrees +/// with the declared `uncompressed_length` is corruption). The caller has +/// already validated `declared_len` against its resource-limit policy, so +/// every allocation here is bounded. Content hashing happens strictly *after* +/// this step, over the uncompressed bytes — compression is `ChunkRef` +/// metadata, never part of content identity. +fn decode_stored_payload( + stored: Vec, + compression: CompressionAlgorithm, + declared_len: u64, +) -> Result, BundleError> { + match compression { + CompressionAlgorithm::None => { + if stored.len() as u64 != declared_len { + return Err(BundleError::ChunkLengthMismatch { + expected: declared_len, + actual: stored.len() as u64, + }); + } + Ok(stored) + } + // Reading zstd at any level is a conformance MUST (Chapter 8 + // §"Compression"); the declared level byte is advisory metadata the + // decoder does not need. + CompressionAlgorithm::Zstd { .. } => decompress_zstd(&stored, declared_len), + CompressionAlgorithm::Reserved(_) => Err(BundleError::UnsupportedCompression), + } +} + +/// Decompresses a zstd frame sequence into a buffer sized *exactly* by the +/// declared uncompressed length, so a hostile stream can never allocate past +/// the (already limit-checked) declaration: +/// +/// * a stream that would exceed `declared_len` hits libzstd's +/// destination-full error → [`BundleError::Decompression`]; +/// * a stream that ends short of `declared_len` → +/// [`BundleError::ChunkLengthMismatch`]; +/// * a truncated or otherwise malformed stream (including trailing garbage +/// after the final frame) → [`BundleError::Decompression`]. +/// +/// No path panics or allocates beyond `declared_len` plus libzstd's own +/// bounded decoding context (whose window is capped internally). +fn decompress_zstd(stored: &[u8], declared_len: u64) -> Result, BundleError> { + let declared = usize::try_from(declared_len).map_err(|_| { + // Unreachable on 64-bit targets; on narrower ones an unaddressable + // declaration is a resource-limit refusal, not a wrap. + BundleError::ResourceLimitExceeded { + length: declared_len, + limit: usize::MAX as u64, + } + })?; + let mut payload = vec![0u8; declared]; + match zstd::bulk::decompress_to_buffer(stored, payload.as_mut_slice()) { + Ok(n) if n as u64 == declared_len => Ok(payload), + Ok(n) => Err(BundleError::ChunkLengthMismatch { + expected: declared_len, + actual: n as u64, + }), + Err(e) => Err(BundleError::Decompression(e)), + } +} + /// Validates that every canonical root a manifest declares resolves to a /// present, hash-intact chunk of the *right kind and shape* before a commit /// publishes it — so a bundle that opens normally can never carry a dangling, @@ -911,6 +1030,14 @@ fn validate_canonical_roots( /// the body — Chapter 8 fixes the prelude layout, so a "manifest" overlapping a /// header or superblock slot is foreign — and within the reader's manifest size /// limit, before allocating. +/// +/// The manifest chunk is mandatorily *uncompressed* in this format version +/// (Chapter 8 §"Manifest Encoding"): the superblock deliberately carries no +/// compression field, so the stored bytes ARE the payload. A bundle whose +/// manifest bytes are compressed anyway therefore fails downstream as +/// malformed: hash verification (over the uncompressed preimage) rejects the +/// slot, and even a colluding hash-over-compressed-bytes cannot survive +/// `Manifest::decode`. fn read_manifest_payload(store: &dyn BlockStore, sb: &Superblock) -> Result, BundleError> { if sb.manifest_offset < BODY_START { return Err(BundleError::ChunkOutOfBounds { @@ -1857,4 +1984,323 @@ mod tests { Err(BundleError::GenerationExhausted) )); } + + // ------------------------------------------------------------------ + // Zstd read support (Chapter 8 §"Compression": reading zstd-compressed + // chunks is a conformance MUST; this crate's writer still emits only + // uncompressed chunks, so tests plant externally-compressed bytes). + // ------------------------------------------------------------------ + + /// Appends externally-zstd-compressed bytes to the bundle body (as a + /// foreign compressing writer would have) and returns the reference + /// describing them. `declared_len` lets a test lie about the uncompressed + /// length; honest callers pass `payload.len()`. + fn plant_zstd_chunk( + bundle: &mut Bundle, + kind: ChunkKind, + payload: &[u8], + declared_len: u64, + ) -> ChunkRef { + let compressed = zstd::bulk::compress(payload, 3).unwrap(); + let offset = bundle.write_cursor; + bundle.store.write_at(offset, &compressed).unwrap(); + bundle.write_cursor += compressed.len() as u64; + let hash = content_hash_for(kind, SchemaVersion::V0, payload); + ChunkRef { + id: ChunkId(hash), + kind, + schema_version: SchemaVersion::V0, + offset, + compressed_length: compressed.len() as u64, + uncompressed_length: declared_len, + compression: CompressionAlgorithm::Zstd { level: 3 }, + hash, + } + } + + /// Like [`plant_zstd_chunk`], but for a blob (bare `MUSCBLOB` addressing). + fn plant_zstd_blob( + bundle: &mut Bundle, + payload: &[u8], + declared_len: u64, + ) -> BlobRef { + let r = plant_zstd_chunk(bundle, ChunkKind::Blob, payload, declared_len); + BlobRef { + blob_id: BlobId(r.hash), + media_type: "application/octet-stream".to_string(), + offset: r.offset, + compressed_length: r.compressed_length, + uncompressed_length: declared_len, + compression: r.compression, + hash: r.hash, + declared_max_uncompressed_length: None, + } + } + + #[test] + fn zstd_compressed_chunk_round_trips_with_hash_verified() { + // §Compression round-trip: an externally-compressed chunk reads back + // byte-identical, and the content hash is verified over the + // *uncompressed* bytes (the preimage rule: compression is metadata). + let mut bundle = fresh_bundle(); + let payload: Vec = b"layout-cache-bytes ".repeat(64); // compressible + let r = plant_zstd_chunk( + &mut bundle, + ChunkKind::LayoutCache, + &payload, + payload.len() as u64, + ); + assert!( + r.compressed_length < r.uncompressed_length, + "fixture actually compressed" + ); + assert_eq!(bundle.read_chunk(&r).unwrap(), payload); + + // The hash check runs on the decompressed payload: a tampered declared + // hash is caught even though the stored (compressed) bytes are intact. + let mut tampered = r; + tampered.hash = ContentHash([0; 32]); + tampered.id = ChunkId(ContentHash([0; 32])); // keep id == hash + assert!(matches!( + bundle.read_chunk(&tampered), + Err(BundleError::ChunkHashMismatch { .. }) + )); + } + + #[test] + fn compressed_operation_root_commits_and_reopens() { + // End to end: a compressed operation block can be published as a + // canonical root (commit-time validation decompresses + verifies it), + // survives a reopen, and streams back through read_operation_block. + let mut bundle = fresh_bundle(); + let envelopes = vec![b"env-1".to_vec(), b"env-2".to_vec()]; + let payload = block::encode_block(&envelopes); + let root = plant_zstd_chunk( + &mut bundle, + ChunkKind::OperationEnvelopeBlock, + &payload, + payload.len() as u64, + ); + bundle + .commit(&[], |ctx| { + let mut m = ctx.previous_manifest.clone(); + m.operation_roots.push(root); + m + }) + .unwrap(); + + let image = bundle.into_store().into_bytes(); + let reopened = Bundle::open(MemStore::from_bytes(image)).unwrap(); + reopened.verify_canonical_chunks().unwrap(); + let stored_root = reopened.manifest().operation_roots[0]; + assert_eq!( + stored_root.compression, + CompressionAlgorithm::Zstd { level: 3 } + ); + assert_eq!( + reopened.read_operation_block(&stored_root).unwrap(), + envelopes + ); + } + + #[test] + fn zstd_stream_ending_short_of_declared_length_is_rejected() { + // §Compression: "Decompression MUST verify the output length against + // the declared uncompressed_length" — a stream that ends short of the + // declaration is corruption, reported with both lengths. + let mut bundle = fresh_bundle(); + let payload = b"short-stream".to_vec(); + let r = plant_zstd_chunk( + &mut bundle, + ChunkKind::LayoutCache, + &payload, + payload.len() as u64 + 5, // declares more than the stream yields + ); + assert!(matches!( + bundle.read_chunk(&r), + Err(BundleError::ChunkLengthMismatch { + expected: 17, + actual: 12, + }) + )); + } + + #[test] + fn zstd_stream_exceeding_declared_length_is_rejected() { + // The dual failure: a stream that would decompress *past* the declared + // length must be refused without allocating beyond the declaration + // (the output buffer is sized by the declared length, so libzstd hits + // destination-full and errors). + let mut bundle = fresh_bundle(); + let payload: Vec = b"overlong ".repeat(32); + let r = plant_zstd_chunk( + &mut bundle, + ChunkKind::LayoutCache, + &payload, + payload.len() as u64 - 1, // declares less than the stream yields + ); + assert!(matches!( + bundle.read_chunk(&r), + Err(BundleError::Decompression(_)) + )); + } + + #[test] + fn corrupt_or_truncated_zstd_stream_is_a_typed_error() { + let mut bundle = fresh_bundle(); + let payload: Vec = b"to-be-corrupted ".repeat(16); + let r = plant_zstd_chunk( + &mut bundle, + ChunkKind::LayoutCache, + &payload, + payload.len() as u64, + ); + + // Corrupt the frame header magic in the stored bytes: malformed stream. + bundle.store.write_at(r.offset, &[0xFF]).unwrap(); + assert!(matches!( + bundle.read_chunk(&r), + Err(BundleError::Decompression(_)) + )); + + // Truncated stream: same compressed bytes, but the reference claims + // fewer of them than the frame needs. + let mut bundle = fresh_bundle(); + let mut truncated = plant_zstd_chunk( + &mut bundle, + ChunkKind::LayoutCache, + &payload, + payload.len() as u64, + ); + truncated.compressed_length /= 2; + assert!(matches!( + bundle.read_chunk(&truncated), + Err(BundleError::Decompression(_)) + )); + } + + #[test] + fn zstd_compressed_blob_round_trips_and_fails_typed() { + // The blob path shares the decode: round-trip, short-stream, corrupt. + let mut bundle = fresh_bundle(); + let payload: Vec = b"blob-audio-bytes ".repeat(64); + let b = plant_zstd_blob(&mut bundle, &payload, payload.len() as u64); + assert_eq!(bundle.read_blob(&b).unwrap(), payload); + + // Declared length beyond the stream's yield → typed error. + let mut short = b.clone(); + short.uncompressed_length = payload.len() as u64 + 3; + assert!(matches!( + bundle.read_blob(&short), + Err(BundleError::ChunkLengthMismatch { .. }) + )); + + // The declared_max cap still applies *before* decompression begins. + let mut capped = b.clone(); + capped.declared_max_uncompressed_length = Some(4); + assert!(matches!( + bundle.read_blob(&capped), + Err(BundleError::ResourceLimitExceeded { .. }) + )); + + // Corrupt stored stream → typed error, no panic. + bundle.store.write_at(b.offset, &[0xFF]).unwrap(); + assert!(matches!( + bundle.read_blob(&b), + Err(BundleError::Decompression(_)) + )); + } + + #[test] + fn reserved_compression_is_still_unsupported() { + // §Compression: Reserved algorithms belong to future format majors. + let mut bundle = fresh_bundle(); + op_block(&mut bundle, &[b"env"]); + let mut r = bundle.manifest().operation_roots[0]; + r.compression = CompressionAlgorithm::Reserved(7); + assert!(matches!( + bundle.read_chunk(&r), + Err(BundleError::UnsupportedCompression) + )); + + commit_blob(&mut bundle, b"blob"); + let mut b = bundle.manifest().blob_roots[0].clone(); + b.compression = CompressionAlgorithm::Reserved(7); + assert!(matches!( + bundle.read_blob(&b), + Err(BundleError::UnsupportedCompression) + )); + } + + #[test] + fn compressed_manifest_chunk_ref_is_rejected() { + // §Manifest Encoding: the manifest chunk MUST be stored uncompressed in + // this format version. A manifest reference declaring compression is + // refused outright — even when the compressed bytes are a perfectly + // valid zstd stream of a perfectly valid manifest. + let mut bundle = fresh_bundle(); + let manifest_payload = Manifest::empty(DocumentId([7; 16])).encode(); + let r = plant_zstd_chunk( + &mut bundle, + ChunkKind::Manifest, + &manifest_payload, + manifest_payload.len() as u64, + ); + assert!(matches!( + bundle.read_chunk(&r), + Err(BundleError::CompressedManifest) + )); + } + + /// A minimal image whose superblock points at `stored` as the manifest + /// payload, declaring `manifest_hash` for it. + fn craft_image_with_manifest_bytes(stored: &[u8], manifest_hash: ContentHash) -> Vec { + let mut image = vec![0u8; BODY_START as usize]; + image.extend_from_slice(stored); + let sb = Superblock { + generation: 0, + manifest_offset: BODY_START, + manifest_length: stored.len() as u64, + manifest_hash, + manifest_schema_version: SchemaVersion::V0, + reduction_algorithm_version: ReductionAlgorithmVersion(0), + profile_id: ProfileId::Full, + commit_state: CommitState::Committed, + commit_timestamp: WallClockTime(0), + }; + image[0..crate::header::HEADER_LEN as usize] + .copy_from_slice(&FixedHeader::new(FileUuid([1; 16])).encode()); + image[SLOT_A_OFFSET as usize..SLOT_A_OFFSET as usize + SUPERBLOCK_LEN as usize] + .copy_from_slice(&sb.encode()); + image + } + + #[test] + fn open_rejects_a_bundle_whose_manifest_bytes_are_compressed() { + // §Manifest Encoding: "Implementations MUST reject as malformed any + // bundle whose manifest payload is not directly parseable as a + // canonical manifest chunk's uncompressed bytes." The superblock + // carries no compression field, so the stored bytes are treated as the + // payload — a compressed manifest fails with a typed error either way + // a hostile writer declares its hash. + let payload = Manifest::empty(DocumentId([1; 16])).encode(); + let compressed = zstd::bulk::compress(&payload, 3).unwrap(); + + // (a) Hash declared over the true (uncompressed) manifest content: + // the stored bytes fail hash verification → no valid superblock. + let image = craft_image_with_manifest_bytes(&compressed, manifest_chunk_hash(&payload)); + assert!(matches!( + Bundle::open(MemStore::from_bytes(image)), + Err(BundleError::NoValidSuperblock) + )); + + // (b) Colluding hash over the compressed bytes: the slot verifies, but + // the payload is not parseable as a manifest → rejected as + // malformed. + let image = craft_image_with_manifest_bytes(&compressed, manifest_chunk_hash(&compressed)); + assert!(matches!( + Bundle::open(MemStore::from_bytes(image)), + Err(BundleError::Decode(_)) + )); + } } diff --git a/crates/epiphany-bundle/src/chunk.rs b/crates/epiphany-bundle/src/chunk.rs index 5414f1a..1c78f48 100644 --- a/crates/epiphany-bundle/src/chunk.rs +++ b/crates/epiphany-bundle/src/chunk.rs @@ -109,15 +109,18 @@ impl ChunkKind { } /// Per-chunk compression metadata (Chapter 8 §"Compression"). **Not** part of -/// content identity. v0 writes only [`CompressionAlgorithm::None`] (the -/// QUICKSTART defers compression: *"Don't implement compression in the bundle … -/// add zstd later as a non-breaking minor version"*); the other variants are -/// modeled for forward compatibility and reading. +/// content identity. v0 *writes* only [`CompressionAlgorithm::None`] (the +/// QUICKSTART defers compression on the write path: *"Don't implement +/// compression in the bundle … add zstd later as a non-breaking minor +/// version"*), but *reading* zstd-compressed chunks is a conformance MUST and +/// is supported. The manifest chunk is mandatorily uncompressed either way +/// (Chapter 8 §"Manifest Encoding"). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum CompressionAlgorithm { /// No compression. Stored bytes equal the uncompressed payload. None, - /// Zstandard at the given level. (Reading is deferred in v0.) + /// Zstandard at the given level. Readers MUST support any level zstd + /// defines; the level byte is writer metadata the decoder does not need. Zstd { level: u8 }, /// Reserved for future format major versions. Reserved(u8), diff --git a/crates/epiphany-bundle/src/codec.rs b/crates/epiphany-bundle/src/codec.rs index e35b232..a201622 100644 --- a/crates/epiphany-bundle/src/codec.rs +++ b/crates/epiphany-bundle/src/codec.rs @@ -309,9 +309,13 @@ impl<'a> Reader<'a> { Ok(i64::from_le_bytes(self.take_array()?)) } - /// A `u32`-length-prefixed byte string, copied out. The length prefix is - /// checked against the bytes remaining *before* any allocation. - pub fn get_var_bytes(&mut self) -> Result, DecodeError> { + /// A `u32`-length-prefixed byte string, *borrowed* from the input rather + /// than copied. The length prefix is checked against the bytes remaining + /// before the slice is taken. The zero-copy counterpart of + /// [`Reader::get_var_bytes`], for callers that need positions or slices + /// into the original buffer (e.g. the per-envelope offsets the operation + /// index records). + pub fn get_var_slice(&mut self) -> Result<&'a [u8], DecodeError> { let len = self.get_u32()? as usize; if len > self.remaining() { return Err(DecodeError::LengthOverflow { @@ -319,7 +323,13 @@ impl<'a> Reader<'a> { remaining: self.remaining(), }); } - Ok(self.take(len)?.to_vec()) + self.take(len) + } + + /// A `u32`-length-prefixed byte string, copied out. The length prefix is + /// checked against the bytes remaining *before* any allocation. + pub fn get_var_bytes(&mut self) -> Result, DecodeError> { + Ok(self.get_var_slice()?.to_vec()) } /// A `u32`-length-prefixed UTF-8 string. diff --git a/crates/epiphany-bundle/src/error.rs b/crates/epiphany-bundle/src/error.rs index b5f62eb..e3db922 100644 --- a/crates/epiphany-bundle/src/error.rs +++ b/crates/epiphany-bundle/src/error.rs @@ -83,10 +83,24 @@ pub enum BundleError { /// an untrusted length in a (possibly sparse) file cannot drive an OOM. ResourceLimitExceeded { length: u64, limit: u64 }, - /// A compressed chunk was encountered. v0 writes only uncompressed chunks - /// and does not implement decompression (QUICKSTART: zstd is deferred). + /// A chunk declared a `Reserved` compression algorithm. This format version + /// defines only `None` and `Zstd`; further algorithms require a new format + /// major version (Chapter 8 §"Compression"). UnsupportedCompression, + /// A zstd-compressed chunk's stream failed to decompress: malformed, + /// truncated, or producing more bytes than the declared + /// `uncompressed_length` (Chapter 8 §"Compression": decompression MUST + /// verify the output length against the declared length). Surfaced as + /// typed corruption — never a panic or an unbounded allocation. + Decompression(std::io::Error), + + /// A manifest chunk reference declared compression. The manifest chunk + /// MUST be stored uncompressed in this format version (Chapter 8 + /// §"Manifest Encoding"): it is the bootstrap entry into the chunk graph, + /// decodable from header + superblock information alone. + CompressedManifest, + /// A chunk declared a schema major version this reader cannot parse /// (Chapter 8 §"Schema Versioning"). UnsupportedSchemaVersion { version: SchemaVersion }, @@ -154,9 +168,13 @@ impl core::fmt::Display for BundleError { "declared length {length} exceeds the reader limit {limit}" ) } - BundleError::UnsupportedCompression => { - f.write_str("compressed chunk encountered; v0 supports only uncompressed chunks") - } + BundleError::UnsupportedCompression => f.write_str( + "reserved compression algorithm; this format version defines None and Zstd", + ), + BundleError::Decompression(e) => write!(f, "zstd decompression failed: {e}"), + BundleError::CompressedManifest => f.write_str( + "manifest chunk is compressed; the manifest MUST be stored uncompressed in this format version", + ), BundleError::UnsupportedSchemaVersion { version } => { write!( f, @@ -177,6 +195,7 @@ impl std::error::Error for BundleError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { BundleError::Io(e) => Some(e), + BundleError::Decompression(e) => Some(e), BundleError::Decode(e) => Some(e), _ => None, } diff --git a/crates/epiphany-bundle/src/lib.rs b/crates/epiphany-bundle/src/lib.rs index 439f4ed..9c3e9bd 100644 --- a/crates/epiphany-bundle/src/lib.rs +++ b/crates/epiphany-bundle/src/lib.rs @@ -37,10 +37,12 @@ //! //! ## Scope (per QUICKSTART "Don't do these") //! -//! v0 writes only uncompressed chunks (zstd is deferred), does not implement the -//! text-projection *content* (only carries its root), and does not *evaluate* -//! edit barriers (their operand types live in other crates). The manifest is -//! mandatory-uncompressed in this format version regardless. See `DECISIONS.md` +//! v0 writes only uncompressed chunks (compression on write is deferred), but +//! *reads* zstd-compressed chunks and blobs, as the spec's §Compression MUST +//! requires. It does not implement the text-projection *content* (only carries +//! its root), and does not *evaluate* edit barriers (their operand types live +//! in other crates). The manifest is mandatory-uncompressed in this format +//! version regardless, and a compressed manifest is rejected. See `DECISIONS.md` //! for the prototype byte-layout choices that anticipate the deferred Binary //! Format companion, and the batched Pass 11 candidates. @@ -53,13 +55,15 @@ mod error; mod header; mod ids; mod manifest; +mod opindex; mod store; mod superblock; pub mod fuzz; pub use block::{ - decode_block, encode_block, pack_operation_blocks, BLOCK_SOFT_LIMIT, MAX_BLOCK_DEFAULT, + decode_block, encode_block, envelope_offsets, pack_operation_blocks, BLOCK_SOFT_LIMIT, + MAX_BLOCK_DEFAULT, }; pub use bundle::{ manifest_chunk_hash, Bundle, CommitContext, StagedChunk, BODY_START, MAX_BLOB_BYTES, @@ -87,6 +91,9 @@ pub use manifest::{ BlobRef, ExtensionDeclaration, Manifest, OperationBlockSummary, ProfileConstraints, ProfileDeclaration, RetentionPolicy, SnapshotRef, }; +pub use opindex::{ + IndexedBlock, OperationIdBytes, OperationIndex, OperationIndexBuildError, OperationIndexEntry, +}; pub use store::{BlockStore, CrashPoint, FaultStore, MemStore, Tear}; pub use superblock::{ select_active, CommitState, ProfileId, Selection, Slot, SlotParse, SlotReject, Superblock, diff --git a/crates/epiphany-bundle/src/opindex.rs b/crates/epiphany-bundle/src/opindex.rs new file mode 100644 index 0000000..d10a1f4 --- /dev/null +++ b/crates/epiphany-bundle/src/opindex.rs @@ -0,0 +1,504 @@ +//! The operation index (Chapter 8 §"The Operation Index"). +//! +//! An optional chunk of kind [`ChunkKind::OperationIndex`] mapping each +//! operation id to the [`ChunkRef`] of its enclosing operation-envelope block +//! plus a byte offset within the block, for O(log n) lookup of an operation +//! without scanning every block. It is **an acceleration structure, not +//! canonical**: *"If absent, readers rebuild it by scanning all blocks. If +//! present but corrupt or stale, readers MUST reject the index and rebuild +//! from blocks"* — and failed verification of a non-canonical chunk is *not* +//! bundle corruption (Chapter 8 §"Canonical and Non-Canonical Manifest +//! Roots"). [`crate::Bundle::usable_operation_index`] packages that +//! reject-and-rebuild discipline. +//! +//! ## Layering +//! +//! The bundle stays semantics-free: entries key on the **raw 16 canonical +//! bytes** of an operation id, which the bundle never interprets. That the +//! leading 16 bytes of a canonically encoded envelope *are* its operation id +//! is an `epiphany-ops` invariant, vouched for by ops' `peek_operation_id`; +//! index builders pair that helper with [`crate::envelope_offsets`] to produce +//! this module's `(id bytes, offset)` inputs. +//! +//! ## Provisional payload layout (see `DECISIONS.md`) +//! +//! The spec defers the index's byte format to the Binary Format companion; the +//! encoding here is a deterministic, golden-locked prototype under the crate's +//! codec conventions: +//! +//! ```text +//! u32 block_count +//! block_count × ChunkRef — strictly ascending canonical order +//! u32 entry_count +//! entry_count × { id: [u8;16], block: u32, offset: u32 } +//! — strictly ascending by id bytes +//! ``` +//! +//! `block` is an ordinal into the block vector; `offset` is the byte offset of +//! the envelope's first content byte within the block's *decoded* +//! (uncompressed) payload, exactly as [`crate::envelope_offsets`] reports it. +//! The decoder **rejects** non-canonical bytes (unsorted or duplicated blocks +//! or ids, out-of-range ordinals, wrong-kind block references, trailing +//! bytes) rather than normalizing — the manifest decoder's discipline. + +use crate::chunk::{ChunkKind, ChunkRef}; +use crate::codec::{DecodeError, Reader, Writer}; + +/// The raw 16 canonical bytes of an operation id. Opaque to the bundle (the +/// semantics-free layering split): ops' `peek_operation_id` is what vouches +/// that an envelope's leading 16 bytes are its id. +pub type OperationIdBytes = [u8; 16]; + +/// One [`OperationIndex::build`] input: an operation-envelope block's +/// [`ChunkRef`] plus, for each envelope it contains, the envelope's id bytes +/// and its offset within the decoded block payload (the +/// [`crate::envelope_offsets`] coordinate). +pub type IndexedBlock = (ChunkRef, Vec<(OperationIdBytes, u32)>); + +/// One index entry: an operation id (raw canonical bytes — the bundle never +/// interprets them), the ordinal of its enclosing block in the index's block +/// vector, and the byte offset of the envelope's first content byte within +/// that block's decoded payload. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct OperationIndexEntry { + /// The operation's 16 canonical id bytes (opaque to the bundle). + pub id: [u8; 16], + /// Ordinal into [`OperationIndex::blocks`] of the enclosing block. + pub block: u32, + /// Byte offset of the envelope's first content byte within the block's + /// decoded payload (`crate::envelope_offsets` coordinates). + pub offset: u32, +} + +/// Why [`OperationIndex::build`] refused its inputs. Building is the writer's +/// act, so these are writer bugs — unlike a decode failure, which is just an +/// unusable (discard-and-rebuild) index. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum OperationIndexBuildError { + /// An operation id was supplied under two blocks (or twice in one block). + /// An `OperationId` names exactly one slot, so it lives in exactly one + /// enclosing block; two coordinates for one id is a builder bug. + DuplicateOperationId([u8; 16]), + /// The same block reference was supplied twice: the block set is a set. + DuplicateBlock, + /// A supplied block reference is not an operation-envelope block. + NotAnOperationBlock, +} + +impl core::fmt::Display for OperationIndexBuildError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + OperationIndexBuildError::DuplicateOperationId(id) => { + write!(f, "operation id {id:02x?} indexed more than once") + } + OperationIndexBuildError::DuplicateBlock => { + f.write_str("the same block reference was supplied twice") + } + OperationIndexBuildError::NotAnOperationBlock => { + f.write_str("an index block reference is not an operation-envelope block") + } + } + } +} + +impl std::error::Error for OperationIndexBuildError {} + +/// The decoded operation index. Construct via [`OperationIndex::build`] (the +/// writer path) or [`OperationIndex::decode`] (the reader path); both uphold +/// the canonical-order invariants [`OperationIndex::locate`]'s binary search +/// relies on. +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct OperationIndex { + /// The indexed operation-envelope blocks, in canonical [`ChunkRef`] order. + blocks: Vec, + /// The entries, strictly ascending by id bytes. + entries: Vec, +} + +impl OperationIndex { + /// Builds an index from per-block entry lists: for each operation-envelope + /// block's [`ChunkRef`], the `(id bytes, offset)` of every envelope it + /// contains (as `peek_operation_id` over [`crate::envelope_offsets`] + /// yields them). Usable at commit time from the [`ChunkRef`]s a commit's + /// builder closure receives. Blocks are put into canonical order and the + /// entry ordinals remapped accordingly; duplicate ids, duplicate blocks, + /// and wrong-kind block references are rejected. + pub fn build(blocks: &[IndexedBlock]) -> Result { + assert!( + blocks.len() <= u32::MAX as usize, + "block count {} overflows the u32 ordinal space", + blocks.len() + ); + if blocks + .iter() + .any(|(r, _)| r.kind != ChunkKind::OperationEnvelopeBlock) + { + return Err(OperationIndexBuildError::NotAnOperationBlock); + } + + // Canonical block order (ChunkRef's total Ord), remembering where each + // input block landed so entry ordinals can be remapped. + let mut order: Vec = (0..blocks.len()).collect(); + order.sort_by(|&a, &b| blocks[a].0.cmp(&blocks[b].0)); + if order.windows(2).any(|w| blocks[w[0]].0 == blocks[w[1]].0) { + return Err(OperationIndexBuildError::DuplicateBlock); + } + let mut ordinal_of = vec![0u32; blocks.len()]; + for (ordinal, &input) in order.iter().enumerate() { + ordinal_of[input] = ordinal as u32; + } + let sorted_blocks: Vec = order.iter().map(|&i| blocks[i].0).collect(); + + let mut entries: Vec = Vec::new(); + for (i, (_, ids)) in blocks.iter().enumerate() { + entries.extend(ids.iter().map(|&(id, offset)| OperationIndexEntry { + id, + block: ordinal_of[i], + offset, + })); + } + entries.sort_by_key(|e| e.id); + if let Some(w) = entries.windows(2).find(|w| w[0].id == w[1].id) { + return Err(OperationIndexBuildError::DuplicateOperationId(w[0].id)); + } + + Ok(OperationIndex { + blocks: sorted_blocks, + entries, + }) + } + + /// Encodes the index to its (provisional, golden-locked) canonical chunk + /// payload. Deterministic: [`OperationIndex::build`]/[`OperationIndex::decode`] + /// established the canonical orders, so re-encoding is byte-stable. + pub fn encode(&self) -> Vec { + let mut w = Writer::new(); + w.put_seq(&self.blocks, |w, b| b.encode(w)); + w.put_seq(&self.entries, |w, e| { + w.put_bytes(&e.id); + w.put_u32(e.block); + w.put_u32(e.offset); + }); + w.into_bytes() + } + + /// Decodes an index payload, **rejecting** (never normalizing) any + /// non-canonical form: unsorted or duplicated blocks or entry ids, a + /// non-operation-block reference, an out-of-range block ordinal, or + /// trailing bytes. A rejection means the index is unusable and must be + /// rebuilt from blocks — it is *not* bundle corruption (the index is + /// non-canonical). + pub fn decode(bytes: &[u8]) -> Result { + let mut r = Reader::new(bytes); + let blocks = r.get_seq(ChunkRef::decode)?; + let entries = r.get_seq(|r| { + Ok(OperationIndexEntry { + id: r.take_array::<16>()?, + block: r.get_u32()?, + offset: r.get_u32()?, + }) + })?; + r.finish()?; + + if blocks + .iter() + .any(|b| b.kind != ChunkKind::OperationEnvelopeBlock) + { + return Err(DecodeError::Malformed( + "operation index references a non-operation-block chunk", + )); + } + // Strictly ascending (so also duplicate-free) in both vectors. + if blocks.windows(2).any(|w| w[0] >= w[1]) { + return Err(DecodeError::Malformed( + "operation index blocks are not strictly canonically ordered", + )); + } + if entries.windows(2).any(|w| w[0].id >= w[1].id) { + return Err(DecodeError::Malformed( + "operation index entries are not strictly ascending by id", + )); + } + if entries.iter().any(|e| e.block as usize >= blocks.len()) { + return Err(DecodeError::Malformed( + "operation index entry names an out-of-range block ordinal", + )); + } + Ok(OperationIndex { blocks, entries }) + } + + /// Locates an operation by its 16 canonical id bytes: the [`ChunkRef`] of + /// its enclosing block and the byte offset of the envelope's first content + /// byte within that block's decoded payload. Binary search — the O(log n) + /// lookup the spec names as the index's purpose. + pub fn locate(&self, id: &[u8; 16]) -> Option<(&ChunkRef, u32)> { + let i = self.entries.binary_search_by(|e| e.id.cmp(id)).ok()?; + let e = &self.entries[i]; + Some((&self.blocks[e.block as usize], e.offset)) + } + + /// Whether this index covers exactly the given operation roots — the + /// staleness gate (Chapter 8 §"The Operation Index": a stale index MUST be + /// rejected and rebuilt). True iff the index's block set equals the root + /// set as **full [`ChunkRef`]s** (not just chunk ids): `locate` hands out + /// the index's *stored* references for reading, so a reference agreeing in + /// content hash but differing in any locator field (offset, lengths, + /// compression) is not the manifest's block and must count as stale rather + /// than silently steering reads elsewhere. `false` = stale: reject and + /// rebuild from blocks; it is *not* bundle corruption. + pub fn covers(&self, operation_roots: &[ChunkRef]) -> bool { + // The index's own blocks are strictly sorted; canonicalize the roots + // the same way (a decoded manifest's roots already are — this only + // shields against hand-assembled inputs). + let mut roots = operation_roots.to_vec(); + roots.sort(); + roots.dedup(); + roots == self.blocks + } + + /// The indexed blocks, in canonical order. + pub fn blocks(&self) -> &[ChunkRef] { + &self.blocks + } + + /// The entries, strictly ascending by id bytes. + pub fn entries(&self) -> &[OperationIndexEntry] { + &self.entries + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::chunk::CompressionAlgorithm; + use crate::ids::SchemaVersion; + use epiphany_determinism::{ChunkId, ContentHash}; + + fn block_ref(hash_byte: u8, offset: u64, len: u64) -> ChunkRef { + ChunkRef { + id: ChunkId(ContentHash([hash_byte; 32])), + kind: ChunkKind::OperationEnvelopeBlock, + schema_version: SchemaVersion::V0, + offset, + compressed_length: len, + uncompressed_length: len, + compression: CompressionAlgorithm::None, + hash: ContentHash([hash_byte; 32]), + } + } + + fn sample() -> OperationIndex { + OperationIndex::build(&[ + (block_ref(0x22, 1000, 64), vec![([3; 16], 8), ([1; 16], 40)]), + (block_ref(0x11, 576, 32), vec![([2; 16], 8)]), + ]) + .expect("valid build inputs") + } + + #[test] + fn payload_encoding_is_golden() { + // PROVISIONAL golden lock (DECISIONS.md "Operation index"): the byte + // form awaits Binary Format companion ratification, but until then it + // is deterministic and locked — a layout change must break here + // deliberately. The expected bytes are spelled out literally. + let index = + OperationIndex::build(&[(block_ref(0x11, 576, 64), vec![([2; 16], 8), ([1; 16], 44)])]) + .expect("valid build inputs"); + + let mut expected: Vec = Vec::new(); + // u32 block count = 1. + expected.extend_from_slice(&[1, 0, 0, 0]); + // ChunkRef: id (32 raw bytes) … + expected.extend_from_slice(&[0x11; 32]); + // … kind discriminant (OperationEnvelopeBlock = 0) … + expected.push(0); + // … schema version 0.1 (u16 major LE, u16 minor LE) … + expected.extend_from_slice(&[0, 0, 1, 0]); + // … offset 576 (u64 LE), compressed and uncompressed length 64 … + expected.extend_from_slice(&[0x40, 0x02, 0, 0, 0, 0, 0, 0]); + expected.extend_from_slice(&[64, 0, 0, 0, 0, 0, 0, 0]); + expected.extend_from_slice(&[64, 0, 0, 0, 0, 0, 0, 0]); + // … compression None (discriminant 0, parameter 0) … + expected.extend_from_slice(&[0, 0]); + // … restated hash (32 raw bytes). + expected.extend_from_slice(&[0x11; 32]); + // u32 entry count = 2; entries ascend by id bytes. + expected.extend_from_slice(&[2, 0, 0, 0]); + // Entry { id [1;16], block ordinal 0 (u32 LE), offset 44 (u32 LE) }. + expected.extend_from_slice(&[1; 16]); + expected.extend_from_slice(&[0, 0, 0, 0]); + expected.extend_from_slice(&[44, 0, 0, 0]); + // Entry { id [2;16], block ordinal 0, offset 8 }. + expected.extend_from_slice(&[2; 16]); + expected.extend_from_slice(&[0, 0, 0, 0]); + expected.extend_from_slice(&[8, 0, 0, 0]); + + assert_eq!(index.encode(), expected); + } + + #[test] + fn empty_index_round_trips() { + let empty = OperationIndex::build(&[]).expect("empty build"); + let bytes = empty.encode(); + // Two zero u32 counts. + assert_eq!(bytes, vec![0, 0, 0, 0, 0, 0, 0, 0]); + let decoded = OperationIndex::decode(&bytes).expect("decodes"); + assert_eq!(decoded, empty); + assert!(decoded.covers(&[])); + assert_eq!(decoded.locate(&[0; 16]), None); + } + + #[test] + fn round_trips_and_reencodes_byte_stably() { + let index = sample(); + let bytes = index.encode(); + let decoded = OperationIndex::decode(&bytes).expect("decodes"); + assert_eq!(decoded, index); + assert_eq!(decoded.encode(), bytes, "re-encode must be byte-identical"); + } + + #[test] + fn build_sorts_blocks_canonically_and_remaps_ordinals() { + // Inputs arrive with the higher-hash block first; build must order by + // the canonical ChunkRef key and keep each entry pointing at its own + // block through the remapped ordinal. + let index = sample(); + assert_eq!(index.blocks()[0].hash.as_bytes()[0], 0x11); + assert_eq!(index.blocks()[1].hash.as_bytes()[0], 0x22); + let (b, off) = index.locate(&[2; 16]).expect("hit"); + assert_eq!((b.hash.as_bytes()[0], off), (0x11, 8)); + let (b, off) = index.locate(&[1; 16]).expect("hit"); + assert_eq!((b.hash.as_bytes()[0], off), (0x22, 40)); + let (b, off) = index.locate(&[3; 16]).expect("hit"); + assert_eq!((b.hash.as_bytes()[0], off), (0x22, 8)); + } + + #[test] + fn locate_misses_an_unknown_id() { + assert_eq!(sample().locate(&[9; 16]), None); + } + + #[test] + fn build_rejects_duplicate_ids_blocks_and_wrong_kinds() { + // The same id under two blocks: one operation, one slot. + assert_eq!( + OperationIndex::build(&[ + (block_ref(0x11, 576, 32), vec![([1; 16], 8)]), + (block_ref(0x22, 1000, 32), vec![([1; 16], 8)]), + ]), + Err(OperationIndexBuildError::DuplicateOperationId([1; 16])) + ); + // The same block twice: the block set is a set. + assert_eq!( + OperationIndex::build(&[ + (block_ref(0x11, 576, 32), vec![([1; 16], 8)]), + (block_ref(0x11, 576, 32), vec![([2; 16], 8)]), + ]), + Err(OperationIndexBuildError::DuplicateBlock) + ); + // A non-operation-block reference. + let mut wrong = block_ref(0x11, 576, 32); + wrong.kind = ChunkKind::Snapshot; + assert_eq!( + OperationIndex::build(&[(wrong, vec![])]), + Err(OperationIndexBuildError::NotAnOperationBlock) + ); + } + + #[test] + fn decode_rejects_unsorted_blocks() { + // Hand-assemble an index whose blocks are out of canonical order; + // encode trusts the construction, so decode must be the gate. + let bad = OperationIndex { + blocks: vec![block_ref(0x22, 1000, 32), block_ref(0x11, 576, 32)], + entries: vec![], + }; + assert_eq!( + OperationIndex::decode(&bad.encode()), + Err(DecodeError::Malformed( + "operation index blocks are not strictly canonically ordered" + )) + ); + // Duplicates violate *strict* ascent too. + let dup = OperationIndex { + blocks: vec![block_ref(0x11, 576, 32), block_ref(0x11, 576, 32)], + entries: vec![], + }; + assert!(OperationIndex::decode(&dup.encode()).is_err()); + } + + #[test] + fn decode_rejects_unsorted_or_duplicate_entries() { + let entry = |id: u8, block: u32| OperationIndexEntry { + id: [id; 16], + block, + offset: 8, + }; + let unsorted = OperationIndex { + blocks: vec![block_ref(0x11, 576, 32)], + entries: vec![entry(2, 0), entry(1, 0)], + }; + assert!(OperationIndex::decode(&unsorted.encode()).is_err()); + let duplicated = OperationIndex { + blocks: vec![block_ref(0x11, 576, 32)], + entries: vec![entry(1, 0), entry(1, 0)], + }; + assert!(OperationIndex::decode(&duplicated.encode()).is_err()); + } + + #[test] + fn decode_rejects_out_of_range_ordinals_wrong_kinds_and_trailing_bytes() { + let out_of_range = OperationIndex { + blocks: vec![block_ref(0x11, 576, 32)], + entries: vec![OperationIndexEntry { + id: [1; 16], + block: 1, // only ordinal 0 exists + offset: 8, + }], + }; + assert_eq!( + OperationIndex::decode(&out_of_range.encode()), + Err(DecodeError::Malformed( + "operation index entry names an out-of-range block ordinal" + )) + ); + + let mut wrong = block_ref(0x11, 576, 32); + wrong.kind = ChunkKind::Snapshot; + let wrong_kind = OperationIndex { + blocks: vec![wrong], + entries: vec![], + }; + assert_eq!( + OperationIndex::decode(&wrong_kind.encode()), + Err(DecodeError::Malformed( + "operation index references a non-operation-block chunk" + )) + ); + + let mut trailing = sample().encode(); + trailing.push(0); + assert_eq!( + OperationIndex::decode(&trailing), + Err(DecodeError::TrailingBytes { remaining: 1 }) + ); + } + + #[test] + fn covers_is_exact_set_equality_over_full_refs() { + let index = sample(); + let a = block_ref(0x11, 576, 32); + let b = block_ref(0x22, 1000, 64); + // Equal set (any input order; duplicates collapse). + assert!(index.covers(&[b, a])); + assert!(index.covers(&[a, b, a])); + // Subset / superset are stale. + assert!(!index.covers(&[a])); + assert!(!index.covers(&[a, b, block_ref(0x33, 2000, 8)])); + // Same content hash at a different locator is stale: the index would + // hand out a reference that is not the manifest's block. + let mut moved = b; + moved.offset = 4096; + assert!(!index.covers(&[a, moved])); + } +} diff --git a/crates/epiphany-core/DECISIONS.md b/crates/epiphany-core/DECISIONS.md index 0b5fdcd..6a1256b 100644 --- a/crates/epiphany-core/DECISIONS.md +++ b/crates/epiphany-core/DECISIONS.md @@ -337,3 +337,74 @@ Phase 2). The rule itself is value-independent and final. question). H spells pitches region-independently (pitch identity does not depend on the time model) but performs no region-specific aleatoric spelling; defer if the algorithm does not generalise cleanly. + +## Audit follow-up (2026-07-01): decomposition precedence + typed inversion tolerance + +### Authored decomposition attachments outrank the pre-pass (`resolve_decomposition`) + +Audit finding: `infer_decompositions` never consulted +`Score.decomposition_attachments`, so an authored decomposition was silently +shadowed by the derived one — violating Chapter 3 §"Sounding Duration and +Notational Decomposition": the pre-pass "produces inferred decompositions for +events that **lack a higher-precedence attachment**", with the "same sources, +same precedence machinery, same pre-pass discipline" as spelling. + +Fixed by `resolve_decomposition`, the decomposition analogue of +`resolve_spelling`: for each event the pre-pass inferred a decomposition for, +an authored `DecompositionAttachment` targeting that event whose source +**outranks `Inferred`** replaces the derived one in +`DerivedAnnotations.decompositions` (the effective attachment keeps its +authored source, so provenance is visible and enters the derivation +fingerprint). Precedence is the spec's default source order — `UserChosen > +Imported > Propagated > Inferred` — as a fixed rank, because the graph model +carries **no** `DecompositionPrecedence` configuration and the attachment has +no `priority`/`layer` axes (unlike `SpellingAttachment`); among competing +authored attachments the lowest rank wins, and a full rank tie keeps the first +in the score's canonical (codec-fixed) `decomposition_attachments` order, so +resolution is deterministic across replicas. + +**Taxonomy decision:** authored-override events are counted **distinctly** in a +new `TaxonomyReport::decompositions_authored` bucket (mirroring +`spellings_authored`); `decompositions_inferred` now counts only events whose +*effective* decomposition is the pre-pass's own. The effective map size equals +`decompositions_inferred + decompositions_authored` (the H harness's accounting +check was updated accordingly). The new bucket is serialized in +`DerivedAnnotations::canonical_fingerprint` with the other counts. + +**Scope, mirroring spelling:** resolution layers overrides above the pre-pass's +*inferred* output only. An authored attachment on an event the pre-pass emits +nothing for (ungriddable / non-metric / inapplicable kind) does not surface as +a derived annotation — exactly as a spelling attachment on a +spelling-unavailable pitch does not (the attachment still lives in canonical +`Score` state either way). Two genuine ambiguities are batched, not improvised: + +- **P12-H6 — Decomposition precedence configurability.** Chapter 3 says "same + precedence machinery" as spelling, and Chapter 2 makes the spelling order + *configurable* per score (`SpellingPrecedence`, plus `priority`/timestamp + tie-breaks); but the graph model has no `DecompositionPrecedence` field and + `DecompositionAttachment` has no `priority`. Whether decomposition precedence + should be configurable (a new canonical `Score` field — a codec/ratification + change), share `SpellingPrecedence`, or stay the fixed spec default needs a + spec disposition. Until then the fixed default order is implemented. +- **P12-H7 — Authored decompositions for events the pre-pass cannot infer + for.** An authored attachment is precisely how a user would notate an event + the algorithm reports ungriddable, yet the derived-annotation surface only + resolves overrides where an inferred output exists (the spelling mirror). + Whether authored attachments should surface in `DerivedAnnotations` for + inference-ineligible events (and how the taxonomy should count them) is a + spec question for both pre-passes. + +### Typed inversion tolerance (`tempo::inversion_tolerance`) + +`INVERSION_TOLERANCE_WHOLE_NOTES` was a bare public `f64` documented as +belonging to tolerance class `TempoIntegration` but never constructed as a +`Tolerance` (Appendix D §"Tolerance Classes": no ad-hoc epsilons). It is now +the private raw magnitude behind the public `inversion_tolerance()` — a +`Tolerance { class: TempoIntegration, absolute: 1e-6, relative: None, +governance: Validation }` (the same construction pattern as the existing +`speed_degeneracy_tolerance`). Behavior is numerically identical: the inverse +conversion passes `inversion_tolerance().absolute.get()` (exactly `1e-6`) to +the continued-fraction approximation. Note the class's *non-normative* unit +label is "wallclock seconds" while this residual is measured in whole notes; +the class identity (`TempoIntegration`: conversion residual in either +direction) is what is normative. diff --git a/crates/epiphany-core/src/lib.rs b/crates/epiphany-core/src/lib.rs index ad58b4b..f0220f0 100644 --- a/crates/epiphany-core/src/lib.rs +++ b/crates/epiphany-core/src/lib.rs @@ -74,18 +74,18 @@ pub use time::{ }; pub use pitch::{ - derive_system_pitch_id, spell, AccidentalId, AccidentalRegistryId, AcousticPitch, - AcousticRealization, CmnNominal, DecompositionAlgorithmId, ForeignFormatId, IdentifiedPitch, - NominalRegistryId, Pitch, PitchSpaceId, PitchSpacePosition, PitchSpelling, PositionRegistryId, - ReferencePitch, ScalePosition, SpellingAlgorithmId, SpellingAttachment, SpellingContext, - SpellingDirective, SpellingNominal, SpellingPrecedence, SpellingRenderHints, SpellingRule, - SpellingRuleSetId, SpellingScope, SpellingSource, SpellingSourceKind, StaffGroupKindRegistryId, - TieClassRegistryId, TuningReference, TuningSystemId, VoiceSelector, + canonical_pitch_bytes, derive_system_pitch_id, spell, AccidentalId, AccidentalRegistryId, + AcousticPitch, AcousticRealization, CmnNominal, DecompositionAlgorithmId, ForeignFormatId, + IdentifiedPitch, NominalRegistryId, Pitch, PitchSpaceId, PitchSpacePosition, PitchSpelling, + PositionRegistryId, ReferencePitch, ScalePosition, SpellingAlgorithmId, SpellingAttachment, + SpellingContext, SpellingDirective, SpellingNominal, SpellingPrecedence, SpellingRenderHints, + SpellingRule, SpellingRuleSetId, SpellingScope, SpellingSource, SpellingSourceKind, + StaffGroupKindRegistryId, TieClassRegistryId, TuningReference, TuningSystemId, VoiceSelector, }; pub use prepass::{ - derive_annotations, resolve_spelling, simplest_spelling, DerivedAnnotations, PrePassProfile, - ResolvedSpelling, SpellingProvenance, TaxonomyReport, + derive_annotations, resolve_decomposition, resolve_spelling, simplest_spelling, + DerivedAnnotations, PrePassProfile, ResolvedSpelling, SpellingProvenance, TaxonomyReport, }; pub use event::{ @@ -112,8 +112,8 @@ pub use graph::{ }; pub use tempo::{ - Tempo, TempoError, TempoMap, TempoSegment, TempoShape, INVERSION_MAX_DENOMINATOR, - INVERSION_MAX_ITERATIONS, INVERSION_TOLERANCE_WHOLE_NOTES, + inversion_tolerance, Tempo, TempoError, TempoMap, TempoSegment, TempoShape, + INVERSION_MAX_DENOMINATOR, INVERSION_MAX_ITERATIONS, }; pub use codec::{CanonicalValue, ScoreDecodeError}; diff --git a/crates/epiphany-core/src/pitch.rs b/crates/epiphany-core/src/pitch.rs index ca10f2a..d8c6bca 100644 --- a/crates/epiphany-core/src/pitch.rs +++ b/crates/epiphany-core/src/pitch.rs @@ -446,7 +446,13 @@ impl Pitch { /// system pitch identifier. Strings are length-prefixed and already NFC (the /// catalog ids normalize on construction); the layout is fixed-shape so equal /// pitches encode to equal bytes (Appendix D §"Canonical serialization"). -fn canonical_pitch_bytes(p: &Pitch) -> Vec { +/// +/// Public because these bytes are the normative "canonical inputs" of the +/// `MUSCSPCH` derivation (`req:graph:system-derived-pitch-id`): the reduction's +/// system-derived counter-collision check (Chapter 5 §"System-Derived Counter +/// Collisions") compares exactly these input bytes to distinguish two pitches +/// contending for one derived counter. +pub fn canonical_pitch_bytes(p: &Pitch) -> Vec { // Length-prefixed UTF-8, normalized to NFC at the derivation boundary so the // canonical input is NFC regardless of how the string was obtained (Appendix // D §"Text and Unicode"). Catalog ids are already NFC at construction, so this diff --git a/crates/epiphany-core/src/prepass.rs b/crates/epiphany-core/src/prepass.rs index 8cbf847..79a294e 100644 --- a/crates/epiphany-core/src/prepass.rs +++ b/crates/epiphany-core/src/prepass.rs @@ -17,7 +17,12 @@ //! [`SpellingSourceKind::Inferred`] in the score's [`SpellingPrecedence`]) //! takes precedence over the algorithm's default. The default is *derived*; //! the override is *authored*. H formalizes the precedence rule, not the model -//! (see [`resolve_spelling`]). +//! (see [`resolve_spelling`]). The decomposition side is governed the same way +//! (Chapter 3: "same sources, same precedence machinery, same pre-pass +//! discipline"): an authored [`DecompositionAttachment`] in +//! `Score::decomposition_attachments` whose source outranks +//! [`DecompositionSource::Inferred`] outranks the derived decomposition (see +//! [`resolve_decomposition`]). //! * **Algorithm version is part of the derivation key.** The //! [`SpellingAlgorithmId`] / [`DecompositionAlgorithmId`] in [`PrePassProfile`] //! key the derivation; a profile-declared change deterministically @@ -113,8 +118,15 @@ pub struct TaxonomyReport { pub spelling_unavailable: usize, // --- Decomposition outcomes (over events). --- - /// Events that received a decomposition. + /// Eligible events whose effective decomposition is the pre-pass's inferred + /// one. pub decompositions_inferred: usize, + /// Eligible events whose effective decomposition came from an authored + /// [`DecompositionAttachment`] whose source outranks + /// [`DecompositionSource::Inferred`] (mirroring `spellings_authored`). + /// Counted distinctly from `decompositions_inferred`: the derived map holds + /// the authored components for these events, not the pre-pass's. + pub decompositions_authored: usize, /// Metric-region events whose duration is wall-clock or indeterminate (no /// determinate musical duration to decompose). pub decomposition_skipped_nonmusical: usize, @@ -195,6 +207,7 @@ impl DerivedAnnotations { t.spellings_authored, t.spelling_unavailable, t.decompositions_inferred, + t.decompositions_authored, t.decomposition_skipped_nonmusical, t.decomposition_deferred_nonmetric, t.decomposition_inapplicable, @@ -257,11 +270,18 @@ pub fn derive_annotations(score: &Score, profile: &PrePassProfile) -> DerivedAnn } // --- Decomposition pre-pass. --- - let decompositions = if decomposition_supported { - infer_decompositions(score, &layout, &mut taxonomy) - } else { - BTreeMap::new() - }; + let mut decompositions = BTreeMap::new(); + if decomposition_supported { + let inferred = infer_decompositions(score, &layout, &mut taxonomy); + for (eid, inferred_attachment) in inferred { + let resolved = resolve_decomposition(score, eid, inferred_attachment); + match resolved.source { + DecompositionSource::Inferred => taxonomy.decompositions_inferred += 1, + _ => taxonomy.decompositions_authored += 1, + } + decompositions.insert(eid, resolved); + } + } DerivedAnnotations { spellings, @@ -1042,8 +1062,11 @@ fn resolve_measure_units(score: &Score, region: &crate::graph::Region) -> i64 { GRID_DEN } -/// Builds the decomposition attachments for every eligible event, counting -/// ineligible / deferred / skipped cases into the taxonomy. +/// Runs the decomposition pre-pass over every eligible event, returning the +/// inferred (pre-precedence) attachment per event. Counts ineligible / deferred +/// / skipped cases into the taxonomy; the inferred/authored split is counted by +/// [`derive_annotations`] after [`resolve_decomposition`], mirroring +/// [`infer_spellings`]. fn infer_decompositions( score: &Score, layout: &ScoreLayout, @@ -1133,11 +1156,73 @@ fn infer_decompositions( source: DecompositionSource::Inferred, }, ); - taxonomy.decompositions_inferred += 1; } out } +/// The precedence rank of a decomposition source: the spec's default order +/// `UserChosen > Imported > Propagated > Inferred` (Chapter 3 §"Sounding +/// Duration and Notational Decomposition" mirrors Chapter 2 §"Configurable +/// Precedence": "same sources, same precedence machinery"). Lower rank wins. +/// The score carries no decomposition-specific precedence configuration (there +/// is no `DecompositionPrecedence` analogue of [`SpellingPrecedence`] in the +/// graph model), so the spec's default order is the fixed rank here; a +/// configurable decomposition precedence is a Pass-12 candidate. +fn decomposition_source_rank(source: &DecompositionSource) -> usize { + match source { + DecompositionSource::UserChosen => 0, + DecompositionSource::Imported { .. } => 1, + DecompositionSource::Propagated { .. } => 2, + DecompositionSource::Inferred => 3, + } +} + +/// Resolves the *effective* decomposition for an event: an authored +/// [`DecompositionAttachment`] in `Score::decomposition_attachments` whose +/// source outranks [`DecompositionSource::Inferred`] wins; otherwise the +/// algorithm's inferred decomposition stands. This is the decomposition +/// analogue of [`resolve_spelling`] — Chapter 3: the pre-pass produces inferred +/// decompositions only "for events that lack a higher-precedence attachment", +/// with the "same precedence machinery" as spelling, minus the axes the +/// attachment does not carry (no analysis layers, no `priority` field). Among +/// competing authored attachments the lowest [`decomposition_source_rank`] +/// wins; a remaining tie keeps the first candidate in the score's +/// `decomposition_attachments` order, which is canonical (codec-fixed), so the +/// resolution is deterministic across replicas. +pub fn resolve_decomposition( + score: &Score, + event: EventId, + inferred: DecompositionAttachment, +) -> DecompositionAttachment { + let inferred_rank = decomposition_source_rank(&DecompositionSource::Inferred); + let mut best: Option<(usize, &DecompositionAttachment)> = None; + for att in &score.decomposition_attachments { + if att.target != event { + continue; + } + let rank = decomposition_source_rank(&att.source); + if rank >= inferred_rank { + continue; // does not outrank the inferred default + } + best = match best { + None => Some((rank, att)), + // Lower rank wins; a full tie keeps `cur` (the earlier attachment + // in canonical order). + Some(cur) => { + if rank < cur.0 { + Some((rank, att)) + } else { + Some(cur) + } + } + }; + } + match best { + Some((_, att)) => att.clone(), + None => inferred, + } +} + #[cfg(test)] mod tests; diff --git a/crates/epiphany-core/src/prepass/tests.rs b/crates/epiphany-core/src/prepass/tests.rs index f2cf4b4..023ac7a 100644 --- a/crates/epiphany-core/src/prepass/tests.rs +++ b/crates/epiphany-core/src/prepass/tests.rs @@ -1019,6 +1019,227 @@ fn decomposition_components_sum_to_event_duration() { } } +// --------------------------------------------------------------------------- +// Decomposition precedence: authored attachments outrank the derived default +// --------------------------------------------------------------------------- + +/// A two-event metric score — two half notes on beats 1 and 3 — plus the two +/// event ids. Each half note sits on a boundary of its own strength, so the +/// pre-pass infers a single (undotted) half for both. +fn two_half_note_score() -> (Score, crate::ids::EventId, crate::ids::EventId) { + let mut ids = Vec::new(); + let score = metric_score(|idc, voice| { + let mut events = Vec::new(); + for i in 0..2i64 { + let eid = idc.mint(); + let pid = idc.mint::(); + ids.push(eid); + events.push(pitched( + eid, + voice, + r(i, 2), + r(1, 2), + vec![IdentifiedPitch { + id: pid, + pitch: integer_pitch(48 + i as i32), + }], + )); + } + (events, vec![]) + }); + (score, ids[0], ids[1]) +} + +/// An authored two-tied-quarters decomposition for `target` — a legitimate +/// alternative to the inferred single half note (components sum to `1/2`). +fn tied_quarters( + target: crate::ids::EventId, + source: DecompositionSource, +) -> DecompositionAttachment { + let quarter = |tied_to_next| NotatedComponent { + base_value: NoteValue::Quarter, + dots: 0, + tuplet: None, + tied_to_next, + }; + DecompositionAttachment { + target, + components: vec![quarter(true), quarter(false)], + source, + } +} + +/// Another authored alternative summing to `1/2`: dotted quarter tied to an +/// eighth. Distinct from [`tied_quarters`] so rank ties are observable. +fn dotted_quarter_eighth( + target: crate::ids::EventId, + source: DecompositionSource, +) -> DecompositionAttachment { + DecompositionAttachment { + target, + components: vec![ + NotatedComponent { + base_value: NoteValue::Quarter, + dots: 1, + tuplet: None, + tied_to_next: true, + }, + NotatedComponent { + base_value: NoteValue::Eighth, + dots: 0, + tuplet: None, + tied_to_next: false, + }, + ], + source, + } +} + +#[test] +fn authored_decomposition_outranks_the_inferred_default() { + // Chapter 3: the pre-pass produces inferred decompositions only "for events + // that lack a higher-precedence attachment" — an authored UserChosen + // attachment must not be shadowed by the derived one. + let (mut score, e1, e2) = two_half_note_score(); + let authored = tied_quarters(e1, DecompositionSource::UserChosen); + score.decomposition_attachments.push(authored.clone()); + + let ann = derive_annotations(&score, &PrePassProfile::default()); + // The authored attachment is the effective decomposition for its event; no + // derived (single-half-note) decomposition shadows it. + assert_eq!(ann.decompositions[&e1], authored, "authored override wins"); + // The un-overridden event keeps the algorithm's inferred half note. + let other = &ann.decompositions[&e2]; + assert_eq!(other.source, DecompositionSource::Inferred); + assert_eq!(other.components.len(), 1); + assert_eq!(other.components[0].base_value, NoteValue::Half); + // Taxonomy counts the two outcomes distinctly, and together they cover the + // effective map (the accounting the H harness checks). + assert_eq!(ann.taxonomy.decompositions_authored, 1); + assert_eq!(ann.taxonomy.decompositions_inferred, 1); + assert_eq!( + ann.decompositions.len(), + ann.taxonomy.decompositions_inferred + ann.taxonomy.decompositions_authored + ); +} + +#[test] +fn inferred_source_attachment_does_not_outrank_the_prepass() { + // An attachment whose source is `Inferred` does not outrank the pre-pass's + // own output (the rank gate, mirroring `resolve_spelling`): the derived + // half note stands. + let (mut score, e1, _e2) = two_half_note_score(); + score + .decomposition_attachments + .push(tied_quarters(e1, DecompositionSource::Inferred)); + + let ann = derive_annotations(&score, &PrePassProfile::default()); + let dec = &ann.decompositions[&e1]; + assert_eq!(dec.components.len(), 1, "the pre-pass's half note stands"); + assert_eq!(dec.components[0].base_value, NoteValue::Half); + assert_eq!(dec.source, DecompositionSource::Inferred); + assert_eq!(ann.taxonomy.decompositions_authored, 0); + assert_eq!(ann.taxonomy.decompositions_inferred, 2); +} + +#[test] +fn decomposition_precedence_ranks_sources_then_canonical_order() { + // UserChosen outranks Imported regardless of attachment order (the spec's + // default precedence over the decomposition sources)... + let (mut score, e1, _) = two_half_note_score(); + let imported = dotted_quarter_eighth( + e1, + DecompositionSource::Imported { + format: crate::pitch::ForeignFormatId::new("musicxml"), + }, + ); + let user = tied_quarters(e1, DecompositionSource::UserChosen); + score.decomposition_attachments.push(imported); // listed first — must lose + score.decomposition_attachments.push(user.clone()); + let ann = derive_annotations(&score, &PrePassProfile::default()); + assert_eq!( + ann.decompositions[&e1], user, + "UserChosen outranks Imported regardless of attachment order" + ); + + // ...and a full rank tie keeps the first attachment in the score's + // canonical `decomposition_attachments` order (deterministic across + // replicas; the attachment carries no `priority` axis). + let (mut score2, f1, _) = two_half_note_score(); + let first = tied_quarters(f1, DecompositionSource::UserChosen); + let second = dotted_quarter_eighth(f1, DecompositionSource::UserChosen); + score2.decomposition_attachments.push(first.clone()); + score2.decomposition_attachments.push(second); + let ann2 = derive_annotations(&score2, &PrePassProfile::default()); + assert_eq!( + ann2.decompositions[&f1], first, + "rank ties keep the earlier attachment in canonical order" + ); +} + +#[test] +fn derivation_with_authored_decomposition_is_deterministic() { + // The authored override is reflected deterministically: the same overridden + // score derives byte-identically twice, and the fingerprint distinguishes + // the overridden derivation from the un-overridden one. + let build = || { + let (mut score, e1, _) = two_half_note_score(); + score + .decomposition_attachments + .push(tied_quarters(e1, DecompositionSource::UserChosen)); + score + }; + let a = derive_annotations(&build(), &PrePassProfile::default()); + let b = derive_annotations(&build(), &PrePassProfile::default()); + assert_eq!(a, b); + assert_eq!(a.canonical_fingerprint(), b.canonical_fingerprint()); + + let (plain, _, _) = two_half_note_score(); + let c = derive_annotations(&plain, &PrePassProfile::default()); + assert_ne!( + a.canonical_fingerprint(), + c.canonical_fingerprint(), + "the override is visible in the derivation fingerprint" + ); +} + +#[test] +fn authored_attachment_on_an_ungriddable_event_does_not_surface() { + // The resolution step mirrors the spelling side: it layers authored + // overrides above the pre-pass's *inferred* output. An event the pre-pass + // cannot grid emits nothing to override, so an authored attachment for it + // stays in canonical score state without surfacing as a derived annotation, + // and the event stays honestly counted as ungriddable. (Whether authored + // decompositions should surface for events the algorithm cannot infer for + // is a Pass-12 question — see DECISIONS.md.) + let mut ids = Vec::new(); + let mut score = metric_score(|idc, voice| { + let eid = idc.mint(); + let pid = idc.mint::(); + ids.push(eid); + let ev = pitched( + eid, + voice, + r(0, 1), + r(1, 128), // finer than a sixty-fourth: ungriddable + vec![IdentifiedPitch { + id: pid, + pitch: integer_pitch(48), + }], + ); + (vec![ev], vec![]) + }); + score + .decomposition_attachments + .push(tied_quarters(ids[0], DecompositionSource::UserChosen)); + + let ann = derive_annotations(&score, &PrePassProfile::default()); + assert!(ann.decompositions.is_empty()); + assert_eq!(ann.taxonomy.decomposition_ungriddable, 1); + assert_eq!(ann.taxonomy.decompositions_authored, 0); + assert_eq!(ann.taxonomy.decompositions_inferred, 0); +} + #[test] fn unknown_algorithm_ids_are_not_honored() { // A profile requesting an algorithm the pre-pass does not implement must not diff --git a/crates/epiphany-core/src/tempo.rs b/crates/epiphany-core/src/tempo.rs index 0f7d000..0689ef7 100644 --- a/crates/epiphany-core/src/tempo.rs +++ b/crates/epiphany-core/src/tempo.rs @@ -24,9 +24,10 @@ //! **Determinism and tolerance.** The inverse [`TempoMap::wallclock_to_musical`] //! uses a deterministic continued-fraction rational approximation with //! documented bounds ([`INVERSION_MAX_ITERATIONS`], [`INVERSION_MAX_DENOMINATOR`], -//! [`INVERSION_TOLERANCE_WHOLE_NOTES`]) — the documented tolerance and iteration +//! [`inversion_tolerance`]) — the documented tolerance and iteration //! bounds Chapter 3 §"Conversion" requires of any numerical inversion. The -//! residual is governed by [`epiphany_determinism::ToleranceClass::TempoIntegration`]. +//! residual is a typed [`Tolerance`] of class +//! [`epiphany_determinism::ToleranceClass::TempoIntegration`]. //! //! Conversion here is **advisory** (it uses `f64`), not canonical state: //! musical time is the exact rational and wall-clock is exact nanoseconds @@ -152,11 +153,28 @@ pub const INVERSION_MAX_ITERATIONS: u32 = 64; /// Maximum denominator the inverse will introduce, in whole-note units. Keeps /// recovered rhythms simple (`1/3`, `1/12`, …) instead of spurious large ratios. pub const INVERSION_MAX_DENOMINATOR: u64 = 1_000_000; -/// Absolute residual tolerance of the inverse, in whole notes -/// ([`epiphany_determinism::ToleranceClass::TempoIntegration`]). Comfortably +/// Absolute residual magnitude of the inverse, in whole notes. Comfortably /// larger than the half-nanosecond rounding of the forward direction, so an /// ordinary rhythm round-trips, yet far smaller than any musical distinction. -pub const INVERSION_TOLERANCE_WHOLE_NOTES: f64 = 1e-6; +/// The typed tolerance built on it is [`inversion_tolerance`]; this raw value +/// never leaves the module. +const INVERSION_TOLERANCE_WHOLE_NOTES: f64 = 1e-6; + +/// The typed absolute residual tolerance of the inverse conversion +/// ([`TempoMap::wallclock_to_musical`]): a [`Tolerance`] of class +/// [`ToleranceClass::TempoIntegration`] (Appendix D §"Tolerance Classes" — no +/// ad-hoc epsilons), absolute bound [`INVERSION_TOLERANCE_WHOLE_NOTES`] whole +/// notes, no relative bound, governing validation (it decides whether a +/// continued-fraction candidate is accepted; conversion is advisory, never +/// canonical state). +pub fn inversion_tolerance() -> Tolerance { + Tolerance::absolute( + ToleranceClass::TempoIntegration, + INVERSION_TOLERANCE_WHOLE_NOTES, + ToleranceGovernance::Validation, + ) + .expect("constant inversion tolerance is finite and non-negative") +} /// Relative tolerance below which two segment speeds count as *equal*, so the /// integration takes the numerically-stable constant-speed limit instead of the @@ -323,7 +341,7 @@ impl TempoMap { /// §"Conversion"), using `region_relative_resolve` for segment boundaries. /// The inverse uses a deterministic continued-fraction rational /// approximation with the documented bounds [`INVERSION_MAX_ITERATIONS`] / - /// [`INVERSION_MAX_DENOMINATOR`] / [`INVERSION_TOLERANCE_WHOLE_NOTES`], so an + /// [`INVERSION_MAX_DENOMINATOR`] / [`inversion_tolerance`], so an /// ordinary rhythm (a triplet `1/12`, a dotted `3/8`) round-trips exactly /// rather than being quantized to a fixed grid. pub fn wallclock_to_musical(&self, time: WallClockTime) -> Result { @@ -343,7 +361,7 @@ impl TempoMap { rational_from_f64( whole_notes, INVERSION_MAX_DENOMINATOR, - INVERSION_TOLERANCE_WHOLE_NOTES, + inversion_tolerance().absolute.get(), ) .map(MusicalPosition) .ok_or(TempoError::ConversionOverflow) @@ -692,6 +710,19 @@ mod tests { assert!(Tempo::new(120.0, MusicalDuration::zero()).is_none()); } + #[test] + fn inversion_tolerance_is_a_typed_tempo_integration_tolerance() { + // The inverse's residual bound is a named `Tolerance` of class + // `TempoIntegration` (Appendix D §"Tolerance Classes": no ad-hoc epsilon + // constants), pinned to the documented magnitude: absolute 1e-6 whole + // notes, no relative bound, validation governance. + let t = inversion_tolerance(); + assert_eq!(t.class, ToleranceClass::TempoIntegration); + assert_eq!(t.absolute.get(), 1e-6); + assert_eq!(t.relative, None); + assert_eq!(t.governance, ToleranceGovernance::Validation); + } + #[test] fn linear_segment_is_integrated_not_rejected() { // A single linear ramp over [0, 1] whole notes from 60 to 120 q-bpm. diff --git a/crates/epiphany-editor-core/src/barriers.rs b/crates/epiphany-editor-core/src/barriers.rs new file mode 100644 index 0000000..30328d5 --- /dev/null +++ b/crates/epiphany-editor-core/src/barriers.rs @@ -0,0 +1,423 @@ +//! The edit-barrier gate (Chapter 8 §"Forward Compatibility and Edit Barriers" +//! / §"Behavior Under Unknown Extensions"). +//! +//! The spec's MUST: *"Edits MUST be checked against every active edit barrier. +//! An edit matching a barrier's scope, affected object kinds, and operation +//! kinds is prohibited unless the user explicitly performs an unsafe edit."* +//! The session holds the active extensions' decoded barriers +//! ([`ActiveExtension`]); before minting an envelope, [`crate::EditorSession`] +//! derives the candidate edit's **subjects** — the objects the operation's +//! payload names, each with its structural containment ([`EditContext`]) — and +//! evaluates every barrier via [`EditBarrier::prohibits_edit`] against a +//! [`ScoreOracle`] over the session's materialized score. +//! +//! Matching policy (documented, deliberate): +//! +//! * **Object-kind matching is on the payload's named targets** (the object an +//! op mints, tombstones, or overwrites — plus, for a pitch insert, the host +//! event whose pitch list it mutates). Indirect containers (the voice an +//! event sits in, say) are *not* treated as edited objects; protecting a +//! container is what the barrier's **scope** is for, and scope is matched +//! against the target's real containment, precisely. +//! * **Score-level operations** (`SetMetadata`, the transaction descriptor) +//! name no graph object: only a score-wide barrier (empty +//! `affected_object_kinds`, `WholeScore`/`TuningContext`/`Registered` scope) +//! can match them. +//! * **Extension-defined operations** (`OperationKind::Registered`) carry a +//! payload the core cannot read, so their targets are unknowable: a barrier +//! prohibiting that registered kind matches **conservatively** (scope and +//! object kinds are treated as matching — Chapter 8's "never silently drop a +//! barrier you cannot evaluate"). + +use epiphany_core::{ + EventId, PitchId, PitchSpaceId, RegionId, Score, StaffInstanceId, TypedObjectId, VoiceId, +}; +use epiphany_layout_ir::{BarrierScope, EditBarrier, EditContext, EditOracle, ExtensionRef}; +use epiphany_ops::{OperationKind, OperationKindTag}; + +/// One active extension declaration's barrier view: the declaring extension +/// (named when its barrier refuses an edit, and recorded for tombstoning when +/// an unsafe edit crosses it) plus its decoded edit barriers. +/// +/// The session opens on a bare [`Score`], not a bundle, so it cannot read the +/// manifest itself: whoever opened the bundle decodes each +/// `ExtensionDeclaration.edit_barriers` blob +/// ([`epiphany_layout_ir::decode_edit_barriers`]) and injects the result via +/// [`crate::EditorSession::set_active_extensions`]. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ActiveExtension { + /// The declaring extension (the manifest `ExtensionDeclaration`'s + /// `extension_id`, as the barrier layer's opaque 128-bit reference). + pub extension: ExtensionRef, + /// The extension's decoded edit barriers. + pub barriers: Vec, +} + +/// What a candidate operation edits, for barrier matching. +pub(crate) enum BarrierSubjects { + /// The graph objects the payload names, each with its containment. + Objects(Vec<(TypedObjectId, EditContext)>), + /// The operation edits score-level state and names no graph object + /// (`SetMetadata`, a transaction descriptor): only a score-wide barrier + /// can match. + ScoreWide, + /// An extension-defined operation whose payload the core cannot read: + /// scope and object kinds are treated conservatively as matching. + Unknown, +} + +/// The [`EditOracle`] over the session's materialized score: **known** barrier +/// conditions are evaluated *precisely* against the graph, so a barrier +/// narrowed to `ObjectExists` really deactivates when the object is gone. +/// +/// `has_extension_data` is `false` for every object: the v0 materialized score +/// carries no extension payloads on graph objects, so "carries data declared by +/// the extension" is precisely (not conservatively) false. +pub(crate) struct ScoreOracle<'a>(pub &'a Score); + +impl EditOracle for ScoreOracle<'_> { + fn object_exists(&self, object: &TypedObjectId) -> bool { + let score = self.0; + match object { + TypedObjectId::Event(id) => score.events.get(*id).is_some(), + TypedObjectId::Pitch(id) => score.live_pitch_ids().contains(id), + TypedObjectId::Voice(id) => score.voices().any(|(_, _, v)| v.id == *id), + TypedObjectId::Staff(id) => score.staves.iter().any(|s| s.id == *id), + TypedObjectId::StaffInstance(id) => score.staff_instances().any(|(_, si)| si.id == *id), + TypedObjectId::StaffGroup(id) => score.staff_groups.iter().any(|g| g.id == *id), + TypedObjectId::Region(id) => score.canvas.regions.iter().any(|r| r.id == *id), + TypedObjectId::Instrument(id) => score.instruments.iter().any(|i| i.id == *id), + TypedObjectId::PartDefinition(id) => score.parts.iter().any(|p| p.id == *id), + TypedObjectId::BarlineAlignmentGroup(id) => score + .canvas + .regions + .iter() + .flat_map(|r| r.content.barline_alignment_groups()) + .any(|g| g.id == *id), + TypedObjectId::Slur(id) => score.cross_cutting.slurs.iter().any(|s| s.id == *id), + TypedObjectId::Tie(id) => score.cross_cutting.ties.iter().any(|t| t.id == *id), + TypedObjectId::Beam(id) => score.cross_cutting.beams.iter().any(|b| b.id == *id), + TypedObjectId::Spanner(id) => score.cross_cutting.spanners.iter().any(|s| s.id == *id), + TypedObjectId::Tuplet(id) => score.cross_cutting.tuplets.iter().any(|t| t.id == *id), + TypedObjectId::Marker(id) => score.cross_cutting.markers.iter().any(|m| m.id == *id), + TypedObjectId::RepeatStructure(id) => { + score.cross_cutting.repeats.iter().any(|r| r.id == *id) + } + TypedObjectId::AnalyticalAnnotation(id) => { + score.cross_cutting.analytical.iter().any(|a| a.id == *id) + } + TypedObjectId::Comment(id) => score.cross_cutting.comments.iter().any(|c| c.id == *id), + TypedObjectId::GraphicGesture(id) => score + .cross_cutting + .graphic_gestures + .iter() + .any(|g| g.id == *id), + TypedObjectId::LyricLine(id) => score.cross_cutting.lyrics.iter().any(|l| l.id == *id), + TypedObjectId::ChordSymbol(id) => score + .cross_cutting + .chord_symbols + .iter() + .any(|c| c.id == *id), + TypedObjectId::GraphicObject(id) => score + .canvas + .regions + .iter() + .flat_map(|r| r.content.graphic_objects()) + .any(|g| g.id == *id), + TypedObjectId::TimeSignature(id) => score.time_signatures.iter().any(|t| t.id == *id), + TypedObjectId::AnalysisLayer(id) => score.analysis_layers.iter().any(|l| l.id == *id), + TypedObjectId::View(id) => score.views.iter().any(|v| v.id == *id), + // The v0 graph hosts no measure objects (measures are derived) and + // no extension-registered objects, so these precisely do not exist. + TypedObjectId::Measure(_) | TypedObjectId::Registered(..) => false, + } + } + + fn has_extension_data(&self, _object: &TypedObjectId, _extension: ExtensionRef) -> bool { + false + } +} + +fn ctx(region: Option, staff_instance: Option) -> EditContext { + EditContext { + region, + staff_instance, + analysis_layer: None, + pitch_space: None, + } +} + +/// The region a staff instance manifests in, if it is in the graph. +fn region_of_staff_instance(score: &Score, instance: StaffInstanceId) -> Option { + score + .staff_instances() + .find(|(_, si)| si.id == instance) + .map(|(region, _)| region) +} + +/// The (region, staff instance) a voice lives in, if it is in the graph. +fn voice_location(score: &Score, voice: VoiceId) -> Option<(RegionId, StaffInstanceId)> { + score + .voices() + .find(|(_, _, v)| v.id == voice) + .map(|(region, si, _)| (region, si)) +} + +/// The (region, staff instance) an event lives in, via the voice listing it. +fn event_location(score: &Score, event: EventId) -> Option<(RegionId, StaffInstanceId)> { + score + .voices() + .find(|(_, _, v)| v.events.contains(&event)) + .map(|(region, si, _)| (region, si)) +} + +/// The containment and pitch space of a live pitch, via the event embedding it. +fn pitch_context(score: &Score, pitch: PitchId) -> EditContext { + let mut buf: Vec<&epiphany_core::IdentifiedPitch> = Vec::new(); + for event in score.events.iter() { + buf.clear(); + event.collect_identified_pitches(&mut buf); + if let Some(ip) = buf.iter().find(|ip| ip.id == pitch) { + let location = event_location(score, event.id()); + return EditContext { + region: location.map(|(r, _)| r), + staff_instance: location.map(|(_, si)| si), + analysis_layer: None, + pitch_space: Some(ip.pitch.scale_position.space.clone()), + }; + } + } + EditContext::default() +} + +/// A context for a pitch value the operation itself carries (an insert's new +/// pitch), whose space is read from the value rather than the graph. +fn carried_pitch_context( + location: Option<(RegionId, StaffInstanceId)>, + space: PitchSpaceId, +) -> EditContext { + EditContext { + region: location.map(|(r, _)| r), + staff_instance: location.map(|(_, si)| si), + analysis_layer: None, + pitch_space: Some(space), + } +} + +/// The context of a cross-cutting structure: the containment of its first +/// locatable endpoint event (a slur/tie/beam/spanner lives where its anchors +/// live), or the default context when none is locatable. +fn structure_context(score: &Score, endpoints: &[TypedObjectId]) -> EditContext { + let location = endpoints.iter().find_map(|endpoint| match endpoint { + TypedObjectId::Event(id) => event_location(score, *id), + _ => None, + }); + ctx(location.map(|(r, _)| r), location.map(|(_, si)| si)) +} + +/// The endpoints of a cross-cutting structure already in the graph, by id. +fn graph_structure_endpoints(score: &Score, structure: &TypedObjectId) -> Vec { + let events = |ids: Vec| ids.into_iter().map(TypedObjectId::Event).collect(); + match structure { + TypedObjectId::Slur(id) => score + .cross_cutting + .slurs + .iter() + .find(|s| s.id == *id) + .map(|s| events(vec![s.start_event, s.end_event])) + .unwrap_or_default(), + TypedObjectId::Tie(id) => score + .cross_cutting + .ties + .iter() + .find(|t| t.id == *id) + .map(|t| events(vec![t.start_event, t.end_event])) + .unwrap_or_default(), + TypedObjectId::Beam(id) => score + .cross_cutting + .beams + .iter() + .find(|b| b.id == *id) + .map(|b| events(b.events.clone())) + .unwrap_or_default(), + TypedObjectId::Spanner(id) => score + .cross_cutting + .spanners + .iter() + .find(|s| s.id == *id) + .map(|s| { + [&s.start, &s.end] + .into_iter() + .filter_map(|anchor| match anchor { + epiphany_core::TimeAnchor::Event { id, .. } => { + Some(TypedObjectId::Event(*id)) + } + _ => None, + }) + .collect() + }) + .unwrap_or_default(), + _ => Vec::new(), + } +} + +/// Derives the barrier subjects of `kind`: the objects its payload names, each +/// with its containment in `score` (see the module docs for the matching +/// policy). Containment that cannot be resolved (the target is not in the +/// graph — reduction's invariant preconditions own that case) yields a context +/// with the unresolved fields `None`. +pub(crate) fn subjects_of(kind: &OperationKind, score: &Score) -> BarrierSubjects { + let one = |object: TypedObjectId, context: EditContext| { + BarrierSubjects::Objects(vec![(object, context)]) + }; + match kind { + OperationKind::InsertEvent(op) => { + let region = region_of_staff_instance(score, op.staff_instance); + one( + TypedObjectId::Event(op.event_id()), + ctx(region, Some(op.staff_instance)), + ) + } + OperationKind::DeleteEvent(op) => { + let location = event_location(score, op.event); + one( + TypedObjectId::Event(op.event), + ctx(location.map(|(r, _)| r), location.map(|(_, si)| si)), + ) + } + OperationKind::ModifyEvent(op) => { + let location = event_location(score, op.event_id()); + one( + TypedObjectId::Event(op.event_id()), + ctx(location.map(|(r, _)| r), location.map(|(_, si)| si)), + ) + } + OperationKind::RespellPitch(op) => one( + TypedObjectId::Pitch(op.pitch), + pitch_context(score, op.pitch), + ), + OperationKind::Transpose(op) => BarrierSubjects::Objects( + op.targets + .iter() + .map(|pitch| (TypedObjectId::Pitch(*pitch), pitch_context(score, *pitch))) + .collect(), + ), + OperationKind::InsertIdentifiedPitch(op) => { + // The op mutates the host event's pitch list *and* mints the pitch: + // both are named targets. + let location = event_location(score, op.event); + let event_ctx = ctx(location.map(|(r, _)| r), location.map(|(_, si)| si)); + let pitch_ctx = + carried_pitch_context(location, op.pitch.pitch.scale_position.space.clone()); + BarrierSubjects::Objects(vec![ + (TypedObjectId::Event(op.event), event_ctx), + (TypedObjectId::Pitch(op.pitch_id()), pitch_ctx), + ]) + } + OperationKind::DeleteIdentifiedPitch(op) => one( + TypedObjectId::Pitch(op.pitch), + pitch_context(score, op.pitch), + ), + OperationKind::ModifyIdentifiedPitch(op) => one( + TypedObjectId::Pitch(op.pitch), + pitch_context(score, op.pitch), + ), + OperationKind::CreateCrossCutting(op) => one( + op.structure.id(), + structure_context(score, &op.structure.endpoints()), + ), + OperationKind::ModifyCrossCutting(op) => one( + op.structure.id(), + structure_context(score, &op.structure.endpoints()), + ), + OperationKind::DeleteCrossCutting(op) => one( + op.structure, + structure_context(score, &graph_structure_endpoints(score, &op.structure)), + ), + OperationKind::ChangeRegionTimeModel(op) => { + one(TypedObjectId::Region(op.region), ctx(Some(op.region), None)) + } + OperationKind::SetUserSystemBreak(op) => { + one(TypedObjectId::Region(op.region), ctx(Some(op.region), None)) + } + OperationKind::SetUserPageBreak(op) => { + one(TypedObjectId::Region(op.region), ctx(Some(op.region), None)) + } + OperationKind::SetMetricGrid(op) => { + one(TypedObjectId::Region(op.region), ctx(Some(op.region), None)) + } + OperationKind::CreateRegion(op) => one( + TypedObjectId::Region(op.region_id()), + ctx(Some(op.region_id()), None), + ), + OperationKind::DeleteRegion(op) => { + one(TypedObjectId::Region(op.region), ctx(Some(op.region), None)) + } + OperationKind::CreateStaffInstance(op) => one( + TypedObjectId::StaffInstance(op.instance_id()), + ctx(Some(op.region), Some(op.instance_id())), + ), + OperationKind::DeleteStaffInstance(op) => one( + TypedObjectId::StaffInstance(op.staff_instance), + ctx( + region_of_staff_instance(score, op.staff_instance), + Some(op.staff_instance), + ), + ), + OperationKind::CreateVoice(op) => one( + TypedObjectId::Voice(op.voice_id()), + ctx( + region_of_staff_instance(score, op.staff_instance), + Some(op.staff_instance), + ), + ), + OperationKind::DeleteVoice(op) => { + let location = voice_location(score, op.voice); + one( + TypedObjectId::Voice(op.voice), + ctx(location.map(|(r, _)| r), location.map(|(_, si)| si)), + ) + } + OperationKind::SetMetadata(_) | OperationKind::DeclareTransaction(_) => { + BarrierSubjects::ScoreWide + } + OperationKind::Registered(..) => BarrierSubjects::Unknown, + } +} + +/// Every active extension with a barrier prohibiting the candidate edit, in +/// declaration order, deduplicated. Empty means the edit is permitted. +pub(crate) fn prohibiting_extensions( + extensions: &[ActiveExtension], + tag: OperationKindTag, + subjects: &BarrierSubjects, + oracle: &dyn EditOracle, +) -> Vec { + let mut crossed = Vec::new(); + for ext in extensions { + let hit = ext.barriers.iter().any(|barrier| match subjects { + BarrierSubjects::Objects(objects) => objects + .iter() + .any(|(object, context)| barrier.prohibits_edit(tag, object, context, oracle)), + BarrierSubjects::ScoreWide => { + barrier.prohibited_operation_kinds.contains(&tag) + && barrier.affected_object_kinds.is_empty() + && matches!( + barrier.scope, + BarrierScope::WholeScore + | BarrierScope::TuningContext + | BarrierScope::Registered(_) + ) + && barrier.condition.is_active(oracle) + } + BarrierSubjects::Unknown => { + barrier.prohibited_operation_kinds.contains(&tag) + && barrier.condition.is_active(oracle) + } + }); + if hit && !crossed.contains(&ext.extension) { + crossed.push(ext.extension); + } + } + crossed +} diff --git a/crates/epiphany-editor-core/src/lib.rs b/crates/epiphany-editor-core/src/lib.rs index 4b385bb..29dc1ae 100644 --- a/crates/epiphany-editor-core/src/lib.rs +++ b/crates/epiphany-editor-core/src/lib.rs @@ -44,8 +44,12 @@ //! GUI plugs in the real `Engraver`, the stub, or any conformant solver. It //! produces a [`RenderIR`]; turning that into pixels is the renderer's job. +mod barriers; + +pub use barriers::ActiveExtension; + use std::cmp::Reverse; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::fmt; use epiphany_core::prepass::{derive_annotations, DerivedAnnotations, PrePassProfile}; @@ -55,20 +59,20 @@ use epiphany_core::{ PitchSpaceId, PitchSpacePosition, PitchSpelling, PitchedEvent, RationalTime, RegionId, RegionTimeModel, ReplicaId, ScalePosition, Score, SpellingDirective, SpellingNominal, SpellingScope, SpellingSourceKind, StaffId, StaffInstance, StaffInstanceId, StemConfiguration, - TimeSignature, TimeSignatureDisplay, TransactionId, TuningReference, TypedObjectId, VoiceId, - WallClockTime, + TimeSignature, TimeSignatureDisplay, TransactionId, TuningReference, TupletId, TypedObjectId, + VoiceId, WallClockTime, }; use epiphany_layout_ir::{ active_clef, manifestation_layout_id, staff_step_pitch, to_constrained, to_logical, to_render, - ConstraintSolver, HitTestMap, LayoutContent, LayoutObjectId, LogicalLayoutIR, Point, RenderIR, - ResolvedLayoutIR, SolverConfig, TimePoint, + ConstraintSolver, ExtensionRef, HitTestMap, LayoutContent, LayoutObjectId, LogicalLayoutIR, + Point, RenderIR, ResolvedLayoutIR, SolverConfig, TimePoint, }; use epiphany_ops::{ - AcceptOutcome, AuthorId, CausalContext, DeleteEventOp, DeleteIdentifiedPitchOp, - HybridLogicalClock, InsertEventOp, InsertIdentifiedPitchOp, ModifyEventOp, - ModifyIdentifiedPitchOp, OperationEnvelope, OperationKind, OperationPayload, OperationSet, - OperationStamp, RespellPitchOp, TransactionCategory, TransactionDescriptor, TransposeOp, - TupletCompensation, + advisory_violations, AcceptOutcome, AuthorId, CausalContext, DeleteEventOp, + DeleteIdentifiedPitchOp, HybridLogicalClock, InsertEventOp, InsertIdentifiedPitchOp, + ModifyEventOp, ModifyIdentifiedPitchOp, OperationEnvelope, OperationKind, OperationKindTag, + OperationPayload, OperationSet, OperationStamp, RespellPitchOp, TransactionCategory, + TransactionDescriptor, TransposeOp, TupletCompensation, }; /// The current selection: the score-graph object to act on, plus the stable layout @@ -175,11 +179,14 @@ pub enum EditorError { /// region is non-metric or has too few rendered events to place a position, or the /// staff has no voice / no diatonic clef. Nothing is inserted. NoInsertTarget, - /// A click-to-insert's make-room would have to trim or delete a **tuplet member**, - /// whose duration is governed by the tuplet's ratio. Compensating a tuplet on a - /// pencil overwrite is a later refinement, so the insert is refused rather than - /// leaving the tuplet inconsistent. Also raised by a duration edit of a tuplet - /// member itself. + /// A make-room overwrite could not treat an overlapped tuplet atomically. Tuplets are + /// atomic: a pencil overwrite touching any member of a *flat* tuplet cascades the whole + /// tuplet away (every member tombstoned, structure removed), freeing its span for the + /// new note. This error is raised only when that cascade is not available — the + /// overlapped member belongs to a **nested** tuplet (parent or child), whose ratio + /// arithmetic a flat cascade would misstate. Also raised by a *resize* + /// ([`set_selection_duration`](EditorSession::set_selection_duration)) of a tuplet + /// member itself: in-place rescaling of a member is a later refinement. OverlapsTuplet, /// A duration edit was given a non-positive duration, which is not a valid written /// note value. Nothing changes. @@ -190,6 +197,29 @@ pub enum EditorError { /// later refinement, so the edit is refused rather than left inconsistent. (A delete /// is fine; the tombstoned target's decomposition is no longer checked.) DecomposedEvent, + /// The operation failed an advisory precondition against the current materialized + /// score (Chapter 6 §"Validation Modes"). The session is **authoring mode**: all + /// preconditions are enforced, and advisory failures refuse the edit *before an + /// envelope is minted* — nothing enters the op log, and a peer never sees the + /// operation. (Replay/remote reduction enforces only invariant preconditions, so + /// the same envelope, had it been minted elsewhere, would reduce cleanly.) + AdvisoryViolation { + /// Every advisory precondition the operation failed. + violations: Vec, + }, + /// The edit matches an active edit barrier (Chapter 8 §"Behavior Under + /// Unknown Extensions": *edits MUST be checked against every active edit + /// barrier; a match is prohibited unless the user explicitly performs an + /// unsafe edit*). Nothing is minted and nothing changes. Crossing the + /// barrier deliberately is [`EditorSession::apply_unsafe`] / + /// [`EditorSession::apply_transaction_unsafe`], which acknowledges the loss + /// of the named extension's data. + BarrierProhibited { + /// The extension whose edit barrier prohibits the edit. + extension: ExtensionRef, + /// The prohibited operation class. + operation: OperationKindTag, + }, } impl fmt::Display for EditorError { @@ -219,12 +249,30 @@ impl fmt::Display for EditorError { f.write_str("the click resolved to no insert target (off-staff, non-metric, or no voice)") } EditorError::OverlapsTuplet => { - f.write_str("the edit would have to trim or delete a tuplet member") + f.write_str("the edit would have to alter a nested tuplet, or resize a tuplet member") } EditorError::InvalidDuration => f.write_str("a non-positive duration is not a note value"), EditorError::DecomposedEvent => { f.write_str("the edit would change the duration of an event with a decomposition") } + EditorError::AdvisoryViolation { violations } => { + write!( + f, + "the edit failed {} advisory precondition(s) (authoring mode): {violations:?}", + violations.len() + ) + } + EditorError::BarrierProhibited { + extension, + operation, + } => { + write!( + f, + "the edit ({operation:?}) is prohibited by an edit barrier declared by \ + extension {extension:?}; only an explicit unsafe edit may cross it \ + (tombstoning that extension's data)" + ) + } } } } @@ -282,6 +330,16 @@ pub struct EditorSession { // active prefix. (`applied` is always a — possibly non-contiguous, after a fork — // subsequence of `authored`.) authored: Vec, + // The active extension declarations whose edit barriers gate edits (Chapter 8 + // §"Behavior Under Unknown Extensions"). Injected via `set_active_extensions` + // (the session opens on a bare `Score`, so it never reads a manifest itself); + // empty means no barriers, i.e. every edit passes the gate. + active_extensions: Vec, + // Extensions crossed by an unsafe edit. Per the spec, an unsafe edit MUST + // tombstone the crossed extension's chunks; the session has no bundle + // plumbing, so it records the obligation here (see + // `extensions_requiring_tombstone`) and deactivates the extension's barriers. + pending_extension_tombstones: BTreeSet, } /// One materialization of the op log: the reduced score and everything derived from it @@ -316,6 +374,8 @@ impl EditorSession { undo_units: Vec::new(), redo_stack: Vec::new(), authored: Vec::new(), + active_extensions: Vec::new(), + pending_extension_tombstones: BTreeSet::new(), }) } @@ -389,6 +449,74 @@ impl EditorSession { self.applied.last() } + /// Installs the active extension set whose edit barriers gate subsequent + /// edits (Chapter 8 §"Behavior Under Unknown Extensions": edits MUST be + /// checked against every active edit barrier). Replaces any previous set. + /// + /// The session opens on a bare [`Score`], not a bundle, so it never reads a + /// manifest itself: whoever opened the bundle decodes each declaration's + /// `edit_barriers` blob ([`epiphany_layout_ir::decode_edit_barriers`]) and + /// injects the result here. A session with no active extensions (the + /// default) has no barriers, and every edit passes the gate. + pub fn set_active_extensions(&mut self, extensions: Vec) { + self.active_extensions = extensions; + } + + /// The currently active extension declarations (barriers included). An + /// extension crossed by an unsafe edit is removed from this set — its data + /// is bound for tombstoning, so its barriers no longer bind. + pub fn active_extensions(&self) -> &[ActiveExtension] { + &self.active_extensions + } + + /// Extensions crossed by an unsafe edit in this session, whose chunks MUST + /// be tombstoned per the spec (§"Behavior Under Unknown Extensions": *the + /// unsafe-edit operation MUST tombstone the relevant extension chunks (so + /// they are no longer preserved) rather than silently breaking extension + /// invariants*). The session has no bundle plumbing of its own, so it + /// records the obligation: the next bundle write reads this set and drops + /// the named extensions' declarations (and with them their + /// `preserved_chunk_roots`) from the manifest it commits. + pub fn extensions_requiring_tombstone(&self) -> &BTreeSet { + &self.pending_extension_tombstones + } + + /// The first active-barrier match for `kind`, as the refusal `apply` / + /// `apply_transaction` surface (spec: a matching edit *is prohibited*). + fn barrier_refusal(&self, kind: &OperationKind) -> Option { + self.crossed_extensions(kind) + .into_iter() + .next() + .map(|extension| EditorError::BarrierProhibited { + extension, + operation: kind.tag(), + }) + } + + /// Every active extension with a barrier prohibiting `kind` against the + /// current materialized score — the extensions an unsafe edit crosses. + fn crossed_extensions(&self, kind: &OperationKind) -> Vec { + if self.active_extensions.is_empty() { + return Vec::new(); + } + let subjects = barriers::subjects_of(kind, &self.score); + barriers::prohibiting_extensions( + &self.active_extensions, + kind.tag(), + &subjects, + &barriers::ScoreOracle(&self.score), + ) + } + + /// Records that an unsafe edit crossed `extension`: its chunks are now + /// bound for tombstoning ([`Self::extensions_requiring_tombstone`]), and — + /// since its data will no longer be preserved — its barriers no longer + /// bind, so the declaration leaves the active set. + fn record_unsafe_crossing(&mut self, extension: ExtensionRef) { + self.pending_extension_tombstones.insert(extension); + self.active_extensions.retain(|e| e.extension != extension); + } + /// The staff and diatonic pitch at a world `point` — the **vertical half** of a /// click-to-insert. Finds the staff the click is over (the nearest staff by its /// rendered line band) and the natural pitch at that height under the staff's @@ -797,10 +925,61 @@ impl EditorSession { /// Applies a single primitive operation: mints an envelope and commits it. A /// [`OperationKind::DeclareTransaction`] is not a primitive mutation — the session /// declares transactions via [`Self::apply_transaction`] — so it is refused here. + /// + /// Two pre-mint gates run, in order (both refuse with the op log untouched): + /// + /// 1. **Edit barriers** (Chapter 8 §"Behavior Under Unknown Extensions"): + /// the edit is checked against every active barrier; a match is refused + /// ([`EditorError::BarrierProhibited`]). The barrier gate runs *first* + /// because its prohibition is the spec's normative MUST and its refusal + /// names the unsafe-edit escape ([`Self::apply_unsafe`]); the advisory + /// check is the author's local policy. + /// 2. **Advisory preconditions** (Chapter 6 §"Validation Modes"): the + /// session is authoring mode, so advisory preconditions are checked + /// against the current materialized score, and any violation refuses the + /// edit ([`EditorError::AdvisoryViolation`]). Reduction itself stays pure + /// replay mode — it never consults advisory checks. pub fn apply(&mut self, kind: OperationKind) -> Result { if matches!(kind, OperationKind::DeclareTransaction(_)) { return Err(EditorError::DeclareTransactionNotAllowed); } + if let Some(refusal) = self.barrier_refusal(&kind) { + return Err(refusal); + } + self.apply_past_barriers(kind) + } + + /// Applies a single primitive operation as an **unsafe edit** (Chapter 8 + /// §"Behavior Under Unknown Extensions"): the explicit user action that + /// crosses matching edit barriers, acknowledging the loss of the crossed + /// extensions' data. Everything else about [`Self::apply`] holds — the + /// advisory gate still runs, and a failed edit changes nothing (including + /// the tombstone record: an edit that did not land loses no data). + /// + /// On success, every crossed extension is recorded in + /// [`Self::extensions_requiring_tombstone`] (the spec's MUST: its chunks + /// are tombstoned rather than silently invalidated) and removed from the + /// active set. An unsafe apply that crosses no barrier is an ordinary + /// apply. + pub fn apply_unsafe(&mut self, kind: OperationKind) -> Result { + if matches!(kind, OperationKind::DeclareTransaction(_)) { + return Err(EditorError::DeclareTransactionNotAllowed); + } + let crossed = self.crossed_extensions(&kind); + let outcome = self.apply_past_barriers(kind)?; + for extension in crossed { + self.record_unsafe_crossing(extension); + } + Ok(outcome) + } + + /// The shared tail of [`Self::apply`] / [`Self::apply_unsafe`]: everything + /// past the barrier gate (advisory gate, mint, commit). + fn apply_past_barriers(&mut self, kind: OperationKind) -> Result { + let violations = advisory_violations(&kind, &self.score); + if !violations.is_empty() { + return Err(EditorError::AdvisoryViolation { violations }); + } // The next id is one past every id ever minted (monotonic across undo), and the // context covers the currently-applied ops. let counter = self.authored.len() as u64; @@ -828,6 +1007,47 @@ impl EditorSession { category: Option, kinds: Vec, ) -> Result { + Self::check_transaction_shape(&kinds)?; + // The barrier gate (see `apply` for the gate ordering): the descriptor + // the session will mint and every member are each checked against every + // active barrier; any match refuses the whole transaction before + // anything is minted. + if let Some(refusal) = self.transaction_barrier_refusal(&kinds) { + return Err(refusal); + } + self.apply_transaction_past_barriers(label, category, kinds) + } + + /// [`Self::apply_transaction`] as an **unsafe edit** — the transaction + /// sibling of [`Self::apply_unsafe`]: matching edit barriers are crossed + /// rather than refused, and on success every crossed extension is recorded + /// for tombstoning and deactivated. The structural checks and the advisory + /// gate still apply, and a transaction that fails to commit records + /// nothing. + pub fn apply_transaction_unsafe( + &mut self, + label: &str, + category: Option, + kinds: Vec, + ) -> Result { + Self::check_transaction_shape(&kinds)?; + let mut crossed = self.crossed_extensions(&Self::descriptor_probe()); + for kind in &kinds { + for extension in self.crossed_extensions(kind) { + if !crossed.contains(&extension) { + crossed.push(extension); + } + } + } + let outcome = self.apply_transaction_past_barriers(label, category, kinds)?; + for extension in crossed { + self.record_unsafe_crossing(extension); + } + Ok(outcome) + } + + /// The structural refusals shared by both transaction entry points. + fn check_transaction_shape(kinds: &[OperationKind]) -> Result<(), EditorError> { // A member-less transaction would log a descriptor-only no-op (a dead // undo/sync unit). Refuse before minting anything. if kinds.is_empty() { @@ -841,6 +1061,49 @@ impl EditorSession { { return Err(EditorError::DeclareTransactionNotAllowed); } + Ok(()) + } + + /// The first active-barrier match across the transaction the session is + /// about to mint: the `DeclareTransaction` descriptor (a score-level + /// operation a score-wide barrier can prohibit), then each member in order. + fn transaction_barrier_refusal(&self, kinds: &[OperationKind]) -> Option { + self.barrier_refusal(&Self::descriptor_probe()) + .or_else(|| kinds.iter().find_map(|kind| self.barrier_refusal(kind))) + } + + /// A stand-in `DeclareTransaction` for gating: barrier matching reads only + /// the operation *class* (and, for a descriptor, no payload-named object), + /// so the placeholder id and label never influence the verdict. + fn descriptor_probe() -> OperationKind { + OperationKind::DeclareTransaction(TransactionDescriptor { + id: TransactionId::new(ReplicaId(0), 0), + label: String::new(), + category: None, + }) + } + + /// The shared tail of [`Self::apply_transaction`] / + /// [`Self::apply_transaction_unsafe`]: everything past the barrier gate. + fn apply_transaction_past_barriers( + &mut self, + label: &str, + category: Option, + kinds: Vec, + ) -> Result { + // Authoring mode (see `apply`): every member must pass its advisory + // preconditions before anything is minted. Members are checked against + // the current materialized score — the pre-transaction state — which is + // conservative for the rare member that only violates against another + // member's intermediate effect (advisory checks are the author's local + // policy, not canonical state, so this cannot diverge replicas). + let violations: Vec<_> = kinds + .iter() + .flat_map(|kind| advisory_violations(kind, &self.score)) + .collect(); + if !violations.is_empty() { + return Err(EditorError::AdvisoryViolation { violations }); + } let envelopes = self.transaction_envelopes(label, category, kinds); self.commit(envelopes) } @@ -1187,12 +1450,14 @@ impl EditorSession { /// goes into the staff's primary voice and **makes room** under an overwrite policy /// — an existing note/rest the new note fully covers is deleted, one it partially /// overlaps is trimmed, and one it lands inside is split (head trimmed, tail - /// re-inserted) — all as one transaction, so it applies atomically or not at all. + /// re-inserted), and a **tuplet** any part of the new note overlaps is cascaded away + /// whole (every member tombstoned, structure removed — tuplets are atomic) — all as + /// one transaction, so it applies atomically or not at all. /// /// Errors with [`EditorError::NoInsertTarget`] when the click resolves to no metric /// staff/position (or the overlap includes a non-note/rest event there is no - /// make-room rule for), or [`EditorError::OverlapsTuplet`] when make-room would have - /// to disturb a tuplet member (its duration is ratio-governed). + /// make-room rule for), or [`EditorError::OverlapsTuplet`] when the overlapped member + /// belongs to a *nested* tuplet, which the flat cascade cannot treat atomically. pub fn insert_note_at( &mut self, point: Point, @@ -1257,10 +1522,12 @@ impl EditorSession { /// Sets the selected event's written **duration** (a notation duration-palette /// gesture; the selection may be a notehead or a rest/stem). Shrinking just frees /// the space after the event; **lengthening makes room** under the overwrite policy - /// — the events it grows over are trimmed, deleted, or split, atomically with the - /// resize. Errors: [`InvalidDuration`](EditorError::InvalidDuration) for a - /// non-positive duration, [`OverlapsTuplet`](EditorError::OverlapsTuplet) when the - /// event (or one it grows over) is a tuplet member, and + /// — the events it grows over are trimmed, deleted, or split, and a tuplet it grows + /// over is cascaded away whole (tuplets are atomic), atomically with the resize. + /// Errors: [`InvalidDuration`](EditorError::InvalidDuration) for a non-positive + /// duration, [`OverlapsTuplet`](EditorError::OverlapsTuplet) when the *selected* event + /// is itself a tuplet member (in-place rescaling of a member is a later refinement) or + /// it grows over a *nested* tuplet the flat cascade cannot treat atomically, and /// [`WrongSelection`](EditorError::WrongSelection) when nothing apt is selected or /// the event is not metric. pub fn set_selection_duration( @@ -1348,8 +1615,13 @@ impl EditorSession { /// The events make-room must change to clear `[start, end)` in `voice` (other than /// `exclude`, the event being inserted/resized): whole-event deletes, in-place - /// trims, and splits. Errors on a tuplet member or a non-note/rest overlap there is - /// no make-room rule for. + /// trims, splits, and whole-tuplet cascade deletes. A tuplet is **atomic** — an + /// overlap with any of its members removes the whole tuplet (every member, plus the + /// structure), since a member's duration is ratio-bound and cannot be trimmed in + /// place. Errors with [`OverlapsTuplet`](EditorError::OverlapsTuplet) for a *nested* + /// tuplet (cascading one level only is not yet safe), [`NoInsertTarget`] for a + /// non-note/rest overlap, and [`DecomposedEvent`](EditorError::DecomposedEvent) for a + /// trim/split of a (non-tuplet) decomposed event. fn make_room( &self, voice: VoiceId, @@ -1358,6 +1630,8 @@ impl EditorSession { exclude: Option, ) -> Result { let mut room = MakeRoom::default(); + let mut cascade_tuplets: std::collections::BTreeSet = + std::collections::BTreeSet::new(); for event in self.score.events.iter() { if event.voice() != voice || Some(event.id()) == exclude { continue; @@ -1376,8 +1650,17 @@ impl EditorSession { if !(ep < end && start < &event_end) { continue; // disjoint from [start, end) } - if self.event_in_tuplet(event.id()) { - return Err(EditorError::OverlapsTuplet); + // A tuplet member: mark its (flat) tuplet for whole-tuplet cascade deletion, + // and stop treating it as an ordinary overlap. A nested tuplet is refused. + let containing = self.tuplets_containing(event.id()); + if !containing.is_empty() { + for tuplet in containing { + if !self.is_flat_tuplet(tuplet) { + return Err(EditorError::OverlapsTuplet); + } + cascade_tuplets.insert(tuplet); + } + continue; } if !matches!(event, Event::Pitched(_) | Event::Rest(_)) { return Err(EditorError::NoInsertTarget); // no make-room rule for this kind @@ -1412,9 +1695,64 @@ impl EditorSession { )), } } + // Expand each cascade tuplet into deletes of all its live members. The first + // member removes the tuplet structure (so the rest no longer belong to a tuplet + // and delete as ordinary events); the order is preserved by `make_room_ops`. + for tuplet in cascade_tuplets { + for (i, member) in self.tuplet_members(tuplet).into_iter().enumerate() { + let compensation = if i == 0 { + TupletCompensation::CascadeDeleteTuplets { + tuplets: vec![tuplet], + } + } else { + TupletCompensation::NotInTuplet + }; + room.cascade_deletes.push((member, compensation)); + } + } Ok(room) } + /// The ids of the tuplets `event` is a member of. + fn tuplets_containing(&self, event: EventId) -> Vec { + self.score + .cross_cutting + .tuplets + .iter() + .filter(|tuplet| tuplet.members.contains(&event)) + .map(|tuplet| tuplet.id) + .collect() + } + + /// Whether `tuplet` is flat — not nested inside another and not the parent of one. + /// Cascade-deleting a nested tuplet would leave the parent referencing tombstoned + /// members, so make-room refuses it for now. + fn is_flat_tuplet(&self, tuplet: TupletId) -> bool { + let tuplets = &self.score.cross_cutting.tuplets; + tuplets + .iter() + .find(|t| t.id == tuplet) + .is_some_and(|t| t.parent.is_none()) + && !tuplets.iter().any(|t| t.parent == Some(tuplet)) + } + + /// `tuplet`'s live member events, in member order. + fn tuplet_members(&self, tuplet: TupletId) -> Vec { + self.score + .cross_cutting + .tuplets + .iter() + .find(|t| t.id == tuplet) + .map(|t| { + t.members + .iter() + .copied() + .filter(|m| self.score.events.get(*m).is_some()) + .collect() + }) + .unwrap_or_default() + } + /// Turns a [`MakeRoom`] into operations: trims (`ModifyEvent`), deletes /// (`DeleteEvent`), and split tails (`InsertEvent`, cloning the original event's /// shape with fresh ids, carrying any authored spelling via `RespellPitch`). Order @@ -1426,6 +1764,14 @@ impl EditorSession { minter: &mut Minter, ) -> Vec { let mut ops: Vec = Vec::new(); + // Cascade-delete whole tuplets first, in order — the structure-removing delete + // must precede the members that then delete as ordinary (no-longer-tuplet) events. + for (event, tuplet_compensation) in room.cascade_deletes { + ops.push(OperationKind::DeleteEvent(DeleteEventOp { + event, + tuplet_compensation, + })); + } for event in room.trims { ops.push(OperationKind::ModifyEvent(ModifyEventOp { event })); } @@ -1802,6 +2148,12 @@ struct MakeRoom { trims: Vec, deletes: Vec, tails: Vec<(Event, MusicalPosition, MusicalDuration)>, + /// Whole-tuplet cascade deletes: every member of each overlapped tuplet, paired with + /// its delete compensation. The first member of a tuplet carries + /// [`TupletCompensation::CascadeDeleteTuplets`] (which removes the tuplet structure); + /// the rest are then ordinary [`NotInTuplet`](TupletCompensation::NotInTuplet) + /// deletes, so they must apply in this order. + cascade_deletes: Vec<(EventId, TupletCompensation)>, } /// Mints fresh event/pitch ids within one intent, advancing local counters (checked, @@ -2991,20 +3343,76 @@ mod tests { } #[test] - fn insert_note_at_refuses_to_disturb_a_tuplet() { + fn insert_note_at_cascades_a_whole_tuplet() { let mut session = open_rich(0x5EED); - // The rich fixture's first metric region is an eighth-note triplet; covering a - // member would need tuplet compensation, so the insert is refused. + // The rich fixture's first metric region is a 3:2 eighth-note triplet over + // [0, 1/4), and its first member carries an in-tuplet decomposition. Tuplets are + // atomic: a pencil overwrite touching any member removes the *whole* tuplet — + // every member, the structure, and the now-orphaned decomposition — freeing the + // span for the new note and leaving an invariant-valid graph. let region = a_region_with(&session, true); + let voice = primary_voice(&session, region); + let members: Vec = voice_events(&session, voice) + .into_iter() + .map(|(id, _, _)| id) + .collect(); + assert_eq!(members.len(), 3, "the region is a three-member triplet"); assert!( - session - .score() - .cross_cutting - .tuplets - .iter() - .any(|t| !t.members.is_empty()), - "the fixture region is a tuplet" + !session.score().cross_cutting.tuplets.is_empty(), + "the region starts as a tuplet" ); + + // Click the first member's onset with a grid of its own (eighth-note) value, so + // the new note overlaps just that one member — yet the whole triplet cascades. + let (_, pos, dur) = voice_events(&session, voice).into_iter().next().unwrap(); + let (_, _, origin_y) = region_staff_line(&session, region); + let at = click_for_position(&session, region, &pos, origin_y + 1.0); + session + .insert_note_at(at, &GridResolution { step: dur.clone() }) + .expect("the overwrite cascades the tuplet and inserts the note"); + + let after = voice_events(&session, voice); + assert!( + members + .iter() + .all(|m| !after.iter().any(|(id, _, _)| id == m)), + "every original triplet member is gone" + ); + assert!( + session.score().cross_cutting.tuplets.is_empty(), + "the tuplet structure is removed" + ); + let inserted = after + .iter() + .find(|(id, _, _)| !members.contains(id)) + .expect("the new note was inserted"); + assert_eq!(inserted.1, pos, "the new note sits at the clicked onset"); + assert_eq!(inserted.2, dur, "the new note has the grid duration"); + assert!( + epiphany_core::check_invariants(session.score()).is_empty(), + "the cascaded graph is invariant-valid" + ); + } + + #[test] + fn insert_note_at_over_a_nested_tuplet_is_refused() { + use epiphany_core::{Tuplet, TupletRatio}; + // A nested tuplet's ratio arithmetic a flat cascade cannot restate, so make-room + // refuses rather than corrupt it. Give the fixture's flat triplet a child tuplet + // so it is no longer flat, then try to overwrite one of its members. + let mut score = valid_score_rich(0x5EED); + let triplet_id = score.cross_cutting.tuplets[0].id; + let replica = score.identity.replica_id; + score.cross_cutting.tuplets.push(Tuplet { + id: TupletId::new(replica, 7_000_002), + ratio: TupletRatio::new(3, 2).unwrap(), + members: vec![], + parent: Some(triplet_id), + required_total: MusicalDuration(RationalTime::new(1, 8).unwrap()), + }); + let mut session = EditorSession::open(score, Box::new(StubSolver)).expect("renders"); + + let region = a_region_with(&session, true); let voice = primary_voice(&session, region); let (_, pos, dur) = voice_events(&session, voice).into_iter().next().unwrap(); let (_, _, origin_y) = region_staff_line(&session, region); @@ -3645,6 +4053,86 @@ mod tests { ); } + #[test] + fn advisory_violating_edit_is_refused_in_authoring_but_reduces_in_replay() { + // Chapter 6 §"Validation Modes": the session is authoring mode — an + // advisory-violating operation is refused before an envelope is minted + // — while the same operation, minted elsewhere, reduces cleanly through + // raw OperationSet reduction (replay mode enforces only invariant + // preconditions; advisory ones fail silently). + use epiphany_core::{ + AnchorOffset, MusicalDuration, MusicalPosition, RationalTime, RegionEdge, TimeAnchor, + WallClockTime, + }; + + // The plain fixture, with its single region given a *musical* end + // bound of 12 whole units (the fixture's own extent is wall-clock, + // which the advisory boundary check cannot resolve). + let mut score = valid_score(0x5EED); + let region_id = score.canvas.regions[0].id; + score.canvas.regions[0].time_extent.end = TimeAnchor::Region { + id: region_id, + edge: RegionEdge::Start, + offset: AnchorOffset::Musical(MusicalDuration(RationalTime::from_int(12))), + }; + let instance = score.canvas.regions[0].staff_instances()[0].id; + let voice = score.canvas.regions[0].staff_instances()[0].voices[0].id; + + // An insert whose span straddles the bound: starts at 10, ends at 14 — + // applying it would require splitting the event across the boundary. + let event_id = EventId::new(ReplicaId(50), 999); + let kind = OperationKind::InsertEvent(InsertEventOp { + staff_instance: instance, + event: epiphany_ops::valuegen::insert_event_value( + event_id, + voice, + MusicalPosition(RationalTime::from_int(10)), + MusicalDuration(RationalTime::from_int(4)), + &[PitchId::new(ReplicaId(50), 998)], + ), + }); + + // Authoring: refused pre-mint, on both the single-op and the + // transaction seam; the op log stays untouched. + let mut session = + EditorSession::open(score.clone(), Box::new(StubSolver)).expect("the fixture renders"); + let err = session + .apply(kind.clone()) + .expect_err("an advisory violation must refuse the edit"); + assert!(matches!(err, EditorError::AdvisoryViolation { .. })); + assert!(session.applied_operations().is_empty()); + let err = session + .apply_transaction("cross-boundary insert", None, vec![kind.clone()]) + .expect_err("an advisory-violating member must refuse the transaction"); + assert!(matches!(err, EditorError::AdvisoryViolation { .. })); + assert!(session.applied_operations().is_empty()); + + // Replay: the same operation in an envelope reduces cleanly and the + // event materializes — the advisory check has no channel into + // reduction. + let id = epiphany_core::OperationId::new(ReplicaId(50), 0); + let env = OperationEnvelope { + id, + author: AuthorId(7), + stamp: OperationStamp::new(HybridLogicalClock::new(WallClockTime(1), 0), id), + causal_context: CausalContext::new(), + transaction: None, + payload: OperationPayload::Primitive(kind), + }; + let mut set = OperationSet::new(); + assert_eq!(set.accept(env), AcceptOutcome::Accepted); + let materialized = set.reduce_onto(&score); + assert!( + materialized.state.is_clean(), + "replay applies the advisory-violating insert cleanly: {:?}", + materialized.state + ); + assert!( + materialized.score.events.get(event_id).is_some(), + "the event materializes under replay" + ); + } + #[test] fn add_note_to_selection_adds_a_chord_note_above_the_top() { let mut session = open_rich(0x5EED); @@ -4611,4 +5099,307 @@ mod tests { "a rejected edit leaves the document untouched" ); } + + // --- The edit-barrier gate (Chapter 8 §"Behavior Under Unknown Extensions") --- + + use epiphany_layout_ir::{BarrierCondition, BarrierScope, EditBarrier, ObjectKind}; + + /// A whole-score barrier prohibiting one operation class (no object-kind or + /// condition narrowing), as extension `ext` would declare it. + fn extension_prohibiting(ext: u128, op: OperationKindTag) -> ActiveExtension { + ActiveExtension { + extension: ExtensionRef(ext), + barriers: vec![EditBarrier { + scope: BarrierScope::WholeScore, + affected_object_kinds: vec![], + prohibited_operation_kinds: vec![op], + condition: BarrierCondition::Always, + }], + } + } + + /// The first event in the plain fixture's (single) voice, and a delete of it. + fn first_event_delete(session: &EditorSession) -> (EventId, OperationKind) { + let event = session + .score() + .voices() + .find_map(|(_, _, v)| v.events.first().copied()) + .expect("the fixture has an event"); + let delete = OperationKind::DeleteEvent(DeleteEventOp { + event, + tuplet_compensation: TupletCompensation::NotInTuplet, + }); + (event, delete) + } + + #[test] + fn a_barrier_matching_edit_is_refused_and_a_non_matching_edit_proceeds() { + let mut session = open_plain(7); + let (_, delete) = first_event_delete(&session); + session.set_active_extensions(vec![extension_prohibiting( + 0xE1, + OperationKindTag::DeleteEvent, + )]); + + // The matching edit is refused, naming the declaring extension, with + // nothing minted (the op log untouched). + assert_eq!( + session.apply(delete.clone()), + Err(EditorError::BarrierProhibited { + extension: ExtensionRef(0xE1), + operation: OperationKindTag::DeleteEvent, + }) + ); + assert!(session.applied_operations().is_empty()); + + // An edit of a different operation class proceeds. + let pitch = last_event_pitch(&session); + let transpose = OperationKind::Transpose(TransposeOp { + targets: vec![pitch], + chromatic_steps: 1, + }); + session + .apply(transpose) + .expect("a non-prohibited class passes the gate"); + assert_eq!(session.applied_operations().len(), 1); + } + + #[test] + fn a_region_scoped_barrier_gates_by_the_targets_real_containment() { + // A barrier scoped to a *different* region does not prohibit deleting + // an event here — known scopes are evaluated precisely against the + // target's containment, not conservatively. + let mut session = open_plain(7); + let (_, delete) = first_event_delete(&session); + let elsewhere = RegionId::from_raw(u128::MAX); + let scoped = |region| ActiveExtension { + extension: ExtensionRef(0xE2), + barriers: vec![EditBarrier { + scope: BarrierScope::Region(region), + affected_object_kinds: vec![], + prohibited_operation_kinds: vec![OperationKindTag::DeleteEvent], + condition: BarrierCondition::Always, + }], + }; + session.set_active_extensions(vec![scoped(elsewhere)]); + session + .apply(delete.clone()) + .expect("a barrier over another region does not bind here"); + + // The same barrier scoped to the event's own region refuses the edit. + let mut session = open_plain(7); + let (_, delete) = first_event_delete(&session); + let here = session.score().canvas.regions[0].id; + session.set_active_extensions(vec![scoped(here)]); + assert_eq!( + session.apply(delete), + Err(EditorError::BarrierProhibited { + extension: ExtensionRef(0xE2), + operation: OperationKindTag::DeleteEvent, + }) + ); + } + + #[test] + fn an_object_kind_narrowed_barrier_matches_only_that_kind() { + // A barrier protecting only Pitch objects prohibits a transpose but not + // an event delete, even under the same prohibited class list. + let mut session = open_plain(7); + let pitch = last_event_pitch(&session); + let pitch_kind = ObjectKind::of(&TypedObjectId::Pitch(pitch)); + session.set_active_extensions(vec![ActiveExtension { + extension: ExtensionRef(0xE3), + barriers: vec![EditBarrier { + scope: BarrierScope::WholeScore, + affected_object_kinds: vec![pitch_kind], + prohibited_operation_kinds: vec![ + OperationKindTag::Transpose, + OperationKindTag::DeleteEvent, + ], + condition: BarrierCondition::Always, + }], + }]); + let transpose = OperationKind::Transpose(TransposeOp { + targets: vec![pitch], + chromatic_steps: 1, + }); + assert!(matches!( + session.apply(transpose), + Err(EditorError::BarrierProhibited { .. }) + )); + let (_, delete) = first_event_delete(&session); + session + .apply(delete) + .expect("an Event target does not match a Pitch-kind barrier"); + } + + #[test] + fn an_unsafe_edit_crosses_the_barrier_and_records_the_tombstone_obligation() { + let mut session = open_plain(7); + let (_, delete) = first_event_delete(&session); + session.set_active_extensions(vec![extension_prohibiting( + 0xE4, + OperationKindTag::DeleteEvent, + )]); + assert!(matches!( + session.apply(delete.clone()), + Err(EditorError::BarrierProhibited { .. }) + )); + + // The explicit unsafe edit proceeds ... + let outcome = session.apply_unsafe(delete).expect("the unsafe edit lands"); + assert!(outcome.graph_changed); + // ... records that the crossed extension's chunks MUST be tombstoned + // (spec §"Behavior Under Unknown Extensions") ... + assert!(session + .extensions_requiring_tombstone() + .contains(&ExtensionRef(0xE4))); + // ... and deactivates the extension (its data is gone, so its barriers + // no longer bind): the next matching edit passes the ordinary gate. + assert!(session.active_extensions().is_empty()); + let (_, next_delete) = first_event_delete(&session); + session + .apply(next_delete) + .expect("the crossed extension's barriers no longer bind"); + } + + #[test] + fn an_unsafe_edit_crossing_no_barrier_records_nothing() { + let mut session = open_plain(7); + session.set_active_extensions(vec![extension_prohibiting( + 0xE5, + OperationKindTag::DeleteEvent, + )]); + let pitch = last_event_pitch(&session); + session + .apply_unsafe(OperationKind::Transpose(TransposeOp { + targets: vec![pitch], + chromatic_steps: 1, + })) + .expect("an unsafe apply of a non-matching edit is an ordinary apply"); + assert!(session.extensions_requiring_tombstone().is_empty()); + assert_eq!(session.active_extensions().len(), 1); + } + + #[test] + fn the_barrier_gate_and_the_advisory_gate_coexist() { + use epiphany_core::{AnchorOffset, RegionEdge, ReplicaId}; + // The plain fixture with its region's end bound declared at 12 whole + // units — the shape under which an event spanning 10..14 fails the + // InsertEvent advisory precondition (Chapter 6 §6.10). + let mut score = valid_score(7); + let region_id = score.canvas.regions[0].id; + score.canvas.regions[0].time_extent.end = epiphany_core::TimeAnchor::Region { + id: region_id, + edge: RegionEdge::Start, + offset: AnchorOffset::Musical(MusicalDuration(RationalTime::from_int(12))), + }; + let instance = score.canvas.regions[0].staff_instances()[0].id; + let voice = score.canvas.regions[0].staff_instances()[0].voices[0].id; + let mut session = + EditorSession::open(score, Box::new(StubSolver)).expect("the bounded fixture renders"); + let crossing_insert = |duration: i32| { + OperationKind::InsertEvent(InsertEventOp { + staff_instance: instance, + event: epiphany_ops::valuegen::insert_event_value( + EventId::new(ReplicaId(50), 999), + voice, + MusicalPosition(RationalTime::from_int(10)), + MusicalDuration(RationalTime::from_int(duration)), + &[PitchId::new(ReplicaId(50), 998)], + ), + }) + }; + + // With no barriers, the advisory gate alone refuses the crossing span. + assert!(matches!( + session.apply(crossing_insert(4)), + Err(EditorError::AdvisoryViolation { .. }) + )); + + // With a matching barrier, the barrier gate fires first (its refusal is + // the spec's MUST and names the unsafe-edit escape). + session.set_active_extensions(vec![extension_prohibiting( + 0xE6, + OperationKindTag::InsertEvent, + )]); + assert!(matches!( + session.apply(crossing_insert(4)), + Err(EditorError::BarrierProhibited { .. }) + )); + + // The unsafe path crosses the barrier but still enforces the advisory + // gate — and a refused edit loses no data, so nothing is recorded. + assert!(matches!( + session.apply_unsafe(crossing_insert(4)), + Err(EditorError::AdvisoryViolation { .. }) + )); + assert!(session.extensions_requiring_tombstone().is_empty()); + assert_eq!(session.active_extensions().len(), 1, "nothing was crossed"); + + // A span inside the bound passes the advisory gate; unsafely applying + // it crosses the barrier and records the obligation. + let outcome = session + .apply_unsafe(crossing_insert(2)) + .expect("within the bound, only the barrier stood in the way"); + assert!(outcome.graph_changed); + assert!(session + .extensions_requiring_tombstone() + .contains(&ExtensionRef(0xE6))); + } + + #[test] + fn a_transaction_is_gated_per_member_and_has_an_unsafe_sibling() { + let mut session = open_plain(7); + let pitch = last_event_pitch(&session); + let transpose = OperationKind::Transpose(TransposeOp { + targets: vec![pitch], + chromatic_steps: 1, + }); + session.set_active_extensions(vec![extension_prohibiting( + 0xE7, + OperationKindTag::Transpose, + )]); + + // A member matching a barrier refuses the whole transaction, unminted. + assert_eq!( + session.apply_transaction("sharpen", None, vec![transpose.clone()]), + Err(EditorError::BarrierProhibited { + extension: ExtensionRef(0xE7), + operation: OperationKindTag::Transpose, + }) + ); + assert!(session.applied_operations().is_empty()); + + // The unsafe sibling crosses and records. + session + .apply_transaction_unsafe("sharpen", None, vec![transpose]) + .expect("the unsafe transaction lands"); + assert!(session + .extensions_requiring_tombstone() + .contains(&ExtensionRef(0xE7))); + + // A score-wide barrier on the descriptor class gates transactions as a + // whole: DeclareTransaction is a score-level operation. + let mut session = open_plain(7); + let pitch = last_event_pitch(&session); + session.set_active_extensions(vec![extension_prohibiting( + 0xE8, + OperationKindTag::DeclareTransaction, + )]); + assert_eq!( + session.apply_transaction( + "sharpen", + None, + vec![OperationKind::Transpose(TransposeOp { + targets: vec![pitch], + chromatic_steps: 1, + })], + ), + Err(EditorError::BarrierProhibited { + extension: ExtensionRef(0xE8), + operation: OperationKindTag::DeclareTransaction, + }) + ); + } } diff --git a/crates/epiphany-editor-gui/src/main.rs b/crates/epiphany-editor-gui/src/main.rs index 87b9f9c..c6a79ac 100644 --- a/crates/epiphany-editor-gui/src/main.rs +++ b/crates/epiphany-editor-gui/src/main.rs @@ -127,6 +127,7 @@ fn payload_label(payload: &OperationPayload) -> &'static str { }, OperationPayload::ResolveConflict(_) => "ResolveConflict", OperationPayload::UndoTransaction(_) => "UndoTransaction", + OperationPayload::ResolveEquivocation(_) => "ResolveEquivocation", } } diff --git a/crates/epiphany-engrave/src/lib.rs b/crates/epiphany-engrave/src/lib.rs index 3add97b..f40ce0e 100644 --- a/crates/epiphany-engrave/src/lib.rs +++ b/crates/epiphany-engrave/src/lib.rs @@ -14,11 +14,16 @@ //! [`Engraver`] runs a genuine deterministic **horizontal spacing pass** (see //! [`spacing`]) — placing each glyph-bearing slot left-to-right by a //! collision-aware advance (its preferred width floored by the real glyph -//! bearings) — and **evaluates the IR's declared hard constraints** against the -//! resolved geometry (no-collision, alignment, position-within; a hard break or -//! unverifiable extension constraint it cannot honour is reported unsatisfied). -//! A solve is [`SolveStatus::Solved`] only when every hard constraint is -//! satisfied; otherwise it is a diagnostic layout naming the ones it could not. +//! bearings) — and **evaluates the IR's declared constraints** against the +//! resolved geometry, routed by [`LayoutConstraint::strength`] (Chapter 9 +//! §"Strength Levels"): a violated `Required` constraint (no-collision, +//! alignment, position-within, a hard break, an unverifiable extension +//! constraint) is reported unsatisfied and the solve is +//! [`SolveStatus::Unsatisfiable`]; a violated `Preferred` constraint (a soft +//! break this single-system solve does not honour) surfaces as a +//! [`SolverWarningKind::LargeSoftConstraintViolation`] warning under +//! [`SolveStatus::SolvedWithWarnings`], never a failure. A solve is +//! [`SolveStatus::Solved`] only when every declared constraint holds. //! //! Having earned it, [`Engraver::tier`] reports [`SolverTier::Minimal`] — which //! (Chapter 9 §"Conformance Tiers" / QUICKSTART) means *hard constraints @@ -44,11 +49,11 @@ mod spacing; use std::collections::BTreeMap; use epiphany_layout_ir::{ - all_available, Axis, BravuraCatalog, BreakKind, ConstrainedLayoutIR, ConstraintId, - ConstraintSolver, GlyphCatalog, GlyphObject, GlyphObjectId, InvalidationSet, LayoutConstraint, - Margins, Point, QualityMetricVector, Rect, ResolvedGlyph, ResolvedLayoutIR, ResolvedPage, - ResolvedSystem, Size2D, SolveReport, SolveStatus, SolverBudgetUsed, SolverConfig, SolverState, - SolverTier, SolverVersion, SolverWarning, SolverWarningKind, Stroke, + all_available, Axis, BravuraCatalog, ConstrainedLayoutIR, ConstraintId, ConstraintSolver, + ConstraintStrength, GlyphCatalog, GlyphObject, GlyphObjectId, InvalidationSet, + LayoutConstraint, Margins, Point, QualityMetricVector, Rect, ResolvedGlyph, ResolvedLayoutIR, + ResolvedPage, ResolvedSystem, Size2D, SolveReport, SolveStatus, SolverBudgetUsed, SolverConfig, + SolverState, SolverTier, SolverVersion, SolverWarning, SolverWarningKind, Stroke, }; /// The glyph a fixed-width stroke (a ledger line) belongs to: the same-source glyph @@ -82,11 +87,13 @@ pub const ENGRAVER_VERSION: SolverVersion = SolverVersion(1); impl Engraver { /// Resolves geometry: a deterministic horizontal spacing pass over the spring /// slots (each glyph to its slot's `x`, baseline `y` preserved), then - /// evaluation of the declared hard constraints. A malformed input — an unknown - /// glyph, a forged catalog identity, or invalid structure — yields - /// [`SolveStatus::InternalError`]; a valid problem whose hard constraints - /// cannot all be satisfied yields [`SolveStatus::Unsatisfiable`] (naming the - /// unsatisfied constraints). Both are diagnostic-only; neither panics. + /// evaluation of the declared constraints by strength. A malformed input — an + /// unknown glyph, a forged catalog identity, or invalid structure — yields + /// [`SolveStatus::InternalError`]; a valid problem whose `Required` + /// constraints cannot all be satisfied yields [`SolveStatus::Unsatisfiable`] + /// (naming the unsatisfied constraints). Both are diagnostic-only; neither + /// panics. Violated `Preferred` constraints yield soft-violation warnings + /// under [`SolveStatus::SolvedWithWarnings`] — a valid, renderable layout. fn resolve(&self, input: &ConstrainedLayoutIR) -> SolveReport { let structural_valid = input.validate().is_ok(); @@ -110,31 +117,43 @@ impl Engraver { }; let resolved_glyphs = glyphs.len(); - // Evaluate every declared hard constraint against the *resolved* geometry. - // A Minimal solve is `Solved` only when all are satisfied. A structurally - // invalid or bad-catalog input is not evaluated — there is no trustworthy - // geometry — so it reports no evaluation work. - let (constraints_satisfied, unsatisfied_constraints, constraints_evaluated) = - if structural_valid && catalog_valid { - let (satisfied, unsatisfied) = evaluate_constraints(&input.constraints, &glyphs); - (satisfied, unsatisfied, input.constraints.len() as u64) - } else { - (false, Vec::new(), 0) - }; - let well_formed = structural_valid && catalog_valid && constraints_satisfied; + // Evaluate every declared constraint against the *resolved* geometry, + // routed by its strength (Chapter 9 §"Strength Levels"): a violated + // `Required` constraint is unsatisfied (the solve is `Unsatisfiable`); + // a violated `Preferred` one is a soft-violation *warning*, never a + // failure. A structurally invalid or bad-catalog input is not evaluated + // — there is no trustworthy geometry — so it reports no evaluation work. + let (evaluation, constraints_evaluated) = if structural_valid && catalog_valid { + ( + evaluate_constraints(&input.constraints, &glyphs), + input.constraints.len() as u64, + ) + } else { + (ConstraintEvaluation::not_evaluated(), 0) + }; + let ConstraintEvaluation { + required_satisfied, + unsatisfied: unsatisfied_constraints, + soft_violations, + } = evaluation; + let well_formed = structural_valid && catalog_valid && required_satisfied; // Distinguish a *malformed/unusable* input (InternalError — a structural or // catalog defect the solver cannot proceed past) from a *valid problem // whose declared hard constraints cannot all be satisfied* (Unsatisfiable), - // per the solver-report contract (Chapter 9 §"The Solver Report"). + // per the solver-report contract (Chapter 9 §"The Solver Report"). Hard + // constraints all satisfied but soft ones violated is a valid layout + // worth flagging: SolvedWithWarnings. let status = if !structural_valid || !catalog_valid { SolveStatus::InternalError - } else if constraints_satisfied { - SolveStatus::Solved - } else { + } else if !required_satisfied { SolveStatus::Unsatisfiable + } else if !soft_violations.is_empty() { + SolveStatus::SolvedWithWarnings + } else { + SolveStatus::Solved }; - let mut warnings = Vec::new(); + let mut warnings = soft_violations; if structural_valid && catalog_valid && !unsatisfied_constraints.is_empty() { warnings.push(SolverWarning { kind: SolverWarningKind::UnusualLayoutDecision( @@ -313,27 +332,53 @@ fn interp((s0, t0): (f32, f32), (s1, t1): (f32, f32), x: f32) -> f32 { } } -/// Evaluates the IR's declared hard constraints against the *resolved* geometry, -/// returning whether all are satisfied and the ids of those that are not — a -/// constraint's id is its index in the IR's constraint list. +/// What evaluating the declared constraints found, routed by strength: whether +/// every `Required` constraint held, the ids of those that did not, and a +/// soft-violation warning per unhonoured `Preferred` constraint. +struct ConstraintEvaluation { + required_satisfied: bool, + unsatisfied: Vec, + soft_violations: Vec, +} + +impl ConstraintEvaluation { + /// The result for an input that was never evaluated (malformed structure or + /// catalog): nothing is claimed satisfied, nothing is named unsatisfied. + fn not_evaluated() -> Self { + ConstraintEvaluation { + required_satisfied: false, + unsatisfied: Vec::new(), + soft_violations: Vec::new(), + } + } +} + +/// Evaluates the IR's declared constraints against the *resolved* geometry — a +/// constraint's id is its index in the IR's constraint list — routing each +/// violation by [`LayoutConstraint::strength`] (Chapter 9 §"Strength Levels"): +/// a violated `Required` constraint is reported unsatisfied, a violated +/// `Preferred` one becomes a [`SolverWarningKind::LargeSoftConstraintViolation`] +/// warning and never fails the solve. /// /// Geometric constraints (no-collision, alignment, position-within) are checked -/// against the resolved glyph boxes. A *hard* break is reported unsatisfied — a -/// single-system, single-page Minimal solve casts off nothing, so it cannot force -/// a break (a *soft* break imposes no obligation). An extension `Registered` -/// constraint this solver cannot interpret is likewise not claimed satisfied -/// (Chapter 7 §"Behavior Under Unknown Extensions": conservative). +/// against the resolved glyph boxes. A break is never *honoured* — a +/// single-system, single-page Minimal solve casts off nothing — so a hard break +/// (`Required`) is unsatisfied and a soft break (`Preferred`) is a warning. An +/// extension `Registered` constraint this solver cannot interpret is likewise +/// not claimed satisfied (Chapter 7 §"Behavior Under Unknown Extensions": +/// conservative). fn evaluate_constraints( constraints: &[LayoutConstraint], glyphs: &[ResolvedGlyph], -) -> (bool, Vec) { +) -> ConstraintEvaluation { let by_id: BTreeMap = glyphs .iter() .map(|g| (GlyphObjectId(g.provenance.stable_id.0), g)) .collect(); let mut unsatisfied = Vec::new(); + let mut soft_violations = Vec::new(); for (index, constraint) in constraints.iter().enumerate() { - let satisfied = match constraint { + let holds = match constraint { LayoutConstraint::NoCollision { a, b } => match (by_id.get(a), by_id.get(b)) { (Some(a), Some(b)) => !overlaps(a, b), // A referenced glyph was dropped (a diagnostic layout): not claimed. @@ -347,15 +392,34 @@ fn evaluate_constraints( Some(g) => within(g, region), None => false, }, - LayoutConstraint::SystemBreakAt { kind, .. } - | LayoutConstraint::PageBreakAt { kind, .. } => matches!(kind, BreakKind::Soft), + LayoutConstraint::SystemBreakAt { .. } | LayoutConstraint::PageBreakAt { .. } => false, LayoutConstraint::Registered(_, _) => false, }; - if !satisfied { - unsatisfied.push(ConstraintId(index as u128)); + if holds { + continue; + } + let id = ConstraintId(index as u128); + match constraint.strength() { + ConstraintStrength::Required => unsatisfied.push(id), + ConstraintStrength::Preferred { .. } => soft_violations.push(SolverWarning { + kind: SolverWarningKind::LargeSoftConstraintViolation { + constraint: id, + // A break preference is binary — honoured or not — so an + // unhonoured one is a full (1.0) violation. + magnitude: 1.0, + }, + affected_objects: Vec::new(), + message: "a preferred (soft) constraint is not honoured by this \ + single-system Minimal solve" + .to_owned(), + }), } } - (unsatisfied.is_empty(), unsatisfied) + ConstraintEvaluation { + required_satisfied: unsatisfied.is_empty(), + unsatisfied, + soft_violations, + } } /// A resolved glyph's absolute bounding box `[left, bottom, right, top]`. @@ -519,14 +583,23 @@ mod tests { } #[test] - fn an_empty_constraint_set_is_vacuously_satisfied() { - let report = Engraver.solve(&fixture(), &SolverConfig::default()); + fn the_pipelines_emitted_constraints_are_satisfied() { + // The spacing stage now emits real constraints (no-collision chains, + // per-glyph containment) — this is *not* a vacuous empty-set solve. The + // collision-aware spacing satisfies every one of them, and the solve + // honestly reports the evaluation work it did. + let input = fixture(); + assert!( + !input.constraints.is_empty(), + "the pipeline declares real constraints" + ); + let report = Engraver.solve(&input, &SolverConfig::default()); assert_eq!(report.status, SolveStatus::Solved); assert!(report.satisfied_hard_constraints); assert!(report.unsatisfied_constraints.is_empty()); assert_eq!( report.budget_used.constraint_evaluations, - fixture().constraints.len() as u64 + input.constraints.len() as u64 ); } @@ -583,6 +656,8 @@ mod tests { #[test] fn a_hard_break_cannot_be_honoured_by_single_system_minimal() { use epiphany_layout_ir::{BreakKind, LayoutConstraint}; + // A hard break maps to ConstraintStrength::Required: a single-system + // solve cannot honour it, so the solve is Unsatisfiable. let input = with_constraints(|c| { let slot = c.horizontal_slots[0].id; vec![LayoutConstraint::SystemBreakAt { @@ -594,7 +669,9 @@ mod tests { assert_eq!(report.status, SolveStatus::Unsatisfiable); assert_eq!(report.unsatisfied_constraints.len(), 1); - // …but a *soft* break imposes no obligation, so it solves. + // …but a *soft* break is ConstraintStrength::Preferred: not honouring it + // is a soft-violation warning on a valid, renderable layout — a + // Preferred violation is a warning, never a failure. let soft = with_constraints(|c| { let slot = c.horizontal_slots[0].id; vec![LayoutConstraint::SystemBreakAt { @@ -602,10 +679,68 @@ mod tests { kind: BreakKind::Soft, }] }); - assert_eq!( - Engraver.solve(&soft, &SolverConfig::default()).status, - SolveStatus::Solved + let report = Engraver.solve(&soft, &SolverConfig::default()); + assert_eq!(report.status, SolveStatus::SolvedWithWarnings); + assert!(report.status.is_renderable()); + assert!( + report.satisfied_hard_constraints, + "a soft-break violation must not flip hard-constraint satisfaction" ); + assert!(report.unsatisfied_constraints.is_empty()); + assert!(report.warnings.iter().any(|w| matches!( + w.kind, + SolverWarningKind::LargeSoftConstraintViolation { + constraint: ConstraintId(0), + magnitude, + } if magnitude == 1.0 + ))); + } + + #[test] + fn a_users_break_flows_to_a_soft_violation_not_a_failure() { + // End to end: a user system break on the score graph projects through + // the logical stage's break override into a Soft break constraint, + // which this single-system solve does not honour — surfacing as a + // Preferred-violation warning on a valid, renderable layout. + use epiphany_core::generators::valid_score; + use epiphany_core::{AnchorOffset, Event, TimeAnchor}; + let mut score = valid_score(3); + let event = score.canvas.regions[0] + .staff_instances() + .iter() + .flat_map(|si| si.voices.iter()) + .flat_map(|voice| voice.events.iter().copied()) + .find(|eid| { + matches!(score.events.get(*eid), Some(Event::Pitched(p)) if !p.pitches.is_empty()) + }) + .expect("valid_score has a pitched event"); + score.canvas.regions[0] + .content + .staff_based_mut() + .expect("valid_score is staff based") + .user_system_breaks + .push(TimeAnchor::Event { + id: event, + offset: AnchorOffset::Zero, + }); + + let constrained = to_constrained(&to_logical(&score)); + assert!( + constrained + .constraints + .iter() + .any(|c| matches!(c, LayoutConstraint::SystemBreakAt { .. })), + "the user break projects into a break constraint" + ); + let report = Engraver.solve(&constrained, &SolverConfig::default()); + assert_eq!(report.status, SolveStatus::SolvedWithWarnings); + assert!(report.status.is_renderable()); + assert!(report.satisfied_hard_constraints); + assert!(report.unsatisfied_constraints.is_empty()); + assert!(report.warnings.iter().any(|w| matches!( + w.kind, + SolverWarningKind::LargeSoftConstraintViolation { .. } + ))); } #[test] diff --git a/crates/epiphany-layout-ir/DECISIONS.md b/crates/epiphany-layout-ir/DECISIONS.md index 3355bf7..47c82bb 100644 --- a/crates/epiphany-layout-ir/DECISIONS.md +++ b/crates/epiphany-layout-ir/DECISIONS.md @@ -244,6 +244,127 @@ object is covered); the provenance-preservation contract itself is unchanged. is the next layer, but the axis machinery now genuinely consumes whatever times the spacing assigns.) +- **`ConstraintStrength` is attached by rule, not by widening the IR.** Chapter 9 + §"Strength Levels" defines `ConstraintStrength { Required, Preferred { weight } }`, + but the spec's `LayoutConstraint` enum carries no strength field and the + "normalized form" the solver consumes never says how strength attaches to a + constraint instance (a genuine gap — see Pass 12 candidates below). Rather than + invent an IR shape the spec doesn't have, `LayoutConstraint::strength()` derives + strength from the constraint's own shape: a break's `BreakKind` *is* its + strength (`Hard` → `Required`, `Soft` → `Preferred { weight: 1.0 }`), the + geometric constraints (no-collision / alignment / containment) are `Required`, + and a `Registered` extension constraint is conservatively `Required` — an + obligation a solver cannot verify must never be silently demoted (Chapter 9: + a solver MUST NOT treat `Required` as `Preferred`). + +- **The spacing pass emits real constraints (Chapter 7 pipeline: "Build collision + constraints").** `try_to_constrained` now populates `constraints`, per region and + in a deterministic order: (1) **NoCollision** chains over *successive notehead + columns* within each staff — adjacent pairs in (column x, glyph id) order, linear + in the noteheads, never the O(n²) closure; chord members share a slot (a second + or unison may genuinely overlap by design), so only cross-column neighbours carry + the obligation. These hold under both v0 solvers: the source layout separates + columns collision-free and the engraver's collision-aware advance keeps + successive columns separated after its remap. (2) **PositionWithin** per glyph + against its region's envelope: the vertical extent is the exact envelope of the + region's glyph boxes (both v0 solvers preserve glyph `y` verbatim, so this is a + genuine obligation a future vertical pass must renegotiate); the horizontal span + is the open v0 canvas (`POSITION_WITHIN_X_REACH`) because v0 does no casting-off + — a region imposes no honest horizontal bound. (3) **Soft break constraints** + projected from the logical stage's break overrides, on the spring slot carrying + the break anchor's onset (the barline column at that time when one exists, else + the note column); an anchor no realized column represents — an event/measure + outside the region, a measure *end*, a region edge — is skipped silently, since + there is no slot for a solver to break at. The four SVG golden snapshots' + `hard_constraint_count` moved off 0 accordingly; the golden SVG *bytes* are + unchanged (emission does not touch geometry). + +- **The stub stays honest — and renderable — under declared constraints.** The + old `StubSolver` flipped to `InternalError` whenever a constraint was present, + which conflated "constraints I did not evaluate" with "a malformed input". Now: + geometry still passes through verbatim, `satisfied_hard_constraints` is `false` + (nothing was checked), a warning names the gap, and the status is + `SolvedWithWarnings` — the closest *non-claiming* renderable status, since + Chapter 9 defines no status for "renderable, constraints unevaluated" (a Pass 12 + candidate below). Editors gate on `SolveStatus::is_renderable()`, so stub-driven + pipelines (editor-core sessions, the edit-loop harness, the acceptance goldens) + keep working; the round-trip harness asserts the stub claims satisfaction + exactly when the problem is constraint-free. + +- **Break overrides carry their anchor; projected from the graph's break lists.** + Per the updated Chapter 7 §"Engraving Overrides", `OverrideKind::SystemBreak` / + `PageBreak` now carry `anchor: TimeAnchor` — a break addresses a *position*, + while the override's `ScoreGraph` target names the owning region. `to_logical` + projects each region's authoritative `user_system_breaks` / `user_page_breaks` + (Chapter 5) into `Soft`, `Internal`-origin overrides (authorship lives in the + op log until P11-C8), ordered by (region id, kind discriminant, anchor canonical + bytes), each with a paired `EngravingDecision` under + `DecisionSource::UserOverride(id)` (Chapter 7 §"Override Resolution" MUST). The + override id reuses the `MUSCLOID` derivation with a literal `engraving-override` + prefix (mirroring the decision id), keyed on (region, kind discriminant, anchor + canonical bytes). The variant-shape change is byte-visible only in memory: + overrides appear in **no** codec today (the layout IR chunks cache no override + records), so no stored or interchanged artifact changes — the stale + "graph exposes no override registry" comment this replaces predated the graph's + break lists. + +- **Edit-barrier decode mirrors + the manifest blob codec (PROVISIONAL byte + form, Push 3).** The barrier tree was encode-only; `barrier.rs` now carries + the exact inverse and the codec for the two opaque manifest fields the bundle + preserves verbatim (`ExtensionDeclaration.edit_barriers` / + `.affected_object_kinds` — the bundle stays semantics-free; no bundle change). + The spec defines **no normative byte form** for `EditBarrier`/`BarrierScope`/ + `BarrierCondition`, so this is a provisional canonical encoding on the + established pattern (define concretely, golden-lock, submit to the Binary + Format companion): both blobs are canonical **sets** in the crate's existing + `push_set` framing — `u64` LE count, then per element a `u64` LE length + prefix and the element's canonical bytes, elements strictly ascending + byte-lexicographic, duplicates removed — an `edit_barriers` element being an + `EditBarrier`'s canonical bytes (scope, affected-kind set, prohibited-tag + set, condition, in that order), an `affected_object_kinds` element being the + kind's 2 LE bytes. Golden literal-byte tests + (`edit_barriers_blob_bytes_are_golden`, + `affected_object_kinds_blob_bytes_are_golden`) lock the layout; the testkit + adds a generator-driven round-trip gate. Decode discipline is + reject-never-normalize (`BarrierDecodeError`): unknown scope/condition/ + operation-kind discriminants, unsorted or duplicated set elements, non-NFC + pitch-space text (`PitchSpaceId::new` would re-spell it, so the bytes are + non-canonical), truncation, and trailing bytes are all typed errors, and a + decoded barrier must re-encode byte-identically. Two deliberate choices: + (1) **`ObjectKind` decodes any `u16`** — the payload is an open discriminant + space (a future core kind or an extension-registered kind is a *value*, not + a decode branch), so there is nothing to reject without breaking append-only + forward compatibility; (2) **`MAX_CONDITION_DEPTH = 64`** bounds the + recursive `BarrierCondition` decode — the spec places no bound on the tree, + a decoder needs one against adversarial bytes, and 64 is far past any real + barrier (spec examples are depth 1–2). Both are named Binary Format + companion candidates. Evaluation wiring (the §"Behavior Under Unknown + Extensions" MUST) lives in epiphany-editor-core, which decodes injected + declarations and gates `apply`/`apply_transaction` through + `EditBarrier::prohibits_edit`. + +## Pass 12 candidates (ambiguities for the spec, not resolved in code) + +1. **Strength attachment to constraint instances.** Chapter 9 §"Strength Levels" + defines `ConstraintStrength`, and §"Constraint Families" says the solver + consumes constraints "in normalized form" — but the normalized form is never + specified, and Chapter 7's `LayoutConstraint` enum has no strength field, so + there is no normative channel by which a constraint instance carries its + strength. v0 attaches strength by rule (`LayoutConstraint::strength()`, above); + the spec should either bless that rule (breaks strength = `BreakKind`, all + other core families `Required`, extensions conservative) or add an explicit + strength/weight field to the normalized constraint record. + +2. **No renderable status for "constraints not evaluated".** A `Stub`-tier + (below-conformance) solver that preserves geometry but evaluates nothing has + no honest `SolveStatus`: every renderable status is documented as "all hard + constraints satisfied", and the failure statuses mark the layout + diagnostic-only, which a verbatim passthrough is not. v0 uses + `SolvedWithWarnings` with `satisfied_hard_constraints == false` and a warning; + the spec should either define the report shape for a non-evaluating tier or + state that `SolvedWithWarnings` + `satisfied_hard_constraints == false` is the + sanctioned encoding. + ## Pass 11 candidates (ambiguities for the spec, not resolved in code) 1. **Agent E's stated dependency set vs. the edit-barrier types.** The QUICKSTART diff --git a/crates/epiphany-layout-ir/src/barrier.rs b/crates/epiphany-layout-ir/src/barrier.rs index 145b795..d912993 100644 --- a/crates/epiphany-layout-ir/src/barrier.rs +++ b/crates/epiphany-layout-ir/src/barrier.rs @@ -19,7 +19,7 @@ //! identically. use epiphany_core::{AnalysisLayerId, PitchSpaceId, RegionId, StaffInstanceId, TypedObjectId}; -use epiphany_determinism::CanonicalEncode; +use epiphany_determinism::{CanonicalDecode, CanonicalEncode, DecodeError}; use epiphany_ops::OperationKindTag; /// The kind of a score-graph object a barrier protects (Chapter 8: @@ -394,6 +394,405 @@ impl CanonicalEncode for EditBarrier { } } +// --- Canonical decoding (the inverse) and the manifest blob codec ----------- +// +// PROVISIONAL byte form, pending Binary Format companion ratification (the +// established pattern: define concretely, golden-lock, document for the +// companion). The manifest's `ExtensionDeclaration.edit_barriers` / +// `.affected_object_kinds` fields are opaque bytes to the bundle (Agent D +// preserves them verbatim); this crate — the owner of the barrier types — owns +// what those bytes mean: +// +// * `encode_affected_object_kinds` / `decode_affected_object_kinds`: a +// canonical SET of [`ObjectKind`]s — `u64` LE count, then per element a +// `u64` LE length prefix and the element's canonical bytes (2 LE bytes), +// elements strictly ascending byte-lexicographic, no duplicates (the same +// `push_set` framing the barrier encoding itself uses). +// * `encode_edit_barriers` / `decode_edit_barriers`: a canonical SET of +// [`EditBarrier`]s under the identical framing, each element an +// `EditBarrier`'s canonical bytes. +// +// Decoding is reject-never-normalize (Appendix D discipline): unknown +// discriminants, unsorted or duplicated set elements, non-NFC pitch-space +// strings, over-deep condition trees, and trailing bytes are all typed errors. + +/// The maximum [`BarrierCondition`] nesting depth the decoder accepts. The +/// spec places no bound on the recursive condition tree; a decoder needs one +/// so adversarial bytes cannot drive unbounded recursion. 64 levels of +/// `All`/`Any`/`Not` nesting is far beyond any plausible real barrier (the +/// spec's own examples are depth 1–2); this constant is part of the +/// provisional byte contract and is a Binary Format companion candidate. +pub const MAX_CONDITION_DEPTH: usize = 64; + +/// Why decoding barrier bytes failed. Construction-side canonical bytes never +/// produce these; any of them means foreign, corrupt, or non-canonical data, +/// which is rejected rather than repaired. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum BarrierDecodeError { + /// A field ended before its declared or fixed width. + UnexpectedEof, + /// A length prefix cannot be represented safely by this process. + LengthOverflow, + /// A tagged union carried an unknown discriminant. + InvalidTag { kind: &'static str, tag: u8 }, + /// An embedded primitive failed its own canonical decoder. + InvalidValue(&'static str), + /// A canonical text field was not UTF-8. + InvalidUtf8, + /// A canonical text field was not in Unicode NFC (Appendix D §"Text and + /// Unicode" requires NFC bytes; a non-NFC spelling is rejected, never + /// silently normalized). + NotNfc, + /// A set-valued field was not in strictly ascending canonical byte order + /// (unsorted, or a duplicate element), or the bytes re-encoded differently. + NonCanonical(&'static str), + /// A condition tree nested deeper than [`MAX_CONDITION_DEPTH`]. + ConditionTooDeep, + /// Bytes remained after the complete value was decoded. + TrailingBytes, +} + +impl core::fmt::Display for BarrierDecodeError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::UnexpectedEof => f.write_str("unexpected end of edit-barrier bytes"), + Self::LengthOverflow => f.write_str("edit-barrier length does not fit usize"), + Self::InvalidTag { kind, tag } => write!(f, "invalid {kind} tag {tag}"), + Self::InvalidValue(kind) => write!(f, "invalid canonical {kind}"), + Self::InvalidUtf8 => f.write_str("invalid UTF-8 in canonical text"), + Self::NotNfc => f.write_str("canonical text is not NFC-normalized"), + Self::NonCanonical(what) => write!(f, "edit-barrier {what} is not in canonical form"), + Self::ConditionTooDeep => write!( + f, + "barrier condition nests deeper than {MAX_CONDITION_DEPTH}" + ), + Self::TrailingBytes => f.write_str("trailing bytes after edit-barrier value"), + } + } +} + +impl std::error::Error for BarrierDecodeError {} + +impl CanonicalDecode for ObjectKind { + /// Exactly the 2 little-endian bytes of the wrapped discriminant. Every + /// `u16` round-trips: the payload is an open discriminant space (a future + /// core kind or an extension-registered kind is a value, not a decode + /// branch), so there is no tag to reject here. + fn decode_canonical(bytes: &[u8]) -> Result { + let arr: [u8; 2] = bytes + .try_into() + .map_err(|_| DecodeError::UnexpectedLength { + expected: 2, + actual: bytes.len(), + })?; + Ok(ObjectKind(u16::from_le_bytes(arr))) + } +} + +/// Fixed-width 16-byte little-endian decode shared by the barrier registry-id +/// newtypes (mirroring their `to_le_bytes` encode above). +macro_rules! barrier_u128_le_decode { + ($name:ident) => { + impl CanonicalDecode for $name { + fn decode_canonical(bytes: &[u8]) -> Result { + let arr: [u8; 16] = + bytes + .try_into() + .map_err(|_| DecodeError::UnexpectedLength { + expected: 16, + actual: bytes.len(), + })?; + Ok($name(u128::from_le_bytes(arr))) + } + } + }; +} +barrier_u128_le_decode!(BarrierScopeRegistryId); +barrier_u128_le_decode!(BarrierConditionRegistryId); +barrier_u128_le_decode!(ExtensionRef); + +type DecodeResult = Result; + +struct Reader<'a> { + bytes: &'a [u8], + pos: usize, +} + +impl<'a> Reader<'a> { + fn new(bytes: &'a [u8]) -> Self { + Reader { bytes, pos: 0 } + } + + fn take(&mut self, n: usize) -> DecodeResult<&'a [u8]> { + let end = self + .pos + .checked_add(n) + .ok_or(BarrierDecodeError::LengthOverflow)?; + if end > self.bytes.len() { + return Err(BarrierDecodeError::UnexpectedEof); + } + let out = &self.bytes[self.pos..end]; + self.pos = end; + Ok(out) + } + + fn byte(&mut self) -> DecodeResult { + Ok(self.take(1)?[0]) + } + + /// A `u64` little-endian length/count field (the width `push_u64` writes), + /// converted to `usize`. + fn len(&mut self) -> DecodeResult { + let raw = u64::from_le_bytes(self.take(8)?.try_into().expect("fixed width")); + usize::try_from(raw).map_err(|_| BarrierDecodeError::LengthOverflow) + } + + /// A length-prefixed byte field (the form `push_elem`/`push_set` write). + fn lp_bytes(&mut self) -> DecodeResult<&'a [u8]> { + let len = self.len()?; + self.take(len) + } + + fn finish(self) -> DecodeResult<()> { + if self.pos == self.bytes.len() { + Ok(()) + } else { + Err(BarrierDecodeError::TrailingBytes) + } + } +} + +/// Runs `decode` over exactly `bytes` — trailing bytes are an error. +fn exact( + bytes: &[u8], + decode: impl FnOnce(&mut Reader<'_>) -> DecodeResult, +) -> DecodeResult { + let mut reader = Reader::new(bytes); + let value = decode(&mut reader)?; + reader.finish()?; + Ok(value) +} + +/// Reads a `push_set`-framed set: a count, then length-prefixed elements that +/// MUST be strictly ascending in raw byte order (the sorted, deduplicated form +/// the encoder emits). Unsorted or duplicated elements are rejected as +/// non-canonical, never re-sorted. +fn read_set<'a, T>( + reader: &mut Reader<'a>, + what: &'static str, + mut decode_elem: impl FnMut(&'a [u8]) -> DecodeResult, +) -> DecodeResult> { + let count = reader.len()?; + let mut values = Vec::with_capacity(count.min(1024)); + let mut prev: Option<&[u8]> = None; + for _ in 0..count { + let elem = reader.lp_bytes()?; + if let Some(prev) = prev { + if prev >= elem { + return Err(BarrierDecodeError::NonCanonical(what)); + } + } + prev = Some(elem); + values.push(decode_elem(elem)?); + } + Ok(values) +} + +/// Streams one `TypedObjectId` (variable width: 2-byte discriminant, then 16 +/// payload bytes — or 32 for the `Registered` variant, discriminant 27). +fn read_typed_object_id(reader: &mut Reader<'_>) -> DecodeResult { + let tag_bytes = reader + .bytes + .get(reader.pos..reader.pos.saturating_add(2)) + .ok_or(BarrierDecodeError::UnexpectedEof)?; + let tag = u16::from_be_bytes(tag_bytes.try_into().expect("two bytes")); + let width = if tag == 27 { 34 } else { 18 }; + TypedObjectId::decode_canonical(reader.take(width)?) + .map_err(|_| BarrierDecodeError::InvalidValue("TypedObjectId")) +} + +fn read_u128_le(reader: &mut Reader<'_>) -> DecodeResult { + Ok(u128::from_le_bytes( + reader.take(16)?.try_into().expect("fixed width"), + )) +} + +/// Streams one 16-byte big-endian graph identifier (the `graph_id!` canonical +/// form `RegionId`/`StaffInstanceId`/`AnalysisLayerId` share). +fn read_graph_id( + reader: &mut Reader<'_>, + name: &'static str, +) -> DecodeResult { + T::decode_canonical(reader.take(16)?).map_err(|_| BarrierDecodeError::InvalidValue(name)) +} + +fn read_scope(reader: &mut Reader<'_>) -> DecodeResult { + match reader.byte()? { + 0 => Ok(BarrierScope::WholeScore), + 1 => Ok(BarrierScope::Region(read_graph_id(reader, "RegionId")?)), + 2 => Ok(BarrierScope::StaffInstance(read_graph_id( + reader, + "StaffInstanceId", + )?)), + 3 => Ok(BarrierScope::AnalysisLayer(read_graph_id( + reader, + "AnalysisLayerId", + )?)), + 4 => Ok(BarrierScope::ObjectSet(read_set( + reader, + "object set", + |elem| { + TypedObjectId::decode_canonical(elem) + .map_err(|_| BarrierDecodeError::InvalidValue("TypedObjectId")) + }, + )?)), + 5 => { + let raw = reader.lp_bytes()?; + let s = core::str::from_utf8(raw).map_err(|_| BarrierDecodeError::InvalidUtf8)?; + // `PitchSpaceId::new` NFC-normalizes; canonical bytes MUST already + // be NFC, so a spelling the constructor would change is rejected + // rather than silently normalized (re-encoding it would differ). + let id = PitchSpaceId::new(s); + if id.as_str() != s { + return Err(BarrierDecodeError::NotNfc); + } + Ok(BarrierScope::PitchSpace(id)) + } + 6 => Ok(BarrierScope::TuningContext), + 7 => Ok(BarrierScope::Registered(BarrierScopeRegistryId( + read_u128_le(reader)?, + ))), + tag => Err(BarrierDecodeError::InvalidTag { + kind: "BarrierScope", + tag, + }), + } +} + +fn read_condition(reader: &mut Reader<'_>, depth: usize) -> DecodeResult { + if depth > MAX_CONDITION_DEPTH { + return Err(BarrierDecodeError::ConditionTooDeep); + } + match reader.byte()? { + 0 => Ok(BarrierCondition::Always), + 1 => Ok(BarrierCondition::ObjectExists(read_typed_object_id( + reader, + )?)), + 2 => Ok(BarrierCondition::ObjectHasExtensionData { + object: read_typed_object_id(reader)?, + extension: ExtensionRef(read_u128_le(reader)?), + }), + 3 => Ok(BarrierCondition::All(read_condition_list(reader, depth)?)), + 4 => Ok(BarrierCondition::Any(read_condition_list(reader, depth)?)), + 5 => { + let inner = exact(reader.lp_bytes()?, |r| read_condition(r, depth + 1))?; + Ok(BarrierCondition::Not(Box::new(inner))) + } + 6 => Ok(BarrierCondition::Registered(BarrierConditionRegistryId( + read_u128_le(reader)?, + ))), + tag => Err(BarrierDecodeError::InvalidTag { + kind: "BarrierCondition", + tag, + }), + } +} + +/// Reads a `push_list`-framed condition list (order-significant — the +/// *structure* of an `All`/`Any` tree, not a set). +fn read_condition_list( + reader: &mut Reader<'_>, + depth: usize, +) -> DecodeResult> { + let count = reader.len()?; + let mut conditions = Vec::with_capacity(count.min(1024)); + for _ in 0..count { + conditions.push(exact(reader.lp_bytes()?, |r| read_condition(r, depth + 1))?); + } + Ok(conditions) +} + +fn read_barrier(reader: &mut Reader<'_>) -> DecodeResult { + Ok(EditBarrier { + scope: read_scope(reader)?, + affected_object_kinds: read_set(reader, "affected object kinds", |elem| { + ObjectKind::decode_canonical(elem) + .map_err(|_| BarrierDecodeError::InvalidValue("ObjectKind")) + })?, + prohibited_operation_kinds: read_set(reader, "prohibited operation kinds", |elem| { + OperationKindTag::decode_canonical(elem).map_err(|err| match (err, elem.first()) { + (DecodeError::MalformedDomainTag, Some(&tag)) => BarrierDecodeError::InvalidTag { + kind: "OperationKindTag", + tag, + }, + _ => BarrierDecodeError::InvalidValue("OperationKindTag"), + }) + })?, + condition: read_condition(reader, 1)?, + }) +} + +impl EditBarrier { + /// Decodes exactly one barrier from its canonical bytes (the inverse of + /// [`CanonicalEncode`]); trailing bytes and every non-canonical form are + /// rejected. The manifest blob form is [`decode_edit_barriers`]. + pub fn decode_canonical_bytes(bytes: &[u8]) -> DecodeResult { + let barrier = exact(bytes, read_barrier)?; + // Belt and braces: canonical decode admits exactly the encoder's image, + // so the round-trip must be byte-identical. + if barrier.to_canonical_bytes() != bytes { + return Err(BarrierDecodeError::NonCanonical("barrier bytes")); + } + Ok(barrier) + } +} + +/// Encodes a set of edit barriers to the canonical blob stored in +/// `ExtensionDeclaration.edit_barriers`: `push_set` framing (`u64` LE count, +/// then per barrier a `u64` LE length prefix and the barrier's canonical +/// bytes), sorted ascending by encoded bytes with duplicates removed, so the +/// blob is order- and repetition-independent. +pub fn encode_edit_barriers(barriers: &[EditBarrier]) -> Vec { + let mut out = Vec::new(); + push_set(&mut out, barriers); + out +} + +/// Decodes an `ExtensionDeclaration.edit_barriers` blob (the inverse of +/// [`encode_edit_barriers`]). Rejects unsorted/duplicated barriers, unknown +/// discriminants anywhere in the tree, non-NFC pitch-space text, over-deep +/// condition trees, and trailing bytes. +pub fn decode_edit_barriers(bytes: &[u8]) -> DecodeResult> { + let barriers = exact(bytes, |reader| { + read_set( + reader, + "edit-barrier set", + EditBarrier::decode_canonical_bytes, + ) + })?; + Ok(barriers) +} + +/// Encodes a set of object kinds to the canonical blob stored in +/// `ExtensionDeclaration.affected_object_kinds` (the same `push_set` framing +/// as [`encode_edit_barriers`]; each element is the kind's 2 LE bytes). +pub fn encode_affected_object_kinds(kinds: &[ObjectKind]) -> Vec { + let mut out = Vec::new(); + push_set(&mut out, kinds); + out +} + +/// Decodes an `ExtensionDeclaration.affected_object_kinds` blob (the inverse +/// of [`encode_affected_object_kinds`]). +pub fn decode_affected_object_kinds(bytes: &[u8]) -> DecodeResult> { + exact(bytes, |reader| { + read_set(reader, "affected-object-kind set", |elem| { + ObjectKind::decode_canonical(elem) + .map_err(|_| BarrierDecodeError::InvalidValue("ObjectKind")) + }) + }) +} + #[cfg(test)] mod tests { use super::*; @@ -546,6 +945,282 @@ mod tests { assert_eq!(one.to_canonical_bytes(), repeated.to_canonical_bytes()); } + // --- Decode mirrors + the manifest blob codec --------------------------- + + fn u64le(n: u64) -> Vec { + n.to_le_bytes().to_vec() + } + + /// `push_set` framing assembled by hand, so the reject tests can produce + /// deliberately non-canonical framings the encoder never emits. + fn set_blob(elems: &[Vec]) -> Vec { + let mut out = u64le(elems.len() as u64); + for elem in elems { + out.extend(u64le(elem.len() as u64)); + out.extend(elem); + } + out + } + + #[test] + fn affected_object_kinds_blob_bytes_are_golden() { + // GOLDEN LOCK (provisional canonical form, pending Binary Format + // companion ratification): u64 LE count, then per element a u64 LE + // length prefix and the ObjectKind's 2 LE bytes, ascending, deduped. + let blob = encode_affected_object_kinds(&[ObjectKind(1), ObjectKind(0), ObjectKind(1)]); + #[rustfmt::skip] + const GOLDEN: [u8; 28] = [ + 2, 0, 0, 0, 0, 0, 0, 0, // count = 2 (the duplicate collapses) + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, // len 2, ObjectKind(0) + 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, // len 2, ObjectKind(1) + ]; + assert_eq!(blob, GOLDEN); + assert_eq!( + decode_affected_object_kinds(&GOLDEN).unwrap(), + vec![ObjectKind(0), ObjectKind(1)] + ); + } + + #[test] + fn edit_barriers_blob_bytes_are_golden() { + // GOLDEN LOCK (provisional canonical form, pending Binary Format + // companion ratification): the set framing wraps each barrier's + // canonical bytes — scope, affected-kind set, prohibited-tag set, + // condition, in that order. + let barrier = EditBarrier { + scope: BarrierScope::WholeScore, + affected_object_kinds: vec![ObjectKind(1)], + prohibited_operation_kinds: vec![OperationKindTag::DeleteEvent], + condition: BarrierCondition::Always, + }; + let blob = encode_edit_barriers(std::slice::from_ref(&barrier)); + #[rustfmt::skip] + const GOLDEN: [u8; 53] = [ + 1, 0, 0, 0, 0, 0, 0, 0, // set count = 1 + 37, 0, 0, 0, 0, 0, 0, 0, // barrier byte length + 0, // scope: WholeScore + 1, 0, 0, 0, 0, 0, 0, 0, // affected kinds: count = 1 + 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, // len 2, ObjectKind(1) + 1, 0, 0, 0, 0, 0, 0, 0, // prohibited tags: count = 1 + 1, 0, 0, 0, 0, 0, 0, 0, 1, // len 1, DeleteEvent (tag 1) + 0, // condition: Always + ]; + assert_eq!(blob, GOLDEN); + assert_eq!(decode_edit_barriers(&GOLDEN).unwrap(), vec![barrier]); + } + + #[test] + fn every_scope_and_condition_variant_round_trips_byte_identically() { + use epiphany_core::{AnalysisLayerId, StaffInstanceId}; + let scopes = vec![ + BarrierScope::WholeScore, + BarrierScope::Region(RegionId::from_raw(7)), + BarrierScope::StaffInstance(StaffInstanceId::from_raw(8)), + BarrierScope::AnalysisLayer(AnalysisLayerId::from_raw(9)), + // In canonical (ascending) order: decode admits only the canonical + // image, so the round-trip compares structurally equal. + BarrierScope::ObjectSet(vec![ev(1), ev(2)]), + BarrierScope::PitchSpace(PitchSpaceId::new("cmn-12")), + BarrierScope::TuningContext, + BarrierScope::Registered(BarrierScopeRegistryId(10)), + ]; + let conditions = vec![ + BarrierCondition::Always, + BarrierCondition::ObjectExists(ev(3)), + BarrierCondition::ObjectHasExtensionData { + object: ev(4), + extension: ExtensionRef(11), + }, + BarrierCondition::All(vec![ + BarrierCondition::Always, + BarrierCondition::ObjectExists(ev(5)), + ]), + BarrierCondition::Any(vec![BarrierCondition::Not(Box::new( + BarrierCondition::Always, + ))]), + BarrierCondition::Not(Box::new(BarrierCondition::Registered( + BarrierConditionRegistryId(12), + ))), + BarrierCondition::Registered(BarrierConditionRegistryId(13)), + ]; + let barriers: Vec = scopes + .into_iter() + .zip(conditions.into_iter().cycle()) + .map(|(scope, condition)| EditBarrier { + scope, + affected_object_kinds: vec![ObjectKind(0), ObjectKind(4)], + prohibited_operation_kinds: vec![ + OperationKindTag::DeleteEvent, + OperationKindTag::Registered(epiphany_ops::OperationKindRegistryId(99)), + ], + condition, + }) + .collect(); + // Single-barrier decode mirrors encode exactly. + for barrier in &barriers { + let bytes = barrier.to_canonical_bytes(); + let decoded = EditBarrier::decode_canonical_bytes(&bytes).unwrap(); + assert_eq!(&decoded, barrier); + assert_eq!(decoded.to_canonical_bytes(), bytes); + } + // The blob is a canonical set: order- and repetition-independent, and + // decode → re-encode is byte-identical. + let blob = encode_edit_barriers(&barriers); + let mut reversed: Vec = barriers.iter().rev().cloned().collect(); + reversed.push(barriers[0].clone()); + assert_eq!(encode_edit_barriers(&reversed), blob); + let decoded = decode_edit_barriers(&blob).unwrap(); + assert_eq!(decoded.len(), barriers.len()); + assert_eq!(encode_edit_barriers(&decoded), blob); + } + + #[test] + fn decode_rejects_unknown_discriminants() { + // Scope tag 8 is one past the vocabulary. + let mut bytes = vec![8u8]; + bytes.extend(set_blob(&[])); + bytes.extend(set_blob(&[])); + bytes.push(0); + assert_eq!( + EditBarrier::decode_canonical_bytes(&bytes), + Err(BarrierDecodeError::InvalidTag { + kind: "BarrierScope", + tag: 8 + }) + ); + // Condition tag 7 is one past the vocabulary. + let mut bytes = vec![0u8]; + bytes.extend(set_blob(&[])); + bytes.extend(set_blob(&[])); + bytes.push(7); + assert_eq!( + EditBarrier::decode_canonical_bytes(&bytes), + Err(BarrierDecodeError::InvalidTag { + kind: "BarrierCondition", + tag: 7 + }) + ); + // Operation-kind tag 24 is one past the v1 vocabulary. + let mut bytes = vec![0u8]; + bytes.extend(set_blob(&[])); + bytes.extend(set_blob(&[vec![24u8]])); + bytes.push(0); + assert_eq!( + EditBarrier::decode_canonical_bytes(&bytes), + Err(BarrierDecodeError::InvalidTag { + kind: "OperationKindTag", + tag: 24 + }) + ); + } + + #[test] + fn decode_rejects_non_nfc_pitch_space_text() { + // scope: PitchSpace(tag 5) carrying a decomposed "café" — canonically + // equivalent to the NFC form but not byte-canonical. Rejected, never + // silently normalized. + let decomposed = "cafe\u{0301}"; + let mut bytes = vec![5u8]; + bytes.extend(u64le(decomposed.len() as u64)); + bytes.extend(decomposed.as_bytes()); + bytes.extend(set_blob(&[])); + bytes.extend(set_blob(&[])); + bytes.push(0); + assert_eq!( + EditBarrier::decode_canonical_bytes(&bytes), + Err(BarrierDecodeError::NotNfc) + ); + // The NFC spelling of the same name decodes (and re-encodes) fine. + let nfc = EditBarrier { + scope: BarrierScope::PitchSpace(PitchSpaceId::new("caf\u{00e9}")), + affected_object_kinds: vec![], + prohibited_operation_kinds: vec![], + condition: BarrierCondition::Always, + }; + let round = EditBarrier::decode_canonical_bytes(&nfc.to_canonical_bytes()).unwrap(); + assert_eq!(round, nfc); + } + + #[test] + fn decode_rejects_unsorted_and_duplicated_sets_and_trailing_bytes() { + // Kinds out of ascending byte order. + let unsorted = { + let mut out = vec![0u8]; + out.extend(set_blob(&[vec![1, 0], vec![0, 0]])); + out.extend(set_blob(&[])); + out.push(0); + out + }; + assert_eq!( + EditBarrier::decode_canonical_bytes(&unsorted), + Err(BarrierDecodeError::NonCanonical("affected object kinds")) + ); + // A duplicated element (sorted but not strictly ascending). + let duplicated = { + let mut out = vec![0u8]; + out.extend(set_blob(&[vec![0, 0], vec![0, 0]])); + out.extend(set_blob(&[])); + out.push(0); + out + }; + assert_eq!( + EditBarrier::decode_canonical_bytes(&duplicated), + Err(BarrierDecodeError::NonCanonical("affected object kinds")) + ); + // Trailing bytes after a complete blob / a complete barrier. + let blob = encode_edit_barriers(&[EditBarrier { + scope: BarrierScope::WholeScore, + affected_object_kinds: vec![], + prohibited_operation_kinds: vec![], + condition: BarrierCondition::Always, + }]); + let mut trailing = blob.clone(); + trailing.push(0); + assert_eq!( + decode_edit_barriers(&trailing), + Err(BarrierDecodeError::TrailingBytes) + ); + // Truncation is an error, at every prefix length. + for cut in 0..blob.len() { + assert!(decode_edit_barriers(&blob[..cut]).is_err()); + } + let mut kinds_trailing = encode_affected_object_kinds(&[ObjectKind(3)]); + kinds_trailing.push(0); + assert_eq!( + decode_affected_object_kinds(&kinds_trailing), + Err(BarrierDecodeError::TrailingBytes) + ); + } + + #[test] + fn decode_bounds_condition_recursion_depth() { + let nested_nots = |n: usize| { + let mut condition = BarrierCondition::Always; + for _ in 0..n { + condition = BarrierCondition::Not(Box::new(condition)); + } + EditBarrier { + scope: BarrierScope::WholeScore, + affected_object_kinds: vec![], + prohibited_operation_kinds: vec![], + condition, + } + }; + // MAX_CONDITION_DEPTH - 1 wrappers put the innermost leaf exactly at + // the bound: accepted. + let at_bound = nested_nots(MAX_CONDITION_DEPTH - 1); + assert_eq!( + EditBarrier::decode_canonical_bytes(&at_bound.to_canonical_bytes()).unwrap(), + at_bound + ); + // One wrapper more nests past the bound: rejected. + let past_bound = nested_nots(MAX_CONDITION_DEPTH); + assert_eq!( + EditBarrier::decode_canonical_bytes(&past_bound.to_canonical_bytes()), + Err(BarrierDecodeError::ConditionTooDeep) + ); + } + #[test] fn canonical_encoding_is_set_order_independent() { let mk = |kinds: Vec| EditBarrier { diff --git a/crates/epiphany-layout-ir/src/constrained.rs b/crates/epiphany-layout-ir/src/constrained.rs index 95adbe7..fae3f78 100644 --- a/crates/epiphany-layout-ir/src/constrained.rs +++ b/crates/epiphany-layout-ir/src/constrained.rs @@ -13,8 +13,8 @@ use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; use epiphany_core::{ - Clef, EventId, KeySignature, MusicalDuration, NoteValue, PitchId, PitchSpelling, - SpellingNominal, StaffId, TypedObjectId, WallClockTime, + Clef, EventId, KeySignature, MeasureId, MeasurePosition, MusicalDuration, NoteValue, PitchId, + PitchSpelling, SpellingNominal, StaffId, TimeAnchor, TypedObjectId, WallClockTime, }; use epiphany_determinism::{DomainTag, Preimage}; @@ -22,18 +22,18 @@ use crate::engrave_theory::{ accidental_glyph, clef_glyph, has_stem, key_signature, notehead_glyph, rest_glyph, staff_position, KeyAccidental, StaffStep, }; -use crate::engraving::EngravingDecision; +use crate::engraving::{EngravingDecision, OverrideKind, OverridePriority, OverrideTarget}; use crate::glyph::{metrics, BravuraCatalog, GlyphCatalog, GlyphCatalogIdentity, GlyphReference}; use crate::logical::{ - BarlineKind, LayoutContent, LogicalLayoutIR, PlacedClef, PlacedKeySignature, ScoreVersion, - StaffContent, + apply_offset, BarlineKind, LayoutContent, LogicalLayoutIR, PlacedClef, PlacedKeySignature, + ScoreVersion, StaffContent, }; use crate::provenance::{ manifestation_layout_id, LayoutObjectId, Provenance, SynthesisInstanceKey, SynthesisKind, SynthesisRegistryId, }; -use crate::solver::SpringSlotId; -use crate::spatial::{BoundingBox, Point, Rect, StaffSpace}; +use crate::solver::{ConstraintStrength, SpringSlotId}; +use crate::spatial::{BoundingBox, Point, Rect, Size2D, StaffSpace}; use crate::time_axis::{time_cmp, SlotPlacement, TimeAxisModel, TimePoint}; use crate::vertical_band::{inter_staff_gap_id, VerticalBand, VerticalBandId}; @@ -208,6 +208,47 @@ pub enum LayoutConstraint { Registered(ConstraintRegistryId, ConstraintParameters), } +impl LayoutConstraint { + /// The strength this constraint binds the solver with (Chapter 9 §"Strength + /// Levels": [`ConstraintStrength`]). + /// + /// The spec's `LayoutConstraint` enum carries no strength field, and the + /// "normalized form" Chapter 9 says the solver consumes does not specify how + /// strength attaches to a constraint instance (a genuine spec gap — see + /// DECISIONS.md), so v0 attaches strength **by rule** rather than widening + /// the IR shape: a break constraint's own [`BreakKind`] is its strength + /// (`Hard` → `Required`, `Soft` → `Preferred` at the default weight), the + /// geometric constraints (no-collision, alignment, containment) are hard + /// engraving obligations (`Required`), and a `Registered` extension + /// constraint is conservatively `Required` — an obligation a solver cannot + /// verify must not be silently demoted (Chapter 9: a solver MUST NOT treat + /// `Required` as `Preferred`). + pub fn strength(&self) -> ConstraintStrength { + match self { + LayoutConstraint::SystemBreakAt { + kind: BreakKind::Soft, + .. + } + | LayoutConstraint::PageBreakAt { + kind: BreakKind::Soft, + .. + } => ConstraintStrength::Preferred { weight: 1.0 }, + LayoutConstraint::NoCollision { .. } + | LayoutConstraint::Align { .. } + | LayoutConstraint::PositionWithin { .. } + | LayoutConstraint::SystemBreakAt { + kind: BreakKind::Hard, + .. + } + | LayoutConstraint::PageBreakAt { + kind: BreakKind::Hard, + .. + } + | LayoutConstraint::Registered(_, _) => ConstraintStrength::Required, + } + } +} + /// A structural defect in [`ConstrainedLayoutIR`] that prevents a solver from /// treating the input as a valid constraint problem. #[derive(Clone, PartialEq, Eq, Debug)] @@ -455,6 +496,17 @@ const KEY_ACC_X: f32 = 0.9; // x advance per key-signature accidental const TIME_SIG_X: f32 = 0.5; // a time signature sits this far right of its barline const TIME_DIGIT_X: f32 = 0.8; // x advance per time-signature digit +/// The horizontal half-reach of an emitted `PositionWithin` region, in staff +/// spaces. v0 performs no casting-off, so a region imposes no *horizontal* +/// bound on its glyphs — a conformant solver may re-space columns freely along +/// the open canvas. The containment obligation v0 can honestly state is the +/// **vertical** envelope (which the spacing pass computes from the very glyph +/// geometry the solvers preserve), so the emitted rect pins that envelope and +/// leaves the horizontal span at canvas scale: wide enough for any plausible +/// re-spacing, finite because the validator rejects non-finite constraint +/// regions. +const POSITION_WITHIN_X_REACH: f32 = 1.0e6; + /// The registry id for the engraver's **structural-line synthesis** (staff /// lines). The normative [`SynthesisKind`] set names *musical* synthesized /// objects (cancellation accidentals, generated rests, …) but no purely visual @@ -530,6 +582,7 @@ pub fn try_to_constrained( let mut diagnostics = Vec::new(); let mut vertical_bands = Vec::new(); let mut horizontal_slots = Vec::new(); + let mut constraints = Vec::new(); let mut constrained_regions = Vec::new(); // Regions tile left-to-right; this advances by each region's width so all // coordinates stay globally monotonic (the solver's coordinate remap relies @@ -807,6 +860,9 @@ pub fn try_to_constrained( ) .collect(); + // Where this region's glyphs begin in the global vector, so constraint + // emission below can see exactly the glyphs pass 2 produced for it. + let region_glyph_start = glyphs.len(); let mut emit = Emit { glyphs: &mut glyphs, strokes: &mut strokes, @@ -1156,6 +1212,144 @@ pub fn try_to_constrained( } } + // --- Constraint emission (Chapter 7 §"Pipeline Overview": the spacing + // pass "build[s] collision constraints"). Everything emitted here is + // satisfiable on well-formed input by construction — the source layout + // separates columns collision-free and a conformant re-spacing keeps + // them so — and the order is deterministic: per region, no-collision + // pairs (staff emission order, then column x / glyph id), containment + // (glyph stable-id order), then projected breaks (override order). + let region_glyph_objects = &glyphs[region_glyph_start..]; + let glyph_by_id: BTreeMap = region_glyph_objects + .iter() + .map(|glyph| (glyph.id(), glyph)) + .collect(); + + // NoCollision between *successive notehead columns* within each staff: + // adjacent pairs in (column x, id) order, one linear chain per staff, + // not O(n²). Chord members share a column slot — a second or unison may + // genuinely overlap by design — so only cross-column neighbours carry + // the obligation. + for staff in &staves_in_order { + let mut heads: Vec<&GlyphObject> = staff_members + .get(staff) + .into_iter() + .flatten() + .filter_map(|id| glyph_by_id.get(id).copied()) + .filter(|glyph| glyph.glyph.as_str().starts_with("notehead")) + .collect(); + heads.sort_by(|a, b| { + a.baseline + .x + .0 + .total_cmp(&b.baseline.x.0) + .then_with(|| a.id().cmp(&b.id())) + }); + for pair in heads.windows(2) { + if pair[0].horizontal_slot != pair[1].horizontal_slot { + constraints.push(LayoutConstraint::NoCollision { + a: pair[0].id(), + b: pair[1].id(), + }); + } + } + } + + // PositionWithin: every glyph must stay inside its owning region's + // envelope. The vertical extent is the exact envelope of the region's + // own glyph boxes (both v0 solvers preserve glyph `y` verbatim, so this + // is a real obligation a vertical pass must renegotiate); the + // horizontal span is the open v0 canvas (see + // [`POSITION_WITHIN_X_REACH`]). + if !region_glyph_objects.is_empty() { + let mut bottom = f32::INFINITY; + let mut top = f32::NEG_INFINITY; + for glyph in region_glyph_objects { + bottom = bottom.min(glyph.baseline.y.0 + glyph.bounding_box.bottom.0); + top = top.max(glyph.baseline.y.0 + glyph.bounding_box.top.0); + } + let envelope = Rect { + origin: Point::new(-POSITION_WITHIN_X_REACH, bottom), + size: Size2D { + width: StaffSpace(2.0 * POSITION_WITHIN_X_REACH), + height: StaffSpace(top - bottom), + }, + }; + let mut ids: Vec = glyph_by_id.keys().copied().collect(); + ids.sort(); + for glyph in ids { + constraints.push(LayoutConstraint::PositionWithin { + glyph, + region: envelope, + }); + } + } + + // Projected break overrides (the logical stage's `SystemBreak` / + // `PageBreak` engraving overrides, Chapter 7 §"Engraving Overrides") + // become break constraints on the spring slot that carries the break + // anchor's onset — the barline column at that time when one exists + // (a break belongs at the boundary), else the note column. An anchor + // no realized column represents — an event or measure outside this + // region, a measure *end* (Minimal resolves measure starts only), a + // region edge, or a column no glyph landed in — is skipped silently: + // there is no slot for a solver to break at. + let mut event_onsets: BTreeMap = BTreeMap::new(); + let mut measure_starts: BTreeMap = BTreeMap::new(); + for object in ®ion.objects { + match (object.provenance().source, object.content()) { + (TypedObjectId::Event(eid), LayoutContent::Note(note)) => { + event_onsets.insert(eid, note.position.clone()); + } + (TypedObjectId::Event(eid), LayoutContent::Rest(rest)) => { + event_onsets.insert(eid, rest.position.clone()); + } + (TypedObjectId::Measure(mid), LayoutContent::Measure(measure)) => { + measure_starts.insert(mid, measure.start.clone()); + } + _ => {} + } + } + for override_record in &logical.overrides { + if override_record.target + != OverrideTarget::ScoreGraph(TypedObjectId::Region(region_id)) + { + continue; + } + let (anchor, system) = match &override_record.kind { + OverrideKind::SystemBreak { anchor } => (anchor, true), + OverrideKind::PageBreak { anchor } => (anchor, false), + _ => continue, + }; + let Some(time) = break_anchor_time(anchor, &event_onsets, &measure_starts) else { + continue; + }; + let slot = [ColumnRole::Barline, ColumnRole::Note] + .iter() + .find_map(|role| { + let info = columns.get(&ColumnKey::Timed(time.clone(), *role))?; + column_members + .get(&info.slot) + .filter(|members| !members.is_empty()) + .map(|_| info.slot) + }); + let Some(slot) = slot else { + continue; + }; + // The override's binding strength is the break's kind: a `Hard` + // override MUST be honored or error, a `Soft` one is a preference + // (Chapter 7 §"Override Resolution"; the projection emits `Soft`). + let kind = match override_record.priority { + OverridePriority::Hard => BreakKind::Hard, + OverridePriority::Soft => BreakKind::Soft, + }; + constraints.push(if system { + LayoutConstraint::SystemBreakAt { slot, kind } + } else { + LayoutConstraint::PageBreakAt { slot, kind } + }); + } + // A staff band per manifested staff that carries glyphs, in first-glyph // order; an (empty) inter-staff gap band between adjacent staves; and a // margin band for any region-level glyphs. @@ -1203,7 +1397,7 @@ pub fn try_to_constrained( glyphs, strokes, vertical_bands, - constraints: Vec::new(), + constraints, engraving_decisions: logical.engraving_decisions.clone(), diagnostics, catalog, @@ -1422,6 +1616,30 @@ fn component_provenance(base: &Provenance, comp: usize) -> Provenance { } } +/// Resolves a projected break override's [`TimeAnchor`] to the region-local +/// [`TimePoint`] whose spacing column carries it, using the onsets this +/// region's own objects resolved to. Returns `None` — the break is skipped +/// silently — when the anchor addresses something no spacing column +/// represents: an event or measure outside this region, a measure *end* (the +/// Minimal slice resolves measure starts only), a region edge, or an offset +/// whose clock does not match its base. +fn break_anchor_time( + anchor: &TimeAnchor, + event_onsets: &BTreeMap, + measure_starts: &BTreeMap, +) -> Option { + match anchor { + TimeAnchor::WallClock { time } => Some(TimePoint::WallClock(*time)), + TimeAnchor::Event { id, offset } => apply_offset(event_onsets.get(id)?.clone(), offset), + TimeAnchor::Measure { + id, + position: MeasurePosition::Start, + offset, + } => apply_offset(measure_starts.get(id)?.clone(), offset), + TimeAnchor::Measure { .. } | TimeAnchor::Region { .. } => None, + } +} + /// The column a measure's barline occupies: the final barline closes the region /// at the right; an interior/region-end barline sits before its measure's notes. fn measure_column(measure: &crate::logical::MeasureContent) -> ColumnKey { @@ -1700,6 +1918,191 @@ mod tests { use epiphany_core::generators::valid_score_rich; use std::collections::BTreeSet; + #[test] + fn constraint_strength_attaches_by_rule() { + // The spec's constraint enum carries no strength field, so strength is + // a rule over the constraint's own shape (Chapter 9 §"Strength Levels"). + let glyph = GlyphObjectId(1); + let slot = SpringSlotId(2); + let required = [ + LayoutConstraint::NoCollision { a: glyph, b: glyph }, + LayoutConstraint::Align { + a: glyph, + b: glyph, + axis: Axis::Vertical, + }, + LayoutConstraint::PositionWithin { + glyph, + region: Rect { + origin: Point::ORIGIN, + size: Size2D::default(), + }, + }, + LayoutConstraint::SystemBreakAt { + slot, + kind: BreakKind::Hard, + }, + LayoutConstraint::PageBreakAt { + slot, + kind: BreakKind::Hard, + }, + // Conservative: an unverifiable extension obligation is never demoted. + LayoutConstraint::Registered(ConstraintRegistryId(3), ConstraintParameters::default()), + ]; + for constraint in required { + assert_eq!(constraint.strength(), ConstraintStrength::Required); + } + // A soft break is a preference at the default weight. + for soft in [ + LayoutConstraint::SystemBreakAt { + slot, + kind: BreakKind::Soft, + }, + LayoutConstraint::PageBreakAt { + slot, + kind: BreakKind::Soft, + }, + ] { + assert_eq!( + soft.strength(), + ConstraintStrength::Preferred { weight: 1.0 } + ); + } + } + + #[test] + fn constraint_emission_is_deterministic_and_principled() { + let logical = to_logical(&valid_score_rich(11)); + let a = try_to_constrained(&logical).expect("well-formed logical IR"); + let b = try_to_constrained(&logical).expect("well-formed logical IR"); + assert_eq!( + a.constraints, b.constraints, + "two runs emit identical constraint vectors" + ); + assert!(!a.constraints.is_empty(), "the pipeline emits constraints"); + // Every constraint references real glyphs/slots and finite geometry. + assert!(a.validate().is_ok()); + + // Containment: one PositionWithin per glyph, against its region envelope. + let contained = a + .constraints + .iter() + .filter(|c| matches!(c, LayoutConstraint::PositionWithin { .. })) + .count(); + assert_eq!(contained, a.glyphs.len()); + + // No-collision: a linear chain over successive notehead columns, never + // the O(n²) all-pairs closure. + let pairs = a + .constraints + .iter() + .filter(|c| matches!(c, LayoutConstraint::NoCollision { .. })) + .count(); + let noteheads = a + .glyphs + .iter() + .filter(|g| g.glyph.as_str().starts_with("notehead")) + .count(); + assert!(pairs > 0, "successive noteheads earn no-collision pairs"); + assert!(pairs < noteheads, "the chain is linear in the noteheads"); + // Every no-collision endpoint is a notehead in a distinct column slot. + let by_id: BTreeMap = + a.glyphs.iter().map(|g| (g.id(), g)).collect(); + for constraint in &a.constraints { + if let LayoutConstraint::NoCollision { + a: first, + b: second, + } = constraint + { + let (first, second) = (by_id[first], by_id[second]); + assert!(first.glyph.as_str().starts_with("notehead")); + assert!(second.glyph.as_str().starts_with("notehead")); + assert_ne!(first.horizontal_slot, second.horizontal_slot); + } + } + // No break constraints without projected break overrides. + assert!(!a.constraints.iter().any(|c| matches!( + c, + LayoutConstraint::SystemBreakAt { .. } | LayoutConstraint::PageBreakAt { .. } + ))); + } + + #[test] + fn user_break_overrides_become_soft_break_constraints() { + use epiphany_core::generators::valid_score; + use epiphany_core::{AnchorOffset, Event, RegionEdge, TimeAnchor}; + + let mut score = valid_score(3); + let region_id = score.canvas.regions[0].id; + // A pitched event in region 0 whose onset column is realized (it draws + // noteheads), so the break has a spring slot to land on. + let event = score.canvas.regions[0] + .staff_instances() + .iter() + .flat_map(|si| si.voices.iter()) + .flat_map(|voice| voice.events.iter().copied()) + .find(|eid| { + matches!(score.events.get(*eid), Some(Event::Pitched(p)) if !p.pitches.is_empty()) + }) + .expect("valid_score has a pitched event"); + let anchor = TimeAnchor::Event { + id: event, + offset: AnchorOffset::Zero, + }; + let content = score.canvas.regions[0] + .content + .staff_based_mut() + .expect("valid_score is staff based"); + content.user_system_breaks.push(anchor.clone()); + content.user_page_breaks.push(anchor); + // An anchor no spacing column represents — a region edge — is skipped + // silently rather than mis-assigned to some column. + content.user_system_breaks.push(TimeAnchor::Region { + id: region_id, + edge: RegionEdge::Start, + offset: AnchorOffset::Zero, + }); + + let constrained = to_constrained(&to_logical(&score)); + assert!(constrained.validate().is_ok()); + let system_breaks: Vec<&LayoutConstraint> = constrained + .constraints + .iter() + .filter(|c| matches!(c, LayoutConstraint::SystemBreakAt { .. })) + .collect(); + let page_breaks: Vec<&LayoutConstraint> = constrained + .constraints + .iter() + .filter(|c| matches!(c, LayoutConstraint::PageBreakAt { .. })) + .collect(); + assert_eq!( + system_breaks.len(), + 1, + "the event-anchored break lands; the region-edge one is skipped" + ); + assert_eq!(page_breaks.len(), 1); + for projected in system_breaks.iter().chain(&page_breaks) { + let (LayoutConstraint::SystemBreakAt { slot, kind } + | LayoutConstraint::PageBreakAt { slot, kind }) = projected + else { + unreachable!("filtered to break constraints"); + }; + // A Soft override projects a Soft break — a Preferred obligation. + assert_eq!(*kind, BreakKind::Soft); + assert_eq!( + projected.strength(), + ConstraintStrength::Preferred { weight: 1.0 } + ); + // The slot is the event's own (realized) onset column. + let slot = constrained + .horizontal_slots + .iter() + .find(|s| s.id == *slot) + .expect("break constraints name realized slots"); + assert!(!slot.members.is_empty()); + } + } + #[test] fn ledger_steps_cover_only_lines_outside_the_staff() { // Within the five-line staff (steps 0..=8) and one space just outside: none. diff --git a/crates/epiphany-layout-ir/src/engraving.rs b/crates/epiphany-layout-ir/src/engraving.rs index b271544..0d194c9 100644 --- a/crates/epiphany-layout-ir/src/engraving.rs +++ b/crates/epiphany-layout-ir/src/engraving.rs @@ -8,7 +8,7 @@ //! provenance and override interfaces (the QUICKSTART scope item); production //! engraving algorithms remain layered specifications beyond the v0 stub. -use epiphany_core::{StemDirection, TypedObjectId}; +use epiphany_core::{CanonicalValue, RegionId, StemDirection, TimeAnchor, TypedObjectId}; use epiphany_determinism::{DomainTag, Preimage}; use crate::provenance::LayoutObjectId; @@ -72,19 +72,41 @@ pub enum OverrideOrigin { /// Core override vocabulary. More detailed engraving payloads are represented /// by stable registered ids until their companion algorithm specifications land. +/// +/// A break override addresses a *position*, not an object (Chapter 7 +/// §"Engraving Overrides"): the kind carries the break's [`TimeAnchor`], while +/// the override's `ScoreGraph` target names the owning region. #[derive(Clone, PartialEq, Debug)] pub enum OverrideKind { StemDirection(StemDirection), AccidentalParenthesized(bool), AccidentalVisible(bool), - SystemBreak, - PageBreak, + SystemBreak { anchor: TimeAnchor }, + PageBreak { anchor: TimeAnchor }, HiddenObject, CustomPosition(Point), LedgerLineSuppression, Registered(u128), } +impl OverrideKind { + /// A stable discriminant byte, part of the override-id preimage and the + /// projection's deterministic ordering key. + pub(crate) fn discriminant(&self) -> u8 { + match self { + OverrideKind::StemDirection(_) => 0, + OverrideKind::AccidentalParenthesized(_) => 1, + OverrideKind::AccidentalVisible(_) => 2, + OverrideKind::SystemBreak { .. } => 3, + OverrideKind::PageBreak { .. } => 4, + OverrideKind::HiddenObject => 5, + OverrideKind::CustomPosition(_) => 6, + OverrideKind::LedgerLineSuppression => 7, + OverrideKind::Registered(_) => 8, + } + } +} + /// A projected engraving override (Chapter 7 §"Engraving Overrides"). #[derive(Clone, PartialEq, Debug)] pub struct EngravingOverride { @@ -95,6 +117,59 @@ pub struct EngravingOverride { pub origin: OverrideOrigin, } +impl EngravingOverride { + /// A system-break override projected from a region's authoritative + /// `user_system_breaks` list (Chapter 5 §"Staff-Based Content"). + pub fn projected_system_break(region: RegionId, anchor: TimeAnchor) -> Self { + Self::projected_break(region, OverrideKind::SystemBreak { anchor }) + } + + /// A page-break override projected from a region's authoritative + /// `user_page_breaks` list (Chapter 5 §"Staff-Based Content"). + pub fn projected_page_break(region: RegionId, anchor: TimeAnchor) -> Self { + Self::projected_break(region, OverrideKind::PageBreak { anchor }) + } + + /// The shared shape of a projected break override (Chapter 7 §"Engraving + /// Overrides"): the kind carries the break's anchor, the `ScoreGraph` + /// target names the owning region, the binding is `Soft` (the layout + /// SHOULD honor it), and the origin is `Internal` — break authorship + /// (author, timestamp) lives in the operation log, not the materialized + /// break lists, until the snapshot-undo refinement (P11-C8) surfaces it. + fn projected_break(region: RegionId, kind: OverrideKind) -> Self { + EngravingOverride { + id: derive_break_override_id(region, &kind), + target: OverrideTarget::ScoreGraph(TypedObjectId::Region(region)), + kind, + priority: OverridePriority::Soft, + origin: OverrideOrigin::Internal, + } + } +} + +/// Derives an [`EngravingOverrideId`] for a projected break override from its +/// owning region, its kind discriminant, and the break anchor's canonical +/// bytes — so equal breaks share an id across re-projection and distinct ones +/// never collide. +/// +/// Like the engraving-decision id, the override is a non-canonical +/// layout-namespace object, so the preimage is domain-separated under +/// [`DomainTag::LAYOUT_OBJECT_ID`] (`MUSCLOID`) with a literal +/// `engraving-override` discriminator prefix, so an override id can alias +/// neither a layout-object id nor a decision id within that namespace. +fn derive_break_override_id(region: RegionId, kind: &OverrideKind) -> EngravingOverrideId { + let anchor = match kind { + OverrideKind::SystemBreak { anchor } | OverrideKind::PageBreak { anchor } => anchor, + _ => unreachable!("projected break overrides carry a break kind"), + }; + let mut p = Preimage::new(DomainTag::LAYOUT_OBJECT_ID); + p.push_bytes(b"engraving-override"); + p.push_bytes(®ion.canonical_bytes()); + p.push_u64_le(kind.discriminant() as u64); + p.push_bytes(&anchor.canonical_bytes()); + EngravingOverrideId(p.finish_trunc128()) +} + /// Where an engraving decision came from (Chapter 7 §"Note Layout": /// `DecisionSource`). #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -258,6 +333,43 @@ mod tests { ); } + #[test] + fn projected_break_override_ids_are_content_derived() { + use epiphany_core::{RegionId, WallClockTime}; + let region = RegionId::from_raw(9); + let anchor = TimeAnchor::WallClock { + time: WallClockTime(7), + }; + let a = EngravingOverride::projected_system_break(region, anchor.clone()); + let b = EngravingOverride::projected_system_break(region, anchor.clone()); + assert_eq!(a, b, "equal breaks share an id across re-projection"); + // A page break at the same anchor is a distinct override… + let page = EngravingOverride::projected_page_break(region, anchor.clone()); + assert_ne!(a.id, page.id); + // …as is the same break at a different anchor… + let other = EngravingOverride::projected_system_break( + region, + TimeAnchor::WallClock { + time: WallClockTime(8), + }, + ); + assert_ne!(a.id, other.id); + // …or in a different owning region. + let elsewhere = + EngravingOverride::projected_system_break(RegionId::from_raw(10), anchor.clone()); + assert_ne!(a.id, elsewhere.id); + // The projected shape the spec pins: the kind carries the break anchor, + // the ScoreGraph target names the owning region, the binding is Soft, + // and the origin is Internal (authorship lives in the op log, P11-C8). + assert_eq!(a.kind, OverrideKind::SystemBreak { anchor }); + assert_eq!( + a.target, + OverrideTarget::ScoreGraph(TypedObjectId::Region(region)) + ); + assert_eq!(a.priority, OverridePriority::Soft); + assert_eq!(a.origin, OverrideOrigin::Internal); + } + #[test] fn stem_direction_payload_changes_the_id() { let target = LayoutObjectId(7); diff --git a/crates/epiphany-layout-ir/src/lib.rs b/crates/epiphany-layout-ir/src/lib.rs index 364b37b..816b0e2 100644 --- a/crates/epiphany-layout-ir/src/lib.rs +++ b/crates/epiphany-layout-ir/src/lib.rs @@ -82,8 +82,10 @@ pub mod time_axis; pub mod vertical_band; pub use barrier::{ - AlwaysLiveOracle, BarrierCondition, BarrierConditionRegistryId, BarrierScope, - BarrierScopeRegistryId, EditBarrier, EditContext, EditOracle, ExtensionRef, ObjectKind, + decode_affected_object_kinds, decode_edit_barriers, encode_affected_object_kinds, + encode_edit_barriers, AlwaysLiveOracle, BarrierCondition, BarrierConditionRegistryId, + BarrierDecodeError, BarrierScope, BarrierScopeRegistryId, EditBarrier, EditContext, EditOracle, + ExtensionRef, ObjectKind, MAX_CONDITION_DEPTH, }; pub use cache::{ ConstrainedRegionCache, DependencyIndex, FineLayoutCache, LayoutCache, LogicalRegionCache, @@ -134,11 +136,11 @@ pub use resolved::{ }; pub use roundtrip::{laid_out_object_ids, round_trip, round_trip_with, RoundTripReport}; pub use solver::{ - ConstraintId, ConstraintSolver, ExtensionMetric, ExtensionMetricId, ExtensionWarningId, - InvalidationScope, InvalidationSet, NormalizedMetric, QualityMetricKind, QualityMetricVector, - SolveReport, SolveStatus, SolverBudget, SolverBudgetUsed, SolverConfig, SolverProfile, - SolverState, SolverTier, SolverVersion, SolverWarning, SolverWarningKind, SpringSlotId, - StubSolver, TieBreakingWeights, + ConstraintId, ConstraintSolver, ConstraintStrength, ExtensionMetric, ExtensionMetricId, + ExtensionWarningId, InvalidationScope, InvalidationSet, NormalizedMetric, QualityMetricKind, + QualityMetricVector, SolveReport, SolveStatus, SolverBudget, SolverBudgetUsed, SolverConfig, + SolverProfile, SolverState, SolverTier, SolverVersion, SolverWarning, SolverWarningKind, + SpringSlotId, StubSolver, TieBreakingWeights, }; pub use spatial::{ BoundingBox, Margins, Point, Rect, ScaleContext, Size2D, StaffSpace, Transform2D, diff --git a/crates/epiphany-layout-ir/src/logical.rs b/crates/epiphany-layout-ir/src/logical.rs index c1e0fef..26a4034 100644 --- a/crates/epiphany-layout-ir/src/logical.rs +++ b/crates/epiphany-layout-ir/src/logical.rs @@ -17,15 +17,17 @@ use std::collections::{BTreeMap, BTreeSet}; use epiphany_core::prepass::{derive_annotations, DerivedAnnotations, PrePassProfile}; use epiphany_core::{ - AleatoricAnchoringDiscipline, AnchorOffset, AnnotationAnchor, Clef, CoordinateDiscipline, - Event, EventId, EventPosition, KeySignature, MeasurePosition, MusicalDuration, MusicalPosition, - NotatedComponent, PitchId, PitchSpelling, Region, RegionEdge, RegionId, RegionTimeModel, Score, - StaffId, StaffPosition, TimeAnchor, TimeSignatureDisplay, TupletId, TupletRatio, TypedObjectId, - WallClockTime, + AleatoricAnchoringDiscipline, AnchorOffset, AnnotationAnchor, CanonicalValue, Clef, + CoordinateDiscipline, Event, EventId, EventPosition, KeySignature, MeasurePosition, + MusicalDuration, MusicalPosition, NotatedComponent, PitchId, PitchSpelling, Region, RegionEdge, + RegionId, RegionTimeModel, Score, StaffId, StaffPosition, TimeAnchor, TimeSignatureDisplay, + TupletId, TupletRatio, TypedObjectId, WallClockTime, }; use epiphany_determinism::{DomainTag, Preimage}; -use crate::engraving::{EngravingDecision, EngravingDecisionKind, EngravingOverride}; +use crate::engraving::{ + DecisionSource, EngravingDecision, EngravingDecisionKind, EngravingOverride, OverrideKind, +}; use crate::provenance::{LayoutObjectId, Provenance}; use crate::spatial::Transform2D; use crate::time_axis::{time_axis_of, TimeAxisModel, TimePoint}; @@ -367,8 +369,12 @@ pub struct LogicalLayoutIR { /// Engraving decisions made during the engraving pass (Chapter 7 /// §"Engraving Decisions"), carried forward through the pipeline. pub engraving_decisions: Vec, - /// User engraving overrides projected from the score graph. Agent B's - /// current graph exposes no override registry, so the projection is empty. + /// User engraving overrides projected from the score graph: each region's + /// authoritative `user_system_breaks` / `user_page_breaks` lists (Chapter 5 + /// §"Staff-Based Content") become Soft, `Internal`-origin break overrides + /// targeting the owning region, ordered by (region id, kind, anchor + /// canonical bytes). Each carries a paired [`EngravingDecision`] with + /// [`DecisionSource::UserOverride`] in `engraving_decisions`. pub overrides: Vec, /// Objects spanning two or more layout regions. pub cross_region: Vec, @@ -394,6 +400,9 @@ pub struct LogicalLayoutIR { pub fn to_logical(score: &Score) -> LogicalLayoutIR { let mut regions = Vec::new(); let mut engraving_decisions = Vec::new(); + // The projected break overrides, keyed by owning region for the final + // deterministic ordering (canvas order need not be region-id order). + let mut projected_breaks: Vec<(RegionId, EngravingOverride)> = Vec::new(); let mut cross_region = Vec::new(); let mut seen: BTreeSet = BTreeSet::new(); // The resolved spellings and decompositions the notation engraving consumes @@ -538,6 +547,34 @@ pub fn to_logical(score: &Score) -> LogicalLayoutIR { region_provenance.stable_id, EngravingDecisionKind::SystemBreak, )); + // The region's authoritative user break lists project as engraving + // overrides (Chapter 7 §"Engraving Overrides": a break override + // addresses a *position* — its kind carries the break's `TimeAnchor`, + // its `ScoreGraph` target names the owning region). Each applied + // override records a paired decision with + // `DecisionSource::UserOverride(id)` (Chapter 7 §"Override + // Resolution") against the region's stable layout id. + if let Some(content) = region.content.staff_based() { + for anchor in &content.user_system_breaks { + let projected = + EngravingOverride::projected_system_break(region_id, anchor.clone()); + engraving_decisions.push(EngravingDecision::with_source( + region_provenance.stable_id, + EngravingDecisionKind::SystemBreak, + DecisionSource::UserOverride(projected.id), + )); + projected_breaks.push((region_id, projected)); + } + for anchor in &content.user_page_breaks { + let projected = EngravingOverride::projected_page_break(region_id, anchor.clone()); + engraving_decisions.push(EngravingDecision::with_source( + region_provenance.stable_id, + EngravingDecisionKind::PageBreak, + DecisionSource::UserOverride(projected.id), + )); + projected_breaks.push((region_id, projected)); + } + } regions.push(LayoutRegion { provenance: region_provenance, coordinate_system: LocalCoordinateSystem::default(), @@ -609,16 +646,41 @@ pub fn to_logical(score: &Score) -> LogicalLayoutIR { } } + // Deterministic override order: by (region id, kind discriminant, anchor + // canonical bytes) — independent of canvas order and of the break lists' + // internal order. + projected_breaks.sort_by(|(region_a, a), (region_b, b)| { + (region_a, a.kind.discriminant(), break_anchor_bytes(a)).cmp(&( + region_b, + b.kind.discriminant(), + break_anchor_bytes(b), + )) + }); + let source = derive_score_version(score); LogicalLayoutIR { source, regions, engraving_decisions, - overrides: Vec::new(), + overrides: projected_breaks + .into_iter() + .map(|(_, projected)| projected) + .collect(), cross_region, } } +/// The canonical bytes of a projected break override's anchor (its ordering +/// key alongside the owning region and kind). +fn break_anchor_bytes(projected: &EngravingOverride) -> Vec { + match &projected.kind { + OverrideKind::SystemBreak { anchor } | OverrideKind::PageBreak { anchor } => { + anchor.canonical_bytes() + } + _ => Vec::new(), + } +} + /// Derives the [`ScoreVersion`] from the **whole score's canonical content** /// (Agent B's whole-score codec), not merely the layout projection's object /// identities. Any score edit — including one that changes an event's content @@ -790,7 +852,10 @@ fn resolve_time_anchor_inner(score: &Score, anchor: &TimeAnchor, depth: u8) -> O } } -fn apply_offset(base: TimePoint, offset: &AnchorOffset) -> Option { +/// Applies an [`AnchorOffset`] to a resolved base time; `None` when the +/// offset's clock does not match the base. Shared with the constrained stage's +/// break-anchor resolution. +pub(crate) fn apply_offset(base: TimePoint, offset: &AnchorOffset) -> Option { match (base, offset) { (base, AnchorOffset::Zero) => Some(base), (TimePoint::Musical(position), AnchorOffset::Musical(duration)) => { @@ -1292,6 +1357,73 @@ mod tests { ); } + #[test] + fn user_breaks_project_as_overrides_with_paired_decisions() { + use crate::engraving::{ + DecisionSource, EngravingDecisionKind, OverrideKind, OverrideOrigin, OverridePriority, + OverrideTarget, + }; + let mut score = valid_score(5); + let region_id = score.canvas.regions[0].id; + let anchor = TimeAnchor::WallClock { + time: WallClockTime(42), + }; + let content = score.canvas.regions[0] + .content + .staff_based_mut() + .expect("valid_score is staff based"); + content.user_system_breaks.push(anchor.clone()); + content.user_page_breaks.push(anchor.clone()); + + // Deterministic across two runs. + let ir = to_logical(&score); + assert_eq!(ir.overrides, to_logical(&score).overrides); + + // One override per break, in the pinned projected shape: the kind + // carries the anchor, the ScoreGraph target names the owning region, + // Soft binding, Internal origin. + assert_eq!(ir.overrides.len(), 2); + for projected in &ir.overrides { + assert_eq!( + projected.target, + OverrideTarget::ScoreGraph(TypedObjectId::Region(region_id)) + ); + assert_eq!(projected.priority, OverridePriority::Soft); + assert_eq!(projected.origin, OverrideOrigin::Internal); + } + assert!(ir.overrides.iter().any(|o| matches!( + &o.kind, + OverrideKind::SystemBreak { anchor: got } if *got == anchor + ))); + assert!(ir.overrides.iter().any(|o| matches!( + &o.kind, + OverrideKind::PageBreak { anchor: got } if *got == anchor + ))); + assert_ne!(ir.overrides[0].id, ir.overrides[1].id); + + // Each applied override records a paired decision sourced to it + // (Chapter 7 §"Override Resolution"). + for projected in &ir.overrides { + let kind = match &projected.kind { + OverrideKind::SystemBreak { .. } => EngravingDecisionKind::SystemBreak, + OverrideKind::PageBreak { .. } => EngravingDecisionKind::PageBreak, + other => panic!("unexpected projected override kind {other:?}"), + }; + assert!( + ir.engraving_decisions.iter().any(|decision| decision.source + == DecisionSource::UserOverride(projected.id) + && decision.kind == kind), + "no paired UserOverride decision for {projected:?}" + ); + } + // The automatic per-region system-break decision is still present. + assert!(ir + .engraving_decisions + .iter() + .any(|decision| decision.source == DecisionSource::Automatic + && decision.kind == EngravingDecisionKind::SystemBreak)); + } + #[test] fn spanning_object_uses_cross_region_collection() { let mut score = valid_score_rich(5); diff --git a/crates/epiphany-layout-ir/src/roundtrip.rs b/crates/epiphany-layout-ir/src/roundtrip.rs index 0587729..5c6d958 100644 --- a/crates/epiphany-layout-ir/src/roundtrip.rs +++ b/crates/epiphany-layout-ir/src/roundtrip.rs @@ -5,14 +5,16 @@ //! > all provenance preserved. //! //! [`round_trip`] runs the whole pipeline and asserts the contract every IR -//! stage must satisfy: the stub solver reports [`SolveStatus::Solved`] with all -//! hard constraints satisfied; the **complete** [`Provenance`] of every object -//! survives every stage unchanged; no two objects share a stable id; the stub -//! solver returns the input geometry verbatim; and the *set* of score-graph -//! sources recovered from the RenderIR is exactly the set laid out — a surjection -//! onto graph identity (one source may back several manifestations, each a -//! distinct layout object). This is the contract the testkit's layout harness -//! drives, now against the real crate. +//! stage must satisfy: the solver reports a renderable status (the stub, which +//! evaluates no constraints, honestly claims hard-constraint satisfaction only +//! for a constraint-free problem; a conformant tier must claim it outright); +//! the **complete** [`Provenance`] of every object survives every stage +//! unchanged; no two objects share a stable id; the stub solver returns the +//! input geometry verbatim; and the *set* of score-graph sources recovered from +//! the RenderIR is exactly the set laid out — a surjection onto graph identity +//! (one source may back several manifestations, each a distinct layout object). +//! This is the contract the testkit's layout harness drives, now against the +//! real crate. use std::collections::{BTreeMap, BTreeSet}; @@ -97,8 +99,8 @@ fn provenance_map<'a>( /// completes without panic and **without losing provenance back-references**. /// Specifically: /// -/// * the stub solver returns [`SolveStatus::Solved`] with all hard constraints -/// satisfied; +/// * the stub solver returns a renderable status, claiming hard-constraint +/// satisfaction exactly when no constraint is declared (it evaluates none); /// * the complete [`Provenance`] of every object — `source`, `synthesis`, /// `dependencies`, and `stable_id` — survives every stage unchanged (compared /// as `stable_id -> Provenance` maps, so a dropped dependency or synthesis @@ -175,10 +177,21 @@ pub fn round_trip_with(score: &Score, solver: &S) -> RoundT "the solver must return a renderable layout, got {:?}", report.status ); - assert!( - report.satisfied_hard_constraints, - "the solver must satisfy all hard constraints" - ); + if solver.tier() == SolverTier::Stub { + // The interface-only stub evaluates no constraints, so it may claim + // hard-constraint satisfaction only for a constraint-free problem — + // with any declared, an honest report claims none. + assert_eq!( + report.satisfied_hard_constraints, + constrained.constraints.is_empty(), + "the stub must claim satisfaction exactly when no constraint is declared" + ); + } else { + assert!( + report.satisfied_hard_constraints, + "a conformant solver must satisfy all hard constraints" + ); + } // The Stub tier's geometry contract: it returns the input geometry *verbatim* // — each resolved glyph's position is exactly its constrained baseline (Chapter @@ -404,8 +417,10 @@ mod tests { .collect(); assert_eq!(manifestations.len(), 2); assert_ne!(manifestations[0], manifestations[1]); + // The pipeline declares real constraints for this score, which the stub + // does not evaluate — renderable, but not exactly `Solved`. let report = round_trip(&score); - assert_eq!(report.status, SolveStatus::Solved); + assert!(report.status.is_renderable()); } /// Across a multi-region score, `to_logical` never emits two layout objects diff --git a/crates/epiphany-layout-ir/src/solver.rs b/crates/epiphany-layout-ir/src/solver.rs index 5f4a830..f6f74a4 100644 --- a/crates/epiphany-layout-ir/src/solver.rs +++ b/crates/epiphany-layout-ir/src/solver.rs @@ -9,7 +9,9 @@ //! a [`SolveReport`] with its full diagnostic surface (unsatisfied constraints, //! warnings, a [`QualityMetricVector`], budget used, state) — and a //! [`StubSolver`] that, per the QUICKSTART, "returns `SolveStatus::Solved` with -//! the input geometry verbatim." +//! the input geometry verbatim" — for a constraint-free problem; with +//! constraints declared it stays a renderable passthrough but claims no +//! satisfaction (see [`StubSolver`]). //! //! **Quality-metric *computation* is deliberately not implemented** (QUICKSTART: //! "only the interface — don't implement quality metrics"): the @@ -273,11 +275,29 @@ pub enum InvalidationScope { pub struct SpringSlotId(pub u128); /// A constraint identifier referenced by [`SolveReport::unsatisfied_constraints`] -/// (Chapter 9: `ConstraintId`). The stub never reports any because it rejects -/// explicit constraints it cannot evaluate. +/// (Chapter 9: `ConstraintId`). The stub never reports any: it evaluates no +/// constraints, so it neither claims one satisfied nor names one unsatisfied. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct ConstraintId(pub u128); +/// The strength a constraint binds the solver with (Chapter 9 §"Strength +/// Levels": `ConstraintStrength`). Constraints do not carry this in the IR — +/// the spec's [`crate::LayoutConstraint`] enum has no strength field — so it is +/// attached by rule via [`crate::LayoutConstraint::strength`]. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ConstraintStrength { + /// Hard constraint. The solver MUST satisfy it or return + /// [`SolveStatus::Unsatisfiable`], and MUST NOT treat it as if it were + /// `Preferred` for any reason, including quality optimization (Chapter 9 + /// §"Strength Levels"). + Required, + /// Soft constraint with an associated weight. The solver minimizes the + /// weighted violation when optimizing; an unhonoured preference is a + /// warning ([`SolverWarningKind::LargeSoftConstraintViolation`]), never an + /// `Unsatisfiable`. + Preferred { weight: f64 }, +} + /// A declared invalidation (Chapter 9: `InvalidationSet`) over the invalidated /// slots, bands, constraints, and glyphs. #[derive(Clone, PartialEq, Eq, Debug)] @@ -384,6 +404,15 @@ pub trait ConstraintSolver: Send + Sync { /// (Chapter 7 §7.3.2). A glyph whose metrics are not bundled, or a catalog hash /// that does not match its glyphs, is a well-formedness failure reported as /// [`SolveStatus::InternalError`] (never a panic). +/// +/// **Declared constraints are not evaluated** ([`SolverTier::Stub`]), and the +/// report is honest about it in both directions: the solve stays renderable +/// (geometry passes through; unevaluated constraints are not a defect in the +/// *input*), but `satisfied_hard_constraints` is `false` and a warning names +/// the gap — the stub never claims satisfaction it did not check. Chapter 9 +/// has no status for "renderable, constraints unevaluated", so the closest +/// non-claiming renderable status, [`SolveStatus::SolvedWithWarnings`], is +/// used (see DECISIONS.md). pub struct StubSolver; impl StubSolver { @@ -398,10 +427,31 @@ impl StubSolver { .collect(); let metrics_available = all_available(names.iter().copied()); let catalog_valid = metrics_available && input.catalog == BravuraCatalog.identity(&names); + let well_formed = structural_valid && catalog_valid; // This interface-only solver can preserve already-resolved geometry but // does not evaluate explicit constraints. It must not claim those are // satisfied merely because the input is structurally well formed. - let well_formed = structural_valid && catalog_valid && input.constraints.is_empty(); + let unevaluated = input.constraints.len(); + + let status = if !well_formed { + SolveStatus::InternalError + } else if unevaluated > 0 { + SolveStatus::SolvedWithWarnings + } else { + SolveStatus::Solved + }; + let warnings = if well_formed && unevaluated > 0 { + vec![SolverWarning { + kind: SolverWarningKind::UnusualLayoutDecision(format!( + "the interface-only stub solver evaluated none of the {unevaluated} \ + declared constraint(s); satisfaction is not claimed" + )), + affected_objects: Vec::new(), + message: "declared constraints were not evaluated".to_owned(), + }] + } else { + Vec::new() + }; let glyphs: Vec = if structural_valid { input @@ -452,12 +502,10 @@ impl StubSolver { .collect(); SolveReport { - status: if well_formed { - SolveStatus::Solved - } else { - SolveStatus::InternalError - }, - satisfied_hard_constraints: well_formed, + status, + // Honest in both directions: false when the input is malformed *and* + // when constraints were declared but not evaluated. + satisfied_hard_constraints: well_formed && unevaluated == 0, layout: ResolvedLayoutIR { source: input.source, pages, @@ -467,7 +515,7 @@ impl StubSolver { catalog: input.catalog.clone(), }, unsatisfied_constraints: Vec::new(), - warnings: Vec::new(), + warnings, metric_vector: QualityMetricVector::unmeasured(), // The stub does no iterative work; its deterministic budget use is zero. budget_used: SolverBudgetUsed::default(), @@ -613,14 +661,14 @@ mod tests { )) ); - // A well-formed constraint reference validates — even though the stub - // solver still refuses to *evaluate* it (it cannot claim it satisfied). + // A well-formed constraint reference validates — and the stub solver + // still does not *evaluate* it: the solve stays renderable, but it does + // not claim the constraint satisfied. input.constraints = vec![LayoutConstraint::NoCollision { a: real, b: real }]; assert!(input.validate().is_ok()); - assert_eq!( - StubSolver.solve(&input, &SolverConfig::default()).status, - SolveStatus::InternalError - ); + let report = StubSolver.solve(&input, &SolverConfig::default()); + assert_eq!(report.status, SolveStatus::SolvedWithWarnings); + assert!(!report.satisfied_hard_constraints); } #[test] @@ -741,8 +789,15 @@ mod tests { .constraints .push(crate::LayoutConstraint::NoCollision { a: glyph, b: glyph }); let report = StubSolver.solve(&input, &SolverConfig::default()); - assert_eq!(report.status, SolveStatus::InternalError); + // Unevaluated constraints are not a defect in the input, so the solve is + // renderable — but satisfaction is not claimed, and a warning names the gap. + assert_eq!(report.status, SolveStatus::SolvedWithWarnings); + assert!(report.status.is_renderable()); assert!(!report.satisfied_hard_constraints); + assert_eq!(report.warnings.len(), 1); + assert!(report.unsatisfied_constraints.is_empty()); + // The geometry still passes through verbatim. + assert_eq!(report.layout.glyphs[0].position, input.glyphs[0].baseline); } #[test] diff --git a/crates/epiphany-ops/DECISIONS.md b/crates/epiphany-ops/DECISIONS.md index ca3bd6d..e63d142 100644 --- a/crates/epiphany-ops/DECISIONS.md +++ b/crates/epiphany-ops/DECISIONS.md @@ -147,6 +147,16 @@ a faithfulness gap the graph convergence gate (criterion 1) would surface. records each seeded spanner's event-anchored endpoints in `structures` (as it already did for slurs/ties/beams), so a base spanner re-anchors through the same rule as a created one rather than being left dangling. +- **A `CascadeDeleteTuplets` also drops decompositions that named the tuplet.** A + notated decomposition component records its tuplet by id (`NotatedComponent.tuplet`), + so once the cascade removes the tuplet structure, any attachment naming it would + dangle — `check_invariants` flags it as a cross-cutting reference that no longer + resolves (invariant 6). `materialize_graph_delete` therefore prunes, in the same + step, every decomposition attachment whose components reference a removed tuplet. + Those members are tombstoned in the same cascade, so the decomposition has nothing + left to describe. This is what lets the editor's atomic tuplet overwrite (a pencil + insert over a triplet member removes the whole triplet) leave an invariant-valid + graph even when a member carried an in-tuplet decomposition. This consistency is what lets `graph_edit_session` create cross-cutting structures and delete their endpoints, giving the Group-2 CRUD ops (and slur re-anchoring) @@ -327,6 +337,17 @@ cascade) is implemented faithfully; only the metric "nearest" is approximated. **For the spec:** no change needed — this resolves once the graph mutation phase tracks positions; recorded so the approximation is explicit. +*Push-3 update (2026-07): the four-key "nearest" metric is now implemented +(`nearest_live_event` + `containment_rank`, over the canonical ledger indices) +and drives the marker and graphic-gesture rows plus the slur/spanner +`Reanchored` reason; see "Re-anchoring rule-table completion" below. For +slurs/spanners the table itself prescribes surviving-endpoint collapse, so +`nearest_survivor` legitimately remains the endpoint-set minimum (proximity- +aware re-targeting beyond the endpoints stays the table's own "deferred +refinement"). Wall-clock distance in proportional regions remains +unimplemented — the occupancy index is metric-only — so a wall-clock referent +falls to the kind's declared failure action.* + ### P11-C6 — time-model compatibility is computed when a graph is available `ChangeRegionTimeModel` retains a `declared_incompatible` list for base-free @@ -409,3 +430,281 @@ conflict-id derivation, and the materialized-state bytes are testable now. This is deterministic and unambiguous but **provisional**: when the Binary Format companion lands, reconcile `encode.rs` and the per-type `CanonicalEncode` impls with it. A failing cross-crate round-trip test is the trigger. + +## Spec-compliance audit follow-up (2026-07, Push 1) + +Four reduction-semantics fixes closing MUST-level gaps the six-agent spec audit +confirmed, plus one parity check. Each changes canonical effect bytes only in +the scenario it fixes; all determinism gates (permutation invariance, 10k fuzz, +migration equivalence) stay green. + +- **Transpose skips tombstoned targets.** The catalog (§Transpose, + re-anchoring) says "tombstoned targets are skipped (the transpose applies + only to live pitches)"; the code refused the whole operation on any dead + target. Now: missing target → whole-op `TargetMissing` refusal (a dangling + reference is malformed authorship, unchanged); tombstoned targets are + skipped and the live remainder shifts (`Applied`); all-tombstoned + degenerates to `NoOp { TargetTombstoned }` (byte-identical to the old + behavior for that sub-case). The skip is not recorded as a repair: no + compensating change is performed on the skipped target. + +- **Marker re-anchoring is a recorded repair.** Chapter 6 §Re-Anchoring: + "Re-anchoring actions MUST be recorded as RepairRecord entries in the + triggering operation's effect." The graph materializer re-pointed + event-anchored markers to their region start silently; + `materialize_graph_delete` now returns those re-anchors as + `RepairKind::Reanchored { …, reason: ExplicitFallback }` records + (`ExplicitFallback` because region-start is the documented P11-C5 stand-in + for the table's "nearest event in same staff instance" metric, which stays + deferred). Delete and undo effects carry them. Bookkeeping-only `reduce()` + cannot see markers (they are graph state), so the records appear only under + graph-aware reduction — same documented asymmetry class as base-only + regions. + +- **System-derived counter collision check** (Chapter 5 §"System-Derived + Counter Collisions" — the audit's top reduction MUST gap). The reducer now + keeps a mint registry `(ObjectKind, counter) → (canonical inputs, minting + op)` seeded from the base graph (`SystemPromoted` voices via the `MUSCSVCE` + preimage, `SYSTEM_DERIVED` pitches via `canonical_pitch_bytes`, now public + in epiphany-core for exactly this) and checked by a pre-walk over the + canonical order before any effect is applied. Prospective mints are the + promotion pre-pass assignments plus `SYSTEM_DERIVED` pitches carried by + minting payloads (InsertEvent, InsertIdentifiedPitch). On the first + differing-inputs collision: a `SystemIdentifierCollision` anomaly is + recorded (both input sets retained), reduction does not continue past the + collision point, and the earlier occupant op is held too, so *neither* + input set occupies the collided counter. Held ops surface in `pending` under + the new `PendingReason::HaltedBySystemCollision { at }` (discriminant 4, + additive); transactions with a held member are wholly held, and causal + dependents hold behind them (`DependsOnPending`). Scope decisions, made + deliberately: (a) the pre-walk is conservative — a claimed mint participates + even if the op would fail an unrelated apply-time precondition, since two + input sets contending for one counter is a structural identity failure + regardless of which contender materializes; (b) a base occupant (owner = + None) cannot be evicted by this reduction and is left to diagnostic + recovery; (c) in-place content rewrites of a live system pitch (ModifyEvent / + ModifyIdentifiedPitch) are *not* treated as mints — that is Invariant-11 + territory. **For Pass 12:** should reduction refuse content modification of + a `SYSTEM_DERIVED` pitch outright (it silently invalidates the id's + content-derivation)? Reader-side diagnostic-recovery gating on a bundle + whose state carries this anomaly is bundle/editor work, tracked with the + edit-barrier seam. + +- **ResolveConflict meta-conflict names both resolvers.** The spec requires a + true conflict's `caused_by` to name "at least two" operations; the + meta-conflict for a differing later resolve had `winner == loser == self` + and one cause. Now: winner = the earlier resolver (its action stands), + loser = the later differing resolver, `caused_by` = both. `affected_objects` + stays empty — a conflict record has no `TypedObjectId` kind, so the + contested conflict cannot be named there (spec-side gap, Pass-12-adjacent). + The related asymmetries (a causally-later resolve cannot supersede; a + differing resolve against `Dismissed` reads `AlreadyApplied`) are spec-gray + and deliberately unchanged. + +- **Base-free pitch-id freshness.** `insert_event` now refuses a carried pitch + id that already exists in canonical state under bookkeeping-only `reduce()` + too (the graph-aware precondition already did, with the same + `TargetTombstoned` reason), closing one base-free/graph-aware divergence + from the audit. Placed after the graph precondition so graph-aware effect + bytes are unchanged. + +Reserved effect vocabulary (`OperationEffect::TombstonedTarget`, +`NoOpReason::SupersededByLaterOperation`, `PositionOutsideRegion`, +`PitchSpaceMismatch`, `ReanchorResult`) is now annotated as reserved at the +type definitions with the condition under which each becomes load-bearing. + +## Re-anchoring rule-table completion (2026-07, Push 3) + +The remaining referent rows of the re-anchoring rule table (core_spec §"The +Re-Anchoring Rule Table") are now implemented: **marker**, **cue event**, +**comment**, **analytical annotation**, and **graphic gesture** — together with +the four-key "nearest" total ordering (§"Total Ordering for Nearest") they +depend on. No discriminant was added or renumbered anywhere; every record uses +the ratified `RepairKind`/`ReanchorReason` vocabulary. + +- **The four-key "nearest" is computed from the canonical ledger indices.** + `nearest_live_event` takes the strict lexicographic minimum of (containment + proximity, absolute rational time distance from the referent's resolved + position, forward-before-backward, ascending `EventId` — whose numeric order + *is* its canonical 16-byte order) over live events within the kind's declared + proximity bound. Proximity (`containment_rank`: same voice 0, staff instance + 1, staff 2, region 3, canvas 4) reads `instance_voices`, the new + `instance_staff` map (seeded + maintained by `CreateStaffInstance`), and + `region_instances`; distance/direction read `voice_occupancy`. All are + base-free indices, so `reduce()` and `reduce_onto()` rank identically + wherever both can represent a scenario. Occupancy is metric-only, so + wall-clock distance (proportional regions) is a deferred refinement: a + wall-clock referent finds no candidate and falls to the kind's declared + failure action. +- **Where the rows run: the graph arm, one decision per row.** None of the five + kinds is creatable by an operation — they exist only in seeded base graphs — + so their rows run in `reanchor_event_referents`, called from + `materialize_graph_delete` (hence from both the `DeleteEvent` path and undo's + `materialize_graph_tombstones`). Each row's ledger record and graph mutation + are decided together, in canonical id order, keeping "the graph follows the + ledger" (above) intact; `reanchor_for_tombstone` explicitly skips these kinds + so no row is double-recorded. The referents are indexed in the same + `structures` map as slurs/ties/beams/spanners (markers by event anchor, + comments/annotations by event-anchored annotation anchors, gestures by + `Events`/`Range` event references, cues — keyed by their own `EventId` — by + their source lists); the four creatable kinds' create/modify/delete paths are + unchanged. +- **Marker: nearest event in the same staff instance replaces the Push-1 + region-start fallback.** The re-anchored anchor keeps its offset (the + survivor shares the staff instance, hence the region and its offset + discipline), and the recorded reason names the *achieved* proximity rank + (`SameVoiceNearer` when the survivor shares the voice). On failure the marker + **orphans**: kept live in ledger and graph with `RepairKind::Orphaned`; the + graph anchor degrades to the containing region's start purely as reference + hygiene (invariant 10 rejects a dangling event anchor) — that form is no + longer presented as a re-anchor choice. +- **Cue event: plain-text cascade on any source deletion.** Deleting *any* + event in a live cue's `source` cascade-deletes the cue — ledger tombstone, + graph removal, `CascadeDeleted` repair — in the same reduction step. The + cascaded cue is itself a tombstoned event, so the full pass runs over its own + referents transitively (a cue-of-a-cue cascades along; ties/slurs on the cue + re-anchor through the ordinary ledger arm). The rationale-vs-action tension + for multi-source cues ("no source is meaningless" suggests truncate-while- + any-survives) is deliberately *not* resolved in code — proposed Pass-12 row. +- **Comment: orphan, with deterministic anchor hygiene.** The ledger records + `Orphaned` and the comment survives everywhere; because invariant 10 rejects + dangling anchors, the graph anchor degrades deterministically — an `Event` + anchor to `AnnotationAnchor::Region(containing region)`, a dead `Range` + endpoint to the region edge on its side (start → `Start`, end → `End`). +- **Analytical annotation: extent-preserving range reconstruction, else + orphan.** An event-anchored annotation whose event dies re-anchors to + `AnnotationAnchor::Range` with both endpoints as region-start `Musical` + offsets covering the event's exact span (positions are region-relative, so + the resolved extent is preserved); recorded as `Reanchored { to: + Region(region), reason: ExplicitFallback }` (the row is a declared fallback, + not a proximity choice). Range-anchored annotations get the same treatment + per dead endpoint (event position plus any musical anchor offset). A + wall-clock or indeterminate span is not expressible as a stored + region-relative range — the annotation orphans with the comment's anchor + hygiene; the expressibility gap is a proposed Pass-12 row. +- **Graphic gesture: nearest re-target / truncate / orphan.** `Events` + references to the dead event re-target to the nearest survivor in the same + staff instance (`Reanchored`, reason per achieved rank); with no candidate + the reference drops — `SpannerTruncated { removed_members: [event] }` while + references remain (the vocabulary's own definition, "lost members but enough + remained", fits), `Orphaned` when the list empties (gesture kept, user + content). `Range` anchoring "truncates": a dead endpoint moves to its region + edge (start → `Start`, end → `End`, offset zero) with `Reanchored { to: + Region, reason: ExplicitFallback }` — the least-surprising deterministic + reading of the table's one-word action; proposed Pass-12 row. `Free` is never + indexed (table: "no action"). +- **Slur/spanner `Reanchored` reason is computed, not hardcoded.** The + surviving-endpoint collapse itself is unchanged, but the reason now names the + survivor's actual containment rank relative to the tombstoned endpoint + (`containment_rank` over the same ledger indices; `SameVoiceNearer` remains + the default when neither side has an indexed metric placement). Rank 4 (same + canvas) has no ratified `ReanchorReason` variant, so it is recorded as + `ExplicitFallback` rather than appending a discriminant — spec-vocabulary + question, proposed Pass-12 row. +- **Known asymmetries, kept deliberately.** (a) The five rows fire only under + graph-aware reduction — the same documented asymmetry class as the Push-1 + marker fix (base-free `reduce()` cannot see these kinds at all). (b) The + tie/beam/slur/spanner *ledger* arm still does not run in the undo path + (pre-existing gap, unchanged by this slice; the graph-only rows *do* run + there via `materialize_graph_delete`). + +## ResolveEquivocation + validation modes (2026-07, Push 3) + +Two Push-3 items land together: the **ResolveEquivocation** meta-operation +(operation_catalog §"ResolveEquivocation", ratified this pass) and the +**validation-mode** seam (core_spec §"Validation Modes"). One payload +discriminant was appended (`OperationPayload::ResolveEquivocation` = 3); the +ratified 0..=2 and every other discriminant table are untouched. Canonical +reduction changes **only** for scenarios containing a valid resolve of an +equivocated slot — everything else reduces byte-identically (the extended +equivocation fuzz plus the unchanged `run_equivocation_fuzz` gate this). + +- **Promotion is a set-level pre-pass, not a walk step.** The catalog's rule + ("when the operation set holds an Equivocated slot for `target` and `chosen` + names one of its candidates, the slot reduces as if it had always been + Single") conditions on the *operation set*, so `Reducer::run` resolves it in + step 1b, before pending computation and ordering: among Single-slot, + non-quarantined resolves whose `(target, chosen)` is valid, the smallest + reduction tuple — the same total HLC order `canonical_reduction_order` + selects ready ops by — governs. The chosen candidate envelope then joins the + reducible set *at its own canonical position*: it flows through + `compute_pending` (its own causal gaps still hold it), transactions, voice + promotion, and the walk exactly like a native Single, and dependents that + were `DependsOnEquivocated` unblock. A resolved slot records no + `OperationSlotEquivocated` anomaly; losing candidates stay only in the + opset's diagnostic candidate store. +- **No `OperationSet` API extension was needed.** The promotion needs the + candidate *envelope*, and `OperationSet::candidate(hash)` already exposes + the retained diagnostic store (the CRDT property forbids dropping + candidates, so every hash in an `Equivocated` slot resolves). `accept` + transitions are untouched — the opset still holds the slot as `Equivocated`; + the promoted view lives only in the reducer (`promoted_singles`, consulted + by `env_of` so concurrency checks see the slot "as if always Single"). +- **Resolve effects mirror `resolve_conflict`.** Governing resolve → + `Applied`; later resolve naming the same candidate → `NoOp(AlreadyApplied)`; + later *valid* resolve naming a differing candidate → + `StructuralFieldCollision` on `FieldPath("equivocation_resolution")` with + winner = governing, loser = later, both in `caused_by`, `affected_objects` + empty (a slot is not a `TypedObjectId`) → `Conflicted`. A resolve whose + target is absent, holds a Single slot, or whose `chosen` names no candidate + is a precondition no-op reusing `TargetMissing` — the named target/candidate + pair does not exist — rather than a new appended reason. +- **Deliberate single-pass simplifications (proposed Pass-12 rows).** (a) A + promoted candidate that is itself a `ResolveEquivocation` does not govern a + further promotion (no cascade/fixpoint; the catalog names none). (b) The + promoted candidate is not re-subjected to HLC-monotonicity segmentation + (quarantine detection runs over native singles first; "as if it had always + been Single" vs. the quarantine pass ordering is a spec question). (c) A + resolve held pending by its own causal gaps still governs promotion — the + set-level rule needs no walk position — while its recorded effect stays + subject to the ordinary pending rules. +- **v0 migration.** v0 predates the entry, so `V0OperationPayload` gains a + `ResolveEquivocation` variant carried **verbatim** — the same "v1-native, + round-trip by identity" treatment as the Group 1–4 kinds. `project_v1_to_v0` + stays total; `migrate_v0_envelope` maps it back by identity (deterministic, + trivially equivalence-preserving). +- **Golden locks added.** `operation_kind_wire_discriminants_are_golden` pins + all 24 `OperationKind` literals (0..=23), + `operation_payload_discriminants_are_golden` pins the payload union + (0..=3 incl. the appended variant), and + `resolve_equivocation_payload_encodes_target_then_hash` pins the 16+32-byte + layout — the append-only discipline is now enforced by test, not convention. +- **Validation modes: the reducer *is* replay mode.** `src/validate.rs` adds + `ValidationMode { Authoring, Replay }` and + `advisory_violations(kind, score)`. `reduce`/`reduce_onto` enforce exactly + the invariant preconditions in every context; authoring enforcement happens + in epiphany-editor-core, which runs `advisory_violations` against its + current materialized score *before minting* and refuses with a new + `EditorError::AdvisoryViolation` (no envelope enters the log). Canonical + reduction behavior and bytes are untouched by the mode machinery; + `AdvisoryViolation` is deliberately **non-canonical** (no encoding, no + discriminants — it never enters effects or state). +- **Advisory inventory (core_spec §6.10).** Implemented: InsertEvent / + ModifyEvent *duration-not-crossing-region-boundary* (the span straddles the + region's musical end bound — resolvable when the extent's end anchor is + region-start-anchored with a `Musical` offset, the same sound-but-incomplete + discipline as `Region::overlaps_in_time`), and CreateCrossCutting(Slur) + *not-spanning-a-region-boundary* (endpoint events resolve to different + regions). Blocked on the truncated data model, documented in the module + docs: InsertEvent *pitch-within-instrument-range* (`Instrument` carries no + range field; staged to the Binary Format companion) and the Slur rule's + "unless explicitly permitted by region configuration" (no such flag on + `Region`; spanning is treated as never permitted until it lands). A + wall-clock or symbolic region extent yields no musical bound, so the + boundary check passes vacuously there (deferred tempo/measure resolution, + P11-C5). + +## Edit-barrier bridge: `OperationKindTag` decode (2026-07, Push 3) + +- **`OperationKindTag` gains its decode mirror.** The tag had `CanonicalEncode` + only (the discriminant byte, plus the registry id's 16 big-endian bytes for + `Registered`); the edit-barrier blob codec (epiphany-layout-ir, the barrier + owner) needs the inverse to read `prohibited_operation_kinds` back out of a + manifest declaration. `CanonicalDecode` now decodes exactly the encoder's + image: variable width (1 byte, or 17 for `Registered`), length mismatches and + trailing bytes rejected, and an **unknown discriminant rejected** — via + `DecodeError::MalformedDomainTag`, the same unknown-discriminant rejection + `TypedObjectId::decode_canonical` already uses, so no new error variant and + no change to the determinism crate. No encoding changed and no discriminant + was appended; `operation_kind_tag_decode_mirrors_encode_exactly` / + `operation_kind_tag_decode_rejects_malformed_bytes` pin the contract. diff --git a/crates/epiphany-ops/src/decode.rs b/crates/epiphany-ops/src/decode.rs index eeb0965..0dd173b 100644 --- a/crates/epiphany-ops/src/decode.rs +++ b/crates/epiphany-ops/src/decode.rs @@ -194,6 +194,7 @@ fn pending_reason(reader: &mut Reader<'_>) -> Result { 1 => Ok(PendingReason::DependsOnEquivocated { on: blocker }), 2 => Ok(PendingReason::DependsOnExcluded { on: blocker }), 3 => Ok(PendingReason::DependsOnPending { on: blocker }), + 4 => Ok(PendingReason::HaltedBySystemCollision { at: blocker }), tag => Err(MaterializedDecodeError::InvalidTag { kind: "PendingReason", tag, diff --git a/crates/epiphany-ops/src/effect.rs b/crates/epiphany-ops/src/effect.rs index 33cc678..aa73886 100644 --- a/crates/epiphany-ops/src/effect.rs +++ b/crates/epiphany-ops/src/effect.rs @@ -36,6 +36,11 @@ pub enum OperationEffect { Conflicted { conflict: ConflictId }, /// The target was tombstoned; preserved in the operation set, no graph /// effect beyond the recorded effect. + /// + /// Reserved: the current reducer expresses this outcome as + /// [`NoOpReason::TargetTombstoned`] instead; no reduction path produces + /// this variant yet. It stays in the vocabulary (and its discriminant + /// stays pinned) because the spec's effect table names it. TombstonedTarget { target: TypedObjectId }, /// Reduces to no effect; the reason is recorded and is canonical. NoOp { reason: NoOpReason }, @@ -75,6 +80,11 @@ pub enum NoOpReason { /// Duplicates a causally-prior operation's effect. AlreadyApplied, /// A later operation in canonical order subsumed this one's effect. + /// + /// Reserved: no reduction path produces this yet — Pass 11 item 2.2 + /// decided the winner carries `Conflicted` while the superseded loser + /// keeps `Applied`. Retagging losers with this reason is an open + /// disposition (see the item's rationale in the ratification log). SupersededByLaterOperation { superseder: OperationId }, /// An invariant precondition satisfied at authoring time fails under /// concurrent reduction; the intent is not preserved. @@ -127,8 +137,14 @@ pub enum PreconditionFailureReason { EventDurationInvalid, /// The target position falls outside the region declared by the envelope, /// or the region does not exist. + /// + /// Reserved: producing this requires resolving positions against region + /// extents, which is the deferred P11-C5 resolved-position machinery. PositionOutsideRegion, /// A pitch-space or tuning-context precondition failed. + /// + /// Reserved: producing this requires the Chapter 4 tuning catalog + /// (pitch-space registry), which is deferred Track-C work. PitchSpaceMismatch, /// The operation targeted a voice that does not exist or is tombstoned. VoiceMissing, @@ -322,6 +338,10 @@ impl CanonicalEncode for TupletCompensationKind { /// The result of the re-anchor function for one referencing object /// (Chapter 6 §6.5). The reduction maps each result to a [`RepairKind`] (or a /// conflict) on the triggering operation's effect. +/// +/// Reserved: the current reducer constructs [`RepairKind`] values directly +/// rather than routing through this intermediate; it becomes load-bearing when +/// the full "nearest surviving anchor" ordering (P11-C5) lands. #[derive(Clone, PartialEq, Eq, Debug)] pub enum ReanchorResult { /// The reference is replaced with a reference to a new target. diff --git a/crates/epiphany-ops/src/envelope.rs b/crates/epiphany-ops/src/envelope.rs index e347485..cc905b1 100644 --- a/crates/epiphany-ops/src/envelope.rs +++ b/crates/epiphany-ops/src/envelope.rs @@ -16,7 +16,7 @@ //! foremost `stamp.id == id`. use epiphany_core::{OperationId, TransactionId}; -use epiphany_determinism::{CanonicalEncode, DomainTag, Preimage}; +use epiphany_determinism::{CanonicalDecode, CanonicalEncode, DomainTag, Preimage}; use crate::causal::CausalContext; use crate::encode::{push_canon, push_tag}; @@ -106,6 +106,24 @@ impl CanonicalEncode for OperationEnvelope { } } +/// Reads the [`OperationId`] a canonically encoded envelope declares from its +/// **leading 16 bytes** alone, without decoding the rest of the envelope. +/// +/// The canonical envelope encoding leads with the id +/// ([`OperationEnvelope::encode_canonical`] pushes `id` first, and an +/// `OperationId`'s canonical form is exactly 16 big-endian bytes), so this is a +/// total, allocation-free peek. Returns `None` when fewer than 16 bytes are +/// present. It deliberately performs **no** validation of the remaining bytes — +/// full decoding stays the caller's job — which is exactly the contract the +/// bundle's operation index (Chapter 8 §"The Operation Index") needs: the +/// bundle layer keys index entries on the raw 16 id bytes without ever +/// interpreting an envelope, and this helper is the one place the ops layer +/// vouches that those bytes really are the id. +pub fn peek_operation_id(envelope_bytes: &[u8]) -> Option { + let head = envelope_bytes.get(..16)?; + OperationId::decode_canonical(head).ok() +} + /// Why an envelope failed the well-formedness check (Chapter 6 §6.4). A /// rejected envelope is recorded in the local diagnostic log but does not enter /// the canonical operation set. @@ -247,6 +265,21 @@ mod tests { ); } + #[test] + fn peek_operation_id_reads_the_leading_canonical_bytes() { + let id = OperationId::new(ReplicaId(0x0102_0304_0506_0708), 0x1122_3344_5566_7788); + let e = env(id, id); + let bytes = e.to_canonical_bytes(); + // The canonical envelope encoding truly *leads* with the id's 16 + // canonical bytes — the invariant `peek_operation_id` (and the bundle's + // operation index built on it) depends on. + assert_eq!(&bytes[..16], &id.canonical_bytes()); + assert_eq!(peek_operation_id(&bytes), Some(id)); + // A short buffer has no id to peek. + assert_eq!(peek_operation_id(&bytes[..15]), None); + assert_eq!(peek_operation_id(&[]), None); + } + #[test] fn envelope_hash_changes_with_payload_bytes() { let mut a = env( diff --git a/crates/epiphany-ops/src/fuzz.rs b/crates/epiphany-ops/src/fuzz.rs index 5bf28bd..4b6d95a 100644 --- a/crates/epiphany-ops/src/fuzz.rs +++ b/crates/epiphany-ops/src/fuzz.rs @@ -40,7 +40,7 @@ use crate::payload::{ use crate::stamp::{HybridLogicalClock, OperationStamp}; use crate::support::AuthorId; use crate::valuegen; -use crate::IntegrityAnomalyKind; +use crate::{EnvelopeHash, IntegrityAnomalyKind, OperationEffect}; /// Number of replicas the generator draws authors from. const REPLICAS: u64 = 3; @@ -410,6 +410,137 @@ pub fn run_equivocation_fuzz(iters: u64, seed: u64) { } } +/// Runs `iters` equivocation-*resolution* iterations from `seed` (the +/// `ResolveEquivocation` sibling of [`run_equivocation_fuzz`]). Each iteration +/// builds two distinct canonical envelopes under one `OperationId` plus a +/// `ResolveEquivocation`, embeds them in random noise, and asserts across four +/// random acceptance orders: +/// +/// * with a **valid** resolve (`chosen` names a real candidate): the resolved +/// slot contributes an effect at its own id, no `OperationSlotEquivocated` +/// anomaly is recorded for it, the resolve itself applies, and every +/// permutation reduces to byte-identical [`crate::MaterializedState`]; +/// * with an **invalid** resolve (`chosen` names no candidate): behavior is +/// exactly today's unresolved equivocation — the slot contributes nothing, +/// the anomaly is recorded, the resolve is a precondition no-op — and the +/// permutation invariance still holds. +pub fn run_equivocation_resolution_fuzz(iters: u64, seed: u64) { + let mut rng = SplitMix64::new(seed); + for _ in 0..iters { + let id = OperationId::new(ReplicaId(1 + rng.below(REPLICAS)), rng.below(5)); + + let mk = |rng: &mut SplitMix64, spelling: u8| OperationEnvelope { + id, + author: AuthorId(0), + stamp: OperationStamp::new( + HybridLogicalClock::new(epiphany_core::WallClockTime(rng.below(100) as i64), 0), + id, + ), + causal_context: CausalContext::new(), + transaction: None, + payload: OperationPayload::Primitive(OperationKind::RespellPitch(RespellPitchOp { + pitch: pitch(0), + spelling: valuegen::spelling(spelling), + })), + }; + let a = mk(&mut rng, 1); + let b = mk(&mut rng, 2); // distinct canonical bytes (different spelling) + debug_assert_ne!(a.envelope_hash(), b.envelope_hash()); + + // Valid two-thirds of the time; otherwise a hash naming no candidate. + let valid = !rng.chance(3); + let chosen = if !valid { + EnvelopeHash([0xEE; 32]) + } else if rng.chance(2) { + a.envelope_hash() + } else { + b.envelope_hash() + }; + // The resolve lives on a replica the noise generator never draws + // (noise uses 1..=REPLICAS), so its own slot can neither equivocate + // nor land in a quarantined segment. + let resolve_id = OperationId::new(ReplicaId(REPLICAS + 2), 0); + let resolve = OperationEnvelope { + id: resolve_id, + author: AuthorId(0), + stamp: OperationStamp::new( + HybridLogicalClock::new(epiphany_core::WallClockTime(rng.below(100) as i64), 0), + resolve_id, + ), + causal_context: CausalContext::new(), + transaction: None, + payload: OperationPayload::ResolveEquivocation( + crate::payload::ResolveEquivocationPayload { target: id, chosen }, + ), + }; + + let noise_count = rng.below(4) as usize; + let noise = gen_envelope_set(&mut rng, noise_count) + .into_iter() + .filter(|e| e.id != id) + .collect::>(); + + let mut items = vec![a.clone(), b.clone(), resolve.clone()]; + items.extend(noise); + + let mut reference: Option> = None; + for _ in 0..4 { + shuffle(&mut items, &mut rng); + let mut set = OperationSet::new(); + set.accept_all(items.iter().cloned()); + let state = set.reduce(); + + let slot_contributes = state.effects.iter().any(|(e, _)| *e == id); + let anomalous = state.anomalies.iter().any(|an| matches!( + an.kind, + IntegrityAnomalyKind::OperationSlotEquivocated { operation_id } if operation_id == id + )); + let resolve_effect = state + .effects + .iter() + .find(|(e, _)| *e == resolve_id) + .map(|(_, eff)| eff); + if valid { + assert!( + slot_contributes, + "a resolved slot must contribute its chosen candidate's effect" + ); + assert!( + !anomalous, + "a resolved slot must record no OperationSlotEquivocated anomaly" + ); + assert_eq!( + resolve_effect, + Some(&OperationEffect::Applied), + "the governing resolve must apply" + ); + } else { + assert!( + !slot_contributes, + "an unresolved equivocated slot must contribute nothing" + ); + assert!( + anomalous, + "an unresolved equivocated slot must record its anomaly" + ); + assert!( + matches!(resolve_effect, Some(OperationEffect::NoOp { .. })), + "an invalid resolve must be a precondition no-op, got {resolve_effect:?}" + ); + } + + let bytes = state.canonical_bytes(); + match &reference { + None => reference = Some(bytes), + Some(reference) => assert_eq!( + &bytes, reference, + "equivocation resolution is not permutation-invariant" + ), + } + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -424,6 +555,11 @@ mod tests { run_equivocation_fuzz(500, 0x1234_5678); } + #[test] + fn equivocation_resolution_smoke() { + run_equivocation_resolution_fuzz(500, 0x9E50_1AE5); + } + #[test] fn generator_is_deterministic() { let mut a = SplitMix64::new(99); diff --git a/crates/epiphany-ops/src/lib.rs b/crates/epiphany-ops/src/lib.rs index 754bae7..f928f6f 100644 --- a/crates/epiphany-ops/src/lib.rs +++ b/crates/epiphany-ops/src/lib.rs @@ -92,6 +92,7 @@ mod slot; mod stamp; mod support; mod v0; +mod validate; pub mod valuegen; pub mod fuzz; @@ -109,7 +110,9 @@ pub use effect::{ NoOpReason, OperationEffect, PreconditionFailureReason, ReanchorReason, ReanchorResult, RepairKind, RepairRecord, TupletCompensationKind, }; -pub use envelope::{well_formed, EnvelopeHash, OperationEnvelope, WellFormednessError}; +pub use envelope::{ + peek_operation_id, well_formed, EnvelopeHash, OperationEnvelope, WellFormednessError, +}; pub use migrate::{migrate_v0_envelope, project_v1_to_v0, MigrationError}; pub use opset::{AcceptOutcome, OperationSet}; pub use payload::{ @@ -117,9 +120,9 @@ pub use payload::{ CreateVoiceOp, CrossCuttingValue, DeleteCrossCuttingOp, DeleteEventOp, DeleteIdentifiedPitchOp, DeleteRegionOp, DeleteStaffInstanceOp, DeleteVoiceOp, InsertEventOp, InsertIdentifiedPitchOp, ModifyCrossCuttingOp, ModifyEventOp, ModifyIdentifiedPitchOp, OperationKind, OperationKindTag, - OperationPayload, PositionRemapping, ResolveConflictPayload, RespellPitchOp, SetMetadataOp, - SetMetricGridOp, SetUserPageBreakOp, SetUserSystemBreakOp, TransactionCategory, - TransactionDescriptor, TransposeOp, TupletCompensation, + OperationPayload, PositionRemapping, ResolveConflictPayload, ResolveEquivocationPayload, + RespellPitchOp, SetMetadataOp, SetMetricGridOp, SetUserPageBreakOp, SetUserSystemBreakOp, + TransactionCategory, TransactionDescriptor, TransposeOp, TupletCompensation, }; pub use reduce::{ canonical_reduction_order, GraphMaterialization, MaterializedState, ObjectState, PendingReason, @@ -135,5 +138,6 @@ pub use support::{ pub use undo::{UndoPolicy, UndoTransactionPayload}; pub use v0::V0OperationEnvelope; +pub use validate::{advisory_violations, AdvisoryViolation, ValidationMode}; mod undo; diff --git a/crates/epiphany-ops/src/migrate.rs b/crates/epiphany-ops/src/migrate.rs index 9719c37..687f69a 100644 --- a/crates/epiphany-ops/src/migrate.rs +++ b/crates/epiphany-ops/src/migrate.rs @@ -95,6 +95,8 @@ fn project_payload(p: &OperationPayload) -> V0OperationPayload { OperationPayload::Primitive(kind) => V0OperationPayload::Primitive(project_kind(kind)), OperationPayload::ResolveConflict(rc) => V0OperationPayload::ResolveConflict(*rc), OperationPayload::UndoTransaction(u) => V0OperationPayload::UndoTransaction(*u), + // v1-native (no v0 predecessor): projected verbatim, like Group 1–4. + OperationPayload::ResolveEquivocation(re) => V0OperationPayload::ResolveEquivocation(*re), } } @@ -231,6 +233,9 @@ fn migrate_payload( } V0OperationPayload::ResolveConflict(rc) => OperationPayload::ResolveConflict(*rc), V0OperationPayload::UndoTransaction(u) => OperationPayload::UndoTransaction(*u), + // v1-native: round-trips by identity (deterministic and trivially + // equivalence-preserving; no context needed). + V0OperationPayload::ResolveEquivocation(re) => OperationPayload::ResolveEquivocation(*re), }) } diff --git a/crates/epiphany-ops/src/payload.rs b/crates/epiphany-ops/src/payload.rs index 47cb464..88c08c9 100644 --- a/crates/epiphany-ops/src/payload.rs +++ b/crates/epiphany-ops/src/payload.rs @@ -33,18 +33,19 @@ use epiphany_core::{ Beam, CanonicalValue, Event, EventDuration, EventId, EventPosition, IdentifiedPitch, - MetricGrid, MusicalDuration, MusicalPosition, Pitch, PitchId, PitchSpelling, Region, RegionId, - RegionTimeModel, Rest, ScoreMetadata, Slur, Spanner, StaffInstance, StaffInstanceId, Tie, - TimeAnchor, TransactionId, TupletId, TypedObjectId, Voice, VoiceId, + MetricGrid, MusicalDuration, MusicalPosition, OperationId, Pitch, PitchId, PitchSpelling, + Region, RegionId, RegionTimeModel, Rest, ScoreMetadata, Slur, Spanner, StaffInstance, + StaffInstanceId, Tie, TimeAnchor, TransactionId, TupletId, TypedObjectId, Voice, VoiceId, }; -use epiphany_determinism::{sorted_canonical, CanonicalEncode}; +use epiphany_determinism::{sorted_canonical, CanonicalDecode, CanonicalEncode, DecodeError}; use crate::conflict::{ConflictId, ResolutionAction}; use crate::encode::{push_canon, push_lp_bytes, push_seq, push_str, push_tag, push_u8_bool}; +use crate::envelope::EnvelopeHash; use crate::support::OperationKindRegistryId; use crate::undo::UndoTransactionPayload; -/// The full payload of an operation envelope: a primitive, or one of the two +/// The full payload of an operation envelope: a primitive, or one of the /// meta-operations (Chapter 6 §"Operation Envelopes"). // v1 payloads carry whole graph values, so the `Primitive` variant is // intentionally larger than the meta-operations — the durability the catalog @@ -60,6 +61,10 @@ pub enum OperationPayload { /// A meta-operation that compensates for a previously-committed /// transaction; the realization of "undo". UndoTransaction(UndoTransactionPayload), + /// A meta-operation that resolves an equivocated operation slot by naming + /// the chosen candidate envelope (operation_catalog + /// §"ResolveEquivocation"). + ResolveEquivocation(ResolveEquivocationPayload), } impl OperationPayload { @@ -68,6 +73,8 @@ impl OperationPayload { OperationPayload::Primitive(_) => 0, OperationPayload::ResolveConflict(_) => 1, OperationPayload::UndoTransaction(_) => 2, + // Appended (ResolveEquivocation); the ratified 0..=2 stay stable. + OperationPayload::ResolveEquivocation(_) => 3, } } } @@ -79,6 +86,7 @@ impl CanonicalEncode for OperationPayload { OperationPayload::Primitive(k) => k.encode_canonical(out), OperationPayload::ResolveConflict(p) => p.encode_canonical(out), OperationPayload::UndoTransaction(p) => p.encode_canonical(out), + OperationPayload::ResolveEquivocation(p) => p.encode_canonical(out), } } } @@ -318,6 +326,63 @@ impl CanonicalEncode for OperationKindTag { } } +impl CanonicalDecode for OperationKindTag { + /// Decodes exactly the canonical form [`CanonicalEncode`] produces: the + /// discriminant byte, plus — for [`OperationKindTag::Registered`] only — + /// the registry id's 16 big-endian bytes. Variable-width, so the input + /// length must match the decoded variant exactly (trailing bytes are an + /// error). An unknown discriminant is rejected, never normalized — + /// [`DecodeError::MalformedDomainTag`], the same unknown-discriminant + /// rejection [`TypedObjectId::decode_canonical`] uses. + fn decode_canonical(bytes: &[u8]) -> Result { + let (&tag, rest) = bytes.split_first().ok_or(DecodeError::UnexpectedLength { + expected: 1, + actual: 0, + })?; + if tag == 16 { + let arr: [u8; 16] = rest.try_into().map_err(|_| DecodeError::UnexpectedLength { + expected: 17, + actual: bytes.len(), + })?; + return Ok(OperationKindTag::Registered(OperationKindRegistryId( + u128::from_be_bytes(arr), + ))); + } + if !rest.is_empty() { + return Err(DecodeError::UnexpectedLength { + expected: 1, + actual: bytes.len(), + }); + } + Ok(match tag { + 0 => OperationKindTag::InsertEvent, + 1 => OperationKindTag::DeleteEvent, + 2 => OperationKindTag::ModifyEvent, + 3 => OperationKindTag::RespellPitch, + 4 => OperationKindTag::Transpose, + 5 => OperationKindTag::CreateCrossCutting, + 6 => OperationKindTag::DeleteCrossCutting, + 7 => OperationKindTag::ModifyCrossCutting, + 8 => OperationKindTag::ChangeRegionTimeModel, + 9 => OperationKindTag::InsertRegion, + 10 => OperationKindTag::DeleteRegion, + 11 => OperationKindTag::InsertStaffInstance, + 12 => OperationKindTag::DeleteStaffInstance, + 13 => OperationKindTag::SetUserSystemBreak, + 14 => OperationKindTag::SetUserPageBreak, + 15 => OperationKindTag::DeclareTransaction, + 17 => OperationKindTag::InsertIdentifiedPitch, + 18 => OperationKindTag::DeleteIdentifiedPitch, + 19 => OperationKindTag::ModifyIdentifiedPitch, + 20 => OperationKindTag::CreateVoice, + 21 => OperationKindTag::DeleteVoice, + 22 => OperationKindTag::SetMetadata, + 23 => OperationKindTag::SetMetricGrid, + _ => return Err(DecodeError::MalformedDomainTag), + }) + } +} + // --- Representative operation payloads (Chapter 6 §6.10). -------------------- /// Insert an event into a voice (Chapter 6 §6.10 InsertEvent). Carries the full @@ -731,6 +796,25 @@ impl CanonicalEncode for ResolveConflictPayload { } } +/// The payload of an equivocation-resolution meta-operation (operation_catalog +/// §"ResolveEquivocation"): the equivocated slot and the candidate envelope (by +/// canonical-bytes hash) that shall stand. Value-complete. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct ResolveEquivocationPayload { + /// The `OperationId` of the equivocated slot to resolve. + pub target: OperationId, + /// The [`EnvelopeHash`] of the candidate envelope that shall stand. + pub chosen: EnvelopeHash, +} + +impl CanonicalEncode for ResolveEquivocationPayload { + fn encode_canonical(&self, out: &mut Vec) { + // Catalog: `target` (16 canonical bytes), then `chosen` (32 bytes). + push_canon(out, &self.target); + push_canon(out, &self.chosen); + } +} + // --- Group 1 (M2): event & pitch leaf-field ops (Chapter 6 §6.10). ----------- /// Overwrite a live event's value (Chapter 6 §6.10 ModifyEvent). Carries the @@ -1053,6 +1137,247 @@ mod tests { use super::*; use epiphany_core::{ReplicaId, SlurId}; + #[test] + fn operation_kind_wire_discriminants_are_golden() { + // GOLDEN LOCK: the discriminant byte leads every canonically-encoded + // primitive payload (operation_catalog §"Value-Typed Payloads"), so the + // literal values are normative wire facts. Encodings are append-only: + // new kinds append past 23; the values below never change. + use crate::valuegen; + use epiphany_core::{MusicalDuration, MusicalPosition, StaffId}; + + let r = ReplicaId(1); + let event_a = EventId::new(r, 1); + let event_b = EventId::new(r, 2); + let pitch = PitchId::new(r, 3); + let region = RegionId::new(r, 4); + let staff = StaffId::new(r, 5); + let instance = StaffInstanceId::new(r, 6); + let voice = VoiceId::new(r, 7); + let slur_id = SlurId::new(r, 8); + let event_value = || { + valuegen::insert_event_value( + event_a, + voice, + MusicalPosition::origin(), + MusicalDuration::whole(), + &[], + ) + }; + let slur_value = || CrossCuttingValue::Slur(valuegen::slur(slur_id, event_a, event_b)); + let anchor = || valuegen::region_start_anchor(region, MusicalPosition::origin()); + + let table: [(OperationKind, u8); 24] = [ + ( + OperationKind::InsertEvent(InsertEventOp { + staff_instance: instance, + event: event_value(), + }), + 0, + ), + ( + OperationKind::DeleteEvent(DeleteEventOp { + event: event_a, + tuplet_compensation: TupletCompensation::NotInTuplet, + }), + 1, + ), + ( + OperationKind::RespellPitch(RespellPitchOp { + pitch, + spelling: valuegen::spelling(1), + }), + 2, + ), + ( + OperationKind::CreateCrossCutting(CreateCrossCuttingOp { + structure: slur_value(), + }), + 3, + ), + ( + OperationKind::ChangeRegionTimeModel(ChangeRegionTimeModelOp { + region, + new_time_model: valuegen::metric_model(), + declared_incompatible: vec![], + remapping: PositionRemapping::PreserveTime, + }), + 4, + ), + ( + OperationKind::SetUserSystemBreak(SetUserSystemBreakOp { + region, + anchor: anchor(), + present: true, + }), + 5, + ), + ( + OperationKind::DeclareTransaction(TransactionDescriptor { + id: TransactionId::new(r, 9), + label: String::new(), + category: None, + }), + 6, + ), + ( + OperationKind::Registered(OperationKindRegistryId(0), vec![]), + 7, + ), + ( + OperationKind::ModifyEvent(ModifyEventOp { + event: event_value(), + }), + 8, + ), + ( + OperationKind::Transpose(TransposeOp { + targets: vec![pitch], + chromatic_steps: 0, + }), + 9, + ), + ( + OperationKind::InsertIdentifiedPitch(InsertIdentifiedPitchOp { + event: event_a, + pitch: valuegen::identified_pitch(pitch), + }), + 10, + ), + ( + OperationKind::DeleteIdentifiedPitch(DeleteIdentifiedPitchOp { pitch }), + 11, + ), + ( + OperationKind::ModifyIdentifiedPitch(ModifyIdentifiedPitchOp { + pitch, + value: valuegen::pitch_value(), + }), + 12, + ), + ( + OperationKind::DeleteCrossCutting(DeleteCrossCuttingOp { + structure: TypedObjectId::Slur(slur_id), + }), + 13, + ), + ( + OperationKind::ModifyCrossCutting(ModifyCrossCuttingOp { + structure: slur_value(), + }), + 14, + ), + ( + OperationKind::CreateRegion(CreateRegionOp { + region: valuegen::region(region), + }), + 15, + ), + (OperationKind::DeleteRegion(DeleteRegionOp { region }), 16), + ( + OperationKind::CreateStaffInstance(CreateStaffInstanceOp { + region, + instance: valuegen::staff_instance(instance, staff), + }), + 17, + ), + ( + OperationKind::DeleteStaffInstance(DeleteStaffInstanceOp { + staff_instance: instance, + }), + 18, + ), + ( + OperationKind::CreateVoice(CreateVoiceOp { + staff_instance: instance, + voice: valuegen::voice(voice), + }), + 19, + ), + (OperationKind::DeleteVoice(DeleteVoiceOp { voice }), 20), + ( + OperationKind::SetMetadata(SetMetadataOp { + metadata: valuegen::score_metadata(0), + }), + 21, + ), + ( + OperationKind::SetMetricGrid(SetMetricGridOp { region, grid: None }), + 22, + ), + ( + OperationKind::SetUserPageBreak(SetUserPageBreakOp { + region, + anchor: anchor(), + present: true, + }), + 23, + ), + ]; + for (kind, expected) in &table { + assert_eq!( + kind.discriminant(), + *expected, + "wire discriminant for {:?} moved — canonical encodings are append-only", + kind.tag(), + ); + // The discriminant byte truly leads the canonical encoding. + assert_eq!(kind.to_canonical_bytes()[0], *expected); + } + } + + #[test] + fn operation_payload_discriminants_are_golden() { + // GOLDEN LOCK: the payload-union discriminant byte leads every + // canonically-encoded envelope payload. 0..=2 are the ratified v1 + // values; 3 (ResolveEquivocation) is appended by the catalog entry + // §"ResolveEquivocation". Append-only; never renumber. + use crate::undo::UndoPolicy; + use epiphany_core::OperationId; + + let r = ReplicaId(1); + let primitive = OperationPayload::Primitive(OperationKind::DeleteEvent(DeleteEventOp { + event: EventId::new(r, 1), + tuplet_compensation: TupletCompensation::NotInTuplet, + })); + let resolve_conflict = OperationPayload::ResolveConflict(ResolveConflictPayload { + target: ConflictId(0), + action: ResolutionAction::Dismiss, + }); + let undo = OperationPayload::UndoTransaction(UndoTransactionPayload { + target: TransactionId::new(r, 2), + policy: UndoPolicy::BestEffort, + }); + let resolve_equivocation = + OperationPayload::ResolveEquivocation(ResolveEquivocationPayload { + target: OperationId::new(r, 3), + chosen: EnvelopeHash([0; 32]), + }); + for (payload, expected) in [ + (&primitive, 0u8), + (&resolve_conflict, 1), + (&undo, 2), + (&resolve_equivocation, 3), + ] { + assert_eq!(payload.discriminant(), expected); + assert_eq!(payload.to_canonical_bytes()[0], expected); + } + } + + #[test] + fn resolve_equivocation_payload_encodes_target_then_hash() { + // Catalog §"ResolveEquivocation": the canonical encoding is exactly the + // target's 16 canonical bytes followed by the 32 hash bytes. + use epiphany_core::OperationId; + let target = OperationId::new(ReplicaId(0x0102_0304_0506_0708), 0x1122_3344_5566_7788); + let chosen = EnvelopeHash([0xAB; 32]); + let p = ResolveEquivocationPayload { target, chosen }; + let bytes = p.to_canonical_bytes(); + assert_eq!(bytes.len(), 48); + assert_eq!(&bytes[..16], &target.canonical_bytes()); + assert_eq!(&bytes[16..], &[0xAB; 32]); + } + #[test] fn transaction_category_discriminants_are_golden() { // RATIFIED by Pass 11 (item 2.4, req:semops:transaction-category): the @@ -1113,6 +1438,48 @@ mod tests { assert_eq!(encoded.len(), tags.len()); } + #[test] + fn operation_kind_tag_decode_mirrors_encode_exactly() { + // Every non-registered variant round-trips through its 1-byte form, and + // the registered variant through its 17-byte (tag + registry id) form. + let mut tags: Vec = (0u8..24) + .filter(|d| *d != 16) + .map(|d| OperationKindTag::decode_canonical(&[d]).expect("known discriminant")) + .collect(); + tags.push(OperationKindTag::Registered(OperationKindRegistryId( + 0x0102_0304_0506_0708_090A_0B0C_0D0E_0F10, + ))); + assert_eq!(tags.len(), 24, "the full v1 tag vocabulary"); + for tag in tags { + let bytes = tag.to_canonical_bytes(); + let decoded = OperationKindTag::decode_canonical(&bytes).expect("round-trips"); + assert_eq!(decoded, tag); + assert_eq!( + decoded.to_canonical_bytes(), + bytes, + "re-encode is byte-identical" + ); + } + } + + #[test] + fn operation_kind_tag_decode_rejects_malformed_bytes() { + use epiphany_determinism::DecodeError; + // Unknown discriminant (24 is one past the v1 vocabulary): rejected, + // never normalized. + assert_eq!( + OperationKindTag::decode_canonical(&[24]), + Err(DecodeError::MalformedDomainTag) + ); + // Empty input. + assert!(OperationKindTag::decode_canonical(&[]).is_err()); + // Trailing byte after a payload-less tag. + assert!(OperationKindTag::decode_canonical(&[0, 0]).is_err()); + // A truncated (and an oversized) Registered payload. + assert!(OperationKindTag::decode_canonical(&[16; 16]).is_err()); + assert!(OperationKindTag::decode_canonical(&[16; 19]).is_err()); + } + #[test] fn reassign_remapping_is_order_independent() { let e1 = EventId::new(ReplicaId(1), 1); diff --git a/crates/epiphany-ops/src/reduce.rs b/crates/epiphany-ops/src/reduce.rs index 118fbf2..db45d83 100644 --- a/crates/epiphany-ops/src/reduce.rs +++ b/crates/epiphany-ops/src/reduce.rs @@ -31,10 +31,11 @@ use std::collections::{BTreeMap, BTreeSet}; use epiphany_core::{ - derive_promoted_voice_id, AnchorOffset, CanonicalValue, Event, EventDuration, EventId, - EventPosition, MetricGrid, MusicalDuration, MusicalPosition, OperationId, Pitch, PitchId, - PitchSpelling, RegionEdge, RegionId, RegionTimeModel, Score, SpellingAttachment, - SpellingDirective, SpellingScope, SpellingSource, StaffInstance, StaffInstanceId, TimeAnchor, + canonical_pitch_bytes, derive_promoted_voice_id, AnchorOffset, AnnotationAnchor, + CanonicalValue, Event, EventDuration, EventId, EventPosition, GestureAnchoring, MetricGrid, + MusicalDuration, MusicalPosition, OperationId, Pitch, PitchId, PitchSpelling, RationalTime, + RegionEdge, RegionId, RegionTimeModel, ReplicaId, Score, SpellingAttachment, SpellingDirective, + SpellingScope, SpellingSource, StaffId, StaffInstance, StaffInstanceId, TimeAnchor, TransactionId, TypedObjectId, Voice, VoiceId, VoiceOrigin, }; use epiphany_determinism::CanonicalEncode; @@ -58,6 +59,7 @@ use crate::payload::{ RespellPitchOp, SetMetadataOp, SetMetricGridOp, SetUserPageBreakOp, TransposeOp, TupletCompensation, }; +use crate::support::{ObjectKind, SerializedCanonicalInputs}; use crate::undo::{UndoPolicy, UndoTransactionPayload}; /// Orders operation envelopes into the canonical reduction order (Chapter 6 @@ -163,6 +165,12 @@ pub enum PendingReason { DependsOnExcluded { on: OperationId }, /// A causal predecessor is itself held pending. DependsOnPending { on: OperationId }, + /// Reduction halted at a system-derived identifier collision (Chapter 5 + /// §"System-Derived Counter Collisions"): this operation is at or past the + /// collision point in canonical order — or is the earlier occupant of the + /// collided counter — and is held pending external recovery. `at` is the + /// operation whose mint collided. + HaltedBySystemCollision { at: OperationId }, } impl PendingReason { @@ -172,6 +180,7 @@ impl PendingReason { PendingReason::DependsOnEquivocated { .. } => 1, PendingReason::DependsOnExcluded { .. } => 2, PendingReason::DependsOnPending { .. } => 3, + PendingReason::HaltedBySystemCollision { .. } => 4, } } fn blocker(&self) -> OperationId { @@ -180,6 +189,7 @@ impl PendingReason { PendingReason::DependsOnEquivocated { on } | PendingReason::DependsOnExcluded { on } | PendingReason::DependsOnPending { on } => *on, + PendingReason::HaltedBySystemCollision { at } => *at, } } } @@ -352,6 +362,11 @@ struct Reducer<'a> { // voice's live events are read from `voice_occupancy`.) region_instances: BTreeMap>, instance_voices: BTreeMap>, + // The staff each staff instance manifests, for the containment-proximity + // key of the re-anchoring "nearest" ordering (same staff = rank 2). Kept + // base-free (seeded + maintained by CreateStaffInstance) so reduce() and + // reduce_onto() rank identically wherever both represent the scenario. + instance_staff: BTreeMap, // Regions whose content carries a staff-based slot (staff-based or hybrid), // and so can hold a metric grid or user break. FreeGraphic regions cannot. // Tracking this lets SetMetricGrid / SetUserPageBreak / SetUserSystemBreak @@ -367,8 +382,24 @@ struct Reducer<'a> { descriptors: BTreeMap, // Losing insert -> (promoted voice, winning insert). promotion: BTreeMap, + // System-derived mint registry for the counter-collision check (Chapter 5 + // §"System-Derived Counter Collisions"): (kind, derived counter) → the + // canonical inputs that derived it, plus the minting operation (None for + // an occupant seeded from the base graph). Consulted only by the pre-walk + // collision detection, never mutated during apply, so it needs no + // transaction snapshot. + system_mints: BTreeMap<(ObjectKind, u64), (SerializedCanonicalInputs, Option)>, tx_minted: BTreeMap>, current_tx: Option, + // ResolveEquivocation promotion results (operation_catalog + // §"ResolveEquivocation"), computed by the set-level pre-pass in `run`: + // target slot id → (governing resolve id, chosen candidate hash), and + // target slot id → the promoted candidate envelope (from the opset's + // diagnostic candidate store). Pure functions of the slot map — never + // mutated during apply — so, like `system_mints`, they need no transaction + // snapshot. + equivocation_resolutions: BTreeMap, + promoted_singles: BTreeMap, graph: Option, } @@ -390,6 +421,7 @@ struct WorkingSnapshot { structures: BTreeMap>, region_instances: BTreeMap>, instance_voices: BTreeMap>, + instance_staff: BTreeMap, staff_based_regions: BTreeSet, migrated_regions: BTreeSet, region_migrator: BTreeMap, @@ -422,6 +454,25 @@ fn apply_break_lww(breaks: &mut Vec, anchor: &TimeAnchor, present: b } } +/// The 64-byte canonical input preimage of a promoted-voice derivation +/// (`MUSCSVCE`, Chapter 5 §"System-Promoted Voices"): staff_instance ‖ +/// original_voice ‖ winning_op ‖ losing_op, 16 big-endian bytes each — exactly +/// the bytes [`derive_promoted_voice_id`] hashes. The collision check compares +/// these inputs to distinguish two derivations contending for one counter. +fn promoted_voice_inputs( + staff_instance: StaffInstanceId, + original_voice: VoiceId, + winning_op: OperationId, + losing_op: OperationId, +) -> Vec { + let mut inputs = Vec::with_capacity(64); + inputs.extend_from_slice(&staff_instance.canonical_bytes()); + inputs.extend_from_slice(&original_voice.canonical_bytes()); + inputs.extend_from_slice(&winning_op.canonical_bytes()); + inputs.extend_from_slice(&losing_op.canonical_bytes()); + inputs +} + fn intervals_overlap( a_position: &MusicalPosition, a_duration: &MusicalDuration, @@ -445,7 +496,7 @@ fn insert_intervals_overlap(a: &InsertEventOp, b: &InsertEventOp) -> bool { ) } -fn graph_voice_location(score: &Score, voice: VoiceId) -> Option<(usize, usize, usize)> { +pub(crate) fn graph_voice_location(score: &Score, voice: VoiceId) -> Option<(usize, usize, usize)> { for (region_index, region) in score.canvas.regions.iter().enumerate() { for (instance_index, instance) in region.staff_instances().iter().enumerate() { if let Some(voice_index) = instance @@ -488,6 +539,112 @@ fn graph_event_from_insert(op: &InsertEventOp, target_voice: VoiceId) -> Event { event } +// --- Re-anchoring referent support (Chapter 6 §"Total Ordering for Nearest", +// §"The Re-Anchoring Rule Table"). -------------------------------------------- + +/// The tombstoned referent's resolved placement and containment, captured from +/// the graph at the moment [`Reducer::materialize_graph_delete`] removes it — +/// the referent side of the four-key "nearest" ordering and of the range +/// reconstructions in the re-anchoring rule table. +struct ReferentContext { + voice: VoiceId, + region: Option, + position: EventPosition, + duration: EventDuration, +} + +/// Proximity bound "same staff instance" (the rule table's declared maximum for +/// markers and graphic gestures): candidates ranked farther than the referent's +/// staff instance are excluded from "nearest". +const PROXIMITY_SAME_STAFF_INSTANCE: u8 = 1; + +/// Maps an achieved containment-proximity rank (k1 of the "nearest" ordering) +/// to the ratified [`ReanchorReason`] vocabulary. Rank 4 (same canvas) has no +/// ratified reason variant, so a beyond-region survivor is recorded as the +/// explicit fallback rather than appending a new discriminant (see +/// DECISIONS.md — a spec-vocabulary question, batched for Pass 12). +fn reason_for_rank(rank: u8) -> ReanchorReason { + match rank { + 0 => ReanchorReason::SameVoiceNearer, + 1 => ReanchorReason::SameStaffInstanceNearer, + 2 => ReanchorReason::SameStaffNearer, + 3 => ReanchorReason::SameRegionNearer, + _ => ReanchorReason::ExplicitFallback, + } +} + +/// The event references among a set of [`TimeAnchor`]s (the referent-index +/// entries a tombstone must repair). Non-event anchors contribute nothing. +fn anchor_event_refs<'a>(anchors: impl IntoIterator) -> Vec { + anchors + .into_iter() + .filter_map(|anchor| match anchor { + TimeAnchor::Event { id, .. } => Some(TypedObjectId::Event(*id)), + _ => None, + }) + .collect() +} + +/// The event references an annotation anchor carries: its point event, or any +/// event-anchored range endpoints. Region anchors reference no event. +fn annotation_anchor_event_refs(anchor: &AnnotationAnchor) -> Vec { + match anchor { + AnnotationAnchor::Event(event) => vec![TypedObjectId::Event(*event)], + AnnotationAnchor::Range { start, end } => anchor_event_refs([start, end]), + AnnotationAnchor::Region(_) => Vec::new(), + } +} + +/// The event references a gesture anchoring carries. `Free` anchoring follows +/// no score content and so never enters the referent index (table row: "for +/// Free anchoring, no action"). +fn gesture_event_refs(anchoring: &GestureAnchoring) -> Vec { + match anchoring { + GestureAnchoring::Events(events) => { + events.iter().copied().map(TypedObjectId::Event).collect() + } + GestureAnchoring::Range { start, end, .. } => anchor_event_refs([start, end]), + GestureAnchoring::Free => Vec::new(), + } +} + +/// Replaces a range endpoint anchored to the tombstoned event with the +/// containing region's edge — the deterministic "truncate" reading for +/// range-anchored referents (start endpoints move to the region start, end +/// endpoints to the region end; see DECISIONS.md and the proposed Pass-12 row +/// on the underdetermined "truncate" semantics). +fn retarget_dead_endpoint( + endpoint: &mut TimeAnchor, + deleted: EventId, + region: RegionId, + edge: RegionEdge, +) { + if matches!(endpoint, TimeAnchor::Event { id, .. } if *id == deleted) { + *endpoint = TimeAnchor::Region { + id: region, + edge, + offset: AnchorOffset::Zero, + }; + } +} + +/// Degrades an orphaned annotation anchor's dead event references to the +/// containing-region forms, so the orphaned (kept) referent stays +/// reference-clean under invariant 10. The ledger records `Orphaned`; this is +/// anchor hygiene, not a re-anchoring choice. +fn orphan_annotation_anchor(anchor: &mut AnnotationAnchor, deleted: EventId, region: RegionId) { + match anchor { + AnnotationAnchor::Event(event) if *event == deleted => { + *anchor = AnnotationAnchor::Region(region); + } + AnnotationAnchor::Range { start, end } => { + retarget_dead_endpoint(start, deleted, region, RegionEdge::Start); + retarget_dead_endpoint(end, deleted, region, RegionEdge::End); + } + _ => {} + } +} + impl<'a> Reducer<'a> { fn new(op_set: &'a OperationSet) -> Self { Reducer { @@ -510,13 +667,17 @@ impl<'a> Reducer<'a> { structures: BTreeMap::new(), region_instances: BTreeMap::new(), instance_voices: BTreeMap::new(), + instance_staff: BTreeMap::new(), staff_based_regions: BTreeSet::new(), migrated_regions: BTreeSet::new(), region_migrator: BTreeMap::new(), descriptors: BTreeMap::new(), promotion: BTreeMap::new(), + system_mints: BTreeMap::new(), tx_minted: BTreeMap::new(), current_tx: None, + equivocation_resolutions: BTreeMap::new(), + promoted_singles: BTreeMap::new(), graph: None, } } @@ -581,6 +742,7 @@ impl<'a> Reducer<'a> { for instance in region.staff_instances() { self.objects .insert(TypedObjectId::StaffInstance(instance.id), ObjectState::Live); + self.instance_staff.insert(instance.id, instance.staff); let voice_set = self.instance_voices.entry(instance.id).or_default(); for voice in &instance.voices { voice_set.insert(voice.id); @@ -592,6 +754,30 @@ impl<'a> Reducer<'a> { for voice in &instance.voices { self.objects .insert(TypedObjectId::Voice(voice.id), ObjectState::Live); + // Register base system-promoted voices in the mint registry + // so a promotion minted by this reduction is collision-checked + // against them (Chapter 5 §"System-Derived Counter Collisions"). + // Base-internal duplicates keep the first registration: a base + // that already collided is invariant-11/18 territory, not a + // reduction-time mint. + if voice.id.replica() == ReplicaId::SYSTEM_DERIVED { + if let VoiceOrigin::SystemPromoted { + winning_operation, + losing_operation, + original_voice, + } = &voice.origin + { + let inputs = promoted_voice_inputs( + instance.id, + *original_voice, + *winning_operation, + *losing_operation, + ); + self.system_mints + .entry((ObjectKind::Voice, voice.id.counter())) + .or_insert((SerializedCanonicalInputs(inputs), None)); + } + } } } } @@ -607,6 +793,16 @@ impl<'a> Reducer<'a> { pitch_ids.push(pitch.id); self.objects .insert(TypedObjectId::Pitch(pitch.id), ObjectState::Live); + // Register base synthetic pitches in the mint registry (same + // rule as promoted voices above). + if pitch.id.replica() == ReplicaId::SYSTEM_DERIVED { + self.system_mints + .entry((ObjectKind::Pitch, pitch.id.counter())) + .or_insert(( + SerializedCanonicalInputs(canonical_pitch_bytes(&pitch.pitch)), + None, + )); + } } self.event_pitches.insert(event_id, pitch_ids); @@ -618,6 +814,22 @@ impl<'a> Reducer<'a> { .or_default() .push((position.clone(), duration.clone(), event_id)); } + + // A cue event *references* its source events (Chapter 5 §"Cue + // Events"), so it enters the referent index: a source tombstone + // cascade-deletes the cue through the re-anchoring rule table. + if let Event::Cue(cue) = event { + if !cue.source.is_empty() { + self.structures.insert( + TypedObjectId::Event(event_id), + cue.source + .iter() + .copied() + .map(TypedObjectId::Event) + .collect(), + ); + } + } } for slur in &score.cross_cutting.slurs { @@ -684,23 +896,47 @@ impl<'a> Reducer<'a> { .collect(), ); } + // The remaining referent kinds of the re-anchoring rule table enter the + // same index as slurs/ties/beams/spanners, keyed by their typed id and + // listing the event references a tombstone must repair. Non-event + // anchorings (region, measure, wall-clock, free) contribute no entry. for marker in &score.cross_cutting.markers { self.objects .insert(TypedObjectId::Marker(marker.id), ObjectState::Live); + let refs = anchor_event_refs([&marker.anchor]); + if !refs.is_empty() { + self.structures + .insert(TypedObjectId::Marker(marker.id), refs); + } } for annotation in &score.cross_cutting.analytical { self.objects.insert( TypedObjectId::AnalyticalAnnotation(annotation.id), ObjectState::Live, ); + let refs = annotation_anchor_event_refs(&annotation.anchor); + if !refs.is_empty() { + self.structures + .insert(TypedObjectId::AnalyticalAnnotation(annotation.id), refs); + } } for comment in &score.cross_cutting.comments { self.objects .insert(TypedObjectId::Comment(comment.id), ObjectState::Live); + let refs = annotation_anchor_event_refs(&comment.anchor); + if !refs.is_empty() { + self.structures + .insert(TypedObjectId::Comment(comment.id), refs); + } } for gesture in &score.cross_cutting.graphic_gestures { self.objects .insert(TypedObjectId::GraphicGesture(gesture.id), ObjectState::Live); + let refs = gesture_event_refs(&gesture.anchoring); + if !refs.is_empty() { + self.structures + .insert(TypedObjectId::GraphicGesture(gesture.id), refs); + } } for repeat in &score.cross_cutting.repeats { self.objects @@ -718,7 +954,7 @@ impl<'a> Reducer<'a> { fn run(mut self) -> (MaterializedState, Option) { let singles = self.op_set.single_envelopes(); - let equivocated: BTreeSet = + let equivocated_all: BTreeSet = self.op_set.equivocated_ids().into_iter().collect(); // 1. HLC monotonicity: exclude anomalous segments. @@ -731,21 +967,81 @@ impl<'a> Reducer<'a> { first_bad_counter: seg.first_bad_counter, }); } + + // 1b. ResolveEquivocation promotion (operation_catalog + // §"ResolveEquivocation"): a set-level, order-independent pre-pass. + // Among the Single-slot, non-excluded resolves whose `target` is an + // Equivocated slot and whose `chosen` names one of its candidates, the + // resolve earliest in canonical order (smallest reduction tuple — the + // same total HLC order `canonical_reduction_order` selects ready + // operations by) governs. The chosen candidate envelope joins the + // reducible set at its own canonical position — the slot reduces as if + // it had always been Single — and no `OperationSlotEquivocated` + // anomaly is recorded for it. The verdict is a pure function of the + // slot map (never of arrival order), so every replica agrees. A + // resolve that is itself equivocated occupies no Single slot and thus + // never governs; a resolve in a quarantined segment is excluded from + // reduction and likewise never governs. + let mut governing: BTreeMap = BTreeMap::new(); + for &env in &singles { + if excluded.contains(&env.id) { + continue; + } + let OperationPayload::ResolveEquivocation(op) = &env.payload else { + continue; + }; + let Some(slot) = self.op_set.slot(op.target) else { + continue; + }; + if !slot.is_equivocated() || !slot.candidates().any(|c| c == op.chosen) { + continue; + } + governing + .entry(op.target) + .and_modify(|current| { + if env.stamp.reduction_tuple() < current.stamp.reduction_tuple() { + *current = env; + } + }) + .or_insert(env); + } + for (target, resolve) in &governing { + let OperationPayload::ResolveEquivocation(op) = &resolve.payload else { + unreachable!("only ResolveEquivocation envelopes govern a promotion"); + }; + let candidate = self + .op_set + .candidate(op.chosen) + .expect("every candidate hash of an equivocated slot is retained in the store"); + self.promoted_singles.insert(*target, candidate); + self.equivocation_resolutions + .insert(*target, (resolve.id, op.chosen)); + } + // The losing candidates remain only in the opset's diagnostic + // candidate store; a resolved slot records no equivocation anomaly. + let equivocated: BTreeSet = equivocated_all + .into_iter() + .filter(|id| !governing.contains_key(id)) + .collect(); for id in &equivocated { self.record_anomaly(IntegrityAnomalyKind::OperationSlotEquivocated { operation_id: *id, }); } - // 2. Reducible candidates = Single slots minus excluded. + // 2. Reducible candidates = Single slots minus excluded, plus the + // promoted candidates (each at its own canonical position). let reducible: Vec<&OperationEnvelope> = singles .iter() .copied() .filter(|e| !excluded.contains(&e.id)) + .chain(self.promoted_singles.values().copied()) .collect(); let reducible_ids: BTreeSet = reducible.iter().map(|e| e.id).collect(); let declared_transactions: BTreeSet = singles .iter() + .copied() + .chain(self.promoted_singles.values().copied()) .filter_map(|env| match &env.payload { OperationPayload::Primitive(OperationKind::DeclareTransaction(descriptor)) => { Some(descriptor.id) @@ -774,9 +1070,54 @@ impl<'a> Reducer<'a> { // 5. Walk active ops in canonical reduction order; group transactions. let order = canonical_reduction_order(&active); let tx_members = transaction_members(&active); + + // 5a. System-derived counter collision check (Chapter 5 §"System-Derived + // Counter Collisions"): on a collision, reduction does not continue past + // the collision point, and neither colliding input set occupies the + // collided counter. Held operations stay in the (grow-only) operation + // set and surface in `pending` for external recovery. + let mut held: BTreeMap = BTreeMap::new(); + if let Some((halt_index, at, earlier_owner)) = self.detect_system_collision(&order) { + for env in &order[halt_index..] { + held.insert(env.id, PendingReason::HaltedBySystemCollision { at }); + } + if let Some(owner) = earlier_owner { + held.insert(owner, PendingReason::HaltedBySystemCollision { at }); + } + // Transitive closure: a transaction with a held member is wholly + // held (atomicity), and an operation causally covering a held + // operation is held behind it. + loop { + let mut changed = false; + for env in &order { + if held.contains_key(&env.id) { + continue; + } + let tx_blocked = member_transaction(env) + .and_then(|tx| tx_members.get(&tx)) + .and_then(|members| { + members + .iter() + .map(|m| m.id) + .filter(|id| held.contains_key(id)) + .min() + }); + let causal_blocked = + held.keys().copied().find(|h| env.causal_context.covers(*h)); + if let Some(on) = tx_blocked.into_iter().chain(causal_blocked).min() { + held.insert(env.id, PendingReason::DependsOnPending { on }); + changed = true; + } + } + if !changed { + break; + } + } + } + let mut processed: BTreeSet = BTreeSet::new(); for env in &order { - if processed.contains(&env.id) { + if processed.contains(&env.id) || held.contains_key(&env.id) { continue; } if let Some(tx) = member_transaction(env) { @@ -790,7 +1131,8 @@ impl<'a> Reducer<'a> { } } - let mut pending_vec: Vec<(OperationId, PendingReason)> = pending.into_iter().collect(); + let mut pending_vec: Vec<(OperationId, PendingReason)> = + pending.into_iter().chain(held).collect(); pending_vec.sort_by_key(|(id, _)| *id); let graph = self.graph.take(); @@ -813,7 +1155,12 @@ impl<'a> Reducer<'a> { } fn env_of(&self, id: OperationId) -> Option<&'a OperationEnvelope> { - self.op_set.slot(id).and_then(|s| s.single()) + // A slot promoted by a governing ResolveEquivocation reduces as if it + // had always been Single with the chosen candidate. + self.op_set + .slot(id) + .and_then(|s| s.single()) + .or_else(|| self.promoted_singles.get(&id).copied()) } // --- Voice promotion pre-pass (Chapter 6 §6.10 InsertEvent). ------------ @@ -866,6 +1213,107 @@ impl<'a> Reducer<'a> { } } + // --- System-derived counter collision check (Chapter 5 §"System-Derived + // Counter Collisions"). --------------------------------------------------- + + /// The system-derived identifiers an operation would admit into canonical + /// state, each with the canonical inputs of its derivation: the promoted + /// voice assigned by the promotion pre-pass, and any `SYSTEM_DERIVED`- + /// namespace pitch carried by a minting payload (InsertEvent, + /// InsertIdentifiedPitch). Non-minting references to system-derived ids — + /// e.g. a ModifyEvent rewriting a live pitch's content in place — are + /// deliberately not treated as mints (that is Invariant-11 territory, not a + /// derivation collision). + fn prospective_system_mints( + &self, + env: &OperationEnvelope, + ) -> Vec<((ObjectKind, u64), SerializedCanonicalInputs)> { + let mut mints = Vec::new(); + let OperationPayload::Primitive(kind) = &env.payload else { + return mints; + }; + match kind { + OperationKind::InsertEvent(op) => { + if let Some((promoted, winner)) = self.promotion.get(&env.id) { + mints.push(( + (ObjectKind::Voice, promoted.counter()), + SerializedCanonicalInputs(promoted_voice_inputs( + op.staff_instance, + op.voice(), + *winner, + env.id, + )), + )); + } + let mut pitches = Vec::new(); + op.event.collect_identified_pitches(&mut pitches); + for pitch in pitches { + if pitch.id.replica() == ReplicaId::SYSTEM_DERIVED { + mints.push(( + (ObjectKind::Pitch, pitch.id.counter()), + SerializedCanonicalInputs(canonical_pitch_bytes(&pitch.pitch)), + )); + } + } + } + OperationKind::InsertIdentifiedPitch(op) + if op.pitch.id.replica() == ReplicaId::SYSTEM_DERIVED => + { + mints.push(( + (ObjectKind::Pitch, op.pitch.id.counter()), + SerializedCanonicalInputs(canonical_pitch_bytes(&op.pitch.pitch)), + )); + } + _ => {} + } + mints + } + + /// Walks the canonical order checking every prospective system-derived + /// mint against the registry (base-seeded occupants plus earlier mints in + /// the walk). On the first collision — the same `(kind, counter)` claimed + /// by *different* canonical inputs — records the + /// `SystemIdentifierCollision` anomaly and returns the halt point + /// `(index, colliding op, earlier occupant op)`: reduction must not + /// continue past the collision, and neither input set may occupy the + /// collided counter (§"System-Derived Counter Collisions"). The earlier + /// occupant is `None` when it was seeded from the base graph, which cannot + /// be evicted by this reduction and is left to diagnostic recovery. + /// + /// The check is conservative: a claimed mint participates even if the + /// operation would later fail an unrelated apply-time precondition — + /// two input sets contending for one counter is a structural identity + /// failure regardless of which contender ultimately materializes. + fn detect_system_collision( + &mut self, + order: &[&OperationEnvelope], + ) -> Option<(usize, OperationId, Option)> { + for (index, env) in order.iter().enumerate() { + for (key, inputs) in self.prospective_system_mints(env) { + match self.system_mints.get(&key) { + None => { + self.system_mints.insert(key, (inputs, Some(env.id))); + } + Some((existing, _)) if existing.0 == inputs.0 => { + // The same derivation re-observed: not a collision. + } + Some((existing, owner)) => { + let owner = *owner; + let existing = existing.clone(); + self.record_anomaly(IntegrityAnomalyKind::SystemIdentifierCollision { + kind: key.0, + colliding_counter: key.1, + input_set_a: existing, + input_set_b: inputs, + }); + return Some((index, env.id, owner)); + } + } + } + } + None + } + fn graph_insert_precondition( &self, op: &InsertEventOp, @@ -1011,16 +1459,38 @@ impl<'a> Reducer<'a> { } } - fn materialize_graph_delete(&mut self, op: &DeleteEventOp) { + /// Removes the deleted event from the materialized graph and keeps it + /// reference-clean. Returns the repair records for the re-anchoring this + /// performs beyond the bookkeeping rules — the rule-table rows for the + /// graph-only referent kinds (markers, cue events, comments, analytical + /// annotations, graphic gestures) via [`Self::reanchor_event_referents`] — + /// so the triggering operation's effect can record them (Chapter 6 + /// §Re-Anchoring: "Re-anchoring actions MUST be recorded as RepairRecord + /// entries in the triggering operation's effect"). + fn materialize_graph_delete( + &mut self, + env: &OperationEnvelope, + op: &DeleteEventOp, + ) -> Vec { let Some(score) = self.graph.as_mut() else { - return; + return Vec::new(); }; let Some(event) = score.events.remove(op.event) else { - return; + return Vec::new(); }; let voice_id = event.voice(); let location = graph_voice_location(score, voice_id); let region_id = location.map(|(region, _, _)| score.canvas.regions[region].id); + // The referent side of the four-key "nearest" ordering, captured before + // any mutation: the tombstoned event's containment and resolved + // placement (positions are region-relative; exact rational time in + // metric regions). + let referent = ReferentContext { + voice: voice_id, + region: region_id, + position: event.position().clone(), + duration: event.duration().clone(), + }; let removed_event_index = location.and_then(|(region, instance, voice)| { score.canvas.regions[region].staff_instances()[instance].voices[voice] .events @@ -1086,6 +1556,17 @@ impl<'a> Reducer<'a> { .cross_cutting .tuplets .retain(|tuplet| !removed.contains(&tuplet.id)); + // A decomposition component records its tuplet by id; once that tuplet is + // gone the reference would dangle (invariant 6, cross-cutting refs + // resolve), so drop any attachment that names a removed tuplet. The + // member it described is being tombstoned in the same cascade, so the + // decomposition has nothing left to describe. + score.decomposition_attachments.retain(|attachment| { + !attachment + .components + .iter() + .any(|component| component.tuplet.is_some_and(|t| removed.contains(&t))) + }); } TupletCompensation::NotInTuplet | TupletCompensation::RewriteTuplets { .. } => {} } @@ -1182,21 +1663,19 @@ impl<'a> Reducer<'a> { line.events.retain(|event| *event != op.event); !line.events.is_empty() }); - if let Some(region) = region_id { - let fallback = TimeAnchor::Region { - id: region, - edge: RegionEdge::Start, - offset: AnchorOffset::Zero, - }; - for marker in &mut score.cross_cutting.markers { - if matches!(marker.anchor, TimeAnchor::Event { id, .. } if id == op.event) { - marker.anchor = fallback.clone(); - } - } - } + // The remaining rule-table rows — markers, cue events, comments, + // analytical annotations, graphic gestures — are decided and applied + // together (ledger record + graph mutation) once the event is out of + // the graph, so the two can never disagree. + self.reanchor_event_referents(env, op.event, &referent) } - fn materialize_graph_tombstones(&mut self, targets: &[TypedObjectId]) { + fn materialize_graph_tombstones( + &mut self, + env: &OperationEnvelope, + targets: &[TypedObjectId], + ) -> Vec { + let mut repairs = Vec::new(); let events: Vec = targets .iter() .filter_map(|target| match target { @@ -1210,14 +1689,17 @@ impl<'a> Reducer<'a> { } self.voice_occupancy .retain(|_, placements| !placements.is_empty()); - self.materialize_graph_delete(&DeleteEventOp { - event, - tuplet_compensation: TupletCompensation::NotInTuplet, - }); + repairs.extend(self.materialize_graph_delete( + env, + &DeleteEventOp { + event, + tuplet_compensation: TupletCompensation::NotInTuplet, + }, + )); } let Some(score) = self.graph.as_mut() else { - return; + return repairs; }; for target in targets { match target { @@ -1247,6 +1729,7 @@ impl<'a> Reducer<'a> { _ => {} } } + repairs } fn materialize_graph_cross_cutting( @@ -1312,6 +1795,7 @@ impl<'a> Reducer<'a> { }, OperationPayload::ResolveConflict(op) => self.resolve_conflict(env, op), OperationPayload::UndoTransaction(op) => self.undo_transaction(env, op), + OperationPayload::ResolveEquivocation(op) => self.resolve_equivocation(env, op), } } @@ -1502,6 +1986,22 @@ impl<'a> Reducer<'a> { } } }; + // Pitch-id freshness in base-free reduction: a carried pitch id that + // already exists in canonical state (live or tombstoned) is not fresh. + // The graph-aware precondition above already enforces this (with the + // same reason), so this only fires when no graph is present — it keeps + // the two reduction APIs in agreement on the same operation set. + if op + .pitch_ids() + .iter() + .any(|pitch| self.objects.contains_key(&TypedObjectId::Pitch(*pitch))) + { + return OperationEffect::NoOp { + reason: NoOpReason::PreconditionFailedUnderReduction { + reason: PreconditionFailureReason::TargetTombstoned, + }, + }; + } let voice_obj = TypedObjectId::Voice(orig_voice); match self.objects.get(&voice_obj) { Some(ObjectState::Tombstoned { .. }) => { @@ -1620,7 +2120,20 @@ impl<'a> Reducer<'a> { .find(|(_, _, event)| *event == op.event) .map(|(position, duration, _)| (*voice, position.clone(), duration.clone())) }); - self.materialize_graph_delete(op); + // The tombstoned referent's voice, for the containment-proximity key of + // the re-anchoring reasons below: the occupancy index (base-free) with + // the graph as fallback for non-metric events. Captured before the + // graph delete removes the event. + let referent_voice = deleted_placement + .as_ref() + .map(|(voice, _, _)| *voice) + .or_else(|| { + self.graph + .as_ref() + .and_then(|score| score.events.get(op.event)) + .map(Event::voice) + }); + let graph_repairs = self.materialize_graph_delete(env, op); let minter = self.minted_by.get(&ev_obj).copied().unwrap_or(env.id); self.objects.insert( @@ -1634,7 +2147,7 @@ impl<'a> Reducer<'a> { events.retain(|(_, _, event)| *event != op.event); } self.voice_occupancy.retain(|_, events| !events.is_empty()); - let mut repairs = Vec::new(); + let mut repairs = graph_repairs; // Tombstone contained pitches. if let Some(pitches) = self.event_pitches.get(&op.event).cloned() { @@ -1713,7 +2226,7 @@ impl<'a> Reducer<'a> { } // Re-anchor cross-cutting structures referencing the tombstoned event. - self.reanchor_for_tombstone(env, ev_obj, &mut repairs); + self.reanchor_for_tombstone(env, ev_obj, &mut repairs, referent_voice); if repairs.is_empty() { OperationEffect::Applied @@ -2138,6 +2651,8 @@ impl<'a> Reducer<'a> { .or_default() .insert(op.instance_id()); self.instance_voices.entry(op.instance_id()).or_default(); + self.instance_staff + .insert(op.instance_id(), op.instance.staff); OperationEffect::Applied } @@ -2524,20 +3039,26 @@ impl<'a> Reducer<'a> { } OperationEffect::Applied } - Some(RS::Resolved { action, .. }) => { + Some(RS::Resolved { by, action }) => { if action == op.action { OperationEffect::NoOp { reason: NoOpReason::AlreadyApplied, } } else { - // Differing concurrent resolution → meta-conflict. + // Differing concurrent resolution → meta-conflict. The + // earlier resolve stands (its action materialized), so it + // is the record's winner; this op is the loser, and both + // resolvers are named as causes ("at least two for a true + // conflict", Chapter 6 §Conflict Records). A conflict + // record has no TypedObjectId, so `affected_objects` + // cannot name the contested conflict and stays empty. let conflict = ConflictRecord::new( ConflictKind::StructuralFieldCollision { - winner: env.id, + winner: by, loser: env.id, field: FieldPath("conflict_resolution".to_string()), }, - vec![env.id], + vec![by, env.id], vec![], ); let cid = conflict.id; @@ -2551,6 +3072,73 @@ impl<'a> Reducer<'a> { } } + /// The recorded effect of a `ResolveEquivocation` (operation_catalog + /// §"ResolveEquivocation"). The slot promotion itself happened in the + /// set-level pre-pass ([`Reducer::run`] step 1b); this only records the + /// per-resolve verdict, mirroring [`Reducer::resolve_conflict`]'s + /// discipline: the governing (earliest-in-canonical-order) resolve is + /// `Applied`; a later resolve naming the same candidate reduces + /// idempotently; a later valid resolve naming a differing candidate is a + /// `StructuralFieldCollision` meta-conflict on `equivocation_resolution`. + /// A resolve whose target is not an equivocated slot, or whose chosen is + /// not among the slot's candidates, is a precondition no-op + /// (`TargetMissing` — the named target/candidate pair does not exist). + fn resolve_equivocation( + &mut self, + env: &OperationEnvelope, + op: &crate::payload::ResolveEquivocationPayload, + ) -> OperationEffect { + let precondition_noop = OperationEffect::NoOp { + reason: NoOpReason::PreconditionFailedUnderReduction { + reason: PreconditionFailureReason::TargetMissing, + }, + }; + match self.equivocation_resolutions.get(&op.target) { + // No governing resolve exists for the target: it is absent, holds + // a Single slot, or is equivocated with no valid resolve — in + // every case this resolve's precondition ("an Equivocated slot for + // `target` with `chosen` among its candidates") failed, or it + // would have governed. + None => precondition_noop, + Some((winner, chosen)) => { + if env.id == *winner { + OperationEffect::Applied + } else if op.chosen == *chosen { + // A later resolve naming the same candidate: idempotent. + OperationEffect::NoOp { + reason: NoOpReason::AlreadyApplied, + } + } else if !self + .op_set + .slot(op.target) + .is_some_and(|slot| slot.candidates().any(|c| c == op.chosen)) + { + // A differing `chosen` that never named a real candidate + // is a failed precondition, not a contested resolution. + precondition_noop + } else { + // Two valid resolves naming differing candidates: the + // governing (earlier) resolve stands as the record's + // winner; this op is the loser, both named as causes. A + // slot is not a TypedObjectId, so `affected_objects` + // stays empty (the ResolveConflict discipline). + let conflict = ConflictRecord::new( + ConflictKind::StructuralFieldCollision { + winner: *winner, + loser: env.id, + field: FieldPath("equivocation_resolution".to_string()), + }, + vec![*winner, env.id], + vec![], + ); + let cid = conflict.id; + self.conflicts.insert(conflict); + OperationEffect::Conflicted { conflict: cid } + } + } + } + } + fn undo_transaction( &mut self, env: &OperationEnvelope, @@ -2585,7 +3173,7 @@ impl<'a> Reducer<'a> { target: *t, }); } - self.materialize_graph_tombstones(&targets); + repairs.extend(self.materialize_graph_tombstones(env, &targets)); OperationEffect::AppliedWithRepair { repairs } } else { // A target was already tombstoned/modified: strict undo conflicts. @@ -2627,7 +3215,7 @@ impl<'a> Reducer<'a> { tombstoned.push(*t); } } - self.materialize_graph_tombstones(&tombstoned); + repairs.extend(self.materialize_graph_tombstones(env, &tombstoned)); OperationEffect::AppliedWithRepair { repairs } } } @@ -2815,28 +3403,45 @@ impl<'a> Reducer<'a> { } fn transpose(&mut self, _env: &OperationEnvelope, op: &TransposeOp) -> OperationEffect { - // Precondition: every target pitch is live. Transpose is order-dependent - // (transpositions do not commute); its canonical footprint is the - // effect-log entry. The transposed values are materialized in the graph. - for pitch in &op.targets { - match self.objects.get(&TypedObjectId::Pitch(*pitch)) { - Some(ObjectState::Live) => {} - Some(ObjectState::Tombstoned { .. }) => { - return OperationEffect::NoOp { - reason: NoOpReason::TargetTombstoned, - } - } - None => { - return OperationEffect::NoOp { - reason: NoOpReason::PreconditionFailedUnderReduction { - reason: PreconditionFailureReason::TargetMissing, - }, - } - } - } + // Precondition: a target that never entered canonical state is a + // dangling reference — the whole operation refuses. Tombstoned targets + // are *skipped* per the catalog's re-anchoring rule ("the transpose + // applies only to live pitches", Operation Catalog §Transpose); the + // shift still applies to the remaining live targets. Transpose is + // order-dependent (transpositions do not commute); its canonical + // footprint is the effect-log entry. The transposed values are + // materialized in the graph. + if op + .targets + .iter() + .any(|pitch| !self.objects.contains_key(&TypedObjectId::Pitch(*pitch))) + { + return OperationEffect::NoOp { + reason: NoOpReason::PreconditionFailedUnderReduction { + reason: PreconditionFailureReason::TargetMissing, + }, + }; } - for pitch in &op.targets { - self.graph_transpose_pitch(*pitch, op.chromatic_steps); + let live: Vec = op + .targets + .iter() + .copied() + .filter(|pitch| { + matches!( + self.objects.get(&TypedObjectId::Pitch(*pitch)), + Some(ObjectState::Live) + ) + }) + .collect(); + if live.is_empty() { + // Every target was tombstoned by a causally-prior delete: the + // skip-all case degenerates to no effect. + return OperationEffect::NoOp { + reason: NoOpReason::TargetTombstoned, + }; + } + for pitch in live { + self.graph_transpose_pitch(pitch, op.chromatic_steps); } OperationEffect::Applied } @@ -3149,6 +3754,7 @@ impl<'a> Reducer<'a> { env: &OperationEnvelope, tombstoned: TypedObjectId, repairs: &mut Vec, + referent_voice: Option, ) { // Find structures referencing the tombstoned object. let referencing: Vec = self @@ -3163,13 +3769,18 @@ impl<'a> Reducer<'a> { // A tie's existence requires both endpoints: cascade-delete. self.cascade_structure(env, sid, repairs); } - TypedObjectId::Comment(_) | TypedObjectId::AnalyticalAnnotation(_) => { - // User content is never silently deleted: orphan. - repairs.push(RepairRecord { - kind: RepairKind::Orphaned, - target: sid, - }); - } + // The graph-only referent kinds — markers, cue events, + // comments, analytical annotations, graphic gestures — are + // repaired where their graph mutation happens + // (`reanchor_event_referents`, run from + // `materialize_graph_delete`), so the ledger record and the + // graph always agree. They only exist under graph-aware + // reduction (none is creatable by an operation). + TypedObjectId::Marker(_) + | TypedObjectId::Comment(_) + | TypedObjectId::AnalyticalAnnotation(_) + | TypedObjectId::GraphicGesture(_) + | TypedObjectId::Event(_) => {} TypedObjectId::Beam(_) => { let survivors = self.surviving_endpoints(sid, tombstoned); if survivors < 2 { @@ -3188,11 +3799,29 @@ impl<'a> Reducer<'a> { if survivors < 1 { self.cascade_structure(env, sid, repairs); } else if let Some(to) = self.nearest_survivor(sid, tombstoned) { + // The survivor is fixed (the structure's other + // endpoint — surviving-endpoint collapse per the rule + // table), so only the containment key applies: the + // reason names the survivor's actual proximity rank to + // the tombstoned endpoint rather than a hardcoded + // same-voice claim. + let survivor_voice = match to { + TypedObjectId::Event(event) => self.event_voice(event), + _ => None, + }; + let reason = match (referent_voice, survivor_voice) { + (Some(referent), Some(survivor)) => { + reason_for_rank(self.containment_rank(referent, survivor)) + } + // No indexed placement for either side (a + // non-metric endpoint): the pre-four-key default. + _ => ReanchorReason::SameVoiceNearer, + }; repairs.push(RepairRecord { kind: RepairKind::Reanchored { from: tombstoned, to, - reason: ReanchorReason::SameVoiceNearer, + reason, }, target: sid, }); @@ -3249,9 +3878,13 @@ impl<'a> Reducer<'a> { sid: TypedObjectId, just_tombstoned: TypedObjectId, ) -> Option { - // Deterministic "nearest" stand-in: the lexicographically-smallest - // surviving endpoint (the spec's full proximity ordering needs resolved - // positions; see DECISIONS.md). + // For slurs/spanners the rule table prescribes surviving-endpoint + // collapse, so the candidate set is the structure's own endpoints; the + // lexicographically-smallest survivor realizes the id tie-break (a + // two-endpoint structure has exactly one). Proximity-aware re-targeting + // beyond the endpoints stays a deferred refinement (the table says so + // explicitly); the open-candidate four-key ordering lives in + // `nearest_live_event`. self.structures.get(&sid).and_then(|eps| { eps.iter() .filter(|e| { @@ -3263,6 +3896,594 @@ impl<'a> Reducer<'a> { }) } + // --- The four-key "nearest" ordering (Chapter 6 §"Total Ordering for + // Nearest") and the graph-only rule-table rows. --------------------------- + + /// The staff instance a voice lives in, from the base-free ledger index. + fn voice_instance(&self, voice: VoiceId) -> Option { + self.instance_voices + .iter() + .find_map(|(instance, voices)| voices.contains(&voice).then_some(*instance)) + } + + /// The region a staff instance lives in, from the base-free ledger index. + fn instance_region_of(&self, instance: StaffInstanceId) -> Option { + self.region_instances + .iter() + .find_map(|(region, instances)| instances.contains(&instance).then_some(*region)) + } + + /// The voice of a live event with an indexed metric placement. + fn event_voice(&self, event: EventId) -> Option { + self.voice_occupancy.iter().find_map(|(voice, placements)| { + placements + .iter() + .any(|(_, _, placed)| *placed == event) + .then_some(*voice) + }) + } + + /// Containment proximity (key 1 of the "nearest" ordering): same voice 0, + /// same staff instance 1, same staff 2, same region 3, same canvas 4. + /// Computed from the base-free ledger indices, so `reduce()` and + /// `reduce_onto()` rank identically wherever both represent the scenario. + fn containment_rank(&self, referent_voice: VoiceId, candidate_voice: VoiceId) -> u8 { + if referent_voice == candidate_voice { + return 0; + } + let (Some(referent), Some(candidate)) = ( + self.voice_instance(referent_voice), + self.voice_instance(candidate_voice), + ) else { + return 4; + }; + if referent == candidate { + return 1; + } + if let (Some(a), Some(b)) = ( + self.instance_staff.get(&referent), + self.instance_staff.get(&candidate), + ) { + if a == b { + return 2; + } + } + if let (Some(a), Some(b)) = ( + self.instance_region_of(referent), + self.instance_region_of(candidate), + ) { + if a == b { + return 3; + } + } + 4 + } + + /// The nearest surviving live event to the tombstoned referent under the + /// four-key total order (Chapter 6 §"Total Ordering for Nearest"): the + /// strict lexicographic minimum of (containment proximity, absolute time + /// distance from the referent's resolved position, forward before + /// backward, typed id bytes ascending — an `EventId`'s numeric order *is* + /// its canonical 16-byte order). Candidates ranked farther than `max_rank` + /// are excluded. Read entirely from the canonical ledger indices, so the + /// choice is a function of canonical state (permutation-invariant). Only + /// *metric* placements are indexed; wall-clock distance (proportional + /// regions) is a deferred refinement, so a wall-clock referent finds no + /// candidate and falls to the kind's declared failure action. + fn nearest_live_event( + &self, + referent: &ReferentContext, + exclude: EventId, + max_rank: u8, + ) -> Option<(EventId, u8)> { + let EventPosition::Musical(referent_position) = &referent.position else { + return None; + }; + let mut best: Option<(u8, RationalTime, u8, EventId)> = None; + for (voice, placements) in &self.voice_occupancy { + let rank = self.containment_rank(referent.voice, *voice); + if rank > max_rank { + continue; + } + for (position, _, event) in placements { + if *event == exclude + || !matches!( + self.objects.get(&TypedObjectId::Event(*event)), + Some(ObjectState::Live) + ) + { + continue; + } + let signed = position.0.sub(&referent_position.0); + let (direction, distance) = if signed.is_negative() { + (1u8, RationalTime::zero().sub(&signed)) + } else { + (0u8, signed) + }; + let key = (rank, distance, direction, *event); + if best.as_ref().map_or(true, |current| key < *current) { + best = Some(key); + } + } + } + best.map(|(rank, _, _, event)| (event, rank)) + } + + /// Drops `dead` from `sid`'s referent-index entry, removing the entry when + /// no event reference remains. + fn drop_structure_ref(&mut self, sid: TypedObjectId, dead: TypedObjectId) { + if let Some(refs) = self.structures.get_mut(&sid) { + refs.retain(|existing| *existing != dead); + if refs.is_empty() { + self.structures.remove(&sid); + } + } + } + + /// The rule-table rows for the graph-only referent kinds — markers, cue + /// events, comments, analytical annotations, graphic gestures (Chapter 6 + /// §"The Re-Anchoring Rule Table"). Runs from + /// [`Self::materialize_graph_delete`], so both the DeleteEvent path and the + /// undo path record the same repairs in the triggering operation's effect. + /// Each row's ledger record and graph mutation are decided together, in + /// canonical id order ("the graph follows the ledger"). + fn reanchor_event_referents( + &mut self, + env: &OperationEnvelope, + deleted: EventId, + referent: &ReferentContext, + ) -> Vec { + let mut repairs = Vec::new(); + let deleted_obj = TypedObjectId::Event(deleted); + // The deleted event's own referent entry (a cue's source list) dies + // with it. + self.structures.remove(&deleted_obj); + let referencing: Vec = self + .structures + .iter() + .filter(|(sid, refs)| { + matches!( + sid, + TypedObjectId::Marker(_) + | TypedObjectId::Comment(_) + | TypedObjectId::AnalyticalAnnotation(_) + | TypedObjectId::GraphicGesture(_) + | TypedObjectId::Event(_) + ) && refs.contains(&deleted_obj) + && matches!(self.objects.get(sid), Some(ObjectState::Live)) + }) + .map(|(sid, _)| *sid) + .collect(); + for sid in referencing { + match sid { + TypedObjectId::Marker(_) => { + self.reanchor_marker(deleted, referent, sid, &mut repairs) + } + TypedObjectId::Event(cue) => self.cascade_cue(env, cue, &mut repairs), + TypedObjectId::Comment(_) => { + self.orphan_comment(deleted, referent, sid, &mut repairs) + } + TypedObjectId::AnalyticalAnnotation(_) => { + self.reanchor_annotation(deleted, referent, sid, &mut repairs) + } + TypedObjectId::GraphicGesture(_) => { + self.reanchor_gesture(deleted, referent, sid, &mut repairs) + } + _ => {} + } + } + repairs + } + + /// Row "Marker / Anchor": re-anchor to the nearest event in the same staff + /// instance (proximity max: same staff instance); orphan on failure. + fn reanchor_marker( + &mut self, + deleted: EventId, + referent: &ReferentContext, + sid: TypedObjectId, + repairs: &mut Vec, + ) { + let TypedObjectId::Marker(marker) = sid else { + return; + }; + match self.nearest_live_event(referent, deleted, PROXIMITY_SAME_STAFF_INSTANCE) { + Some((to, rank)) => { + if let Some(score) = self.graph.as_mut() { + if let Some(value) = score + .cross_cutting + .markers + .iter_mut() + .find(|value| value.id == marker) + { + if let TimeAnchor::Event { id, .. } = &mut value.anchor { + if *id == deleted { + // The anchor offset is preserved: the survivor + // shares the staff instance, hence the region + // and its offset discipline (invariant 9). + *id = to; + } + } + } + } + self.structures.insert(sid, vec![TypedObjectId::Event(to)]); + repairs.push(RepairRecord { + kind: RepairKind::Reanchored { + from: TypedObjectId::Event(deleted), + to: TypedObjectId::Event(to), + reason: reason_for_rank(rank), + }, + target: sid, + }); + } + None => { + // Orphan: the marker (user content) is kept. Invariant 10 + // rejects a dangling event anchor, so the graph anchor degrades + // to the containing region's start — anchor hygiene, not a + // re-anchoring choice; the ledger records the orphaning. + if let Some(region) = referent.region { + if let Some(score) = self.graph.as_mut() { + if let Some(value) = score + .cross_cutting + .markers + .iter_mut() + .find(|value| value.id == marker) + { + if matches!(value.anchor, TimeAnchor::Event { id, .. } if id == deleted) + { + value.anchor = TimeAnchor::Region { + id: region, + edge: RegionEdge::Start, + offset: AnchorOffset::Zero, + }; + } + } + } + } + self.structures.remove(&sid); + repairs.push(RepairRecord { + kind: RepairKind::Orphaned, + target: sid, + }); + } + } + } + + /// Row "Cue event / Source event": cascade-delete — the plain normative + /// action, on *any* source deletion (the multi-source rationale tension is + /// a proposed Pass-12 row). The cascaded cue is itself a tombstoned event, + /// so the full re-anchoring pass — the graph-only rows via the recursive + /// `materialize_graph_delete`, and the tie/beam/slur/spanner ledger arm via + /// `reanchor_for_tombstone` — runs over its own referents transitively, in + /// the same reduction step. + fn cascade_cue( + &mut self, + env: &OperationEnvelope, + cue: EventId, + repairs: &mut Vec, + ) { + let sid = TypedObjectId::Event(cue); + // A cue this pass already cascaded transitively (a cue-of-a-cue chain + // reaching back into the referencing list) must not double-record. + if !matches!(self.objects.get(&sid), Some(ObjectState::Live)) { + return; + } + let cue_voice = self.event_voice(cue); + self.cascade_structure(env, sid, repairs); + self.structures.remove(&sid); + for events in self.voice_occupancy.values_mut() { + events.retain(|(_, _, event)| *event != cue); + } + self.voice_occupancy.retain(|_, events| !events.is_empty()); + self.event_pitches.remove(&cue); + let cue_delete = DeleteEventOp { + event: cue, + tuplet_compensation: TupletCompensation::NotInTuplet, + }; + repairs.extend(self.materialize_graph_delete(env, &cue_delete)); + self.reanchor_for_tombstone(env, sid, repairs, cue_voice); + } + + /// Row "Comment / Anchor": orphan — user content is never silently + /// deleted. The comment stays live in ledger and graph; its dangling + /// anchor references degrade to the containing-region forms so invariant + /// 10 keeps holding. + fn orphan_comment( + &mut self, + deleted: EventId, + referent: &ReferentContext, + sid: TypedObjectId, + repairs: &mut Vec, + ) { + let TypedObjectId::Comment(comment) = sid else { + return; + }; + if let Some(region) = referent.region { + if let Some(score) = self.graph.as_mut() { + if let Some(value) = score + .cross_cutting + .comments + .iter_mut() + .find(|value| value.id == comment) + { + orphan_annotation_anchor(&mut value.anchor, deleted, region); + } + } + } + self.drop_structure_ref(sid, TypedObjectId::Event(deleted)); + repairs.push(RepairRecord { + kind: RepairKind::Orphaned, + target: sid, + }); + } + + /// Row "Analytical annotation / Anchor": re-anchor to a time range + /// preserving the original extent; orphan when the range cannot be + /// reconstructed. Reconstruction needs the containing region plus an exact + /// musical placement — the range endpoints become region-start offsets, so + /// they resolve to the deleted event's exact span. A wall-clock or + /// indeterminate span is not expressible as a stored region-relative range + /// (the expressibility gap is a proposed Pass-12 row), so it orphans. + fn reanchor_annotation( + &mut self, + deleted: EventId, + referent: &ReferentContext, + sid: TypedObjectId, + repairs: &mut Vec, + ) { + let TypedObjectId::AnalyticalAnnotation(annotation) = sid else { + return; + }; + let deleted_obj = TypedObjectId::Event(deleted); + let current = self.graph.as_ref().and_then(|score| { + score + .cross_cutting + .analytical + .iter() + .find(|value| value.id == annotation) + .map(|value| value.anchor.clone()) + }); + let Some(current) = current else { + self.drop_structure_ref(sid, deleted_obj); + return; + }; + // A stale index entry (the anchor no longer references the deleted + // event) drops the reference with no repair. + if !annotation_anchor_event_refs(¤t).contains(&deleted_obj) { + self.drop_structure_ref(sid, deleted_obj); + return; + } + let musical_span = match (&referent.position, &referent.duration) { + (EventPosition::Musical(position), EventDuration::Musical(duration)) => { + Some((position.0.clone(), duration.0.clone())) + } + _ => None, + }; + let range_point = |resolved: RationalTime, region: RegionId| TimeAnchor::Region { + id: region, + edge: RegionEdge::Start, + offset: AnchorOffset::Musical(MusicalDuration(resolved)), + }; + let reconstructed: Option = match ¤t { + AnnotationAnchor::Event(event) if *event == deleted => { + match (musical_span.as_ref(), referent.region) { + (Some((position, duration)), Some(region)) => Some(AnnotationAnchor::Range { + start: range_point(position.clone(), region), + end: range_point(position.add(duration), region), + }), + _ => None, + } + } + AnnotationAnchor::Range { start, end } => { + // Per endpoint: an event-anchored endpoint of the deleted event + // is rebuilt at its resolved position (the event's position + // plus any musical anchor offset); live endpoints are kept. + let rebuild = |endpoint: &TimeAnchor| -> Option { + match endpoint { + TimeAnchor::Event { id, offset } if *id == deleted => { + let (position, _) = musical_span.as_ref()?; + let region = referent.region?; + let resolved = match offset { + AnchorOffset::Zero => position.clone(), + AnchorOffset::Musical(delta) => position.add(&delta.0), + AnchorOffset::WallClock(_) => return None, + }; + Some(range_point(resolved, region)) + } + other => Some(other.clone()), + } + }; + match (rebuild(start), rebuild(end)) { + (Some(start), Some(end)) => Some(AnnotationAnchor::Range { start, end }), + _ => None, + } + } + // Stale index entry (the anchor no longer references the deleted + // event): drop the reference, no repair. + _ => { + self.drop_structure_ref(sid, deleted_obj); + return; + } + }; + match reconstructed { + Some(anchor) => { + let region = referent + .region + .expect("range reconstruction required the containing region"); + if let Some(score) = self.graph.as_mut() { + if let Some(value) = score + .cross_cutting + .analytical + .iter_mut() + .find(|value| value.id == annotation) + { + value.anchor = anchor; + } + } + self.drop_structure_ref(sid, deleted_obj); + repairs.push(RepairRecord { + kind: RepairKind::Reanchored { + from: deleted_obj, + to: TypedObjectId::Region(region), + reason: ReanchorReason::ExplicitFallback, + }, + target: sid, + }); + } + None => { + if let Some(region) = referent.region { + if let Some(score) = self.graph.as_mut() { + if let Some(value) = score + .cross_cutting + .analytical + .iter_mut() + .find(|value| value.id == annotation) + { + orphan_annotation_anchor(&mut value.anchor, deleted, region); + } + } + } + self.drop_structure_ref(sid, deleted_obj); + repairs.push(RepairRecord { + kind: RepairKind::Orphaned, + target: sid, + }); + } + } + } + + /// Row "Graphic gesture / Anchor event": re-anchor each deleted event + /// reference to the nearest surviving event of the same staff instance + /// (proximity max: same staff instance); with no candidate the reference is + /// dropped — truncation while references remain, orphaning when the list + /// empties. Range anchoring truncates (dead endpoints move to the region + /// edges); Free anchoring is never indexed. + fn reanchor_gesture( + &mut self, + deleted: EventId, + referent: &ReferentContext, + sid: TypedObjectId, + repairs: &mut Vec, + ) { + let TypedObjectId::GraphicGesture(gesture) = sid else { + return; + }; + let deleted_obj = TypedObjectId::Event(deleted); + let current = self.graph.as_ref().and_then(|score| { + score + .cross_cutting + .graphic_gestures + .iter() + .find(|value| value.id == gesture) + .map(|value| value.anchoring.clone()) + }); + let Some(anchoring) = current else { + self.drop_structure_ref(sid, deleted_obj); + return; + }; + let set_anchoring = |reducer: &mut Self, anchoring: GestureAnchoring| { + if let Some(score) = reducer.graph.as_mut() { + if let Some(value) = score + .cross_cutting + .graphic_gestures + .iter_mut() + .find(|value| value.id == gesture) + { + value.anchoring = anchoring; + } + } + }; + match anchoring { + GestureAnchoring::Events(events) => { + if !events.contains(&deleted) { + self.drop_structure_ref(sid, deleted_obj); + return; + } + match self.nearest_live_event(referent, deleted, PROXIMITY_SAME_STAFF_INSTANCE) { + Some((to, rank)) => { + let retargeted: Vec = events + .iter() + .map(|event| if *event == deleted { to } else { *event }) + .collect(); + self.structures.insert( + sid, + retargeted + .iter() + .copied() + .map(TypedObjectId::Event) + .collect(), + ); + set_anchoring(self, GestureAnchoring::Events(retargeted)); + repairs.push(RepairRecord { + kind: RepairKind::Reanchored { + from: deleted_obj, + to: TypedObjectId::Event(to), + reason: reason_for_rank(rank), + }, + target: sid, + }); + } + None => { + let remaining: Vec = events + .iter() + .copied() + .filter(|event| *event != deleted) + .collect(); + let emptied = remaining.is_empty(); + if emptied { + self.structures.remove(&sid); + } else { + self.structures.insert( + sid, + remaining + .iter() + .copied() + .map(TypedObjectId::Event) + .collect(), + ); + } + set_anchoring(self, GestureAnchoring::Events(remaining)); + repairs.push(RepairRecord { + kind: if emptied { + // The reference list emptied: the gesture (user + // content) is kept, reference-free. + RepairKind::Orphaned + } else { + RepairKind::SpannerTruncated { + removed_members: vec![deleted_obj], + } + }, + target: sid, + }); + } + } + } + GestureAnchoring::Range { start, end, staves } => { + let Some(region) = referent.region else { + self.drop_structure_ref(sid, deleted_obj); + return; + }; + let mut start = start; + let mut end = end; + retarget_dead_endpoint(&mut start, deleted, region, RegionEdge::Start); + retarget_dead_endpoint(&mut end, deleted, region, RegionEdge::End); + set_anchoring(self, GestureAnchoring::Range { start, end, staves }); + self.drop_structure_ref(sid, deleted_obj); + repairs.push(RepairRecord { + kind: RepairKind::Reanchored { + from: deleted_obj, + to: TypedObjectId::Region(region), + reason: ReanchorReason::ExplicitFallback, + }, + target: sid, + }); + } + GestureAnchoring::Free => { + self.drop_structure_ref(sid, deleted_obj); + } + } + } + // --- Transactions (Chapter 6 §6.6). ------------------------------------- fn reduce_transaction_block(&mut self, tx: TransactionId, members: &[&'a OperationEnvelope]) { @@ -3375,6 +4596,7 @@ impl<'a> Reducer<'a> { structures: self.structures.clone(), region_instances: self.region_instances.clone(), instance_voices: self.instance_voices.clone(), + instance_staff: self.instance_staff.clone(), staff_based_regions: self.staff_based_regions.clone(), migrated_regions: self.migrated_regions.clone(), region_migrator: self.region_migrator.clone(), @@ -3401,6 +4623,7 @@ impl<'a> Reducer<'a> { self.structures = s.structures; self.region_instances = s.region_instances; self.instance_voices = s.instance_voices; + self.instance_staff = s.instance_staff; self.staff_based_regions = s.staff_based_regions; self.migrated_regions = s.migrated_regions; self.region_migrator = s.region_migrator; @@ -4253,4 +5476,882 @@ mod tests { ConflictKind::StructuralFieldCollision { .. } )); } + + // --- Push-1 spec-compliance fixes (Transpose skip, meta-conflict record, + // marker re-anchor repair, system-derived counter collisions). ----------- + + /// An InsertEvent envelope whose event carries exactly one identified + /// pitch with the given id and intrinsic content. + #[allow(clippy::too_many_arguments)] + fn insert_with_pitch_content( + replica: u64, + counter: u64, + physical: i64, + voice: u64, + event: u64, + pos_units: i64, + pitch_id: PitchId, + content: &Pitch, + ) -> OperationEnvelope { + let mut env = insert(replica, counter, physical, voice, event, pos_units); + if let OperationPayload::Primitive(OperationKind::InsertEvent(ref mut op)) = env.payload { + op.event = crate::valuegen::insert_event_value( + op.event_id(), + op.voice(), + pos(pos_units), + epiphany_core::MusicalDuration::whole(), + &[pitch_id], + ); + if let Event::Pitched(pe) = &mut op.event { + pe.pitches[0].pitch = content.clone(); + } + } + env + } + + #[test] + fn transpose_skips_tombstoned_targets_and_shifts_the_live_ones() { + // Operation Catalog §Transpose (re-anchoring): "Tombstoned targets are + // skipped (the transpose applies only to live pitches)." + let p1 = PitchId::new(ReplicaId(9), 501); + let p2 = PitchId::new(ReplicaId(9), 502); + let neutral = crate::valuegen::pitch_value(); + let a = insert_with_pitch_content(1, 0, 10, 1, 100, 0, p1, &neutral); + let b = insert_with_pitch_content(1, 1, 11, 2, 101, 0, p2, &neutral); + let del = prim_env( + 1, + 2, + 20, + CausalContext::new().with_seen(ReplicaId(1), 1), + OperationKind::DeleteEvent(DeleteEventOp { + event: EventId::new(ReplicaId(1), 100), + tuplet_compensation: TupletCompensation::NotInTuplet, + }), + ); + let after_delete = CausalContext::new().with_seen(ReplicaId(1), 2); + // Mixed live/tombstoned targets: skips p1, shifts p2, applies. + let t_mixed = prim_env( + 3, + 0, + 30, + after_delete.clone(), + OperationKind::Transpose(TransposeOp { + targets: vec![p1, p2], + chromatic_steps: 2, + }), + ); + // All targets tombstoned: degenerates to no effect. + let t_dead = prim_env( + 4, + 0, + 31, + after_delete.clone(), + OperationKind::Transpose(TransposeOp { + targets: vec![p1], + chromatic_steps: 2, + }), + ); + // A target that never existed: dangling reference, whole op refuses. + let t_missing = prim_env( + 5, + 0, + 32, + after_delete, + OperationKind::Transpose(TransposeOp { + targets: vec![p2, PitchId::new(ReplicaId(9), 999)], + chromatic_steps: 2, + }), + ); + let mut set = OperationSet::new(); + set.accept_all(vec![ + a, + b, + del, + t_mixed.clone(), + t_dead.clone(), + t_missing.clone(), + ]); + let state = set.reduce(); + let effect = |id: OperationId| { + state + .effects + .iter() + .find(|(e, _)| *e == id) + .map(|(_, eff)| eff) + .expect("effect recorded") + }; + assert_eq!(effect(t_mixed.id), &OperationEffect::Applied); + assert_eq!( + effect(t_dead.id), + &OperationEffect::NoOp { + reason: NoOpReason::TargetTombstoned, + } + ); + assert_eq!( + effect(t_missing.id), + &OperationEffect::NoOp { + reason: NoOpReason::PreconditionFailedUnderReduction { + reason: PreconditionFailureReason::TargetMissing, + }, + } + ); + } + + #[test] + fn differing_concurrent_resolves_name_both_resolvers_in_the_meta_conflict() { + // Chapter 6 §Conflict Resolution Operations: a later differing resolve + // reduces to Conflicted with a meta-conflict record; the record names + // the earlier resolver (whose action stands) as winner and both + // resolvers as causes. + use crate::conflict::ResolutionAction; + use crate::payload::{ResolveConflictPayload, RespellPitchOp}; + + let pitch = PitchId::new(ReplicaId(9), 500); + let mut insert_env = insert(1, 0, 10, 1, 100, 0); + if let OperationPayload::Primitive(OperationKind::InsertEvent(ref mut op)) = + insert_env.payload + { + op.event = crate::valuegen::insert_event_value( + op.event_id(), + op.voice(), + op.musical_position(), + op.musical_duration(), + &[pitch], + ); + } + let respell = |replica: u64, physical: i64, byte: u8| { + prim_env( + replica, + 0, + physical, + CausalContext::new().with_seen(ReplicaId(1), 0), + OperationKind::RespellPitch(RespellPitchOp { + pitch, + spelling: crate::valuegen::spelling(byte), + }), + ) + }; + let respell_a = respell(2, 20, 0xAA); + let respell_b = respell(3, 21, 0xBB); + let mut set = OperationSet::new(); + set.accept_all(vec![ + insert_env.clone(), + respell_a.clone(), + respell_b.clone(), + ]); + let cid = set.reduce().conflicts.records()[0].id; + + let resolve = |replica: u64, physical: i64, action: ResolutionAction| { + let id = OperationId::new(ReplicaId(replica), 0); + OperationEnvelope { + id, + author: AuthorId(0), + stamp: OperationStamp::new(HybridLogicalClock::new(WallClockTime(physical), 0), id), + causal_context: CausalContext::new() + .with_dot(respell_a.id) + .with_dot(respell_b.id), + transaction: None, + payload: OperationPayload::ResolveConflict(ResolveConflictPayload { + target: cid, + action, + }), + } + }; + let first = resolve(4, 30, ResolutionAction::KeepWinner); + let second = resolve(5, 31, ResolutionAction::AcceptLoser); + let mut set2 = OperationSet::new(); + set2.accept_all(vec![ + insert_env, + respell_a, + respell_b, + first.clone(), + second.clone(), + ]); + let state = set2.reduce(); + let meta = state + .conflicts + .records() + .iter() + .find(|r| r.id != cid) + .expect("a meta-conflict record exists"); + assert_eq!( + meta.kind, + ConflictKind::StructuralFieldCollision { + winner: first.id, + loser: second.id, + field: FieldPath("conflict_resolution".to_string()), + }, + "the earlier resolver's action stands, so it is the winner" + ); + assert_eq!( + meta.caused_by, + vec![first.id, second.id], + "both resolvers are named as causes" + ); + } + + #[test] + fn deleting_an_event_records_the_marker_reanchor_repair() { + // Chapter 6 §Re-Anchoring: "Re-anchoring actions MUST be recorded as + // RepairRecord entries in the triggering operation's effect", and the + // rule table's marker row: re-anchor to the *nearest event in the same + // staff instance* (four-key ordering). The fixture voice's events sit + // at ascending quarter positions, so deleting the first re-anchors the + // marker to the second (same voice: proximity rank 0 dominates any + // closer event in a sibling voice). + use epiphany_core::generators::valid_score; + let mut base = valid_score(0x5EED); + let voice_events = base + .voices() + .map(|(_, _, v)| v.events.clone()) + .next() + .expect("the fixture has a voice"); + let event_id = voice_events[0]; + let expected = voice_events[1]; + let marker_id = epiphany_core::MarkerId::new(ReplicaId(9), 700); + base.cross_cutting.markers.push(epiphany_core::Marker { + id: marker_id, + anchor: TimeAnchor::Event { + id: event_id, + offset: AnchorOffset::Zero, + }, + }); + + let del = prim_env( + 2, + 0, + 10, + CausalContext::new(), + OperationKind::DeleteEvent(DeleteEventOp { + event: event_id, + tuplet_compensation: TupletCompensation::NotInTuplet, + }), + ); + let mut set = OperationSet::new(); + set.accept_all(vec![del.clone()]); + let result = set.reduce_onto(&base); + + let effect = result + .state + .effects + .iter() + .find(|(id, _)| *id == del.id) + .map(|(_, e)| e) + .expect("delete effect recorded"); + let OperationEffect::AppliedWithRepair { repairs } = effect else { + panic!("expected AppliedWithRepair, got {effect:?}"); + }; + assert!( + repairs.iter().any(|r| { + r.target == TypedObjectId::Marker(marker_id) + && r.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(event_id), + to: TypedObjectId::Event(expected), + reason: ReanchorReason::SameVoiceNearer, + } + }), + "the marker re-anchor to the nearest same-voice event is a recorded \ + repair, not a silent mutation: {repairs:?}" + ); + let marker = result + .score + .cross_cutting + .markers + .iter() + .find(|m| m.id == marker_id) + .expect("marker survives"); + assert!( + matches!(marker.anchor, TimeAnchor::Event { id, .. } if id == expected), + "the graph agrees with the recorded repair" + ); + assert!(epiphany_core::check_invariants(&result.score).is_empty()); + } + + #[test] + fn marker_reanchor_prefers_the_forward_survivor_on_distance_ties() { + // Four-key ordering, key 3: forward (0) before backward (1). Three + // whole-note events at positions 10/12/14 in the base's first voice; + // deleting the middle one leaves survivors at equal distance 2 on both + // sides, so the *forward* neighbor (position 14) wins. + use epiphany_core::generators::valid_score; + let mut base = valid_score(0x5EED); + let (staff_instance, voice) = { + let instance = &base.canvas.regions[0].staff_instances()[0]; + (instance.id, instance.voices[0].id) + }; + let backward = EventId::new(ReplicaId(3), 0); + let referent = EventId::new(ReplicaId(3), 1); + let forward = EventId::new(ReplicaId(3), 2); + let insert_at = |counter: u64, event: EventId, position: i64| { + let ctx = if counter == 0 { + CausalContext::new() + } else { + CausalContext::new().with_seen(ReplicaId(3), counter - 1) + }; + prim_env( + 3, + counter, + 10 + counter as i64, + ctx, + OperationKind::InsertEvent(InsertEventOp { + staff_instance, + event: crate::valuegen::insert_event_value( + event, + voice, + pos(position), + epiphany_core::MusicalDuration::whole(), + &[], + ), + }), + ) + }; + let marker_id = epiphany_core::MarkerId::new(ReplicaId(9), 701); + base.cross_cutting.markers.push(epiphany_core::Marker { + id: marker_id, + anchor: TimeAnchor::Event { + id: referent, + offset: AnchorOffset::Zero, + }, + }); + let del = prim_env( + 3, + 3, + 20, + CausalContext::new().with_seen(ReplicaId(3), 2), + OperationKind::DeleteEvent(DeleteEventOp { + event: referent, + tuplet_compensation: TupletCompensation::NotInTuplet, + }), + ); + let mut set = OperationSet::new(); + set.accept_all(vec![ + insert_at(0, backward, 10), + insert_at(1, referent, 12), + insert_at(2, forward, 14), + del.clone(), + ]); + let result = set.reduce_onto(&base); + let effect = result + .state + .effects + .iter() + .find(|(id, _)| *id == del.id) + .map(|(_, e)| e) + .expect("delete effect recorded"); + let OperationEffect::AppliedWithRepair { repairs } = effect else { + panic!("expected AppliedWithRepair, got {effect:?}"); + }; + assert!( + repairs.iter().any(|r| { + r.target == TypedObjectId::Marker(marker_id) + && r.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(referent), + to: TypedObjectId::Event(forward), + reason: ReanchorReason::SameVoiceNearer, + } + }), + "equal distances tie-break forward before backward: {repairs:?}" + ); + assert!( + matches!( + result + .score + .cross_cutting + .markers + .iter() + .find(|m| m.id == marker_id) + .expect("marker survives") + .anchor, + TimeAnchor::Event { id, .. } if id == forward + ), + "the graph agrees with the recorded repair" + ); + assert!(epiphany_core::check_invariants(&result.score).is_empty()); + } + + #[test] + fn system_pitch_counter_collision_halts_reduction() { + // Chapter 5 §"System-Derived Counter Collisions": two different + // canonical input sets claiming one system-derived counter record a + // SystemIdentifierCollision, reduction does not continue past the + // collision, and neither input set occupies the collided counter. + use epiphany_core::derive_system_pitch_id; + let content_x = crate::valuegen::pitch_value_nth(1); + let content_y = crate::valuegen::pitch_value_nth(2); + let system_id = derive_system_pitch_id(&content_x); + assert_eq!(system_id.replica(), ReplicaId::SYSTEM_DERIVED); + + let before = insert(3, 0, 5, 4, 400, 0); + let legit = insert_with_pitch_content(1, 0, 10, 1, 100, 0, system_id, &content_x); + let claim = insert_with_pitch_content(2, 0, 20, 2, 200, 5, system_id, &content_y); + let after = insert(1, 1, 30, 3, 300, 9); + + let mut set = OperationSet::new(); + set.accept_all(vec![ + before.clone(), + legit.clone(), + claim.clone(), + after.clone(), + ]); + let state = set.reduce(); + + assert_eq!(state.anomalies.len(), 1, "exactly one collision recorded"); + match &state.anomalies[0].kind { + IntegrityAnomalyKind::SystemIdentifierCollision { + kind, + colliding_counter, + input_set_a, + input_set_b, + } => { + assert_eq!(*kind, ObjectKind::Pitch); + assert_eq!(*colliding_counter, system_id.counter()); + let mut sets = [input_set_a.0.clone(), input_set_b.0.clone()]; + sets.sort(); + let mut expected = [ + canonical_pitch_bytes(&content_x), + canonical_pitch_bytes(&content_y), + ]; + expected.sort(); + assert_eq!(sets, expected, "the anomaly retains both input sets"); + } + other => panic!("expected SystemIdentifierCollision, got {other:?}"), + } + // Only the operation before the collision point reduced. + assert_eq!(state.effects.len(), 1); + assert_eq!(state.effects[0].0, before.id); + // Neither input set occupies the collided counter. + assert!(!state.objects.contains_key(&TypedObjectId::Pitch(system_id))); + assert!(!state + .objects + .contains_key(&TypedObjectId::Event(EventId::new(ReplicaId(1), 100)))); + // The colliding pair and everything past the halt are held pending. + let pending: BTreeMap<_, _> = state.pending.iter().copied().collect(); + let halted = PendingReason::HaltedBySystemCollision { at: claim.id }; + assert_eq!(pending.get(&legit.id), Some(&halted)); + assert_eq!(pending.get(&claim.id), Some(&halted)); + assert_eq!(pending.get(&after.id), Some(&halted)); + // Determinism: any permutation reduces to identical bytes. + let mut reversed = OperationSet::new(); + reversed.accept_all(vec![after, claim, legit, before]); + assert_eq!(state.canonical_bytes(), reversed.reduce().canonical_bytes()); + } + + #[test] + fn reobserving_the_same_system_derivation_is_not_a_collision() { + // The same (counter, inputs) pair re-observed is idempotent, not a + // collision; the duplicate insert is refused by pitch-id freshness + // (base-free parity with the graph-aware precondition). + use epiphany_core::derive_system_pitch_id; + let content_x = crate::valuegen::pitch_value_nth(1); + let system_id = derive_system_pitch_id(&content_x); + let a = insert_with_pitch_content(1, 0, 10, 1, 100, 0, system_id, &content_x); + let b = insert_with_pitch_content(2, 0, 20, 2, 200, 5, system_id, &content_x); + let mut set = OperationSet::new(); + set.accept_all(vec![a.clone(), b.clone()]); + let state = set.reduce(); + assert!(state.anomalies.is_empty(), "same derivation: no collision"); + assert!(state.pending.is_empty(), "nothing is held"); + let effect = |id: OperationId| { + state + .effects + .iter() + .find(|(e, _)| *e == id) + .map(|(_, eff)| eff) + .expect("effect recorded") + }; + assert_eq!(effect(a.id), &OperationEffect::Applied); + assert_eq!( + effect(b.id), + &OperationEffect::NoOp { + reason: NoOpReason::PreconditionFailedUnderReduction { + reason: PreconditionFailureReason::TargetTombstoned, + }, + }, + "a reused pitch id is not fresh, in base-free reduction too" + ); + } + + #[test] + fn base_seeded_system_pitch_collides_with_an_op_claim() { + // The registry seeds from the base graph: an operation claiming a + // base-occupied system counter with different content collides. The + // base occupant is graph state (not an operation of this reduction), + // so it is left in place for diagnostic recovery. + use epiphany_core::generators::valid_score; + use epiphany_core::{derive_system_pitch_id, IdentifiedPitch}; + + let content_x = crate::valuegen::pitch_value_nth(1); + let content_y = crate::valuegen::pitch_value_nth(2); + let system_id = derive_system_pitch_id(&content_x); + + let mut base = valid_score(0x5EED); + let pitched_id = base + .voices() + .flat_map(|(_, _, v)| v.events.clone()) + .find(|e| matches!(base.events.get(*e), Some(Event::Pitched(_)))) + .expect("the fixture has a pitched event"); + if let Some(Event::Pitched(pe)) = base.events.get_mut(pitched_id) { + pe.pitches[0] = IdentifiedPitch { + id: system_id, + pitch: content_x.clone(), + }; + } + + let claim = insert_with_pitch_content(2, 0, 10, 2, 200, 5, system_id, &content_y); + let mut set = OperationSet::new(); + set.accept_all(vec![claim.clone()]); + let result = set.reduce_onto(&base); + + assert_eq!(result.state.anomalies.len(), 1); + assert!(matches!( + &result.state.anomalies[0].kind, + IntegrityAnomalyKind::SystemIdentifierCollision { + kind: ObjectKind::Pitch, + .. + } + )); + assert!(result.state.effects.is_empty(), "reduction halted"); + let pending: BTreeMap<_, _> = result.state.pending.iter().copied().collect(); + assert_eq!( + pending.get(&claim.id), + Some(&PendingReason::HaltedBySystemCollision { at: claim.id }) + ); + assert!( + result.score.events.get(pitched_id).is_some(), + "the base occupant stays; recovery is external" + ); + } + + // --- ResolveEquivocation (operation_catalog §"ResolveEquivocation"). ----- + + /// A `RespellPitch` envelope at `id` with an explicit causal context. + fn respell_at( + id: OperationId, + physical: i64, + spelling: u8, + ctx: CausalContext, + ) -> OperationEnvelope { + use crate::payload::RespellPitchOp; + OperationEnvelope { + id, + author: AuthorId(0), + stamp: OperationStamp::new(HybridLogicalClock::new(WallClockTime(physical), 0), id), + causal_context: ctx, + transaction: None, + payload: OperationPayload::Primitive(OperationKind::RespellPitch(RespellPitchOp { + pitch: epiphany_core::PitchId::new(ReplicaId(9), 500), + spelling: crate::valuegen::spelling(spelling), + })), + } + } + + /// A `ResolveEquivocation` envelope at `id` naming `(target, chosen)`. + fn resolve_equivocation_env( + id: OperationId, + physical: i64, + target: OperationId, + chosen: crate::EnvelopeHash, + ) -> OperationEnvelope { + OperationEnvelope { + id, + author: AuthorId(0), + stamp: OperationStamp::new(HybridLogicalClock::new(WallClockTime(physical), 0), id), + causal_context: CausalContext::new(), + transaction: None, + payload: OperationPayload::ResolveEquivocation( + crate::payload::ResolveEquivocationPayload { target, chosen }, + ), + } + } + + fn effect_of(state: &MaterializedState, id: OperationId) -> Option<&OperationEffect> { + state + .effects + .iter() + .find(|(e, _)| *e == id) + .map(|(_, eff)| eff) + } + + #[test] + fn resolve_equivocation_promotes_the_chosen_candidate_and_unblocks_dependents() { + let pitch = epiphany_core::PitchId::new(ReplicaId(9), 500); + + // An InsertEvent carrying `pitch` makes the pitch Live. + let mut insert_env = insert(1, 0, 10, 1, 100, 0); + if let OperationPayload::Primitive(OperationKind::InsertEvent(ref mut op)) = + insert_env.payload + { + op.event = crate::valuegen::insert_event_value( + op.event_id(), + op.voice(), + op.musical_position(), + op.musical_duration(), + &[pitch], + ); + } + + // An equivocated pair of respellings under one id, both after the insert. + let eq_id = OperationId::new(ReplicaId(9), 0); + let after_insert = CausalContext::new().with_seen(ReplicaId(1), 0); + let cand_a = respell_at(eq_id, 20, 0xAA, after_insert.clone()); + let cand_b = respell_at(eq_id, 20, 0xBB, after_insert.clone()); + assert_ne!(cand_a.envelope_hash(), cand_b.envelope_hash()); + + // A dependent causally covering the equivocated id: previously held + // pending (DependsOnEquivocated); must unblock and reduce. + let dependent = respell_at( + OperationId::new(ReplicaId(2), 0), + 30, + 0xCC, + CausalContext::new() + .with_seen(ReplicaId(1), 0) + .with_seen(ReplicaId(9), 0), + ); + + // Baseline (no resolve): the slot is anomalous, the dependent pending. + let mut without = OperationSet::new(); + without.accept_all(vec![ + insert_env.clone(), + cand_a.clone(), + cand_b.clone(), + dependent.clone(), + ]); + let state = without.reduce(); + assert!(state.anomalies.iter().any(|an| matches!( + an.kind, + IntegrityAnomalyKind::OperationSlotEquivocated { operation_id } if operation_id == eq_id + ))); + let pending: BTreeMap<_, _> = state.pending.iter().copied().collect(); + assert_eq!( + pending.get(&dependent.id), + Some(&PendingReason::DependsOnEquivocated { on: eq_id }) + ); + + // With a resolve choosing candidate A: the slot reduces as if it had + // always been Single with A — A contributes at its own canonical + // position, the dependent unblocks, and no anomaly is recorded. + let resolve = resolve_equivocation_env( + OperationId::new(ReplicaId(3), 0), + 40, + eq_id, + cand_a.envelope_hash(), + ); + let all = vec![ + insert_env.clone(), + cand_a.clone(), + cand_b.clone(), + dependent.clone(), + resolve.clone(), + ]; + let mut set = OperationSet::new(); + set.accept_all(all.clone()); + let state = set.reduce(); + assert!( + state.is_clean(), + "no conflict, anomaly, or pending: {state:?}" + ); + assert_eq!(effect_of(&state, eq_id), Some(&OperationEffect::Applied)); + assert_eq!( + effect_of(&state, dependent.id), + Some(&OperationEffect::Applied) + ); + assert_eq!( + effect_of(&state, resolve.id), + Some(&OperationEffect::Applied) + ); + // The dependent respell is causally after the promoted candidate, so + // its spelling (0xCC) is the resolved value — an intentional overwrite. + assert_eq!( + state.spellings.get(&pitch), + Some(&crate::valuegen::spelling(0xCC)) + ); + // Losing candidate B remains only in the diagnostic candidate store. + assert!(set.candidate(cand_b.envelope_hash()).is_some()); + + // Order-independent: a reversed acceptance order reduces to the bytes. + let mut reversed = OperationSet::new(); + let mut rev = all; + rev.reverse(); + reversed.accept_all(rev); + assert_eq!(reversed.reduce().canonical_bytes(), state.canonical_bytes()); + } + + #[test] + fn later_resolves_reduce_idempotently_or_collide_on_equivocation_resolution() { + let eq_id = OperationId::new(ReplicaId(9), 0); + let cand_a = respell_at(eq_id, 10, 0xAA, CausalContext::new()); + let cand_b = respell_at(eq_id, 10, 0xBB, CausalContext::new()); + + // Three resolves: the earliest (in canonical order) governs; a later + // one naming the same candidate is idempotent; a later one naming a + // differing candidate collides. + let first = resolve_equivocation_env( + OperationId::new(ReplicaId(2), 0), + 20, + eq_id, + cand_a.envelope_hash(), + ); + let same = resolve_equivocation_env( + OperationId::new(ReplicaId(3), 0), + 30, + eq_id, + cand_a.envelope_hash(), + ); + let differing = resolve_equivocation_env( + OperationId::new(ReplicaId(4), 0), + 40, + eq_id, + cand_b.envelope_hash(), + ); + + let mut set = OperationSet::new(); + set.accept_all(vec![ + cand_a.clone(), + cand_b.clone(), + first.clone(), + same.clone(), + differing.clone(), + ]); + let state = set.reduce(); + + assert_eq!(effect_of(&state, first.id), Some(&OperationEffect::Applied)); + assert_eq!( + effect_of(&state, same.id), + Some(&OperationEffect::NoOp { + reason: NoOpReason::AlreadyApplied, + }) + ); + assert!(matches!( + effect_of(&state, differing.id), + Some(OperationEffect::Conflicted { .. }) + )); + assert_eq!(state.conflicts.records().len(), 1); + let record = &state.conflicts.records()[0]; + assert_eq!( + record.kind, + ConflictKind::StructuralFieldCollision { + winner: first.id, + loser: differing.id, + field: FieldPath("equivocation_resolution".to_string()), + } + ); + assert_eq!(record.caused_by, vec![first.id, differing.id]); + assert!(record.affected_objects.is_empty()); + // The slot still promoted A; no anomaly for it. + assert!(state.anomalies.is_empty()); + assert!(effect_of(&state, eq_id).is_some()); + } + + #[test] + fn resolve_without_a_matching_equivocation_is_a_precondition_noop() { + let precondition_noop = OperationEffect::NoOp { + reason: NoOpReason::PreconditionFailedUnderReduction { + reason: PreconditionFailureReason::TargetMissing, + }, + }; + + // (a) Target id entirely absent from the operation set. + let absent = resolve_equivocation_env( + OperationId::new(ReplicaId(2), 0), + 20, + OperationId::new(ReplicaId(9), 7), + crate::EnvelopeHash([1; 32]), + ); + let mut set = OperationSet::new(); + set.accept_all(vec![absent.clone()]); + let state = set.reduce(); + assert_eq!(effect_of(&state, absent.id), Some(&precondition_noop)); + + // (b) Target occupies an ordinary Single slot (no equivocation). + let single = respell_at( + OperationId::new(ReplicaId(9), 0), + 10, + 0xAA, + CausalContext::new(), + ); + let not_equivocated = resolve_equivocation_env( + OperationId::new(ReplicaId(2), 0), + 20, + single.id, + single.envelope_hash(), + ); + let mut set = OperationSet::new(); + set.accept_all(vec![single.clone(), not_equivocated.clone()]); + let state = set.reduce(); + assert_eq!( + effect_of(&state, not_equivocated.id), + Some(&precondition_noop) + ); + + // (c) Target is equivocated but `chosen` names no candidate: the slot + // stays equivocated (anomaly recorded, dependents still pending) and + // the resolve is a precondition no-op — behavior is otherwise exactly + // the unresolved baseline. + let eq_id = OperationId::new(ReplicaId(9), 0); + let cand_a = respell_at(eq_id, 10, 0xAA, CausalContext::new()); + let cand_b = respell_at(eq_id, 10, 0xBB, CausalContext::new()); + let dependent = respell_at( + OperationId::new(ReplicaId(4), 0), + 30, + 0xCC, + CausalContext::new().with_seen(ReplicaId(9), 0), + ); + let bogus = resolve_equivocation_env( + OperationId::new(ReplicaId(2), 0), + 20, + eq_id, + crate::EnvelopeHash([0xEE; 32]), + ); + let mut set = OperationSet::new(); + set.accept_all(vec![ + cand_a.clone(), + cand_b.clone(), + dependent.clone(), + bogus.clone(), + ]); + let state = set.reduce(); + assert_eq!(effect_of(&state, bogus.id), Some(&precondition_noop)); + assert!(effect_of(&state, eq_id).is_none()); + assert!(state.anomalies.iter().any(|an| matches!( + an.kind, + IntegrityAnomalyKind::OperationSlotEquivocated { operation_id } if operation_id == eq_id + ))); + let pending: BTreeMap<_, _> = state.pending.iter().copied().collect(); + assert_eq!( + pending.get(&dependent.id), + Some(&PendingReason::DependsOnEquivocated { on: eq_id }) + ); + } + + #[test] + fn an_equivocated_resolve_is_excluded_like_any_equivocated_slot() { + let eq_id = OperationId::new(ReplicaId(9), 0); + let cand_a = respell_at(eq_id, 10, 0xAA, CausalContext::new()); + let cand_b = respell_at(eq_id, 10, 0xBB, CausalContext::new()); + + // Two distinct resolve envelopes under one id (differing `chosen`): + // the resolve slot itself equivocates, so it never governs. + let resolve_id = OperationId::new(ReplicaId(5), 0); + let resolve_a = resolve_equivocation_env(resolve_id, 20, eq_id, cand_a.envelope_hash()); + let resolve_b = resolve_equivocation_env(resolve_id, 20, eq_id, cand_b.envelope_hash()); + assert_ne!(resolve_a.envelope_hash(), resolve_b.envelope_hash()); + + let mut set = OperationSet::new(); + set.accept_all(vec![cand_a, cand_b, resolve_a, resolve_b]); + let state = set.reduce(); + + // Neither slot contributes; both record equivocation anomalies. + assert!(state.effects.is_empty()); + for id in [eq_id, resolve_id] { + assert!( + state.anomalies.iter().any(|an| matches!( + an.kind, + IntegrityAnomalyKind::OperationSlotEquivocated { operation_id } if operation_id == id + )), + "expected an equivocation anomaly for {id:?}" + ); + } + } } diff --git a/crates/epiphany-ops/src/v0.rs b/crates/epiphany-ops/src/v0.rs index 5028840..645eb4c 100644 --- a/crates/epiphany-ops/src/v0.rs +++ b/crates/epiphany-ops/src/v0.rs @@ -22,7 +22,7 @@ use epiphany_core::{ }; use epiphany_determinism::ContentHash; -use crate::payload::{ResolveConflictPayload, TransactionDescriptor}; +use crate::payload::{ResolveConflictPayload, ResolveEquivocationPayload, TransactionDescriptor}; use crate::support::OperationKindRegistryId; use crate::undo::UndoTransactionPayload; use crate::OperationEnvelope; @@ -49,6 +49,10 @@ pub enum V0OperationPayload { ResolveConflict(ResolveConflictPayload), /// Value-complete in v0 already; unchanged in v1. UndoTransaction(UndoTransactionPayload), + /// v1-native (no identifier-only v0 predecessor existed — v0 predates the + /// catalog's equivocation-resolution entry); carried verbatim so the + /// migration round-trips it by identity, like the Group 1–4 kinds below. + ResolveEquivocation(ResolveEquivocationPayload), } /// Frozen v0 primitive kinds (the representative §6.10 set). diff --git a/crates/epiphany-ops/src/validate.rs b/crates/epiphany-ops/src/validate.rs new file mode 100644 index 0000000..a34bc22 --- /dev/null +++ b/crates/epiphany-ops/src/validate.rs @@ -0,0 +1,451 @@ +//! Validation modes and advisory-precondition checking (Chapter 6 +//! §"Validation Modes", label `sec:semops:validation`). +//! +//! The spec distinguishes two precondition-checking modes: +//! +//! * **Authoring mode** — interactive edits. *All* preconditions are enforced: +//! invariant preconditions (which preserve graph invariants) and advisory +//! preconditions (user-intent constraints, range checks, style policy). +//! * **Replay mode** — replaying historical operations or applying remote +//! operations under reduction. Only invariant preconditions are enforced; +//! advisory preconditions MAY fail silently, since they represent the +//! authoring replica's local policy at the moment of authoring, not +//! invariants of the canonical state. +//! +//! ## Where each mode lives +//! +//! [`crate::OperationSet::reduce`] and [`crate::OperationSet::reduce_onto`] +//! **are** replay mode: the reducer enforces exactly the invariant +//! preconditions and nothing else, in every context. Authoring-mode +//! enforcement happens **before an envelope is minted** — the authoring layer +//! (epiphany-editor-core) runs [`advisory_violations`] against its current +//! materialized score and refuses to mint on any violation. Canonical +//! reduction behavior and canonical bytes are therefore **untouched** by the +//! mode machinery: an envelope that exists reduces identically whether its +//! author checked advisories or not (the spec's replay-parity requirement). +//! +//! ## The advisory inventory (core spec §6.10) +//! +//! The spec declares advisory preconditions for two of the implemented K0 +//! operations (every other implemented kind's precondition bucket is entirely +//! invariant): +//! +//! * **InsertEvent** — (a) for pitched events, every pitch is within the +//! instrument's declared range, if any; (b) the event's duration does not +//! extend past a region boundary in a way that would require splitting. +//! * **CreateCrossCutting (Slur case)** — the slur does not span a region +//! boundary, unless explicitly permitted by region configuration. +//! +//! `ModifyEvent` carries the full replacement event value, so check (b) +//! applies to it identically (the replacement's span must not straddle the +//! region boundary any more than an inserted one may). +//! +//! ### Implemented here +//! +//! * InsertEvent / ModifyEvent duration-not-crossing-region-boundary +//! ([`AdvisoryViolation::DurationCrossesRegionBoundary`]), for regions whose +//! musical end bound is resolvable (see below). +//! * CreateCrossCutting(Slur) not-spanning-a-region-boundary +//! ([`AdvisoryViolation::SlurSpansRegionBoundary`]): the slur's endpoint +//! events resolve to different regions. +//! +//! ### Documented gaps (blocked on the truncated data model) +//! +//! * **InsertEvent pitch-within-instrument-range**: `epiphany_core::Instrument` +//! carries only `{ id, name }` — it has no declared range field. The +//! data-model completion is staged to the Binary Format companion; until the +//! field exists there is nothing to check against ("if any" in the spec text +//! makes the absent-range case a vacuous pass, which is exactly what this +//! module does by omission). +//! * **Slur spanning "explicitly permitted by region configuration"**: +//! `epiphany_core::Region` has no such configuration flag. The check treats +//! spanning as never permitted; when the flag lands, it suppresses the +//! violation. +//! * **Region musical end bound**: a region's `TimeExtent` is a pair of +//! `TimeAnchor`s. The bound is resolvable in musical time only when the end +//! anchor is region-start-anchored with a `Musical` offset (the same +//! sound-but-incomplete resolution discipline as +//! `epiphany_core::Region::overlaps_in_time`, which resolves only wall-clock +//! extents). A wall-clock or symbolic extent yields no musical bound and the +//! boundary check passes vacuously — the full tempo/measure resolution +//! machinery is deferred (P11-C5). + +use epiphany_core::{ + AnchorOffset, EventDuration, EventId, EventPosition, MusicalPosition, Region, RegionEdge, + RegionId, Score, SlurId, TimeAnchor, +}; + +use crate::payload::{CrossCuttingValue, OperationKind}; +use crate::reduce::graph_voice_location; + +/// The two precondition-checking modes of Chapter 6 §"Validation Modes" +/// (`sec:semops:validation`). +/// +/// Invariant preconditions hold in **all** modes — the reducer +/// ([`crate::OperationSet::reduce`] / [`crate::OperationSet::reduce_onto`]) +/// enforces them unconditionally, and is thereby exactly +/// [`ValidationMode::Replay`]. [`ValidationMode::Authoring`] additionally +/// requires [`advisory_violations`] to be empty *before an envelope is +/// minted*; it never alters reduction. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum ValidationMode { + /// Interactive edits: invariant **and** advisory preconditions are + /// enforced. The advisory half is enforced pre-mint by the authoring + /// layer via [`advisory_violations`]. + Authoring, + /// Replaying historical operations or applying remote operations under + /// reduction: only invariant preconditions are enforced; advisory + /// preconditions MAY fail silently. + Replay, +} + +impl ValidationMode { + /// Whether this mode enforces advisory preconditions (only + /// [`ValidationMode::Authoring`] does). + #[inline] + pub fn enforces_advisory(self) -> bool { + matches!(self, ValidationMode::Authoring) + } +} + +/// A failed advisory precondition (Chapter 6 §6.10, the "Advisory +/// preconditions (authoring mode only)" buckets). +/// +/// **Deliberately non-canonical**: this type has no canonical encoding and no +/// discriminant table because it never enters effects, conflicts, or any other +/// canonical state — it exists only on the authoring side, *before* an +/// envelope is minted. An operation refused for an advisory violation leaves +/// no trace in the operation set; one that slipped past (a remote author's +/// different policy) reduces normally in replay mode. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum AdvisoryViolation { + /// An `InsertEvent`/`ModifyEvent` event's span starts inside its region's + /// musical extent but ends past the region's end bound — applying it would + /// require splitting the event across the boundary (core spec §6.10 + /// InsertEvent, advisory bucket). + DurationCrossesRegionBoundary { + /// The offending event. + event: EventId, + /// The region whose end bound the event's span crosses. + region: RegionId, + }, + /// A `CreateCrossCutting` slur's endpoint events lie in different regions + /// (core spec §6.10 CreateCrossCutting, Slur advisory bucket). Region + /// configuration cannot yet permit spanning (see the module docs' gap + /// list), so a cross-region slur always reports. + SlurSpansRegionBoundary { + /// The offending slur. + slur: SlurId, + /// The region containing the start event. + start_region: RegionId, + /// The (different) region containing the end event. + end_region: RegionId, + }, +} + +/// Checks `kind` against every implemented advisory precondition (the +/// authoring-mode-only bucket of Chapter 6 §6.10), evaluated against `score` +/// — the authoring replica's current materialized graph. Returns every +/// violation found (empty = the operation may be minted in authoring mode). +/// +/// Replay mode never calls this: the reducer applies invariant preconditions +/// only, so an envelope violating an advisory check still reduces cleanly +/// (spec: advisory preconditions MAY fail silently in replay mode). The check +/// is deliberately *conservative*: anything it cannot resolve against the +/// graph (a missing voice, a non-musical placement, an unresolvable region +/// bound) passes vacuously and is left to the invariant preconditions under +/// reduction. +pub fn advisory_violations(kind: &OperationKind, score: &Score) -> Vec { + let mut violations = Vec::new(); + match kind { + OperationKind::InsertEvent(op) => { + check_event_span(&op.event, score, &mut violations); + } + OperationKind::ModifyEvent(op) => { + check_event_span(&op.event, score, &mut violations); + } + OperationKind::CreateCrossCutting(op) => { + if let CrossCuttingValue::Slur(slur) = &op.structure { + let start = event_region(score, slur.start_event); + let end = event_region(score, slur.end_event); + if let (Some(start_region), Some(end_region)) = (start, end) { + if start_region != end_region { + violations.push(AdvisoryViolation::SlurSpansRegionBoundary { + slur: slur.id, + start_region, + end_region, + }); + } + } + } + } + // Every other implemented kind's spec precondition bucket is entirely + // invariant (see the module docs); nothing to check here. + _ => {} + } + violations +} + +/// Reports a violation when `event`'s musical span straddles its region's +/// musical end bound (starts strictly before it, ends strictly past it — the +/// "would require splitting" shape). A non-musical placement, an unlocatable +/// voice, or an unresolvable bound passes vacuously. +fn check_event_span( + event: &epiphany_core::Event, + score: &Score, + violations: &mut Vec, +) { + let (EventPosition::Musical(position), EventDuration::Musical(duration)) = + (event.position(), event.duration()) + else { + return; + }; + let Some((region_index, _, _)) = graph_voice_location(score, event.voice()) else { + return; + }; + let region = &score.canvas.regions[region_index]; + let Some(bound) = region_musical_end_bound(region) else { + return; + }; + let end = position.clone() + duration.clone(); + if position < &bound && end > bound { + violations.push(AdvisoryViolation::DurationCrossesRegionBoundary { + event: event.id(), + region: region.id, + }); + } +} + +/// The region's end bound as a region-local musical position, when its +/// `TimeExtent`'s end anchor expresses one: anchored to this region's own +/// start edge with a `Musical` offset. Any other shape (wall-clock, symbolic, +/// another region's edge) is not resolvable without the deferred tempo/measure +/// machinery and yields `None` (the advisory check then passes vacuously). +fn region_musical_end_bound(region: &Region) -> Option { + match ®ion.time_extent.end { + TimeAnchor::Region { + id, + edge: RegionEdge::Start, + offset: AnchorOffset::Musical(length), + } if *id == region.id => Some(MusicalPosition(length.0.clone())), + _ => None, + } +} + +/// The region containing `event`, resolved through the event's voice. `None` +/// when the event or its voice is not in the graph (the invariant +/// preconditions own that case). +fn event_region(score: &Score, event: EventId) -> Option { + let ev = score.events.get(event)?; + let (region_index, _, _) = graph_voice_location(score, ev.voice())?; + Some(score.canvas.regions[region_index].id) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::payload::{CreateCrossCuttingOp, InsertEventOp, ModifyEventOp}; + use crate::valuegen; + use epiphany_core::generators::valid_score; + use epiphany_core::{ + EventId, MusicalDuration, MusicalPosition, PitchId, RationalTime, ReplicaId, SlurId, + VoiceId, + }; + + /// A fixture score whose (single) region declares a musical end bound of + /// `bound` whole units, plus the ids needed to aim operations at it. + fn bounded_score(bound: i32) -> (Score, RegionId, epiphany_core::StaffInstanceId, VoiceId) { + let mut score = valid_score(7); + let region = &mut score.canvas.regions[0]; + let region_id = region.id; + region.time_extent.end = TimeAnchor::Region { + id: region_id, + edge: RegionEdge::Start, + offset: AnchorOffset::Musical(MusicalDuration(RationalTime::from_int(bound))), + }; + let instance = region.staff_instances()[0].id; + let voice = region.staff_instances()[0].voices[0].id; + (score, region_id, instance, voice) + } + + fn insert_kind( + instance: epiphany_core::StaffInstanceId, + voice: VoiceId, + position: i32, + duration: i32, + ) -> OperationKind { + OperationKind::InsertEvent(InsertEventOp { + staff_instance: instance, + event: valuegen::insert_event_value( + EventId::new(ReplicaId(50), 999), + voice, + MusicalPosition(RationalTime::from_int(position)), + MusicalDuration(RationalTime::from_int(duration)), + &[PitchId::new(ReplicaId(50), 998)], + ), + }) + } + + #[test] + fn insert_event_crossing_the_region_end_bound_is_an_advisory_violation() { + let (score, region, instance, voice) = bounded_score(12); + // Starts inside the extent (10 < 12), ends past it (14 > 12). + let kind = insert_kind(instance, voice, 10, 4); + let violations = advisory_violations(&kind, &score); + assert_eq!( + violations, + vec![AdvisoryViolation::DurationCrossesRegionBoundary { + event: EventId::new(ReplicaId(50), 999), + region, + }] + ); + } + + #[test] + fn insert_event_within_the_region_end_bound_passes() { + let (score, _, instance, voice) = bounded_score(12); + // Ends exactly at the bound: nothing to split, no violation. + let kind = insert_kind(instance, voice, 10, 2); + assert!(advisory_violations(&kind, &score).is_empty()); + } + + #[test] + fn insert_event_against_an_unresolvable_extent_passes_vacuously() { + // The unmodified fixture's extent is wall-clock — no musical bound is + // resolvable, so the boundary check cannot fire (module docs, gap 3). + let score = valid_score(7); + let instance = score.canvas.regions[0].staff_instances()[0].id; + let voice = score.canvas.regions[0].staff_instances()[0].voices[0].id; + let kind = insert_kind(instance, voice, 10, 1_000); + assert!(advisory_violations(&kind, &score).is_empty()); + } + + #[test] + fn modify_event_crossing_the_region_end_bound_is_an_advisory_violation() { + let (score, region, _, voice) = bounded_score(12); + // A replacement value for an existing event, moved to straddle the + // bound. (The advisory check reads the replacement's span; liveness of + // the target is the reducer's invariant precondition.) + let target = score.canvas.regions[0].staff_instances()[0].voices[0].events[0]; + let kind = OperationKind::ModifyEvent(ModifyEventOp { + event: valuegen::insert_event_value( + target, + voice, + MusicalPosition(RationalTime::from_int(11)), + MusicalDuration(RationalTime::from_int(3)), + &[PitchId::new(ReplicaId(50), 998)], + ), + }); + let violations = advisory_violations(&kind, &score); + assert_eq!( + violations, + vec![AdvisoryViolation::DurationCrossesRegionBoundary { + event: target, + region, + }] + ); + // The same replacement kept inside the bound passes. + let kind = OperationKind::ModifyEvent(ModifyEventOp { + event: valuegen::insert_event_value( + target, + voice, + MusicalPosition(RationalTime::from_int(11)), + MusicalDuration(RationalTime::from_int(1)), + &[PitchId::new(ReplicaId(50), 998)], + ), + }); + assert!(advisory_violations(&kind, &score).is_empty()); + } + + #[test] + fn slur_spanning_two_regions_is_an_advisory_violation() { + // Two single-region fixture scores merged: distinct regions, each with + // its own events. + let mut score = valid_score(7); + let other = valid_score(8); + let start_region = score.canvas.regions[0].id; + let end_region = other.canvas.regions[0].id; + let start_event = score.canvas.regions[0].staff_instances()[0].voices[0].events[0]; + let end_event = other.canvas.regions[0].staff_instances()[0].voices[0].events[0]; + score.canvas.regions.push(other.canvas.regions[0].clone()); + for event in other.events.iter_canonical() { + score + .events + .insert(event.clone()) + .expect("distinct seeds mint distinct event ids"); + } + + let slur_id = SlurId::new(ReplicaId(50), 1); + let cross = OperationKind::CreateCrossCutting(CreateCrossCuttingOp { + structure: CrossCuttingValue::Slur(valuegen::slur(slur_id, start_event, end_event)), + }); + assert_eq!( + advisory_violations(&cross, &score), + vec![AdvisoryViolation::SlurSpansRegionBoundary { + slur: slur_id, + start_region, + end_region, + }] + ); + + // A slur within one region passes. + let second = score.canvas.regions[0].staff_instances()[0].voices[0].events[1]; + let within = OperationKind::CreateCrossCutting(CreateCrossCuttingOp { + structure: CrossCuttingValue::Slur(valuegen::slur(slur_id, start_event, second)), + }); + assert!(advisory_violations(&within, &score).is_empty()); + } + + #[test] + fn replay_reduction_ignores_advisory_violations_and_is_unchanged_by_the_mode_machinery() { + // Spec §"Validation Modes": advisory preconditions MAY fail silently + // in replay mode. An envelope carrying an advisory-violating insert + // reduces cleanly (Applied) through the ordinary reduction path, and + // the reduction's canonical bytes are a pure function of the operation + // set — consulting `advisory_violations` beforehand (as an authoring + // layer would) changes nothing. + use crate::causal::CausalContext; + use crate::stamp::{HybridLogicalClock, OperationStamp}; + use crate::support::AuthorId; + use crate::{OperationEnvelope, OperationPayload, OperationSet}; + use epiphany_core::{OperationId, WallClockTime}; + + let (score, _, instance, voice) = bounded_score(12); + let kind = insert_kind(instance, voice, 10, 4); + assert!( + !advisory_violations(&kind, &score).is_empty(), + "the scenario must actually violate an advisory precondition" + ); + + let id = OperationId::new(ReplicaId(50), 0); + let env = OperationEnvelope { + id, + author: AuthorId(0), + stamp: OperationStamp::new(HybridLogicalClock::new(WallClockTime(1), 0), id), + causal_context: CausalContext::new(), + transaction: None, + payload: OperationPayload::Primitive(kind), + }; + let mut set = OperationSet::new(); + set.accept(env); + let first = set.reduce_onto(&score); + assert!(first.state.is_clean(), "replay applies the insert cleanly"); + assert!(matches!( + first.state.effects.as_slice(), + [(applied, crate::OperationEffect::Applied)] if *applied == id + )); + // Byte-identity across repeated reductions of the same set — the mode + // machinery has no channel into reduction. + let second = set.reduce_onto(&score); + assert_eq!( + first.state.canonical_bytes(), + second.state.canonical_bytes() + ); + } + + #[test] + fn validation_mode_advisory_enforcement_is_authoring_only() { + assert!(ValidationMode::Authoring.enforces_advisory()); + assert!(!ValidationMode::Replay.enforces_advisory()); + } +} diff --git a/crates/epiphany-ops/tests/graph_reduction.rs b/crates/epiphany-ops/tests/graph_reduction.rs index df7f5b2..9843db7 100644 --- a/crates/epiphany-ops/tests/graph_reduction.rs +++ b/crates/epiphany-ops/tests/graph_reduction.rs @@ -2,18 +2,20 @@ //! graph rather than only the Chapter 6 bookkeeping projection. use epiphany_core::{ - check_invariants, derive_promoted_voice_id, AnchorOffset, EventId, MusicalDuration, - MusicalPosition, OperationId, PitchId, RationalTime, RegionEdge, RegionTimeModel, ReplicaId, - Score, SlurId, StaffInstanceId, TimeAnchor, TransactionId, TypedObjectId, VoiceId, VoiceOrigin, - WallClockTime, + check_invariants, derive_promoted_voice_id, AnalyticalAnnotation, AnalyticalAnnotationId, + AnchorOffset, AnnotationAnchor, Comment, CommentId, CueEvent, CueRendering, Event, + EventDuration, EventId, EventPosition, GestureAnchoring, GraphicGesture, GraphicGestureId, + Marker, MarkerId, MusicalDuration, MusicalPosition, OperationId, PitchId, RationalTime, + RegionEdge, RegionTimeModel, ReplicaId, Score, SlurId, StaffInstanceId, TimeAnchor, + TransactionId, TypedObjectId, VoiceId, VoiceOrigin, WallClockTime, }; use epiphany_ops::{ valuegen, AuthorId, CausalContext, ChangeRegionTimeModelOp, ConflictKind, CreateCrossCuttingOp, CrossCuttingValue, DeleteEventOp, HybridLogicalClock, InsertEventOp, NoOpReason, OperationEffect, OperationEnvelope, OperationKind, OperationPayload, OperationSet, - OperationStamp, PositionRemapping, PreconditionFailureReason, SetUserSystemBreakOp, - TransactionCategory, TransactionDescriptor, TupletCompensation, UndoPolicy, - UndoTransactionPayload, + OperationStamp, PositionRemapping, PreconditionFailureReason, ReanchorReason, RepairKind, + RepairRecord, SetUserSystemBreakOp, TransactionCategory, TransactionDescriptor, + TupletCompensation, UndoPolicy, UndoTransactionPayload, }; fn envelope( @@ -1031,6 +1033,76 @@ fn deleting_both_slur_endpoints_cascades_in_both_graph_and_ledger() { assert!(check_invariants(&result.score).is_empty()); } +#[test] +fn cascade_delete_tuplet_prunes_dangling_decompositions() { + // `valid_score_rich`'s metric region is a 3:2 triplet whose first member carries an + // in-tuplet decomposition. Cascade-deleting the tuplet — member 0 carries the + // `CascadeDeleteTuplets`, the rest delete as ordinary (no-longer-tuplet) events — + // must also drop that decomposition; otherwise its tuplet reference would dangle + // (invariant 6, cross-cutting refs resolve). + let base = epiphany_core::generators::valid_score_rich(0x5EED); + let tuplet = base.cross_cutting.tuplets[0].id; + let members = base.cross_cutting.tuplets[0].members.clone(); + assert_eq!(members.len(), 3, "the fixture triplet has three members"); + assert!( + base.decomposition_attachments + .iter() + .any(|d| d.components.iter().any(|c| c.tuplet == Some(tuplet))), + "the fixture has an in-tuplet decomposition referencing the triplet" + ); + + // Three deletes in causal order: the structure-removing cascade first, so the + // remaining members then delete as ordinary events. + let mut ops = Vec::new(); + for (i, &member) in members.iter().enumerate() { + let counter = (i + 1) as u64; + let compensation = if i == 0 { + TupletCompensation::CascadeDeleteTuplets { + tuplets: vec![tuplet], + } + } else { + TupletCompensation::NotInTuplet + }; + ops.push(envelope( + 70, + counter, + 10 + i as i64, + CausalContext::new(), + None, + OperationPayload::Primitive(OperationKind::DeleteEvent(DeleteEventOp { + event: member, + tuplet_compensation: compensation, + })), + )); + } + let mut set = OperationSet::new(); + set.accept_all(ops); + let result = set.reduce_onto(&base); + + assert!( + result.score.cross_cutting.tuplets.is_empty(), + "the tuplet structure is removed" + ); + assert!( + !result + .score + .decomposition_attachments + .iter() + .any(|d| d.components.iter().any(|c| c.tuplet == Some(tuplet))), + "the now-orphaned decomposition is pruned" + ); + for &member in &members { + assert!( + matches!( + result.state.objects.get(&TypedObjectId::Event(member)), + Some(epiphany_ops::ObjectState::Tombstoned { .. }) + ), + "each member is tombstoned" + ); + } + assert!(check_invariants(&result.score).is_empty()); +} + /// Helper: the effect recorded for `id` in a reduction. fn effect_of(result: &epiphany_ops::GraphMaterialization, id: OperationId) -> OperationEffect { result @@ -1828,3 +1900,854 @@ fn create_rejects_carried_non_hierarchy_children() { ); assert!(check_invariants(&result.score).is_empty()); } + +// === Re-anchoring rule-table coverage: markers, cue events, comments, +// analytical annotations, graphic gestures (core_spec §"The Re-Anchoring Rule +// Table", §"Total Ordering for Nearest"). All five kinds exist only via seeded +// base graphs (no operation creates them), so every scenario reduces onto a +// base. ======================================================================== + +/// The repairs of an `AppliedWithRepair` effect. +fn repairs_of(result: &epiphany_ops::GraphMaterialization, id: OperationId) -> Vec { + match effect_of(result, id) { + OperationEffect::AppliedWithRepair { repairs } => repairs, + other => panic!("expected AppliedWithRepair, got {other:?}"), + } +} + +/// A plain (non-tuplet) DeleteEvent envelope. +fn delete_event( + replica: u64, + counter: u64, + physical: i64, + ctx: CausalContext, + event: EventId, +) -> OperationEnvelope { + envelope( + replica, + counter, + physical, + ctx, + None, + OperationPayload::Primitive(OperationKind::DeleteEvent(DeleteEventOp { + event, + tuplet_compensation: TupletCompensation::NotInTuplet, + })), + ) +} + +/// The first voice's event list (the fixture voice all these scenarios edit). +fn first_voice_events(base: &Score) -> Vec { + base.canvas.regions[0].staff_instances()[0].voices[0] + .events + .clone() +} + +/// Adds a cue event sourcing `sources` to `base`'s first voice at whole-note +/// `position` (clear of the fixture's quarter-note content in `[0, 1)`). +fn push_cue(base: &mut Score, id: EventId, sources: Vec, position: i32) { + let (_, voice) = target(base); + base.events + .insert(Event::Cue(CueEvent { + id, + voice, + position: EventPosition::Musical(MusicalPosition(RationalTime::from_int(position))), + duration: EventDuration::Musical(MusicalDuration::whole()), + source: sources, + rendering: CueRendering, + })) + .expect("fresh cue id"); + base.canvas.regions[0] + .content + .staff_instances_mut() + .expect("fixture is staff based")[0] + .voices[0] + .events + .push(id); +} + +#[test] +fn deleting_a_cue_source_cascade_deletes_the_cue() { + // Rule table, "Cue event / Source event": cascade-delete ("a cue with no + // source is meaningless") — ledger tombstone, graph removal, and a + // CascadeDeleted repair in the triggering delete's effect, all in the same + // reduction step. + let mut base = epiphany_core::generators::valid_score(100); + let source = first_voice_events(&base)[0]; + let cue = EventId::new(ReplicaId(90), 0); + push_cue(&mut base, cue, vec![source], 40); + + let del = delete_event(91, 0, 10, CausalContext::new(), source); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id) + .iter() + .any(|r| r.kind == RepairKind::CascadeDeleted && r.target == TypedObjectId::Event(cue)), + "the cue cascade is recorded in the triggering delete's effect" + ); + assert!( + matches!( + result.state.objects.get(&TypedObjectId::Event(cue)), + Some(epiphany_ops::ObjectState::Tombstoned { .. }) + ), + "the cue's event id is tombstoned in the ledger" + ); + assert!( + !result.score.events.contains(cue), + "the cue is removed from the event arena" + ); + assert!( + result.score.tombstoned_events.contains(&cue), + "the cue is a graph tombstone" + ); + assert!( + !first_voice_events(&result.score).contains(&cue), + "the cue is removed from its voice" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn a_cue_with_multiple_sources_cascades_on_any_source_deletion() { + // The table's action is the plain "cascade-delete" on a source deletion — + // not truncate-while-any-source-survives (the rationale-vs-action tension + // for multi-source cues is a proposed Pass-12 row). Either source's + // deletion cascades the cue. + for victim_index in [0usize, 1] { + let mut base = epiphany_core::generators::valid_score(100); + let events = first_voice_events(&base); + let cue = EventId::new(ReplicaId(90), 1); + push_cue(&mut base, cue, vec![events[0], events[1]], 40); + + let del = delete_event(91, 0, 10, CausalContext::new(), events[victim_index]); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id) + .iter() + .any(|r| r.kind == RepairKind::CascadeDeleted + && r.target == TypedObjectId::Event(cue)), + "deleting source #{victim_index} cascades the two-source cue" + ); + assert!(!result.score.events.contains(cue)); + assert!(check_invariants(&result.score).is_empty()); + } +} + +#[test] +fn a_cascaded_cue_reanchors_its_own_referents_transitively() { + // A cascaded cue is itself a tombstoned event, so the same re-anchoring + // pass runs over *its* referents in the same reduction step: a cue-of-a-cue + // cascades along. + let mut base = epiphany_core::generators::valid_score(100); + let source = first_voice_events(&base)[0]; + let cue1 = EventId::new(ReplicaId(90), 2); + let cue2 = EventId::new(ReplicaId(90), 3); + push_cue(&mut base, cue1, vec![source], 40); + push_cue(&mut base, cue2, vec![cue1], 44); + + let del = delete_event(91, 0, 10, CausalContext::new(), source); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + let repairs = repairs_of(&result, del.id); + for cue in [cue1, cue2] { + assert!( + repairs + .iter() + .any(|r| r.kind == RepairKind::CascadeDeleted + && r.target == TypedObjectId::Event(cue)), + "cue {cue:?} cascades in the same reduction step" + ); + assert!( + matches!( + result.state.objects.get(&TypedObjectId::Event(cue)), + Some(epiphany_ops::ObjectState::Tombstoned { .. }) + ), + "cue {cue:?} is tombstoned in the ledger" + ); + assert!(!result.score.events.contains(cue)); + } + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn deleting_a_comment_anchor_orphans_the_comment() { + // Rule table, "Comment / Anchor": orphan — user content never silently + // deleted. The comment survives (ledger Live, graph present); its anchor + // degrades to the containing region so invariant 10 keeps holding. + let mut base = epiphany_core::generators::valid_score(100); + let region = base.canvas.regions[0].id; + let anchor_event = first_voice_events(&base)[0]; + let comment_id = CommentId::new(ReplicaId(90), 4); + base.cross_cutting.comments.push(Comment { + id: comment_id, + anchor: AnnotationAnchor::Event(anchor_event), + resolved: false, + }); + + let del = delete_event(91, 0, 10, CausalContext::new(), anchor_event); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id) + .iter() + .any(|r| r.kind == RepairKind::Orphaned + && r.target == TypedObjectId::Comment(comment_id)), + "the orphaning is a recorded repair" + ); + assert_eq!( + result + .state + .objects + .get(&TypedObjectId::Comment(comment_id)), + Some(&epiphany_ops::ObjectState::Live), + "the orphaned comment stays live in the ledger" + ); + let comment = result + .score + .cross_cutting + .comments + .iter() + .find(|c| c.id == comment_id) + .expect("the orphaned comment survives in the graph"); + assert_eq!( + comment.anchor, + AnnotationAnchor::Region(region), + "the dangling event anchor degrades to the containing region" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn annotation_reanchors_to_a_range_preserving_the_events_extent() { + // Rule table, "Analytical annotation / Anchor": re-anchor to a time range + // preserving the original extent. The fixture's second event spans + // [1/4, 1/2), so the reconstructed range is region-start + 1/4 .. + 1/2. + let mut base = epiphany_core::generators::valid_score(100); + let region = base.canvas.regions[0].id; + let anchor_event = first_voice_events(&base)[1]; + let annotation_id = AnalyticalAnnotationId::new(ReplicaId(90), 5); + base.cross_cutting.analytical.push(AnalyticalAnnotation { + id: annotation_id, + anchor: AnnotationAnchor::Event(anchor_event), + layer: None, + }); + + let del = delete_event(91, 0, 10, CausalContext::new(), anchor_event); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id).iter().any(|r| { + r.target == TypedObjectId::AnalyticalAnnotation(annotation_id) + && r.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(anchor_event), + to: TypedObjectId::Region(region), + reason: ReanchorReason::ExplicitFallback, + } + }), + "the range reconstruction is a recorded repair" + ); + let annotation = result + .score + .cross_cutting + .analytical + .iter() + .find(|a| a.id == annotation_id) + .expect("the annotation survives"); + let offset_at = |num: i64, den: i64| { + AnchorOffset::Musical(MusicalDuration(RationalTime::new(num, den).unwrap())) + }; + assert_eq!( + annotation.anchor, + AnnotationAnchor::Range { + start: TimeAnchor::Region { + id: region, + edge: RegionEdge::Start, + offset: offset_at(1, 4), + }, + end: TimeAnchor::Region { + id: region, + edge: RegionEdge::Start, + offset: offset_at(1, 2), + }, + }, + "the reconstructed range covers the deleted event's exact span" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn annotation_orphans_when_the_range_cannot_be_reconstructed() { + // The extent of a wall-clock event is not expressible as a stored + // region-relative range in this prototype (the expressibility gap is a + // proposed Pass-12 row), so the annotation orphans: kept, anchor degraded + // to the containing region. + let mut base = epiphany_core::generators::valid_score_rich(0x5EED); + let (region, wall_clock_event) = base + .voices() + .find_map(|(region, _, v)| { + v.events + .iter() + .copied() + .find(|e| { + matches!( + base.events.get(*e).map(Event::position), + Some(EventPosition::WallClock(_)) + ) + }) + .map(|e| (region, e)) + }) + .expect("the rich fixture has a proportional region with wall-clock events"); + let annotation_id = AnalyticalAnnotationId::new(ReplicaId(90), 6); + base.cross_cutting.analytical.push(AnalyticalAnnotation { + id: annotation_id, + anchor: AnnotationAnchor::Event(wall_clock_event), + layer: None, + }); + + let del = delete_event(91, 0, 10, CausalContext::new(), wall_clock_event); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id) + .iter() + .any(|r| r.kind == RepairKind::Orphaned + && r.target == TypedObjectId::AnalyticalAnnotation(annotation_id)), + "an unreconstructable range orphans the annotation" + ); + let annotation = result + .score + .cross_cutting + .analytical + .iter() + .find(|a| a.id == annotation_id) + .expect("the orphaned annotation survives"); + assert_eq!(annotation.anchor, AnnotationAnchor::Region(region)); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn gesture_event_references_retarget_to_the_nearest_survivor() { + // Rule table, "Graphic gesture / Anchor event": re-anchor to the nearest + // surviving event of the same staff instance. + let mut base = epiphany_core::generators::valid_score(100); + let events = first_voice_events(&base); + let (dead, survivor) = (events[0], events[1]); + let gesture_id = GraphicGestureId::new(ReplicaId(90), 7); + base.cross_cutting.graphic_gestures.push(GraphicGesture { + id: gesture_id, + objects: Vec::new(), + anchoring: GestureAnchoring::Events(vec![dead]), + }); + + let del = delete_event(91, 0, 10, CausalContext::new(), dead); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id).iter().any(|r| { + r.target == TypedObjectId::GraphicGesture(gesture_id) + && r.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(dead), + to: TypedObjectId::Event(survivor), + reason: ReanchorReason::SameVoiceNearer, + } + }), + "the gesture re-target is a recorded repair" + ); + let gesture = result + .score + .cross_cutting + .graphic_gestures + .iter() + .find(|g| g.id == gesture_id) + .expect("the gesture survives"); + assert_eq!( + gesture.anchoring, + GestureAnchoring::Events(vec![survivor]), + "the graph reference list agrees with the recorded repair" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn free_anchored_gestures_ignore_event_deletion() { + // Rule table: "for Free anchoring, no action" — a free gesture follows no + // score content, so the delete reduces with no gesture repair. + let mut base = epiphany_core::generators::valid_score(100); + let dead = first_voice_events(&base)[0]; + let gesture_id = GraphicGestureId::new(ReplicaId(90), 8); + base.cross_cutting.graphic_gestures.push(GraphicGesture { + id: gesture_id, + objects: Vec::new(), + anchoring: GestureAnchoring::Free, + }); + + let del = delete_event(91, 0, 10, CausalContext::new(), dead); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert_eq!( + effect_of(&result, del.id), + OperationEffect::Applied, + "no repair is recorded for a free-anchored gesture" + ); + let gesture = result + .score + .cross_cutting + .graphic_gestures + .iter() + .find(|g| g.id == gesture_id) + .expect("the gesture survives"); + assert_eq!(gesture.anchoring, GestureAnchoring::Free); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn gesture_range_anchoring_truncates_to_the_region_edge() { + // Rule table: "for Range anchoring, truncate" — the deterministic reading: + // a dead start endpoint moves to its region's start edge (an end endpoint + // would move to the end edge); the underdetermined "truncate" semantics is + // a proposed Pass-12 row. + let mut base = epiphany_core::generators::valid_score(100); + let region = base.canvas.regions[0].id; + let dead = first_voice_events(&base)[0]; + let gesture_id = GraphicGestureId::new(ReplicaId(90), 9); + let end_anchor = TimeAnchor::Region { + id: region, + edge: RegionEdge::End, + offset: AnchorOffset::Zero, + }; + base.cross_cutting.graphic_gestures.push(GraphicGesture { + id: gesture_id, + objects: Vec::new(), + anchoring: GestureAnchoring::Range { + start: TimeAnchor::Event { + id: dead, + offset: AnchorOffset::Zero, + }, + end: end_anchor.clone(), + staves: Vec::new(), + }, + }); + + let del = delete_event(91, 0, 10, CausalContext::new(), dead); + let mut set = OperationSet::new(); + set.accept(del.clone()); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id).iter().any(|r| { + r.target == TypedObjectId::GraphicGesture(gesture_id) + && r.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(dead), + to: TypedObjectId::Region(region), + reason: ReanchorReason::ExplicitFallback, + } + }), + "the range truncation is a recorded repair" + ); + let gesture = result + .score + .cross_cutting + .graphic_gestures + .iter() + .find(|g| g.id == gesture_id) + .expect("the gesture survives"); + assert_eq!( + gesture.anchoring, + GestureAnchoring::Range { + start: TimeAnchor::Region { + id: region, + edge: RegionEdge::Start, + offset: AnchorOffset::Zero, + }, + end: end_anchor, + staves: Vec::new(), + }, + "the dead start endpoint moved to the region's start edge" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn marker_reanchor_breaks_full_ties_by_ascending_event_id() { + // Four-key ordering, key 4: with equal proximity rank, distance, and + // direction, the ascending typed-id byte order decides. The referent sits + // alone in its own voice; two candidates in two sibling voices share its + // exact position (rank 1, distance 0, forward) — the smaller EventId wins + // even though it was authored later and lives in the higher-id voice. + let mut base = epiphany_core::generators::valid_score(100); + let (staff_instance, _) = target(&base); + let referent_voice = VoiceId::new(ReplicaId(9), 77); + let voice_b = VoiceId::new(ReplicaId(9), 78); + let voice_c = VoiceId::new(ReplicaId(9), 79); + { + let instances = base.canvas.regions[0] + .content + .staff_instances_mut() + .expect("fixture is staff based"); + instances[0].voices.push(valuegen::voice(referent_voice)); + instances[0].voices.push(valuegen::voice(voice_b)); + instances[0].voices.push(valuegen::voice(voice_c)); + } + let referent = EventId::new(ReplicaId(95), 50); + let larger_id = EventId::new(ReplicaId(95), 9); + let smaller_id = EventId::new(ReplicaId(95), 3); + let marker_id = MarkerId::new(ReplicaId(90), 10); + base.cross_cutting.markers.push(Marker { + id: marker_id, + anchor: TimeAnchor::Event { + id: referent, + offset: AnchorOffset::Zero, + }, + }); + + let ins = |counter: u64, event: EventId, voice: VoiceId, pitch: u64| { + let ctx = if counter == 0 { + CausalContext::new() + } else { + CausalContext::new().with_seen(ReplicaId(95), counter - 1) + }; + envelope( + 95, + counter, + 10 + counter as i64, + ctx, + None, + insert( + staff_instance, + voice, + event, + PitchId::new(ReplicaId(95), 100 + pitch), + 100, + ), + ) + }; + let del = delete_event( + 95, + 3, + 20, + CausalContext::new().with_seen(ReplicaId(95), 2), + referent, + ); + let mut set = OperationSet::new(); + set.accept_all(vec![ + ins(0, referent, referent_voice, 0), + ins(1, larger_id, voice_b, 1), + ins(2, smaller_id, voice_c, 2), + del.clone(), + ]); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, del.id).iter().any(|r| { + r.target == TypedObjectId::Marker(marker_id) + && r.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(referent), + to: TypedObjectId::Event(smaller_id), + reason: ReanchorReason::SameStaffInstanceNearer, + } + }), + "a full tie falls to the ascending typed-id byte order" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn marker_orphans_when_the_staff_instance_has_no_other_live_event() { + // Rule table, "Marker / Anchor": proximity max is the same staff instance, + // orphan on failure. Every event of the marker's staff instance is deleted + // (the anchored one last), so no candidate survives within the bound; the + // marker is kept and its anchor degrades to the region start. + let mut base = epiphany_core::generators::valid_score(100); + let region = base.canvas.regions[0].id; + let instance_events: Vec = base.canvas.regions[0].staff_instances()[0] + .voices + .iter() + .flat_map(|v| v.events.clone()) + .collect(); + let marked = instance_events[0]; + let marker_id = MarkerId::new(ReplicaId(90), 11); + base.cross_cutting.markers.push(Marker { + id: marker_id, + anchor: TimeAnchor::Event { + id: marked, + offset: AnchorOffset::Zero, + }, + }); + + let mut order: Vec = instance_events + .iter() + .copied() + .filter(|e| *e != marked) + .collect(); + order.push(marked); + let ops: Vec = order + .iter() + .enumerate() + .map(|(i, &event)| { + let ctx = if i == 0 { + CausalContext::new() + } else { + CausalContext::new().with_seen(ReplicaId(96), i as u64 - 1) + }; + delete_event(96, i as u64, 10 + i as i64, ctx, event) + }) + .collect(); + let last = ops.last().expect("at least one delete").clone(); + let mut set = OperationSet::new(); + set.accept_all(ops); + let result = set.reduce_onto(&base); + + assert!( + repairs_of(&result, last.id).iter().any(|r| r.kind == RepairKind::Orphaned + && r.target == TypedObjectId::Marker(marker_id)), + "the marker orphans when its staff instance has no other live event" + ); + assert_eq!( + result.state.objects.get(&TypedObjectId::Marker(marker_id)), + Some(&epiphany_ops::ObjectState::Live), + "the orphaned marker stays live in the ledger" + ); + let marker = result + .score + .cross_cutting + .markers + .iter() + .find(|m| m.id == marker_id) + .expect("the orphaned marker survives in the graph"); + assert_eq!( + marker.anchor, + TimeAnchor::Region { + id: region, + edge: RegionEdge::Start, + offset: AnchorOffset::Zero, + }, + "the dangling anchor degrades to the region start" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn slur_reanchor_reason_names_the_survivors_containment_rank() { + // The Reanchored reason on a slur's surviving-endpoint collapse names the + // survivor's actual containment proximity to the tombstoned endpoint — + // same voice → SameVoiceNearer, sibling voice in the same staff instance → + // SameStaffInstanceNearer — instead of a hardcoded same-voice claim. + let mut base = epiphany_core::generators::valid_score(100); + let (staff_instance, voice_a) = target(&base); + let voice_b = VoiceId::new(ReplicaId(9), 80); + base.canvas.regions[0] + .content + .staff_instances_mut() + .expect("fixture is staff based")[0] + .voices + .push(valuegen::voice(voice_b)); + + let r = 97; + let e1 = EventId::new(ReplicaId(r), 0); + let e2 = EventId::new(ReplicaId(r), 1); + let e3 = EventId::new(ReplicaId(r), 2); + let cross_slur = SlurId::new(ReplicaId(r), 10); + let same_slur = SlurId::new(ReplicaId(r), 11); + let step = |counter: u64, payload: OperationPayload| { + let ctx = if counter == 0 { + CausalContext::new() + } else { + CausalContext::new().with_seen(ReplicaId(r), counter - 1) + }; + envelope(r, counter, 10 + counter as i64, ctx, None, payload) + }; + let create = |slur: SlurId, a: EventId, b: EventId| { + OperationPayload::Primitive(OperationKind::CreateCrossCutting(CreateCrossCuttingOp { + structure: CrossCuttingValue::Slur(valuegen::slur(slur, a, b)), + })) + }; + let del = step( + 5, + OperationPayload::Primitive(OperationKind::DeleteEvent(DeleteEventOp { + event: e1, + tuplet_compensation: TupletCompensation::NotInTuplet, + })), + ); + let mut set = OperationSet::new(); + set.accept_all(vec![ + step( + 0, + insert( + staff_instance, + voice_a, + e1, + PitchId::new(ReplicaId(r), 100), + 100, + ), + ), + step( + 1, + insert( + staff_instance, + voice_b, + e2, + PitchId::new(ReplicaId(r), 101), + 101, + ), + ), + step( + 2, + insert( + staff_instance, + voice_a, + e3, + PitchId::new(ReplicaId(r), 102), + 102, + ), + ), + step(3, create(cross_slur, e1, e2)), + step(4, create(same_slur, e3, e1)), + del.clone(), + ]); + let result = set.reduce_onto(&base); + + let repairs = repairs_of(&result, del.id); + assert!( + repairs.iter().any(|rec| { + rec.target == TypedObjectId::Slur(cross_slur) + && rec.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(e1), + to: TypedObjectId::Event(e2), + reason: ReanchorReason::SameStaffInstanceNearer, + } + }), + "a sibling-voice survivor is SameStaffInstanceNearer: {repairs:?}" + ); + assert!( + repairs.iter().any(|rec| { + rec.target == TypedObjectId::Slur(same_slur) + && rec.kind + == RepairKind::Reanchored { + from: TypedObjectId::Event(e1), + to: TypedObjectId::Event(e3), + reason: ReanchorReason::SameVoiceNearer, + } + }), + "a same-voice survivor is SameVoiceNearer: {repairs:?}" + ); + assert!(check_invariants(&result.score).is_empty()); +} + +#[test] +fn referent_reanchoring_is_permutation_invariant() { + // The new rule-table rows are functions of canonical order and canonical + // state: a marker re-anchor (with distance and direction tie-breaks), a + // cue cascade, and a comment orphan reduce to byte-identical materialized + // state under any delivery permutation. + let mut base = epiphany_core::generators::valid_score(100); + let (staff_instance, voice_a) = target(&base); + let source = first_voice_events(&base)[0]; + let cue = EventId::new(ReplicaId(90), 20); + push_cue(&mut base, cue, vec![source], 40); + let comment_id = CommentId::new(ReplicaId(90), 21); + base.cross_cutting.comments.push(Comment { + id: comment_id, + anchor: AnnotationAnchor::Event(source), + resolved: false, + }); + let referent = EventId::new(ReplicaId(98), 1); + let marker_id = MarkerId::new(ReplicaId(90), 22); + base.cross_cutting.markers.push(Marker { + id: marker_id, + anchor: TimeAnchor::Event { + id: referent, + offset: AnchorOffset::Zero, + }, + }); + + let ins = |counter: u64, event: u64, position: i32| { + let ctx = if counter == 0 { + CausalContext::new() + } else { + CausalContext::new().with_seen(ReplicaId(98), counter - 1) + }; + envelope( + 98, + counter, + 10 + counter as i64, + ctx, + None, + insert( + staff_instance, + voice_a, + EventId::new(ReplicaId(98), event), + PitchId::new(ReplicaId(98), 100 + event), + position, + ), + ) + }; + let envelopes = vec![ + ins(0, 0, 10), + ins(1, 1, 12), + ins(2, 2, 14), + delete_event( + 98, + 3, + 20, + CausalContext::new().with_seen(ReplicaId(98), 2), + referent, + ), + delete_event( + 98, + 4, + 21, + CausalContext::new().with_seen(ReplicaId(98), 3), + source, + ), + ]; + + let mut reference_set = OperationSet::new(); + reference_set.accept_all(envelopes.clone()); + let reference = reference_set.reduce_onto(&base); + assert!(check_invariants(&reference.score).is_empty()); + // Non-vacuity: all three rows actually fired. + assert!(!reference.score.events.contains(cue), "the cue cascaded"); + let permutations: [[usize; 5]; 4] = [ + [4, 3, 2, 1, 0], + [2, 4, 0, 3, 1], + [3, 0, 4, 1, 2], + [1, 2, 3, 4, 0], + ]; + for (k, permutation) in permutations.iter().enumerate() { + let mut set = OperationSet::new(); + set.accept_all(permutation.iter().map(|&i| envelopes[i].clone())); + let got = set.reduce_onto(&base); + assert_eq!( + got, reference, + "delivery permutation #{k} changed the materialized graph" + ); + assert_eq!( + got.state.canonical_bytes(), + reference.state.canonical_bytes(), + "delivery permutation #{k} changed the canonical bytes" + ); + } +} diff --git a/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.engrave.snapshot.txt b/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.engrave.snapshot.txt index 6d1fdab..c082312 100644 --- a/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.engrave.snapshot.txt +++ b/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.engrave.snapshot.txt @@ -5,7 +5,7 @@ fallback_rect_count=0 stroke_count=91 provenance_count=142 layer_count=1 -hard_constraint_count=0 +hard_constraint_count=90 xml_well_formed=true view_box=[-3.059857 -3.632 102.98304 11.024] class_counts: diff --git a/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.stub.snapshot.txt b/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.stub.snapshot.txt index 363ec67..91ab969 100644 --- a/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.stub.snapshot.txt +++ b/crates/epiphany-render-svg/tests/golden/ten_measure_single_staff.stub.snapshot.txt @@ -5,7 +5,7 @@ fallback_rect_count=0 stroke_count=91 provenance_count=142 layer_count=1 -hard_constraint_count=0 +hard_constraint_count=90 xml_well_formed=true view_box=[-3.065 -3.632 88.87701 11.024] class_counts: diff --git a/crates/epiphany-render-svg/tests/golden/valid_score_rich.engrave.snapshot.txt b/crates/epiphany-render-svg/tests/golden/valid_score_rich.engrave.snapshot.txt index caa35f9..ba9c1ea 100644 --- a/crates/epiphany-render-svg/tests/golden/valid_score_rich.engrave.snapshot.txt +++ b/crates/epiphany-render-svg/tests/golden/valid_score_rich.engrave.snapshot.txt @@ -5,7 +5,7 @@ fallback_rect_count=0 stroke_count=38 provenance_count=49 layer_count=1 -hard_constraint_count=0 +hard_constraint_count=15 xml_well_formed=true view_box=[-3.1598568 -3.632 31.588375 11.024] class_counts: diff --git a/crates/epiphany-render-svg/tests/golden/valid_score_rich.stub.snapshot.txt b/crates/epiphany-render-svg/tests/golden/valid_score_rich.stub.snapshot.txt index 6597dcb..de82ec7 100644 --- a/crates/epiphany-render-svg/tests/golden/valid_score_rich.stub.snapshot.txt +++ b/crates/epiphany-render-svg/tests/golden/valid_score_rich.stub.snapshot.txt @@ -5,7 +5,7 @@ fallback_rect_count=0 stroke_count=38 provenance_count=49 layer_count=1 -hard_constraint_count=0 +hard_constraint_count=15 xml_well_formed=true view_box=[-3.065 -3.632 39.329998 11.024] class_counts: diff --git a/crates/epiphany-testkit/src/bundle_harness.rs b/crates/epiphany-testkit/src/bundle_harness.rs index bc3655c..d869818 100644 --- a/crates/epiphany-testkit/src/bundle_harness.rs +++ b/crates/epiphany-testkit/src/bundle_harness.rs @@ -14,10 +14,14 @@ //! > generation when the crash precedes the durable flush. use epiphany_bundle::{ - pack_operation_blocks, Bundle, CommitContext, CrashPoint, DocumentId, FaultStore, FileUuid, - Manifest, MemStore, Slot, StagedChunk, Tear, + encode_block, envelope_offsets, pack_operation_blocks, BlockStore, Bundle, BundleError, + CommitContext, CrashPoint, DocumentId, ExtensionDeclaration, ExtensionId, FaultStore, FileUuid, + IndexedBlock, Manifest, MemStore, OperationIndex, SemVer, Slot, StagedChunk, Tear, }; +use epiphany_determinism::CanonicalEncode; +use epiphany_ops::{peek_operation_id, OperationEnvelope}; +use crate::generators; use crate::rng::Rng; // --- Re-exported authoritative gates from Agent D -------------------------- @@ -233,10 +237,419 @@ pub fn run_manifest_selection(seed: u64) { assert_selection_through_commits(seed); } +// --- The operation-index harness (Chapter 8 §"The Operation Index") -------- +// +// The C/D seam: `epiphany-ops` vouches that a canonical envelope *leads* with +// its 16 operation-id bytes (`peek_operation_id`); the bundle records those +// raw bytes against `(block ChunkRef, offset-in-decoded-payload)` coordinates +// (`envelope_offsets` + `OperationIndex`) without ever interpreting an +// envelope. The index is an acceleration structure, not canonical: absent → +// rebuild by scanning blocks; present but stale or corrupt → reject and +// rebuild, never bundle corruption. + +/// Stages real canonical envelope encodings into operation blocks of at most +/// `per_block` envelopes each (forcing a multi-block layout regardless of the +/// 1 MiB soft target, so index ordinals are actually exercised). +fn staged_envelope_blocks(envelopes: &[OperationEnvelope], per_block: usize) -> Vec { + envelopes + .chunks(per_block) + .map(|group| { + let payloads: Vec> = group.iter().map(|e| e.to_canonical_bytes()).collect(); + StagedChunk::operation_block(encode_block(&payloads)) + }) + .collect() +} + +/// The reader-side rebuild the spec mandates when no usable index exists: +/// scan every operation block the manifest references, recover each +/// envelope's `(offset, bytes)` with [`envelope_offsets`], peek the leading +/// operation-id bytes with ops' [`peek_operation_id`], and build a fresh +/// [`OperationIndex`]. The same procedure serves the writer at commit time +/// (the spec's SHOULD-rebuild-on-commit), from the committed block refs. +pub fn scan_rebuild_operation_index(bundle: &Bundle) -> OperationIndex { + let blocks: Vec = bundle + .manifest() + .operation_roots + .iter() + .map(|root| { + let payload = bundle.read_chunk(root).expect("operation block reads"); + let entries = envelope_offsets(&payload) + .expect("a committed block payload decodes") + .into_iter() + .map(|(offset, bytes)| { + let id = peek_operation_id(bytes) + .expect("a canonical envelope leads with its 16 id bytes"); + (id.canonical_bytes(), offset) + }) + .collect(); + (*root, entries) + }) + .collect(); + OperationIndex::build(&blocks).expect("scanned blocks build a valid index") +} + +/// Commits `index` as an operation-index chunk and wires it into the +/// manifest's `operation_index_root` — the writer's commit-time update. +fn commit_index(bundle: &mut Bundle, index: &OperationIndex) { + bundle + .commit(&[StagedChunk::operation_index(index.encode())], |ctx| { + let mut m = ctx.previous_manifest.clone(); + m.operation_index_root = Some(ctx.new_chunks[0]); + m + }) + .expect("commit operation index"); +} + +/// Locates every envelope through the index and verifies each `(block, +/// offset)` coordinate addresses exactly that envelope's canonical bytes in +/// the block's decoded payload — plus a miss for an id no envelope uses. +fn assert_index_locates_all( + bundle: &Bundle, + index: &OperationIndex, + envelopes: &[OperationEnvelope], +) { + for env in envelopes { + let id = env.id.canonical_bytes(); + let (block_ref, offset) = index + .locate(&id) + .unwrap_or_else(|| panic!("operation {:?} missing from the index", env.id)); + let payload = bundle.read_chunk(block_ref).expect("indexed block reads"); + let pairs = envelope_offsets(&payload).expect("indexed block payload decodes"); + let (_, bytes) = pairs + .iter() + .find(|(off, _)| *off == offset) + .expect("the indexed offset lands on an envelope boundary"); + assert_eq!( + *bytes, + env.to_canonical_bytes().as_slice(), + "the (block, offset) coordinate must address exactly this envelope's bytes" + ); + // The bundle-opaque bytes really lead with this operation's id — the + // ops-side half of the seam. + assert_eq!(peek_operation_id(bytes), Some(env.id)); + // The kind-checked block read path sees the same envelope. + let envs = bundle + .read_operation_block(block_ref) + .expect("kind-checked block read"); + assert!(envs.iter().any(|e| e.as_slice() == *bytes)); + } + assert_eq!( + index.locate(&[0xFF; 16]), + None, + "an id no envelope uses must miss" + ); +} + +/// End-to-end: generate real envelopes, pack multi-block, commit, build the +/// index at commit time and wire it into `operation_index_root`, reopen, and +/// verify the index is usable and locates every operation at its exact bytes. +pub fn assert_operation_index_end_to_end(seed: u64) { + let mut rng = Rng::new(seed); + let envelopes = generators::operation_envelopes(&mut rng, 36, 3, 8, 8); + let uuid = FileUuid(rng.array16()); + let doc = DocumentId(rng.array16()); + let mut bundle = + Bundle::create(MemStore::new(), uuid, Manifest::empty(doc)).expect("create bundle"); + bundle + .commit(&staged_envelope_blocks(&envelopes, 12), append_roots) + .expect("commit operation blocks"); + + // Writer side: rebuild the index at commit time from the committed block + // refs (the spec's SHOULD) and reference it from the manifest. + let index = scan_rebuild_operation_index(&bundle); + assert!( + index.blocks().len() >= 2, + "the fixture must span multiple blocks to exercise ordinals" + ); + assert_eq!(index.entries().len(), envelopes.len()); + commit_index(&mut bundle, &index); + + // Reader side: reopen from the durable image; the fresh index is usable + // and locates every operation. + let image = bundle.into_store().into_bytes(); + let reopened = Bundle::open(MemStore::from_bytes(image)).expect("reopen"); + let usable = reopened + .usable_operation_index() + .expect("a fresh, covering index is usable"); + assert_eq!(usable, index, "the index round-trips through storage"); + assert_index_locates_all(&reopened, &usable, &envelopes); +} + +/// A commit that grows the operation set *without* updating the index leaves +/// a stale index: intact as a chunk, but no longer covering the operation +/// roots. Readers must reject it (`usable_operation_index` → `None`) and a +/// scan-rebuild must produce a fresh valid index (spec §"The Operation +/// Index": present but stale → reject and rebuild from blocks). +pub fn assert_stale_operation_index_rejected_and_rebuilt(seed: u64) { + let mut rng = Rng::new(seed); + // One authoring session, so ids are unique across both phases. + let envelopes = generators::operation_envelopes(&mut rng, 48, 3, 8, 8); + let (first, later) = envelopes.split_at(36); + + let uuid = FileUuid(rng.array16()); + let doc = DocumentId(rng.array16()); + let mut bundle = + Bundle::create(MemStore::new(), uuid, Manifest::empty(doc)).expect("create bundle"); + bundle + .commit(&staged_envelope_blocks(first, 12), append_roots) + .expect("commit first blocks"); + let index = scan_rebuild_operation_index(&bundle); + commit_index(&mut bundle, &index); + assert!(bundle.usable_operation_index().is_some()); + + // Grow the operation set WITHOUT updating the index (the closure carries + // the old `operation_index_root` forward). + bundle + .commit(&staged_envelope_blocks(later, 6), append_roots) + .expect("commit later blocks"); + let root = bundle + .manifest() + .operation_index_root + .expect("the stale index is still referenced"); + // The chunk itself is intact — readable and well-formed — + let stale = bundle + .read_operation_index(&root) + .expect("the stale index chunk still reads and decodes"); + // — but STALE: its block set no longer equals the operation roots. + assert!(!stale.covers(&bundle.manifest().operation_roots)); + assert!( + bundle.usable_operation_index().is_none(), + "a stale index must be rejected" + ); + + // The same verdict from a cold reopen; then rebuild from blocks. + let image = bundle.into_store().into_bytes(); + let mut reopened = Bundle::open(MemStore::from_bytes(image)).expect("reopen"); + assert!(reopened.usable_operation_index().is_none()); + let rebuilt = scan_rebuild_operation_index(&reopened); + commit_index(&mut reopened, &rebuilt); + let usable = reopened + .usable_operation_index() + .expect("the rebuilt index is usable"); + assert_eq!(usable, rebuilt); + assert_index_locates_all(&reopened, &usable, &envelopes); +} + +/// A defective operation index — a garbage payload staged as the index chunk, +/// or on-disk corruption of a valid index chunk's bytes — must be rejected +/// *without* being treated as bundle corruption (Chapter 8 §"Canonical and +/// Non-Canonical Manifest Roots"): the bundle still opens cleanly, canonical +/// chunks verify, canonical reads work, and only `usable_operation_index` +/// says `None` (rebuild from blocks). +pub fn assert_corrupt_operation_index_is_not_bundle_corruption(seed: u64) { + let mut rng = Rng::new(seed); + let envelopes = generators::operation_envelopes(&mut rng, 24, 3, 8, 8); + let uuid = FileUuid(rng.array16()); + let doc = DocumentId(rng.array16()); + let mut bundle = + Bundle::create(MemStore::new(), uuid, Manifest::empty(doc)).expect("create bundle"); + bundle + .commit(&staged_envelope_blocks(&envelopes, 8), append_roots) + .expect("commit operation blocks"); + + // (a) A garbage index chunk, staged and referenced like a real one. The + // commit succeeds (the bundle does not interpret non-canonical chunks); + // readers must reject it and rebuild. + bundle + .commit( + &[StagedChunk::operation_index(b"not an index".to_vec())], + |ctx| { + let mut m = ctx.previous_manifest.clone(); + m.operation_index_root = Some(ctx.new_chunks[0]); + m + }, + ) + .expect("commit garbage index chunk"); + let image = bundle.into_store().into_bytes(); + let mut reopened = Bundle::open(MemStore::from_bytes(image)) + .expect("a defective index must not prevent opening"); + assert!(reopened.anomalies().is_empty()); + assert!(!reopened.is_read_only()); + reopened + .verify_canonical_chunks() + .expect("canonical chunks are intact"); + assert!( + reopened.usable_operation_index().is_none(), + "a malformed index is rejected: rebuild, not corruption" + ); + for root in &reopened.manifest().operation_roots.clone() { + reopened + .read_operation_block(root) + .expect("canonical block reads are unaffected"); + } + // Rebuild-from-blocks restores a usable index. + let rebuilt = scan_rebuild_operation_index(&reopened); + commit_index(&mut reopened, &rebuilt); + let usable = reopened + .usable_operation_index() + .expect("the rebuilt index is usable"); + assert_index_locates_all(&reopened, &usable, &envelopes); + + // (b) On-disk corruption of the now-valid index chunk's payload region. + let valid_image = reopened.into_store().into_bytes(); + let probe = Bundle::open(MemStore::from_bytes(valid_image.clone())).expect("reopen"); + let root = probe + .manifest() + .operation_index_root + .expect("the index is referenced"); + let mut corrupt = valid_image; + corrupt[(root.offset + 3) as usize] ^= 0xFF; + let reopened = Bundle::open(MemStore::from_bytes(corrupt)) + .expect("index-region corruption must not prevent opening"); + assert!(reopened.anomalies().is_empty()); + reopened + .verify_canonical_chunks() + .expect("canonical chunks are intact"); + // The raw read surfaces the hash defect for diagnostics … + assert!( + matches!( + reopened.read_operation_index(&root), + Err(BundleError::ChunkHashMismatch { .. }) + ), + "the raw index read reports the hash mismatch" + ); + // … while the reject-and-rebuild gate simply declares it unusable. + assert!(reopened.usable_operation_index().is_none()); + for root in &reopened.manifest().operation_roots { + reopened + .read_operation_block(root) + .expect("canonical block reads are unaffected"); + } +} + +// --- The edit-barrier declaration harness (Chapter 8 §"Forward Compatibility +// and Edit Barriers" / §"Behavior Under Unknown Extensions") ------------------ + +/// The end-to-end edit-barrier round-trip: a manifest [`ExtensionDeclaration`] +/// carrying *really-encoded* barrier blobs (the provisional canonical byte +/// form owned by `epiphany-layout-ir`) commits, reopens byte-verbatim — the +/// bundle preserves the blobs opaquely, exactly as it preserves unknown +/// extension chunks — decodes through the owning layer's codec, and +/// *evaluates*: the reopened barrier prohibits exactly the edits the authored +/// one did. +pub fn run_barrier_declaration_roundtrip(seed: u64) { + use epiphany_core::{EventId, TypedObjectId}; + use epiphany_layout_ir::{ + decode_affected_object_kinds, decode_edit_barriers, encode_affected_object_kinds, + encode_edit_barriers, AlwaysLiveOracle, BarrierCondition, BarrierScope, EditBarrier, + EditContext, ObjectKind, OperationKindTag, + }; + + let mut rng = Rng::new(seed); + let protected = TypedObjectId::Event(EventId::from_raw(rng.next_u64() as u128)); + // One deterministic barrier the evaluation half asserts against, plus one + // generated barrier so arbitrary shapes ride the same declaration. + let locked_barrier = EditBarrier { + scope: BarrierScope::ObjectSet(vec![protected]), + affected_object_kinds: vec![ObjectKind::of(&protected)], + prohibited_operation_kinds: vec![OperationKindTag::DeleteEvent], + condition: BarrierCondition::Always, + }; + let authored = vec![ + locked_barrier.clone(), + crate::layout_stub::gen_edit_barrier(&mut rng), + ]; + let kinds = vec![ObjectKind::of(&protected)]; + + let declaration = ExtensionDeclaration { + extension_id: ExtensionId(rng.array16()), + version: SemVer { + major: 1, + minor: 0, + patch: 0, + }, + required: false, + preserved_chunk_roots: Vec::new(), + affected_object_kinds: encode_affected_object_kinds(&kinds), + edit_barriers: encode_edit_barriers(&authored), + }; + let extension_id = declaration.extension_id; + let barrier_bytes = declaration.edit_barriers.clone(); + let kind_bytes = declaration.affected_object_kinds.clone(); + + // Commit a manifest carrying the declaration; reopen from the raw image. + let uuid = FileUuid(rng.array16()); + let doc = DocumentId(rng.array16()); + let mut bundle = + Bundle::create(MemStore::new(), uuid, Manifest::empty(doc)).expect("create bundle"); + bundle + .commit(&staged(&[rng.byte_vec(1, 40)]), |ctx| { + let mut m = append_roots(ctx); + m.extension_declarations.push(declaration.clone()); + m + }) + .expect("commit the declaration"); + let image = bundle.into_store().into_bytes(); + let reopened = Bundle::open(MemStore::from_bytes(image)).expect("reopen"); + + // The bundle preserved the opaque blobs verbatim ... + let decl = reopened + .manifest() + .extension_declarations + .iter() + .find(|d| d.extension_id == extension_id) + .expect("the declaration survives the commit"); + assert_eq!( + decl.edit_barriers, barrier_bytes, + "barrier blob is verbatim" + ); + assert_eq!( + decl.affected_object_kinds, kind_bytes, + "object-kind blob is verbatim" + ); + + // ... the owning layer's codec decodes them, re-encoding byte-identically ... + let decoded = decode_edit_barriers(&decl.edit_barriers).expect("the canonical blob decodes"); + assert_eq!( + encode_edit_barriers(&decoded), + barrier_bytes, + "decode → re-encode is byte-identical" + ); + assert_eq!( + decode_affected_object_kinds(&decl.affected_object_kinds).expect("kinds decode"), + kinds + ); + + // ... and the reopened barrier evaluates as authored: deleting the + // protected event is prohibited; a different operation class and a + // different object are not. + let reopened_barrier = decoded + .iter() + .find(|b| **b == locked_barrier) + .expect("the locked barrier survives the round-trip"); + let ctx = EditContext::default(); + assert!(reopened_barrier.prohibits_edit( + OperationKindTag::DeleteEvent, + &protected, + &ctx, + &AlwaysLiveOracle + )); + assert!(!reopened_barrier.prohibits_edit( + OperationKindTag::InsertEvent, + &protected, + &ctx, + &AlwaysLiveOracle + )); + let other = TypedObjectId::Event(EventId::from_raw(u128::MAX)); + assert!(!reopened_barrier.prohibits_edit( + OperationKindTag::DeleteEvent, + &other, + &ctx, + &AlwaysLiveOracle + )); +} + #[cfg(test)] mod tests { use super::*; + #[test] + fn barrier_declaration_roundtrip() { + for seed in 0..8u64 { + run_barrier_declaration_roundtrip(0xBA22_1E20_0000 + seed); + } + } + #[test] fn crash_recovery_smoke() { run_crash_recovery(400, 0xF00D_BEEF_1234_5678); @@ -253,4 +666,19 @@ mod tests { fn manifest_selection_passes() { run_manifest_selection(7); } + + #[test] + fn operation_index_end_to_end() { + assert_operation_index_end_to_end(0x0091_D0EC_5EED_0001); + } + + #[test] + fn stale_operation_index_is_rejected_and_rebuilt() { + assert_stale_operation_index_rejected_and_rebuilt(0x0091_D0EC_5EED_0002); + } + + #[test] + fn corrupt_operation_index_is_not_bundle_corruption() { + assert_corrupt_operation_index_is_not_bundle_corruption(0x0091_D0EC_5EED_0003); + } } diff --git a/crates/epiphany-testkit/src/layout_stub.rs b/crates/epiphany-testkit/src/layout_stub.rs index dfc8365..45bf6f6 100644 --- a/crates/epiphany-testkit/src/layout_stub.rs +++ b/crates/epiphany-testkit/src/layout_stub.rs @@ -727,6 +727,17 @@ pub fn gen_layout_constraint(rng: &mut Rng) -> LayoutConstraint { } } +/// A constraint strength (both variants). +pub fn gen_constraint_strength(rng: &mut Rng) -> ConstraintStrength { + if rng.boolean() { + ConstraintStrength::Required + } else { + ConstraintStrength::Preferred { + weight: (rng.range(1, 1_000) as f64) / 100.0, + } + } +} + /// A bundled glyph metric (drawn from the in-tree Bravura table). pub fn gen_glyph_metric(rng: &mut Rng) -> GlyphMetric { BRAVURA_METRICS[rng.below(BRAVURA_METRICS.len() as u64) as usize].clone() @@ -790,6 +801,21 @@ pub fn gen_override_target(rng: &mut Rng) -> OverrideTarget { } } +/// A break anchor for a generated break override (a representative subset: a +/// wall-clock instant or an event anchor without offset). +pub fn gen_break_anchor(rng: &mut Rng) -> epiphany_core::TimeAnchor { + if rng.boolean() { + epiphany_core::TimeAnchor::WallClock { + time: epiphany_core::WallClockTime(rng.range(0, 10_000) as i64), + } + } else { + epiphany_core::TimeAnchor::Event { + id: epiphany_core::EventId::from_raw(rng.next_u64() as u128), + offset: epiphany_core::AnchorOffset::Zero, + } + } +} + pub fn gen_override_kind(rng: &mut Rng) -> OverrideKind { match rng.below(9) { 0 => OverrideKind::StemDirection(if rng.boolean() { @@ -799,8 +825,12 @@ pub fn gen_override_kind(rng: &mut Rng) -> OverrideKind { }), 1 => OverrideKind::AccidentalParenthesized(rng.boolean()), 2 => OverrideKind::AccidentalVisible(rng.boolean()), - 3 => OverrideKind::SystemBreak, - 4 => OverrideKind::PageBreak, + 3 => OverrideKind::SystemBreak { + anchor: gen_break_anchor(rng), + }, + 4 => OverrideKind::PageBreak { + anchor: gen_break_anchor(rng), + }, 5 => OverrideKind::HiddenObject, 6 => OverrideKind::CustomPosition(gen_point(rng)), 7 => OverrideKind::LedgerLineSuppression, @@ -1286,6 +1316,43 @@ mod tests { use epiphany_core::TypedObjectId; use epiphany_determinism::CanonicalEncode; + #[test] + fn edit_barrier_blob_codec_round_trips_generated_barriers() { + // Property gate for the provisional manifest-blob byte form + // (`ExtensionDeclaration.edit_barriers` / `.affected_object_kinds`): + // any generated barrier set encodes to a blob that decodes and + // re-encodes byte-identically, and each decoded barrier's own canonical + // bytes round-trip through the single-barrier decoder. + let mut rng = Rng::new(0xBA22_1E2C_0DEC); + for _ in 0..256 { + let barriers: Vec = (0..rng.range_usize(0, 4)) + .map(|_| gen_edit_barrier(&mut rng)) + .collect(); + let blob = encode_edit_barriers(&barriers); + let decoded = decode_edit_barriers(&blob).expect("a canonical blob decodes"); + assert_eq!( + encode_edit_barriers(&decoded), + blob, + "decode → re-encode is byte-identical" + ); + for barrier in &decoded { + let bytes = barrier.to_canonical_bytes(); + assert_eq!( + EditBarrier::decode_canonical_bytes(&bytes).as_ref(), + Ok(barrier) + ); + } + + let kinds: Vec = (0..rng.range_usize(0, 6)) + .map(|_| gen_object_kind(&mut rng)) + .collect(); + let kind_blob = encode_affected_object_kinds(&kinds); + let decoded_kinds = + decode_affected_object_kinds(&kind_blob).expect("a canonical blob decodes"); + assert_eq!(encode_affected_object_kinds(&decoded_kinds), kind_blob); + } + } + #[test] fn ir_generators_are_deterministic_and_well_formed() { let mut a = Rng::new(13); @@ -1295,11 +1362,14 @@ mod tests { let generated = gen_logical_layout_ir(&mut Rng::new(14)); let constrained = try_to_constrained(&generated) .expect("generated logical IR must be structurally transformable"); + // The spacing stage emits real constraints, which the stub does not + // evaluate: the solve is renderable either way, and satisfaction is + // claimed exactly when the problem is constraint-free. + let report = StubSolver.solve(&constrained, &SolverConfig::default()); + assert!(report.status.is_renderable()); assert_eq!( - StubSolver - .solve(&constrained, &SolverConfig::default()) - .status, - SolveStatus::Solved + report.satisfied_hard_constraints, + constrained.constraints.is_empty() ); // Provenance ids are consistent with their synthesis: a projected one // (no synthesis) carries the source-only id; a synthesized one does not. @@ -1404,6 +1474,7 @@ mod tests { let _ = gen_spring_slot(&mut rng); let _ = gen_constrained_layout_region(&mut rng); let _ = gen_layout_constraint(&mut rng); + let _ = gen_constraint_strength(&mut rng); let _ = gen_engraving_override(&mut rng); let _ = gen_resolved_staff(&mut rng); let _ = gen_resolved_measure(&mut rng); diff --git a/crates/epiphany-testkit/src/prepass_harness.rs b/crates/epiphany-testkit/src/prepass_harness.rs index f02d980..2e7e2a4 100644 --- a/crates/epiphany-testkit/src/prepass_harness.rs +++ b/crates/epiphany-testkit/src/prepass_harness.rs @@ -229,11 +229,14 @@ pub fn assert_decompositions_reconstruct(score: &Score, ann: &DerivedAnnotations ); } - // Map and taxonomy count agree. + // Map and taxonomy counts agree: the effective map is exactly the inferred + // plus authored-override outcomes (an authored `DecompositionAttachment` + // outranking `Inferred` replaces the derived one and is counted + // distinctly, mirroring the spelling buckets). assert_eq!( ann.decompositions.len(), - ann.taxonomy.decompositions_inferred, - "decomposition map size disagrees with the taxonomy count" + ann.taxonomy.decompositions_inferred + ann.taxonomy.decompositions_authored, + "decomposition map size disagrees with the taxonomy counts" ); } diff --git a/spec/PASS12_BATCH.md b/spec/PASS12_BATCH.md index 0ce1d4f..2f2e2e8 100644 --- a/spec/PASS12_BATCH.md +++ b/spec/PASS12_BATCH.md @@ -42,11 +42,30 @@ code instead is the failure mode this batch exists to prevent. | P12-H7 | `epiphany-core` H | Authored decompositions for inference-ineligible events: an authored attachment is exactly how a user would notate an *ungriddable* event, but the derived-annotation surface (mirroring spelling, which likewise ignores attachments on spelling-unavailable pitches) only resolves overrides where inferred output exists. Needs a spec answer for both pre-passes. | G / Pass 12 (pre-passes) | | P12-K3 | `epiphany-ops` K | Content modification of a `SYSTEM_DERIVED` pitch: `ModifyEvent`/`ModifyIdentifiedPitch` can rewrite a synthetic pitch's intrinsic content in place, silently invalidating the id's content-derivation (Invariant 11). The new reduction-time collision check deliberately does not treat in-place rewrites as mints. Decide whether reduction must refuse them outright. | G / Pass 12 (identity) | | P12-K4 | `epiphany-ops` K | `ResolveConflict` beyond the concurrent case: the spec pins outcomes only for *concurrent* differing resolves; the implementation applies the same rule to causally-later resolves (so an intentional re-resolution cannot supersede) and reads `AlreadyApplied` for any resolve against a `Dismissed` conflict. Also: the meta-conflict record cannot name the contested conflict in `affected_objects` because `TypedObjectId` has no Conflict kind. Pin the causally-later semantics and decide whether conflict records need an addressable object kind. | G / Pass 12 (conflict resolution) | +| P12-C1 | `epiphany-ops` C | Multi-source cue re-anchoring: the rule table's action is plain "cascade-delete" (implemented: any source deletion cascades, like Tie) but its rationale ("a cue with no source is meaningless") implies truncate-while-any-source-survives. Pin one reading. | G / Pass 12 (re-anchoring) | +| P12-C2 | `epiphany-ops` C | Graphic-gesture Range "truncate" is underdetermined. Implemented reading: a dead event-anchored range endpoint moves to its containing region's edge (start→Start, end→End, zero offset). Define "truncate" normatively. | G / Pass 12 (re-anchoring) | +| P12-C3 | `epiphany-ops` C | Analytical-annotation range reconstruction: a wall-clock (region-relative) or indeterminate event span cannot be expressed as a stored `Range` anchor without region-origin resolution, so such annotations orphan. State whether orphaning is the sanctioned outcome or an expressible form is required. | G / Pass 12 (re-anchoring) | +| P12-C4 | `epiphany-ops` C | `ReanchorReason` has no same-canvas variant: a rank-4 (same-canvas) survivor is recorded `ExplicitFallback` rather than appending a discriminant. Ratify a beyond-region reason or bless the fallback recording. | G / Pass 12 (re-anchoring) | +| P12-K5 | `epiphany-ops` K | Equivocation resolution's third path — a profile-declared deterministic selection function (e.g. lowest-hash-wins) — is unpinned and unimplemented; the reducer has no policy hook. Referenced from the catalog §ResolveEquivocation rationale. | G / Pass 12 (equivocation) | +| P12-K6 | `epiphany-ops` K | `ResolveEquivocation` edge semantics to pin: cascaded resolves (a promoted candidate that is itself a resolve does not govern a further promotion — single-pass implemented, vs. fixpoint); interaction with HLC-monotonicity quarantine (may a quarantined resolve govern?); a resolve held pending by its own causal gaps still governs promotion (set-level rule) while its effect stays pending; whether the invalid-target/chosen no-op warrants a dedicated `PreconditionFailureReason` (implemented: reuses `TargetMissing`). | G / Pass 12 (equivocation) | +| P12-K7 | `epiphany-ops` K | Advisory-precondition catalog: the spec declares the duration-boundary advisory only for InsertEvent while the implementation also applies it to ModifyEvent's replacement value — state ModifyEvent's bucket explicitly. Also: which advisory checks are blocked on graph-model completion (Instrument declared range; a Region slur-spanning permission flag; which extent shapes constitute a resolvable musical end bound). | G / Pass 12 (validation) | +| P12-I4 | `epiphany-layout-ir` I | Constraint-strength attachment: Ch9 defines `ConstraintStrength` and says the solver consumes constraints "in normalized form", but neither the normalized form nor Ch7's `LayoutConstraint` provides a channel for an instance to carry strength. Implemented rule: break strength = `BreakKind` (Hard→Required, Soft→Preferred{1.0}); other core families Required; `Registered` conservative Required. Bless the rule or add a strength field. | G / Pass 12 (solver) | +| P12-I5 | `epiphany-layout-ir` I | No renderable status exists for "constraints present but not evaluated": every renderable `SolveStatus` is documented as "all hard constraints satisfied", leaving a below-conformance passthrough solver no honest report. Implemented encoding: `SolvedWithWarnings` + `satisfied_hard_constraints == false` + a warning. Sanction it or define a non-evaluating-tier report shape. | G / Pass 12 (solver) | +| P12-I6 | `epiphany-layout-ir` I | The spacing pass MUST "build collision constraints" but no per-tier minimum emission set is named. Implemented floor: successive-notehead-column no-collision chains + per-glyph region containment + user-break constraints. A normative Minimal-tier floor would make the acceptance surface testable. | G / Pass 12 (solver) | +| P12-D1 | `epiphany-bundle` D | Operation-index provisional encoding (block-refs + id-sorted entries with u32 block ordinal and u32 in-block offset; golden-locked) awaiting Binary Format companion ratification, together with: the offset's meaning (first content byte within the uncompressed block payload), a normative definition of "stale" (implemented: index block-set ≠ manifest `operation_roots` under full-`ChunkRef` equality), the one-slot-per-id invariant, the load-bearing property that the envelope encoding *leads* with the 16-byte OperationId, and whether the commit-time "grown significantly" SHOULD gets a threshold or stays implementation-defined. | J (Binary Format companion) | +| P12-E1 | `epiphany-layout-ir` E | Provisional canonical byte form for the `EditBarrier`/`BarrierScope`/`BarrierCondition` tree and the two `ExtensionDeclaration` blobs (`push_set` framing, u64 LE lengths; golden-locked). Ratify into the Binary Format companion. | J (Binary Format companion) | +| P12-E2 | `epiphany-layout-ir` E | The spec places no bound on `BarrierCondition` recursion; the decoder needs one against adversarial bytes. `MAX_CONDITION_DEPTH = 64` implemented — ratify a normative bound or bless the constant. | J (Binary Format companion) | +| P12-E3 | `epiphany-layout-ir` E | Barrier `ObjectKind` byte form = the `TypedObjectId` 16-bit discriminant (2 LE bytes) with open-value decode (unknown kinds never match, preserving append-only forward compat). Ratify representation + stance. | J (Binary Format companion) | +| P12-E4 | `epiphany-editor-core` E | Barrier matching for operations with no graph target (`SetMetadata`, `DeclareTransaction` — implemented: score-wide barriers only) and for opaque `Registered` operations (implemented: fully conservative match) is unspecified. | G (Ch. 8) | +| P12-E5 | `epiphany-editor-core` E | The unsafe-edit tombstone MUST has no defined mechanism: the manifest-side form (drop declaration + preserved roots? an explicit tombstone record?), interaction with `required = true`, and whether crossing immediately deactivates the extension's remaining barriers (implemented: yes, recorded via `extensions_requiring_tombstone()` for the next bundle write). | G (Ch. 8) | ## Not yet open elsewhere -Agent I (Track A) has contributed P12-I1..I3 above. Track B's Agent K has -contributed P12-K1..K4; H has contributed P12-H1..H7 (H6/H7 from the 2026-07 -spec-compliance audit follow-up, alongside K3/K4). Agent J (Binary Format -companion) has not yet contributed; when it does, append rows — the batch is -already open, so it joins directly (no new threshold). +Agent I (Track A) has contributed P12-I1..I6. Track B's Agent K has +contributed P12-K1..K7; H has contributed P12-H1..H7 (H6/H7 from the 2026-07 +spec-compliance audit follow-up, alongside K3/K4). The 2026-07 Push-3 wiring +work added C1..C4 (re-anchoring), D1 (bundle operation index), and E1..E5 +(edit barriers). Agent J (Binary Format companion) has not yet contributed; +when it does, append rows — the batch is already open, so it joins directly +(no new threshold). Note the P12-D1/E1/E2/E3 rows are *inputs* to J's +companion rather than G-dispositions. diff --git a/spec/PASS12_RATIFICATION_LOG.md b/spec/PASS12_RATIFICATION_LOG.md index 41a5fbf..42accb6 100644 --- a/spec/PASS12_RATIFICATION_LOG.md +++ b/spec/PASS12_RATIFICATION_LOG.md @@ -30,6 +30,17 @@ P12-H/K rows await G's ratification alongside Phase 2's open questions and are reduction-rule behavior text). Core spec: revision-history row "Pass 12 tranche 1 (audit spec-alignment)" appended. +## Tranche 1 addendum (2026-07-02, Push-3 enablers) + +Two further ratifications landed the same day as spec-side *enablers* for the +Push-3 wiring work — each defines normative text the implementation then built +against (spec-first, per the batch discipline): + +| Item | Disposition | Spec locus | Consumer | +|---|---|---|---| +| `ResolveEquivocation` meta-operation | **fixed (dangling prose reference)** — the core spec named the operation only in prose (§Equivocation, resolution path 2) with no payload schema, no catalog entry, no K1 slot. Ratified: catalog §ResolveEquivocation pins `ResolveEquivocationPayload { target: OperationId, chosen: EnvelopeHash }`, order-independent earliest-resolve-governs promotion, `AlreadyApplied` idempotence, `StructuralFieldCollision` on `equivocation_resolution` for differing resolves, precondition no-ops, and the equivocated-resolve exclusion; core spec `OperationPayload` gains the variant. Catalog 0.3.0 → 0.4.0. The profile-policy path stays open (P12-K5) | operation_catalog §ResolveEquivocation; core_spec §Operation Envelope | `epiphany-ops` (payload discriminant 3 appended; set-level promotion pre-pass) | +| Anchored break overrides | **fixed (representational gap)** — `OverrideKind::SystemBreak`/`PageBreak` were nullary, so a break's *position* was unrepresentable and the logical-stage projection required by §Engraving Overrides could not exist. Ratified: both kinds carry `anchor: TimeAnchor`; the `ScoreGraph` target names the owning region; projected break overrides carry `Internal` origin (authorship lives in the op log, P11-C8) | core_spec Ch7 §Engraving Overrides listing + note | `epiphany-layout-ir` (`to_logical` projection + paired `UserOverride` decisions) | + **Deliberately not touched here** (still open in `PASS12_BATCH.md`): every P12-H/K row (algorithm-id ratification, decomposition precedence configurability, authored decompositions for ineligible events, system-pitch diff --git a/spec/core_spec.pdf b/spec/core_spec.pdf index 0aab3336e00602b1cdfa380d9e4d89cd4ff3269f..16e86352efc0322ec90935141ee9c69cba516d26 100644 GIT binary patch delta 298316 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

%Ey4qG7HO4=aJR7Nk0!Ag!*&7_U2Ju& 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

|TS2oNqDG3^WqX7&rihfTqtsL6y)!K~ zNRa@adPLABw+DYDiW}BTlxMnN-Zn^)5kxTFQRGF+sA$-|0rxJ4Km#u5_NavL35-au zKs1I);xW1_LPVEDAKpeibBIzTz-qDL8%SUhpaecSSMFNzwkTY4a z(cI`)q$+Od@JjFn)jdN^MBv!FsaJ4#mq4#~coE`vhxdOP4zI98YIjG6w?kmN4sSz< zx4;rZXi6AUFF;i~CeqOuAJlU?u zL7VmO80de|%ZpEL8?!}kRS^eJI%-f3ye}TT)FcmYxCK1X4)V| zu*s&{x8Xhme8>46xepOI_B?Y1?pp%Ap8F8uwyl5CE!oLBVvV^YJ0Swco(ZnNPD`NI zvlBx6y*fF088qQvUq)~ZcdN!E=iI$t@b!L)wt$Lir?_s#LaKw{=50&|qp)h?p0*=l zaO`FD8bw1(uwPL&gdo4Ca<7rfb(V0c?wHE$5ZG=iwky513I#S<7MntV(T4dbAjLPq?zwH&8RQ6{CNl0A61&BnbB<^x=Pc>N z?X5;Pxgw+{YKx(D4q$3RQe+)Y##uQl_DV#HTguk}K_5qU+#}zr!X`!w&D5skr_FyW zADXzSV+xFET?GCL#}r|HcTBJ1m~u{-()V;tI}A4LoHmrax7?Xm ztIXP-%&jKRiig^e^PaM2Oj`oP3`yJ~1Nws#A$oG;7Mag`DoT!a<~FI#fwM#O_;aa{4I2DV zRm@_xA!XWqd5WP`RjnI7{{GgbDiT6(*sweDI%05~G3YgTeG&L8cpYKBD_$>emeGXj zq?zl;zUSBQRIoQ5FVVkDPYe63Kza3y((CHWd6s}Rqm+5Os&u9q(J=gu5`%vj9A|8P z4T)I<{tAgfnD5g%DDZeW%hl;`$caV}rSGb{5rgB5eXhZYi@;yOi3sz1BIhcJ9PNPQ zyC!lv3^ts|X((YEEH?2cQ(DjVgjFwW5#>NGnf1+<;^EVD-M&4Ys!iYWQR8q!yAu2D zK7Zblmmll2+kg2@F4k*F-0Xid_UVm9BbnPEIo2Ob&G-)=HBLHGrUTUti&`$&Yf1eU z-@wGIB8uHLxZ|zF7M4%2d-~KJ1{?ONTS^Wkk(9Km zPcW62>AcYkit?dmgWflH3gY~m4)2;>Kn#vE^>qzRxCs0enh;^W&pdyZ^Usi(?g8EN zVO`Ase(l4&{T%UaV)x1Za_T_D@97^T430BazJgRN179x{3Ffhp+K( z{MSePW)~5_k1+4YYoLGsRdDI_)AaK%@bLtoe}tcMhfbN2b3r%-26UD zra%7s%gdi04-7Wv%YWl0`JZF_r*N8BA-x&HzYP%(BY1-#r3Qbc;9IPqfk5Xp*sId= zIKf&eA{m8AOY^U>*=ee)RsiR(Fw&};q;5k*0?gFvQ37cHoWLX^t$q=EqQG!Eu2do{ z{fRKa_WfEn#>x2vR##Y6=rPdZthJ(QsVG!cbDM=`MX-4uT`PUf*^~KDV(e&oPpLGwGHI_ zE|YeE@5~04SjHz!m^6V4$_0;{hyB)ZxAE0nU1N16WSSy}R+;1LGZFuM zuE03_2!C_qBi`I-u#Ms;gP)uQ>xo&9Yx=wf@BRz_aRz_p64Rnb=p_p*b9KsJHRqpAF14A+5zMT{rc1+=OvQqnI`_RoN_Dtez0rDY! z54a{EX?}l|$2VYk^OdYxMKkFMTqIKZT(^edx*HT1zmO|q&cUZA90@n0dPWjN$xB|Q z7jtL`pSF}o`| zPIP~~xz<<5^#W+YLZb5PmU z%6S|O2zyY2bInk+L`}*ye@M)UyL%|~fj)nXq&FIf;kshSq)FrxTC{@)%WAMPS|P5* zNY{JA5b;RHFm?<>QEkUba=&7hazne}NS7=+KH3gMh7|=WRipniz@g~wq$P@(PH+TXpyuNMB$TOJ_GRa+jptEYdY z;d-qI=QeY2$MXJ6?IB#?&C<2tV?hX4+Q^w8#NkR8??eWmvSqi3bVjrwybE`w2cIJ` zlg{I9Vul%a;Mg=x_0=KD4C2LbEgP=@+4PVAB$p;ItcsNQyV*rpU4O^9=Thv;GwdW7 ziPf`Q+aPgJawTztGgp5rdD<=MToPd(;pcN^?*!RIrpP{;z8s>J=w%HA z5}iw&3|ATd;&}+ejd?h|=EYAdvY!|uts^W+uqAn;(XnS#HjZE*gCfECw)zhCb5UAV zUzV|WsrK%W@pQCEYVXZvme6hxW-x76h8Z}*6lV2L;W0B*i#TcLtz+wHo=kt>OyvhZ zRlae7F%+lx)si@cDX1HWYXBq)_Guqx{va;K+>q3W)Im+0G;0sp`1qsUQ!>+4oYKnq z=fa${Bw`Ri72@L8XXQ-Tlgb+!56IlY4Gm%huaH8CQ#|+RCnRKNNwR{8J^094aKk`r z6?1WpqvAqEcLVpcs5GACOOAhIS{%)jWR}P2z{0bY2~SQ{fYfgjIv2tE`_RtZ2-_1N6vTA8m{OE6L0RISq|14iWC%T|tI{7d zhpMjSvW81xG`q^yH z*ATFA^pj=3n~H{PV_Hx1h{bfNR_7(wn}_=k=~ApU+A$}IwRW~)XZ_Yd%5&}J&r%AP zxWBz|Su*8~T|S_sot@y6L8yKEY}^AiQQIk3yRuRdZChW5>xz9Ok|G-;{Zc#UjVgHQ z1Eq|GD15Cd$aQjOp3Z-mr!o9xy#De?sX!V{x|P?c<&nY?V8(u=r}mWF0-mH@6GyX= zI}lsvqRQMQq8bOEQRWC|7`!ukN&LiHJE9457(M-ia`mBC!HhV4OPK|R6snimz^o!X z^`JW46P4(m%fyZ;%U3I4!A3hH_=PMSdtSoAUUMoFLNZx;h24LMv#rTuN382auxKI} zRRlXmV2N5@2`bK;@RZ@=mDI`;+vS!+w!5@d3t6u}7c<0E78E!3AmOXvQFx{ZDLEAl znGa!+xfh(%2s(RDX>9`3K8`?+uT(dD%VSKMMFri+q}Y@Hh2M&rN*oL7fmU#7!Ag`Y zJGRuj6>)S`j8uR6p^lGz`bFzxZb!K7vzKq}`*0#{$)}w*>b^pqm7MVT>kmg$NlPp( zZek8CtI%U9ki5u%t}tB}p7x-Dltntx%wA;B6ysjAuD55+K)y!5P&c$!Y;3RSMfQp< z+ADV2UcDmU2U|oaLw@<;VPLNOYol&zue?z9aaVRBi#~t#r-4Mu-h6!nwfU8y=PbD20uL4Y^c$b&y`HvLEpBt=fu3%zEULhrms!i?j4ed!*F z{ycaDGNtSqusKybU)$7ERZ>^UXG|TKhZ$A83Ft3yqj211?y%pla9eB_Dh}BR6;eEl z=px||?+$;CQgmugS?GA~QY$2{txhkY|1NnSvL;p5=Qvf+9g#?!u5@uCAadC$<;FPj zGn>llft2UJF-fuV9szkIp}}tm5F~nCwCJMnjT|vyhv*<1Sw;x zH0z8n>NS-4fIzsVWYKemUY}rA#{uWliS~3lv9})JE~nG3CJ&o1=WYBRRFE&{XagBt zg+ppk4WqjqltMPgaGdXTh+&4VGIxYm9>;9OQ>l?oDLYXIYjmvVsH_zup9@q;HRkg( zTH=4GMsHAA7Z8O07sbGFTz3MH=4Ov+b7UoODKRBQmprc-A)AosC236zwSxqss*Vam zq$65n)#no&#`Vc_0X{b9+^pp0EH^PKI)B92r|vl?Ra*Ii+6F}|8`L&LI%P3*Lt~>d z*}CJ(r-pLZo%gDT!hP}y3u}}m(y&v8=Q4lQyW<8V#;26ME6sD@7>^>B0qu7t`gE-L zPNn2c`masxC5S5DAoAez5jgX%JFSjaE_lPB=2b*KR27zohnZ-d$y%vCjZmk2l0v%A z%Lv&ii~=M-{krb1-zI3MEIbI*Rt^ix{4P^rp5mva%O+F$N9~O2i;(>p+dMz~aaJz) zmg-p7mj};_mM?uoAGpM6uA?wp;_KCS+Q^W#!G(~p2s2M3&G_*T{|5pZ9G4M%5fhiz z<_1OrGB=kV=LRBw+cA(sVEHEaAj?Ez#1;ja2AqGN@9U*@hazPq(hPS+=^$UYsaUg;r!GjrScD!L^=na z#O9@u#Fc}ZB%Fhuq}G|4lJoS2cA@a@eFS@sdWxI=E%vkk+ceD z7)hJqPaS{i4No4PtZ;&(CKJwZjARC&QLwa-j)7v0#(^bk!9gVJcxn{fP^_d7;6%D$ z0CV+4Ba9z13%)6U&V5t+?0qS%B!=RENzfaEBBSrUEk};`|Nwieljv^A)kq5jatt zPZ4r*1wAS#Ez-b@Rd`1ShAN%}fdN-kP*hZatcrz*nv+C;q2%ETqKa~spcY2JHAZ-z z4)9@r1@Ryxfv13aVhRQWF)=criTDsBQ<5%XHSpx1Shd05@Dv+d5jaG=a7CadR>t{Z zRggMhvr;tO!84Vz30A?ADV)w{)hV5=am1%|V7pQ*AtsnJRv=(>%(+o`4cMumE5w*{ z20aDrf_p(w0Sf>IL{VZs1+>MTd`hRh3-JPfq5@N-45?Zjf>24-I_ZX0No~MqC4KQI zJcabde_&41w}B2A;ohdeVk3Qgd9M^7R~_`loP;B)e^Q@#P&Z(#WA*AZ6&-U_SR;<`6sOd7;T;`# z>ALCuF*LET_}upY2~K)4U= zgAt%W9pa8^oC`PtmJ84C;0T4N;a+gOR`S7TpPha8pBLw6pFe+oae4Omw;wL~?e9N5 z|M%G!7cYN2fBB@qFqiMo{&x1w*~2HY`|>$%dwllw#djBHkN*7h#f$UjKmPQ4e)yLM z56-?le|Gr<`Y}^GYHc|vi)CbggA&%(bF}XtJowX^a39@-8=edGo0ME8CL$M=wE=&5 z6R?-;R8)O)bY)%eWzezpVsvcVwr$&X=f&uxla6iMwrzE6bvm}^ee+v0Yv%8B?^<#GV1bw-#=@-JM_M6 zwK6i`?;W}_>Yuyp2~qNdocj2S&WuHM!yx=|a5UUFdXlO%^LcYx*?2Vr>;>|_9jBIl z@dMl5o=u-_rm^anfW7apH%E(deLuGrcaT599&Aa!nC6}&E*gOXKU{o1ShCCezaskcM@h)lsH>ASVmUP<12 zRcOs^iiK1?_G%g#Asu`{9Tu27fL*S1fnt8p49!}&}fC34ZRSyTxPkpHjz zjgj^se1tb;!g@8Og1OxpiA}V<{SSl`bgWSeE#2S+LYwj<2}Re6ycG~XNAvLv8vmq` zb<-sz8I9At?KdA*mUZ`!Z48NRwyeNCS=8dha7wuxPKw#Ul13-+Qk zJoE|)VP4aPNtplY$QC%2^=rGkv2j&@5{{ng(Ux^|)d8l_LjAxUVbhI-q`|uL3jE1> zZ2gow&p0X#k`U(3SPR?x_QsX~r?;b?^7zEljPk&qOOnLrB&p|2qc;jGPRS;MYyj-f z_wWI8+vqK?$ox%{6E}#o zQTT9Mv@+^BtliYrDc*N|vy)X5Fuw%`Xag4|4qlTNZ{C!+cE0}USh#rQ`_O9MSG7uy zl=zSk;nM&vF$&DalLU4&I1B1_j5zkSof9>vWv9#r&5~w}8zLa|0kWLX79vnTwiqIG&s1;OXu~!YnLDw!L)GpYZSbRi= z!ZwS;M@^=GsCR@yF?#av@R_UFp68~qDOS%1eXrV%Jq(Ry!)~XW&(;nrH|CfA>%!W2 zW?24R6u>_|Uj9|)7dzx&qoj+oy@rBc7pcT~lwTE7(2QB&<6%&gk;~C48c+Y^eMG6e1Gp?ier=RB=UtOx{qTh=GV#$2XC0hX)hWOB)3GXFld^AHJcOmtL8b~T zhgf-|jn>pYhDGW6L4d2MXI~~6Z?j@O^HW}v6VO3hwPBm|Om=fY5f^rkoPxN-7r#w- zs0AGGL%P;Qti#;WOWV^%L|x@fD{Y-59h}m29?HEg4MdfebQ8M3d?K7bV-NL=XR^i; zrF*MDDUtF%G~TL++aN7Qon06qaA_d^sP~Eh;%A9pB&TJ z@LXdPx7|OeAWvRi;&3A~*DQMVtgL3XZUlZKFxDY8k~;RmRUCcw^hm7Tg-494uc~R# z4;#J?>@*lomAtIdq1W-bgit);M^ZK!9ljK+xh6zN6udmWkhUp=+;;qhlPWW=w%Ki9 z&&>|&M95Y>L|}{w;9QrdBXkYS49dlF-sF=6!`wWhfsJe{v{_qq84v_R7W%$(4GBzJ zfjbLX^tu+Rf9Kdq=<*SPy5 zN8F;vw3!XlX=dqVCKX`UN%$AKjz8mX-8h9#l|Fjl6KK&{ z5z!B+;u#n{3leAqIAgzj6HwP{!vkh>R)J{NVNTjls0$5vacPR%mJ9Kv8WBv|e#zSV z+RKkr7M_Z32(N=X3~%Z}AFr_jvyu-I?acBx%^7_yF#*LE+80hd9o0?)q#MnoKx&m* z8zMKTg{mYS;XVawqw17@9M_)J{4L_y9Ofa~yF3mk+6x&{_nq8-Z&or&$$*l3;w$^+ zj5foKN5aTT(6emEY{TI@m0MT*m!g6CZUX=2%Mt4om6ih;a@1O~>2$L#LViGAGrvu` zX{W4pP+$^F?vHWC$uwf2aQ|uD-z`jz>x$YLD}-_ZvxZi z4r&9-^4m*$Vew2Cn@prgORtEyg2)?jrH<+!V0UJSkb(;5kZCLBl=@0QR)i@+D_!Dj zbOWGO&I8N<`%0w#p8^Hrw>8wd>qV|7MV;S7f|X3X(ZMCF)Q#^2PF_H2FCAikJiV?~ zto9pop^ZBzed`vE<#{(VEw$%4)pJY!y#_mrg0NDI1h&2L%isZwB^NvxPNDMmxJ3+p zm4zP}D*|;JPGjl*ngzh>0v|Md*yV3PT*nR8V#gdjSK)FA=c_0n#kpc|8^n=tg! zR_Y%#3%sZQl_=rW9pftUzbU2qcw6%sRtAm~vRrTL;KTQbq4wuIWlLFJYHcJ-+|fxl z)qP8u9)FI7cjm_TT_sT%NjcH$Te6QQHnTb}NHXwJ5mzZ3K9+gcbb~<(`Ot(|$021L zd|nCvx5Bx^(AWqB?C^tsCmv{Z3;gD<@GS;Nj30>|C%{;QFWGWN#QW5~?*B2IG3S)X z^tfoU%%%W$SSf>SHjS^o_4mz|D^AsU`K}mUONyrM{dnVH#v)zKtk&=#{#TEX7)4|0 zg(sDiAxG<;A@5F9U%(jZRsZqo1_u^z*hNPs`?aM`Fb6fzp|yBJ*sTqNpIG0bO4ZLZ zsd{MxeVoem+5K#Rp3a=WRL}@)umsV6d^%aqfG*4T$}6FrKVUQ~ah54dHzF-lv|2NN z>_s$}U+Ft->!w3{yTX4Se&%tVEw6&bs-*49k@(Y1;d&tza{>LrbF~x zmrd&7$!nW@&VdGLQY zU?PRERFLc}T&V$`$k;&T%qtiY5dCW?&?)oZ^tA|I#u~vt5>Mop4@@12hA~UKA{~>i zb7QSS8&2W}(|W_Kqg4q;h|lq1x@V@8Qls6ctGzp1-QI}VlgBP!;svF%-O^u^JH0zC zA1SZ6$pL**ei7XrfYZCwxJfTyqMUxAn&ZoJgLHkkMEml$UVmWMyEmpN&-Z35RjAiT z(Fufi#xVBV`^8aW5TDJTUpX9-;^S`Fg&le_{K;59}Nv8jFYmRPCj)*5=aL}`q zgf!$6wL{!ue{q+`s4UAI*@oIB?wh6GYjRIYj;j$B&5=;@UZfgfpHd_@*~DOS7CE71 z-P$y4c`@6d3y2FUfVfE<0*g+>r_a`^`TLIUGu?Ku>kTg8D}$z5c@9f z78g|`N`Rxesl2cv=!0yYVJctxDXGEM1-p^)p*0h_u^Kj{nA}yq+uZ%KaoTHt@+}Z_ z{}Zh-m{aWwHAb6+#-Cvy;LYPQe*EP``oBeMwCcVs5EUSskAn%Ti0de%hj>;d3|rPY zr|AAj00eM3TjF#7V92Tmw87Nw5~n{R!4_R&wQEp>4(ZvQ~6Us6xnGD~qqN zv--1a!Z!5?bEy$R3*SB-dd4Gn7POc0`3Rc;0DqVwA$(+93eWk4mMRo zH(87BDQS(M0PaW-5{$-Kt{x>{S?X#>ApczJ_u3n!-*#P5u8 z^%adJFHRRM|Ba^%yA_DvB)JT|$-k~jrU)~0$s}A+O!QyR_;U!&4xAbxh1=VFfy`vc z+d*EYnUSgOUUA4rkn%O*@%u47BMYOGt$LZOj3;ZRqA|5E;x(onk;i^$;KBm&c&&WtAOAs07!k?Y@-LAoVha zN9ZDIAq_u@m=M;{fA>pUi&K6^9Jm;%m-PbYU^JY54xsqw-nrW({{UEex%cFL1It@G zv*h#1hf)q%RhU#_ne;68z>qhTJY!5*is1V8o9IIQJvyMB5Taat`x2RuWc@?z0K2b3 zUAwtq$M!ui=&R=@q^uViCIxNRD~h;_4N~@fH}m^fI06vI(z-Xe6_PIE5LgCW{zpv^ zFDjXOL5U{Tl9h$P74BxL?-99T5=kK>Mfk&BBoY%0j%oAgR+6%#cn z{IP7#$2q%L%Y4fQti-{k3NXvWV}D-ddbR(Hm2B_pC%+RvhqwaRvpGWt!ReDF$Bej; z6Z!BQ-SUpb+J@NC)&EftC_(Vp*~3CYSMG5e8uaLQZGJ7odq2&#&366Zd1H7;w*_;b z_&CAwt$|dYy`CRFCx~w+Ub+2%eX0ID{>(yYYT71SzO9kc1j;pwFT?H9@nD}Br_cSB za%~z#p3gx)pPWx|=B4I}YcX!LGKrNVHpZiD12nlh0+d}JR|3&%u5E?OtCk`ZBCLI5 zp%tAO*YHCBEfs-D&*h{^&4r``Fvo{vfwMby@77_RYzxm6Fk{%_YiSbn7Tj?q2ut~g zqdJ^DZK_SC*Y`11NX_k!zRlJ2TAbx&Kn_Z?AoPT%0Iz9upx3RnTP$WvshKZ4=6JX& zJR#=rlkf2sB!odeoxBDrH_x7bOZcu@uK{H(o~*!P=^XH;bd{TM=K~FkqS> zOgDMo4jiH2QZ}tgA$|CzKhdD@x1JN0@VEPf z)weoWTr(Np1g$a&ozDO&ot*Lg%qD82sic2IFOB|VZ-0V~boHQ1_e?u}@!!r1dUPl?G8eQo zao&B*#debu3~+HkfbdBK-#${V6>-nJ{YQOR;mUK$%>aF!9mSj)qH)eG17pO1*k@Wg zCJRg#)d*or7F-fGD8$hOEZIT_+#Z7X+W{G=HtV&*Cu1DClkUi;R@W9sl4o;Ii+``$qya(=DZLzDg~^J6#A`S|4uC3ra49MlHrn0Pd|H$FcrhA}Q81@J&R4)V zN7`(?jK{Y`#}0Fk5hzX++Ogf6wj=2MFwxa&FbdZYnA=za{2N#FAr-srpa^;cLbj4i_7RKj$)XcmO3V zD`Novq#1<|lRQPm>l=qmkJ@52^Xo<%P}6NNgCE7Up@LE3s76rs0%`&6&c;|# z`L}W^-9o-jSKt2PhqHCFlxD1M{NpBp?65odkHX#CQhG!^1%*jy049-qp9=nGb?f z15=~$L5ypZR*FCCOYl_I&5VJpf$vqPL~^A^wB3Xi|D3`&Jx5*cM-6e!zsCjf6|~PP zv{MqaVjLDHZ?vtW}un(rIdCP4T4O1)oGQXU)ysc{!gl5#p_G%*GgH<1u{%m&Q#vPK%bI0zu zBWU%t+jNFylF6w!WANT{u@o77c$Zfk8}nZ0RQ{@B#~(^!#(aR z&0`YB7ZSv6TjM`wTht5G>Pz%~V<)4IoWH++6ejV-8R+^7svfkp$C(MN zGr?nv9zjqKwra`kTzT6kc{t46qRu+bxq>;noMWDDrb9wm%+wswz~h_GydcscUA_rw zN!Jyq;%1z7U;{SV!g9ILFYy(Af>a{B^&=>1o+DHX46~hxM4^Gh`#V@NCgyOP9_|Kn z3HsL0kGZE#as0(kY-A*-+le^A{Sy&nZmUQRsU(-~k_szswg1z9IffEv5 z1C}vCoWIBuXrXf><0Y}<5-2cPhVc)$5MA__@ZQNJ*Qxo8qunkY4OohJlU*`Sn#)X+ z*Xzt`08sc-53 zNpB>H3&?q-)h`U9fPR;Ord5ZyiYN#@6^X$^6G*}b|AcP4AzSV29$ zGd?2#eQ=0(_dW>|s5t=v8J|4eA&dY-v`^QQC~91r$6xW(Zn0JcG13(X^UrK(2DG!c zHU&v1((pTD_FZ*$aw{eMBav!9Pk63}$o2mf)aT=>n8bSXCk3@Vb!D@W1CdlDTj-%W ze;dE4VxOV z;!qR4yxZuV)o07O#C|Tm;ZwT$Sj53<7F^+qs36Ff^oBTVWas&UFvsWT)2LY6RVSbG z7iok0tHtXB7dJuR?d&y853qML9#ol$#rzx_*g9N%Ncp3C^6>7$uqx2&nV9xfZ>jg& zY!mIpEcBipE&@%rAr2bnFh^L1oc>w2hhfi0&1F0)?0q)Y%c{WzIFx8=k7$pwo=DoyUw*;|AJ?oY_1?-Zm3BAhiQHDD!tZ0q!q3EeFdYk5GV|bZuoT zT2}Jy#%W5)vS`|PGd!);KhTAF+-M0NX55u0gxE2qK|me`1Fk&x)+s!0aq=9b;|*=r z;z5rRb+3}m6dr)(_sr=$ zQda&Eu(FMmIn9SdkfcnX9l0jCK_jL6C8biWu2nUxKr%p=DbX-(inpd3Uu`^wn#dnj zw~B+aHf`T^Y|R*yV8P*7tx;k?mYxEMxccoNd0lSO-cbbEXHXk%WJVl81fa8peB#Na zkOrJb1$5fa+Q-Qk_2E3JLJ>|w(L~-fkFw)tJt4CVTQayGM^%e82BweA7d4>zyq-{S zR%=pohAS^`$rDjK%b?D4FUDa@Hc|-R&d4pvCLfSY5{o&zT6g(s3z@T~n5XhK=VX8D zR}8{Wl?;fuQ=$x~HA;j?E%!>PH$<{@@RK2<3@a$OclMhsUv67_u== zV^c)kZaj}a2Sy*%u=R}1TLY%|JFOVlC)JRek1fW!1^|)<3sld7=f^Z{(12RqeqhFS z09$tZw04yf3vl`ElCWhwb3fgy7@Mm^c6;U)f4ScRrQMChMe5}V}CVnKG?X=dYf|E8u!skJ_;82XLf+8G0J#QSY8Ucqeprz|B&M|GrH;MeSR;NIU& zTBZrf5bJe_O=~0b7IJ#V?pe6D9KzPsoAHyaXaCab2y}&t(2R?Z#0`HACP#$hDB5;$ zu9{Ei{=+z?WM3?dqD`X=UI)6VVV&KnscZHrBU9Cd%UJwLfFq#FuZ@tKr`)0#a9r79 zMwPf({>F`O4W;1(EpkNf>^;UQ-FnwRfZ6Vzd5UG65(i-p4`0uSJ*(wx6!i3+GSP0{ z1q-ZmR&%Zv!p>6MwQgHg82FuBO{9!z)0QP2>kZ|bg{p#jXm*zXI*6;(mzl>(%nt#c z(oXv!gqiv>H!s~MPfR5DqJc7M@H;&QgOco?;$uZ|wNE}$A?;8^THNwD1)z|YiO+4~ zSX~$LLg}DqY~KB6N;cU;FNs}@tx=Gb(+%tIyX|~B$^$YcjBw0ux{=%;7iffss)8Oz z#QiPP;44`HpfUT-0wQo5tSJ522t)R+>!OE9-pzehYL}h3Lw^f-2@{$Z*M+G3#hKk8 zdW9e6b}*s5!qa(yNa>r@3Lkvc_FtRdrfiJ7?+69#s$o2k1b`66Fb`Cta(tCkg)9A3 zxaJkzFa2x~Nt6s)8u}`zc$xFnRUZ~0W??2j@J$cpXin(sf(aNBOyj>?KtfW%`WZifCz(gf@&3INHKg)rb0sg@kqOA%P-uYW z^h|rT8;&&X_V(Bb&7{+ELHh?;BNH$9Hw!UAD+Clb+;FD?TulotCit(frOsWO4RR5m z1iLZm*!d;FN&{eNWc_=(OGs^_ZC8~uY{M4d{A#Z;@0+=vxwBTF1%;cqN&uN|%b7q( z5!`f5s0Z9M4E`imcD$TCH{F(FTXDe26!t(H!lmG2@oCx_oWnP?^nqzkZ#uh*)(!Pz z`*xzA4Deny0z5FnerK$A3B?kukv}Q4!<$gaBH;nY?Rmh??_n|Z^8^>H?I`tOP99h;y(kG1EyWmQ1Ry`R6yy*$ z(;;{m$aI07ugJIX3>@9FwlcfhanWVQ-*peomKLNTXV5AfmBHlg67z+)BBFH3bN9ux z-j^c^|6~b=R|TdQsNHKtPW!M2TZ%DTYI~}@gFkwx2n)hUCc$KmD1)><5W-P!@kb(6 zI*9O^H(l4a<>*g3+7HOLrBRLylF4_K9;*C|rleO?DC&N3!*dklSV={Y@f9yD|n*rr;X9 zWn|36(n}=HKsTj!NE!GI)d-!_*`_wYa*V`Lh}2M$1mkNrdf_kq82Ppb_?S4Vm4}R! z?;CJ2N?o{e#OcJI9e!e+-GEbgE4U=~M&_&SCwt~=0(ATs89@RCm`ju^;0Bv2+f1B> z6H-RgIfJD(!x1$DOaG!Pk|mQO-G*QYzDykEIQ-!kdG6)+#o8~hyd6G3N#!fn^O(u_ z9ZQOI;oHFXEej8I>v|oc@(D=nlbkF&;szj;lUX8JT7F?JBrKpdaQy$|BOk_C( z3k@VsxnP6|uK>YdQMPsZPZcpNU8JDld9JCxTpqB_zer*9|LRzAKSe>xQ>S|H_PHI>{PT@F-@b;f|N(7q(lS(|6RA+exIQLqddqpzlxKvhp=?KH+{$!YkV4{w>%YSKaIymRIBqkWq&9ii{8}pU#|mxJE1*lKq^>5 z{@F!>R5;wdqv!3C%6p-|!G};NdNF{>kVg~Q;a>RXt?g5`COf#0cr$NSQhEe5@>58= zgK?ZG+~fUB(kpGrCexiQnr|8cnm7d~KfvuM)b*Uo;ECd%OCa?R%VOY^+!ZYUDG;sy z^Rw`Y;Jl@vn%keL-;pd~GZmJLDy!gM?c3Ezwcn-7*l-*0xzmkp`OzBlOGPn@&q&SU z>1MwcFBV?5%73wg%Jtd@Ahr!8BlwZ>jI>9+pzp`+yH$dR4^{lBLDiv)C3;BiRDZLP zK7OM=9n)v4D;?lemiPU+pyFulx=WVoc3|}pN!IW;U>;VE9-p$7XPN?rq1$F9ioic- zdfHF^&MIn$c{={MHP=Is{s2AJxnzet;^7MX7?Mb{r*TfU@%96qF0vWek@{D!dgT}? zK~k4#D~wCO#yNEe-9ntH#0ZLllCV7B9GID`DE;-S_~q|IRU%U4RkzxFtf?AdQGvmr zxv52)P-_Rv$2zgA@;H1D3L*m;QiXcZZKYrZg9qLC7g;d=6yV*Au$U4Rv*$Hhbeu@L zOKj(QXL9C=cvpUr?w1A(IQT|%CKJ_hh%GT3pKaxSqGabTBK=RMKoT32DPU(|Np;4C zAp~B37e*&(C3iz`y>1cki$czn`wWndDpEJ!aJBnmno9C-ooz8i?mz>Va;F|dWps}9Qlvd zKmC=hLb*2C+xvBKdvbM=oFG@6_FcD5l<8%_`g!q%NwIu2!uKP%M?EstNx#FWtnO3o z_24M8VZn&*@ZRlH@B{e^4S3>_^z^HeL}gB9ot#Ghg>+;mRx3O=u9xP(pn<+70f@-- ztJ7$qnaTfk>WgoJ;OK9WNJ65J#$xh;Q())zS68p+))h8smPYEA1j6o6@A0H_JSb)G z`I0*+!~}fmHEo95X-5!E$}&$ORuoNl<43R%R~10W{!9-Iz>R|~DbQ$(E8sNL_UAS{ zi-FzIn47$zZg_WAPxSFOoOPOd1?HD9jTjyMnlU2ax#bya-F37DZmYPslN z#Ut}oq%rHm2pW={>&sdJ4JoRSI=bnW8eI4kx3M(C%M~fARdVi~n-HK=gKm3Wn!9LR zKzh{aD8dUoFgOGZ!gMBHVNFy!4{+%ln_(on>PPdUp9z{kE%Gf@3+HzAegX0BSU?DMk@{#o)FKm z>uFbTb>gYAKYpR>%!kFON!V_X4`%2H6G+`XtG2X#RdO^JoU7Tis z%Rh#A@yN}jdetLg3YL>b{KHewOe00QF&m3>ciGb%28|-Gj_IW(4*e75GKX5M05ypJ zmpdAZjA=m2wXkE)SvqO#SILI-f|80y9@a?EP&Wl!siU@P-s&FRyMRto7o+tvourf) zYR!a8;%2#U^HVeseA5}0UvH_Y$;0BYqmxwg4qEPjYzw(Ma#28RLM15Q9e~$H2>KK+ zzJeh!%31yhtVe`)Hc+|6_b)5NvQWEGEH}i8F8{mS2%gQN-eL}DL#{C5=M8?^rAQ-q zfGid1_I@M(_8(UZw**)XFcx+O`zPeizdSd6%AvuxN9RB(6ywh>ef43#0B+A-^`aZG zth-o90njoSZ0r{{!uate9EU!uekgTpo=s(6Qph6#6}|wAm$sO3`Zi4?%Ri{WFrcA{ zvCW17cNNE_4dqNgg3>RBMbsV{N0Jg0xi%Z%~&z&n1s-)$Yv8Qjt8M!#yYFWYJY-`oZ>L2U! z`{Wv#xiiy6J#?2}YOV$6lyVu4U*|YWMF~+tX_eE4If+p`8seH`4PUmeaBPv#W-pdo zuI*pC025~4`EM|icV4B^sP4k*+QNmnZ+awI3z0zB`B0zGj)iN(8{gkkaTacqU~%Hw z4O$RJdIYBX@N&e1C!L_q53qMap&0^tB{3jvfD7DPc|1fc9_xNK%`hhtJe6Y>u1pqL z?+m(t5Br)i1g&I@H~(1NJJYj?WIk!+%Q`dDC?Bb@v6_26TW0lyk|dTzj-dfUZ7iG&jv3)rhbm-OfI-k9SUF{6nNq`< zW^g1LBm4#TMrANpN$JnlUkilnX4%?s6ac4KMzwW`&;_)6O?p|rm-6e&Mf-=!9qsiS zfNul&2`9!`#BidZj2f0(gjiM?@66DQm@`mZaCGSN)F2_oT1O;Vsf{8*<|HgKM^Sjm zxGc>Nfy!9p8Jdb@fVW{(ca(8w2g6v1jNDW9Rjbxd?=G@20vlIGFWRDL;Ua zur~B3L#NoG+Q2AF{e1g(QG-DMm-Gq-sqCtxHL3j~#d-eaug9FUuZP%61&~$#34qIK z&@^2tB>8l3DQx0fz#SR55rjcUZs7-#e5?kSI$QH=yd5_FAOrL5_6;=t%=8I@Y> zzdr0CKD~gIdC9o!isQv_-uRPxWtlGu4>7r%i$}{u;W?!ci!$9xXD34P2q=o)b*@gp zfkP{2ZK7T|z=fj$`m8PmeM4;8HhHDg);X~HNrZTU{3;X@URRW;{jGYa*(fBY*2l4c z48upLA+0R9$jxQM0g+548HFX1tQtdm>PXiTybm0NJJI0GH8O?i_QBH&TszrBQbnDY z8)1gZaIS@MF0SFWj~3lw;6Bk=f%9Mfxtsu}1>>^!pU{jG9oKILN#u9#D!OgdS+6YQ zK2q4lOJKFp5b=j(#?*$`P^1GLibV&|BpFM>UiLZBE@ld4%8NC@Sf*_NCoROtaHEr; zB-2A1ve%?-$$#cpY`NN@cScWq2xM052z_fy(gsVy$c4WEAy-kRydl7^n!e5i!v zv#tSFdTISb9;DJE8a{oj`FeGaH5M+-!&K2OJ7)U-dm$7OETRmf2%|E8Mx2NrUBt@5Tl!hM1Vopb_zour5*Wtrwh5BI>Rm zSR^-*YXc{pVAEaL!$(D)a1%FGE7>0|>h`!wL^>Am;LG756CM3)>+$EJ?Qhq7yEgA~ z*P=6Rqjy7S(1VhK$1gf@(0Srxy%zyGYIY;U(@TjLhEP~6tB@{EBQWtu9>u^CN=+{E zdzOIfssgbuX-Ke8ZfJ5f)PaRyZgS;K23_Iquve50*ue1l9<>Yh(4QUHY8BaxB>5M^ zm|Ni7%|=$O>}y5(ZP4S4qda%7=AnP!2Gah@M1uCnu&EyEK4?;5U6Opz_bEgFpwJ9= zLLVa_p<*Y^MDFUys&}aQ|%5Lp7;)7{L{fP82uy87D+WKR9 zXx~2J1b*_HOBCgO!s*tJEpPoryj?~n_tW5nw}d?s(2-d%rbem_gR33iHXcv`r5zvh zWnAR+X9YY!xXBs<05ntjg-9rnDkW?LABHQG4?M)Yrr_;Tv_mC8s^jguEk60MOogdue}m0tpXb~9QS`ahwcvCkq3_NvxP0Os7c0RN z2l{p<4<8Lgm=X^Bp(TsS%gDL^7fKdGp}K0f-zcG7^rh_npahzYGsq?omB-xanzCTb zY(zWs`@mvm+munMhw~aSHFNeH&?$KsaX#VZACcY-Lh6MMI2INTt)HDqhg}0#+9mmI zOqIX2^17RNxu353k}>r~UYJBR=yO$64srEt(Dml+=~+&3^k~?H3G~3F|6mcLlSSgZ zkO`9-_~5_~lm&YY6Sh(`iG@dlQqgsP8B7I6SaB#0mc@hGPnjdyz>3I#o|YL0^2=>{ zoblqgr!x2+@Pn8(v+wU-KEs{ew5{K|1wM0bHeKR|8}U~X)ufQZf5NqrEQ8Ley1&$S z=F1A&9@Lu_4OEqk?7~wO;0dK0r4UOSPJTYT6dFT}?U2F^Xl zwKb1ShgBXBoMS5t0yZ3(i9(3}(sOqXV=3p*#4CC*0lbFLP|#vjSGw3Wdi8U!+`UY? zUn}fPDM5gnV}wBE`X7q1f>3OX5+s@zdIoC5BnmmCNG|RQ{Jphhd_`c;kvYZIo3TAl91s;1(Y6awXX~ljssGz^tEB-&WaOEC` z)Muz1&g^G_KT?I@u2x`LfEL|mlVUV0R||K$o@ZYL9!jHRHq7c`g~QZ(SUo0566sdy zdl8bu6!Tr@ON9SFUidaLbm@%a=8JmVTgo9_`!=GEYqQ49f#1gHxfvA5ROcY-J&Tw! z#)zgv##E1eUuar$@Tt38!g2Nt0xGY5FL764xi-XBSVQfRC%Rp(YS3Fk8dQrnyeavK zY|mSAc=Ce_Hs7~UJwwBdTGb5m`vB>S0{7LOw%k$5?7EZ^yh761nmY~1*rWz1J_D?t zplr!>Dn5q+#Sb-i0X2p&h{$#tumoQ(!}v!WmrxnCKy=SbSZ+rRtVlmKAf$QFpmc_< z2r99L8vgh7$EA9I5Ym~y9lKj{3e(0P)B0GikxitN`S_K4ph$HwkW)>O3_Ptx3}-ZB z#-Q6y>X@J9$2E^#u`FIEHoKt|FN12Q`u!IEg0RJ9576Wb^1LpgMNU%(Ty;tU_Zr8k zo^@cFHYB+Xu1t_B{5+To*=N<0Y9fx#ri55!4yjsYni-S*WV1b!! zC8&Fszp;Fl1R8{{F#JnSi{52HXSRq$=dr>}QGjOg6>_Ts%FPq!TX`&8i>@zJHZd?9A;R}euh^K z{UkM2j?HcEx$oi>KH1gM7tSi5-O>)pTrYq;Bm28N`3Zft0a-jc9TMkJ+VyqZ@u=AK z9m&P7*cP^nbh{k!SfAx&S(QsY$twF~An_=3z~9ttclPo)G^{o81zpaY#R6sf&=z|2 z&IRV@MU#jR9I(ZS>FN-kA@!%#2C6xKW~u=OBFMU1LtSoB&@Sf|RXIL`3c zsZq`cH?@K#<>{LjMpe;hz02|D+Aq-=meX^eUQLr5^@wd^*vt1YQ^Ti)g)uuI2h3c1 zVkM!n!};;5A>vzzQfQI%+mHxSjIOM{hliP^~HnbAEJRPkI&BvVl*cP&59cr|{#ALjhdm17xbzqlCJ*Q1Ma zHgNO*&u%Hbwib}xZ7m?X*EwAr7${Qeb7~wwcCP|Rc=mY^+)5CIy9xWnx4%HQ_Fi8g zw^RKG;s{sjq9f|c#!@LXS&{#xgTUp2w;aQBU5+f9Rn4yVd0*B^76yA>ckJ!-w(qqsFMRz3g|Dw%3cz>#69yG8g)J-)Dm#HCG_XoXzIw%0MPDWec|<4LPO$HI(87NBmG^V2nUhtinlOW4h^nUaA7W4YLq z8_tCPna}U!%OaQ-7O@^im+Ep__9mp z$R)s#Iw7_44qTXlu6VUS8q3i@t&y0;`tO=EX&;T{r|}$)#W%r!`10+iO@YEA<)Ofb z=f?^3O7!uJf|EsD;fr)4usHR0uN|s0i!^UY-D}x}{=dK_P%kD76hVxLCi#@r|As?t z6-Riq$!F#!JD`%9)He`_i~Z}!mtB@$L>|z5!2>9O7PIJM7#RS~s@eAm{^Jgk4~mtd zwxL+7PU>Q~0|Tog&|#3SgdnGn)zgn&ICW>Ait>w=9j@7+v=s;%(h)@{)CCQdfv#lA z%jC+%#Xy@9tGtRiFqb@d&|+ugk35a+j#kq`iDdUM#gA(~bi)^Ea)4CJH#I4!{9&` z9XH)58UNi^Nv8wlg zI>>sgIGhjI4m1)leRLT!YH#gik|>0|B%XKK*4-0 zxcf^xFK3U3PWQt^8T|EN^s$pYS-W>K)6+8w_DMEpO=-?3QNjEd%c&VcOK@HxK! zh0ezZNMOPqxArBK1r8lEm7M{G63EWMEGP)?=I&}?;sEcxeqk`3aL@v3fkbl;AsGqG zn`n+urzoG89^Y2wiD_=^359t}SVa-$6z0s+sj-e!UZmAy>(nn_%bokyBgxgl)NA-` z0sD0mjkWi+=Ss)~*|;*CyBV6hZuI%`^t$fU8>$p`o@&(d^|A9INU>x)RkI z@cX=dxjpHr_#%vl9Neee2(64E1C8H zK9O0e+9_>*A0Afv2Atf(xv#$UUS0X^)M8V1FQ$G4LBRsTUsw&3TI7p*Kc8-ECzbZd zX8t^@JyVNU>R9@?04BPzb*QaunWN`kYGqEn4&vw4V`87?LqfO!KvJ2*EPoOdj_w!8*fMFRiNbRWRezbfKV`!tQFLVe}AZx^UHp( zR>T_xuy=-ZbDn-DIU$&a0p+>lGJegG)mCU@A{t@GSet5Ks)XAu1m38`ly@xMiqq`i z+=PuzRTzO%qPmX^==iBkBFW6P#sh)A0?i?R4$dR2$a*3VM@|3DXBa2!rrwu`O3a-SZKlx{2&J(|CW#V5pl&?(K2oIQ zft4rJf8C1V6*Hj-fd^a!27cGommCLeuQN^@{&gA*(z zgH>cO5$BP5AXt$wcD#%fs)Boi1&?N;8`4aMkCNl*lxhi!zmO#*p#Qh`^XPu(1YGU5b`LFr)23p?ibmMgLCLP2~n3VT+Nd zDB(ffmQ@mB>CqSnHOabR+7cg+geacATCNb0wepQ0b^3E7KS= z)S%%ZLnIz(b0~S;-{sIE6feVz`q%L;c&KWQHZ+i{sa`qGqAG0rUtZ?O1?@znVKG-0 z1>oq%j)K&<0Z|hlbn=3`yowbCDN8>4Am*X1ksi)Kls6Z$_hV;c9&OSq={FmvtTW$e zM?HJ*(LdNH6zq)iw(l8i*wPGJyLqQ6=lJ5PLi-bp7CTrTBSEKa#9CB>ORT+uL}zSr zxpTNTpb;R1=1HW%F>n%|(^1s+o2KxsphB-HcIENZ#abL{0f~;E!trjq*+#+vCJE{i z=s^KnFt^9!PNiP8&s2^j={I?UaJ$72V^l^*f4 zk&Y2(R!#&dhI~9Z)Y-rh8)3H4n~59)Uh!?;Q)$^ zpsSc4qG&DJRi~#Rfl$V#9`rUI%1=n&q0(y_$Ov(h8z-NtzmZxnsin;Hmx8{_L=*SC zx?!mlE<-cSeWe*uIpgO*&l0tdFf@u%z|ZXy%im?Mu^vr5%+Qv1R>>{L1(}M}ZJdVQ z@OH~EdV!j#zWR_B`33!2iRLKz7?6`^kO(m-X2EHb%c0bXN0?4N%!?X*;!5Hauxiop zm~Py`a09N}GQi*Ow-edPy)wQZN}n{JqW)pv#=}7q|25#ah=S2D`!MF#l7uX5B2S6L zhD|$N5&W%%+9&iIG>g8RPNvgr2;#6y6=gJgo{oZ7G#O~D__Y={xQVq_F#zKNmi+XL zLy!ZdjYxC?sh^0I#$GgX2#I$PMj`?Jc22#KjK$u-_t*JeTJ?lorCc1`iLE1zJz^~0 zN+_nd`VJR=p#iC)f7U!5K|Q%xT7tfOgLhtlDJ%W@CguYSgj!K|Fi;DU1^B|E{~`44 zQ}72zShY}&Fhu_cm@pbJK&%XgvBLP3iqM8u#k(1gh&G)=*IiODur8xrYce3S-yPJX z^EQiHa2OhKmd9>r{8i?jCPbSVKdf?G)$t;Cf~wzNQ%H{WPe=7dUY|y~Q6h(vcK@SG zLZ)eVeE>fj4Pl|FZi&>4K_y*&u%a#8mZ1vKttfUTiWuQHK^u9XU&BH$jfsRTYkSIy zSJGI9ox=V$N4Kc=*@NdGh73DL!}VH1Qr=4SXM)eJGR<;?Ate&VPKB!(#{%nfodi@( zRH{wgB9q9-=vlOR{5f&0ip3WZ9^?A_sH2S}s(hLP&0v(fU0yarj(JXZ2J;_uPd? zW{Z1dACJfZ3&P1B-Iwv`+j7MpfpcU=ek+Ttqcn;x8&ZtXG$-@-UJ=CHPGwsA+6M7z9RLX{@J;?QjnhNgD}OK zKnhm$pIrJ7N_-DYyWzi!noY(<*%T0zcuIELaEqd-o=JJj#|WFnm41j|f5`wBiI2uuLWwmchhUCdgl6T>)>Vd%(?plNDta(vg#+oDXI=4NIKPffPEZ6>AM#p78FC zr>vF+{!rcNI121dsP9R3BD!Is#om1^Zjo?eq$bc9vrU70CD!^HKEfiTm*OzW@jThR z82z_wy0^-h?XSX7Bhff_987aC0)_WXLb8<{Mq(ykqmzT+mf@WT_#y)IckWwQOVTJwWqQ>KPque zx@S=ZSZKH{IPT8LAmO5t@!6QlWLF-w(ZhV6-|63cxr2zE>kGH^tpt~@7~`_?qEW== zDR0lz&IqS=Ph5+#x5ZtxLWV_#ER+#yXeOYhXsOI$qe>DMf-wm7o^OD>bx{OX_q+Ss z359AVrD>7FUnj#^onI0b;+2=He4)m$d>Dw>rJOyeFpdnx(D~jwiuyEIjxlw7q#uwN zkVy1RI$?2+5~x>LVbrYz)1pYp%qwD2dV4t^mf8>!4P{{aa+ zcJ}AQEK!t!Ev+c|O#b=NwmLA^$ojYAp{+?Rs|)%7)QY=h;DS zR7cxWTxu#dqVp^wvUp^A0lDh;QSR+NxV{@Qk`cYCp4}gEqee4%)KD?}ySs3%Uzj_$#KYq{&wo(8=-2;uxx{v`;79`B9U_T*Q zJd&gJp{6HCIQQo-vdgQF2~?}Alc8h^+%&b&f=V(+@sdN~t3!lLsR{zZz*M?|Q(36b zJn`hZWeHO=W76ZqO^dg}j1tX&kL-9%c@1hhHz)hc8KBtGvZLEB*28G?s*w99qc_J> zJ{J*0Ve%EhbIl;HvINDVuc!U3hMoZJpuA*B%|dY5dO$)>0TPLn$C!ETyqBn`WWsMk z4>CZK83-DI*l5q-j9Jm-DrLY95o?P0Sq(3?b^LQ3d;2m;44S+;a_9`wTUnZB@sDe| zFO3>IART8@lbOwqaO7U($vbc8EabYuJ_-f0fYgP4!!?k@GlWQI46OL-eJOab=e?xb3Z z$csY!80{MFY(py(3Fi0I15RHJ!dddwAZQ)5YBc}+!M?_XcH{t}@P(7)`D|ynW_{Qn z;0tryeDPP#R8=xqMHy;wXVXoY`h=$l9s@;}KszzW-D3pW?;zN~ZS5fVO{TKW4B}k( zp~)^Go`8b1sV`zAsXuKThvqePU?1xTnWg~-Qrjt#Wmv1r6XIC@M1S#}F(5C6Q4*B;OzU$UcxCsnA{YMN;mHR^ETTgY8Z?V;j*69)K zwvqAhS#w$u_;UyILj`^!^)V~}`uAZ8I(>?#jH)v%$;LNN_|+&UooMhcC;Uc+P1YkAmq^Veu9S<{&has0cG_!V*3>ePxE-VSby z89rdr*^VKkO$hp|djuzg6X9wDAqn${LLR^S`J#IB3GA{l9y_+E1E}@^19`h!yPF~q z{x?N_lgfP5@LU+(18g<$?r|9H{)qMF1J5AR`!9F44uSzr=+OGdt4QI$9on1n5=H<2 zF@JOSU^~%2bH)e1!G%UT7?}a?MK@aZyrXWD#o#!F%KQvnsUR|QmrAa}b_VZ6Yddj( zBb5^WY;cD4Yd1rgG<8UKHR*FJ$3C>{b%kNcKY_BzuYV%)X5{e(q>G=%h7te$_PWoa z_>8PqjIc;r=&yBBAsuyf&m%>a-%qjE;ERAZa<;zij~bjE6y{rT>%k$rEic(i0&UP} z)o;%Zz9)B&A|23)u@1SWAmwpdSAqcA@md7ICz$0OgOxvqJB-Kel2fXZXdf`w|<3^pv`Mr!SR*( zmGV#a2`|YQ$;Zi?q3v%iUYw47FQq2Z4oHycp*0(%f=sVgI_??TEOlohX&tyXNezYy zS|Jy%pR!_iO2;YVfN;xkG?h;J*Pg{18-{VvXo5g*E3Da_RHW>*qL!5aMz-@Uu4Nl- z6Ow@fZTu&Tsha&X)oHe!d#nyhw;#?oYrLUzD=Ln#oteq%9P6n0*!dQzd*#ih>5j1` z`pcVY!tvW+Q#tny(f{J`ETCok86?rQ4@jcJXJKa4`Sa0Rctn_6pCGaWw90g*`(Cfp zj^OwQOVMY?u`b~s0n9Q4YWRkp_YUg_f++lt=`XT|X(nr|rd~0K3XHxaL)8Wo53cv~ ziA8(Ve;@}Wi@zwFxBt|+b(L>TaAS@hRaM?-5q}QbvhaC*r92J={#l%)@992H2!VL1 zhu-7v_ccB*uF34-U!O1vI<{DW=Gy~&h6_H`!)JHmOt(p!-m3Vm*Tby>cPwpYqi z)AtQ~-x7}ml()nuO!@WEVcfiu~kfti-qI2Qp{%ToV5V&KdG0JU`26Sp4JqGyZg4HSjIL#-tX-Pa(foBr0jx?LM-~w z+V;N}ezXK)m7wqE6Xm9+!reRsOFw?Yz~nF9+UlmF-O(aG0*(l8-Jjgwre1>{gK1-_ zj-xn8pJ}%S?`%6~KVR=;!`(G&Tj8+%fZ+}KomEbL0O|_Wxqm?@z^}ol{E)W9{-=A_ zyC-njt`7ye(>m}O2bLwsio8dZOw8N)esw*)b9IeT5&b!q4Xx-jEF+L5lU2D;JO z6)kDa(uY9#IvIbI+A!W^zzyH>Wi{by6t)v!Av41 z$lVIL!)XdtE`$rCl@c3L#1Z-e!pHK|P~X5BIQ~jKpRBo+BB~n{wkEmQDE|lq|B9{r zBQHQyF`#>+NN})Q7EX-Mz0K%@a(Qqr_#_m*cqNAUi(QP7)7;kG$iBilFnWFh`AT0`Fi0@L&&-5&2qE-x50u}wS+itPpF43Uj<;)RQJ&wpJSCDJb& za%y)DYgEkfKH!HND9soIknw%?y=h!P;M3dMqZ`P`X2A_B!M?Z|!=eILzH~CP{hQO# z8~v}2V~^`)l*VM^K=X}RHeu+}Q}Uw@##*NS4xhkM1N%%3m;Ex(q2R}S@eRXE9rop6 zGdPUzu{vrl(k=m}E)D4c??qF*k{R(N6g-OBl4hm`^4E`dlp73Ie`s9()XE&A-KP#$s&3UTCl|Rd^_HagfNrW_niA43??0% zrzU&Th=!Z9a04I#<3%v*y91IZ|EZ|78VSqfcI@jV&x!i9;}3lGA)7mc)Q>x+0GO)8 zhu%`zFv5^W-_re5{()X=(J?Va(wVjkMPkd}2IF!Q*>j2MEI-44e(_Xtu&2*odFZjH z75_!Yt}=6n`>03j*ev^YiE*ZYvjvter(G!`8bqO#R-`%z*bI5K<8WxF>^zznx^b~P zT=%dj8*<_;=h}fUTe!0LR$_SI(~z+{dRMu!*?X&BLFaVG%R=B#^`*7Zv3KT@Jb_(7 zGwW~4V_bzg_b1t%e3GHLoP!NzWLfw#bW4-!Lm2tZ|c(DH&? zZd6DN(G zck3BRT|&2d(ynfUUrwcs8z>!T@kYCD8S2;0YP}wv60n&9XbhGz*m2R@+$DC{5t!JHwtY<0K z$iWHIDlS|BX3(5F2Gtv1uv_QZ={k-%r0TxX9+xcNn1z47V~v1F>?_+-P{x=Rjg0~4 z*XeyNrOg8lXnyhHdPj${xRJ{2leSYX6Z6{-4%OD~M~yL_5-sEC{)7-qowu|zK$HBU zE(PQE_YyY_W_PgW1q|cWDT#wvP%^zPBxsN4FSrcCsBeCeerb$Y`4N%52uyz)T~N_r zdE8J*WEZP!UN?TwS!O=^x{DaA2)j3@OSM)=m!2S`=hPMzpS?_V-h1f?92g%4+-#(* zX?nP*AwJZL(PN(d9ZzWWE1}c@q#+ZADiIX)M-@tHTgLxXoh3Z_2ZdmHgc*A|K|dm67~$YrwY4=!)ls`8*&4J2Wd|K1 zdERTt{#q=st{u;sco}W5IR=ej%Q6+I6d~D=ts*?9Pv*5;*-^&GfT5kj*0?%Nqt&8nAf+Uv!a4T*&u zTI#edHr6Fj%iat)J;qEc-nvVaK}NpsC*0}+Y84!%G=rYropc?k6b0#toPttzpAIF` zw8FA;bH$Wk!!|KBPMt1bucObi-}aRcEg*v_EwJ39-$!Zr7y;5W;-nTf%RoqDsY+aQ zdPBlIDnPiqo>QHAh~AMt)w1A=u~;B(6pbOF!92qAzc?!o34RL_ory_V8lfHnrAo=^ z^vojJoM)W`4OPNv{bnlEY%GJ3@@Gs|nk*N*qZ}{Wp<+0%+}hKC`@(`-2+98Ly1ERO zN`m9MgMNxy$q7DbEi#*v3}i;}xnOs8A#xw848V&WWT;v(>^3uK4`AQXiS@-SFi2If zkLjz6Q8OfF>QHel>nk%*&b9(_T4bn`dIy!V-Ly0{T(P$F3}oMYCIuUd_VMa!tte7X zcZ}+0IBg~}l+X<(hi`C|g<)TNlbA&K&FR#5NVbvjR6d+-75pE!YVNDP88>S6Ym{m$ z0a)bN%KZy@cCfEsTv7jF6n05b7v@verX&f&4oAVTbE!fK2+|Dtq>rk~m;eZ06X|95 ze+Iz{C$Sk}k&zm^nM+o+R@(&)ATERNgtMNF;vk z^t$CleQAny;1v_wEe$*d-EVglMF9ehcHAmZpdG=oOZ>kbJ)f|@xkv)|`Se&>WZ-va z#o`fnIx-m4M*ZP#1$(PyacYt5XCBmdN{E=2=!;xmD=cZ?ystcdDKC$+5RiIpq_N^P z6Ck5+dFeFohncM`(;xCJ6lir#jEOgkqh(`4!de#>bc7-l#<*!;uvKIA^U8B_!iWhG zr?80Ilr!)zK2?6&@-za9L5!pOR-yTG{!qwj8hMIXhU}@7iZjm}?@6SNq1=?@ zd8Xjy-y)14z6`49+W>_Gmn4VIPU@Ds2|UHn#+Cjf44E;_|M5{Jlre~pup`r^E$J+z zD`yd>0FF2{w4IEY?Ej^!h?t5Zrwo_{7Y~vDQQB9=3P?tLCdIRqz6sDV3`~uu(8Y2c zv<)zKlk1pk^F3=w-;y6%Rq3jh{s9^)T7*jvHa6j9p&2$rQG)Q$0dFXi}Z)^417X56p%wT-8Xz-O|Gh+e=PyCRB%w_hZeOWp=Yc_ z6+oDVj&e&qFa^4g7F|8Fvr1Nl!3Jk88;u8Ys1h21)1Z^#BQ{wg^G0nKj(Hy9(dRZ0 zelqCZ;8=aaVXI-z6Obx*>7Y~~E-9I2$@B0ZV_oC^Du(gRt06jcj(JC8sQWE6u1Jjt zAooAy5UhSds9gdS{_jr--x#+Z@Yg zyu^%SC+Td_QIhd21+kR#Sggx2Pe9;vyT+P>hp3BzSKwF3Nyc@ybdM5S3)`=CBmj>K zU!Lg=w3jaKS?X>>h0CMe-^R7vW8hYBihL*)h3X%MJRF;m6+_DY&TbUwrkU2I2mu*3 zD|~qfvl@t)qlgckUoyl3m3R^0?^qj%YPD*XhD9U@MB75R@$GFE!R<}u?ws)(^AqX4 z!9WLbz6vy|avRzU%!pr=QKJJ?E>w-08XOGq1(B0`Hn+pB@BLhcm23Bn5N*p+s>L9( zV<(a$!69;u9ESG&taKmv9QXut!{KsBb^HVRyMCnvO`dw-1%sTr`Uv|S;PzO(95dt? zwL^M-{TrA>m0aFYUNT~PMd!APtXV*nP*57%=>Fom`wjl{W-Q`5RyMXr#-@33NZhW! z@L_HX&}n{u;Esa3m^)IxQzzjM60nrL+-MBy2GQ*MH7Eb`%6G%xvGU){8#05^lN;tn zZl{r>U~qu`;ZQyhH(q#EwM2*S_jo05|n!bkb?l?ji>9Z(H3U9<8_yr||%XqKwIzCJ--E1o@-04b`c-(wQhCE}7dU_A|eF{$Xh~HEg+&+@M1ta+~ zmMhSVyE+-ENp00LDBx>lZs+vlP_;$LrTn1y_J3PO`M%ulg+u@G`LJI^$^6BIrR&ge zQib8~l=UL*Y2T&Fo1jeb1o3@6AVDhGzj((Hu3)xdmkyZJ((2h)vk$mpi1t@;ITTZW zkySP$Mjcekx|Ci^OQ&J|nL_*RW@Aq!WVppr(^El@?`-p^+Hk(-_X(^iuImDPY-qKx zHI1N6fiRh^XMSH)(cDivqlYPOPw0T3azb&f2~W*Zq~A`9=V0$*HozcG%y&6)^yoY` zDafP1+_?ZzLZhG-{#?ENk29ptD+#U|UKDHssP(UpMA1>18*Q4`+t^~Z+sMaIK&s@A z{wr%pJ2xE}v%_(U?^K+03_oX^$J(c+O6|$8th2y#=YB2zjN!ZG)wL+R!U}%($wy2T zVCc_{!a5aiRnWFDzQ$u%_!pGg>r4NtIdsIyv(QJy4Q^pZkO9pyENE?g9qnY zYk}r|hNWN0F`M8LpWp_WY-4GJ5ox+pMj&EagZc51NqUTSVpC(4GtqWjp9Hi29i37? zU?R7X_ar)2BJI1_Jj4rHZpyIStIa4=e!pxHh4J%=5^@m5`XYmd08Wa_EW!7^aNKV+ zEQJZM^q4WMRZ7}mYn!GUmPgAxDlBzELmqX(O{H|*v5`tr9u8W1!^0{_TfYX?JG^X>9j7uf~ONn0hLjCA219>S79UG8Z=7wiJr9g zOKFFhzbeBk2SGH!=2qu~>hGfk!q+y3Vs-n6nabV}2HCUWKfT{@S8PK>!f4H~NW#@x zOtHLvtOu8A6914N^pG!l$MfbfLDeLUK-uK&@J~=%Om~1t|6&bqO`E%Hd@q&oFtSkw z_@p}}nhc0&l$u=nmnxY;%;Z^>?@qc~fhm%Kod#d?F!p-kXWzPsyBlb1UXJ0Tt23=K zQRol^j88PT;BZXMfzMIBLZVuS8i~V;jcO7@z(UQ8^(is7gfAG7M=Una!n}4ha#L-0RBU|1_JCEjxe8dfDhb%;0zdYT|-3|o`H)WWz$0w zM2eF+t^>P^Y1O=pZX~f$)J`gYqS!T_25ZqWy-uwZAwd4fKM?#LAb^Dg$Dloj$lp(d znuh!uDiTa>Knr7ztnf_m>)hZuPyuxTU0yr}qtv)|voyUf;&SAk!Ef~^U={vILFM%A zILlivj7yQL1kRZP6%cmCEKU3kHfrI<5JimbMdIO@bMsS3`KP;a1Vy3L1#j;s4x;~l z;4H6{nMQMSWmr*Q*&I=d{}x18he(WgS$#i-ne=SLH?!uf7Ga0^j|)ZN>L98LsxpYp zvIsa6J&U<4za2<%{u&5BAY8V=f#OFSY+2 z_>#`#&TKK%;LLQ?toe=|(Ob@4I&2B0WbOgz838vdQKqWVY=KP_6|~$OwU)wj{s-d< zJy}(TZzV3M1Ah8G!Ivz2(_O!$(aF?ol{EOn&`J8LbocQ5#zkiy;75=cffXDyn)wY= zP*JJa&JNno6S_F*k1~0Gx>$Zgvp;X>8gNI&BBXUM2l2C0YURFUHy6-jv#0cZJ@Ral z%3d~;lp(cMe<(vz(k{$eeRZAnrRRbxah3)>{ylZx8`h*Gu}S7#7_w@k)wavn?LiKI}hgxO_c{!`ZSw<}xx&Fric(5}xI^INKM>o_aVKX*fR<>bw`fs#@4L|pys%EO z*gvCvzU?pL6O$!gSJW+t+WSs0){l-~bwcCz+p;PqOVUcn#QQ?ks0TV|pBxfYh{kXM zD=p(hq%0R*%Uxvus;a-RT(SSYgpC^_)>r%Max56mQ#&n;@ZplWcxp)t+63HjdN6UfuhvODHiEU?XD?Xn z(6I3@SeEzaO;>07In|1fN}l0VT}=3#umX~5k7c1^059go3+{;ZZqMqTp#phfEE1nM zkD5ubBCSFsu%!s$9LX*h5x(NwHp9#-pw~4##;`w7y4h+T;wA!RF-dD(`73vVGiSnLHZFS<8S7YAuO7jHpN6yM zzTegXu#y}6MT$|#Rdg4;{5R>+yDsvAsfFxId%M$p9b3U>lmeZ0#TIKvITWTJ+*H6T zy9CNYAAWYKF~*g`UmV#IEHJwcIO`3pKJZ_78w1toDPOE;{WHoEm|&lyIC=BEj+UxM zu3j+xiHMk*+Q+&?;SWE}Vb}Ih2NtK~{T}uMP=vG_alo|79$|me7_!%wF-J`!#GV^U zR*4AHI~sj_3HIb(;bQyCmQ$SQ(~{+;~V+|a0r+x;L^0(%qLzQnTB|8^gt z1BfJ*baq77ch|qUQ#*E*UmN?M;fH^eA5^KUKqiqn4(!@Lt=H0Yw|hy1jvNa}YgWVz zYP@ihmMYAbaWMPNAx>yXOKS&fW@OS#&PvfROpw`X9~M>g>mD!EF2rIYquBMqY z2LBEoQL^CCDj;BBwyhwV_t>p?YdqMxn){XESw}=NRfM|`u%Z%TjLbf0 z>wlae>B8mY_4;8hVH{WMC0x`VSFS%;A0;~pD-}DeI{ex~^gL8Ni#zIeBCC3;1UBH= zk)q{_GBv~2+T(Y1Shm6Y40U z^2nul?%m!@0xO%~3FI&1n-IO#?nqlGyd=Ep_eMif)sS3?g4ap|*PSbnifVuT-bmSR zTMKAspF>pOEGm>JZW*+7I)(ca1bi=f-f+9)D&7wyLrf)2bBmX&NzQBivvextP=S0( zh``Z9#&9g^|LhP!RY~VkLj2G&?Fu{YUcBH% zrgTfKr@ic+N#P#-+?z@iRw3y9L!_^t8W0c(2RHY&?Hp@w zNGO?doki&>Josl^7B;z;p{q51kC64?o5jLNzWna!V5M|aQr9y#*jFOTO6As7Nqz<2 zuqMLoGz)0xxZFf^VmWK<64gBAnuKBJ4Kfm9SD5YK&GW8|Tt8BO+`sKr5`NqPXflQ3 zaHe)9|F3MvG}RUj6*_fYADR+iX5;>!dLH}1k}V2m$0vCixqbnDzMlRqfq`jt z>~|dB?#0JR?%1B-;4KOn;M0@;;m6b*8qgQ(#PR1;3^16|=a(0FmzDAVN_%nlY>Jlk zEUERoE0fX$Y1C-q|d`)44gvcAamT=BB!3})GF$=PWg$Pg)g6p-U&SzABH?y63jm# zO^RR<$7kCBNnyA^X-G~2{kE1_;>xaEFq!?%pTG}r$e1l7YI{_Zq@957CI5Q9y%p;n@_Dy!Cz=93wn8qz-=Z0-?5*mNOAs zYy@1egL?ecn>Y+0TcZ_jqA_`mAl%uKi=Q6WR4~bdp04?2gH=B>eq)h*i?uHj?^Uss zk^Y8g3g;48xysrun2LMCl21B`Vwmvts*9wbOecUdd@4dWfX(O!3fD}t9V%Kz8x!o1 z&w3n%2_e)qEN|HEAd1zP_KbnhJ^YF$1SX)4jR$okq|LHwVA+Ps1zvM1nfG@It%UN+ zlPAQ_qjZWkY#JU|7CT4*3Ls;r$@r;-x;jA7GAU5G!1Y&8tFsQOctl5mZa=w8$IQN2M_C7sPz2xN{r2RBop&#wI?TUV%>*cUwV3mhh;SoD`_ev`ww zjzJ$P?9tY6%LYHw&j(n239E8C7aiZevI-+G$wrNAqBm?vf~}z8^yC*L&;&q z<@Lyi8WS*OyD4~XaMQ5(EfLjJ62%sN{<`cXJoR8`MDARMLe>&qDgE0SnuiFu&h%@j z!B=H%na<69!*4NwnC^^AG!=GFk6;a0+<7=jE~uwiB2I^|-_0Fh843;}3?9ln(&=>c zj5<;W6Zjs{EM_z{lB`$L*Flb7OL&O!UZzbpZf8~fU^0$mHra^bm%vsxs}}IegnXH6 zbU2x&;#(o)`-aeFxvfBy1wRPTEnT>^!C_i!dkTd{)o(8?*ApE!NWuBn8#9{|QP-t9 z!?KqgI@=)&Y&3Isw;qyX+)e%#JYbF$t4N&-v@M_q-`L%fpPdN_ieRJ_X8rzwqCbqj z{zgOQ;lSIgYS9;z_>7Xp-L2#~Y}i+;6iz8CnVJw}!>roPrxstgQDg$_^TOhkc__^0 zW-pS@r|uKC4x{<0X;`nesOVB#bl|WtF>Y&c?gFZ!MdtQ?a?%A%t27 zEQ#m8Xadr#)-1|MpS_jv`9@_&!0{LEF}-oYevIA1=C}rK`nNe8t>+nI>SP*{KS-vH z>_mO1P#;DoltEQIZ z(k11x0~(9T#`Xlg{-&D}8MNnF}#iM^0IBzMvt55e8e)WJJW zNG^XzxEFaWsjsTA%$hT$JfvVtuS#FCVBEnl@7H@6L`SI&j+zlr4m7{Doi(ZKk8lMx ziVOYPo?@%iCbj?sPG}<_D(;)16_x7bAVl zX})1Vdl(Z`ynDsq|@)*qfa|MkmB-B_L9)l&wRLHiA0GG48G&!OMG`998zKQObb1y78qZIO2hs@EB z!ZriI+5ZkeIeV?G=`e8Ly98HQP~_6CTnzzZlQOH}Y@RoCm>FMM+@QnG;Nq^K!#rxl z3?;eV`rDS*W+q(K?3@qsFxl{0%zw5dPdd5%I$RjmpTKLK4OK^gxvAhxJ*b6jy1m*v zzO7+)T&&)o9y^Abm)h4U)MwU9;GK`coUT_aGZ?_?goU;RV_=hl+;%3aut5_&`~_-C zoebr|(}bb|a&L#gu=`r2gR*Jw+(~A!Uhw0t(RmpR0bj|ZZd6YO#C0f7POM(AcYPne z7Y58H`#sJ1(MHRes>bRqW)~c1lUnK>4OK}AbTI_{_>xsG#1jN%s=Y(A-R%oo9x0Kx z<}*MM$d%u@zUNii9grTz>kYP)gm;%WY)ez`M<%Tb>TL4^g-P~3tG)q~qcM}Wd16cS z&@yM40$m7ZuXTg2m>@6^dmt6DU4}3DN@uM8USK zd`y>?m@xD0z>Vw8R<6w6;diO0HO(OH<{~h5@?vt!p8Q76sEpQ7^1xU0p24G#mh3O4 zG#K18AhjZNNZP4FOGmK;S?{oaONYQ&y8@B8{q=6_n$v*&4|@CYAX*dNLLRu-SM5|O z8lOzJsPvPe^)@z{ate1Ol`D>4=@b;7tsXYzjty2f3O{x_v1V9iQjA#KOTpjU{J{Z~ z>`5Q3M^21}(aicT){KQz*Jf4wqF7G}j1a!$QraZb86(K+T!JKs`@D6K^Stb?ZdPxy zhBXt607E#+)S8{^b;c`k=`2y1d#SZP1x>RzOwJ%1OHT-mVQ@|EeE$mzLAd*Ps`91d z5|!PJC6(4Pyv5c<52k;5 zpw_K+4<7QJ{&oE7;%{*j6^O8A9|Z%OZ>FxcEKcVzcKmazjlMv`pyh9G3vB}wIBqVH zvR4$i;*%UE&@2@|Ga_2>+7dlMnzNrdY^9AYE6v=U9lBEjA_7$l(N;JeIiNnQLeX&x zl9Rco!^vb^t|{B47#`=raTC9=c2)YCf3g2^87&nLV&r)*cYHcXJ#}oeRWkU;?P)Xy zq5UsB%4{(bf?rYS29jRgi=r0@E1be!4QapBtD}rCbO@vT8}uT7@W@5!l^n?i&hgYq z%+HT19Daag% ziP|OCmH-F;$LO^W<(@$nj*d@)QfD>M?ctt*le)9r3U)32lpNCUgThSTEm_7fkzbL~ z=}208te0fi^vcX0RiqkL@%NJMltzxQ=W{nHwI#MlGPJO(+8f)z~C7%fB#>tIjjOwtxUo_^VF;Ct|NP?xs9}=}`a!WT%Ge?0fnsm~T!k)+;Y>T{SqvL%n%gWjpG;fweNbUGRdfrxY0d~$A8 zX(ub<<`C}*r_*cT2rb$X7Kx}qiedYjDE)Q{6@eG9A}D*l{?@**_kLFQcjJ=DrX6Ijl(4H>`a zE(~kQFejr3vl*iL40oO@vOrosbA=?ONir&aJ?#S$m^k2Q{?8QtIs<9{`L4YgHyOW^ zof{E_PW@+Qy9Yz<_7(1wDT1E4?+Uw4XJId+!wt)%fSsVa4y$=O+!D;OnW6HHYCHX? z+L$eDa15kU8b&0o8z)>kxIr7wB;3?wbM*~M6hZ|Jcf8GSfg!XZhG%4OZ@S24d6eV(8R)@( z>*(tu-I;FN7ag>iI6H=9+lPK0OTmgDuZ-T%$X?JC)BdES)hjMj?>IyVS4puvuRo`X zZCY=FK5XcSGJQSAQ|=QvLXY#(qilkk<6G_k+NlyHHnftXl}LOq@=Bu0MJD>Dt85ya zo{Id^PXYHbBwB>q!<>8^!)qRApPC&J!mqym$k~RzPc!Pb`8!TU?2oPm(0FQ>qVDry zNB2B>^E5NcK~nhH<;MnP7#+zPa5uigzTYe1^YFE)H4V}W4KGWDt+QS@)TA(8qU9!m zBI}ODxZh7-NUszJrnUC$b|Cf)hyAVw*prT%+tZ~Qyo&##YdC&imyml0Ka?61K2i7( zpEFbmz*hw|aDGNft1}A!L^5Ad!@UbYMN?z6yttaE>#|Iu#`k!+%uzHO-gd>r)gv9} zg?kI2VjXx3W2wP3-EDw4_!T%w5S%;$q|q~5V2OUD;C(f>{^Oy1W-3lp9J&T|cf6&5 zb`M=k-!%GHi6C)X_N>e8Og=(-W|}5SCW;t&8J zic*Y^j6w}oKBDYP-5}vQt=|O7@76kuh^htidlPPL;Jfmn>F_VJ^Df1j&Uo-9j9=vz zG?Wd%l&4E;i-sth!Nuf8LKTYb4~Hocew}p3YZD@Qklf^g5)a1Vg_r+dE9P+rXexk- z<9~7uy3)@3|Md=0pCr_Pyb@2gMlO?5O3qB|Dt3x1*3_R2bROH1544Gc6okcP2*I9F zZf;!FEMJlJ{nG85=lJ~I&w&16j5V+WczNP8Br#RJxpVs-o&KBdvG;k}(%*U9CS>T@ z{P%qj`>cl*5!9d=V37H*L-RTi$Y^-yqIw6bbDL_PD)1Sti|3eeHqmm0B^KW0AX~(q zYH$Df5w28C{VjsU?nYh&$2%|=G|1`K`*aJS^YK#Et>jdN&iWHR<(RyO<@D3#dWib# zFRJ6C`(k0A_x|G7aJc_N)i;Jm`aIFbw(VqNCmVZX8@sV>CllMYv9WF2w$0ti#<=sl z|NG^Bo9B6_->L3C)u^dD2Qh!~&Y1B* z9aML|qoVi2cmI!{ndI|z>%<^E|3Isn`;*^8KO!l4`e8_h)+KIE3_nqwMXbCJrZB%% z%JaA73E-~y_XuJ#>KH>V`e)Z)Z{9eHB~&Rc{B>AweqKWDpM(0SWkDI{V*!;i{pVB;h)aaQ@2^9hreh^}~QMx9Djpu;c)ILKp>p z)~ zC4X}mLqRulLs*|8PVC+IV7|S##iz@M^K`xWCWbP_%Jt>}2X`8+Hj=R%l#s~~4NC0> z;Gz4h;m>A%=}*={dA`Hgj55~y{o9Z{em&^gV9tw(wSyjbA_i8;hZQ}Zo*}FE2a6iR zD7cC5r{7Ceue$&7cMtJn7{YHWw>*?72a=c8V8c1eJlsIxQ47I4B114TCe|mlQuc#b z{xJ5((S*kcxMukLYXzeK+OWH&GASyzfQB-DYIrlI4?lH7>2DPXOTR$PmxyJreL78+ z#X$mOeKx`5Z^uLU3$`XjswAKEWV#B?p;LN^g1i0pNPE)$*S7JEpUX)?jxiGo$_Q6)LNW3AdFk{o zn(5Enim=HHU$Zo%kt1^p+}HqsC%#AV9G?kG4l3CL&j9x)dezIQ?T!t%f~Umk&k?<0 zQif$?;)YSq<3GRq6B_Rj1bV4n-AUpx@&$Tf;@h(B(*jSPKR+6uTZsJ!A27?6`d&}^ zSuoXt8t)#6fs_fI>+5L8Kwh~o7j49mo%TZ<8)VE2-3Hj`at;J>#pW2mDim^(t+oJKrMup7u2#<*)?TCsH&b`;AMCB|AOO+pAKl;q^s`kro z%aXBa*ryG;wAf51N*YO;GQJEHg(iRWxiDCm>NfLGWfVZZ;iDt~Ocz8m%x&6y&67rw zJ-AE4I7)%EP+Q>>LV$$-Q9WQ9J?O!zlk#HPsF6{f5W=>aG(kh)I&DfR_YT$Tm?y+B zsfZz?@ECXgCbu${Q*!iS{f81xFJRETg~L?t6xn8C%U?%6$DP;cmqO@{(u~5R8@C>e zTuA$MBP)a^^<*1hTD4o;#a#9ELdFu+pqF7PdA|=_!)pAmaxi(ZIhVG+$}>t@ID0;0 z9l{i(L&Rm-pGk?}I30acnYxxB5gT8Zx?zGnWQJ>|l)5Uvu)}qc;q6Frul0CM@%)1M~#ETD?Qy5ebJ?^r0cH09Y_Eh_ZAeHUIpc!e$n>iS-znp1ST-EO4A z_Q~%eD9VUMg%><)R@2~`(RL6e^0Nafpbi0$`FGCU+>)!cIC2;gJeP$0R~9R!oUL0@S> zdl6V;vo^XW&5@h+#9AAR9>S3R+at&3=;?+neGW_T5gClg!e-S&3=19Jm%&dT5t7H;9Wl>$DUEXcsAKPi~N#3lOHfJlIxxatlcVeHkR39}-8aD;maNZut z5>AlZ$b}U18Do>$@&8sTciiBt{cpC+eh&zNdS8#4;#Fy9#(}RKWGU!k-us}su(lF5 zaaGwDg*ubTsn)ldy$?tWWf^91BqQk|73CkaQY(uEwHL85?4k9AT~#@)s257+s);av z%*6;oi_vXGXV7HMLiw1C-^7__qLk;#?NbRRhcrf(#|^#f=bRMyRu+rz12}OyQoO&0 zGLml@<^VYnS#{u9(LJ%JWaim$lbeLooBfY{f;l}#i3#jl0P1i)E z+`t6_i-K*T8UnlMjER_6T8brwX+LL5Z)^#Te-|~8k;=hSq9zKsbA-jXzy_$tAR<2y zUszTULk>%cS|w|t-r$#Jit=sTq_5V*qcEL<98^OF@R_$XP?M*NzX{J#HN@1!A@*{c zwzUuOEYyzeK=~U~8D-K5-qFBGv5wKiW-4}?o^?^_8YR1awr=tQq@1R%?c%l@kL)0} zT=cwgo*Tvx*as!s1XXVqCflIobz99INwM+RTXlll(@gKkYLmxZ$}&qRA^f$oe0}X{ z7)b&E?v9yh^QvE;s;=yLNjz=hdn$BAS148(>D zW3h>J2W?oax{$XZB;SLWz9T*QU{fbF2Bso5l@~F7_TG_(21{Mfoof_Rt3K15B5^4R zZC%^+LTyu~A|Y2_hi7Na&Ey>NkEd^0FAW3!^&eP^`mMM+fkw$TW(BVn^wuy25Rxt$ zqgZbUmLK~gV6pX>iA00RgO#AE(n9y*hRJ|BJD_!TAGStM(E;>8Tnt$mJM<0=d(!t* z%=%c2$}MCwtRg`o(4T`mk^H)4F2mxynGoM)G{r_==b9 zK>TDixw{4@@-QwIU&q_JdZmJC#Nxt@G!})j;_;o-9{LZm8K&}Vx%s~>Pp(GG+gZmR zi|;qVS!t4Kp^taJT9XiFq7FT%N$aF#o#Abq)Bu>EeL=`zh>I3P2tZIUU2da1!nGfx zT&VjB16sZLVH>D398t|GRjUDrF?_dbSlJgADkr>_7 zDIixKGC-yUxpDxAE!u1%EG3Dj0zq`EooFJ1I!y49&PZ>d`DiM!Bqew6k5pDD|Nj3Uhsa;)$-QBvmpjcOgcb^p(EM!S1#ctj z=e54A?*BfjIZMhvza=LXhC#n@o)wuZH=5xRPAuJ`{*oFQJWDmL!2n!&-nj%FHfR={ z1r_5la@Hach7Vs=Cbnn?Svjwj0b-@rpOA16vu7f*ozhTdT;gbF8reLeoQbz3ax-Y& z;;;ncukJC1B|mQi?tg5 z?1Sp$!4ZFbzK88}oDbAy6CI{K*t1I@=+jszoVkF8q+id32rKjs50(~~a}*Ff#H_uU zZVP$z?sikBWMb@tDf-<+R2Cx6e5xS;w1NlN#Ds#DToZ7!yyPwE_Tem;7phXuc3lMv zGtj&C)gU85a7c(?&j-Aec!-|Jnb<8|AcN+MY8gxeG+)Yv(-uM%l0q_8@GLba3(KH& z^fcL6&Rgh?yp>7<>6AFTZp>^FFO?O^u5wYOqR}f~E@-iTz+meir2T`)U~AHGU^nBL zI1x;2eND+iGTcSo@nePtoEPN1#+dOlW`2T ze3}+{DM9;%2Ut0)WZgC)G($f6&OPJG^~U;;=?e*ha`Upz%($sQW0#|krQAID{kc@t z4Y;4~$R56cb)CPhnqG3F6D)4QzN3a<*4u{GN{r=bWDQ3_4u~1^Gz4J zJ4Pm1*G+!ijzOe4;$iHI235y>8_EijrRTfoA=sSxil9I5~l9z3Npo3B$ofYx>D1y2XsDc+9d-{c-z$L zD;!Yluy^NJ&$C>`GIjV7?xCNJ0URamt3QkFco#){J|t_xIH*Az@{(R`W+Uh#A|J^P zP|``OI^cyj*P1!S!NvT1r*@kyn-eCW^iJ>L`3;sXkFm~@*MI(gztZmn!VeM1-w(Ad2Rn9BnX_AQ?apo(a^vx3 zuZ_8E^5XFuyC;J0857UKdR$1DPN8qzJ3{|}!Y#efQyDQU_l(^zAUTX^0yrRoL0|ux zo`3q>#w!q{;l-F{kerB(nJyCiU)YH4|Bo99PQ@MbIC}s>^zUxo zZW*I;{j(&M4D;~4zvB;Li7cs1tbN0~bk ziDbk1Vn+s~5`G@B+_dcV4XHW$J^R0W;O>3n{R~WJ<=X~m{0#K@{I_*~2CxXGRCE#a z^&!NgcHajnd4)N!0N%v@ALGHF9pzE|eU4)J#<4!Y+tt0p-lLT4Y~p{62lU;?l*P}t z`=B_HFYSK#vnn|WX}c>($ICIbS5OEPCekM#x_jpm7}`7JP$Jod)Phr)2V)W$X&YJ|)}!L!Y3+b%-y_;R(pA;? z%TcU!5-#Q?D2ybB?^BhiHr$tYmPmJ5&ES8*q1#TFQ?uz~>{wz(G$?CAtXR`wknn&^ z(SF)*OGf&b%>A7NaA@iRO(oO*h<wz;Iawyh+_cd zx*7DyJqqp3yxi@{8t|pU_*>a1a#<$SI=C+TB?=lM3UfdY%6{S54t^m=dv47|Y~2MA zf(H`4`WI1u4kxTefAH(*itguB-@<1^XnTaC3VQS~9v3>T0px&m`{8qsxL6ID=5h)J zm#o4NTw+oAYimmDx)T5o#+<(FNSgnUUp{(2TjIP3I1dWw?aEA{@?|uI zPb$T{<#@AyNIKK?qmmk&h|ZR&Ca)4@Og13VqLcgYwVAm4aoBDfi1C0UxC7Low`qRQ zJ)45Mr(Vior8^(gJH3OMONqNKu>ym;F0$bWLuC1IsKPFDH^7esB{!+NEkY-pm>?wq zkE_67;0e80VgZR%Y@mqKkaeJ#!4&GRa4aL9anG5EatUcfeKM&XgQ*^8;@2iR2zojr zav^c1vb^A@T}oUhWcyT*1YV(M_;P?VjPeuZageOBS552uU;%6R{U5wQod3cyC=h;A z%AyR151Em#0Fbf#&-@_>AY)OnDTcdpyrKHk)=jZqvQ(flU)^3~CJ^LR$B$Dfax$i89>Yz9tzgg?KVi#y1?GNc*^0f!y~Nk_%b2Vmzr5AHc`AoZTCBC&E2Ln zALI-}7QaLbr_|sq^^sb~O%P!fcJ)Ba3E$WO5{7_k9e3DM14utXpj3p%#JeWu?Iqe< z#WdAh0za_#bSWn?Mkj3eYgA$5G5rmB~OjCaH~Fo!-hwwxE@@g8R%eG3D@LMW{kC@|C8;#N};`>H>1hO zRt6S92JaoC$%sD9Y5c0mc*|*GWEGluqarlDyK}wf-#8Ol@ulRdfT>_M4)CcXKw0Mq zqx-6vJABci=_a-T<3lUjbMBKe) zlO6u))|y#Vr{yC+QS1kTZY(3h3vMYcQp6z!fBy?dkyvOgZxxkL`b$6@?nWAwUvp}9 z4hKcGz|ue*UQDc3cX)6QXkvnijXnd3ZOsFGrh9nSskwaVYjRnh*Xq6YU zYdnr+S?%D-_FUEGuKt3QNx3K;hSgnf%BOymr@{942dE}`sLv;A9i`3`3&@W^=04iG zKTqcU;~yYe?vg~S{RxsdzVM(kEY&tXza#eAJkw+kqN6Y^=2)|KvTsB3n|KZ!JNqbX zd^&-3Q3@p!YvJLC1YUcMt) zf_8&-5ms+%u9RXsH%lN2G#D~FLwt1*dxp7`({prR9+?Pj)9K}%z90Y`ga~F>g8)z# z#rkz_BiN2%2zUwCzEU}KE^Z+)qvT(?C27tJ2C)o+0>(D;Ib66G`+N#+`+d^3pKLCjx)zv zvb!PMl{lY~Ox^qVttvq+=+yV^qp}Dq;AB!t7oDT3Hnc6F(5e(JcWTTajayzB@Y!XL zz$B}(gOE7?dq0Z|pS|~+RFeX=FzK-ad=6(RpwsHJxO9n;Qa(59B?2!-0k26)q8Y(g zTms8z_e56GzCRlr$^TeAm~m^uLk?wDg#on#Glb2JW=s-kG;HQ^e;w2#9`3>Sm;;Z< zgBr@He1ah@JXfNj^ptrkYj+{+)sqDXG!I^TLX0ky^4sYjt3hPy{T1KLHV$R;Hnbe;-&}- ziffUw0I3%Qcs-k4iMyQ2!HXy-kGE&%iP&9dqh-Yu!U|EsojJOLk9Ir7a*nrlyOg1= zSnw}JM1#PdlXgeczZ|3MC%zU4;^rfOOjrSsy}pAkqB8p4J-$U_Y^CmW+_WnE^jwj8 zoE%%+UjwSiLHJ@XnUQ%R1KL+Jf}HoDMVEjlsC#O-#4u>w*BzBalVUg}h0~V~Mv$3~ zuATaJnkkq9!eq$6r~VT3-D(06e?E{>Dk7RJqDN(uveA4)ld|ex_WUEBGJw*OOd~ao zl$|zYA%1e1{Z4ppomw?FF~|B7dFzU0pPG#$ZkL$RFMOLH|EwmrU3Hq18Y8fEDDJPi z!E84DxHK4_x_moIaGv5c1dvZft=e3ntRg4Fqsgg$VwI1gfl%sR{^&TpYUtoNO)>r! zLmomd*12IcV+HA2N4D;23ov$Cme@?l{5t=1ygu|^u@Kf1K)k=b&P)|W4{SJi5|pq& zeuPBhSQ*ld^s0B3(^k)k}DJpKN)j4m)oGTM0jL8k!?SXFX!0x`TWWp1Es?}**x{Zwp z?zAgrYUu_ECS|?ZABMPW=Y!w5SYAf&VTpKUDkWJghkRVG>;#?Rxpb8OIqbDyh$+Zn z=^|N$DeHexu>R}^3@gU=(Xy{=CudUtY?lXxQ1{ zJDzXl-9M*5$~9)em?-3@6*ULTuPCN1qLWLY0CJzvo}D3pnm%;zfLa`@u;9rr0kbL* z+nvlj=TOnHJZBl1F&f4-r&O#R0c2nG8&6Tq-L#PsYTt!q*QTQEGk-(}JQ5r;358ay z9?js99{(+s2SwJKjWq+)X>ZtQ=BmC$6osc^Dj>NnwamL0-#cyo)P@yW7VhsfDw392 zf-7LPeU>o5&4T9GWH;h6?L?_9hC!sPpoN3u9zM7M9>zU_VKvZzREsJj-)V%|DU>55 zFee93OC99hS}7^haY=9!CBa%+SnIZ#d0(_!%bFjP7U7t)Whz~+FKYNoGDdTlgdIe` z$u2%Fe*1G&sBtRCk#w21y^`#ldy4IiDZ9K79p(epT)w;A?+341(8OWFm>i|v9PHOX z?CtOW$nemKpsJu;)-S-02T79s#F$Zv6`_DJ8Pf1!J*U4%Mj|lsmn8F%AWPy98_7hM zjuq`gmzIIgo60(c5S#c+6ZaNUBvOuD%6-*&sSZ#2X~eHDnPkqLCZ#;BuvdLuwAD|h zF|GwT^t2fHRpDP&vN$(eDpsDI>(b-84-P$6iJpy$i@N`(?R1*y3j<^s<;{Wpf0o(* z$aum>1yiZjPro+_jR5kclSVy}$cKb8U=3bE=HTEQt)zQ7y*9mtRTAi3~96u=vQcMsTk zU;mX4NnnM{?4N0THd=+8*7f1l&)2NNvsM3I$lg&vL;0OE7}bHF8-N4Bg9Ct9(0<>q z3nMnrfAlpzlqe}dhpdaxZ54=TQc8?XGJAja_44`1GN-gJgu3_j9SK7lvYhvJ>b#Gg z)lyNr{-CcEF-ZCf4}n)3o9`Of#cT)(@(do%L|GCiX`hAbL8nd zYDR%^S6;4XJukL`)Gd+fZ=8VpEnouaNL^mzz4AG@t{-aKpxPH#z@ONUC`e5YvJA_y z)GQC) z%lh8>;v@t2(5PX|h38oWXX1~17uZkbou&n$d0Rq8OZY zWs@VouLZ@5=r(+cu_*vz6zCWe73&w{J!g;7>vuwjH@h*B`U5^3~>r=tHeew_Zy>xPJ2vb1)Of2Y!PcJNk>yr%=Wz}5Op(j8SqBKynZ z8KTd=ND>(m0E@56j7l`BDu<_T2$lN1A;sy)=LcyA!jI)75bx(k-9Kr#A3T?TtKy$x z0=B!CxZ3jyI0WiJx;9FvVjTwO`8bl{_{OQTHH+y4O!wNU8IpHJJs-Gi5C;&+dWOU9 z{g!6s^U(4o!0;~sPR6|l8yl`kV{s>+^LRvH{Iu%6c-E;nP=NkK}+u@+rCT`hyEkgFox{@npKfUiu z8U@kaIOP`$y1W{uqE)Iu(xlW7s47AXozv1x*_!czj>!oC-|u!}HT8P%LPu=s5_Kg}mZGqKN`L3Er!QHO?GUx(w_q2jtQ}T^tjjKRVHO`Po(n@pj-YLD zB7U|C#6!ri3RJph>ZK&xsag{N;r;DZ!sf`NPzA1e88M@nI+QBVfo9&@!4Z-JPb*i( z!6!`)8-_xF`er#T(R?qgJY2~11?noCu~4;_(#DtxvTg}N*&i?R`wfE)+%dF5OZt{l z^Rv>f(W;d1H;Lq$`gK**nkzx`_;_>}FeGi`^b;Bhp;ZaP^H*`Q&78kEFPYbBpcRwE z=M=JJHu|}Z-ZAX&;>z;=t%so6Gx1p&HPE&epxw9v;*XQ3smP;u8qcwUe(ab1gJ)UX zhbHj<;u%sO5nJYB!mv1&NY;ZWi^#;!|3)V2Ez`qp{>y-Ve(^F%^aI^ZHmQR$ ziHDIcAf5H#XGLs?8#Tv!`;5 zEzOScsCm5lz`AY7+2RC{jv~!wcsM(&y8Smg`Rw#X(`kPN%WO;9OPLihoFMho0ieEq(`E4M4C&o#g+z~tMB z$N#dyzS3d8rTghYp#x^@sd(dh@6?77O`AVU!D5Du12e%-HM{%>r^%->Zv|bM%6w4Y zUgaW7B3n~$AO049QJ>fGSUu7qyuOakF3N?ktTNLL2LTVjrIM8#8cg%_!w2At z1FCFhLGwS^Y>7P;E5ES4mPJLo(qgRT@`BIl z_{K+1R(mgHZqZ6_J`!K&gf%{22WIV20hLU(LJw9UwPu70^3oijrJU7d=3aVIoOMNW zj0J(n3?pjJ6Tp%cIWN+@kT3(XOifMjl##kqckOR??Ghl{yo*ZsgY;iPW?^=jLo(2b z`~CUq!C(oOHc4z+cqS>*Gn{iwf~qooM7_w{ou0Gkd0e9IB>9^dx!1fsogWJDpbg&H zs@RXYI92IIuhh_(ru7Xa;=QTqDyT%70aduMS^%EGOWhhMhy zS{~t{0U*AnqDIXNkaf7s-xm1xQ_zx-2vt zzRHUJ*}RA0>gb<5sIgm}x(4he?W0oXX>G!3+=xRk8HuY{)6Ga)5H}}ET8qvCJt|zu z-e-r%W@LsY?N@8jY`a+Ok9g>_N~xd zKq2>igIC*!bk~ivRaCFhn4MC$I1!->f8F~Bj>!|?Jl(>w_aFb5tDztFLS2L80_=~SMQ(4-%WkP0Q{00#n>bd`MqyNZbd%}|3LO(y^ z0k19)n5w=yO&;KqQK5IC-qc`(2O;ud+aXfky@pvr#k7XK3{t(te{%%I3<~+g0Y$p^ ze)Z447FmWxgn1Zg^*~y##J|mukY@K~Y=r1KG3Nu% zaGc~^rU;+zQF@QG{>EZY*tXDaY=o-A;C6ym}W?IdJsoi`@7 z8Ne&7wESLrJYN2ksXXtThNl^zIKk58j?9rbw^a_vE3#+3}0}x^29x*1v z5S!YXhED2=*Xv3aC}cO)QOPOfxIwq=wgq)fMlj3`nT*?1HWHj#x|@gw@-QZY-E+XXXkrET0>;%@U29Wd;2?K zz(?bXH7o^gD95+-WIUm~7m1;tUKrxlzGrQT5(>rZ^t_>-iGe4CT;T-E(z($UfoI8- zJ6BSfGF{Viyxm7pf^EGD#I+V$xk1KpF0xkVa+*KgDqO5(hr(ubq5u{G0$E%T|eyJ78>gRb3JEvub@)!KHOv6qit6UfmVl|>h) z+rO+$X0d5wiJOo_JocxpQl%wxnbe*Hg3E#rlL#?36j*+`8a4e zU*N7wX8bbZbDJ8m@&iN;0;-j^L4>d_D zja{sI*H5XKRPnI0(p)L!lvipnxeCt+w8UlanvwEd`_=8B>-VVvsOvPZcnig^I3zWo z-#lU}nVaHBDPyQMznDc=_^0}yG=vi$?g-R+Yz)?U2yJL?1_9kXABA1PJ`xN)$AgA^ zY4VdHU|kOkCYAI0SJky_8lH;LEfi(eOSU)0Kjd4=9z^@IwxPjoD&d}2WM7*H$HyWo z#2P268X6nMLsaGKGhaVirK`~D<%b^Eq-|1FW1IaE$N}rpSHIlC4pG*ln*CEk#}x&R zeu(a1h*O+oo&p@}ln=9OFh7+Ky-H6kMdvcsq6=wT&dqVRG1@S{o7CK?-grpq?YYt# zHm?j29N8~up7#CF``2;J+9IgZ+#;bJ?NYa&Jwq+^YmZ~IQ`jHyv)Qd`)<;6`&bpCy z6QPFf@zSy?SjRnJ0!9w%QAGw&@`vfrk>rp*?=T~`ToJ%0>icIDi?lcXR`fXz)6cYd z;Eu<)-tz1)t@qERL95qT=@9bg7n88d&(j}ovt5d_Wrdx=kcH&Og)YN+4VrQ2r*Ptt zDf+J&M)gbxD#hsBa)>{M*nZ3c6sDcN=_YO?;Z(Msy9#(7={r7nFLm#oKUmY9*IoH} zJfukm+Ry=%dc<*T9=TXiKdPd}>;!#TZAb)z@Ygi3o#oTF57#FPIVgT`WvD&sY@P;k zTRCn;VeQwwXN~(gw9`VXH{r5SJC_`?UPK@mz0AL#z8aY{k`bf#G7S!>4`EGRL}3cs z@eR%t@xkL3wL~gKNnF|?H z-PMD$)nDKd!H?t5kbfk@EqFA5s$kJ>$0Hrn_}FN}$R$f{&nZruQ0(FS3gU!#LR341Xy0=XoOI+%40I7!8kr@`ctjI;|?DkuO`ufLcHpP5EfpDRY@XC#qw>GUK2O=7sx zAxQ>WA6{6Q@ifHoF7B3y|GxXK*GAme2(96~5ksU;Dl@d+$Rs|3CkdmmguYyR(XS;V z|M$l_V&B8B8F&gLZ=8+M%u15S0EB-`4AMI7S%XZS!xc4Hl0MknH>rI)`Wi5;PPA13 zo;#Y5N+a^c?vhq@KUmt_C7>~MfDL5S&{Vah<#R3B_u1)DP9MF_spb~D`Rr$Gj;_)g zDJ>&cRWj!w_r~GRR>FBoRfJW0NOZK+=3Obrz$;sc%;I2al+jmSZDGX?Z0QprwjBod z^*fxUnGyLvm=}lCQ4&tl-E8G7V?&JqT!G?uwxfhcA7F9+{L}8T%fbAYk-k{JesR+p zbfjMIQODyt>b~Dhacq*E630x;;bn5PWHzBz~A6IlA>#?bU$7cd@jh z_$JhfJQo1Ik(EX_dP=ZkO?wy2q{EP$BW?AHx~%Pj<7;{>_$_jaZlI_sw9g>mTcdl5 zuSt8m5*}>O##E6DsMXp2` zeSZHXVO;jt(P|4PC{PV96j;k2_0zp=c3B{%VBQ%Q&`|`+@c9PCZ;C-T|T?d0%ZMU)Nz+` z>a6iAll_mp|4Ki{LHgK|ZW(89Ozp~g=2u75C4ZGDO2Ph)R7DTSqj~-Pxg~ z7D+hVL_L%mMvzlD-(oDE$P0((Qt9H9l>Y@=UG;mK(tvcKXu0>){2EIY2(j*l?g<8O zIm|-`evyzozW>|oC<_8gH&*KpEwYK4q3`$;zU>hG4|kY5(EZPYdAhL|z4sP@(AF3q zxfC${1k;?@pjbgF?`$XrV`m6Tw{Y0^Ls+zMESHJk`Lh|aM4WHdaNxIBFMGw_t~~=W_FMuBepHnM zI0SG-%}POMcuG1}X7Z6v5Jwd z$Ng?xQm>$!R5#kOu9yF)<+t8_$uTkqu2etqm@}1t)V%^}R%P~rW_LRk>RVWE;i_8? z@lC{-x&Zcmp}$q1>Z9rWQIaHJZo|dp>a@SU5OwJbO8wcIVy8%&ADlfbE0!p=<`~28 zm7Y17Opi76DszpOraqY}9Re7U`MNm&MPEaxN&ad|TVvoU@fizM#H z5YLkeUrVwXmA#_Urc0}!-Ov{uT5=K%uQ!F;BLD!T7_X3YtS_?c$Y^RUj=Ei?TMN6- z)glp07uU4pTusc@|QjOeXclYbfbbaE~miN@}RSQILVNbbhcr0!pxLA!$2B-Tv~Pi{P^)jot+ ziGrsuHvS$IRMPsQYh(F({FDl%<)X+lR12NiE)d;(ABxpR2W{?ygquZ5iM z3CAyezCx6e^}IBa^`$+-3QcaLbp01}d8v3g__hFrQ{6mMu13iNjBS?pS@ZS&{Fmrr z)u9}QcyY1iM4orhwhs`C-f_tHxBC2d@mJRESB2v=J=<@sJE*ZcFwzO$<*`Ell5mC= zp9DSu=M(bOe0S7QoAD~wPL}wJ7*NQ?Z`daR1|3_;5+2^=R-I9S_m4kgMMYW=wZbSE zCq9YGZmztQqe2GynmGcyq6`-`M+jjmL@@qb_+CcUxfD;guG{DMbR~&1?Zs2eC zxg;Qp?m+yR3N9L>m@zaAMK6{BtKRhCb+*%LU~fvx*^0<_It&8Ueu=R7+MUr zdYf#*dq;{gHVr`2HDh?jl#Hgl%ZIF@SBtgbBuh8W14(5VvDh_>+O1>(JZ!Nb=%p#p z9#<8Q2nyUUWN%yV0#x1K4O<-2nAHw1x(H}jSbMmNycM8=IA>UWa|Pe)mHzyG@b@(R zbZu|{3cmmlrc{pGMPI5e@4O;ij5ltiIyuF6UD2O@*$e1_%{wP``}Zp@KvKb3?L(L# ztP3Bxron=c5-HiRy!-56oYFW3S`hj)6a(Rm<)9;qX9gAE%lqNEj)<4T0w@;^l7W>+ zLFLfy=GypVId|Vq%(=qEK}gL)M`v&_$&;I8`WLLJGAj>J%>DDY#4uMvHS_ zi-GHuvblXfE$L*qYF<`_A39Rl@%oRBs59|)dRf)u^mN~B?Hj!1x>T@zkJ(NC5?DLb zr%+8C`hvxyT5BuId=j{Pc#GSyz{{RFhOgF66TmTQ-^&|~BqgK~;m58I4fOBu3eH7@ zmJA2g3ouU;?)z!P4Q(1%b-W#KO=E1Y=z3`=QA90hQdHPg2D{c zM!;CW!$%V3V4zh2|C*L={MEU#2sg-gP%D|dYp5cMhA(M>7TS3xr<7;6yd99ofi7K2 zWKozR@gA{eis2~7(#$32ctsF`^w`S?P^S=ld_?Z3e4V0=LlpcnFW zKEp*z;}fdi1qJkN#UQevvV!_-iE~E5hz4SxnOhk7#q(7^Kyl_;tabfW31Tt7kGNy- zG|ODDhMG(MCeW#Rum#^KMBOm03*bybf6c-I?sFOAZ6!XJB~cSk!yCy>P#|n3@>G-S zH0>i&MYB5SHA=o$Lj!-7Z;S+sD!SAcdp%2c@yvC>VmivAkJ;iT1b;!-#sPI=9lJ3s zs=(x;70!@~3Wyty2yz4wdjp!_f%?39_}c9+wyfX)1lA13`%(?;c#r6 z)`}sfxm`nsB4DIR0_=&9&468JrrF1bDUvmauB%jp3Stu-vyL3qWgT&tTy(dJ(-QV- zuKFxdO2ubPsk8@sgHngWQOh9PKhKJ;{@$rJImB`$!YV|eWPrXbWJ8rGBFKGw*d}6# z=n=w+Y@9ziTyYc9g?$bMFly$%YB@j()VP7qY<5rjPIcz4b!Zmem8I9{Oi@7mXOEy- zAiO6a74!J1i<>z)027o?dJW62`zS{wGF8!#^uoC)XpLf;bEBnQ5%dxyg zvbh7qW+@MZ?)i1;|WA6xq}}uuuPsBd*}$7kR4kEFdwIFgj|~iZP2e7;&o-q z_0_!EX=$}mPIC%F2f;};hm7NP$u4IL#5o{X%2tUs%`$Qv)jbth?={;HpLf`p>XK;N zkfogtLLM^DYuj)uRv1mxuwFO)rDM23KUg;UA$%F+$sQG7Lqq(;ZQsOS0-TOOhoz#t zm&^`fI7p`gJegfRaT8WGn;8jI#Kb;7xko6`L*h)Pz0HB_HWjKdikt~zsUL;|niPxC zpWpvQ`?pGn4Qah=TwG)js?ie2wF{D$3-cbLa1g0=9f#h5&mghlaT_BzD)Bm*fvO;e zlxX7fI;I$$`)g4?O;+{_3%i2Aw_`DZp$0x`uU@G%*rXI*#tcblL$Y`fM3Q{`v zKMfZhnvJrd4`{wyi$3$f(#awk+Xc$}1h8*8I zDd<|Na!C$M?%b=$Aa|;tHscqdxARg@^9#}x#2EgJK+Zc?Uu8F0PV1HibrD847}sI| z_nyMYe?1pLzSrwILOA7C%Y3G*Havw&&j+&=68$L3jbU%E&I*(z2aCIA9#!neWh zHR{Z^X?~v*7sxERvhRK_QvZjmcZ{y&d*Z!g+nU&!m=oK!ZQIF-ZQHhO+nm_8Gr`U8 z`9E*&UF)oVb2e62*Y4h3UG@3?48k}IpBS}Ikt36NFtV{;`ThMA_`epzqs+xQh)o?2c;=4>cm#Qrh6In)^=Zlu)q1>DSAUlMsKY;|VRrby*e^nYj;#qr zb$1PH;5!g{U;&zwwx2ngo5GOOm#w4%Xe4Mx-tM$|()pC;VuY>XEwX*EI$%54ZWJ{VnIz%0+d(i#~=lI8@l~@(|9wp4|8iFc2thTxESB8BJ ze^@X7@REIGO~|EkYWzLf5q-~pc;$#^%CTsPbBc$lA6l#RA0@9q;n!Y-FscRaEjs;Ch!LN=an;25@qe*@k$C8iwwI zI=TtOG}Z_BUh^14!*cUT55uXLlW3RomrBMXYb>%@WE5fteQH>x=dJYaXkkGELL-!M zN(M-O7LHt0v@V13b9%85*M}9a*F2T%g#mPG@bY3{!S=sz>nB|>hn)Jf+7n+akUSF5 zwh?ilRf@ynx;D7``qE6@Z*01+$8mJC{1cI2A0m?dfcg z=pzxhC~H+;M##p+V+tcoWmvlK9BEiqfaa<;8)PlS4JMsK{|TsP#$Yt5VqH$rbHFeE zGgH2;eh~Byo^QZ#(p>~7r@c=)j{@}LQ#9WTLEupK`-mw+Q&@GB>@$edM+Ti#k_waJ zm`a8Tr^41KR};Hr%c=e-r|_LyQ`2}ki=N45(Ug)SO7aGx4*>`7;jzg)_7ajN6qOfM z=(au;{gKKmlZH0ZL$A^7Ryy5eUiJd>nJGR$lP&pSJvdI8hSn%6jT@Z4Ap^Vv0ogRq z68)6$vQ)|HZ1~5xEI(}=R0@uhx16< zV7RU99=8sGi+@i8%za-ECeKC(b^H3f-?-qBeE&W!x*s>qox(}4`uBs`9Q43QYr&vq zIU*!GKw(IiCD@zeRKqU@(5x2w%9Qs99MgrL$}esXcq`mi7D)?&O##Zq;q*VZSxRe? z1qv*Xt~jlW+;l6;MPc$(a1wDd=r2Z6nxx~5H9eG?35(KFAzSp(>}+Z%Awi@!EXCU44|dQ?JTLPZmY)x20` znQd4(Z%R=plK+w~BLMPRO~7WmfRe`pT;mZrSD)Ky0{dT2ZcfjyJ<#q&VdLd;Y=?v0 zW9YE*pS8sicj8KfAG`Z`#JL7axzl;9Cy$DH8b~{nJSHQoo>aDllQHjR;HQ)XL4{ZZ z83~MI-*h)<1#tdMZRo1b-eS%U_9=|VW@8d|>T-$c-E*8CiUM+7oXBqiWf3|j{>3SZ zUgv>nX^+fum5=`sK*#4=6@A`CqX>@K?vgNf{6_k<-s!xy>?=z9#3J#m@*+}hf2xe% zMhf0+ykJG@_Np&+}}x;LZze95)qI@U~6!snJ{aeR(MiZUNPG)+q{U@Pev5mJ^_$?5c;ZK+^!QdfIp@|;P~{VUWE%mp{E zbftvhot%BD9{Q`}YVj+-WJY;8EY7I8(D)R|8|SROiim+e$7Mumul+{U0;DR#c#|S! zfhn}MwpqVPTn@F-5%Sf0WYK95;!rd9>ka_A>Z<*}lp3LqAJ_{E2V*Kf7zi#v9WDSU z9C(LqJu`l=s>lIB6^SeK!?$8=zi@ra(?$xX8nP2d!rHaILS3$54aXOEsBbS9D=X;R zdkug0A@=qiToVwqO8>;=G;^S5uvZH`xC6*)`HcB&8sfWEoGH;Q#5jFOr5{8DpbF{t zOLBR8;DVX?#-&)?gwS{9@;LzLXfY@3iFmrX=!Ot@Vd`#Kk~uS%@>gpwpUpO675XJF?-2M2_C?~uR;a-lNXOq zU)(g9ZMbg|=s36%4-UA$9OMtHdZ7Tg+&zr{FRJ5@m976A4P6E$fRPtqVM{aj$O_7X zIa@`Ed^ln;5-jBMX5%OOLvC(`vgPh^vMUx+k6Z;Jm((rzGQWjR?}9r zv%*%tt<)g%23A?x^g-L>=I>+DwmIHyxKg(6|D2kml3gm9oYg?MX8ceRqw9q_ktSVroAjK<6A!OwGv$0{4}H3k1g8AMJ^Z#c2*?x*Omtv&!1$qci|{uy}hX z8|`+?Ks?}oOY-dL6Axi<1qDHDuF0XfC{7*Ig-pJc;*V{aK>+I@?PWc@hG;4aY(@l8gmK94eXzD$H<{8=z6oB+iNK##yt4Y7No1@kIlP)0yA1lCwKmRxd>oW|HJ8O?f5 z$};oOvhJGtItv?rNt;WWj|DT+D}m| z4$Z_|A!NAV)|%PUzwnx$N(_A*R`oD2I@t>mxWwQXKrzuo=LjhS%&Mw291VP_#s#j? z?5<%D4h4%iPM4juCn3>kg1%%CIPh&?pzYAse^nM4xpu4!ivm{K3UP4KvctRbT7<++ zgdipcd(td5AiliEC=ku?lT86o+hqVQ`zw^RlgMR}3W}j!e{W2cT1OB?oKzRYMpiU+-Ig!TSiCwkR zU;W;;-I?N^tTZ`q4N1R!dNBYF3cjw(e*+!!tVDS(X3PS=K3jNw!nkH`3}31Z`h=c& zZ@7Wm-rkfibEgK}n6WiU%pmu84hFg|&c>Jxqn^mCnMSVk_S#|0Y(-&D(lFa9KdfwT zr8RIZ@~;%l?*v0S__VZIgc|R(GXcNOkDYC*xz=3bT4;?LeAu~mIV=E}moBks8o10q zUo<-$N$oWGpoLa9i~y#v{T2|E9qzgQqfJP=+@eQNS0GB*gr0FUxD$(~04?>~P{Y|| z-vCU4y?#kb+-jsYk#H?rCmUmo5i(&!tj7PJt=Wy;mQNgBXJw~m z1rV-EKs0p=*h#;j!vJOp3lmx`e%|JqZD*W2Iri0>7B6Y?< zUOO>!&V=@DBClowXqgl>$-D`ROfXhS|2Rh3!9-;YfB}E8X8~a07A~Orn_2PhPe^)S zmo=6uY&(?HcGC2%Hb;TZTL|}qvT?HL8s!0DN?`z5BGH95;$lK3RzcF334cn3i?tG> zi4uIgVnb!D)C;SM2`XbEmNdrsv6}43S^*1l%O)lwXB)p5dRa~hu2lc@d6}?Y6G&&_ zs+Oe~ho=^w7Aqi>l>^4qWVoP~dU9X(qep)8LFb^MfaPFdBiO_VBwf{M8W~VEb!QQg2S=OO+@#e@X6%6pmP&~@A0ppq&&{8ToLA@FdN*m+VfO#Pn6bs>^ zZg4rBT47|umWe+kQR~RTXHdH@Z&|3d?_(d1wBw;j!J5>QqSDh#4};7%t;9CkGa{70 z@XU9wUj!(_BID74YTFtf;0PUf&^hU`<%l#XcbmAh@RvW62ECqX(2@p{spv8crUB3vYe)u!VI~d-;o6_J;G72 z(vU?^ZMB`RB2$zEFPtPKf7G*0;cSTMJKd>pUZz+2tAKFTAYY%3oYpAB(fBm#>#D7G z(e!84Kr%MGCoYm5l6U2sDtuaqMcZwWx15)#XIwwaba&EeF8l>2+%RIiZjHCWk~T5I zwFI2`z|}*|2dJuwF{(~0@Vu%EEqq8J$#5xLuOoRos~@`z?I<$m6p|0pOH??!u@rI5 zC^mIf>)A=pQTSFeo{Mdo(pRgW71+gF2IS6pGA^@-$x@V)HxJk~_G7cUnUN@7Fn){j z;0#I)Mnj4dR?6h16-UETmkeD|n(B$I6aox)O#K9nTmo{(AtS6#p6Vo=)=Wr@64b7+ z;j7Hxm_lM4d7C8D3#P3J$*k~9;PMoCooZMphVK8MEe^zs#c|}CZWHQzvP1&J<@*K0 zsIBXcW^@N3*h}g)08ZH21mFidL4W($Q&oGoZHgGtVSUewZT;DNHJEs{Ol= zRzIW-2D_8=inC&WMmbYg^|}pBYh)p@|5Y;NT*)y>elJXHdpV%(k|UZT=S3WswS0QG zZS6XO*|1O~fArfd$1i@;0zrXRh9A%&S^aPI8E9p*y!>C)9{^rtMJF~6h~)-eqjaHGj_nl`(1^t z4iq*KyQ>8@w&c1H!tryr9l@`R=&+$Ovg(huaCGY|-vB$kfzqSljJxsOgk#ol`H?dF zQhw@V`<>tZ71u%M`7}?Bs=g_|8MDVrk<1MSiyJ3y4z+V# z%W~iS(Pyy(HIv}{IU5N@Xp{lmxe&e{!%iV@4mEOGqlA~96esT^Ynvb1dhB?^$HaEt z6(lFb+m;gqwXhwwr&+l}Enc~2i@GDi7yc=J3>?x+Ztzm}D6i-#e)_&ye-`r4`zy3^ z{@@@YJ8AQB8aewzZ2#jX7$e^NlBbu#!Xt;N53$V#^9{B|o-$jl)`|cm?_szm1pFy!h~$?|Et=$MZ`R$?#OabTIJUNyM9c8~*gK|qqECopqtnto_0 zCGu>g;XI{eQC**r?YPokza!E3aC!d~1Kx4QeM_+7q0k^=peZ><4AlARnjj>59}Z^| z#%(J-u^y)&li9$+dyJULbc}8Q^2_v+lO%VKu`rKAW&WGs#aWTmr$fnDPt4*mPhe9X zA+R$3n=9d5cSTD>9IC`W2>Qn6Zhe=E(f~ib7YQO%VxeC2%Mk_eiv9-M|Do>4B*;wv zNt>EAA|yRn-}a##(y8y{E{x>quo?F&He^H06UZ$rtarq zD4)3A;-+;1lR?F-lJj}EHiTMR5H&2tch?XQa4FF~Zmocx>$CDi$K88K9+Achb}Lc65-4deeIo7-T`pJ~IRc5y=*jFcZ1swzhYhJZS* zAp|A&V-^4u>R4>^7zr`DJ;y)sbYeJ!Zqh0ur5{@oDS_P|Fa+PdqB8GgQ>ru)NU)p|DY)H}^0+6y7Zz%HfUqfAp`hN>U9eL^o;AC$) z-f#;fR}va(ePZAeqNaqGS)Sv_ARdFR)p^c+N;ySDIz*j=f*Iv#2rT_1+b5obGmOPO>b9fX` zTCFq+@6DRt-{s&f>SlDH=LU%19w%b+B?OvCNC+kSrg&vi&M7PTVP_}OyD8zWEg zIVX_ag$hj@B~~GXQph!kF6GHMmt+9Gy5c-93i^+nhKxS00Woa{a;}LzfAsH$Y83Qc zv`@>qRb(rcc%*71`%kdOU)1i5(cPK<%>@hnY{nggtzMfF`)Y43z#fb!W~rx>02H_$ zB*qa0VY7+qg)lU=0nLR~YRN1Qa837IwkLmciTu`9gNS1`}05)>L_SQRUG|x5td5sRtLu7@M@L-knweY_m<9- zMRjIYdeoQNo=of``l=uZ#0T;!^#N0Dhd42Wn-7{4@o?1-0qW9Bb+hbaQ8=@9oObpr zNd~Q%60ihQto)#QvZBu1JxdG!tY|?c#p0I{!LIzGn#|-bnvq^Zf)FN4+gxmFJO9+7 zx4m)x$vMpl!S#vB%0JC8y*OxGm5a{v#q{a(4kQ!saMl_T9>yActgaq5fu%x5ZAPL^ zqKO}VdVF_UL_JgDTLq==Ksm))xO&zq<1G?Q3K$)jDhav+&V|J8TiQI#$DsVR1QOVp zI}_YnJAY$cz$n3MiJ^Zm)F(u1PuNfXTFre~+Ldhv&eK6oQ@Cth5|h!^BvpS~`byl*}w0R;g*}d{I4k!PoU<1O*Q{(N^A4i zMO|^SDKBue31eBYr%IC(0LzuV`j|4-H&`Y;o0k$Bzg?RmewV2%RciXnTm}=%Hoz3; z)wv@$PeSN{tIR0BAX&ugOvkaI+}6^JQJb}fyY!}fi|ie3fxL3;QIDbPNgq_QyMT=F zXX-EBKr-&1smTb3?Iuvp*QTmi|Cpm!yf0g?JC*WLhNd#3Lly(L$CQhew`-MTyCpLJ ziW>;MqxDnehUs`i3M+|L9x9{6-y`ZCF#G=VvqK05{uul8bw_ya4Xa7>&G@=w_RjKq zjJ;jFPp+0Keyj@0sha$&*pMriuo^1a{rvMm{nhU~zo>T{nxWBCZ(na}fSnn8gmgS0 zakVk&Sw;?WI;2f9%AO{&Wf zIaA^foyB4E)-7!wHP!%R!J|(CbLc{s9spukP;am z(MG9-9gVi){_8g;{t^PwsT;BEKE|-b;5es}NdOM>m^spg*E2!@d7eBVQ(!dUB08X8 z%{nwQ3h7UonQKC9|BWQKoHmKD4grWe^p$hN8b6z9qW+}k-pd%SPJ#YDgKGKQazy3zB$ie=H>S-~jlZ>|zFcBAeb5@xWBZI*>RYZ12?6#39v% zxh`!tH8oJJV>lguV-eg04xLfPSyjd`{NauN-)CbTvOllrRob7Dcg7urE7msI6tWTk zKAHmvx4p6EoO?6^=ea5Ry+ms3l82Cc)ABrd)@b>m5##4f2%a0CWn$uqqC%njE^Jjb zF1GGBN7b2E4ILw=VF*^Xb|8{po_0tAzoi1peN~lOc}O-1$M4Kg#8iC?GK?uTIAc7n zjI5|)hGKe&){n4}2bJM8AsTVftJ%Z=Bf~xif+FoD=RV<5ZGL&|j z50|(u4rWCt?VzXc_?lyK7I7K`ZMK*OX2_9VXh2li{XO34!!rm4r|KpC3DBmUNztuL zg9WNOKguoL(LB*>1v^xQ_`lXUls356Q=V?}q;n$sd|+|)N9rXVSK7o~44GH}tJ-Bc zb&V*+WrmQLnE022$dD}P>%?hg50S;h=_=K~v##N0!`A9iN7Cu5P9K*t7C}9{%tnyL z+4xf0m!=wGruwtADAnr*M~q5A+IdVwl~v#Q)eRK?ardy5SaNiS=Bb`4NYPHNq<^UX zPEr(Q)tXOPo%YweL}LnO#&Yxlyo}x;PW-zWda>H$cE;7RZdnXqIvl=+17CS{F>mH z5eYJwbyc}@vMJPpQcT@oXlow;cj9U9D|@z7&tiBzeO8>T83#Q_uNBh)Ak4@_d~O}V z2dJG=N?(1AWevACJ0_$9uutRHN=nbuNP}7atWny>fl?Y=3O%w($t=)ID71vbYDbA76xA}+xY}ht_0B61qPU8b>zT}geQpo!6qg{QDz>K?u8@?2JZu2I@ ziAxVLusV0o!t<8I;-~B2W zVs~cJaqL=^GcrdNRLglW8BubC4ot#S!!noKN>Eh6i1xdsNa@1@(A-}SPgMTa%uaYX ze+e0Akh85eVKW*xO+o)tbfElKO_s-ODp7AjJc6AKy}f0b`*m&Q*mF4MzE)WoQ=0Tp z7th9^l_k_p&|;4;KA!NSk5J$VA(cAZP|Uf~AFih``TG_rW^|VPvYV=256UyL zPaK3Bq7~Pzq4@X!z_qUVV3=ju!JqxI6Io#m_A3NUz7zaDI@fpW2=34-xOBfWIbZbH zk)(BWYefMK(}=M=AAUpU$;Q>{%aJ!)e3kNvA%D8-`s`s+1yXx4YwtVzT;JP!j`ONE zX>>|5{k*FJYYm8!c?c~sO2oFutAE)L>RJ*-$4yv8=Tox-@U+IJ-u?`&RmNdm@vvn1 zXGFH6XbuOxX$9X`s!mV4_TTv6K-WS>s80Vr5qF43u?gni7N0IQLW^TObJ3C<3*PA&AC zdUqKU-8Z17hh)B&(*6mY0t8rW;-7}#)QfBBzEr(HU0}#n92=N=u(?GG6L27uZ<=I5 z^xG^p8jvB)8B$7h8p&@hi$L)fS$AwECc@vCaYYvl0L6ZyB5(WZsCV)ylY=<^^h(gC zO3B?@Foe^*kP`anEs2y(QtMuf-jVQ}Eq(e^*OczK{ zqy2XdP*!Tw^F=>@l>hdi8D!F@vn^5?9&t>uJ(&LSzTGg zxeaZ=Dk{O7yD;xwk}ddCNy34v0pj`ejBcaRJuKCD5IOO0R0Ids$~pKuZINzn@-8-A z&Jrcw83$VQhgal%`+)pGymjD_Rqknr#(Vf7K?k~F9y=C$^=1_Xgbz{4{NF`M~XPQB7^$##5t5DFf?`IZY#g@_{H`=zwK3Uus3CIw4fao|?yFcV13DY&8BrQu`HLy0OA*M}EbYJBUC2`BYE< zmMi@;$*mM4Sa$IWPy-dPAmZ|^LV-9Sj-G_5&7!A|>w|p$Y;wlm`e%6!>1)OUhBcz5v1#J=^s#WbBRdb3ChqI%qX^@$5g)qFM zWHnK(Uu2LQ>JBzG%~n$ILKDNdBOZ`|Icmka`fR3H3Ls}BNpcs)7Qg9%WF>xD74R*l zF*{r4;|-}T1nU{bsA^GmLqRC1Zjy)Gj;U8=TpZmAzY+sz7?elGZxGxK~bN^9{^lenr7roHC9}_Y)c)4lPwc3IN#tY3r;HFdX98( zfO_hWzJwg{J?GR@^ZVst2}6CIeO23@de_pX{qLEQihqqNrDS<6dI&dnzbn+ABG`6u zLkfS*m2t(6*N{lpmP5SPGz-ldfnLsAvg015NM*-tF>a9e`IA-YYz-udJN7xyxk;bd zF~EdXRj)M0IqywxjA{uI!V4?`))aq5ZiG~iR%o`rq6s_f@j2 zenD&*AVS};!t2U&=)es=6?LFdKt<3#dXL@+b~aMa9QnJS*0PG;k#MbczY&GBRWsUlVIVU_Mns=**c|v^I>#8yoHki`CA;lR zqu@5EqYP9oY1_*T|C7e~N6(WRYL>Mtb3mrX`1h9);rcIod`Zra|Q z_dN}?d<~QL-eOCNP^^IUWz5Th_Fvb4l8;b#ken3*byo(5F3~`>PkJb!$m?r2h0kOa zGqORkOX{5CpTrWPt!SG18i+95BqHOFIu72#z}9Yx^vOlCWr`0uPh}Vv^s=xAQ&r$^ z!@6g;+Xso$JkhW6RYbrm0r_bU%KzderdvNE<$oCe?}*7SnOc(8t8G0-Kp(1)JOL<{ zs6rle+(wHRtm7>&pB-Xmfdt~`zhY9wf)QrlXRX>?J(Nq&tN9;hjN;Gl@7}5aBFy(G z5!Od#NU7fK3*zfrR59P~iIW$;P}rH?)tw$Y{P*i#(`BnNqVzi?AAs#uv67~r6Y!72 z`=uMd#NmDfksvlu)d(+&fGA||V6U`VafHSudx3nxOM^h1r=FGT7Ms%>y>Wn{2Pj#jUT>5Pu_bD>RoIc{%a6tircy=5CA z3sXfm2Uo0UZ)|5>21wsHN#*HM|31Ki5M*9Vxww|58Z-+?-}4;t+gnmpvpmMosa;+C z*WlTUP?%kS`z3~=FKYa7I|)P=6++Mp_l?J^pLiJwFdq;^GS+s1_5s zHNgS`9Q=N<1+>TE&cNKUOH%s@!6nl(+yVb+UlN9f{AJxgJeVzDP(_u?8^{|dR;nh~ zU7^L}Y{evA&W`xY(Hw-sJMhBpE1HFVR(JatH){Dm^7&Aqf`?bg1huD zSE8qrf!QJ#KPU(Sl;LbQ1=b8^6Q-x*5iQW3ikH7ph^);*=Lydf?5`%UBXup{J^Mp; z78E+ZC4j5^Y0^l__Mu(wbizDUAd|j=8`2gt5jX4FP1Od>?eh7bqo|8h@F7qwApgR9 z7(Xl0x^0#zRNIPlY3A;?J#>txXx6LVv(Y0cbEEr)-N^!Z>KWKx5S3qpSk=C@5Xt=C zz8J|52Vh@}7%l>S?2P5tQ+~!u-8A>P_IqxFZ~$$$Xjahk0%Y=kbC>!t=EbE;SgV;- z{!H8d-1DO=n+3Fn&}nMX)SD)=7N>b9k0V@rT5QPV0_)7R?o#tLx~rSgN2*aZM$))> zqAa3^M+BH0N(KL75wDRg6ws=4%q-!3Bq1QFb|+C0iSe*_zFd>l&=fJJW^f{z3h;kpfd5^d>U z$To%0_OY6=fu?&1eSp<2V@y%{cGfd@i`jvbebb}|doQi3WfX9=Ii94I( zr|*y-q6j84XW#T|Mw5H(hXnSQJr&X0q$_0Y! zK1O5NjTEh;Io_lWt&Ag3kTR~&5~b1}Qgq0!O6cDaukeQr6U~(*!*Ms@6*pwPhnCq| zBXON$>M`xVTst`C6w9~ixGZGF5-rIw)m`xYPw~#f$oEJi;fwMAUDg;{#tl*|$^-5? z{}z_To0sK0Oer%1(A)Ro8b)lwO_lUD>$MQaWR|x%d^w*?WE^PJDfBQsr%#pg)ca?J zZXyJZ63&?SAOwN<`S{#ugfv3ZC+!9!waQu!H z-Qx;Quu$PHhIGR&TD?x^T`R5z# zAS>m!vDdAL{DH_jq;nXwrmw|L8Q&Vv2s7}h@HOk@=oY6@eQhS^q>E_a7XUKHL5b|+ znYEt@x9++T5(YVzqtB}KvdO^H%ZU%BPo^;e9M^wp^=yhlSXQ@3RW?fHJfik<|>= z9`^TIS;EoI)(89^sl(7oVgahlikdsS78J>1{;mzXi(Rwkf$CVDCW|(;YQqJyRe#G; zN^tn&I1EJ+k}&*0e%|2JchIl{p_o7(?3Xq9n!9ci z(@X+YxY#HFd+!BsXxhn?8H6bR=xDjvY)E#La_>|Qmli%F}F8=a`n z5=BOM?m`XVwYCPF*Wd^;LZ%oh#Tt56xdZe_mss)L6q8Z^BD%r!Y);X=3dNr!UkJmZ zh%BL$=`3W$IQQS&Np}mB>itUXD91`_OCoss+*gbOL`tQjg-V*a=1|h1mr2jJ z$}(2AMoCpqUbjX{(LQ;k;+=WXsaZ)Zn1L#V?bR{1eR%LMR;4| zwh*rkdD{ZwdQq4il~mQvlyI3nW-b-e2))pOkGzQdia5PBlG5@Hg|(&SX9H)NsLeht zqw?FloFb2>wGIp!4nrZ+XTA(S@_#ga+q2=yS?%_)Epi{t@w6$f`Ukp9Fy$O7wVha( zKtGzQIK=C;lczL$-94;6O3y*}3TLac>{yCOfN=pAd095qD3D55Ce!QPe$3BIv{?uC zx;ZhsM9MnUC5cc|Z2k_u8s~!HA*=SlhAJICf8UfF|I8h5AG%i1rXo6qm5u*3KsC>? zPVh#4Le8ju?~~ec(yY>NLbE;p_0LL7Am*mP|(qXmA}c4Z=DcoW$Eq!u(h~R4FR#jsFR%4ZS}}v z0$!1Q>wByKlHo3-4nkL4%^7OG>4|OQnhYIhFAT3oq(7q=2vouRHP^D)X2i6c@~e99 zFB>+6?r+E{X-SYFvZyA>nv7(4{|W6y3VBojO^U4Rd?t@jG-ggg!I#XcEW2x`X6Wkh z@L`OqH@Z~g5V>QUjm*;;VSIA7n3>kdm<4GgjBRq25{%BDPo5}Loc-FgFCD3zufH6f zNVKDdPWf5(%QU9ktRB-zX5NFg30BMb(w0|AI?@V^9wtZbCg9c=R$l&Lk7pXw`k7RK zKc^Hrj3N)qY zhXx5xwXf<$+ zO6M)o$QXW99xObPKbTIHo|qZ{zditIy?N??n{?!_S&AB03*~u#qr;dRE({zEFCVTb%BNcia zDx=U@xh+2g+?`bLOgS9R7lb;U%-uh2B7TJlRr1#=JSY2f{-H?dY$perNKqRMdF>60w3lGbb z^W84r>qf6SGzK9g}`4_=zz;9el7o!gI9IU zBsQ>qL0~+g9Jax$!xAB-gi%Wet#BM3>?tQ2c5*)?_#nsfIUVz09+q-})qDjAotvW!r=*u>Lb+Rs++R-dm3u%lFW)K+3SY;*37`13fr z+4%kE1lgH=;8lYT6w;ZGc9y=-5-L$Gh-Wa_*A1I)7IIE%HiXFAWE`7_WHYkOtpGolk}EB#?+ansTbKvjN&^pK z{5CnB1TDAWqJXCI&XCT+mQ3p>daxt#Ox7_vxVQ%#5iB z2(TD{50JsIZ{uZE0>$Ja>Q+)GsiV1zvu!EoHSPO%U^00WiO%(vxuSB{tCo#}7D9fo zF+@VBEMLC)MWFBbMAO@Ed(PNWe|fU4$~4{dpKOC#Ox}+hJNsWBdygBmYDm@5Ud1rF z#o4`BK5Ra63@;#j+Ldow{S>#^d_H`icl3_{<8T$}?4I7-Q~s%ND&i2lPmy?X2<1nt;8c#+=$ zZZ3l(^*-D_k{8+0nGSbgyBrHRb~bcqKbLEn5idWVPu|*ZK7ENdaXj7$Vi-smqDt>b zi^!+GANWcEIbR5=SjAg3jWJ6FbWw8B)#ftukn-;ct4w1{pMc}1PEcyPXq z@AmH{%bVSjqp2q1Okehfi2>eyC+wDhzN96I!B*L%f!4mfZP^=Uz)KrFvMSVzHx_nZ z2oLDNy?+2j8}IAvy*<~_?8DSz8~;7lo=HO^rh|1 z2V5Zvt8~?$5NI1hy&TeyJ<#(?j?$=K+=ZL7wox7gC}jT=TBIE8){LZ_6fRjbsQC2b zfHW&kJ64feTP2}BGihGJQ`AE5hBXGWts#XHXQQ*}lSdB%3VkzG9Odrf!`mg48S5ZP z{?(|6(HwQNs%6g?_M|iGUlTmQlml2XKkrd2G(cUzom<}q)ceMFA-f@SKS+{s$8%j60jYLd3}}*1$5m|Tp0-$RWGN|$2A_`v&AJ4 zA$L<0TmjHQddKnPi>Gl^Xl!mahLkD(CQ^6 zUTA6rtF4@&d+T(_FbpAIXizP0r=&R$ox!u!r_KKj{Arc1pSqYA z((k~}{1DwOXb`z{ZEggUqPfgO?EhmX6STT|yt54(I4a)OomxP7B7}%xRX!&Xs8JOd z_!5=ayQ_;}#4M0nI8Z7^kkdLtA3EclogWR_kmpImV6~fUltMgz=tj|qz8qnZ`g75I z_z&e@>5o1#?=z$mT@;zGzx%Bz5H4C8jMRg^DL3SJ?gq~ zn=5vrXiT{*c%hAIk|{`Ys4opy5_Dw}epAO&^fq*%mMp1GIG{z1{xe#JykL35kQ*iX zg7^LtvAYf>6Xh~Wy%?Tz)Hm=QpmMi%u%5Abezb_-Wh5uwMKGS!CTh_ zvBoHLCLo^5K6h*GK!9IJ|2Im!?!PVE!jXjj`=Kes7Os&t;(!ZvX+A5Lbo`4LzV<@5 z)Y2#q!d zaHzJp{MhJiB)vQ}%B2VzbJ-%xa}Z)kBSS(mYXGg3cW5=ybdC+}{EZ87eP2JwybKvF z3kpU_2{Z4{DOM;I)hNfj<}4^OPn$VkR48gdc4f%gjP<9P3qlwF|JS5)AnfT+o3ild zB0~XG5wyETjC+49$2WIXztco~U#F~q``Dm!wn!j6hIdX%WXOrWbX0?%&q?@>Enp|- znAuaOC}5MYpUOPl4#jEC0lr-xMXS+NtvD-DehA-+zS`t)V4jozt(Xi3Kf*QWU1~|> zlO14%(7=~vSYx?HTP&h3A~CCuynQ%Ej?KRUc8l46TH zG~|#>Gteh3#U&(=Mg=)!EI)*1=@8SQ4t8WhPs|)^&ZQHi(q_G;S zv8~3*jcwablQg!`*lJ@ZjnNqUeSiBr`|R%D2ltFVGxy#(Gde|Ndxcu>QW@asW5B^n zlwC-m*g^SCRvAmcm|DUOeqw*wn^7jjS%&Hx840HA>USX;w2`V>u``2}TxI4o!EYG2 z%-?7A+_dj6|NM$7XCVg(H?a$V@|nfh4%$jO!tB8nze>g|%XW;H1}X5Cq#T1IuC;Si zg{)J*I5SfvvdgAINf)fuy$k$f(uX4=rq>j4{QWvpl98xp{l%|0?_77XmSNSJZ@v^y z!W<@o7Yv7p#cfUNheS$*L*K+boqb8Qw^5$nf9}8@8%ea1IPS~q4u%8eN!lO_1Ji~- zPp9sM>>{5wb2Olr!{T07Ma$#;DT0fU#oG{iOHndr+7yHz3S2i%aXrHqjgCFG_Fw*iem{HmnePSQ100}HAoicy>J&{XQS~^ zEnW5wf5nP z217wfkL00M@~M;@J91)tky& zG4D9r*`)sTt$z0u5||nSc+%cf3*HRt++~#r6Js;eUGU9~74KU^;Sa2@*n+YSKyUUs zgS*o{b5VJ#aXHXgeYLQ8<&q2(Q=d-;Yp%rb@6WjSkj#a^g~p`}f|%uKWtI z!m1A)i=HAVc`3iXx9}<0uAr&Egb-e2!D;|PX&qH~vnh;ilQ`MC%#{-YKJ`9^NYZx5 z3$j0;%xDu-VNn><2Gg|pA zYvHcBMlg4Hp0-7((p`S7Azl?qoP|*x|>+#AY!@_TFpL52^50wELMo*MiM& z>GX6YsnG6;`IOyk=)}W)z1bT6+S)p-_g%xpHLVRj;&Xu!XQI4Vv!8IeIiv%GLK+=F zsHQmx*%3;;K{b~l`DQE^n~fnjD_bLYVQ3;vl``N!n#9!}$_|>u22<*-Xl9&>q=0Do z(F@K>81b$*Xvkd)O>4+=F>($%lO|(Pi|(FaGmZ_3x}7*(SD{~DLs0uD<@YFd5>nmH zX7rOjN}eS8F#R3Pq%Jloo{QLX0JN-@sb~kZ42uY~Y#@wGi)oR=_D4dqqR5f=vN;ev zLheTzmW3j?c7a}|x!=R>#h2VuS593S6j_d(Ck#T8UTP+C5X4ZEO`GWjYnY#UIjzKX zmPNwli5lIfnMo|J`&`S+UzoHyV^@~162Mg0(CYu^QqACdW-x&5qE(Qzd}@){6&}~% zos4t8?V)7moc{KXTeSC_Etfs4U0uo@i6iT_xzYixsm<~o{ z(fwr$*rkEC7^aOmQ(W^$g=o~<^NT74z~l?B(DzLq&g%zd(;&m3#UeB@KVFJ=)i72D zb+1{pWOjrQz(>bK7hb(NioinMZL=@&-y@X4nWr%Oz99-v9}f)F$d7Ey|44WEA@qMR z^FPQeDQQE*W_iObjHas!8 z3@4WJaDe+cQdo8)k;=syKEkgfI2N$<31n(a0XnFq1~W{QHE$&jz1(cW8n9Op++Pii zWzSZKoLw3o+DeQrV<;sp(I~8!27LY9R-PV#QHDbTvf=(g&u3RsG&?xtbUy$ zMms6ipe;Vx3C`8T3&)38IrCHUGm5hg7ZSkugK{^I0b(BI0Tl;sk(3?o`PhrY;=cT8=QyZ)u z^*9Tt7t{8Z=_I??ji`VNo}fPF4-9Ig5LjZ~%lOo514@|NdCUIvJlkEC8G7SZ#HQ(x zA{XtIKU~O5Acqc7q)>PRLMv+`kQ}+{poC6_p#DPI(6o80t8dMYnL=Xvz0_Q~mzT3p zZ)BR2-2`4X%G`*2zN&#*{g55l9nhUZLcIj**FZLA#Dp5sirbNqi#$xH9r0dH%nB7*CUZYQqh+kY8 zn~!1=mxF?7$p{(W?wmt?k*JU%XdqK65k)1`?l*L(Q_l%#v~q?8=zXWCa6%R4ZC7+L zvqW#28OyeS&dM<5qbQOT@l}l==O901b*Hx7?W(u(ANQr-xCAtXH{CW^(MCcpsLyI; zL`~uM!isNv4~>>4uw<3?&{HCr1HBpbIwe8j;1e75MiGcHmuL%bgO`cym@`6=f>^SY zywrKv$Yx28lkhdE^k}l3mx9{Crii7eYbWTBstiC>CY#@rlpqV!PcP~shsRvU2BJkI z*wb!;e`>Hf_5R#LqpiZ>71RwH)RrEB`@>Vja|=fcQV&h!$Nrblv@d9P_-@KRrmu_9 zt9PSP?LW84p|A7D43Kkm=3Pq$-PmZHJHa?+G5d(Ke6x*kvueP5OXC~AqRYF5Vozn5 zz*7T)rgGh7b*5aAUz3n(1x0Fc<4o&{E*_fhgeeV30|%|S0yb)3=E{EZ^5Gf$VuEYs z`J=P*q~C`>M}j5Id9%)NXh2aUV-WU*iDI6FtFbEZ8*ZdSWWj%-qcHWgI>_MPLb>|b z0)ivPtN0ND5XyGXrUdvU{hA)1_1c6a#sJ+~(@7C=N*@-dUMyWumSVCELDV5CmyGb% z;H4IE^x5ribJLn-3yTIRz~lFW-#mkuTIj{BWl3gAy5C zuPC~@-Zp~|GW>biPQFXuzg040HGMl;l)>ZGV0blNOSdsKUtA*tg?@p}P_5G#+dz;* z(ovK5yk^;6I^Lfp6A6@2DNK1fP0+#1B(nV(v57aj$Ed#7%g-9ciW-zF_>4P1B!sXx zZQ8h`@pzI2y>~yo-6m#0pY~qx=jYx3(BEq->hBmU&=HN9?X-E{gJ3`rsvSFoI?r{~ z9a2u$Io44s5?LkNs%_LmvrLq!!`j#$EJ!oUm^P_(fFg_&mP9z0UTkD7-IYVDQ zudiN40Ff*|jms{2dp&|Vx8)|AJvUc3XIXO#uQsD0O~|0cY`9xrz~2T)xdu1#8W z3E%2=Si(>Vd=e*-yAACUuX|Mr%8IrR^-eSVR024*Y~YLDbQe?5O>GGac%Dy{2E}^~ zXJ+q!%hw(=2Cv2U1RoualhMmLoBhlwBjD^~**{38`}>nN43w#R@NYv!u`h6qVAzUo z>yS!DoO4a5U+EB5j0MAeI~zLiu8@>>jY7Pj<;d1!(3QaN!Sfk+v*udeoV978HY_?t zA2#gLsEp)3ZD5-zP6rRd0Z!C7fTR-UPIPa zcJ&M->;P)u;X<%?T~Jmweqahy2IxL!)*%s@F_pS&Y(FzWA2YcY2kD`o7#tojT{2)q zByPxl+7bLfgR@Dd2E|!_L7J^8Hu#xk%xC{X} zm>XO2f9f5(ybZdUd&tZ+Kgei0qHWK6F2#4vVwow|zQWIL*rlgnk zcsUzv>DsviaPFfz`DlF2j1H|HReQ&GkiMbb)l&Quy;Ut3T-nBaB}h zf}`EOJG)7`aAmu&ANQw&D3ag`;>(Bd@8H82wm`LaqE}w|X?)!52-*od7=HK^>tu2y ziY(wru6!&-%mB`0*Uu)|-I8vlVrOo215@g%Ld=My2XlD##6S9E)22K%i`~x&O$Ts%6CpeJAbA>X zNZC>J+E&F6DTmg|f`U=vAv)!B57Gg(_KD(F9xuhLmA@EoVC|raGm|ePn81pYbEeTM zb=6-LS+p9##VZJMXhnnPT7ux7xxbs)%WYO#7+~sX5a{bi(>GbxZcUC!wVco(Ddxs9 z;xzBFpgM-Uo0-NNM+YDxcs{bpk_Dk(Ze`=i0;FBlrChf-_>cEeOkOAB_H6}Xdr(np zt%7+S_ESlY7koXee7eMrkw=APx7k{w64F#$w7UZ;kkaN@R+3;M$Ej5u2_sQQ{CV8? zeWw%o5*mV+yhqo9F$+Sr)*qxsGyYbLmL={gkE>K<5Nxftn?E^~=GU$I%#7hGkR)PBud9BC^llB91sx=b}dGbh8>WH?P=OOda%CH2FW^KZEq z2}jJSPiM8w;1T^1pTM%a09|r5Z4nN7Bf3^(-+|AU6Sn%>DQ?^$nGa5`lG90|+OgyV z$bCZ%V|9{jng$j*UqY`i)C(c@tf&u?MD!2#O1gIf)~s@%RmjEi)Q*tpWAPCgN)JLE zvh{xsQ(rZoTZq}LFfX;;;JFpW4Bm~Ii&d#>?&Yz%kVG15CFF903X4^fVQZ2wb>g(I zSO!YlIo+)PDm#n0pJ7TV4ad>W7W4%7rCR z`CNIyH_YPGebFXx-a_&S&N3pS`P}h--S%>7jvkHLU7-cFk>;%>`ajGQ3e(C3F;5F^ z>Ub$S@Kx);%_{ctv9ZpqMT=3@ZuD_k&xL3qH<{JjSa0SOl>g76R&SZFwxu!k8 z2W*dN$XPn>f^TBVK2i>cThqAGp;fwc=Nhc8Sr)o#M&%awMMmWWoijTJ7?eIe?4qp7 zZJZrxNERO?Nat26= zY|L0B8;`yb?(!ynrK?_k$6FI)!Mp%up^myz#Siktd(wdNtNT;L_eOcRIeq)bNvsn9 zj^!%gZ@>rimIv62jMu+o%m*d;s>}nt3-At}yzgGbeZ5#GWi1JuJBaU;%Ayvq)-)L- zA75F8l&q|Y)q4kiqD=vkkJ6WDX3pet?o1P3RtGgh7vHZ7uIhnJN2vSh$Io&Rhy)UQ zr0jidJcdr=xNu`C|29RNv*H2>#@cHLDI3Fd*vT*l*lvm8e)50XfP!|&VQU{;;q|qw zozK&9S*!$9X8qAo0HL9xY#I*QAqo6j>%~OL6L)eNiTu*tkuT7Ro&VAjvJ>SMowv+^ zx?z$yx`Z^9VM~*4m!%pxm&%L1P4%K$kJCREOV7@s9&F_6NF~PXNf6HRo9ucxAex$l za|(~#pQgZ7)<4Q5R7YId9#^I0vw>_!Wh9?*6JnM{+=~r^!E#yfDhtb)B>o#^jcUy^ zQyfpA6%OQVcOsByA<;z#Z867C8vE{`?zDJa)1i|`nx8Xv<*fsQlMb7t1vfu$6ADxX zBEqwV!TLL$7COnS^7SBkrCE$IvuEsQZ&xI40*euz#>#lo->5_tuC*jWRNW=mMN>t6 zDlqr#=pnAXP>PcwG^S8sAFE?mG=2U_`VbAsz}uECzyWL!kxGU+N>&YLURpjr#({yZ zv67|JXDvn^J!*RD$qRE_wo_Qc56pY2mu#t`V{1Ko@l#JVQ8ustt*lIZKkpVZ`1xQU?x)S$c@$Z{|V?_x>6OOYoB1(l%_g zWq?UsnF787?;Mm}eJe?>Sqa?^0(uOf=3(FRZIio6crpTwC2#*?b9= zGi9fmg!A}2HA6N|Uo%7X_pe>1FL3YdnlJWgj7X_cHT1K6vp-C;d=|9XiY>R=%iF}M zLaSo)m&hNh<%DyRFFLNS^RBk9%d+c075%S99F{CHx`xe^kh}umk2fO!$s4r5CX9}# zoxx+jc-GS5eUQ;FMT0jjVP0;4YpCd;yk6<4wA)!7bSH+*r}><0WtQd}Txkbvlijqnzm0=K)^BOQY zgZ1PF>%O1gH5rQLZFHx7zF&jC9nbwJh!!sR7s5Yc9R4Cc3dsEnX|s6r_!na4uvHS^ ztnIYCiW=PgBd{Vl4G>RT)(gYNVEnCSoXx#jI)O;jVjlx{Y(CyHw}0NN zt|`r9g*0iP_Q8QwlzEwuAf@p=OxLwEg@X8w9tQA0rUh)uB zQS9R7D!XSyrZfRh2O^mMyPCzIo8i6wG{So?S%rIpLQVy$&kx!B0QK9_Xuav2i&#~# z28^=Df4$-FyIZcm+L$t$C)uYP{noK|hwqTk0WY9z) z_^zOP#hd-LL$#rXqxt)3R0ay*HT?*PJs?EBt<_Bw<8o$H)2)g9HQG>M&WF~_aFxb4 zoIpM!UWQLJZBl>jG7qWf$gp=OJPlIqJ?9s{{McRBM438x4^|A;zW5v|?9 zcB`;7a^+3!bN@DB8Zc-D`l?b>?RV%3C3oqvJLQ?Rf{15G=$E2Zy4|JWBHhlfU$uw6 zQg59bt5<8p&bKa>?eQMn{i`#L1eZuH0w>1{N8Ty1k(L~PawT&rUy*wgE80Fe`62n6 z{or?f*u)Czc$@K3R`O+_%_rvffvsDtHqY-eVi}eKGKx^+-ns*Iah-{h@ACATk{(={ zx*Zlb!I#8n0;|nm>Zga~KfHpG=l&rJw|NnoGcjXg{`D!}IuxvoafLL~*A%npsLa*J zPq6oKnrqtcX=l9ivL0mjn~0y!WRM!;q=s;s>Of`1E@>3~-owlTv=;M;ka&O1HE6wx zO4R8>r7oT!M&ANj->P5f;Nsj|sdLI{A)O}YPot}k%r%C&W~&Z@DIf>IOmvYCBLo>AYsoYWKK6QfR-b`60PG9VP%&W^V^!d6H=YRVV$TP_`MJ`&p(}hE-$1vdtU*y zlP>VMc`|JpFEiUA;{Xbs)h6k=-az#SxpIv^Ky;j>2HzxOV_H9X-AVnyd6&gB^?FhL z?P0!6>MOjVbNqw$VZWAQW|M^&#tb}7WQMH;iC#yy!bCQm*Th-h>w%P{E#e7EJ z8!1H!ml{IG-Woh+Mr0-ElMF96TgG)KJScStawyWN@vj!^f2l)VR80yN^NR`g#a|l7 zuV7Qf_Jg#v-se(m91|A%W;s%`Vhz2x3d|a`xzL%M8oLpCjYZtKs zuXky@pRcS>B!14%tHRsHE1lO9$lbQ0hM7IQ1{G3XL8La*UYfTk26qux8QY&xMu535_(T;wgDxqLs(@!&9cMYuYj{qG>Z z0W{1%4{y@v_5EH&@3O%sxRoGe8JL$-WJpRr)Hf^d_JZ4EZyaYC&V;n&V0va$ygFa& z0BDQkoumQlKlGR!bH@Uz;yEj_+x5z_Nv#64v)}&FT6w#$1*7TpOI7l@<#qanM5(%k zVHP#)TD3*-nTR3Md>QWtNO-rk(I_(!eew_>8bbeuKLzEADRUev(j@wU2Z_-kG8BJD zi_bUCwS)Wc`=}%{T?j7ZO6DYYGhx%vaKek8xZYyNnMPK&f|vP&NuHfS_XgKE}oKVMz=Z)vqG~jRnAC9#HwTYoi z3F(hw!Vp-*z3>=9Ug{NGL|`l{P#)_97tR555?myeI8fvE$CwUX7Pjq~M4JC>E ziz*g{SRzvzn-rcn&`3VvMNX#~3C29j{5Ok*p@2<}V!lCqapo&|zuT$XF?utbe5J>i zW>}Nt8UlWyF5X~J@&vi%uJ8e#BLepOUT$3B2_>y{qAb7Nz9GpW0__BwQ7D7HE0b^d zwO&Jf+Yc);NPiM9ZMfZ4*=^E6$}fM&g|31x5vGS~8rEDBfgb)Uu09OEv%*gS+h!6< zCKui}633mo&{Ft!jy&O&d!^Md6(F^s&gxS_7Z|vRf3T1kTfv|J(d~$heQp|_Y;=^OSbg=>Y*?Cu1Ln>!7*>H2jy(qXIu#WE$AM5HpimD?5WywB3` z{HV2vAi6V$VsV*t@(-(D49*mBJiipv0yi=rJ7y8mg`XJj$5vSF7T5{p_*T_lIPhaC zp~`~2A_%`fb%Rvzy1IDs*wZ1Q(|0Tf+w;@(ne!MJ5MB=tM8ZFD!_x#$tWD}AO(Y*N z5(bWtFa!GTe$db(MNqXAihol2bJAJDRS{!NBk|=1 z(4;ieFn=opwTj|j&3`){l&2&4ar2StG1b~4&?ScS!u__D0&0eNr2yGGZP+le7!14Z&AG6J_e+WMHyU#5qGdYXZ$r*b+Z{u9LgDw7D%sx|Tjp`!N)`7$B2 zB<3^((1229kp^f0l%6D18ENlVPwZQ!AhCnoVpEo?c4cko@TtXI|GCoQ=>SGBvIYuyGa zqrnEQLJ__(Veb~21v#ugc${tF4-ltSaTbKWYGJ3Ak;kKVQ%_9rk;OKu$^C2*ZO?B{ zoFQt?U12O2$Z?Z$oorMN!tVqOu)+ktAcxT?cx52`l+>@D(N`s&(Ac zCyqy`PQTA>gj5vRYqQvl5=wLr{i8BSRV&I#j867WicS+P`i9JPQ9uVb|c6ZL`HC8cB3NlB#qD&htJfWaTOfR;$JAGpeGP#+29O$EsS~>C~^w znB*t(V^X7l2l%V$O^yeXtY9Ew6g$y`kUHo)tZbh~Nw(+(_tH!y3rwmLhbJiKX2oS0 znj9vk{mJPsELaxUr~P@;*Qw9p0?;&YC=~s|CMkb^#W|DAq66N*Rr&{yI?nR_)_SBq z{0@uWlf;h# zMGOy`DtWC;`{IOWQJIb`Dc+UwxmnbKVd0{b`cUVsI`j2MXy-gzTI0=fG^2z(O_>uv zCMB#tyZ=gNlr|9Mlo^$DRBvd2KFC=!5-^f>53{=3%@jkYcSuk01V57UxF1a;VMF7$ zIEDkV2FgkkmH*5Hb3rJEhLj<#Rk5;Mnc)95lU+6J_EKu8A*C1^eAv)kH3~VMVRTC# zyHgSXPy0`4^2oEU$Eiv6>uxk5HV_fYncR}H#*ycrtZCPzbk(QsC3ls~?i1?f z$;Q9*2wfdV-b<%(BTH6J^}%DOhP)z@q4T|}=2Iu(?$K`_N&uS$^oUS^4^8A0Ki7yM zus%qjGRKq?qytlp;bHX{+s3=HcTjI28Z(gYJImBSHdX}Boobu*1Oxi1N4rxG@sww! z*Pb3Ix*y24qe9iNXnDCGs{9@H!^Tjh0CPn~5(}LIAvw>f{mPg@*GpOQIFW>!P?dL? z+xq5y@_ZM4^TEMU6JQ!9@8bQU14WN`JpbdB<6z$0Ow34106Vx` z^UvciMcG?znLmvo10JrTrFmP0xs(}S?4K!lZ*G>l_XuHk^~agdq!j2d_)px_D@`=) zntAcClS}P2!)Rs)+gn|LL;os>OfbJ>RBQ&qIo1GihRfzK?rNbVMwg^R46&@yF~OQqX|25k#_U z^A;o-9rn!MzaINpu;PsLGq>7d?=&Y>xtR@-MWp%e91%qTL?x~TUgMv9hZ z(FGGk2y8%PX5t|Zf2WFPnhHL9s$H$vWw(9hLIL0E#Ih?5(vB$N85h&*cH{jEv-O2y zWY2N@C)B?{Rd#zOnk=n=Bwmu!-H?}tM2!-2wk~+?nGsvg8ct%TtmkhUrE8rON4c18Ixxsy3U180is=#QhPa?l$Ha}q3JI+L zBZe!CONC1lSqUH3Ey^~goP#8?q)I9~VTPT6VvNyuC>bGnALZ+B$k-gp7q5lyonx7) zkvCqw8pDA}(~KT}(DPU;xRjATMXw8Olvlo${L$J{l(0r-`-^i=8Rq{w%*-98l z9DikdXN*V(`3koaRxFiG*~g@LA~WQf5<6uV%b>haVEjPWsKeMs)1a7c%C0uBw%KgS z?Ch4j9#KcS4`8Ow@nkJMUYI3Do`ftxt!eN<#^nlg0uhlZgRB6;tAT|?;7Hf(U8mL^ z7J*t%;2Jb^A_3i^M;p+m_a)m(t58czOtPJFod%i%$NCrw!$iVtu4Nyy{86AdkmK@4 zvh4cLndr3fP~t|5mB4@f3YH$?JyQhQ>9lH9ZO`Y=XhF))9M$wu?PdCyLu=nU+gtRi zvtllG>1n|#iVrkTMN&3_&C3N(WX=w&nW%IV8rM1829r28x3s5lHcXp*6U!F16hfMQ zcAhv+PLfF2>?$q}r38a@6;Gqyy;f0rBMp6|@}?tom%$+LN#+>le_{dA+?ebUp@az* zSk>UPipM+FZu0?C5r2?W=C9V}zcWfJ;;Fx}!R#f4l_5S`N3bLVEsax{r@9ptAs=1= zW26pGnIL79X*wGT39_M#+@(?L9GaAStHC34efoAEDfjpHx?~=TorKb9?c#!vJSyHV5 zdH*F)NcuYgu>Fk+C)cs-&_s%lI^0AW#Z@Hd2IlfIfWuL4+G;eGdE119OvhqAm1+%F z5y{JHg?cgp-|JgmQ^$6Mozm$nn(Z^`QZ7*M_7V8TFrmm53VxHQ*+{%(l2y-S@K<9? za81oar8|_W1f!!J@@LHPx4ZY$e|j{LoFxqW!Qa3`fQBg#B^Npnu++(ojb~KgRBf`lRsWVXnSa~5Ngw0^#6f?)or!j?F9b{{34Gxkai;`i!hD_YmA|h;yaE~Z9?BEO7j-9% zwuI=a$|c|4DJ2slCq(*10F(z|2M0|7>yO^29SCtYd=&wabOaAwEe?K_ z=~46rXopy4B~}}rzKO#HN-*oKP=byYL}VM72vQj_xCJ4*eVRxX&)T?(w)V7a_?Fu< z{8RaVx0yvsx&*e%CNlFG1l+EiS%5p2&8ht{+zv(!s-qjDA;hWj%b)-~D+Y|9_jWirEzE6-ax3<$vFn>0|Im#g$;2>JAAM;BP(G!Osost^)wf+}ehg?68KK{Gl$ zz5^|oxzEaa-~m*}Vkoe;i3W8`hvK$RHMiHeA3ok}h9>J)?T*)R-FV%)!iGozT66Ndap8^! zx99evqq(?GEbUGpL zc$ZZspdwtL1fv@9&S0vs7gH*AFhJ}$7ON<1)0ahxAq-@TWa@_!PHCL$qAsx%w(aO^9Oj?I{?*;49Ek+K^9 z`c1)Q!i7F!^X{-X(=Ipx2Z|B*hJWu3^ODqaj#DL?iqSACSZNO?U`Io$+c|cMbzH4d zRr+r3oa3&{rb;1TRhK(W2cJiEZ3$`nk}?0uADz?7eI+=?bUns)Ye5I=d-RJ9bOH5x z8_F;<$N9LsDeWI<>gEBp2a4WMTH0JdjXrEWdO;|olSTs%Fx+edV(GD_ywC)Ran;el z{fQB{;26>ioe~(}ZZ^J#?a*~C!1;y!F6HGAgrekhl2R!0((^O|jEmqXA9%SLQY+PvMR=+{4OX13pOC*95XK# zH`+)u02tIvJpY+`i?>*Mn{n7ihW1^HL=gZJc@!};> z&Srqoy8tVca;$PrjuCFs) zyQpyL9aOl`bC4*h#XYdx1+^Ay%RCtItaV8x^oM8H{yLi+m7ZfqN`WU!&`Vx?Y~1dx zK%ElwEOa4*c+o2(#EYOlS&xGx&;QLgW$w8%&B0GZMd05{-c;tmF!ak|iJ94n4K2M_ zn4fA25Q3{Rp|d8a_>pqcmSb)1`{$TTJn|&Ax)Oqeg#=T%8Cnp7(|kiyO zkaYB`;d^4%-g#OjFM|4Nr_-xJ)!{OSaITINAmfE0Tc3(HIoNE6QzI76ivar^YJ5SnbN+bm}B=)i#Q#{SM-<>7v5QFy!=+!@f@n5?tJ-os$*4 z6f$D8q_4MJ{rhu@T^!-P1yUS+R2KJAYQbI#V2i@Rotl*Ja)A|!R9GT%j9uiD&Wln^ z$n41iT$qes+4$E_jBR1;epBJw!TTwR09u1@*(AfiMr{29+2f(6I);{9m@%?zto8-QZz zfUQ>{tu)FC4k*V$zPH1F^LU@g^n6by3YNTRU8--4*&~}czMs;P^*tq&O}dwvvHEW+ z74y9Vx?fl?`qA%y4(biT4M{JmoXS}DoVwQJS}{9}!_jP4mIm^0NU_^XvAEw(#&;d3 zh$ek^7l#kqQv@?T8GotMvHNcT6?U@rA|1(p&(6(9TShy%W&RR=otsT94eMnNuAk!t z^{~oWn(I-``Mcg7;~B%6tA!e8F-RnEg%16$=&g6MOYwvtOf}U-vRA}u)|U4e&B6su zHN*6G{aA(gKoT4~BbbkQW{zh^2k%!b24^~{s3X^dkT+SaRYdt12Kc)ou&SRKM}3a1 zMJc`&7v7wW-*Iv9&7FM{1uuawxnZsITtbB2FxkEKa?oeU1U4=Ap&^I-I@g8lPE0`z z>%Qfq^(U0V8Y2_9_?A+Td%8_q?Wd~y&G+h`SmxY3upMX$<1dCsWP$la-UeB4Csqs_ zg9J<_^*>?YZ+m%O4ZpKO1ISZFhdmh3{><=7e|?#a>*=r4$YxnINXL_Hq8>cT8K#gG zpWC8gofITzv}$eE%0Fv6#xdQ-r`5dEIbAXpnp26k)JhH&H&9rVsPi>lPpWh#NS1QT z?3VSENA&8}IB;ji(OdG6)>WI!s4TMsAHNWxk#P}utEPjFqb!LCe44@ghJ7ZHU4hpH zvuo-(;qRn>J5P_+_V8uKb@B(x!QEn9QBI7nC^g$6C8$D!_OIP$W*WhGKu{1*Jm$f6 zqB#uOo-uDvPH(Hlss?M_opW825*JO$!!d1#>y+R)i@{d z17|=x65C|!E-du{P`thVavLUZ8_uAV*||CxGC)k>_}5XybI|9io7@81?PyLeln%tX zKN9P>1KQStCLiWAQ-xeO>sFp`f3mQqo_almyY@yePND^eh(z66DG*+==2{ZBzg%PA zDrAb*ya~WNxN_0|n(zzx+Dp-i=dx#&+u(uu?JBb+BHOSSC@dJ)N1Xo#WklW?`rH&< zw;C(hMAp^Lkc=vL_@z+t0M}D&xTrh>bOec2i2%?M##l{0e%ul=?LQl5(UXodGuDig7Ixh}C<8pQ?g#>PiI$l{RY1m74QRY`3U?K+!FusG6IaD?Rpk^x~DO zjqEXjcnX7rhn_cG0D^{+wccrzJZ>BxWrdkH^$%h5-en?G>a4xA7&v~n0p-6WWjOIa zT}{e09<8;MqW=n@qt8N}viLCJdn7#>zCGElw*dmi5+g|+;aS1sl5Ijq8QgMOIxt2i zJ0Q6^SM@}6i1{alO(thgBNC@=j*}jiK)bFEQH~gm+RG|cRPHO+Djpnu)9rdSE#J+= zcQH>l0})^45F_*QAMur>CR?a3ffG%IJkx4)T|aG$IZcx>LERB2_wd)2AA%W3uNweu zItwU1s}EUj1*m(@W$PjfkU6C?iEnx4ZKKnllI!u`$|{u?)>9XSDKeYXC(;LZ6FSZ* zvDL2=To%U^5e=)q`<0DWTunH(@%w8(1O=HRe$L*WNj4wT3rCt}Aw-C5@?*@+PKl-b z5@a>5_wIEI?VeS;io~KhJ(0Ac2g(2c-nyc)MgA)%K^;C|9j&J{)S&e798DJ(D|fW3o)Ed=5%RFSLCKmw*Y@5pucw^JIRG zALEj-SK3K?L+;M@bvgLilBq%8$1tGryZGwr!2U`a~J-$4P2d) z_dmB4`vMG&YeOP9ZmApz*dX!Svts>79}$0u6$@=N_P6!vHH0$d_wYFgdQ=n_%uics$a=`D1|s4BCF89?bjv&7^s zU@oVAF+bDOY$Fbt&7|h%Br;-q(a1FLt=yNzx^J@S7(wcT>opCho$|f6ae-?7&GBNw z)D`*qyGedFu2`YYq}zYfV*jqeU8DSbf8}p#mvlP8ViqbgcqGW-Ei)qxgPaYdcqT0` znq=>b3~fJ4U>~`IfTNlCrfOEM<-+1K>R~?HBVjlh4|bH;)E5@mH{mnWbmf24=KLN_tvrH>Q&Y9fx8W)%p3rFwL_#*j|%{Gz>+-}iR%@y5HtzsI$@nV|lQu7P+}N^kMq z>+_MZ%s`z6%VJ}%qA0d!$WuDYJmT~1N#=2t^e`(~p`3{g%5%hTJmiiP#V}XRI0C{q z{~N>bZkWQ8rp{AXJ__pu0&pd0p#6a;O85EGOOWofEwC#TPz82FQu_wZnyKImNcTPK zt~~?LZn-xw^NB8(##EnJZpMT5bXozuu!?PIlBd&$m+s46Q2~lv&CSoBVf;as=P$|( zl3q`DkC#T9tk;ptqkV42QFQzZimdTcS#Ew56OpApGy)&^k%r6(*Q#?986}k?gefsY zc{6aIbwWn*l)(7?UOx@wbKoqlrFfdV)lOYJdpjc5-x9&Nx6Kj*ioDd`0KTHap`f6E z&cY&?@uI`VO&knXGQwEN>gMYp?1qp;Q=DDnTT9Y#NU z!iA2m33c#^XXo93k$Y$=vbfLa2Sl1UNj<0r3h(27xvzi33NQ596G#3>7nTue(nGyE zgD?(7X+Wij7Y%-WGbzDg0~dy|4^jH~a88%Tege=Jn!l}{*@``BJ?XG{$#jv6muXC& zVB(*sJFpt_g0fB=c@s_7J@)gR)m-PIe4Hg@lW+u2u+}X+_Q(4m7Z;{ztDEEe^4Z&d-2QpbYVu*sZ{{Due(4iT3 zK>;o$p8nWZgC|lMlyl+`izd!Q>i*$Lp-20Gs5Ovaoi8Lr)&p~d9uFnpXbC~L=1af; zB`&Q=K`7~|_Tb#jO4#n*#*^&Rv8M5D)m+RtLzc&>=Q-bPHcIHBSJ+8=f>I^~=Ak!k zxEI>G_GNFZW)Xt^7ggUFU0D-t8{6vGwr$%^I=1cP#I|kQwrwXJ+v<+H@A=*vZ;W?; z>~Vh7*}JONnyYs0nyY4glH7bJi^@HT*79UHeFNO$Y&EGZG4RtVQYc&{*HN#;<@YOM z*Zb^pD<5SjZn8L8ja0cCth5t@1UaA~5oT~NcM#!K?Y0`tl=IC}#3QHLIz9)HS0{1R zPy>Lq1($<-0gZ+vRQfinYmgf(QFM*YF{g7-sAQ~cg0+r&i}>7_c(QOs8|LGb?o`ze zxS>mX*e2BsHay)*GW67Ig)~rC9p8}bLSo8R-8aqj_dyu<8#HX0fx&;tGD%;21TGe) z;#&(wP({zSn-z|7Q0YmYa`A7t&_v)p*F<+vB^2mcxzjHsmb+T1u4TsBxg4FaYq*i* z7L1ft2o{MH4f`cXSB6uCuwJYOy=xN#m|~5e>G_Z+oE@xULf8((qDC!Z8Kpypoh0z( z5W)rTR-&ASVAy01^{}8c8YC{_IlKa$8KS+%Y4)8FjPtj8)CV0oLkB@TB{k#XfC(GV z9&+6Cz{PRydFkh(C;t?p86IOwDd*!^3SDn*vn&T#;rJ<1}fP{~|>iNlj*B;H0P+?v*T9v1Ya^Xhyaa z;h6(iI}=tzmo=X2HHbLJQbc#T9${k^59cM*&7+p-Oiy>nHCRcq^BXJ~0-2lHDaOMF zAjx~sKsGla-#{%#Z5h)io*eKh!P9Zx$>ZfDs})BDv=q1otY1BFgMXk>>AUh$E06=%qM-`Vr1gPMijscj+4VqG7eyh_S5OABeBq&Jg}T53 zpt=vwuBJ(6oU2r9HBS@wY2mNKcI{-~fNUZ|Xw%7nb*mD-V^ZZ;xOGH{@tp3J#7*cr z!kx-JK<3htGZ6aA&D8lAbu8QxKccHS>ZhNhm()Qipam`mpQt1&8u8BJSo#hD0dHV4 zyrWqLw`Q5%{!psG74Q2O6k3;hXixPagUh1jp;(l(8IVMhhOid2D2D9E#zhN}4cLRk z3us^1_D-tbw~d{tUSbFSbC53R5Ev}XvFt>wU2|!~x`1}x<~R|&dIC_(Cd&H%JYWi| z4*+^9(6;nFvvWP#%0lS3XvXF``}n;>XWPL?W%VCyo(s0dw82{-{5mDF6E4-T#W0+d zjUUEghcm0A#DPreff`s85bwmO)`HNEj0IW6FdP~S@;KNRZ1@;F?B-#A($&?T<^F3d0M`s)FH71e}ObszacQ zE8-2=2F%L_`b6=_aCe4Sc*ia0Sk>-5lt!s$X3K0vwu>qDwb~jqbA`jC!k(Ujdts-Dv_j}kVG4eX!u-J zES{ULCehTU_9{5*R8h6wq`glfF`7r70?(kGg!f`(q({R-n*7!SaTY z$uJ6qHm!qOKx+cgEhZv^6!zP=T28>qB!m213q(Y}s#?d!KgrgVY_eES!MvAZ}DOogbz{zr}n z%9g$-qUNb*ck<_72g-Y<)EI0YcbzJ7tma|-B^~LOtq-GJBuEjLj$1K{x-}T|C*!1d zMaObW&OdNvF|Fla;9&x&3MZJOIehhUaL%GEbw20rtK5ALesh>3=^r`<7&6}dWQiZ> zBN%;%+G4mbdFo(zK0x7)zmSM?mgr=cNmqz@KXGZ9te5d+G!?R#e&IHQ=&z%?tu!5x z&cR2@Eg?A-BA-BF^21OdFvuKE0;#H)ftUGqFh71hZCI{NOe_KfD~Wl_hZA@fp@#Ro zPtH8_P|fYyuF@axpAlD3qMN!l8X_|VZyjD8&MGjO>NuiPdDxvjUQs8y6^#bj_Sd3Y z{drJ`69>wuQq}T>6`T?8(#i5aO*b9|qWLP^jb|5D6h#>ns(d+z23LCXHi%k?g429t z|4rNY?SwOgO&A5R39#cQl8If+zYE@WE6OkJk=KXydtuj-?u2Tq`zoPcuiV#t_v8U4 zdFtlq_xg&8S_@S*8w~KL3wh>FE6FEHSkToc_4g?e(gZ9JzWZ?d3t)m~gPrLHBu8(C zxEaa6^!s#CStR*6Sl?vIo_pN*H}k0aDQP1 z0=Zg6bOso@i)^J^-TA-JH9>r+ThE-#4hk0$5mClebUbr>Eb| zuFJ}9UIC{hv)YQ@ol5Vo=@wVNNv)STL}$jv7-XQ0drB!&7B2@702Sk$Je?XG%xEU5YIiHbdwafxECF0nJ4`Ko%Hd}4^8+7;R#V_@8T2C^4`-cvQAWh<++?T7#;K=2es|4o2uffJwu2FwQ= z!<6TjELu>Tn+=0DTLNVk8lmJ{jR2UWlqUkp<|fCC`X#HG`}oqIwD|zf zpYwSa>o)lz)^fs?>a%Y!hmsP{Jq%U5U;IWkM!YmUpx4t~8$JW-poA#753k>>kZ8Fa zdK_rNz?seh?O}5raHi7?)JQ8Amb*Z`&!*DGaJpk&R?P~wCR#NQGDn9rwp})d-6(~f z&uh*ug)8Uj+`z4#7g1XH-H94X>4D2!Dv9RcZ0ctm|G@jc(3@&|eUKsaO;p}UlfmMN zfRO>*Mnw(I&B2p#s0@b%cmazGI^i-YMv8AFINaHGb$we@Tj>Lm!~T!gd?Hb@!tOP) zF{PSX6Y}4!vLDjQ0W!&@g`a)s1QUSb7PNoQce|dsuq7is(f6vJ|GqxcLjHYYHjEH; z8{T&X>s$}_Fu&D*JDE7s=U13{jr`DN%S|H~a{c?%_xZdpexAhzSa#bt8HHU*2>f*!N0q)9JC%=K3hw`1{QcfnP zy7cr0`^}J-QXdPj#6_d_*K#u#$Dc;hx_0~hOdR6ZHz451cmEn6@(sJa)El=2V;*N?@+1qdHkf8xsEr6T+}f;?^f zSW6%H!=KPyz2uWmMi^>F-^%k;hl#S~Enb>b5cy%DKEPugq2Jf3GiVyrt%#<$UASQv z6QB{=56TW5(+&epcFfbYi@RFWz@}2e5woueXA=tL1F>*qS_)W`K>Vw~5nHX1J_6iH zM@?&1{Px%SUBl;%;frm92#U~Vo!116r7FXU;}?M%OObqho%|*{(NAxAl;R!$$|I|o6eY&_KVs3e+(I!wB7GKA zFku%n?rg!Oynwxv%0wB!Kg5b><}Q!jUqWSs;I1dj)gtc-4sZ$#sj(V;q&*j48^=mp zu^`(|rz@vfCCKPv}46dJ1PKb0B0BOQ(6T6q_{H|Y=g zVi=}^*c-wDovzEm_$Swx1oXp&d(+5>2ihO-Z!j4pL7)+X|Dt}Cw72A1kX!@F zlO5cT&_(v~Yf)m;z8hw!$=zr{kQ5-Zn4xc%)W99lM{JrzOym!7LXcuJhN>LL1ofBv z4nj-tG^AA7XtIy+tz<1u%Z?od1uWCu*CSshxZgwyzIZN}$q3h2kauO6JV!slO6?7s z!V9N4S(Mo)Gua-4Lz*pZ1x(EN47wi|0&&@I7X!fNBR5yO-G)a2`w^YOZ~+j2?+@Gy zeSdgKPlmPEB=^!3jt>jJ! z1j{d|ig-4H3v-)=apNYS172Kgg(3sq7#J!Yva0x{1nvAnung*-ou?$I=H{s7k-8XzJJgK*kkX{I}$_A5gOmH1}L-(|YAM_2qHEA_c1=^_Bzp)M#cR|06vw zBL{tHtNp5b{q!`dftX<|ME~}DsEl1Uiq{+dWC(wWc_{t@=z)TB*ykl^p=4Y9(pqj2 z&$2)*QE3pcUkY@3e1Kq@63>Z~Oeu`x^}Mqx66`Fm#bjWJl76m{VJi0UgjQKkrz9 z?3fI>-GN`NM!H>$blqiDAVb3;gA%_S8Zk(M4(dJ}ZCHk7du+5Sf`JCf?r6jY8iXFo zIAHp%e|0c632)-H>{0&d=O+UYHR=^%So6V5i=x9{(f0#Y>Wa)oo*eeT)?16hmt{i& z3=7pm-!C5htr=FRZ=@pc&zo!U_nF{woK3Dy!sbjr39-AqeO+>a6`8ajyaC}9kA60S z?3HV&+l>j$?+zLfe+v#w-1^x;7YX))DUf}m#T?RSHWCc;e!&kOA9rgckbep}*riz6 z<8-Cl{qyS7q!Ed6!e0PAFaTGrM4EYSAj!!lBP_E(%8kbMY8i>=^Ow*q ztx*SCk<|8Lta*O=`h8X`2=ku3%7XyMuV`2XX^x1#Ky~mFAh>Oy0_O7R=!o^I3i2u7 z{Z&u03ZXmnLdPb?;+{WXt4$?OJ-Y6_tyv`R&gpXH$I@AxmAz0rZbM~)0sUs)@V+b& zeS-!lCnIiROGajp^h(A_4}a4xU%l2eYsJJ4|HQ5*gZPi7VwL8M7zlTRJ{|H@ z@PpTDp6CMub|4(Iv^rg~^*kTSJyZ{_qxPe~1L4?s$ z(r*v$F>{Rd9qssq@#UfBx{&4B_{&YSNXqV{^Y>Q@T6$FKnZjqs@%gA*TSiy91SnFK z8Hs{6IQz|R{i2?7!wC4^VGq>ykbphkLKjhdXv>Qi)?eHofPy9})b=>!g^-$u+&A-U zFU3J2CDN}t)L^C@0<0n)f!APNO&t6Yx*MYLwer9}wkjhY+9G62yOQn*3CblNKUOBK zOOxpR68D|Dx#^U`B4|fp3fE*VTE*lmTlo+XgD{~TsB;4?mkf0a@{b_N4R{eYas>T# zy_2tYFr>%y0K)b-M`RW#!2|jE>_7Iyb1*`RGHh?0@;`9y!3o=F5NIp?Bp#7P_9-+N zjK=u9`gCQ^BERroKLSe?O@F;;>q!hK%awe@>Xt~Aror>bt1ECvqB^Xm zNaUOjrvwJ(;@>ZnnV3sJjmZ~J&<-RUX|q(B#=aG|14aLv6Sh`cQ?fN&nPIs0(iSa*y;gMl z4goTt>yp9GK=xE8mocfi$_=!*anh48%2kVQ0T3{HTHC-?BFe{1F2itzprU3;npe%G z<(!q+vYF>8y1P2$C=K*!Q{LMb zkfMcZQJiA`gXwiaaCKGGQsDt^XHm9`rDKqzF!R|fm?37%MpjL3VzqwC6Brk(f3f(p zM+^qZg1>6Tla0qWezDi*mLElC;9(g%WweHz{4EblA8E_E>=pG~y6;x-#wcufX`K>0 zW!seFq)kXH&^RVBqn4lRDHV`eUGw(`R2x!}l($}$ukF-pl#9_T-P()+t5F}tq7{hf z6E1^&YPo71Huc#h`{dth`h|Gx#BHc&+JLYj@9yhkt}95zSfM5u)0#GqH}*$g!H0UF zp|v$^ctMzH@ip>os?{I=Gdoe4?Tmb9CFKtbI>{R$(}w%k3wi$BDgGK)R%NUFTeLphc|RSRsAY95v@H+;V^G7uk!;~Z;n zbJSSf=WHmzqUA6s8xCaPJ^+f@265V3#FceGqIk7_c2`+pI+faziL!+Aoc>cCdJRGV zs>?z=h0LN>tGzKO@ZF^i02%(0t+h$hHt#gWU9FGOC_|V~tOX_zKNEO^#^prGhsLy@4Joq&S=OkKgv|Mk%vUrs(q0E$X8t*)oTNk>??9E{JjL>$fMTluJGTA6PIZK{>Z z4qDGZi>EQRD%SvX9w2QbG7UwFEksDmHs?u-<%2_@BPrc+N>&Byn7kJkQ8c4=js%Ae zSVIlGCw+u2sJZwF%>4|yTDdQb3vk8BroyOOAHR57RYHfd!g^h<{JLzN$wpnb-#?F( z2{~BlnpV`6ACzWn>CPSArLz#O1uuhnV!|hnMO8YYm%J%XYVp&*lPEtxmBwi)3Cur( z1dgvU4TY{xD;?6V|NCyHdeo5lzxs@IXRuTNPByOp#cmVK#GiED<~KYbw-&#GW3vZ? z$OP_EX6Yr0DY(C$HDa1^MSKNF3)soIwAJtjwEDoa{Y1`?Pr{H%BBk&gaH}nONN^7y z0c__n5m3m}`KA3$tGROoWOcq>D>)H;Eq=Q#5R78SG{}$CxD**X&jC78@C^@?unBa{ zwF>8m2HXe!v0dXkXJ6m#=>0!(+u!$n;)iTkxjglBXWV@_>mRTJ9P?y>f6qIHJwpC^ zL^M2-(_o^Dv=efIe15JE6Eu)+)P)fjswDXZouP(dVTKnw&neAdJN<+1VMK2&!#QJ@ zI)|R1br5@%M}WB0f`fZ|1hhTF5zG3c`!AhIrYeQ*m5x=^q8FWUK7r9iu05cPUqv7| zpr@dqqwTYdY*=UQn<<`|iaGXIS;{m@e*fRy@4ipC4sH8~G(L!8vp^jK1mP^#Ug-b0 zZ4lgk%0jLcGG&a`;Q)-bCS&KN4mZhz8qr?-1mc+(0HFdDP{vVdHkkHuUbrTn#R?Mc z_jVuTSNlbVG!?~D1UejVE=uRi4|XRfqpv#dUF3I3Ji>YJQCfptf1+TIHg!ksvtO}i$Qc7dEneM27Gp0EAl^(ZeaS)Mn9bK zM$RoS0O0cJZihcxj9LfX4jT5U0u(kt=!_2uW+SC(^c-^Uwr;%5Vh0WZ^xj5&DE5`y^kC$!wAM4wMKgRKEfbrXHb0ZKl+$& z%*=!crBJ0Jt3&*2fA(epL#+tWfVx@yY!5550{AHj!xsTdBd`4FvfPe zTE3QVswlZbc^yZo)G<#Rj@RIPTl+?(dExEhXJf8mB<4eKEDpYeNG0KH%4{5e2w0Holh4?5Lad?Br6LF!k*H za5c*{xAVI05)>PHb5d3m?ia5UIUrhYs3^FKK@TeXji?YHA5k*=At^~QaD#+?IcTfx z+n+7epG21V9z1B5Bm?r9aaP5sVe?fLb9G>iFN)pJr2b{Q>$5*-g~;`$zQ-(+P^FF`0pS<0o) z;v)3U;TdnM0k=`c3|=&noeTiL)7i1sTgX`%!4Ws9o~wp1Y6o|Gn-S;~*$u>sbRA_*)E z_>#Fv@)XBCAjyq)@>!Na_o_;ZZ?ooBq?Z{%3XxTSj7v^rnQT;B136B9XT*wHl;R{|fELPe)&UKFnP!wy zzF=B5;+$#C=#m;n;fk~sRJdX+#U?{BLXRmkWahr{gFmJ6s~2@bTE$R;EdI}bI^-l1 z>+2mz_=T6EqIjo#V5MZkH`29Ix-1N5%>C(B^LO}$j{*j4O(9b(9E0o+6lmy`c(6qc zOD93SRN)kui}X=cMx7y4#wO`ix>$P0al=69qJc*kuazS-?lcGa z&C$oA3grk|h!~0j!t<5RYXMZx(p0v|j19*k*KInuDL$aDap2*s%ajfm$H)F5p z*jLl-bCTpl3V2%E7#Ty=Z(B~q=y<0;v)n?qH~YuzxQxHc0NBGxT~SVb>fzCP=EE{FEGO-{z}Qgp!kNptI?8quoTTy;GNF-)LHiK9;@bPxyAnp)!ve{o2_# z>Z+$|7{qyZ3!OhcaO5f-UF~J7xexANITz4{aEC!NE%UHT4$LzV#o~zFKk|z(d0A3o z5`?RqqFUE<>m)5<5DbO&Xz$c4;Cc~H*K^jHI=7(fxYA^fD@)YE2xS47kaC5+zkcJ46>A4 zTCRgVb+^k}IYb9=t!%3YWLt1LaaPwSc2-0tGJZe0oY;tX$t1)T57w-rv|RK3!7d;~%_mYuhY}VFv<1G05p@M(Vl_l#q{)b~A z53(jNV7Zj+MD1$e0S#P5c$UML?-H-ed!IV%goaVP1m`S;yAN6hk&KmfkKfg7+-d)7 z^YLV7!mwPyPY4;=qEFP;ZXqp>fAFZEQR;I(lO0B#_QVy_*fa|aqOV8Vs7F`at#dA)kK ziQ9P^fK>1N^K9@NA2diMjej;rvr>c8ZFb0@v4kw}E0cq@BWCrfx;+TBNdDMIXNPd} zW$X)wv&s(<94P@ay(I5$qPCinwUf7a=B}Q>(byc{VB(Gf@mX#6x4Fl59R-MI;f3&T zKs>g-Y?;1T-?1ulZV6E zp0jSkCx@!H$vRn9lA_I+gF!@RpDxww9;xX^x{}Z9KR(ABia2A9Okz?tp zXHi%PG+p=8>~05Cg74_ z)22;R=Be-=|t0o>EvdM}X3yI9_l!*%C zFyrtD8%p8zBu^vLP#4jH!*lWQ-V(d%l&|7luQD?|%rlRiCNM~rCwf;4P-!+gTC8UU zJMPUAI=^$*hILF|O^uqG`-vcrFq2S*@$&tQz@;cjy?dxd@(H@Zo=Xu;gexb3z?fFi z9lpW`?-#U!XDqnR5t=dz+jZG3xh}ygX)yX5K7cSaK)=~V%G*;C+w?7mp$F5k#MHsM zvIiLxmQI2Ij(gB#}#q9l&<&qG7QagEmKTMDgkIL z-=^{RiRyB>`#I%mrkU>E z1-Q5c*}UWBh&I{W&nBLyEJV-{IdfS}Z<`VP2Z{xI7-k|(8P;n++(fzs&9!LDYeK#D z1Wj}dtM|r^E?F2~l+IQKmlVHQ;dli1=daQ;C`C=#7{Yxv){ffIkJB_H^3Hb2D5t!#BeV_BC zC3W=io1}$!;J`(zqkVk21Ox`Z5bv-betQ-5s~(!*xN!~-XAV(&mS>0GzuUbCM_LQm zFeqpnKcHW#E^%>%fPNX5%1kJ0Z%f|>V5Era`d{ekMTzai*z<4DRg`_$LthIt)QXzPbhD#I^e_$1E;59>|A5F%aZ~NL!ZP<{{ao)vcCa{ga9Ha z5`uJAio8*md~k?y+O*}40x3=k42Oe($a9ma%?u-K_RWCRBoDypJ*BbXVeLTj$R|{L z=;Lk2vi!MbQrcLS-1^kmn-1TC6TT*@KC=H%bm31U#o|(BGR}_AQo6irUBv%%kUA$b zQDRP))04w7Sn){X=U^2SxCgk!&URY`u)OqmO9mg7c-SJf8X)JTn2stdEk70O0c@58 zkD7USyzHv;a^o`UaO`l!L(UIwiY{A$?T_}`fGGz02BsM3c$7X}6b5?Ky8}1fAhBZ+ zH${cxm<4}chLY<2cQ+*XRtCqHtC)9JwC^q5c9mpR`CJutPw_86I^DGzY8lyTRP-%T zeX0SCNG`Wq9Ul<6XX_m0mq6r}U&1`A$Rc-3LI^hc_o#mK#ympNkcInKT@xUtMx#7A zc=9l@+^-NJo|u5CBSw5tbLMg26a07?vAZa^%PcWl#tM0cGjpx#OH@kqx9=Ijzw|0! z%0I`Ysf%=v2nTSZ0*8f%^~O9Pj5gker7EdT1Vpqo5pxqvA>pv)H24zdX2g=yX<^zg<5CM=lkWLUm3sz0?qN za!lGUxg;NMY~UKyzvqXDR=$m`)ocrXlZC6?>8@TB^+X~Btk(PlX;}%rOyu`tXHZ5$&7Uw zZvc(^9L3_cWCM6xd61xhd695Gs?z!4KEZ@;Z*o)>#rbpb*)Ar2(C$pzEneFqZA=^^ zkf}U#VN`u~4K#KPOhBnBrcDs^!ldNs2fa%-2zHECESm-vzZr;~vn{4D{axlNghy}D zXH=W_#KOvAW=xKS+-meVmK;nve^9eBu@UYg*V5*7unxcohMp$7gy<_qaB+Mob0v2Z zE>?KMRiJDC#l2gCS`ktKG#Q zyiD41Hb@?qrH1L$5vYPDPPa&ZE=-%Hk^+Ew*FJUtg9hP~sB+qJwE$O+S|{hHM=eZj zXcV8;VZ};^VTMJ$2E!(Ytc5o^7uH4?WI;oaKF!vHL7;|`MN$1xX^D)nJSg`Rq#W$J zp2;a(4Ig-8tUeFgQ=^SPh2L7@V}xNOr$GUb&~uXeE6Z>&MSy}{o$6&oD=3)-jRKGr zsfq%5Vu>~g^qNhEXQ39pK^2Cfu+vaLNf2R>4<3vUql#=3spbg2DN2c06cE0GX=HX+ zk%fhHt~$RfA`9F`7e{s|m4TF?StS&qhm0XkQmv@;R3aIiNbY=)3UpPL4fG%;o(g+| zB!&j7(yBgIpC816DWQ^%!)6n?x&|mJlCDv6(+w3)&$a~>W4z4q2+s=NIQ1+c6@tzX z`MW*7Gi@01cLjI=k2=Y(nGs?X?E5&pT1&}T$Um<5I(%Gr`GEZOfbpq9%vU6==S&QJqE5Y&{d&~DcEKffJvZ1W z4p*i<(Fx^B9-XWO9iH~bXBQBc6tAg$P}^XP%~bdWE>Bk0KQ-RFhM|Sd_ieVWrmb-E zlER~SIQM>@-*W#95b*W(f3J=u+xK81@L7mR6EXE&HAzeo>_do}!_kV*y;hTrfD7bh zB4A}JO%GRS4yPIW!&`l0ID7iEM{Q*pA%@i@P1O&~HB$L>?Scp455kL2)) zejjCirt`4m%sK(HUj}BIsibJ9Z+(3pZxfb>|V3{2G4O_Z|;x9Y7g~=-{iO(RtWg7Q8+O) ztUC723k3qi^ATngz)xR{q_h+4%bg)iM&@~8CJ_a(iuTL}=yK=3lj1(E+q;Bf6|a93 z$0~%r+`f;_i3Y;VU$nHtJ>0BXMXE>26Y9sjJy>jcxj~^PB6b1i91SlYDp?v#-hrUU zJR>6|p@=XP;bJepXj58>KqC%3Iw(kG^J%g&+QmaQsLt(E9VAFK&s3aspijkA#sZI- zS7s1Z2(5Q8Cer-NSlS+(+JI-E#n!(Jr&J>C z3}xReq*IxVfieQ{=-%0l>0VxrpY3K!rF|aVFWwIi97?O*})n^e>YFxbU-abGv5Gc!N- z{r}0mzg2n@1f;TMQAPg|E6tghLS#jQ=)jZWd9ll6i-P2Xf0nwe7y=2D+cA}E^QFCH z(aNa_vj#PzvEWu&V?`Z<&RzY(xs=-idz8EJxcARJYT=L3F+Hg)XpbMJa&UgmufvR& z<@jS3)D)3P;CX^rTSeA7!Nj{|;;z#V3IEM{HaV}i67@v3v84!W z|IGFGsIWTubB`AQ-xq1VQP?08TKW4Ai3Dc5MsCdAf|X-!sxK5t8@H=|Go z5>md-(F(!EVm8asNq@TcX4vHhqQh|Hcd=-&^SC}PdR^v_y=v|V>r(aah_u&D&7v$7 zFIy6X0-s5d)TYn{RoffRT8KnMyG-FHX3GJYeD$nl=vIYdOe*B%udBQGw%Lki*t6G= z`CdXm=Poi8DCc*`g+CW6%z+<4kW~wIKUQ3)=vJTf=Z;#qo7X*BR*Cg+DBSx12DBiwRLqg@NntDEx_BbE^E7SgITA zR3eRfTCZdzdhg`TF|(CK($FqVIBbiV)CqeJaXF5Q#u0HqL;Y1zb(cKitFO!3Nek(< ztE}|bw5}bZAOqHU@5pe>ZW}_QPAu!}KHlfy1wohGq5Tt75SsaSFvx8@6PKnhrc_jymFdf3RG={G_cv<4UY zp35gpl77LxCR=Fe)~BXc-eQ*;G8ZFA}+4#%2S=47*sx z=DF|f1|#!xDMc8Z<{=y87S!rMo*TIK(T`9)xF~Q5zJCz>xK$sD&w2ZGUL(reo8yAQ zQF{wKUE{>xIpnPYnOwjR^T~<9-dzTcA4}UEPgR?G9$|FwKBePihp=}7dnWqb3mv3Z zhz}n=UEgkujyxc2M8*8|QAZL$Q^VCyxF72oV1N7w@V%PjLr#-~$_!Y~DsI@A6je0+ zh*u@tWu*TL`7dLNDJbfNKOt^e#d4*6CpqZX(#-}MPU%F$hXM+doq_U(UcJGUe7V*gd8qpzP ztZT21shCMQBU1W7&V$c>4UO1+@`3&eh+kTN`D@aw36GKRE|ppU+kE%I$ZfyAylGL= zV=Q+Aec~jWAAcd%HZ6V+r7wkLHU?CZZ0h{=xgtrgO5^Y(q)p>_=JqltdqM)O{tdRE^-&QgqYJtQA4C%{}hFbzUybOG6(d zQ4OzEg73i(QOOK1Ky+~Iuk`={bfdeL{iIZmh1h;`Ur1VX?S0O!AI-A;Z~?Qu%P+Qw ztWZKvpLMuqe1&>_?6-2)ZPdtYBskA}?LQ-K$}!mKLSB0TbKBl_u(s>IGp4(QpLH1< zSX9>EK;bm$2U3dM*olpzntlN`XS5EI=(=UBp$CW@qUmo(xzQ+UP zXN!&IEcz>m_bF4>YAyRKgkSX;IaAg`-@-wV`%ljv`W~xS14bmxW$IhAy?MuDrr&>g zNx2OeUz1EwEf&6cv*c1ey%QvNf9B`F*H#n7=N}T$9w&aymz;~)Km7w6r?PBKL8V5I zpi4&tUPv8u>Bvz5050bLKW8FOmoJ5^3vvFN?&Jo)GT~k-O?F7*UH|mvX3h>eJLwF~ z&?)2X9*-CV?WWwLRj(&IeUn`J=pFRr@-;;O=gm@SYY5=#^Y7NIJs19O8|>e4pO13~hDOpdIRCn%#Z8E_KP5?RY~AxJe+A2gP=8|- zGc~lBWdxN1H|b2x8-tINEFExV)Ul&%QFex|XsI#C&VvhN{VJ52lNjU8E*p}_Tsjv}@mTaAOUVBaqG{uxn>YkK z@~+$;doSHhz!IP@;~2M!M#sR%#TF-FUrHmM2I`+6kCYL%U)7`8O^Hdu4TEax?LmIv zJ(#n;*RIlX?5?Fzm@ccXFGgzL2q?iU=5qJ(#Y!r3C8qP{1ui{imU+?LY zxD%>xf7;6yU#6E{2WeRxbvPVxS{Sp)YEQ0up$H|3T8C2ljHfiY34=6B6dp4Cd$nEd zAa-^(MCZ0)Gzlf69lnaABf8RowQtSS7FaFb;HPxsx7>3(9q_`(px&x61Sq$UY?nZx zKsrz3o;|i|XqCnSLk&~86P4?*kB~82hGpFeAzGe}_g6&$n`_xK*IKSlwW3gAf};8* zDDJW0T6;=by^zv$JtlL>0I$3!YFqxwdGnjXJ=&Kc9%FE>(f{`D&$OgkYvlok3bP7@9~^=x!c#-wRW%; ztFwv-;K3W9;QMvBj}r4ww6FRO@^Cwd%OU9;dPbm}8^+Mp1uaMLmp`@j#G(ahND)5h z))R}FXerk5Q783&2&XrThNkBdaektI2h!}9WM>+0DYsa!fVlXw9$?9H6u22((pDp% zR)-4`)I)_dX~K!25iY`)tf)DMR?D%K@54Rz7w%kc;3(k!7O-$5Rp6-unD zTx0}t{*8_$pJw$Z4FGt1H;}BDDlvjzi7Ku5!zNrWY=08w35&6KZ3#G{dK$b@lmls1 z*qS@Bt};ebh>?zQCYzFBBVAr}AV^!C%kNIjVn7GCRgPT81_@948X(!E^Ll zJCq03tWEWE%wo$(O+_iyZ!aGSwglQNn`^FjD#HE|VB^bLS{w`&yQLNQ zKUBQ~aAi;MFCN>ro!vMan;YBM*fvjW?#9N(wylje8{4+6|NZ{{@4b4j>Q>*bJD=0H z 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 h!)dxB*YY`r5r6U<~ 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
6_>Mc7WDOh*ul7ed1< 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
!2x-Z5&u@c4Bn+5$1ZKXKR*Dk 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 delta 294303 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­z+Lsi~7cW(CQiS2J? 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

%R|@xd70#+s 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 delta 52990 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 A=l}o! diff --git a/spec/operation_catalog.tex b/spec/operation_catalog.tex index 286b252..8f82c55 100644 --- a/spec/operation_catalog.tex +++ b/spec/operation_catalog.tex @@ -226,7 +226,7 @@ {\Large\scshape\color{epiphanyslate}Operation Catalog}\\[6pt] {\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt] {\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt] - {\normalsize\color{epiphanyink}Version 0.3.0 --- Phase 2 (K0 representative + broad-K0 M2 groups)}\\[4pt] + {\normalsize\color{epiphanyink}Version 0.4.0 --- Phase 2 (K0 representative + broad-K0 M2 groups)}\\[4pt] {\small\color{epiphanyslate}Normative for the operation kinds it defines} \vfill \end{titlepage} @@ -855,6 +855,54 @@ representable. The catalog records that \texttt{Dismiss} is the action that selects it (resolving the v0 ambiguity P11-C10). \end{rationale} +\section{ResolveEquivocation (meta-operation)} +\label{sec:k0:resolve-equivocation} + +\textbf{Payload schema.} \texttt{ResolveEquivocationPayload \{ target: +OperationId, chosen: EnvelopeHash \}} --- the equivocated slot and the +candidate envelope (by canonical-bytes hash) that shall stand. Value-complete. + +\textbf{Canonical encoding.} \texttt{target} (16 canonical bytes), then +\texttt{chosen} (32 bytes), per the codec baseline. + +\textbf{Reduction rule.} Order-independent promotion of an equivocated slot +(core specification Chapter~6, \sectionsc{Equivocation}): when the operation +set holds an \texttt{Equivocated} slot for \texttt{target} and \texttt{chosen} +names one of its candidates, the slot reduces as if it had always been +\texttt{Single} with the chosen envelope --- the chosen candidate contributes +to canonical reduction at its own canonical position, and operations that were +pending on the equivocated id unblock. Among multiple resolves naming the same +slot, the one earliest in canonical order governs; a later resolve naming the +\emph{same} candidate reduces idempotently (\texttt{AlreadyApplied}). The +resolve operation must itself occupy a \texttt{Single} slot; an equivocated +resolve is excluded from reduction like any other equivocated slot. A resolved +slot records no \texttt{OperationSlotEquivocated} anomaly; the losing +candidates remain in the diagnostic candidate store only. + +\textbf{Conflict cases.} Two resolves of one slot naming \emph{differing} +candidates produce a \texttt{StructuralFieldCollision} meta-conflict on the +field \texttt{equivocation\_resolution}, recording the governing resolve +(earlier in canonical order) as winner and the later as loser, with both +operations in \texttt{caused\_by} --- the same discipline as +\texttt{ResolveConflict} meta-conflicts. Preconditions: a resolve whose +\texttt{target} is not an equivocated slot, or whose \texttt{chosen} is not +among the slot's candidates, is a precondition no-op. + +\textbf{Undo semantics.} Mints nothing; not inverted under the prototype's +minted-object undo (P11-C8). + +\textbf{Re-anchoring.} Not applicable (the payload references an operation +slot, not a graph object). + +\begin{rationale} +The core specification names three resolution paths for an equivocated slot: +transport-level reconciliation, this explicit operation, and a +profile-declared deterministic selection policy. This entry pins the schema +for the explicit-operation path, which the core specification previously named +only in prose. The profile-policy path remains unpinned and unimplemented --- +a Pass-12 question (P12-K5). +\end{rationale} + \section{UndoTransaction (meta-operation)} \label{sec:k0:undo}