- write.rs: a save's new base is sha256 of the bytes written; the script's
post-mv hash comes back as disk_hash, and a mismatch (another writer landed
after us) shows "Changed on disk" instead of being adopted (ledger M2).
- write.rs: conflict:/gone:/read-only strings are constants with a pure
saved_file() mapping and tests; app/src/viewer/ipcMessages.ts is the one TS
copy and a cargo test checks it against the Rust originals.
- write.rs: the comment now says the in-place `cat >` fallback follows a
planted symlink, and why that is accepted (runs as claude).
- poll.rs: a file deleted between `test -f` and `sha256sum` reads as gone.
- viewerState/EditorPane: poll_failed carries its message; only the
"Start the project before" refusal reads as Container not running, anything
else gets its own banner and leaves Save enabled.
- EditorPane: a failed first read shows Retry and is retried by the poll.
- spec §1: refused OSC 8 targets keep the refusal card (Task 9 ruling).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Keep CRLF (or CR) line endings and a UTF-8 BOM through the editor:
textFormat.ts records the dominant separator and the BOM on load and
restores both on save, so a save changes only the user's edits.
- A clean document whose reload failed retries on the next poll.
- A poll that overlaps a save, or was issued before one settled, is
ignored instead of reading the pre-save hash as a change.
- A conflict whose follow-up poll has no hash shows an error with a
Reload button rather than an Overwrite that could only conflict again.
- Match write.rs's exact read-only message; show the read-only reason as
visible text; error banners are role="alert".
- vite/client types move to src/vite-env.d.ts.
- Tests: CRLF and BOM saves, reload retry, poll/save race, null-hash
conflict, Save and close success and failure, and CodeEditor.setDoc
keeping cursor and scroll.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- viewerState.ts: pure reducer for the clean/dirty, same/changed/gone,
container-down and overwrite-on-save states (spec §5), plus the
pollEffect/canSave helpers EditorPane will drive off.
- editability.ts: classifies a fetched file as text/image/binary and
decides whether it is editable, deferring to Rust's readonly_reason
when it refuses.
Per preflight P1, languages.ts/.test.ts move to Task 10 (needs the
CodeMirror packages Task 6 installs; out of scope for this task's
worktree). Per P3, the "reloaded" action now carries `truncated` and
`polledHash` so a poll-driven reload of a truncated (prefix-hash-only)
file adopts the polled full-file hash instead of re-triggering a
reload on every subsequent poll -- with a reducer test covering it.
Per P13, tightened the poll_failed/canSave test to start from a dirty
doc so it actually exercises containerDown rather than passing only
because the doc was clean.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>