You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Reopening a file silently reuses a stale rope and discards the file's current bytes #350
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:
Jim opens a.txt → buffer B with head H0 built from bytes X.
a.txt changes on disk to bytes Y (another editor, git checkout, formatter).
Jim restarts or reopens a.txt → the host returns B/H0 (bytes X).
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.
Activity
docs(edict): draft Edict-authored rope representation and source
docs(edict): separate import provenance from host synchronization
docs(edict): handle third-party file changes and the save race
docs(edict): make external file reconciliation a first-class contract
docs(edict): treat external file changes as causal transport
docs(ownership): record the import-anchor policy in its canonical owner