From b4b31b9a7bc5aa6def2aa79f39306c7caf81af49 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 3 Nov 2026 10:01:42 -0500 Subject: [PATCH] fix(triage): chain rejected fixes straight into retriage Previously, when FixVerifier classified a candidate fix as rejected, the workflow just swapped the issue to the `triage: fix rejected` label and stopped silently. Since that label is retriageable, the system would only pick up the rejection's feedback on a *second*, separate comment on the issue -- the comment that triggered the rejection was dropped on the floor even though it usually already contains the actionable regression info needed to retriage. Now the rejected branch posts an acknowledgment comment and chains straight into retriage() with the same conversation, so a single comment pointing out a regression in a fix branch is enough to kick off a new triage attempt. --- src/triage/workflow.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/triage/workflow.ts b/src/triage/workflow.ts index 0fe1513..70ea569 100644 --- a/src/triage/workflow.ts +++ b/src/triage/workflow.ts @@ -281,7 +281,9 @@ export class TriageWorkflow extends WorkflowEntrypoint< await this.retriage(step, client, credentials, params, routed), ); case 'verify-fix': - return finish(await this.verifyFix(step, client, params, routed)); + return finish( + await this.verifyFix(step, client, credentials, params, routed), + ); } } @@ -1328,6 +1330,7 @@ export class TriageWorkflow extends WorkflowEntrypoint< private async verifyFix( step: WorkflowStep, client: () => Promise, + credentials: GitHubCredentials, params: TriageWorkflowParams, routed: RoutedIssue, ): Promise { @@ -1426,8 +1429,25 @@ export class TriageWorkflow extends WorkflowEntrypoint< triage.labels.fixPending, triage.labels.fixRejected, ); + await postIssueComment( + api, + params.owner, + params.repo, + params.issueNumber, + `The candidate fix was rejected: ${verdict.reasoning}\n\nRe-evaluating whether the feedback warrants a new triage attempt.`, + ); + }); + + // The comment that rejected the fix already carries whatever new, + // actionable information prompted the rejection — most often a + // concrete regression and a suggested fix, as here. Don't park the + // issue waiting on a second human comment to notice: feed the same + // conversation straight into the retriage judge now that the label + // reflects the rejection. + return this.retriage(step, client, credentials, params, { + ...routed, + issue: { ...issue, currentLabel: triage.labels.fixRejected }, }); - return { outcome: 'fix-rejected' }; } const pullRequest = await step.do(