Standalone follow-up to the M2b review: close the pre-existing reanchor /
graph-delete divergence, which unlocks at-scale criterion-1 coverage for the
Group-2 cross-cutting CRUD ops.
The divergence: a DeleteEvent tombstoning a slur/spanner endpoint re-anchored the
structure in the bookkeeping ledger (object stays Live) but materialize_graph_delete
removed it from the graph unconditionally — so the object was Live in
MaterializedState yet gone from the Score. Latent only because graph_edit_session
never created cross-cutting structures.
Fix (graph-materialization only; bookkeeping/convergence unchanged):
- materialize_graph_delete now mirrors reanchor_for_tombstone for slurs and
spanners: an endpoint-deleted structure re-anchors onto its surviving endpoint
(stays in the graph) and is removed only when no endpoint survives. A
two-endpoint structure collapses onto the survivor (degenerate (B,B), but
reference-clean — the cross-cutting invariant requires only live endpoints;
proximity-aware target deferred, P11-C5). Ties (cascade) and beams
(truncate-while->=2) were already consistent and are unchanged. This also fixes
a latent dangling-spanner bug (spanners weren't handled on event delete at all).
- seed_from_graph records each base-score spanner's event-anchored endpoints in
`structures`, so a seeded spanner re-anchors through the same rule as a created
one.
Coverage:
- New reduce_onto tests: deleting one slur endpoint re-anchors in both graph and
ledger (slur Live + collapsed onto survivor); deleting both cascades in both
(slur Tombstoned + removed).
- graph_edit_session now creates slurs over replica-0 events and emits
DeleteCrossCutting / ModifyCrossCutting, so criterion 1 (reduce_onto +
check_invariants, across delivery permutations) exercises cross-cutting CRUD and
slur re-anchoring at scale.
Docs: DECISIONS.md records the graph-follows-ledger re-anchoring decision and the
degenerate-collapse / P11-C5 deferral.
Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (ops
graph_reduction 20; criterion 1 green with cross-cutting wired in); conformance
scale 1 passes. The unrelated Agent-I working tree is left uncommitted; this
commit stages only ops/testkit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>