Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions bin/fm-backend.sh
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,6 @@ fm_backend_target_exists() { # <backend> <target> [expected-label] [recorded-sc
case "$backend" in
tmux)
fm_backend_source tmux || return 1
fm_backend_tmux_expected_label_matches "$target" "$expected_label" "$recorded_scoped_target" || return 1
# The probe was `tmux display-message -p -t <target> '#{pane_id}'`, which
# exits 0 for a window that no longer exists (tmux silently falls back to
# the session's current window - see fm_backend_tmux_target_exists), so
Expand All @@ -718,12 +717,20 @@ fm_backend_target_exists() { # <backend> <target> [expected-label] [recorded-sc
# fm-teardown.sh refuse to release the task forever, leaking its worktree
# lease.
#
# The probe used to fall back to the recorded scoped target for a
# @window-id. That indirection is gone: the guard above already proves a
# @window-id resolves AND that the session and window it resolves to are
# the recorded ones, which is strictly stronger than probing the recorded
# session:window on its own.
fm_backend_tmux_target_exists "$target"
# ONE tmux round-trip either way. When the caller supplies an expectation
# the identity guard already RESOLVES the target to prove that identity -
# exactly for a session:window, and by reading the id back for a
# @window-id - so its success is itself the existence proof and a second
# probe would only re-ask a question already answered. With no
# expectation there is nothing to verify and the probe is the whole check.
# This path runs in a bounded retry loop in fm-teardown.sh's
# managed_endpoint_is_gone, so a redundant probe there is a doubled
# process spawn per iteration on a machine that may already be loaded.
if [ -n "$expected_label" ] || [ -n "$recorded_scoped_target" ]; then
fm_backend_tmux_expected_label_matches "$target" "$expected_label" "$recorded_scoped_target"
else
fm_backend_tmux_target_exists "$target"
fi
;;
herdr)
fm_backend_source herdr || return 1
Expand Down
7 changes: 7 additions & 0 deletions tests/fm-teardown-suite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6415,6 +6415,13 @@ test_secondmate_registry_updates_are_locked_and_literal() {
case_dir=$(make_case secondmate-registry-locked-literal)
id='foo.bar'
prepare_secondmate_home_fixture "$case_dir" "$id"
# This case is about registry locking, and a secondmate teardown legitimately
# requires an already-quiesced endpoint, so model one the way the rest of this
# suite does. It previously read as gone only by accident: the stub's
# list-windows answers with a hardcoded fm-task-x1, which never matched this
# task's fm-foo.bar window, so the bare-name lookup missed it whatever the
# live marker said.
rm -f "$case_dir/fakebin/.tmux-live"
fm_write_meta "$case_dir/state/$id.meta" \
"window=fm-$id" \
"tmux_session_target=firstmate:fm-$id" \
Expand Down
10 changes: 9 additions & 1 deletion tests/secondmate-helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,15 @@ case "${1:-}" in
prev=$arg
format=$arg
done
if [ -n "$target" ] && [ -f "$FM_FAKE_TMUX_LOG.killed" ] && grep -qxF "$target" "$FM_FAKE_TMUX_LOG.killed"; then
# Compare against the killed log in tmux's PLAIN target spelling. Firstmate
# resolves a window with tmux's exact-match syntax ("=session:=window") so a
# name can never resolve by fnmatch, and real tmux treats that spelling and
# the plain one identically - both fail once the window is killed. This stub
# matches the recorded kill-window target literally, so without normalising
# the "=" markers it would report a killed window as still alive.
probe_target=$(printf '%s' "$target" | tr -d '=')
if [ -n "$probe_target" ] && [ -f "$FM_FAKE_TMUX_LOG.killed" ] \
&& grep -qxF "$probe_target" "$FM_FAKE_TMUX_LOG.killed"; then
exit 1
fi
case "$format" in
Expand Down
Loading