Skip to content
Merged
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
35 changes: 35 additions & 0 deletions scripts/lib/self-name.sh
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,41 @@ agmsg_self_name_on_action() {
return 0 # named AND recorded at where I am
fi

# #1137: none of send.sh/inbox.sh/history.sh pass project or type -- they
# never had them to pass, not merely forgot to -- so a record this hook
# writes had two empty fields, and arrange.sh (which requires both) refused
# any seat whose ONLY placement record came from acting rather than from
# spawn/actas/SessionStart (measured live: 12 of 36 records). Resolve them
# here, the same way whoami.sh does for the identical question, rather than
# threading two new arguments through three callers that have no better
# source for them than this process's own cwd and type anyway. Only when
# the caller did not supply them -- a caller that already knows better
# (every other path through the primitive) is never second-guessed.
if [ -z "$project" ] || [ -z "$type" ]; then
# Best-effort, matching every other lazy source in this function: a
# failure here must not block the naming this hook exists to do, so a
# record written with what could be resolved is better than none, and
# the record's own project/type stay only as good as this detection is.
if [ -z "$type" ]; then
# shellcheck disable=SC1091
. "${SKILL_DIR:-}/scripts/lib/type-registry.sh" 2>/dev/null || true
# shellcheck disable=SC1091
. "${SKILL_DIR:-}/scripts/lib/compat.sh" 2>/dev/null || true
# shellcheck disable=SC1091
if . "${SKILL_DIR:-}/scripts/lib/detect-cli-type.sh" 2>/dev/null \
&& declare -F agmsg_detect_cli_type >/dev/null 2>&1; then
type="$(agmsg_detect_cli_type 2>/dev/null || true)"
fi
fi
if [ -z "$project" ]; then
# shellcheck disable=SC1091
if . "${SKILL_DIR:-}/scripts/lib/resolve-project.sh" 2>/dev/null \
&& declare -F agmsg_resolve_project >/dev/null 2>&1; then
project="$(agmsg_resolve_project "$(pwd)" "$type" "$team" 2>/dev/null || true)"
fi
fi
fi

# Slow half, once: name the pane through the same primitive every other path
# uses, and -- the #1109 fix -- record this pane as the seat's placement. The
# `record` claim is legitimate here and only here among the label writers (see
Expand Down
29 changes: 29 additions & 0 deletions tests/test_self_name.bats
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,35 @@ _placement() { # <team> <agent> -> "<terminal>:<id>" or empty
[ "$(_placement team alice)" = 'tmux:/tmp/s:%3' ]
}

@test "a hand-started seat's record carries project and type, not the two empty fields arrange.sh refuses (#1137)" {
_install_fake_tmux; _under_tmux /tmp/s 4242 %3
# None of send.sh/inbox.sh/history.sh pass project or type -- this call
# shape (2 args) is exactly what they do.
[ -z "$(_placement team alice)" ]
agmsg_self_name_on_action team alice
# shellcheck disable=SC1090
source "$SKILL_DIR/scripts/lib/actas-lock.sh"
local rec ref project type
rec="$(agmsg_spawn_path team alice)"
[ -f "$rec" ]
IFS=$'\t' read -r ref project type < "$rec"
[ "$ref" = 'tmux:/tmp/s:%3' ]
[ -n "$project" ]
[ -n "$type" ]
}

@test "a caller that already supplies project and type is never second-guessed (#1137)" {
_install_fake_tmux; _under_tmux /tmp/s 4242 %3
agmsg_self_name_on_action team alice /explicit/project explicit-type
# shellcheck disable=SC1090
source "$SKILL_DIR/scripts/lib/actas-lock.sh"
local rec ref project type
rec="$(agmsg_spawn_path team alice)"
IFS=$'\t' read -r ref project type < "$rec"
[ "$project" = /explicit/project ]
[ "$type" = explicit-type ]
}

@test "named once but never recorded: the next action writes the missing record (#1109)" {
_install_fake_tmux; _under_tmux /tmp/s 4242 %3
# A mark-only prior naming (watch.sh names with five args, no record): the mark
Expand Down
Loading