Ralph Loop accepts an untagged response as a completion promise
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 84/100
Research direction
Start with ralph-loop/hooks/capture-response.sh and reproduce the documented Perl extraction with tagged, untagged, empty, and malformed responses. Check the related comparisons and done-flag handling in ralph-loop/hooks/stop-hook.sh. Done means only complete tagged promises can create the flag, with whitespace normalization preserved, and tests cover tagged and untagged cases.
Written by the indexing model from the issue text.
Description
Description
ralph-loop/hooks/capture-response.sh is intended to recognize a completion promise only when an assistant response contains:
<promise>EXPECTED TEXT</promise>
The current Perl expression uses -p:
PROMISE_TEXT=$(echo "$RESPONSE_TEXT" | perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g; s/\s+/ /g' 2>/dev/null || echo "")
Perl's -p mode prints the pattern space even when the <promise> substitution does not match. Consequently, an untagged response is returned as PROMISE_TEXT after whitespace normalization.
If that response exactly matches the configured completion promise, the hook creates .cursor/ralph/done. The stop hook then treats the loop as complete and terminates it, even though the required <promise> tag was absent.
Affected files
ralph-loop/hooks/capture-response.sh, lines 39–44ralph-loop/hooks/stop-hook.sh, lines 43–48 and 73–77
Steps to reproduce
Run the current extraction expression with an untagged response:
printf '%s' 'ALL TESTS PASS' | \
perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g; s/\s+/ /g'
Actual output:
ALL TESTS PASS
In an active Ralph Loop whose configured completion promise is ALL TESTS PASS, this untagged response satisfies the equality check and creates the done flag.
Expected behavior
When the response does not contain a complete <promise>...</promise> element, PROMISE_TEXT should be empty and the done flag should not be created.
Actual behavior
An untagged response is treated as the extracted promise text and can prematurely complete the loop when it equals the configured promise.
Proposed fix
Use non-printing mode and print only after an explicit tag match:
PROMISE_TEXT=$(echo "$RESPONSE_TEXT" | perl -0777 -ne '
if (/<promise>(.*?)<\/promise>/s) {
my $p = $1;
$p =~ s/^\s+|\s+$//g;
$p =~ s/\s+/ /g;
print $p;
}
' 2>/dev/null || echo "")
Acceptance criteria
- An untagged response that equals the configured completion promise does not create the done flag.
- A correctly tagged promise still creates the done flag.
- Whitespace inside a tagged promise continues to be normalized before comparison.
- Empty, malformed, or partially closed promise tags do not complete the loop.
- Tests cover both tagged and untagged responses.
- Dominant language
- TypeScript
- Stars
- 8.2k
- Forks
- 751
- Avg merge
- 12h 1m
- Merged PRs (30d)
- 43
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cursor/plugins
-
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
-
Zoom connector Open
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Similar issues
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100