Skip to content

fix(rfc64): settle SWM only after VM commit - #2040

Open
branarakic wants to merge 2 commits into
codex/rfc64-m1-edge-periodic-scope-planfrom
codex/rfc64-m1-finalization-ordering
Open

fix(rfc64): settle SWM only after VM commit#2040
branarakic wants to merge 2 commits into
codex/rfc64-m1-edge-periodic-scope-planfrom
codex/rfc64-m1-finalization-ordering

Conversation

@branarakic

Copy link
Copy Markdown
Contributor

User impact

An Edge node no longer hides a synchronized SWM assertion until the corresponding VM transition is genuinely durable:

  • if trusted VM metadata repair fails, the matching SWM assertion remains queryable and the round remains retryable;
  • a cold join with exact VM content but unavailable transaction provenance still retires only the matching SWM head, while provenance remains explicitly pending;
  • snapshot catch-up materializes content and metadata first, then performs finalization settlement before advancing completion checkpoints.

This closes the failure mode where a store/RPC interruption could make content disappear from the user-facing SWM view before VM recovery completed.

Before

sequenceDiagram
    participant Sync as Sync or reconcile
    participant Store as Triple store
    participant SWM as SWM query view
    Sync->>SWM: Write finalized marker early
    Sync->>Store: Repair VM metadata
    Store--xSync: Repair fails
    Note over SWM: Matching SWM is hidden despite incomplete VM repair
Loading

After

sequenceDiagram
    participant Sync as Sync or reconcile
    participant Lock as Per-KA lock
    participant Store as Triple store
    participant Settle as Finalization settlement
    participant SWM as SWM query view
    Sync->>Lock: Materialize verified graph and head
    Lock->>Store: Commit graph and verified metadata
    Store-->>Sync: Commit succeeds
    Sync->>Settle: Revalidate finalized VM outside lock
    Settle->>SWM: Retire only matching current head
    Note over Sync,SWM: Any commit failure leaves SWM visible and retryable
Loading

Implementation

  • moves SWM retirement from the top of the verified-VM branch to explicit successful terminal outcomes;
  • keeps the deliberate no-provenance cold-join retirement path;
  • retires after successful applied or preserved-metadata finalization, never before an atomic repair that can fail;
  • restores SharedMemorySnapshotMaterializer as a store-only adapter;
  • adds a required higher-level SharedMemorySnapshotCommitter that composes materialization with post-commit settlement without lock recursion.

Validation

  • pnpm --filter @origintrail-official/dkg-agent build
  • focused finalization/materialization suite: 3 files, 79 tests passed
    • ka-graph-finalization-handler.test.ts
    • swm-public-snapshot-materialization.test.ts
    • swm-snapshot-materializer.test.ts
  • regression proves a failed trusted metadata repair leaves no retirement marker and keeps SWM query results visible
  • real committer test proves every settled descriptor is delegated to the finalization owner
  • git diff --check

Stacked on #2039.

Comment thread packages/agent/src/sync/requester/swm-snapshot-committer.ts Outdated
Comment thread packages/agent/src/finalization-handler.ts Outdated
@branarakic
branarakic force-pushed the codex/rfc64-m1-finalization-ordering branch from d52ab96 to 8cd5a47 Compare August 3, 2026 03:42
@branarakic
branarakic force-pushed the codex/rfc64-m1-edge-periodic-scope-plan branch from c73afcc to cd49cfe Compare August 3, 2026 03:46
@branarakic
branarakic force-pushed the codex/rfc64-m1-finalization-ordering branch from 8cd5a47 to 6d75cc0 Compare August 3, 2026 03:46
// snapshot lock above: the finalizer acquires that same lock before
// stamping the local retirement marker. A failed insert therefore keeps
// the recovery snapshot visible and cannot deadlock settlement.
if (settleGraphScopedSnapshot) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Snapshot materialization can now be wired without its required settlement step

What's wrong
This PR reintroduces two independent optional knobs for one protocol. The code comment says settlement is post-commit policy for materialized snapshots, but the type system no longer enforces that relationship, so readers and future callers must remember a hidden invariant instead of being guided by the API.

Example
A future caller or test harness can pass snapshotMaterializer and publicSnapshotStore but omit settleGraphScopedSnapshot; the sync path will still write verified snapshots and metadata, then silently skip post-commit retirement. That is exactly the half-wired mode the old cohesive materializer contract was designed to prevent.

Suggested direction
Keep the ordering outside the lock, but model materialization plus post-commit settlement as one dependency again. A small GraphScopedSnapshotCommitter/commitSettledSnapshots abstraction could own the full protocol while still exposing an internal store adapter for the lock-bound writes.

For Agents
Look at SharedMemorySyncContext, runSharedMemorySync, and createSharedMemorySnapshotMaterializer. Preserve the current ordering requirement: materialize under the per-KA lock, insert verified metadata, then settle outside the lock. Prove the contract cannot be half-wired, ideally with a type-level/harness case where materialization-enabled sync must also provide settlement.

* verified metadata insert succeeds and outside the per-KA write lock.
*/
snapshotMaterializer?: SharedMemorySnapshotMaterializer;
settleGraphScopedSnapshot?: (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: The split settlement dependency is not verified against the half-configured case

What's wrong
This change moves post-commit settlement out of SharedMemorySnapshotMaterializer, but the new callback is optional and the coordinator no-ops when it is missing. The added tests validate the desired ordering only in harnesses that provide the callback, so they would not fail if a production or future caller materialized verified public SWM snapshots without retiring the finalized recovery copy.

Example
A caller supplies snapshotMaterializer and publicSnapshotStore so a verified graph-scoped snapshot is materialized, but omits settleGraphScopedSnapshot. runSharedMemorySync still inserts metadata, records phase completion, and never calls retireSyncedGraphScopedSwmIfFinalized, so the missing post-commit retirement is not caught by the current tests.

Suggested direction
Either make settlement a required dependency whenever snapshot materialization is enabled, or add a focused test proving that omitting it fails or leaves the phase incomplete instead of silently checkpointing.

Confidence note
I did not run the test suite in the read-only sandbox, but the diff and surrounding tests show the coordinator only exercises settlement when a callback is provided.

For Agents
Look at runSharedMemorySync in packages/agent/src/sync/requester/shared-memory-sync.ts and its snapshot materialization tests. Preserve the new ordering where settlement runs after verified metadata insertion and outside the KA lock, but add a regression test or contract check for the half-configured case: materializer present with settled descriptors but no settleGraphScopedSnapshot should not silently complete as successful materialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants