diff --git a/surfaces/gui/e2e/board.spec.ts b/surfaces/gui/e2e/board.spec.ts index 70a7dbce..1d76099a 100644 --- a/surfaces/gui/e2e/board.spec.ts +++ b/surfaces/gui/e2e/board.spec.ts @@ -35,15 +35,20 @@ test("a decomposition turn raises the plan gate; approving moves items to Approv await gate.getByRole("button", { name: /1 more item/ }).click(); await expect(gate.getByText("Rate-limit audit — public endpoints")).toBeVisible(); - // Blocked renders on top in the rail; proposed items are listed under Proposed. + // Blocked renders on top in the rail; proposed items collapse to ONE line — + // the gate card is the only place the plan renders in full (no double listing). const rail = page.getByTestId("board-rail"); await expect(rail).toBeVisible(); const groups = rail.locator(".board-group"); await expect(groups.first()).toHaveText("Blocked"); + await expect(page.getByTestId("board-proposed-note")).toHaveText("4 items awaiting your approval."); + await expect(rail.getByText("Dependency audit — lockfiles")).toHaveCount(0); await page.getByTestId("plangate-approve").click(); await expect(page.getByTestId("plangate-card")).toHaveCount(0); + await expect(page.getByTestId("board-proposed-note")).toHaveCount(0); await expect(rail).toContainText("Approved"); + await expect(rail.getByText("Dependency audit — lockfiles")).toBeVisible(); }); test("expand opens the overlay board; Esc closes; the user can act on a review item", async ({ diff --git a/surfaces/gui/src/components/BoardPanel.tsx b/surfaces/gui/src/components/BoardPanel.tsx index bafdb72d..c1508029 100644 --- a/surfaces/gui/src/components/BoardPanel.tsx +++ b/surfaces/gui/src/components/BoardPanel.tsx @@ -39,10 +39,16 @@ export function boardSummary(board: Board): string { } export function BoardSection({ board, onExpand }: { board: Board; onExpand: () => void }) { - const groups = GROUPS.map((g) => ({ - ...g, - items: board.items.filter((i) => i.state === g.state), - })).filter((g) => g.items.length > 0); + // Proposed items are the plan gate's content — the rail collapses them to one + // line (mock UX-030 state 1: "4 items awaiting your approval") instead of + // listing the same items twice on screen. + const proposed = board.items.filter((i) => i.state === "proposed"); + const groups = GROUPS.filter((g) => g.state !== "proposed") + .map((g) => ({ + ...g, + items: board.items.filter((i) => i.state === g.state), + })) + .filter((g) => g.items.length > 0); return (