From 23b8cfacd3d86dbb959670189719dd880bdb73d9 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Tue, 5 May 2026 14:26:27 -0400 Subject: [PATCH] fix: setup wizard non-interactive safe, TUI script daemon detection + timing --- lisp/system-config.lisp | 5 ++-- org/system-config.org | 5 ++-- org/system-integration-tests.org | 44 +++++++++++++++++++++++++------- test/integration-tui.sh | 44 +++++++++++++++++++++++++------- 4 files changed, 76 insertions(+), 22 deletions(-) diff --git a/lisp/system-config.lisp b/lisp/system-config.lisp index 123b499..869bda2 100644 --- a/lisp/system-config.lisp +++ b/lisp/system-config.lisp @@ -53,10 +53,11 @@ (config-write config)))) (defun prompt (prompt-text) - "Simple prompt that returns user input as a string." + "Simple prompt that returns user input as a string. +Returns nil if stdin is non-interactive." (format t "~a" prompt-text) (finish-output) - (read-line)) + (ignore-errors (read-line))) (defun prompt-yes-no (prompt-text) "Prompts yes/no question. Returns T for yes, nil for no." diff --git a/org/system-config.org b/org/system-config.org index 99f00f4..29ffb75 100644 --- a/org/system-config.org +++ b/org/system-config.org @@ -98,10 +98,11 @@ Creates the config directory tree if it does not exist. ;; REPL-VERIFIED: 2026-05-03T13:00:00 #+begin_src lisp (defun prompt (prompt-text) - "Simple prompt that returns user input as a string." + "Simple prompt that returns user input as a string. +Returns nil if stdin is non-interactive." (format t "~a" prompt-text) (finish-output) - (read-line)) + (ignore-errors (read-line))) #+end_src ** prompt-yes-no diff --git a/org/system-integration-tests.org b/org/system-integration-tests.org index e12ba5c..55c8c6c 100644 --- a/org/system-integration-tests.org +++ b/org/system-integration-tests.org @@ -333,14 +333,35 @@ run_test() { } # ---- Setup ---- -echo "Starting daemon..." -passepartout daemon & -DAEMON_PID=$! -sleep 3 +# Check if daemon is already running (bash /dev/tcp, no nc needed) +if timeout 2 bash -c 'echo >/dev/tcp/127.0.0.1/9105' 2>/dev/null; then + echo "Daemon already running on port 9105" + DAEMON_PID="" +else + echo "Starting daemon..." + passepartout daemon & + DAEMON_PID=$! + for i in $(seq 1 10); do + sleep 2 + if timeout 1 bash -c 'echo >/dev/tcp/127.0.0.1/9105' 2>/dev/null; then + echo " Daemon ready after $((i*2))s" + break + fi + done +fi + done +fi echo "Starting TUI in tmux..." tmux new-session -d -s tui-test "passepartout tui 2>&1 | tee $TUI_LOG" -sleep 4 +# Wait for TUI to render: up to 30 seconds for Croatoan + daemon connect +for i in $(seq 1 15); do + sleep 2 + if grep -q 'Connected v[0-9]' "$TUI_LOG" 2>/dev/null; then + echo " TUI ready after $((i*2))s" + break + fi +done # ---- Tests ---- @@ -358,15 +379,15 @@ test_agent_responds() { tmux send-keys -t tui-test "hello" Enter - # Wait up to 20 seconds for ⬇ to appear + # Wait up to 45 seconds for ⬇ to appear (LLM calls can be slow) while true; do if grep -q '⬇.*[a-zA-Z]\{3,\}' "$TUI_LOG"; then return 0 fi local now_ts now_ts=$(date +%s) - if (( now_ts - before_ts > 20 )); then - echo "TIMEOUT: no agent response in log" >&2 + if (( now_ts - before_ts > 45 )); then + echo "TIMEOUT: no agent response in log after 45s" >&2 return 1 fi sleep 1 @@ -397,7 +418,12 @@ test_status_bar() { } test_connection_drop() { - kill $DAEMON_PID 2>/dev/null || true + # If we started the daemon, kill it. Otherwise kill by port. + if [ -n "$DAEMON_PID" ]; then + kill $DAEMON_PID 2>/dev/null || true + else + pkill -f "sbcl.*passepartout" 2>/dev/null || true + fi sleep 3 grep -qi 'connection.*lost\|ERROR.*Connection' "$TUI_LOG" } diff --git a/test/integration-tui.sh b/test/integration-tui.sh index 19183cb..221c7bf 100755 --- a/test/integration-tui.sh +++ b/test/integration-tui.sh @@ -25,14 +25,35 @@ run_test() { } # ---- Setup ---- -echo "Starting daemon..." -passepartout daemon & -DAEMON_PID=$! -sleep 3 +# Check if daemon is already running (bash /dev/tcp, no nc needed) +if timeout 2 bash -c 'echo >/dev/tcp/127.0.0.1/9105' 2>/dev/null; then + echo "Daemon already running on port 9105" + DAEMON_PID="" +else + echo "Starting daemon..." + passepartout daemon & + DAEMON_PID=$! + for i in $(seq 1 10); do + sleep 2 + if timeout 1 bash -c 'echo >/dev/tcp/127.0.0.1/9105' 2>/dev/null; then + echo " Daemon ready after $((i*2))s" + break + fi + done +fi + done +fi echo "Starting TUI in tmux..." tmux new-session -d -s tui-test "passepartout tui 2>&1 | tee $TUI_LOG" -sleep 4 +# Wait for TUI to render: up to 30 seconds for Croatoan + daemon connect +for i in $(seq 1 15); do + sleep 2 + if grep -q 'Connected v[0-9]' "$TUI_LOG" 2>/dev/null; then + echo " TUI ready after $((i*2))s" + break + fi +done # ---- Tests ---- @@ -50,15 +71,15 @@ test_agent_responds() { tmux send-keys -t tui-test "hello" Enter - # Wait up to 20 seconds for ⬇ to appear + # Wait up to 45 seconds for ⬇ to appear (LLM calls can be slow) while true; do if grep -q '⬇.*[a-zA-Z]\{3,\}' "$TUI_LOG"; then return 0 fi local now_ts now_ts=$(date +%s) - if (( now_ts - before_ts > 20 )); then - echo "TIMEOUT: no agent response in log" >&2 + if (( now_ts - before_ts > 45 )); then + echo "TIMEOUT: no agent response in log after 45s" >&2 return 1 fi sleep 1 @@ -89,7 +110,12 @@ test_status_bar() { } test_connection_drop() { - kill $DAEMON_PID 2>/dev/null || true + # If we started the daemon, kill it. Otherwise kill by port. + if [ -n "$DAEMON_PID" ]; then + kill $DAEMON_PID 2>/dev/null || true + else + pkill -f "sbcl.*passepartout" 2>/dev/null || true + fi sleep 3 grep -qi 'connection.*lost\|ERROR.*Connection' "$TUI_LOG" }