diff --git a/packages/ui/src/features/inbox/components/InboxReportCard.tsx b/packages/ui/src/features/inbox/components/InboxReportCard.tsx
new file mode 100644
index 000000000..ec051514a
--- /dev/null
+++ b/packages/ui/src/features/inbox/components/InboxReportCard.tsx
@@ -0,0 +1,120 @@
+import {
+ ArrowSquareOut,
+ CaretDown,
+ CaretUp,
+ Tray,
+} from "@phosphor-icons/react";
+import { useInboxReportById } from "@posthog/ui/features/inbox/hooks/useInboxReports";
+import { useInboxReportSelectionStore } from "@posthog/ui/features/inbox/stores/inboxReportSelectionStore";
+import { useInboxSignalsFilterStore } from "@posthog/ui/features/inbox/stores/inboxSignalsFilterStore";
+import { navigateToInbox } from "@posthog/ui/router/navigationBridge";
+import { Box, Flex, Spinner, Text } from "@radix-ui/themes";
+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/packages/ui/src/features/sessions/components/ConversationView.tsx b/packages/ui/src/features/sessions/components/ConversationView.tsx
index 5b1e618cc..54d347bdf 100644
--- a/packages/ui/src/features/sessions/components/ConversationView.tsx
+++ b/packages/ui/src/features/sessions/components/ConversationView.tsx
@@ -213,6 +213,11 @@ export function ConversationView({
? slackThreadUrl
: undefined
}
+ signalReportId={
+ item.id === firstUserMessageId
+ ? (task?.signal_report ?? undefined)
+ : undefined
+ }
/>
);
case "git_action":
@@ -256,7 +261,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/packages/ui/src/features/sessions/components/session-update/UserMessage.tsx b/packages/ui/src/features/sessions/components/session-update/UserMessage.tsx
index db0b50db4..5a950c2e8 100644
--- a/packages/ui/src/features/sessions/components/session-update/UserMessage.tsx
+++ b/packages/ui/src/features/sessions/components/session-update/UserMessage.tsx
@@ -14,6 +14,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Tooltip } from "../../../../primitives/Tooltip";
import { MarkdownRenderer } from "../../../editor/components/MarkdownRenderer";
import { useFeatureFlag } from "../../../feature-flags/useFeatureFlag";
+import { InboxReportCard } from "../../../inbox/components/InboxReportCard";
import { usePanelLayoutStore } from "../../../panels/panelLayoutStore";
import type { UserMessageAttachment } from "../../userMessageTypes";
import { extractChannelContext } from "./channelContext";
@@ -29,6 +30,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;
/** Task the message belongs to — needed to open the context file tab. */
@@ -55,6 +59,7 @@ export const UserMessage = memo(function UserMessage({
content,
timestamp,
sourceUrl,
+ signalReportId,
attachments = [],
animate = true,
taskId,
@@ -208,6 +213,7 @@ export const UserMessage = memo(function UserMessage({
View Slack thread
)}
+ {signalReportId && }
{timestamp != null && (