From 60be385145005bc709685dc8ebffdf344c3c62df Mon Sep 17 00:00:00 2001 From: aayank13 Date: Sat, 10 Oct 2026 15:53:28 +0530 Subject: [PATCH] fix: skip the cursor verify reminder when the turn was stopped or errored --- crates/trodden/src/harness/cursor.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/crates/trodden/src/harness/cursor.rs b/crates/trodden/src/harness/cursor.rs index b003c80..c9b6b5f 100644 --- a/crates/trodden/src/harness/cursor.rs +++ b/crates/trodden/src/harness/cursor.rs @@ -57,6 +57,8 @@ struct CursorHookInput { #[serde(default)] loop_count: Option, #[serde(default)] + status: Option, + #[serde(default)] trigger: Option, } @@ -391,8 +393,13 @@ impl Agent for Cursor { observed.push(observer.edit("Edit", path, edit, true)); Moment::ToolDone } + // A turn the user stopped, or one that errored, must not be restarted by a reminder. "stop" => Moment::TurnEnd { - continued: input.loop_count.is_some_and(|count| count > 0), + continued: input.loop_count.is_some_and(|count| count > 0) + || input + .status + .as_deref() + .is_some_and(|status| status != "completed"), }, "preCompact" => { observed.push(observer.compaction(input.trigger.as_deref() != Some("manual"))); @@ -721,6 +728,10 @@ mod tests { ), Some(Moment::TurnEnd { continued: true }) ); + assert_eq!( + Payload::moment(json!({"hook_event_name": "stop", "loop_count": 0})), + Some(Moment::TurnEnd { continued: false }) + ); assert_eq!( Payload::rendered( Moment::TurnEnd { continued: false }, @@ -734,6 +745,21 @@ mod tests { ); } + #[test] + fn stopped_or_failed_turns_are_never_reminded() { + for status in ["aborted", "error"] { + let moment = Payload::moment( + json!({"hook_event_name": "stop", "status": status, "loop_count": 0}), + ) + .expect("event"); + assert_eq!( + Payload::rendered(moment, Reply::Remind("run it")), + None, + "{status}" + ); + } + } + #[test] fn other_events_and_odd_payloads_are_ignored() { assert_eq!(