@@ -233,9 +233,99 @@ func (e *Engine) reviewPR(ctx context.Context, p iteragent.Provider, tools []ite
233233 return nil
234234 }
235235
236- // Reviewer found issues but didn't say LGTM — block the merge.
237- e .logger .Warn ("PR self-review did not pass — blocking merge" )
238- return fmt .Errorf ("review blocked merge: reviewer did not say LGTM" )
236+ // Reviewer found issues — try to auto-fix them
237+ e .logger .Warn ("PR self-review found issues — attempting auto-fix" )
238+
239+ fixed , fixErr := e .autoFixIssues (ctx , p , tools , systemPrompt , skills , reviewOutput )
240+ if fixErr != nil {
241+ e .logger .Error ("auto-fix failed" , "err" , fixErr )
242+ e .postReviewComment (ctx , "Auto-fix attempt failed: " + fixErr .Error (), false )
243+ return fmt .Errorf ("review blocked merge: %w" , fixErr )
244+ }
245+
246+ if ! fixed {
247+ e .logger .Warn ("auto-fix could not resolve all issues — blocking merge" )
248+ return fmt .Errorf ("review blocked merge: auto-fix could not resolve all issues" )
249+ }
250+
251+ // Re-review after fixes
252+ e .logger .Info ("auto-fix applied — re-reviewing PR" )
253+ return e .reviewPR (ctx , p , tools , systemPrompt , skills )
254+ }
255+
256+ // autoFixIssues attempts to fix issues identified during review.
257+ // Returns true if fixes were applied and tests pass, false otherwise.
258+ func (e * Engine ) autoFixIssues (ctx context.Context , p iteragent.Provider , tools []iteragent.Tool , systemPrompt string , skills * iteragent.SkillSet , reviewOutput string ) (bool , error ) {
259+ e .logger .Info ("starting auto-fix based on review feedback" )
260+
261+ // Build fix prompt with review feedback
262+ fixPrompt := fmt .Sprintf (`The code review identified issues:
263+
264+ %s
265+
266+ Fix these issues in the codebase. Run tests to verify the fixes work.
267+ If you cannot fix an issue, explain why. Only commit if tests pass.` , reviewOutput )
268+
269+ a := e .newAgent (p , tools , systemPrompt , skills )
270+ var fixResult string
271+ for ev := range a .Prompt (ctx , fixPrompt ) {
272+ if e .eventSink != nil {
273+ select {
274+ case e .eventSink <- ev :
275+ default :
276+ }
277+ }
278+ if ev .Type == string (iteragent .EventMessageEnd ) {
279+ fixResult = ev .Content
280+ }
281+ }
282+ a .Finish ()
283+
284+ // Check if any changes were made
285+ status , err := e .runTool (ctx , "bash" , map [string ]interface {}{
286+ "cmd" : "git status --porcelain" ,
287+ })
288+ if err != nil {
289+ return false , fmt .Errorf ("failed to check git status: %w" , err )
290+ }
291+
292+ if strings .TrimSpace (status ) == "" {
293+ e .logger .Info ("no changes made during auto-fix" )
294+ return false , nil
295+ }
296+
297+ // Run tests to verify fixes
298+ e .logger .Info ("running tests to verify auto-fix" )
299+ _ , testErr := e .runTool (ctx , "bash" , map [string ]interface {}{
300+ "cmd" : "go test ./... 2>&1 | head -50" ,
301+ })
302+ if testErr != nil {
303+ e .logger .Warn ("tests failed after auto-fix, reverting changes" )
304+ // Revert failed fixes
305+ e .runTool (ctx , "bash" , map [string ]interface {}{
306+ "cmd" : "git checkout -- ." ,
307+ })
308+ return false , fmt .Errorf ("tests failed after auto-fix" )
309+ }
310+
311+ // Commit the fixes
312+ e .logger .Info ("committing auto-fix changes" )
313+ if _ , err := e .runTool (ctx , "bash" , map [string ]interface {}{
314+ "cmd" : "git add -A && git commit -m 'fix: auto-fix issues from review'" ,
315+ }); err != nil {
316+ return false , fmt .Errorf ("failed to commit auto-fix: %w" , err )
317+ }
318+
319+ // Push fixes to the PR branch
320+ if _ , err := e .runTool (ctx , "bash" , map [string ]interface {}{
321+ "cmd" : fmt .Sprintf ("git push origin %s" , e .branchName ),
322+ }); err != nil {
323+ return false , fmt .Errorf ("failed to push auto-fix: %w" , err )
324+ }
325+
326+ e .logger .Info ("auto-fix applied successfully" )
327+ e .postReviewComment (ctx , fmt .Sprintf ("Auto-fix applied:\n \n %s\n \n Changes committed and pushed." , fixResult ), true )
328+ return true , nil
239329}
240330
241331// postReviewComment posts the reviewer's output as a GitHub PR comment.
0 commit comments