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
9 changes: 9 additions & 0 deletions packages/core/src/inbox/reportFiltering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ export const INBOX_PIPELINE_STATUS_FILTER =
*/
export const INBOX_DISMISSED_STATUS_FILTER = "suppressed";

/**
* Status filter for the Pull requests tab's list and count. Only `ready` PRs —
* a Responder draft awaiting review — are surfaced; PRs that have already been
* merged/closed (`resolved`) or are still running drop off so the tab and its
* count reflect only actionable work the user can act on. Keeps the count
* honest about what the list actually shows.
*/
export const INBOX_PULL_REQUEST_STATUS_FILTER = "ready";

/** Polling interval for inbox queries while the Electron window is focused. */
export const INBOX_REFETCH_INTERVAL_MS = 3000;

Expand Down
44 changes: 41 additions & 3 deletions packages/core/src/inbox/reportMembership.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,44 @@ describe("inbox scope", () => {

describe("tabFilters", () => {
describe("isPullRequestReport", () => {
it("returns true when implementation_pr_url is set", () => {
it("returns true when a ready report has an implementation PR", () => {
expect(
isPullRequestReport(
fakeReport({ implementation_pr_url: "https://gh/p/1" }),
fakeReport({
status: "ready",
implementation_pr_url: "https://gh/p/1",
}),
),
).toBe(true);
});

it("returns false when implementation_pr_url is null", () => {
expect(
isPullRequestReport(fakeReport({ implementation_pr_url: null })),
isPullRequestReport(
fakeReport({ status: "ready", implementation_pr_url: null }),
),
).toBe(false);
});

it("returns false for a PR whose report is no longer ready", () => {
expect(
isPullRequestReport(
fakeReport({
status: "candidate",
implementation_pr_url: "https://gh/p/1",
}),
),
).toBe(false);
});

it("returns false for a still-running PR", () => {
expect(
isPullRequestReport(
fakeReport({
status: "in_progress",
implementation_pr_url: "https://gh/p/1",
}),
),
).toBe(false);
});
Comment thread
Twixes marked this conversation as resolved.

Expand Down Expand Up @@ -171,6 +198,17 @@ describe("tabFilters", () => {
).toBe(false);
});

it("excludes any PR-bearing report rather than surfacing it as a Report", () => {
expect(
isReportTabReport(
fakeReport({
status: "candidate",
implementation_pr_url: "https://gh/p/1",
}),
),
).toBe(false);
});

it("excludes in-progress reports", () => {
expect(isReportTabReport(fakeReport({ status: "in_progress" }))).toBe(
false,
Expand Down
14 changes: 11 additions & 3 deletions packages/core/src/inbox/reportMembership.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,14 @@ export function isInboxDetailPath(pathname: string): boolean {
return INBOX_DETAIL_PATH_RE.test(pathname);
}

/** PR tab membership: Responder shipped a draft PR and the report is still in-inbox. */
/**
* PR tab membership: Responder shipped a draft PR and it is `ready` for review.
* PRs that have already been merged/closed (`resolved`) or are still running
* are excluded so the tab — and its count — only show actionable PRs, matching
* the PostHog Cloud inbox.
*/
export function isPullRequestReport(report: SignalReport): boolean {
return !!report.implementation_pr_url && !isExcludedFromInbox(report);
return report.status === "ready" && !!report.implementation_pr_url;
}

// ── Runs-tab partitioning ─────────────────────────────────────────────────
Expand Down Expand Up @@ -217,7 +222,10 @@ export function orderedRunsTabReports(reports: SignalReport[]): SignalReport[] {
export function isReportTabReport(report: SignalReport): boolean {
if (isExcludedFromInbox(report)) return false;
if (report.status === "failed") return false; // failed runs live in the Runs tab only
if (isPullRequestReport(report)) return false;
// Any report carrying a PR belongs to the Pull requests tab, even once it has
// been merged/closed (`resolved`) — those just drop out of the inbox here
// rather than reappearing as a Report.
if (report.implementation_pr_url) return false;
if (isAgentRunReport(report)) return false;
return true;
}
Expand Down
9 changes: 7 additions & 2 deletions packages/ui/src/features/inbox/hooks/useInboxAllReports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
buildSuggestedReviewerFilterParam,
filterReportsBySearch,
INBOX_PIPELINE_STATUS_FILTER,
INBOX_PULL_REQUEST_STATUS_FILTER,
INBOX_REFETCH_INTERVAL_MS,
} from "@posthog/core/inbox/reportFiltering";
import {
Expand Down Expand Up @@ -80,7 +81,11 @@ export function useInboxAllReports(options?: {

const query = useInboxReportsInfinite(
{
status: INBOX_PIPELINE_STATUS_FILTER,
// The Pull requests tab shows only `ready` PRs (active review work),
// matching its count query and the PostHog Cloud inbox.
status: pullRequestsOnly
? INBOX_PULL_REQUEST_STATUS_FILTER
: INBOX_PIPELINE_STATUS_FILTER,
has_implementation_pr: pullRequestsOnly ? true : undefined,
ordering: buildSignalReportListOrdering(sortField, sortDirection),
source_product:
Expand Down Expand Up @@ -110,7 +115,7 @@ export function useInboxAllReports(options?: {
// returns the real total regardless of page size.
const pullRequestCountQuery = useInboxReports(
{
status: INBOX_PIPELINE_STATUS_FILTER,
status: INBOX_PULL_REQUEST_STATUS_FILTER,
has_implementation_pr: true,
// Mirror the list query's active filters so the badge matches the tab
// body. These are empty when `ignoreFilters` is set (sidebar usage), so
Expand Down
Loading