Commit Graph

8 Commits

Author SHA1 Message Date
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