diff --git a/ralph-loop/hooks/capture-response.sh b/ralph-loop/hooks/capture-response.sh index d8da50a2..5aa1052b 100755 --- a/ralph-loop/hooks/capture-response.sh +++ b/ralph-loop/hooks/capture-response.sh @@ -37,7 +37,17 @@ if [[ -z "$RESPONSE_TEXT" ]]; then fi # Check for TEXT in the response -PROMISE_TEXT=$(echo "$RESPONSE_TEXT" | perl -0777 -pe 's/.*?(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g; s/\s+/ /g' 2>/dev/null || echo "") +PROMISE_TEXT=$( + printf '%s' "$RESPONSE_TEXT" | + perl -0777 -ne ' + if (/(.*?)<\/promise>/s) { + my $promise = $1; + $promise =~ s/^\s+|\s+$//g; + $promise =~ s/\s+/ /g; + print $promise; + } + ' 2>/dev/null || true +) if [[ -n "$PROMISE_TEXT" ]] && [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then touch "$DONE_FLAG" diff --git a/ralph-loop/hooks/tests/capture-response.test.sh b/ralph-loop/hooks/tests/capture-response.test.sh new file mode 100755 index 00000000..27c91efa --- /dev/null +++ b/ralph-loop/hooks/tests/capture-response.test.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +set -euo pipefail + +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +HOOK="$SCRIPT_DIR/../capture-response.sh" +TEST_PROJECT=$(mktemp -d) +STATE_DIR="$TEST_PROJECT/.cursor/ralph" +DONE_FLAG="$STATE_DIR/done" + +cleanup() { + rm -rf "$TEST_PROJECT" +} +trap cleanup EXIT + +mkdir -p "$STATE_DIR" +cat >"$STATE_DIR/scratchpad.md" <<'EOF' +--- +iteration: 1 +max_iterations: 10 +completion_promise: "ALL TESTS PASS" +--- +Run the requested task. +EOF + +run_case() { + local name=$1 + local response=$2 + local expected=$3 + local actual="absent" + + rm -f "$DONE_FLAG" + jq -n --arg text "$response" '{text: $text}' | + CURSOR_PROJECT_DIR="$TEST_PROJECT" bash "$HOOK" + + if [[ -f "$DONE_FLAG" ]]; then + actual="present" + fi + + if [[ "$actual" != "$expected" ]]; then + echo "FAIL: $name (expected done flag $expected, got $actual)" >&2 + return 1 + fi + + echo "PASS: $name" +} + +run_case "untagged matching text" "ALL TESTS PASS" "absent" +run_case "tagged matching text" \ + "Finished: ALL TESTS PASS" "present" +run_case "tagged text with normalized whitespace" \ + $'\n ALL TESTS\n PASS \n' "present" +run_case "tagged non-matching text" \ + "TESTS FAILED" "absent" +run_case "missing closing tag" "ALL TESTS PASS" "absent" +run_case "empty response" "" "absent"