diff --git a/frontend/src/components/agents/AgentsArtifactPane.test.tsx b/frontend/src/components/agents/AgentsArtifactPane.test.tsx index 7dfd312c1d..7c8d52107d 100644 --- a/frontend/src/components/agents/AgentsArtifactPane.test.tsx +++ b/frontend/src/components/agents/AgentsArtifactPane.test.tsx @@ -367,7 +367,7 @@ function deferred() { function renderPane( activeTab: AgentArtifactTab = "tasks", - paneWorkspace = workspace(), + paneWorkspace: AgentConversationWorkspace | null = workspace(), onPublishWorkspace = vi.fn(), isPublishingWorkspace = false, paneConversation = null, @@ -629,6 +629,72 @@ describe("AgentsArtifactPane", () => { useUiStore.setState({ activeModal: null, modalContext: undefined }); }); + it("hydrates plan artifacts for an ideation conversation without a workspace link", async () => { + getIdeationSessionMock.mockResolvedValue({ + session: { + id: "session-1", + projectId: "project-1", + title: "Planning session", + titleSource: "auto", + status: "active", + planArtifactId: null, + seedTaskId: null, + parentSessionId: null, + teamMode: null, + teamConfig: null, + createdAt: "2026-04-23T09:00:00Z", + updatedAt: "2026-04-23T09:00:00Z", + archivedAt: null, + convertedAt: null, + verificationStatus: "unverified", + verificationInProgress: false, + gapScore: null, + inheritedPlanArtifactId: null, + sessionPurpose: "general", + sessionFlow: "planning", + acceptanceStatus: null, + }, + proposals: [], + messages: [], + }); + getSessionPlanMock.mockResolvedValue({ + id: "artifact-1", + type: "specification", + name: "Implementation Plan", + content: { + type: "inline", + text: "# Implementation Plan\n\nDo the work.", + }, + metadata: { + createdAt: "2026-04-23T09:00:00Z", + createdBy: "orchestrator", + version: 1, + }, + derivedFrom: [], + bucketId: "prd-library", + planApproval: { + status: "draft", + }, + }); + + renderPane( + "plan", + null, + vi.fn(), + false, + { + ...conversation(), + contextType: "ideation", + contextId: "session-1", + agentMode: "ideation", + }, + ); + + await waitFor(() => expect(getIdeationSessionMock).toHaveBeenCalledWith("session-1")); + await waitFor(() => expect(getSessionPlanMock).toHaveBeenCalledWith("session-1")); + expect(screen.queryByText("No plan yet")).not.toBeInTheDocument(); + }); + it("anchors the active tab border to the bottom edge of the tab bar", async () => { getIdeationSessionMock.mockResolvedValue({ session: { diff --git a/frontend/src/components/agents/AgentsArtifactPane.tsx b/frontend/src/components/agents/AgentsArtifactPane.tsx index 227dad57dd..bfaf60ad13 100644 --- a/frontend/src/components/agents/AgentsArtifactPane.tsx +++ b/frontend/src/components/agents/AgentsArtifactPane.tsx @@ -221,7 +221,8 @@ export const AgentsArtifactPane = memo(function AgentsArtifactPane({ }: AgentsArtifactPaneProps) { const queryClient = useQueryClient(); const canHydrateIdeationArtifacts = Boolean( - focusedIdeationSessionId || + conversation?.contextType === "ideation" || + focusedIdeationSessionId || workspace?.mode === "ideation" || workspace?.mode === "plan" || workspace?.linkedIdeationSessionId ||