Commit Graph

16 Commits

Author SHA1 Message Date
Levi Neuwirth dfdbc625b1 Agent K M2e review follow-up: tighten catalog accuracy + container creates
Address the two-pass review of the M2e catalog expansion (ca07c28). All gates
green: cargo test --workspace 535/0, conformance_suite scale 1, fmt + clippy
-D warnings clean, catalog PDF rebuilt (no undefined refs).

Pass 1 (doc-vs-implementation accuracy):
- Undo semantics narrowed to the prototype minted-object model (the catalog's
  own UndoTransaction model + P11-C8): the new K0 sections' minting members
  (insert/create) keep tombstone-the-mint undo; the non-minting ops (modify /
  transpose / deletes / settings) now state they synthesize no inverse, rather
  than promising rich restore/reintroduction the reducer does not implement.
- Spanner migration corrected: Tie/Slur/Beam reconstruct self-containedly while
  a Spanner remains read-only/unmigratable until the v0 projection carries its
  TimeAnchors (a Phase-3/Pass-12 extension); the "joins in M2" claim is removed,
  in both the CreateCrossCutting section and the migration chapter.
- The reduce()/reduce_onto() agreement claim (DECISIONS + the staff_based_regions
  comment) narrowed to regions represented in reducer state: op-created/deleted
  regions agree, but reduce_onto additionally seeds base regions a base-free
  reduce() never sees.

Pass 2 (empty-container enforcement, made real and complete):
- create_region / create_staff_instance / create_voice reject (ContainerNotEmpty)
  a carried value bearing ANY typed child object — not just the structural
  hierarchy. A region: no staff instances, barline-alignment groups, or graphic
  objects; a staff instance: no voices or measures; a voice: no events. Each is a
  distinct TypedObjectId the reducer mints separately, so a carried child would
  otherwise materialize an unminted object into the graph (a graph/ledger
  faithfulness gap). ClefChange/KeySignatureChange/metric-grid carry no
  TypedObjectId and are values, so they are correctly not gated. The check reads
  the carried value only, so reduce() and reduce_onto() agree.
- Catalog §Structural Containers states the precondition as "no typed child
  object" with the per-container enumeration, matching enforcement exactly.

Coverage: new graph_reduction tests create_rejects_a_non_empty_carried_container
(hierarchy children) and create_rejects_carried_non_hierarchy_children (barline
group / graphic object / measure). DECISIONS M2c gains the create-emptiness bullet.

Stages only ops + spec; the unrelated Agent-I working tree is left untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 09:52:13 -04:00
Levi Neuwirth ca07c28c82 Agent K M2e: catalog expansion + DECISIONS for the M2 broad-K0 groups
The documentation milestone deferred through M2a–M2d. Documentation only —
no Rust changes; the d93baac code gates (cargo test --workspace 533/0,
conformance_suite scale 1) are unchanged.

operation_catalog (v0.1.0 -> v0.2.0):
- Chapter K0 gains full six-part schema sections for every M2-implemented op:
  ModifyEvent; Identified-Pitch Operations (insert/delete/modify, with the
  note<->rest equivalence stated normatively); Transpose; DeleteCrossCutting;
  ModifyCrossCutting; Structural Containers (region/staff-instance/voice
  set-union mint + empty-only delete); Score Settings (advisory metadata,
  structural metric grid with the staff-based + live-time-signature
  preconditions, advisory page break under the resolved-position LWW key).
- Chapter K1 cleanup: the implemented groups now cross-reference their K0
  sections rather than sit in "MUST reject"; the stale Phase-3 listing of
  SetMetadata / SetMetricGrid / page-break advisory (implemented in M2d) is
  removed, and the remaining slots are split to the genuinely-unimplemented
  finer metric ops (time signature / tempo segment) and non-break layout.
- Intro, conformance-profile, and version strings updated for the expansion.
- PDF rebuilt with xelatex (18 pp, no undefined refs); .xdv removed, only
  tex+pdf tracked.

epiphany-ops/DECISIONS.md: new M2c (Group 3 — empty-only structural-container
delete; live-child indices; staff-extent maintenance) and M2d (Group 4 — the
per-op disciplines as review-hardened in d93baac: advisory metadata, metric
grid with both preconditions, resolved-position break key) entries, and a note
that the dedicated 10K-envelope reducer micro-bench (criterion 5) is Agent F's
worklist F1 — the M2 value-typed ops are already exercised at 10K*scale by the
conformance reduction-determinism / convergence gates.

The unrelated Agent-I working tree is left untouched; this commit stages only
spec/ + ops DECISIONS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 22:21:32 -04:00
Levi Neuwirth 7a94814ba3 Cross-seam review fixes: respell→pre-pass visibility, profile enforcement, canonical fingerprint, catalog reconciliation
Addresses four findings spanning the H (pre-pass) and K (reduction) seams plus
the Operation Catalog.

1. [High] A reduced RespellPitch is now visible to the pre-pass. The reducer
   stored overrides only in MaterializedState.spellings, but Agent H's
   derive_annotations resolves authored spellings from score.spelling_attachments
   — so a real respelling accepted by reduce_onto was lost before annotation
   derivation, violating manual-override precedence. respell_pitch now upserts a
   user-chosen explicit SpellingAttachment into the materialized graph
   (materialize_respell / graph_respell_pitch); DeleteIdentifiedPitch drops that
   attachment (graph_delete_pitch) so none dangles (it does NOT tombstone the
   pitch — the event survives a pitch delete and a later ModifyEvent may reuse
   the id, which would make it both live and tombstoned). New testkit gate
   assert_reduced_respell_is_honored reduces a real RespellPitch and proves
   derive_annotations honors it as Authored(UserChosen); wired into run_all.

2. [Medium] PrePassProfile algorithm ids are now enforced, not just recorded.
   derive_annotations ran the default logic and labeled the result with the
   requested algorithm. It now runs each pre-pass only when its requested id is
   the implemented "default"; an unknown/future id yields no annotations for that
   pre-pass (the requested id stays in the result profile), so a future algorithm
   can no longer silently alias the default in a derivation cache. Test:
   unknown_algorithm_ids_are_not_honored.

3. [Medium/Low] The determinism gate now fingerprints canonical bytes, not Debug.
   DerivedAnnotations gains canonical_fingerprint(): embedded graph values
   (PitchSpelling, DecompositionAttachment, SpellingSourceKind — the latter two
   added to the CanonicalValue surface) use their ratified bytes; counts/ids are
   little-endian, length-framed. The pre-pass harness fingerprints with it. A
   discrimination check confirms it is not a degenerate constant.

4. [Low] operation_catalog.tex K1 chapter reconciled with the implemented M2
   work: the now-dispatched ops (event/pitch leaf-field, cross-cutting CRUD,
   structural container CRUD) are listed as implemented-since-M2 (available under
   the Phase-2 profile), and the "MUST reject" scope is narrowed to the genuinely
   deferred slots (create score/canvas/staff, set metadata, metric-grid/time-sig/
   tempo, layout/page-break). PDF rebuilt clean (0 undefined refs).

Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (criterion
1 + the pre-pass and convergence gates); conformance scale 1 passes. The unrelated
Agent-I working tree is left uncommitted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 18:52:34 -04:00
Levi Neuwirth c47f4b5cec Agent K M2a review follow-up: graph-materialization fixes for the leaf-field ops
From the M2a review (no bug in the bookkeeping reduction; the gap was that the
Group-1 ops' *graph* materialization — reduce_onto — was unexercised by the
gates, which hid two invalid-graph edges). Fixes are graph-materialization only;
the bookkeeping projection, and therefore convergence/determinism, is unchanged.

- DeleteIdentifiedPitch of a single-pitch note's last pitch left an empty
  (Chapter-5-invalid) PitchedEvent via EventArena::get_mut (which bypasses
  insert's well-formedness guard). It now degrades the note to a Rest of the
  same id/voice/position/duration; InsertIdentifiedPitch into a rest is the dual
  (rest -> one-pitch note), keeping the graph consistent with the bookkeeping
  that mints/tombstones the pitch object either way.
- ModifyEvent now skips placement-changing (move) and malformed-empty pitched
  replacements in the graph rather than corrupting invariant 3
  (VoiceEventsSortedNonOverlap) via get_mut; voice re-sort stays deferred and the
  LWW bookkeeping still records the modify.

Coverage: graph_edit_session (criterion 1, reduce_onto + check_invariants) now
emits all five Group-1 kinds, so the real-Score gate exercises their graph
mutations at scale; plus two targeted reduce_onto regression tests (note->rest,
rest->note) in tests/graph_reduction.rs.

Docs: DECISIONS.md records the note<->rest equivalence and the ModifyEvent
placement deferral (catalog section prose routed to M2e); Transpose / P12-K2 note
the i8-saturation caveat; valuegen::pitch_value_nth no longer implies spelling()
is injective.

Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (ops
graph_reduction 13, ops lib 51); conformance_suite scale 1 passes. The unrelated
Agent-I working tree is left untouched; this commit stages only ops/testkit/spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 18:25:48 -04:00
Levi Neuwirth 1658fd18f3 Agent K M2a (Group 1): event & pitch leaf-field operations
First broad-K0 subsystem group — five new value-typed ops reusing M1's proven
disciplines (additive: new OperationKind variants 8–12, new apply arms +
reduction methods; framework frozen):

- ModifyEvent { event: Event } — field-overwrite LWW by EventId; concurrent
  differing ⇒ StructuralFieldCollision.
- Transpose { targets, chromatic_steps } — order-dependent; pitch ids preserved;
  canonical footprint = effect-log entry; reduce_onto applies a minimal CMN
  alteration shift (rich interval algebra deferred — P12-K2).
- InsertIdentifiedPitch / DeleteIdentifiedPitch — pitch-within-event mint /
  delete-wins tombstone.
- ModifyIdentifiedPitch { pitch, value: Pitch } — field-overwrite LWW (the pitch
  VALUE, distinct from RespellPitch's spelling-only overwrite).

Design (honesty rule): the modify/transpose ops record effect + conflict
canonically — the resolved values live in the graph (reduce_onto), since
MaterializedState is bookkeeping, not a second graph; respell stays special
because spelling is a bookkeeping-owned annotation. LWW diff uses new
`last_event_modify`/`last_pitch_modify` working maps (synced through
WorkingSnapshot/snapshot/restore).

- core: expose Pitch + IdentifiedPitch via CanonicalValue (no new layout).
- The five kinds are v1-native (no lossy v0 predecessor): project/migrate them by
  identity; only the original kinds reconstruct from a lossy v0 form.
- Generators (testkit operation_payload, ops fuzz gen_payload) now emit the new
  kinds, so the convergence / determinism / migration-equivalence gates exercise
  them at scale; plus targeted migrate identity + reduce LWW/mint/delete tests.

Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (ops lib
51 tests); conformance_suite scale 1 passes. Catalog sections + DECISIONS for
these ops land in M2e per the staged plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 13:56:01 -04:00
Levi Neuwirth 339b1e475b Agent K M1 review follow-up: correct two doc-accuracy findings
From the M1 review (no correctness bugs found; these are accuracy corrections to
shipped artifacts, not new feature work):

- migration gate: the `v1 == migrated` assertion's comment overclaimed a
  universal inverse. It is round-trip self-consistency over the representative
  corpus (which is built from the same valuegen helpers the migration
  reconstructs values with); the spec-level property is the reduction-equivalence
  asserted alongside it. The ReplaceWithRest rest-voice is the known
  non-invertible field, recovered from the deleted event's placement at reduction.
- operation_catalog §CreateCrossCutting: document that v0→v1 migration covers the
  event-anchored Tie/Slur/Beam; a Spanner (anchor-based) cannot be reconstructed
  from the v0 event-reference and is reported unmigratable (read-only) under M1,
  so the catalog no longer silently implies it round-trips.

Review findings deferred to M2 (per project lead): migrate.rs unit tests for the
untested reconstruction branches, and the valuegen::spelling() mod-7 domain
cleanup. Gates unchanged and green (comment + spec-text only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 13:06:22 -04:00
Levi Neuwirth 4556ede9f0 Phase 2 (Agent K) M1: value-typed operation payloads + Operation Catalog scaffold
Foundation milestone for Track B's Operation Catalog: shift epiphany-ops from
the v0 identifier-only payload projections to durable value-typed payloads, and
scaffold the companion spec. Scope: the representative §6.10 set (7 primitives +
2 meta-ops); the slice-driven K0 expansion follows.

Core (the K↔J seam):
- epiphany-core exposes a public `CanonicalValue` trait (canonical_bytes /
  decode_canonical) delegating to the existing private `Codec` machinery, for
  Event/Rest/PitchSpelling/Tie/Slur/Beam/Spanner/RegionTimeModel/TimeAnchor.
  No new byte layout — a value's bytes equal what the whole-score codec emits,
  so all goldens / criterion 4 stay byte-identical.

Ops (value-typed payloads, frozen reduction rules):
- InsertEventOp{staff_instance,event:Event}, RespellPitchOp{pitch,spelling:
  PitchSpelling}, CreateCrossCuttingOp{structure:CrossCuttingValue},
  ChangeRegionTimeModelOp{...,new_time_model:RegionTimeModel},
  SetUserSystemBreakOp{...,anchor:TimeAnchor}, ReplaceWithRest{rest:Rest}.
  Payloads frame each value's CanonicalValue bytes behind a u32 length prefix.
- reduce.rs: read-sites only moved onto the value (rules, conflicts, ordering,
  promotion, re-anchoring, undo, transactions unchanged); reduce_onto now
  materializes the real event/structure instead of the C4 placeholder.
  MaterializedState.spellings now stores PitchSpelling (encode + decode updated).
- v0.rs: frozen identifier-only shapes (migration regression guard).
- migrate.rs: migrate_v0_envelope(v0, &Score) + project_v1_to_v0 + MigrationError;
  deterministic and equivalence-preserving. Respell spelling recovered from the
  score context; irreversible case is P12-K1.
- valuegen.rs: shared value-type builders (reused by fuzz, migration, tests,
  testkit). Resolves P11-C1; P11-C10 Dismiss recorded.

Testkit (Agent F merge gate):
- migration.rs: reduce(v1)==reduce(migrate(project(v1))) byte-identical, plus
  migration determinism and a non-vacuity guard; wired into acceptance.rs as
  agent_k_migration_equivalence_gate. Generators/harnesses build v1 payloads.

Spec:
- spec/operation_catalog.{tex,pdf}: new companion (independent semver) — framework
  + per-primitive template, the 7+2 representative primitives, the v0→v1 migration
  contract, and K1 framework slots for the remaining K0 primitives. Builds clean.
- PASS12_BATCH.md: P12-K1 (respell fingerprint irreversibility).

Gates: cargo build/fmt/clippy -D warnings clean; cargo test --workspace green
(incl. criteria 1/4/5/6 and the new K gate); conformance_suite scale 1 passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:52:02 -04:00
Levi Neuwirth ac7c076e73 Phase 2 (Agent I): visible-slice scaffold — Bravura SVG renderer vs stub
Lands the renderer-against-stub slice of Agent I's visible engraving work
(spec/PHASE2_QUICKSTART.md). Two new crates; prerequisites (G Pass 11, H
spelling/decomposition) are in place. Real engraving + Minimal-tier solver
follow next phase.

epiphany-render-svg (the deliverable this phase):
- Renders a ResolvedLayoutIR to well-formed SVG 1.1, drawing each glyph as a
  GENUINE Bravura SMuFL outline <path>. Outlines are extracted reproducibly
  from the official OFL Bravura.otf by a committed generator
  (tools/extract_bravura_outlines.py, OFL.txt); the font is not vendored, only
  the generated Rust (src/outlines_generated.rs). Staff-space/y-up coords with
  one global y-flip wrapper; viewBox in staff spaces, px scale on the root.
- Non-overreach: every element traces to a ResolvedGlyph (data-prov) or a
  declared wrapper; a glyph lacking an outline is surfaced as a diagnostic and
  drawn as a fallback rect, never silently dropped.
- Hand-rolled xml::check_well_formed (no XML dep); acceptance tests cross-check
  with system xmllint when present.
- examples/render_fixture.rs demo (fixture name -> SVG stdout, --solver=stub|real).
- Golden-locked machine acceptance snapshot + full-SVG golden for
  ten_measure_single_staff and valid_score_rich; deterministic output.

epiphany-engrave (honest scaffold):
- Engraver: a deterministic horizontal-spacing pass (first axis of the planned
  two-pass spring layout). Reports SolverTier::Stub — NOT Minimal — until it
  evaluates the declared hard constraints, guarded by a regression test. The
  demo's --solver=real exercises it end to end.

Honesty notes (recorded as Pass-12 candidates P12-I1..I3 in spec/PASS12_BATCH.md
and the crates' DECISIONS.md): the v0 to_logical/to_constrained pipeline is a
structural placeholder (arbitrary glyph per object, y=0), so stub output is not
yet recognizable notation and the QUICKSTART human visual gate is a next-phase
gate; MUSCLOID layout-id derivation stays unwired; bundled BRAVURA_METRICS are
approximations that disagree with the real outlines.

Gates: cargo fmt + clippy -D warnings clean; cargo test --workspace 504 passed,
0 failed, 0 ignored (criterion 6 layout round-trip still green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:01:40 -04:00
Levi Neuwirth 732660988d Phase 2: spelling + decomposition pre-passes (Agent H) with F merge gate
Land the two real pre-passes as canonical *derived annotations* (pure
functions of the materialized Score + profile, recomputed on
materialization, never serialized into canonical Score bytes), exposed via
`derive_annotations`:

- Spelling: a Temperley-style line-of-fifths centre-of-gravity preference
  rule (key-free, deterministic), preserving authored CMN letters and only
  inferring spelling for chromatic/integer input. `resolve_spelling`
  layers authored overrides above the inferred default (the RespellPitch
  precedence rule). `spell` now takes `&Pitch` and delegates to
  `simplest_spelling`.
- Decomposition: metric greedy-aligned splitting on a 1/4096 integer grid
  (barline + dyadic-boundary ties), with exact sounding->notated tuplet
  conversion before gridding. Components reconstruct the event duration
  (invariant 15).
- A per-event-kind eligibility `TaxonomyReport` so "ineligible" is always
  explicit and counted, never silently absent.

Test infrastructure (Agent F): a 29-fixture representative corpus +
taxonomy harness (corpus.rs), the H spelling/decomposition merge gate
(prepass_harness.rs), a discrete `tests/prepass.rs` CI target, conformance
stage [7b], a dedicated CI job, and the Pass-12 batch tracker.

Review hardening folded in (nine findings):
- Guard `decompose_metric` against a zero-length measure (was a
  divide-by-zero panic; now reported ungriddable).
- Resolve spelling-override priority via `Reverse` instead of negation
  (was an i32::MIN overflow).
- Verify spelling *register* (octave), not just pitch class, in the gate.
- Close the decomposition under-emission gap: the unusual-outcome
  taxonomy buckets are an exact per-fixture whitelist (classify_corpus
  step 5b).
- Generalize `accidental_ids` to a glyph stack so authored extreme
  alterations (triple-sharp+) reconstruct exactly instead of being clamped.
- Per-fixture spread checks in the non-vacuity tripwire and broad-bucket
  coverage, so no single rich fixture can carry a signal (partial-stub
  resistance); added a `mixed_rhythm` fixture for margin.
- Pin the integer-grid note-value math to the canonical rational helpers
  via an exhaustive test; cross-reference comments.
- Replace the O(n^2) tuplet innermost-resolution scan with an id index.

fmt + clippy -D warnings clean; 199 tests pass; conformance suite green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011giSRaHCFCGm1Z2SWv6JHt
2026-06-23 16:33:39 -04:00
Levi Neuwirth 83bc202ff6 Pass 11 follow-up: disambiguate 'reserved built-in tags' in Appendix E
The Canonical Byte-Layout Reference used the phrase 'reserved built-in
tags' in two scopes: the system-derived-identifier section called it the
closed set of three (MUSCSVCE/MUSCSPCH/MUSCSANM), while the domain-tag
registry calls eleven tags 'reserved built-in'. The source section
(req:graph:system-derived) qualifies the three as tags 'for
system-derived identifiers'; the consolidation had dropped that
qualifier, leaving the single-import appendix internally ambiguous for
the Binary Format companion author.

- Restore the scope qualifier and cross-reference the full registry,
  noting the other reserved tags feed plain hashing preimages, not the
  system-derived counter.
- Tighten the 'canonical' gloss: canonical tags produce identifiers and
  content hashes that are part of the interoperable, durably persisted
  form (not loosely 'document state', which misreads the storage-layer
  chunk/manifest/blob tags).

Spec-text only; rebuilds clean (0 undefined refs, 261 pages, no new
overfull boxes). No code or byte-layout change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 14:35:30 -04:00
Levi Neuwirth dffac4c744 Pass 11: consolidated byte-layout appendix + pin ObjectKind/ResolutionAction discriminants
Adds Appendix E (Canonical Byte-Layout Reference) — the single
byte-convention table the Binary Format companion imports — and closes
two pins (ObjectKind, ResolutionAction discriminant bytes) that were
golden-locked in code but absent from spec text. Audit follow-up:
completed the domain-tag registry (added canonical MUSCCONF/MUSCENVH and
non-canonical MUSCFNTM) and corrected golden-lock wording for the two
non-literal-byte anchors (BlobId, RationalTime).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 13:16:20 -04:00
Levi Neuwirth 0d8ec61a3c Pass 11 audit follow-up: honest LayoutObjectId status + doc/test gaps
Independent audit of b2f2e20 / a7adbdc. The canonical, document-state byte
layouts were already correct and golden-locked; this closes the one real
spec-vs-code gap (in the non-canonical layout namespace) and the smaller
doc/test gaps around it.

LayoutObjectId (item 2.6): the spec normatively stated the id "is derived ...
with MUSCLOID" and the ratification log / layout DECISIONS header called it
"pinned" -- but no code uses MUSCLOID (stable_layout_id and
manifestation_layout_id are untagged; synthesized_layout_id borrows MUSCCONF),
and MUSCLOID cannot even be constructed: DomainTag::from_bytes accepts only
built-ins or MUSCS-prefixed tags, so wiring it requires changing the frozen
determinism crate (out of scope for a spec pass, and the spec itself says
MUSCLOID is not a canonical system tag). Kept MUSCLOID as the pinned Track-A
target and made every artifact honest that the v0 code is provisional:
  - spec: "is derived" -> "MUST be derived" (forward contract) + a note that
    the prototype mints provisional ids; changelog "pinned" -> "specified ...
    as the Track-A target".
  - records: ratification-log line 2.6 and layout DECISIONS header/body now
    state spec-pinned-but-code-provisional; stale "Pass 11 candidate 3"
    pointer now cites the ratified requirement.
  - provenance.rs comments name the MUSCLOID target and label the current
    derivation provisional.

Other fixes:
  - epiphany-core/DECISIONS.md: the Tuplet bullet still claimed degenerate
    ratios are caught by runtime invariant 16 "since a Tuplet is a plain
    struct" -- stale after the construction-time TupletRatio change. Rewritten.
  - codec.rs: added degenerate_tuplet_ratio_is_rejected_on_decode, guarding
    the TupletRatio::dec re-validation branch that no test exercised (the
    constructor was tested, the decode path was not).
  - spec: integrity-anomaly snippet kind.canonical_bytes() ->
    to_canonical_bytes() (the actual method).
  - ids.rs / reduce.rs: clarifying comments (ManifestId's intentional,
    golden-locked document_id/generation duplication; compute_promotions
    bucketing by voice == (staff_instance, original_voice) via Invariant 5).

Verification: cargo test --workspace (434 pass, +1), clippy --all-targets clean
(0 warnings), fmt clean; spec rebuilds (lualatex, 0 undefined refs, 254pp).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 10:02:05 -04:00
Levi Neuwirth a7adbdc5a1 Pass 11 follow-up: golden-lock the ratified discriminant tables; fix three spec-text inaccuracies
Audit follow-up to b2f2e20. The ratification was byte-faithful, but the
audit found a gap between the protection the worklist claims ("a
golden-bytes test already locks every byte-layout item") and the
protection actually in place for several newly-normative tables, plus
three small inaccuracies in the ratified spec text.

Golden locks (close the round-trip-vs-golden gap):
- ChunkKind: chunk_kind_discriminants_are_golden pins the literal 0..=8.
  ChunkKind::canonical_bytes() is in the chunk hash preimage, so the
  prior round-trip-only test would let a coordinated renumbering silently
  change every chunk content address while passing.
- CompressionAlgorithm: compression_algorithm_encoding_is_golden pins the
  exact bytes (None -> [0,0], not a bare tag).
- ProfileId (load-bearing superblock field): profile_id_discriminants_are_golden
  pins the u32 discriminants and the fixed 20-byte encoding.
- ResolutionAction / TransactionCategory / ObjectKind: *_discriminants_are_golden
  pin the canonical discriminants (ObjectKind feeds the anomaly id;
  ResolutionAction/TransactionCategory feed operation content hashes).
- IntegrityAnomalyId: integrity_anomaly_id_byte_form_is_locked golden-locks
  the MUSCSANM-derived id (cross-replica agreement is a conformance
  property; it previously had no byte-form golden).

Spec-text fixes (core_spec.tex):
- CompressionAlgorithm: "None = 0 (no payload)" was wrong; the code writes
  a fixed two bytes (discriminant + always-present parameter byte). Text
  now states the fixed-width framing.
- ProfileId: "a single discriminant followed by any variant payload" was
  wrong; it is a u32-LE discriminant + a fixed 16-byte registry id (zero
  unless Custom), 20 bytes total. Text now matches the only encoding.
- TupletRatio listing showed `pub` fields (freely constructible by struct
  literal), contradicting req:time:tuplet-ratio-construction. Listing now
  shows private fields + the checked `new`/`actual()`/`notated()`, matching
  the code.

Test honesty:
- testkit resolution_action generator now emits Dismiss (rng.below(6)); it
  previously skipped the variant, leaving the Dismiss path unfuzzed.

Verification: cargo test --workspace (433 pass, +7), clippy -D warnings
clean, fmt clean; spec rebuilds (lualatex/latexmk, 0 undefined refs, 254pp).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 09:22:55 -04:00
Levi Neuwirth b2f2e204a7 Pass 11: ratify provisional byte choices into normative spec text
Spec-revision pass (architecture unchanged) converting the v0
implementation's provisional, golden-locked choices into ratified
core_spec.tex text, so durable byte layouts are fixed before the
next-phase build-outs. Worklist: spec/PASS11_WORKLIST.md; per-item
dispositions: spec/PASS11_RATIFICATION_LOG.md.

Adopt-and-pin (bytes): TypedObjectId 16-bit BE discriminant table
0..=27 (added the 5 variants the code carried); promoted-voice
(MUSCSVCE), synthetic-pitch (MUSCSPCH, tuning always in identity),
and integrity-anomaly (MUSCSANM, now a reserved built-in tag)
derivations; ChunkKind/ProfileId/CompressionAlgorithm discriminants;
ManifestId preimage (manifest_id excluded); RationalTime/scalar
layouts + the codec convention baseline the Binary Format companion
inherits.

Decide-and-pin: tempo Linear interpolates speed (not bpm);
StructuralFieldCollision tags the winner Conflicted; lifted the
>2-way / partial-overlap voice-promotion rule to normative; pinned
TransactionCategory and ObjectKind core vocabularies; added
ResolutionAction::Dismiss so the Dismissed state is reachable by an
authored op; pinned the (non-canonical) LayoutObjectId derivation
(MUSCLOID).

Fixes: blob hashing is bare MUSCBLOB||payload (deleted the
contradictory "identically to chunks" phrasing); equal-generation
superblock rule (DivergentSameGeneration); defined ProfileConstraints
with the required RetentionPolicy + first-declared precedence; made
the DVV zero-based floor normative; reconciled the invariant count to
19 and named the three construction-time MUSTs — TupletRatio now
rejects degenerate ratios at construction (zero term or
actual==notated), enforced by a checked constructor + codec decode
validation.

Code changes carry regression tests; byte-layout golden tests now
cite their ratified requirements. Workspace green: cargo test, clippy
-D warnings, fmt; spec builds (lualatex, 253pp). Per-crate DECISIONS
files annotated with the ratification status.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011giSRaHCFCGm1Z2SWv6JHt
2026-06-21 22:30:06 -04:00
Levi Neuwirth e9c4bad7a6 Land M1 + M2 (Agent C): framework edge fixes and real-Score graph integration
M1 — fix Agent C framework defects, tests-first:
- causal ordering: topologically order DVV edges instead of assuming HLC
  alone implies causal order (false for adversarial remote envelopes);
  HLC only breaks ties among ready operations.
- anomaly cutoff: quarantine from the earliest counter participating in
  any violating HLC pair (suffix-minima), e.g. [100,200,50] quarantines
  from counter 0, not counter 1.
- pending detection: DVV contiguous ranges use the zero-based per-replica
  counter floor; first absent id in any asserted range holds the dependent
  pending (vector coverage, not only dots).
- transaction snapshots: rollback removes member-generated conflicts.
- edge tests in concurrent_reduction.rs for all six audited cases.

M2 — reduce onto Agent B's real score graph:
- OperationSet::reduce_onto(&Score) -> GraphMaterialization { state, score }
  mutates the real arena, voices, regions, tombstones, indexes, and
  cross-cutting structures; base-free reduce() retained.
- VoiceOrigin::SystemPromoted now carries { winning_operation,
  losing_operation, original_voice }; spec and Invariant 18 updated.
- graph-aware migration, forward undo, system breaks, promotion pre-pass.
- tests/graph_reduction.rs: 11 tests asserting check_invariants is clean,
  plus a 64-seed order-independence sweep.

Pass-11 spec decisions resolved (blocking subset): DVV floor (P11-C7),
HLC-vs-causality, promoted-voice derivation inputs (P11-C4 / core P11-3).
Payload/Score canonical encoding remain deferred to the companion docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 16:37:51 -04:00
Levi Neuwirth a2e9ec32f6 A B C D F 2026-06-19 12:42:31 -04:00