Skip to content

ralph-loop: four open hook fixes in one branch (#620, #444, #777, #658) - #1000

Open
deanrie wants to merge 6 commits into
cursor:mainfrom
deanrie:bundle/ralph-loop-hooks
Open

deanrie wants to merge 6 commits into
cursor:mainfrom
deanrie:bundle/ralph-loop-hooks

Conversation

@deanrie

@deanrie deanrie commented Oct 27, 2026 •

Copy link
Copy Markdown

What

One branch with the four open ralph-loop hook fixes that touch the same lines, applied in order so the maintainers do not have to resolve them against each other: #620 (mine), #444 (@Mosquito1123), #777 (mine, trimmed to its frontmatter half) and #658 (@rudycelekli). Each change keeps its own commit and author. If a single PR is easier to review, this replaces #620, #444, #777 and #658; if the separate PRs are preferred, close this one and land them in that order.

Included

Commit Original Change
e69369c, 60eea47, 0b5203e #620 hook paths go through CURSOR_PLUGIN_ROOT (and the continual-learning hook path is quoted); both hooks fail with one line on stderr and leave state untouched when jq or perl is missing, instead of advancing the iteration and dying; README Requirements section; continual-learning documents its Bun requirement
224f21f #444 capture-response.sh prints a promise only on an explicit <promise>...</promise> match, so an untagged reply equal to the promise word no longer ends the loop; tests/capture-response.test.sh
f7e830e #777 both hooks keep a missing frontmatter key as an empty value (`{ grep ...
cc859a8 #658 both hooks read the frontmatter only up to its first closing ---, the stop hook feeds the body back verbatim, and iteration: is rewritten inside the frontmatter only, so --- rules and iteration: lines in the prompt survive; tests/test_ralph_prompt.py. Applied on top of #777, keeping its { grep ... || true; } reads

The only conflicts between #620, #444 and #777 are in adjacent comment lines; #658 changes the same FRONTMATTER= lines as #777, resolved by keeping #777's missing-key handling and #658's awk read. #777's first version also carried the #444 change; that half was removed from #777 today in favour of #444.

Checked on the combined branch

deanrie and others added 5 commits October 27, 2026 12:40
…ontinual-learning hook path

(cherry picked from commit 0cb8152)
…lently breaking the loop

Both hooks hard-depend on jq (and capture-response on perl), but neither
checks for them and the README never mentions them. jq is not installed
by default on macOS or most Linux distributions, so a fresh install dies
on the first turn: the stop hook increments the iteration counter, then
hits "jq: command not found" (exit 127) and never emits a followup, so
the loop just ends. capture-response fails the same way before it can
detect a promise.

- stop-hook.sh: check for jq before touching the state file; print a
  clear line to stderr and exit 0 without advancing the iteration
- capture-response.sh: same for jq and perl
- guards run only when a loop is active, so unrelated projects see no
  noise
- README: Requirements section (bash, jq, perl) with install hints
- tests/prerequisites.test.sh: runs the hooks with a PATH that lacks the
  tool and checks message, exit code, untouched state, no done flag; all
  13 checks pass on this branch and 6 fail against the unguarded hooks
- bump 1.0.0 -> 1.0.1

(cherry picked from commit 7cc76e2)
hooks.json runs the stop hook with `bun run` and the script imports
stdin from the "bun" module, but the README never says Bun is needed.
Without it every stop event fails with "bun: command not found" (exit
127) and the learning cadence silently never fires. Add a Requirements
section with install hints and bump to 1.0.1.

(cherry picked from commit 1fc8491)
capture-response.sh extracted the completion promise with `perl -pe`, which
prints the pattern space even when the `<promise>...</promise>` substitution
does not match. An untagged response was therefore returned as PROMISE_TEXT
after whitespace normalization, so a response whose plain text equalled the
configured completion promise created the done flag and ended the loop without
the required tag (closes cursor#282).

Switch to `perl -ne` and print only after an explicit tag match, and add a
standalone test script covering tagged, whitespace-padded, untagged, mismatched
and unclosed cases. The new test fails on the previous hook and passes on this
one.
grep exits 1 when a key is absent from the state file frontmatter, and
under set -e that ended both hooks silently: stop-hook.sh before it
could report a corrupted file or emit the followup_message,
capture-response.sh before it could check the promise. '|| true' keeps
a missing key as an empty value, which the checks below already handle.

The tagged-promise half of cursor#777 is the same change as cursor#444 and is
carried here by that commit instead.
Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
(cherry picked from commit af939bb)
@deanrie deanrie changed the title ralph-loop: three open hook fixes in one branch (#620, #444, #777) ralph-loop: four open hook fixes in one branch (#620, #444, #777, #658) Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants