diff --git a/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx b/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx index ac1d9a570..1403a7474 100644 --- a/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx +++ b/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx @@ -118,6 +118,8 @@ describe("global board first launch", () => { expect(screen.getByText("Describe a task")).toBeInTheDocument(); expect(screen.getByText("Ready to merge")).toBeInTheDocument(); expect(columnCount()).toBe(0); + // The welcome carries its own orientation — no dangling "Board" header. + expect(screen.queryByText("Board")).not.toBeInTheDocument(); }); it("opens the native folder picker from the welcome CTA", async () => { @@ -154,7 +156,7 @@ describe("project board with no sessions", () => { respondWith([project], []); renderBoard(); - expect(await screen.findByText("No sessions yet")).toBeInTheDocument(); + expect(await screen.findByText("No worker sessions yet")).toBeInTheDocument(); // Board header + empty state each offer the pair; the orchestrator is primary in both. expect(screen.getAllByRole("button", { name: "Spawn Orchestrator" }).length).toBeGreaterThan(0); expect(screen.getAllByRole("button", { name: "New task" }).length).toBeGreaterThan(0); @@ -167,7 +169,7 @@ describe("project board with no sessions", () => { spawnOrchestratorMock.mockRejectedValue(new Error("branch is already checked out in another worktree")); renderBoard(); - await screen.findByText("No sessions yet"); + await screen.findByText("No worker sessions yet"); const [spawnButton] = screen.getAllByRole("button", { name: "Spawn Orchestrator" }); await userEvent.click(spawnButton); @@ -229,7 +231,7 @@ describe("project board with no sessions", () => { , ); - await screen.findByText("No sessions yet"); + await screen.findByText("No worker sessions yet"); await waitFor(() => expect(useUiStore.getState().orchestratorStartupErrors["proj-1"]).toBeUndefined()); expect(screen.queryByText(/Project added, but orchestrator did not start/)).not.toBeInTheDocument(); }); @@ -244,7 +246,7 @@ describe("project board with no sessions", () => { ); renderBoard(); - await screen.findByText("No sessions yet"); + await screen.findByText("No worker sessions yet"); await waitFor(() => expect(useUiStore.getState().orchestratorStartupErrors["proj-1"]).toBeUndefined()); expect(screen.queryByText(/Project added, but orchestrator did not start/)).not.toBeInTheDocument(); }); @@ -255,7 +257,7 @@ describe("project board with no sessions", () => { spawnOrchestratorMock.mockRejectedValue(new Error("branch is already checked out in another worktree")); const { rerender } = renderBoard(); - await screen.findByText("No sessions yet"); + await screen.findByText("No worker sessions yet"); const [spawnButton] = screen.getAllByRole("button", { name: "Spawn Orchestrator" }); await userEvent.click(spawnButton); await screen.findByText(/branch is already checked out/); @@ -267,7 +269,7 @@ describe("project board with no sessions", () => { , ); - await screen.findByText("No sessions yet"); + await screen.findByText("No worker sessions yet"); expect(screen.queryByText(/branch is already checked out/)).not.toBeInTheDocument(); }); @@ -276,7 +278,7 @@ describe("project board with no sessions", () => { renderBoard(); expect(await screen.findByText("fix the bug")).toBeInTheDocument(); - expect(screen.queryByText("No sessions yet")).not.toBeInTheDocument(); + expect(screen.queryByText("No worker sessions yet")).not.toBeInTheDocument(); expect(columnCount()).toBe(4); }); }); diff --git a/frontend/src/renderer/components/BoardEmptyState.tsx b/frontend/src/renderer/components/BoardEmptyState.tsx index adf4a9263..e339844af 100644 --- a/frontend/src/renderer/components/BoardEmptyState.tsx +++ b/frontend/src/renderer/components/BoardEmptyState.tsx @@ -29,19 +29,19 @@ export function BoardWelcome() { Welcome to Agent Orchestrator

- Point it at a git repository and delegate. Agents do the work on isolated branches; you review and merge the - PRs from this board. + Add a git repository, describe the work, and AO coordinates agent sessions on isolated branches. This kanban + board tracks each session from work through review to merge.

    - Pick a local git repository and choose which agents run it. + Choose a local git repository and select the agents AO should use. - The orchestrator plans the work and spawns worker sessions, each on its own branch. + Tell the orchestrator what you want done; it creates worker sessions on isolated branches. - Sessions move across this board as they progress: + Follow each session from work to review to merge readiness: {FLOW_LEGEND.map((zone, index) => ( @@ -123,7 +123,7 @@ export function ProjectBoardEmpty({ return (
    -

    No sessions yet

    +

    No worker sessions yet

    Describe a task and the orchestrator plans it, spawns worker sessions, and tracks them here from work to merge. diff --git a/frontend/src/renderer/components/SessionsBoard.tsx b/frontend/src/renderer/components/SessionsBoard.tsx index 451666da7..cb6148f36 100644 --- a/frontend/src/renderer/components/SessionsBoard.tsx +++ b/frontend/src/renderer/components/SessionsBoard.tsx @@ -225,11 +225,16 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) { return (

    - + {/* The first-launch welcome carries its own orientation; a "Board" + header above it would describe a board that isn't rendered + (review feedback on #2432). */} + {!showWelcome && ( + + )}
    {projectId && health.state !== "ok" ? (