fix(compound-engineering): clear artifact project scope drift

This commit is contained in:
Phil Larson
2026-06-30 22:03:41 -07:00
parent d58ba268c5
commit 228554d125
4 changed files with 15 additions and 4 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Prevent Compound Engineering artifacts from showing stale project files after project switches.
category: fix
dev: Clears cached artifact discovery on project changes and opens CE artifacts through the project workspace.

View File

@@ -223,7 +223,7 @@ function ArtifactRow({
type="button" type="button"
className="ce-artifact-open" className="ce-artifact-open"
data-testid="ce-artifact-open" data-testid="ce-artifact-open"
onClick={() => openFile?.(entry.path)} onClick={() => openFile?.(entry.path, { workspace: "project" })}
> >
Open Open
</button> </button>

View File

@@ -3,7 +3,7 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import type { DiscoveryResult } from "../../artifacts/discovery.js"; import type { DiscoveryResult } from "../../artifacts/discovery.js";
// Mock the network layer so the view renders from seeded discovery results. // Mock the network layer so the view renders from seeded discovery results.
const listArtifacts = vi.fn(async (): Promise<DiscoveryResult> => { const listArtifacts = vi.fn(async (_projectId?: string): Promise<DiscoveryResult> => {
throw new Error("listArtifacts mock not configured"); throw new Error("listArtifacts mock not configured");
}); });
const listSessions = vi.fn(async (): Promise<CeSession[]> => []); const listSessions = vi.fn(async (): Promise<CeSession[]> => []);
@@ -15,7 +15,7 @@ const getSession = vi.fn(async (_id: string, _projectId?: string): Promise<CeSes
throw new Error("getSession mock not configured"); throw new Error("getSession mock not configured");
}); });
vi.mock("../hooks/api.js", () => ({ vi.mock("../hooks/api.js", () => ({
listArtifacts: () => listArtifacts(), listArtifacts: (projectId?: string) => listArtifacts(projectId),
getArtifactPreviewUrl: (id: string) => `/preview/${id}`, getArtifactPreviewUrl: (id: string) => `/preview/${id}`,
listSessions: () => listSessions(), listSessions: () => listSessions(),
deleteSession: (id: string, projectId?: string) => deleteSession(id, projectId), deleteSession: (id: string, projectId?: string) => deleteSession(id, projectId),
@@ -95,6 +95,7 @@ describe("CompoundEngineeringView", () => {
render(<CompoundEngineeringView projectId="p1" enabledOverride />); render(<CompoundEngineeringView projectId="p1" enabledOverride />);
await screen.findByTestId("ce-empty-state"); await screen.findByTestId("ce-empty-state");
expect(listArtifacts).toHaveBeenCalledWith("p1");
expect(screen.getByText(/Start your compounding pipeline/i)).toBeInTheDocument(); expect(screen.getByText(/Start your compounding pipeline/i)).toBeInTheDocument();
const start = screen.getByTestId("ce-start-action"); const start = screen.getByTestId("ce-start-action");
expect(start).toBeInTheDocument(); expect(start).toBeInTheDocument();
@@ -144,7 +145,7 @@ describe("CompoundEngineeringView", () => {
await screen.findByTestId("ce-artifact"); await screen.findByTestId("ce-artifact");
fireEvent.click(screen.getByTestId("ce-artifact-open")); fireEvent.click(screen.getByTestId("ce-artifact-open"));
expect(openFile).toHaveBeenCalledWith("STRATEGY.md"); expect(openFile).toHaveBeenCalledWith("STRATEGY.md", { workspace: "project" });
}); });
it("renders artifact open button without crashing when openFile is not in context", async () => { it("renders artifact open button without crashing when openFile is not in context", async () => {

View File

@@ -57,6 +57,9 @@ export function useArtifacts({
return; return;
} }
setResult(undefined);
setError(undefined);
const controller = new AbortController(); const controller = new AbortController();
setLoading(true); setLoading(true);
listArtifacts(projectId) listArtifacts(projectId)