fix(tmux): resolve send-message targets to an exact session and window
tmux resolves the two halves of a target with different, individually
dangerous defaults, and send-message.sh took both defaults:
* An unpinned name PREFIX-matches. With `foobar` alive and no `foo`,
`-t foo` resolves to `foobar` at rc=0 -- pasted, Enter-ed, verified
and reported OK against the wrong agent's pane.
* A bare `=name` is only half a pin. capture-pane REJECTS it ("can't
find pane") while list-panes silently PREFIX-MATCHES it, and the
validation at :76 uses list-panes -- so for any caller already
supplying `=name`, that rewrite was the only thing between them and
a wrong-session pass.
The direction is what makes this expensive. Paste (:93-94), Enter (:151)
and the verifying capture (:153) all read one EFFECTIVE_TARGET, so a
wrong-window send is confirmed by a wrong-window read: it manufactures a
false "delivered", not a loud failure. A false negative gets
investigated; a false positive gets believed.
Normalise to `=session:` -- exact session, active window. Explicit tmux
ids (%pane, @window, $session) pass through untouched.
BEHAVIOUR CHANGE for callers that already pass `=name`: they previously
landed on `:0.0` (window 0 unconditionally) and now land on the session's
ACTIVE window. This is the intended fix -- window 0 is not where a
multi-window agent is sitting -- but it does move a live target rather
than being a no-op normalisation.
Test: test-send-message-target.sh covers all four arms (absent name must
not prefix-match, delivery follows the active window, an explicit window
part is preserved, a unique prefix is still refused). Proven able to go
red: against the pre-fix script it FAILs at arm 1, and with arm 1 removed
it FAILs at arm 2. The multi-window fixture is load-bearing -- a
single-window session cannot tell `=s:` from `=s:0.0`, which is why this
survived.
It is registered as a signed enumeration exclusion rather than on a CI
surface: it drives a real tmux server and the CI image ships no tmux,
the same condition its two siblings are already excluded under. It
hard-fails when tmux is absent rather than skipping, so it cannot go
quietly green where it cannot run.
This commit is contained in:
@@ -64,13 +64,31 @@ if [ -n "$SOCKET_NAME" ]; then
|
||||
tmux_cmd+=(-L "$SOCKET_NAME")
|
||||
fi
|
||||
|
||||
# tmux accepts `=session` for some commands, but pane-level commands such as
|
||||
# capture-pane require a pane-qualified target. Keep exact-session addressing
|
||||
# convenient while avoiding accidental prefix matches.
|
||||
# Normalise the target to an EXACT session plus a window part, because tmux
|
||||
# resolves the two halves with different and individually dangerous defaults:
|
||||
#
|
||||
# * An unpinned name is a PREFIX match. With a session `foobar` alive and
|
||||
# no session `foo`, `-t foo` resolves to `foobar` at rc=0, so a message is
|
||||
# delivered, verified and reported OK against the wrong agent's pane.
|
||||
# * A bare `=name` is not enough on its own: capture-pane REJECTS it
|
||||
# ("can't find pane") while list-panes silently PREFIX-MATCHES it, so the
|
||||
# validation below would pass on a session the capture cannot read.
|
||||
# * A trailing `:` follows the session's ACTIVE window. Pinning `:0.0`
|
||||
# instead addresses window 0 unconditionally, and since the paste, the
|
||||
# Enter and the verifying capture all use EFFECTIVE_TARGET, a multi-window
|
||||
# agent gets typed into window 0 and confirmed by reading window 0 --
|
||||
# a false "delivered" rather than a loud failure.
|
||||
#
|
||||
# Explicit tmux ids (%pane, @window, $session) are passed through untouched;
|
||||
# prefixing `=` to them would break addressing that is already unambiguous.
|
||||
EFFECTIVE_TARGET=$TARGET
|
||||
if [[ "$TARGET" == =* && "$TARGET" != *:* ]]; then
|
||||
EFFECTIVE_TARGET="${TARGET}:0.0"
|
||||
fi
|
||||
case "$TARGET" in
|
||||
=*|%*|@*|\$*) ;;
|
||||
*) EFFECTIVE_TARGET="=$TARGET" ;;
|
||||
esac
|
||||
case "$EFFECTIVE_TARGET" in
|
||||
=*) [[ "$EFFECTIVE_TARGET" == *:* ]] || EFFECTIVE_TARGET="${EFFECTIVE_TARGET}:" ;;
|
||||
esac
|
||||
|
||||
# Target must resolve to a live pane.
|
||||
if ! "${tmux_cmd[@]}" list-panes -t "$EFFECTIVE_TARGET" >/dev/null 2>&1; then
|
||||
|
||||
Reference in New Issue
Block a user