Skip to content

fix(ralph-loop): detect VERIFIED promise in tool_result parts and add verification circuit breaker (fixes #3212)#3447

Closed
MoerAI wants to merge 2 commits intocode-yeongyu:devfrom
MoerAI:fix/ulw-verification-loop
Closed

fix(ralph-loop): detect VERIFIED promise in tool_result parts and add verification circuit breaker (fixes #3212)#3447
MoerAI wants to merge 2 commits intocode-yeongyu:devfrom
MoerAI:fix/ulw-verification-loop

Conversation

@MoerAI
Copy link
Copy Markdown
Contributor

@MoerAI MoerAI commented Apr 15, 2026

Summary

  • Fix Oracle VERIFIED promise detection in tool_result message parts
  • Add MAX_VERIFICATION_ATTEMPTS circuit breaker to prevent infinite verification loops

Problem

The ULW verification loop runs infinitely after Oracle emits <promise>VERIFIED</promise> because:

  1. detectOracleVerificationFromParentSession only scans assistant role messages, missing VERIFIED in tool_result parts delivered via non-assistant messages
  2. detectCompletionInSessionMessages filters to assistant-only messages when searching for the VERIFIED promise, skipping tool_result parts in other message roles
  3. No circuit breaker caps verification retry attempts, allowing up to 100 expensive Oracle calls before the general iteration limit stops the loop

Fix

  1. Relaxed role filtering in detectOracleVerificationFromParentSession to skip only user messages instead of requiring assistant, so VERIFIED evidence in tool_result parts is found regardless of message role
  2. When searching for ULTRAWORK_VERIFICATION_PROMISE, detectCompletionInSessionMessages now scans all non-user messages instead of assistant-only
  3. Added MAX_VERIFICATION_ATTEMPTS = 3 circuit breaker: after 3 failed verification attempts, the loop state is cleared and an error toast notifies the user

Changes

File Change
src/hooks/ralph-loop/pending-verification-handler.ts Skip only user role instead of requiring assistant when scanning for Oracle VERIFIED
src/hooks/ralph-loop/completion-promise-detector.ts Include non-user messages when detecting ULTRAWORK_VERIFICATION_PROMISE
src/hooks/ralph-loop/loop-state-controller.ts Add circuit breaker in restartAfterFailedVerification, reset counter in markVerificationPending
src/hooks/ralph-loop/verification-failure-handler.ts Show error toast when circuit breaker trips
src/hooks/ralph-loop/types.ts Add verification_attempts field to RalphLoopState
src/hooks/ralph-loop/constants.ts Add MAX_VERIFICATION_ATTEMPTS constant

Fixes #3212


Summary by cubic

Fix the infinite ULW verification loop by detecting Oracle VERIFIED in non-assistant tool_result parts and adding a 3-attempt circuit breaker to stop runaway retries (fixes #3212).

  • Bug Fixes
    • Scan all non-user messages when detecting ULTRAWORK_VERIFICATION_PROMISE.
    • Detect VERIFIED evidence in tool_result parts regardless of message role.
    • Add MAX_VERIFICATION_ATTEMPTS = 3; preserve attempt count across pending states, end loop and show error toast when limit is reached.

Written for commit efd6da1. Summary will update on new commits.

@MoerAI
Copy link
Copy Markdown
Contributor Author

MoerAI commented Apr 15, 2026

I have read the CLA Document and I hereby sign the CLA

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 193c8cf5a5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

state.verification_pending = true
state.verification_attempts = 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve verification attempt count across retries

Resetting verification_attempts to 0 when entering verification mode causes the new circuit breaker in restartAfterFailedVerification to never reach MAX_VERIFICATION_ATTEMPTS in normal ULTRAWORK flow. Each failed verification clears verification_pending, and the next completion path calls markVerificationPending again, which wipes the accumulated count before the next failure is recorded. In repeated Oracle-failure scenarios, this leaves the loop effectively unbounded (until general iteration limits), so the intended protection does not activate.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files

Confidence score: 3/5

  • verification_attempts is reset in src/hooks/ralph-loop/loop-state-controller.ts, which can nullify the new circuit breaker and allow repeated retries beyond the intended limit.
  • There is a user-facing risk: src/hooks/ralph-loop/verification-failure-handler.ts can show a misleading “max attempts” toast even when other restart failures occur.
  • Given a high-severity behavioral issue (7/10) that can change retry control, this carries some regression risk and merits extra verification.
  • Pay close attention to src/hooks/ralph-loop/loop-state-controller.ts and src/hooks/ralph-loop/verification-failure-handler.ts - circuit breaker state reset and misleading failure messaging.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/hooks/ralph-loop/loop-state-controller.ts">

<violation number="1" location="src/hooks/ralph-loop/loop-state-controller.ts:129">
P1: Resetting `verification_attempts` here nullifies the new circuit breaker across verification retries.</violation>
</file>

<file name="src/hooks/ralph-loop/verification-failure-handler.ts">

<violation number="1" location="src/hooks/ralph-loop/verification-failure-handler.ts:86">
P2: The failure toast claims the loop ended because maximum attempts were reached, but `restartAfterFailedVerification()` returns `null` for several other restart failures too, so the user-facing diagnosis can be wrong.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/hooks/ralph-loop/loop-state-controller.ts Outdated
await ctx.client.tui?.showToast?.({
body: {
title: "ULTRAWORK LOOP",
message: "Verification failed after maximum attempts. Loop ended.",
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The failure toast claims the loop ended because maximum attempts were reached, but restartAfterFailedVerification() returns null for several other restart failures too, so the user-facing diagnosis can be wrong.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/ralph-loop/verification-failure-handler.ts, line 86:

<comment>The failure toast claims the loop ended because maximum attempts were reached, but `restartAfterFailedVerification()` returns `null` for several other restart failures too, so the user-facing diagnosis can be wrong.</comment>

<file context>
@@ -77,9 +77,17 @@ export async function handleFailedVerification(
+		await ctx.client.tui?.showToast?.({
+			body: {
+				title: "ULTRAWORK LOOP",
+				message: "Verification failed after maximum attempts. Loop ended.",
+				variant: "error",
+				duration: 10000,
</file context>
Suggested change
message: "Verification failed after maximum attempts. Loop ended.",
message: "Verification failed. Loop ended.",
Fix with Cubic

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 2 unresolved issues from previous reviews.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: efd6da188a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +163 to +164
const attempts = (state.verification_attempts ?? 0) + 1
if (attempts >= MAX_VERIFICATION_ATTEMPTS) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Persist verification attempts before checking breaker

restartAfterFailedVerification increments state.verification_attempts, but this value is never serialized in writeState/readState (see src/hooks/ralph-loop/storage.ts), so each retry reloads the state with verification_attempts as undefined and this line recomputes attempts as 1 every time. In repeated Oracle verification failures, MAX_VERIFICATION_ATTEMPTS is therefore never reached and the new circuit breaker does not actually stop the retry loop.

Useful? React with 👍 / 👎.

@MoerAI
Copy link
Copy Markdown
Contributor Author

MoerAI commented Apr 30, 2026

Closing — PR has been open 14+ days with zero maintainer engagement. Happy to reopen or rework if this fix is still wanted.

@MoerAI MoerAI closed this Apr 30, 2026
@MoerAI MoerAI deleted the fix/ulw-verification-loop branch April 30, 2026 10:14
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.

ULW verification loop: infinite loop when Oracle VERIFIED not detected in parent session

1 participant