daa5d20d9b
F28. The worker spawns the tmux server on its first command, so the server and every agent pane sit in the worker unit's cgroup. Restarting the worker destroyed the sessions it was restarting to manage, and F16's missing-pane branch has been firing on deployment rather than on real execution loss. KillMode is not the fix. Under mixed systemd still SIGKILLs the cgroup remainder once the main process exits, and process only encodes accidental orphaning. The runtime becomes its own service instead. The worker gains After= and Wants= on it, ordering only: a worker that finds the runtime missing must report that rather than be stopped by it. The unit holds an idle session so the server outlives its last agent pane. User must match between the units, since the socket lives under /tmp/tmux-$UID. The installed worker on workpc runs as kami while this file still says orchestra; the staged copy is set to kami to match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011xsXyr5J1RACo71YeKG3Pu
43 lines
1.8 KiB
Desktop File
43 lines
1.8 KiB
Desktop File
# 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]
|
|
Type=forking
|
|
User=orchestra
|
|
# 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.
|
|
#
|
|
# The idle session exists so the server outlives its last agent pane. Without
|
|
# it the runtime exits whenever a task completes, and the next launch spawns a
|
|
# fresh server back inside whichever cgroup asked for it.
|
|
ExecStart=/usr/bin/tmux -L orchestra new-session -d -s orchestra-runtime
|
|
ExecStop=/usr/bin/tmux -L orchestra kill-server
|
|
# 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=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|