Rail collapses proposed items to one awaiting-approval line

The plan gate is the single full rendering of the proposal; no double listing.
This commit is contained in:
Rohit C Prasad
2026-08-16 07:50:02 -07:00
committed by Rohit P
parent 2ebc5fd7aa
commit d8e4fc73c0
3 changed files with 22 additions and 5 deletions
+6 -1
View File
@@ -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 ({
+15 -4
View File
@@ -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 (
<div className="board-rail" data-testid="board-rail">
{groups.map((group) => (
@@ -61,6 +67,11 @@ export function BoardSection({ board, onExpand }: { board: Board; onExpand: () =
))}
</div>
))}
{proposed.length > 0 && (
<div className="board-proposed-note" data-testid="board-proposed-note">
{proposed.length} item{proposed.length === 1 ? "" : "s"} awaiting your approval.
</div>
)}
</div>
);
}
+1
View File
@@ -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; }