diff --git a/scripts/watch.sh b/scripts/watch.sh index 722a95b5b..55b917659 100755 --- a/scripts/watch.sh +++ b/scripts/watch.sh @@ -36,6 +36,7 @@ source "$(cd "$(dirname "$0")" && pwd)/lib/compat.sh" # in — notably Grok Build's `monitor` tool, where "$GROK_SESSION_ID" expands to # empty — still starts the watcher. project_path and agent_type are required. SESSION_ID="${1:-}" +[ "$SESSION_ID" = "-" ] && SESSION_ID="" # #477: caller sentinel for empty session id PROJECT_PATH="${2:?Missing project_path}" AGENT_TYPE="${3:?Missing agent_type}" ACTIVE_NAME="${4:-}" diff --git a/tests/test_watch.bats b/tests/test_watch.bats index 6e6d50929..db6c29e14 100644 --- a/tests/test_watch.bats +++ b/tests/test_watch.bats @@ -845,3 +845,24 @@ _record_handover_events() { [ "$started" -eq 1 ] ! grep -q "Usage: watch.sh" "$out" } + +# Callers pass "${GROK_SESSION_ID:--}" (and the same pattern for other hosts) +# so a launcher that drops a quoted-empty first arg cannot shift project/type. +# watch.sh must fold "-" into the same generated-fallback path as "" (#236). +@test "watch: sentinel '-' session_id resolves like an empty one (#477)" { + local out="$BATS_TEST_TMPDIR/dash-sid.out" + AGMSG_WATCH_INTERVAL=1 bash "$SCRIPTS/watch.sh" - "$PROJ" claude-code alice >"$out" 2>&1 3>&- & + local pid=$! + # Folded to empty => a generated fallback id, so a watch.agmsg-*.pid appears. + local i started=0 + for i in $(seq 1 25); do + if ls "$TEST_SKILL_DIR/run"/watch.agmsg-*.pid >/dev/null 2>&1; then started=1; break; fi + sleep 0.2 + done + kill "$pid" 2>/dev/null || true; wait "$pid" 2>/dev/null || true + [ "$started" -eq 1 ] + # No literal "-" session id leaked into the run dir key space. + refute ls "$TEST_SKILL_DIR/run"/watch.-*.pid >/dev/null 2>&1 + refute grep -q "Usage: watch.sh" "$out" + refute grep -q "ERROR: unknown agent type" "$out" +}