Skip to content

Reopening a file silently reuses a stale rope and discards the file's current bytes #350

Closed

Description

@flyingrobots

Problem

Reopening a file can show a stale persisted rope as if it were the file's current contents.

The production open path keys the Echo buffer by file path and supplies the file's current bytes as initialText (src/app/workspace/workspace-text-commands.ts, bufferKey: request.filePath). The native host returns any buffer that already exists for that key and discards initial_text without comparing it (native/jedit-echo-host/src/host.rs, open_buffer → existing_buffer, verified on main ecefbbb6). The Echo WAL persists buffers across restarts, so after an outside edit:

  1. Jim opens a.txt → buffer B with head H0 built from bytes X.
  2. a.txt changes on disk to bytes Y (another editor, git checkout, formatter).
  3. Jim restarts or reopens a.txt → the host returns B/H0 (bytes X).
  4. TypeScript pairs H0 with the new disk fingerprint sha256(Y) (workspace-buffer-durability.ts, openedFileDurability), so the buffer is reported as saved/clean while presenting X.

Nothing in Echo binds a rope head to a file digest: BufferFact, HeadFact, and CheckpointFact carry no host digest, and projection_path is unchecked metadata.

Why it matters

Jim presents stale state as current authority. This violates the identity relationship History Over State requires of Jim (ch. 21/42: the rope head must be the workspace coordinate, an explicitly anchored refinement of it, or the source of a witnessed crossing — never a silent second identity) and blocks any durable Jim-on-Echo claim. Related: #251 (end-to-end open/edit/save/restart), #302 (ReplaceRange in Edict).

Required behavior

Opening a file establishes a witnessed relation between the imported bytes and the rope coordinate:

  • The open/import record binds file coordinate, host digest of the imported bytes, and the resulting head (anchored refinement).
  • Reopen compares the current host digest with the anchored digest. Equal → reuse. Different → typed obstruction or an explicit, witnessed external-edit transition (docs/design/0147-unmaterialized-file-frontier.md already sketches expectedHostDigest / ExternalEditIntent). Never silent reuse.
  • Regression: open X, change disk to Y, reopen → must not render X as clean.

Treat as a correctness defect, prerequisite for durable file integration. Save/export (currently unsupportedOperation in workspace-production-text-session.ts) must also work before claiming an end-to-end editor workflow.

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