Reviewing the reattach code found the fault it exists to prevent, sitting
in its own save point.
`process::write` used `fs::write`, which truncates before it fills. A crash
inside that window leaves no readable record -- and a missing record reads
as "nothing is running", which is the single answer that makes the next
launch start a *second* CLI against a conversation that already has one.
The window is not rare: the record is rewritten on every read that makes
progress, so many times a second while a turn is producing output.
Written to a neighbouring file and renamed over the real name now. The
rename is atomic, so a reader sees the whole old record or the whole new
one. That also makes the fixed-size padding pointless -- a rename replaces
the file rather than overwriting part of it -- so it goes.
Two more from the same pass:
- A failed read of the stdout log was logged and nothing else. The session
then went deaf with nothing on screen: no more output, no error, a status
that stayed wherever it was. It now says so, closes the queue rather than
stranding messages in it, and reports `Unknown` -- not `Exited`, because
the process may well still be running; what failed is this server's
ability to hear it.
- Sizing the stderr log by reading it. `read_from` with a large offset
answers "how long is it" by allocating the whole file first, which on a
chatty process is a large pointless read on every reattach. `size_of`
asks the filesystem.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VETa8afmpWaYezLCqJhDB8