When a workflow is stuck at review_response_gate and a user adds the forge:retry label, the workflow unpauses but immediately re-pauses in an infinite loop. This is because the retry handler does not clear contested_comments from the state.
Related: This issue compounds #184 — since review_response_gate cannot be unpaused via GitHub PR review events, forge:retry is the only alternative, but it doesn't work either.
Steps to reproduce
- Submit a PR review with changes requested
- Forge analyzes the review, finds contested comments, posts objections on the PR
- Workflow pauses at
review_response_gate
- Add
forge:retry label on the Jira ticket
Expected behavior
The workflow should unpause, clear the contested state, and return to human_review_gate to accept new review input.
Actual behavior
The retry handler unpauses the workflow, but:
review_response_gate is re-invoked and immediately sets is_paused=True again (line 30-34 of implement_review.py)
route_review_response checks is_paused first and returns END — the routing logic that would advance the workflow is never reached
- The workflow is stuck again at the same gate
Worker logs show the loop:
Detected retry signal via forge:retry label for review_response_gate
Retry requested for AISOS-XXXX at review_response_gate (clearing error: none)
Resuming workflow for AISOS-XXXX
Re-invoking workflow from review_response_gate
Review response gate: pausing for AISOS-XXXX
Workflow completed for AISOS-XXXX, final node: review_response_gate, paused: True
Root cause
The retry handler at src/forge/orchestrator/worker.py line 1186-1204 clears revision_requested, feedback_comment, and last_error, but does not clear contested_comments. Without that, review_response_gate has no way to know the previous contested state was resolved, so it re-pauses unconditionally.
Suggested fix
Add contested_comments to the fields cleared by the retry handler when at review_response_gate:
updated_state["contested_comments"] = []
Additionally, consider whether the retry at review_response_gate should set current_node to human_review_gate so the workflow returns to accepting PR review events rather than re-entering the same gate.
When a workflow is stuck at
review_response_gateand a user adds theforge:retrylabel, the workflow unpauses but immediately re-pauses in an infinite loop. This is because the retry handler does not clearcontested_commentsfrom the state.Related: This issue compounds #184 — since
review_response_gatecannot be unpaused via GitHub PR review events,forge:retryis the only alternative, but it doesn't work either.Steps to reproduce
review_response_gateforge:retrylabel on the Jira ticketExpected behavior
The workflow should unpause, clear the contested state, and return to
human_review_gateto accept new review input.Actual behavior
The retry handler unpauses the workflow, but:
review_response_gateis re-invoked and immediately setsis_paused=Trueagain (line 30-34 ofimplement_review.py)route_review_responsechecksis_pausedfirst and returnsEND— the routing logic that would advance the workflow is never reachedWorker logs show the loop:
Root cause
The retry handler at
src/forge/orchestrator/worker.pyline 1186-1204 clearsrevision_requested,feedback_comment, andlast_error, but does not clearcontested_comments. Without that,review_response_gatehas no way to know the previous contested state was resolved, so it re-pauses unconditionally.Suggested fix
Add
contested_commentsto the fields cleared by the retry handler when atreview_response_gate:Additionally, consider whether the retry at
review_response_gateshould setcurrent_nodetohuman_review_gateso the workflow returns to accepting PR review events rather than re-entering the same gate.