61af05c7328da2c4657246df764ced4d797410b1
Restarting the server relaunched a driver for every session in the config, and ClaudeDriver::launch starts a process when there is none to adopt -- so a session somebody had deliberately stopped came back at the next rebuild, and the Idle its new driver announced stamped the session as active at that moment. On the phone that read as every session idle and "just now" after every restart, with the list sorted by that time in an order that meant nothing. A launch now says why it is happening. Launching::Restart takes charge of the processes still running and leaves every other session as it found it; Launching::Asked -- a spawn, a Start, a message -- starts one where there is none. A session with no process therefore has no driver: DriverCell is an option rather than a driver whose requests go nowhere, and LiveSession::ask reports what could not happen instead of sending into a dead fifo. Two clocks that moved on their own, both the same lie in the same field that Transcript::last_activity exists to prevent: - The status a launch has to correct is written into the transcript at the time of the last thing the session actually did. A backend killed mid-turn leaves a transcript saying Running, which has to become Exited -- but this server noticing is not the session doing something. - A session that has never done anything reports when it was created. Its transcript is empty, since a driver announcing the state it starts in is not news, so it is the one session with no line to read a time off and the clock was the fallback. Exercised end to end against a real server: a stand-in CLI adopted across a restart keeps its status and its time, a stopped session stays stopped with no process started, a process killed while the backend was down reports exited stamped at the last thing the session did, and Start brings it back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Languages
Rust
54%
Kotlin
43.6%
Shell
2.4%