# The tmux execution runtime, owned separately from the worker. # # The worker used to spawn this server implicitly on its first tmux command, # which put the server and every agent pane inside the worker unit's cgroup. # Restarting the worker then destroyed the sessions it was restarting to # manage: a deploy killed the run it was deploying for, and F16's missing-pane # branch fired on deployment rather than on real execution-runtime loss. # # KillMode does not fix that. Under `mixed` systemd still sends the final # SIGKILL to whatever remains in the cgroup, and `process` only encodes # accidental orphaning. The runtime has to be a service of its own. # # Lifecycle this gives you: # systemctl restart orchestra-worker -> panes survive, worker reconciles # systemctl stop orchestra-tmux -> panes die, deliberately # # User MUST match orchestra-worker.service. The socket lives under # /tmp/tmux-$UID, so a mismatch leaves the worker talking to a different # server, or to none. [Unit] Description=Orchestra tmux execution runtime After=network.target [Service] # -D runs the server in the foreground, so systemd tracks the real server pid # as MainPID. Type=forking left MainPID=0, and systemd then read a crashed # server as a clean exit, which Restart=on-failure ignores. # # -D also turns exit-empty off, so the server outlives its last agent pane. # That removes the need for a synthetic idle session to hold it open. # # The socket name is the worker's tmux_socket for this harness (-L, not -S). # Keep the two in step; the worker does not create the server any more. Type=simple User=kami ExecStart=/usr/bin/tmux -D -L orchestra # The runtime coming back empty is honest: the panes are gone either way, and # F16 observes that as real execution loss. Refusing to restart would instead # block every later launch until an operator noticed. Restart=on-failure RestartSec=1 [Install] WantedBy=multi-user.target