Files
tty7/crates
l0ng-aiandl0ng-ai 5e6bc1246f fix(workspace): stop switching workspaces from destroying live sessions (#410)
* fix(workspace): stop switching workspaces from destroying live sessions

Switching workspaces rebuilt every pane it was asked to restore, and a
window that rebuilt nothing then deleted the workspace outright — tree
and store both. Three separate guesses, each one authorizing an
irreversible act:

- `session_from_tree` erased a pane's id when the tree said `live: false`.
  That flag is a cached observation from another process, reloaded as
  false on every server start, so a quiet pane read as dead while its
  shell was running. The restore had nothing to attach to and spawned a
  fresh shell over it.

- Two servers could start against one config dir. `run_with` decided
  another server was dead by failing to connect once, then unlinked its
  socket and bound its own. The loser kept `control.sock` with an empty
  pane registry, so `MachineGet` reported every pane dead and nothing
  logged an error.

- `finish_hydration` marked a window informed before the rebuild and
  without looking at the result. `tabs_from_session` drops any tab whose
  panes all fail to start, which is every tab when the pane socket is
  unreachable — leaving a window that was empty and authoritative at
  once, and the next switch deleted a workspace with ten live tabs.

Each is now settled by whoever holds the truth: attaching decides
whether a pane is there, an advisory lock decides which process is the
server, and a deletion needs the machine's own mirror to agree that the
workspace is empty.

* fix(state): quarantine a corrupt views.json instead of silently discarding it

machine.json already sets a corrupt file aside before falling back to
defaults; views.json just logged and returned None, and the next save
overwrote whatever the file held. Move the quarantine helpers to config
so both loaders share them.

Also make the no-lock-primitive fallback in the daemon singleton report
Unavailable rather than Taken, so a platform without flock still gets a
server instead of one that refuses to start.

* fix(restore): a failed List no longer reads as every pane being dead

Review follow-ups on #410, all three the same shape the PR exists to
stamp out:

- alive_panes_on flattened a failed List RPC into an empty alive-set,
  which made pane_attachable respawn every pane in the batch over its
  running session. The failure now surfaces as None and the attach
  itself decides, the way session_from_tree already leaves it to.
- pub fn run() bypassed the singleton lock entirely; it had no callers,
  so a future one would have silently reintroduced the split-brain.
  Removed.
- Singleton::path() and the field behind it were unused. Removed.

---------

Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
2026-08-08 16:22:19 +08:00
..