Skip to content

Add session.ingest() for applying external ops to a live session#347

Open
johannesmutter wants to merge 1 commit into
op-engine/2-splice-opsfrom
op-engine/3-ingest
Open

Add session.ingest() for applying external ops to a live session#347
johannesmutter wants to merge 1 commit into
op-engine/2-splice-opsfrom
op-engine/3-ingest

Conversation

@johannesmutter

Copy link
Copy Markdown
Collaborator

Part 3/4 of the op-engine series (#335). Stacked on op-engine/2-splice-ops.

session.ingest(ops, { origin }) is the supported entry point for external writers — another tab, a sync layer, an agent, a version restore:

  • validates the affected subgraph on a draft BEFORE the doc swaps (validate_transaction_result's affected-set logic is factored into a shared _validate_affected); the session stays untouched when validation throws
  • rebases the live selection: text offsets transform across foreign splices, offsets clamp after whole-value sets, and the selection clears when its node disappeared
  • keeps foreign ops out of local undo — undo() reverts your own edits, never someone else's — and closes the history batch window so a typing batch never straddles a foreign change

Deliberately out (listed in the commit message): repair policies for conflicting op streams, id-stable path rebasing across parent-array reorders, rebasing local undo inverses over foreign splices.

Tests: 11 for this PR.

🤖 Generated with Claude Code

External writers are now a fact of editing: another tab, a sync layer,
an agent, a version restore. Until now they had no supported entry
point — mutating the doc out-of-band skips validation, breaks the
selection and corrupts undo bookkeeping, so hosts fell back to full
reloads.

ingest(ops, { origin }) applies foreign ops through the same commit
funnel as local transactions:

- the affected subgraph is validated on a draft BEFORE the doc is
  swapped (validate_transaction_result's affected-set logic is factored
  into _validate_affected and shared); the session stays untouched when
  validation throws
- on_change listeners fire with the given origin ('external' by
  default)
- the live selection is rebased: text offsets transform across foreign
  splices, offsets clamp after whole-value sets, and the selection
  clears when its node disappeared or cannot be made valid (a batch
  that deletes and recreates the same id keeps the selection)
- foreign ops stay out of the local undo history: undo() reverts your
  own edits, never someone else's
- the history batch window closes, so a local typing batch never
  straddles a foreign change

Batches containing deletes or type changes trigger a full-document
referrer scan, so related foreign ops should arrive as one ingest call
rather than many small ones.

Known follow-ups, kept out of this PR deliberately: repair policies for
conflicting op streams (ingest applies ops as given and rejects invalid
results), id-stable path rebasing across parent-array reorders, and
rebasing local undo inverses over foreign splices.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
svedit Ready Ready Preview, Comment Jul 18, 2026 9:16am

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.

1 participant