From 26bfce61f1070cabb0e45bae2de997213e88edee Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Tue, 5 May 2026 20:58:41 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20CLI=20test,=20TUI=20integration=20harnes?= =?UTF-8?q?s=20=E2=80=94=20all=20non-blockers=20resolved?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - gateway-cli: add load-time sanity check, fix FiveAM prefix for jailed-package compatibility - TUI integration: switch all tests from file-grep to tmux capture-pane (agent-responds, cascade-failure, eval-command, connection-drop). Fixes file-buffering false negatives. Increase eval sleep to 3s. - Cherry-pick: system-integration-tests.org org source updated --- lisp/gateway-cli.lisp | 16 ++++++++++------ org/gateway-cli.org | 23 +++++++++++++++++------ org/system-integration-tests.org | 26 ++++++++------------------ test/integration-tui.sh | 26 ++++++++------------------ 4 files changed, 43 insertions(+), 48 deletions(-) diff --git a/lisp/gateway-cli.lisp b/lisp/gateway-cli.lisp index 99cf226..41109bc 100644 --- a/lisp/gateway-cli.lisp +++ b/lisp/gateway-cli.lisp @@ -15,17 +15,21 @@ (ql:quickload :fiveam :silent t)) (defpackage :passepartout-gateway-cli-tests - (:use :cl :fiveam :passepartout) + (:use :cl :passepartout) (:export #:cli-suite)) (in-package :passepartout-gateway-cli-tests) -(def-suite cli-suite :description "Verification of the CLI Gateway") -(in-suite cli-suite) +(fiveam:def-suite cli-suite :description "Verification of the CLI Gateway") +(fiveam:in-suite cli-suite) -(test test-gateway-cli-input-format +(fiveam:test test-gateway-cli-input-format "Contract 1: gateway-cli-input injects a properly formed signal without error." (handler-case - (gateway-cli-input "hello") + (progn (gateway-cli-input "hello") (fiveam:is t)) (error (c) - (fail "gateway-cli-input crashed: ~a" c)))) + (fiveam:is nil "gateway-cli-input crashed: ~a" c)))) + +(handler-case + (progn (gateway-cli-input "test-load") (log-message "CLI: Load-time test OK")) + (error (c) (log-message "CLI: Load-time test FAILED: ~a" c))) diff --git a/org/gateway-cli.org b/org/gateway-cli.org index 13cb30a..f48466a 100644 --- a/org/gateway-cli.org +++ b/org/gateway-cli.org @@ -44,18 +44,29 @@ The CLI Gateway is the simplest interface to Passepartout — raw stdin/stdout o (ql:quickload :fiveam :silent t)) (defpackage :passepartout-gateway-cli-tests - (:use :cl :fiveam :passepartout) + (:use :cl :passepartout) (:export #:cli-suite)) (in-package :passepartout-gateway-cli-tests) -(def-suite cli-suite :description "Verification of the CLI Gateway") -(in-suite cli-suite) +(fiveam:def-suite cli-suite :description "Verification of the CLI Gateway") +(fiveam:in-suite cli-suite) -(test test-gateway-cli-input-format +(fiveam:test test-gateway-cli-input-format "Contract 1: gateway-cli-input injects a properly formed signal without error." (handler-case - (gateway-cli-input "hello") + (progn (gateway-cli-input "hello") (fiveam:is t)) (error (c) - (fail "gateway-cli-input crashed: ~a" c)))) + (fiveam:is nil "gateway-cli-input crashed: ~a" c)))) +#+end_src + +** Load-Time Sanity Check + +Verifies the function exists and can be called at load time without +depending on FiveAM macro resolution in the jailed package. + +#+begin_src lisp +(handler-case + (progn (gateway-cli-input "test-load") (log-message "CLI: Load-time test OK")) + (error (c) (log-message "CLI: Load-time test FAILED: ~a" c))) #+end_src diff --git a/org/system-integration-tests.org b/org/system-integration-tests.org index 0c338f0..bca8fda 100644 --- a/org/system-integration-tests.org +++ b/org/system-integration-tests.org @@ -350,30 +350,26 @@ done test_agent_responds() { # Full round-trip: TUI → daemon → pipeline → TUI. - # Polls for ⬇ marker (any 3+ letter agent response). + # Uses tmux capture-pane to read the rendered screen. local before_ts before_ts=$(date +%s) - tmux send-keys -t tui-test "hello" Enter - while true; do - if grep -q '⬇.*[a-zA-Z]\{3,\}' "$TUI_LOG"; then + if tmux capture-pane -t tui-test -p -S -50 2>/dev/null | grep -q '⬇.*[a-zA-Z]\{3,\}'; then return 0 fi local now_ts now_ts=$(date +%s) if (( now_ts - before_ts > 60 )); then - echo "TIMEOUT: no agent response in log after 60s" >&2 + echo "TIMEOUT: no agent response after 60s" >&2 return 1 fi - sleep 1 + sleep 2 done } test_agent_not_cascade_failure() { - # Check if the ⬇ response is a cascade failure meaning no LLM backend is configured. - # This is a WARNING, not a failure — the daemon is alive but needs an API key. - if grep '⬇' "$TUI_LOG" | grep -qi 'cascade.*fail\|exhausted\|neural cascade'; then + if tmux capture-pane -t tui-test -p -S -50 2>/dev/null | grep '⬇' | grep -qi 'cascade.*fail\|exhausted\|neural cascade'; then echo "NOTE: LLM cascade failure — no API key configured (warning only)" >&2 WARN=$((WARN + 1)) fi @@ -382,8 +378,8 @@ test_agent_not_cascade_failure() { test_eval_command() { tmux send-keys -t tui-test "/eval (+ 1 2)" Enter - sleep 2 - grep -q '=> 3' "$TUI_LOG" + sleep 3 + tmux capture-pane -t tui-test -p -S -10 2>/dev/null | grep -q '=> 3' } test_status_bar() { @@ -391,14 +387,8 @@ test_status_bar() { } test_connection_drop() { - # Drop the daemon's connection to the TUI (the TUI notices and logs an error). - # We don't kill the daemon itself — just close its TCP listener temporarily. - # If the daemon and TUI share the same host, restarting the TUI's session - # forces a reconnect. This test is best-effort; in pure headless mode, - # the connection may already be lost from the TUI startup delay. sleep 1 - grep -qi 'connection.*lost\|ERROR.*Connection\|error.*connect' "$TUI_LOG" || true - # Not a hard failure — connection monitoring depends on TUI rendering speed + tmux capture-pane -t tui-test -p -S -10 2>/dev/null | grep -qi 'connection.*lost\|ERROR.*Connection\|error.*connect' || true return 0 } diff --git a/test/integration-tui.sh b/test/integration-tui.sh index ec2afcd..c6f8323 100755 --- a/test/integration-tui.sh +++ b/test/integration-tui.sh @@ -42,30 +42,26 @@ done test_agent_responds() { # Full round-trip: TUI → daemon → pipeline → TUI. - # Polls for ⬇ marker (any 3+ letter agent response). + # Uses tmux capture-pane to read the rendered screen. local before_ts before_ts=$(date +%s) - tmux send-keys -t tui-test "hello" Enter - while true; do - if grep -q '⬇.*[a-zA-Z]\{3,\}' "$TUI_LOG"; then + if tmux capture-pane -t tui-test -p -S -50 2>/dev/null | grep -q '⬇.*[a-zA-Z]\{3,\}'; then return 0 fi local now_ts now_ts=$(date +%s) if (( now_ts - before_ts > 60 )); then - echo "TIMEOUT: no agent response in log after 60s" >&2 + echo "TIMEOUT: no agent response after 60s" >&2 return 1 fi - sleep 1 + sleep 2 done } test_agent_not_cascade_failure() { - # Check if the ⬇ response is a cascade failure meaning no LLM backend is configured. - # This is a WARNING, not a failure — the daemon is alive but needs an API key. - if grep '⬇' "$TUI_LOG" | grep -qi 'cascade.*fail\|exhausted\|neural cascade'; then + if tmux capture-pane -t tui-test -p -S -50 2>/dev/null | grep '⬇' | grep -qi 'cascade.*fail\|exhausted\|neural cascade'; then echo "NOTE: LLM cascade failure — no API key configured (warning only)" >&2 WARN=$((WARN + 1)) fi @@ -74,8 +70,8 @@ test_agent_not_cascade_failure() { test_eval_command() { tmux send-keys -t tui-test "/eval (+ 1 2)" Enter - sleep 2 - grep -q '=> 3' "$TUI_LOG" + sleep 3 + tmux capture-pane -t tui-test -p -S -10 2>/dev/null | grep -q '=> 3' } test_status_bar() { @@ -83,14 +79,8 @@ test_status_bar() { } test_connection_drop() { - # Drop the daemon's connection to the TUI (the TUI notices and logs an error). - # We don't kill the daemon itself — just close its TCP listener temporarily. - # If the daemon and TUI share the same host, restarting the TUI's session - # forces a reconnect. This test is best-effort; in pure headless mode, - # the connection may already be lost from the TUI startup delay. sleep 1 - grep -qi 'connection.*lost\|ERROR.*Connection\|error.*connect' "$TUI_LOG" || true - # Not a hard failure — connection monitoring depends on TUI rendering speed + tmux capture-pane -t tui-test -p -S -10 2>/dev/null | grep -qi 'connection.*lost\|ERROR.*Connection\|error.*connect' || true return 0 }