From 6fa71a28eaca4398247fad835f3989c56abdb395 Mon Sep 17 00:00:00 2001
From: Rafael Audibert <32079912+rafaeelaudibert@users.noreply.github.com>
Date: Tue, 9 Jun 2026 12:30:59 -0700
Subject: [PATCH] feat(inbox): render expandable inbox report card under
initial prompt
When a task is associated with a PostHog inbox report (task.signal_report),
the conversation now renders an expandable report card directly under the
initial prompt, so the report can be read inline instead of navigating away
to the inbox view.
- New InboxReportCard component fetches the report via the existing
useInboxReportById hook (shared query cache, stays in sync). Collapsed
shows title + status badge; expanded shows the researched summary,
priority/actionability badges, and an "Open in inbox" action.
- UserMessage gains an optional signalReportId prop that renders the card
below the message body, mirroring the existing slackThreadUrl pattern.
- ConversationView passes task.signal_report to the first user message only.
Generated-By: PostHog Code
Task-Id: c0568add-708f-41eb-a334-563d52b70afa
---
.../inbox/components/InboxReportCard.tsx | 120 ++++++++++++++++++
.../sessions/components/ConversationView.tsx | 14 +-
.../components/session-update/UserMessage.tsx | 6 +
3 files changed, 139 insertions(+), 1 deletion(-)
create mode 100644 apps/code/src/renderer/features/inbox/components/InboxReportCard.tsx
diff --git a/apps/code/src/renderer/features/inbox/components/InboxReportCard.tsx b/apps/code/src/renderer/features/inbox/components/InboxReportCard.tsx
new file mode 100644
index 000000000..68720a367
--- /dev/null
+++ b/apps/code/src/renderer/features/inbox/components/InboxReportCard.tsx
@@ -0,0 +1,120 @@
+import { useInboxReportById } from "@features/inbox/hooks/useInboxReports";
+import { useInboxReportSelectionStore } from "@features/inbox/stores/inboxReportSelectionStore";
+import { useInboxSignalsFilterStore } from "@features/inbox/stores/inboxSignalsFilterStore";
+import {
+ ArrowSquareOut,
+ CaretDown,
+ CaretUp,
+ Tray,
+} from "@phosphor-icons/react";
+import { Box, Flex, Spinner, Text } from "@radix-ui/themes";
+import { navigateToInbox } from "@renderer/navigationBridge";
+import { useCallback, useState } from "react";
+import { SignalReportActionabilityBadge } from "./utils/SignalReportActionabilityBadge";
+import { SignalReportPriorityBadge } from "./utils/SignalReportPriorityBadge";
+import { SignalReportStatusBadge } from "./utils/SignalReportStatusBadge";
+import { SignalReportSummaryMarkdown } from "./utils/SignalReportSummaryMarkdown";
+
+interface InboxReportCardProps {
+ reportId: string;
+}
+
+/**
+ * Compact, expandable card for the inbox report a task is associated with.
+ * Rendered under the initial prompt so the report can be read inline instead
+ * of navigating away to the inbox view. Reads the report from the same query
+ * cache the inbox uses (`useInboxReportById`), so it stays in sync and an
+ * "Open in inbox" action can reuse the warmed cache for the detail pane.
+ */
+export function InboxReportCard({ reportId }: InboxReportCardProps) {
+ const [expanded, setExpanded] = useState(false);
+ const { data: report, isLoading } = useInboxReportById(reportId, {
+ staleTime: 60_000,
+ });
+
+ const setSelectedReportIds = useInboxReportSelectionStore(
+ (s) => s.setSelectedReportIds,
+ );
+ const resetFilters = useInboxSignalsFilterStore((s) => s.resetFilters);
+
+ const handleOpenInInbox = useCallback(() => {
+ // Reset inbox-local filters first so the report isn't hidden by an active
+ // filter, then navigate and select it (mirrors the deep-link open path).
+ resetFilters();
+ navigateToInbox();
+ setSelectedReportIds([reportId]);
+ }, [reportId, resetFilters, setSelectedReportIds]);
+
+ if (isLoading && !report) {
+ return (
+
+
+
+ Loading inbox report...
+
+
+ );
+ }
+
+ if (!report) return null;
+
+ return (
+
+
+
+ {expanded && (
+
+
+
+ {(report.priority || report.actionability) && (
+
+
+
+
+ )}
+
+
+
+ )}
+
+ );
+}
diff --git a/apps/code/src/renderer/features/sessions/components/ConversationView.tsx b/apps/code/src/renderer/features/sessions/components/ConversationView.tsx
index 2a1d9e994..92e16289b 100644
--- a/apps/code/src/renderer/features/sessions/components/ConversationView.tsx
+++ b/apps/code/src/renderer/features/sessions/components/ConversationView.tsx
@@ -202,6 +202,11 @@ export function ConversationView({
? slackThreadUrl
: undefined
}
+ signalReportId={
+ item.id === firstUserMessageId
+ ? (task?.signal_report ?? undefined)
+ : undefined
+ }
/>
);
case "git_action":
@@ -245,7 +250,14 @@ export function ConversationView({
);
}
},
- [repoPath, taskId, slackThreadUrl, firstUserMessageId, initialItemIds],
+ [
+ repoPath,
+ taskId,
+ slackThreadUrl,
+ firstUserMessageId,
+ initialItemIds,
+ task?.signal_report,
+ ],
);
const getItemKey = useCallback((item: ConversationItem) => item.id, []);
diff --git a/apps/code/src/renderer/features/sessions/components/session-update/UserMessage.tsx b/apps/code/src/renderer/features/sessions/components/session-update/UserMessage.tsx
index 698f9255a..3a5b0a688 100644
--- a/apps/code/src/renderer/features/sessions/components/session-update/UserMessage.tsx
+++ b/apps/code/src/renderer/features/sessions/components/session-update/UserMessage.tsx
@@ -1,5 +1,6 @@
import { Tooltip } from "@components/ui/Tooltip";
import { MarkdownRenderer } from "@features/editor/components/MarkdownRenderer";
+import { InboxReportCard } from "@features/inbox/components/InboxReportCard";
import {
CaretDown,
CaretUp,
@@ -28,6 +29,9 @@ interface UserMessageProps {
content: string;
timestamp?: number;
sourceUrl?: string;
+ /** Inbox report this message's task is associated with — rendered as an
+ * expandable card under the message (first user message only). */
+ signalReportId?: string;
attachments?: UserMessageAttachment[];
animate?: boolean;
}
@@ -52,6 +56,7 @@ export const UserMessage = memo(function UserMessage({
content,
timestamp,
sourceUrl,
+ signalReportId,
attachments = [],
animate = true,
}: UserMessageProps) {
@@ -160,6 +165,7 @@ export const UserMessage = memo(function UserMessage({
View Slack thread
)}
+ {signalReportId && }
{timestamp != null && (