framework tools/tmux: B1 fixes from codex (precedence + TMUX_TMPDIR) + env-disambiguation arm
ci/woodpecker/pr/ci Pipeline was canceled
ci/woodpecker/pr/ci Pipeline was canceled
- MOSAIC_TMUX_SOCKET now disambiguates BEFORE the ambiguity refusal
(the old order told users to set the env var while never consulting
it on multi-hit; codex blocker).
- Socket discovery scans ${TMUX_TMPDIR:-/tmp}/tmux-UID, tmux's own
socket dir — TMPDIR was wrong wherever they diverge (codex blocker).
- Arm A2: env var beats ambiguity (twin delivers on the named socket,
no cross-delivery); arms A/B run hermetic (env unset).
- Same precedence + dir fix applied to brain agent-watch.
This commit is contained in:
@@ -155,15 +155,19 @@ B64=$(printf '%s' "$FULL" | base64 -w0)
|
||||
|
||||
vflag=""; [ "$VERBOSE" = 1 ] && vflag="-v"
|
||||
|
||||
# Socket default resolution (B1, 2026-08-29): explicit -L wins; else the
|
||||
# launcher-exported MOSAIC_TMUX_SOCKET; else the tmux default socket. When
|
||||
# the target session exists on MULTIPLE socket servers and no explicit -L
|
||||
# was given, refuse with a disambiguation error instead of silently picking
|
||||
# one (measured 2026-08-28/29: tasking sends landed in a stale default-
|
||||
# socket twin of the target seat; rc 0 reported honest delivery to the
|
||||
# wrong pane). Local targets only; remote targets pass -L through as-is.
|
||||
# Socket default resolution (B1, 2026-08-29). Precedence: explicit -L >
|
||||
# launcher-exported MOSAIC_TMUX_SOCKET > unique socket hit > refusal on
|
||||
# ambiguity > tmux default socket. The ambiguity refusal fires ONLY when
|
||||
# no explicit or env choice exists and the session name lives on multiple
|
||||
# servers (measured 2026-08-28/29: tasking sends landed in a stale
|
||||
# default-socket twin; rc 0 reported honest delivery to the wrong pane).
|
||||
# Socket discovery scans tmux's own socket dir, ${TMUX_TMPDIR:-/tmp}/tmux-UID
|
||||
# (codex PR #1466: TMPDIR is not where tmux keeps -L sockets).
|
||||
if [ -z "$SOCKET_NAME" ] && [ -n "${MOSAIC_TMUX_SOCKET:-}" ]; then
|
||||
SOCKET_NAME="$MOSAIC_TMUX_SOCKET"
|
||||
fi
|
||||
if [ -z "$SOCKET_NAME" ] && [ -z "$SSH_TARGET" ]; then
|
||||
socket_dir="${TMPDIR:-/tmp}/tmux-$(id -u)"
|
||||
socket_dir="${TMUX_TMPDIR:-/tmp}/tmux-$(id -u)"
|
||||
hits=""
|
||||
for sf in "$socket_dir"/*; do
|
||||
[ -S "$sf" ] || continue
|
||||
@@ -173,17 +177,12 @@ if [ -z "$SOCKET_NAME" ] && [ -z "$SSH_TARGET" ]; then
|
||||
hit_count=$(printf '%s' "$hits" | wc -w)
|
||||
if [ "$hit_count" -gt 1 ]; then
|
||||
echo "agent-send.sh: REFUSING - session '$DST_SESSION' exists on multiple sockets:$hits" >&2
|
||||
echo " Pass -L <socket> explicitly (or set MOSAIC_TMUX_SOCKET)." >&2
|
||||
echo " Pass -L <socket> explicitly (or export MOSAIC_TMUX_SOCKET to disambiguate)." >&2
|
||||
exit 4
|
||||
elif [ "$hit_count" -eq 1 ]; then
|
||||
SOCKET_NAME="${hits# }"
|
||||
elif [ -n "${MOSAIC_TMUX_SOCKET:-}" ]; then
|
||||
SOCKET_NAME="$MOSAIC_TMUX_SOCKET"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$SOCKET_NAME" ] && [ -n "${MOSAIC_TMUX_SOCKET:-}" ] && [ -n "$SSH_TARGET" ]; then
|
||||
SOCKET_NAME="$MOSAIC_TMUX_SOCKET"
|
||||
fi
|
||||
|
||||
socket_args=()
|
||||
if [ -n "$SOCKET_NAME" ]; then
|
||||
|
||||
@@ -88,17 +88,34 @@ done
|
||||
tmux -L "$SOCKET" new-session -d -s "$TWIN" -c "$TMPDIR" 'PS1="❯ " exec bash --noprofile --norc -i'
|
||||
tmux new-session -d -s "$TWIN" -c "$TMPDIR" 'PS1="❯ " exec bash --noprofile --norc -i'
|
||||
amb_rc=0
|
||||
"$AGENT_SEND" -s "$TWIN" -m "must refuse" >/tmp/amb.out 2>/tmp/amb.err || amb_rc=$?
|
||||
env -u MOSAIC_TMUX_SOCKET "$AGENT_SEND" -s "$TWIN" -m "must refuse" >/tmp/amb.out 2>/tmp/amb.err || amb_rc=$?
|
||||
[ "$amb_rc" -eq 4 ] || fail "ambiguity refusal: rc=$amb_rc want 4 (stderr: $(cat /tmp/amb.err))"
|
||||
grep -q "multiple sockets" /tmp/amb.err || fail "ambiguity refusal message missing socket list"
|
||||
grep -qF "$SOCKET" /tmp/amb.err || fail "ambiguity refusal message does not name the test socket"
|
||||
tmux kill-session -t "$TWIN" >/dev/null 2>&1 || true
|
||||
tmux -L "$SOCKET" kill-session -t "$TWIN" >/dev/null 2>&1 || true
|
||||
|
||||
# Arm A2: with MOSAIC_TMUX_SOCKET exported, a twin session is NOT ambiguous:
|
||||
# the env var disambiguates by precedence (codex PR #1466 blocker).
|
||||
tmux -L "$SOCKET" new-session -d -s "$TWIN" -c "$TMPDIR" 'PS1="❯ " exec bash --noprofile --norc -i'
|
||||
tmux new-session -d -s "$TWIN" -c "$TMPDIR" 'PS1="❯ " exec bash --noprofile --norc -i'
|
||||
a2_rc=0
|
||||
MOSAIC_TMUX_SOCKET="$SOCKET" "$AGENT_SEND" -s "$TWIN" -m "env disambiguated" >/tmp/a2.out 2>/tmp/a2.err || a2_rc=$?
|
||||
[ "$a2_rc" -eq 0 ] || fail "env disambiguation: rc=$a2_rc (stderr: $(cat /tmp/a2.err))"
|
||||
sleep 0.2
|
||||
a2_pane="$(tmux -L "$SOCKET" capture-pane -t "=$TWIN:0.0" -p)" || fail "cannot capture twin (arm A2)"
|
||||
grep -qF "env disambiguated" <<<"$a2_pane" || fail "env disambiguation did not deliver on the named socket"
|
||||
a2_default="$(tmux capture-pane -t "=$TWIN:0.0" -p)" || true
|
||||
if grep -qF "env disambiguated" <<<"$a2_default"; then
|
||||
fail "env disambiguation cross-delivered to the default-socket twin"
|
||||
fi
|
||||
tmux kill-session -t "$TWIN" >/dev/null 2>&1 || true
|
||||
tmux -L "$SOCKET" kill-session -t "$TWIN" >/dev/null 2>&1 || true
|
||||
|
||||
# Arm B: session unique to ONE socket, no -L -> auto-resolve to that socket
|
||||
# and deliver there.
|
||||
uniq_rc=0
|
||||
"$AGENT_SEND" -s "$TARGET" -m "autoresolved hello" >/tmp/uniq.out 2>/tmp/uniq.err || uniq_rc=$?
|
||||
env -u MOSAIC_TMUX_SOCKET "$AGENT_SEND" -s "$TARGET" -m "autoresolved hello" >/tmp/uniq.out 2>/tmp/uniq.err || uniq_rc=$?
|
||||
[ "$uniq_rc" -eq 0 ] || fail "unique auto-resolution: rc=$uniq_rc (stderr: $(cat /tmp/uniq.err))"
|
||||
sleep 0.2
|
||||
auto_pane="$(capture_named)" || fail "could not capture named socket pane (arm B)"
|
||||
|
||||
Reference in New Issue
Block a user