Skip to content

Hot-exit does not persist redo/undone state (futureStack) — undo of a saved edit is lost on reopen #425

@zknpr

Description

@zknpr

Split out from PR #424 review (CodeRabbit, src/core/undo-history.ts:258) as a tracked follow-up. Pre-existing on main — not introduced by the web-edit PR — and affects both desktop and web, so it's out of scope for #424 and deserves its own change.

Problem

ModificationTracker.serialize() persists only { timeline, checkpointIndex }:

// src/core/undo-history.ts
serialize(): Uint8Array {
  const payload = { timeline: this.timeline, checkpointIndex: this.checkpointIndex };
  ...
}

But stepBack() (undo) and rollbackToCheckpoint() move entries into futureStack (the redo stack), which is not serialized. Hot-exit restore opens the last saved DB bytes and replays only getUncommittedEntries() (timeline.slice(checkpointIndex)).

Consequence

Repro:

  1. Make an edit, save (checkpoint advances past the edit).
  2. Undo that saved edit (entry moves to futureStack; document is now dirty).
  3. Hot-exit (close VS Code with the dirty doc), then reopen from the backup.

Expected: the database reflects the undone state (edit removed).
Actual: restore opens the saved bytes (which still contain the edit) and replays no forward entries, so the undone state is lost — and the redo stack is gone entirely.

Possible approaches (design decision — not prescribing)

  • Persist futureStack + futureStackSizes and reconstruct the cursor on restore, then replay the net state (requires representing the undo, e.g. applying inverse ops or re-deriving live state).
  • Snapshot the live DB bytes for the hot-exit backup instead of replaying forward entries from the saved image (exact, simpler to reason about, larger backups).

CodeRabbit tagged this a "Heavy lift"; flagging for a dedicated PR with its own tests (desktop + web hot-exit round-trips covering undo-of-saved-edit).

Refs: PR #424 review thread on src/core/undo-history.ts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions