You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(pr-patrol): reduce compute waste with issue-type budgets and timeout abandonment
PR Patrol was burning 90%+ of compute on failed attempts:
- Timeouts (30 min each) didn't count toward abandonment, causing infinite retries
- All issue types got the same 40-turn / 30-min budget regardless of complexity
- No early-exit guidance in prompts, so Claude kept trying unfixable issues
- Reflection used expensive Sonnet model for simple log analysis
Changes:
- Unify failure tracking: timeouts now count toward abandonment (2 failures = abandoned)
- Add per-issue-type budgets: missing-issue-ref gets 5 turns/3 min, ci-failure gets 25/15, etc.
- Add "when to stop early" section to prompts with clear unfixable-scenario detection
- CI failure prompt now explicitly lists human-required checks to skip immediately
- Reflection uses haiku model with 5-min timeout instead of sonnet/30-min
- Include pr-patrol tests in vitest config
- Add computeBudget tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Check CI status: gh pr checks ${num} --repo ${repo}
929
973
- Read the failing check logs to understand the failure
930
-
- Fix the issue (build error, test failure, lint error)
931
-
- Run locally to verify: pnpm build and/or pnpm test
932
-
- Commit and push the fix`);
974
+
- **STOP IMMEDIATELY and report** if ANY of these apply:
975
+
- The check requires a human action (adding a label like \`rules-change-reviewed\`, manual approval, etc.)
976
+
- The failure is in a Vercel deployment or external service (not a code issue)
977
+
- The same check is also failing on the \`main\` branch (pre-existing, not caused by this PR)
978
+
- The failure is a permissions or authentication issue
979
+
- If the failure IS a code issue you can fix: fix it, run locally to verify (pnpm build / pnpm test), commit and push`);
933
980
}
934
981
935
982
if(issues.includes('missing-testplan')){
@@ -979,7 +1026,14 @@ ${issues.join(', ')}
979
1026
- Use git push --force-with-lease (never --force) when pushing rebased branches
980
1027
- Do not modify files unrelated to the fix
981
1028
- Do NOT run /agent-session-start or /agent-session-ready-PR — this is a targeted fix, not a full session
982
-
- Do NOT create new branches — work on the existing PR branch`);
1029
+
- Do NOT create new branches — work on the existing PR branch
1030
+
1031
+
## When to stop early
1032
+
- **If the issue requires human intervention** (adding labels, approvals, external service fixes): output a clear summary of why and stop immediately. Do not attempt workarounds.
1033
+
- **If the issue is pre-existing** (also failing on main, not introduced by this PR): state that and stop.
1034
+
- **If you've tried 2+ approaches and none worked**: stop and summarize what you tried. Do not keep cycling through the same strategies.
1035
+
- **If the fix is "no action needed"** (e.g., no matching issue exists for missing-issue-ref): say so and stop. Not every detected issue requires a code change.
1036
+
- Stopping early with a clear explanation is BETTER than burning through all turns without progress.`);
body: `🤖 **PR Patrol** ran for ${elapsedS}s (${config.maxTurns} max turns, model: ${config.model}).\n\n**Issues detected**: ${pr.issues.join(', ')}\n\n**Result**:\n${summary}`,
1217
+
body: `🤖 **PR Patrol** ran for ${elapsedS}s (${effectiveMaxTurns} max turns, model: ${config.model}).\n\n**Issues detected**: ${pr.issues.join(', ')}\n\n**Result**:\n${summary}`,
1136
1218
},
1137
1219
}).catch(()=>log(' Warning: could not post summary comment'));
1138
1220
}
1139
1221
}elseif(result.hitMaxTurns){
1140
-
constfailCount=recordMaxTurnsFailure(pr.number);
1222
+
constfailCount=recordFailure(pr.number);
1141
1223
outcome='max-turns';
1142
-
reason=`Hit max turns (${config.maxTurns}) — attempt ${failCount}`;
1143
-
log(`⚠ PR #${pr.number} hit max turns after ${elapsedS}s`);
1224
+
reason=`Hit max turns (${effectiveMaxTurns}) — attempt ${failCount}`;
1225
+
log(`⚠ PR #${pr.number} hit max turns after ${elapsedS}s (attempt ${failCount})`);
1144
1226
1145
1227
if(failCount>=2){
1146
-
reason=`Abandoned after ${failCount}max-turns failures`;
1228
+
reason=`Abandoned after ${failCount} failures`;
1147
1229
log(
1148
-
`✗ PR #${pr.number} abandoned after ${failCount}max-turns failures`,
1230
+
`✗ PR #${pr.number} abandoned after ${failCount}consecutive failures`,
0 commit comments