Reliable loop messaging: msg-loop.sh + hardened ping_session (retry submit)

tmux `send-keys -l <long msg>` often leaves the text UNSENT in the input box (the
immediate Enter is swallowed while the TUI ingests the paste). Both now type the
message then retry Enter/C-m until the leading text is no longer in the input box
(= submitted) or a bounded loop gives up.
- msg-loop.sh: standalone reliable messenger for orchestrator use.
- launch.sh ping_session: same retry-submit (loads on next watchdog restart).
Live-tested: delivered first try.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 15:31:28 +01:00
parent 7a1f7f75aa
commit 71a4a1fea4
2 changed files with 46 additions and 3 deletions

View File

@ -142,11 +142,21 @@ stop_loops() {
done
}
# Wake a loop by typing a one-line message into its tmux session (queues if mid-turn).
# Wake a loop by typing a message into its tmux session and SUBMITTING it. A single Enter after a
# long `send-keys -l` is often swallowed while the TUI ingests the paste (text left unsent in the
# input box), so retry Enter/C-m until the message's leading text is no longer in the input box.
ping_session() {
local s="$1" msg="$2"
local s="$1" msg="$2" prefix i
session_alive "$s" || return 0
tmux send-keys -t "$s" -l -- "$msg" 2>/dev/null && { sleep 0.3; tmux send-keys -t "$s" Enter 2>/dev/null; }
prefix="${msg:0:28}"
tmux send-keys -t "$s" -l -- "$msg" 2>/dev/null || return 0
sleep 0.5
for i in 1 2 3 4 5; do
tmux send-keys -t "$s" Enter 2>/dev/null
sleep 1
tmux capture-pane -pt "$s" 2>/dev/null | tail -4 | grep -qF -- "$prefix" || return 0 # submitted
tmux send-keys -t "$s" C-m 2>/dev/null; sleep 0.5
done
}
# A loop can stall ALIVE on a usage/spend-limit notice: the claude process stays up (so the

33
cc-ci-plan/msg-loop.sh Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env bash
# msg-loop.sh — reliably send a message to a loop's tmux session AND submit it.
# -------------------------------------------------------------------------
# `tmux send-keys -l <long message>` frequently leaves the text sitting UNSENT in
# the input box (the immediate Enter is swallowed while the TUI is still ingesting
# the paste). This types the message, then retries Enter/C-m until the text is no
# longer in the input box (= it was submitted), or gives up after a bounded loop.
#
# msg-loop.sh <tmux-session> <message...>
# exit 0 = delivered; 2 = could not confirm submit; 1 = bad args / no session.
set -uo pipefail
S="${1:?usage: msg-loop.sh <session> <message...>}"; shift
MSG="$*"
[ -n "$MSG" ] || { echo "msg-loop: empty message"; exit 1; }
tmux has-session -t "$S" 2>/dev/null || { echo "msg-loop: no tmux session '$S'"; exit 1; }
PREFIX="$(printf '%s' "$MSG" | head -c 28)"
# Submitted ⇔ the message's leading text is no longer in the input box (bottom of the pane).
in_input_box() { tmux capture-pane -pt "$S" 2>/dev/null | tail -4 | grep -qF -- "$PREFIX"; }
tmux send-keys -t "$S" -l -- "$MSG" 2>/dev/null || { echo "msg-loop: send-keys failed"; exit 1; }
sleep 0.8
for _ in 1 2 3 4 5 6 7 8 9 10; do
tmux send-keys -t "$S" Enter 2>/dev/null || true
sleep 1.2
in_input_box || { echo "$S: delivered ✔"; exit 0; }
tmux send-keys -t "$S" C-m 2>/dev/null || true # some TUI states take C-m not Enter
sleep 0.8
in_input_box || { echo "$S: delivered ✔"; exit 0; }
done
echo "$S: WARNING — could not confirm submit; message may remain in the input box"
exit 2