Skip to content

v0.17.0 — a tmux watchdog, and revive that survives losing the server

Choose a tag to compare

@lacion lacion released this 22 Jul 17:18
f8821b8

Losing the tmux server took the whole board with it — silently, and then permanently. Every spawn vanished at once with nothing said about why, and from then on ⟲ revive answered 503 tmux window lookup failed; revive held to avoid a duplicate session forever, with no way back except starting a tmux server by hand. This release makes that survivable: Fleet Deck now watches the tmux server it depends on, says plainly when it dies, settles the sessions that went down with it so they can be revived, and stands a fresh server back up.

Added

  • A tmux server watchdog. The liveness tick was the only thing watching tmux, and it watched in silence. Per-window absence is deliberately UNKNOWN at runtime — right for one window, wrong for the whole server — so a SIGKILLed tmux left every row live forever: the board kept showing panes that no longer existed and ⟲ revive answered 409 spawn is live, not revivable, with no way for a human to say "it's dead, bring it back". The tick now asks the one question that separates a healthy-but-empty server from a dead one, and acts only on proof (a death certificate plus tmux's own absence verdict — a pane cannot outlive the server that ran it): the loss is announced once, the rows it took down are settled to gone so Revive is offered instead of a 409, and a fresh fleet session is stood back up. It never relaunches an agent — resuming one spends money, so that decision stays with the human. A tmux that merely stops answering is reported too (once, with a matching recovery line) and still condemns nothing.

Fixed

  • Revive no longer wedges permanently when the tmux server dies. Proving the recorded owner dead (ESRCH) is what proves its panes died with it — and retiring the claim destroyed that proof at the instant it was obtained, so exactly one call could answer "empty" and every call after it went back to UNKNOWN. That refusal could not heal, because revive/adopt//rc ask "is this window free?" before ensureSession, the only code that ever creates a tmux server. The proof is now kept as a death certificate (tmux-generation-<port>.retired) that outlives the claim it replaced and is cleared by the next successful claim. A home that never claimed a server still reports UNKNOWN — with no certificate there is no evidence, and a silent socket is exactly what a live server behind an unlinked socket looks like.
  • A failed tmux probe is no longer mistaken for an empty fleet. Only tmux's own two absence verdicts (no server running on …, error connecting to … (No such file or directory)) count as proof that nothing is listening. A timeout, a shadowed or missing tmux binary, an unreadable socket directory or fork exhaustion stays UNKNOWN and fails closed — previously any of them could have told boot reconciliation that a board full of live panes was gone.
  • ensureSession can no longer report success without a tmux server. has-session is a predicate, so an authoritatively-empty short circuit (correct for a listing: there is nothing to list) must not be read as "the session exists".

Full changelog: https://github.com/lacion/fleet-deck/blob/v0.17.0/CHANGELOG.md