diff --git a/frontend/src/renderer/components/SpawnWorkerModal.test.tsx b/frontend/src/renderer/components/SpawnWorkerModal.test.tsx
new file mode 100644
index 000000000..38d6f68f4
--- /dev/null
+++ b/frontend/src/renderer/components/SpawnWorkerModal.test.tsx
@@ -0,0 +1,59 @@
+import { render, screen, waitFor } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { describe, expect, it, vi } from "vitest";
+import { SpawnWorkerModal } from "./SpawnWorkerModal";
+import { TooltipProvider } from "./ui/tooltip";
+import type { WorkspaceSummary } from "../types/workspace";
+
+const workspaces: WorkspaceSummary[] = [{ id: "proj-1", name: "my-app", path: "/p", type: "main", sessions: [] }];
+
+function renderModal(onCreateTask = vi.fn().mockResolvedValue(undefined), onOpenChange = () => undefined) {
+ render(
+
+
+ ,
+ );
+ return onCreateTask;
+}
+
+describe("SpawnWorkerModal", () => {
+ it("requires a non-empty prompt before it can spawn", () => {
+ const onCreateTask = renderModal();
+ expect(screen.getByRole("button", { name: /Spawn worker/ })).toBeDisabled();
+ expect(onCreateTask).not.toHaveBeenCalled();
+ });
+
+ it("keeps the modal open and shows the daemon error when the spawn fails", async () => {
+ const user = userEvent.setup();
+ const onOpenChange = vi.fn();
+ let rejectSpawn!: (reason: Error) => void;
+ const onCreateTask = vi.fn(
+ () =>
+ new Promise((_, reject) => {
+ rejectSpawn = reject;
+ }),
+ );
+ renderModal(onCreateTask, onOpenChange);
+
+ await user.type(await screen.findByLabelText("Prompt"), "do the thing");
+ await user.click(screen.getByRole("button", { name: /Spawn worker/ }));
+ expect(screen.getByRole("button", { name: /Spawn worker/ })).toBeDisabled();
+
+ rejectSpawn(new Error("branch already checked out at ~/Projects/skills"));
+
+ expect(await screen.findByRole("alert")).toHaveTextContent("branch already checked out at ~/Projects/skills");
+ expect(onOpenChange).not.toHaveBeenCalled();
+ expect(screen.getByLabelText("Prompt")).toHaveValue("do the thing");
+
+ onCreateTask.mockResolvedValueOnce(undefined);
+ await user.click(screen.getByRole("button", { name: /Spawn worker/ }));
+ await waitFor(() => expect(onOpenChange).toHaveBeenCalledWith(false));
+ expect(onCreateTask).toHaveBeenCalledTimes(2);
+ });
+});
diff --git a/frontend/src/renderer/components/SpawnWorkerModal.tsx b/frontend/src/renderer/components/SpawnWorkerModal.tsx
index b09e46738..02c7311da 100644
--- a/frontend/src/renderer/components/SpawnWorkerModal.tsx
+++ b/frontend/src/renderer/components/SpawnWorkerModal.tsx
@@ -202,7 +202,11 @@ export function SpawnWorkerModal({
)}
- {error && {error}
}
+ {error && (
+
+ {error}
+
+ )}