From 4e932fbef22f48bebed57d9d37da6f9fc8a070b0 Mon Sep 17 00:00:00 2001 From: Matt Pua Date: Tue, 28 Jul 2026 13:58:24 -0400 Subject: [PATCH 1/5] fix: include PR titles in generated task names Generated-By: PostHog Code Task-Id: 0c226c8d-1b4d-4527-8d8c-2c0819279f10 --- .../sessions/titleGeneratorService.test.ts | 20 +++++++++++++++++++ .../src/sessions/titleGeneratorService.ts | 2 ++ 2 files changed, 22 insertions(+) diff --git a/packages/core/src/sessions/titleGeneratorService.test.ts b/packages/core/src/sessions/titleGeneratorService.test.ts index 956fd897ac..5252680a94 100644 --- a/packages/core/src/sessions/titleGeneratorService.test.ts +++ b/packages/core/src/sessions/titleGeneratorService.test.ts @@ -220,6 +220,26 @@ describe("generateTitleAndSummary", () => { expect(result?.title).toBe("Fix login bug"); }); + it("instructs the model to include existing GitHub PR titles", async () => { + prompt.mockResolvedValue({ + content: + "TITLE: Review PR #123: Fix login redirect\nSUMMARY: Reviewing the existing pull request.", + }); + + await makeService().generateTitleAndSummary( + '', + ); + + expect(prompt).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + system: expect.stringContaining( + "the generated TITLE MUST include both the PR number and the PR title verbatim", + ), + }), + ); + }); + it("returns null on error", async () => { prompt.mockRejectedValue(new Error("network error")); const result = await makeService().generateTitleAndSummary("some content"); diff --git a/packages/core/src/sessions/titleGeneratorService.ts b/packages/core/src/sessions/titleGeneratorService.ts index 537317fb02..67a66f3043 100644 --- a/packages/core/src/sessions/titleGeneratorService.ts +++ b/packages/core/src/sessions/titleGeneratorService.ts @@ -40,6 +40,7 @@ Title rules: - Remove: the, this, my, a, an - If possible, start with action verbs (Fix, Implement, Analyze, Debug, Update, Research, Review) - Keep exact: technical terms, numbers, filenames, HTTP codes, PR numbers +- GitHub PR rule: If the content contains a with a non-empty title, the generated TITLE MUST include both the PR number and the PR title verbatim. This rule overrides the 6-word title limit. Never replace the PR title with a generic phrase. Before responding, verify that both values appear in TITLE. - Never assume tech stack - Only output "Untitled" if the input is completely null/missing, not just unclear - If the input is a URL (e.g. a GitHub issue link, PR link, or any web URL), generate a title based on what you can infer from the URL structure (repo name, issue/PR number, etc.). Never say you cannot access URLs or ask the user for more information. @@ -58,6 +59,7 @@ Title examples: - "Update user documentation for new API endpoints" → Update API documentation - "Research competitor pricing strategies for our product" → Research competitor pricing - "Review pull request #123" → Review pull request #123 +- "" → Review PR #123: Fix login redirect - "debug 500 errors in production" → Debug production 500 errors - "why is the payment flow failing" → Analyze payment flow failure - "So how about that weather huh" → Weather chat From 21923d19d72a2dd2814bea1c98434f0ea4043658 Mon Sep 17 00:00:00 2001 From: Rafael Audibert <32079912+rafaeelaudibert@users.noreply.github.com> Date: Tue, 28 Jul 2026 15:11:40 -0300 Subject: [PATCH 2/5] feat(inbox): bulk-remove yourself as a suggested reviewer Adds a "Remove me as reviewer" action to the inbox bulk-selection toolbar so you can drop yourself as a suggested reviewer across many reports at once, instead of opening each report and removing yourself one at a time. The action reuses the existing per-item bulk fan-out (Promise.allSettled with partial-failure tolerance): per selected report it fetches the latest suggested_reviewers artefact, filters out the current user's entry, and writes the remaining list back. Eligibility is driven by the server-annotated is_suggested_reviewer flag so the button disables when no selected report lists you. Fires one INBOX_REPORT_ACTION (remove_suggested_reviewer) per succeeded report. Generated-By: PostHog Code Task-Id: 869023f3-9853-4f11-a433-6ea896c1c32f --- packages/core/src/inbox/engagement.test.ts | 13 ++ packages/core/src/inbox/engagement.ts | 7 +- .../components/InboxBulkSelectionBar.tsx | 19 +++ .../inbox/hooks/useInboxBulkActions.ts | 123 +++++++++++++++++- 4 files changed, 156 insertions(+), 6 deletions(-) diff --git a/packages/core/src/inbox/engagement.test.ts b/packages/core/src/inbox/engagement.test.ts index 4256dced8f..f880ace30c 100644 --- a/packages/core/src/inbox/engagement.test.ts +++ b/packages/core/src/inbox/engagement.test.ts @@ -65,6 +65,19 @@ describe("buildBulkActionEvents", () => { expect(events.every((e) => e.action_type === "delete")).toBe(true); }); + it("passes through the remove-suggested-reviewer action type", () => { + const events = buildBulkActionEvents({ + reports: [fakeReport({ id: "a" }), fakeReport({ id: "b" })], + actionType: "remove_suggested_reviewer", + surface: "toolbar", + }); + + expect( + events.every((e) => e.action_type === "remove_suggested_reviewer"), + ).toBe(true); + expect(events.every((e) => e.dismissal_reason === undefined)).toBe(true); + }); + it("attaches dismissal reason/note only for dismiss, truncating the note", () => { const longNote = "x".repeat(600); const [dismissed] = buildBulkActionEvents({ diff --git a/packages/core/src/inbox/engagement.ts b/packages/core/src/inbox/engagement.ts index bb31915e35..dc4428ddbb 100644 --- a/packages/core/src/inbox/engagement.ts +++ b/packages/core/src/inbox/engagement.ts @@ -123,7 +123,7 @@ export function resolveActionProperties( /** Bulk-capable report actions fired from the selection toolbar / dismiss flows. */ export type InboxBulkActionType = Extract< InboxReportActionProperties["action_type"], - "dismiss" | "snooze" | "delete" | "reingest" + "dismiss" | "snooze" | "delete" | "reingest" | "remove_suggested_reviewer" >; export interface BuildBulkActionEventsInput { @@ -137,8 +137,9 @@ export interface BuildBulkActionEventsInput { /** * Build `INBOX_REPORT_ACTION` payloads for a bulk (or single-report) dismiss / - * snooze / delete / reingest. Pure so it can be unit-tested and reused across - * the toolbar, the per-row dismiss action, and detail-screen dismiss. + * snooze / delete / reingest / remove-suggested-reviewer. Pure so it can be + * unit-tested and reused across the toolbar, the per-row dismiss action, and + * detail-screen dismiss. * * `is_bulk` / `bulk_size` carry the grouping; `rank` / `list_size` are left at 0 * because these flows act on a selection, not a positional list slot. diff --git a/packages/ui/src/features/inbox/components/InboxBulkSelectionBar.tsx b/packages/ui/src/features/inbox/components/InboxBulkSelectionBar.tsx index 263b2b5d4b..9a6e96e28b 100644 --- a/packages/ui/src/features/inbox/components/InboxBulkSelectionBar.tsx +++ b/packages/ui/src/features/inbox/components/InboxBulkSelectionBar.tsx @@ -3,6 +3,7 @@ import { EyeSlashIcon, PauseIcon, TrashIcon, + UserMinusIcon, XIcon, } from "@phosphor-icons/react"; import { isDismissalReasonSnooze } from "@posthog/shared/dismissalReasons"; @@ -158,6 +159,24 @@ export function InboxBulkSelectionBar({ Reingest + +