What happened
On PR #799, the review agent and fix agent entered a feedback loop that ran 11+ full iterations across May 12-13. The sequence: review agent submits CHANGES_REQUESTED (flagging branch refs in workflow uses: directives) -> fix agent dispatched via dispatch-fix-bot on pull_request_review event -> fix agent pushes a commit -> pull_request_target/synchronize fires -> review agent dispatched again -> same finding flagged -> loop repeats. The fix agent could not resolve the branch-ref issue (it's intentional during development), so the loop never self-terminated.
The loop was broken twice by human intervention: ralphbean dismissed the review on May 12, and the fullsend-no-fix label was applied on May 13. Before that, the loop consumed ~36 review workflow runs (27 successful, 2 failed, 6 cancelled, 1 retro), generated 27 orphaned notification comments, and submitted 13 redundant CHANGES_REQUESTED reviews that all flagged the same issue.
Existing proposals #893 (reduce redundant dispatches) and #887 (cancel in-flight reviews) are complementary but do not address the core loop: a fix agent push is a legitimate synchronize event, so neither event filtering nor concurrency cancellation would prevent the next review from dispatching.
What could go better
The review-fix loop needs a circuit breaker. Without one, any review finding that the fix agent cannot resolve will cause an infinite loop, bounded only by human intervention or the fullsend-no-fix label. This is high-confidence based on clear evidence: 11+ identical cycles on a single PR.
The circuit breaker should operate at the dispatch layer (in fullsend.yaml or reusable-dispatch.yml) rather than inside the agents themselves, because the problem is in the dispatch logic, not the agent logic.
Possible approaches (not mutually exclusive):
- Iteration cap: Track how many review-fix cycles have occurred for a given PR (e.g., via a PR label like
fix-attempt-N or a repo variable). After N iterations (e.g., 3), stop dispatching the fix agent and leave a comment asking for human review.
- Fix-result awareness: Have the fix agent report whether it actually changed anything. If the fix agent pushed no meaningful changes (or pushed changes but the same findings persist), do not re-dispatch.
- Duplicate-finding detection: Before dispatching the fix agent, check if the current review's critical findings are identical to the previous review's. If so, the fix agent already failed to resolve them -- escalate to human.
Approach 1 is simplest and most robust. Approach 2 requires fix agent output schema changes. Approach 3 requires cross-run state.
Proposed change
Add a review-fix iteration counter to the dispatch-fix-bot job in .github/workflows/fullsend.yaml (or equivalent in reusable-dispatch.yml for per-repo mode). The counter should:
- On each
dispatch-fix-bot trigger, check how many previous fix dispatches have occurred for this PR (e.g., by counting commits from fullsend-ai-code[bot] on the PR branch, or by checking for a fix-attempt-N label).
- If the count exceeds a threshold (suggest 3), skip the fix dispatch and post a comment: "Review-fix loop detected after N attempts. The following findings could not be auto-resolved: [list]. Requesting human review."
- Optionally apply the
fullsend-no-fix label automatically when the threshold is hit.
This should be implemented in the fullsend-ai/fullsend repo since it's in the reusable workflow layer that all installations share.
Validation criteria
On the next PR where the fix agent cannot resolve a review finding, the loop should terminate after at most 3 review-fix cycles (6 total workflow runs: 3 reviews + 3 fixes) instead of running indefinitely. The PR should receive a human-readable comment explaining which findings could not be auto-resolved. Validate on the next 5 PRs that trigger fix agent runs.
Generated by retro agent from #799
What happened
On PR #799, the review agent and fix agent entered a feedback loop that ran 11+ full iterations across May 12-13. The sequence: review agent submits
CHANGES_REQUESTED(flagging branch refs in workflowuses:directives) -> fix agent dispatched viadispatch-fix-botonpull_request_reviewevent -> fix agent pushes a commit ->pull_request_target/synchronizefires -> review agent dispatched again -> same finding flagged -> loop repeats. The fix agent could not resolve the branch-ref issue (it's intentional during development), so the loop never self-terminated.The loop was broken twice by human intervention: ralphbean dismissed the review on May 12, and the
fullsend-no-fixlabel was applied on May 13. Before that, the loop consumed ~36 review workflow runs (27 successful, 2 failed, 6 cancelled, 1 retro), generated 27 orphaned notification comments, and submitted 13 redundantCHANGES_REQUESTEDreviews that all flagged the same issue.Existing proposals #893 (reduce redundant dispatches) and #887 (cancel in-flight reviews) are complementary but do not address the core loop: a fix agent push is a legitimate
synchronizeevent, so neither event filtering nor concurrency cancellation would prevent the next review from dispatching.What could go better
The review-fix loop needs a circuit breaker. Without one, any review finding that the fix agent cannot resolve will cause an infinite loop, bounded only by human intervention or the
fullsend-no-fixlabel. This is high-confidence based on clear evidence: 11+ identical cycles on a single PR.The circuit breaker should operate at the dispatch layer (in
fullsend.yamlorreusable-dispatch.yml) rather than inside the agents themselves, because the problem is in the dispatch logic, not the agent logic.Possible approaches (not mutually exclusive):
fix-attempt-Nor a repo variable). After N iterations (e.g., 3), stop dispatching the fix agent and leave a comment asking for human review.Approach 1 is simplest and most robust. Approach 2 requires fix agent output schema changes. Approach 3 requires cross-run state.
Proposed change
Add a review-fix iteration counter to the
dispatch-fix-botjob in.github/workflows/fullsend.yaml(or equivalent inreusable-dispatch.ymlfor per-repo mode). The counter should:dispatch-fix-bottrigger, check how many previous fix dispatches have occurred for this PR (e.g., by counting commits fromfullsend-ai-code[bot]on the PR branch, or by checking for afix-attempt-Nlabel).fullsend-no-fixlabel automatically when the threshold is hit.This should be implemented in the fullsend-ai/fullsend repo since it's in the reusable workflow layer that all installations share.
Validation criteria
On the next PR where the fix agent cannot resolve a review finding, the loop should terminate after at most 3 review-fix cycles (6 total workflow runs: 3 reviews + 3 fixes) instead of running indefinitely. The PR should receive a human-readable comment explaining which findings could not be auto-resolved. Validate on the next 5 PRs that trigger fix agent runs.
Generated by retro agent from #799