From d8e4fc73c0e3bbabcc5482b02e18791dbe7994e0 Mon Sep 17 00:00:00 2001 From: Rohit C Prasad Date: Sun, 16 Aug 2026 07:50:02 -0700 Subject: [PATCH] Rail collapses proposed items to one awaiting-approval line The plan gate is the single full rendering of the proposal; no double listing. --- surfaces/gui/e2e/board.spec.ts | 7 ++++++- surfaces/gui/src/components/BoardPanel.tsx | 19 +++++++++++++++---- surfaces/gui/src/styles.css | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) 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 (
{groups.map((group) => ( @@ -61,6 +67,11 @@ export function BoardSection({ board, onExpand }: { board: Board; onExpand: () = ))}
))} + {proposed.length > 0 && ( +
+ {proposed.length} item{proposed.length === 1 ? "" : "s"} awaiting your approval. +
+ )} ); } diff --git a/surfaces/gui/src/styles.css b/surfaces/gui/src/styles.css index 2fce60c2..689055ac 100644 --- a/surfaces/gui/src/styles.css +++ b/surfaces/gui/src/styles.css @@ -1729,3 +1729,4 @@ html[data-platform="linux"] ::-webkit-scrollbar-thumb:hover { background-color: color: var(--accent); font-size: 12px; cursor: pointer; padding: 6px 0; } .plangate-note { font-size: 11.5px; color: var(--faint); } +.board-proposed-note { color: var(--faint); font-size: 12px; padding: 8px 6px 2px; }