Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/agents/definitions/respond-to-review.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ capabilities:
triggers:
- event: scm:pr-review-submitted
label: PR Review Submitted
description: Trigger when a review with changes requested is submitted
description: Trigger when a review with changes requested or comments is submitted
defaultEnabled: true
providers: [github]
contextPipeline: [prContext, prConversation, directoryListing, contextFiles, squint]
Expand Down
6 changes: 3 additions & 3 deletions src/triggers/github/pr-review-submitted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export class PRReviewSubmittedTrigger implements TriggerHandler {
// Only trigger on submitted reviews, not edits or dismissals
if (ctx.payload.action !== 'submitted') return false;

// Only respond to changes_requested reviews — not approved or commented
if (ctx.payload.review.state !== 'changes_requested') return false;
// Respond to changes_requested and commented reviews — not approved
if (ctx.payload.review.state === 'approved') return false;

return true;
}
Expand Down Expand Up @@ -51,7 +51,7 @@ export class PRReviewSubmittedTrigger implements TriggerHandler {
const prNumber = reviewPayload.pull_request.number;
const reviewAuthor = reviewPayload.review.user.login;

// Only respond to changes_requested from the reviewer persona
// Only respond to reviews from the reviewer persona
if (!ctx.personaIdentities) {
logger.warn('No persona identities available, skipping review trigger', { prNumber });
return null;
Expand Down
76 changes: 75 additions & 1 deletion tests/unit/triggers/pr-review-submitted.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('PRReviewSubmittedTrigger', () => {
expect(trigger.matches(ctx)).toBe(true);
});

it('does not match submitted review with commented state', () => {
it('matches submitted review with commented state', () => {
const ctx: TriggerContext = {
project: mockProject,
source: 'github',
Expand All @@ -76,6 +76,25 @@ describe('PRReviewSubmittedTrigger', () => {
}),
};

expect(trigger.matches(ctx)).toBe(true);
});

it('does not match dismissed reviews (action is dismissed, not submitted)', () => {
const ctx: TriggerContext = {
project: mockProject,
source: 'github',
payload: makeReviewPayload({
action: 'dismissed',
review: {
id: 100,
state: 'dismissed',
body: 'Dismissed',
html_url: 'https://github.com/...',
user: { login: 'cascade-reviewer' },
},
}),
};

expect(trigger.matches(ctx)).toBe(false);
});

Expand Down Expand Up @@ -272,5 +291,60 @@ describe('PRReviewSubmittedTrigger', () => {

expect(result?.agentInput.triggerCommentBody).toBe('Review: changes_requested');
});

it('returns respond-to-review result when reviewer persona posts commented review', async () => {
const ctx: TriggerContext = {
project: mockProject,
source: 'github',
payload: makeReviewPayload({
review: {
id: 200,
state: 'commented',
body: 'Left some inline comments',
html_url: 'https://github.com/owner/repo/pull/42#pullrequestreview-200',
user: { login: 'cascade-reviewer' },
},
}),
personaIdentities: mockPersonaIdentities,
};

const result = await trigger.handle(ctx);

expect(result).toEqual({
agentType: 'respond-to-review',
agentInput: {
prNumber: 42,
prBranch: 'feature/test',
repoFullName: 'owner/repo',
triggerCommentId: 200,
triggerCommentBody: 'Left some inline comments',
triggerCommentPath: '',
triggerCommentUrl: 'https://github.com/owner/repo/pull/42#pullrequestreview-200',
},
prNumber: 42,
workItemId: 'abc123',
});
});

it('uses Review: commented fallback when commented review has null body', async () => {
const ctx: TriggerContext = {
project: mockProject,
source: 'github',
payload: makeReviewPayload({
review: {
id: 200,
state: 'commented',
body: null,
html_url: 'https://github.com/owner/repo/pull/42#pullrequestreview-200',
user: { login: 'cascade-reviewer' },
},
}),
personaIdentities: mockPersonaIdentities,
};

const result = await trigger.handle(ctx);

expect(result?.agentInput.triggerCommentBody).toBe('Review: commented');
});
});
});