From a7e689b3c35347b529cb9f54c9b9a8575a3dcab6 Mon Sep 17 00:00:00 2001 From: scotttong Date: Fri, 21 Aug 2026 10:28:55 -0700 Subject: [PATCH] feat(ui): rename "Agent mode" to "Auto mode" and show full work-mode labels (#11866) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The task composer and the New Task dialog show a work-mode chip (how the agent will run a task) > - The default mode was labeled "Agent mode", and the New Task dialog chip abbreviated every mode to one word ("Auto", "Plan", "Ask") > - "Agent mode" is confusing because every mode runs an agent, and the abbreviated chip hid what the label means > - This pull request renames the mode to "Auto mode" and makes every mode chip show the full label > - The benefit is a clearer, consistent mode name in every place the user selects a work mode ## Linked Issues or Issue Description No public GitHub issue exists for this change. Description follows the enhancement template: **What existing behavior does this improve?** The work-mode selector chips in the task composer and in the New Task dialog. **Subsystem affected** UI (`ui/src/lib/work-mode-meta.ts`, `ui/src/components/NewIssueDialog.tsx`). **Current behavior** The default work mode is labeled "Agent mode". The New Task dialog chip shows a shortened label ("Auto", "Plan", "Ask") from a separate `shortLabel` field. **Proposed behavior** The default work mode is labeled "Auto mode". Every chip shows the full label ("Auto mode", "Plan mode", "Ask mode"). The `shortLabel` field is removed so no surface can fall back to the short form. **Reason and benefit** "Agent mode" does not describe the behavior — all modes use an agent. "Auto mode" states what the mode does. One label field keeps every surface consistent. **Breaking changes** None. This is a display-string change only. No API, storage, or mode-key changes. ## What Changed - Renamed the `standard` work-mode label from "Agent mode" to "Auto mode" in `ui/src/lib/work-mode-meta.ts`, the single source for all mode chips. - Changed the New Task dialog mode chip to render the full `label` instead of `shortLabel`. - Deleted the `shortLabel` field from `WorkModeMeta` so nothing can silently regress to the short form. - Updated unit tests and fixtures to pin the full labels. ## Verification - Run `pnpm --filter @paperclipai/ui test -- src/lib/work-mode-meta.test.ts src/components/NewIssueDialog.test.tsx src/components/IssueChatThread.test.tsx src/components/task-chat/TaskChatComposer.test.tsx`. All tests pass. The tests assert the labels are exactly "Auto mode", "Plan mode", and "Ask mode". - Manual: start the dev server, open the board, press `c` to open the New Task dialog, and press Cmd+Period to cycle modes. The chip reads "Auto mode", "Plan mode", then "Ask mode". The composer chip on an open task shows the same labels. ## Risks - Low risk. Display strings only. The chip is a few pixels wider in the New Task dialog; no layout overflow was observed in any of the three modes. ## Model Used - Claude Fable 5 (Anthropic, model ID `claude-fable-5`), extended thinking with tool use, run inside a Claude Code agent session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Fable 5 --- tests/e2e/planning-mode-visual-verification.spec.ts | 2 +- ui/src/components/IssueChatThread.test.tsx | 6 +++--- ui/src/components/NewIssueDialog.test.tsx | 9 ++++++--- ui/src/components/NewIssueDialog.tsx | 2 +- ui/src/components/task-chat/TaskChatComposer.test.tsx | 2 +- ui/src/components/task-chat/task-chat-fixtures.ts | 2 +- ui/src/lib/work-mode-meta.test.ts | 8 ++++---- ui/src/lib/work-mode-meta.ts | 8 ++------ 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/tests/e2e/planning-mode-visual-verification.spec.ts b/tests/e2e/planning-mode-visual-verification.spec.ts index 398fe24f0d..47053beb38 100644 --- a/tests/e2e/planning-mode-visual-verification.spec.ts +++ b/tests/e2e/planning-mode-visual-verification.spec.ts @@ -135,7 +135,7 @@ test("captures planning mode UI for desktop and mobile", async ({ page }) => { await page.goto(issuePath); await page.getByTestId("task-chat-composer-mode").click(); - await page.getByRole("menuitem", { name: /Agent mode/ }).click(); + await page.getByRole("menuitem", { name: /Auto mode/ }).click(); await expect(page.getByTestId("task-chat-composer-mode")).toHaveAttribute("data-pending-work-mode", "standard"); await page.screenshot({ path: `${screenshotDir}/desktop-standard-toggle-${timestamp}.png`, diff --git a/ui/src/components/IssueChatThread.test.tsx b/ui/src/components/IssueChatThread.test.tsx index 12a4f931c1..ac548ba055 100644 --- a/ui/src/components/IssueChatThread.test.tsx +++ b/ui/src/components/IssueChatThread.test.tsx @@ -649,13 +649,13 @@ describe("IssueChatThread", () => { ); }); - // The mode chip is always present (mockup rev 5) — neutral "Agent mode" here. + // The mode chip is always present (mockup rev 5) — neutral "Auto mode" here. const chip = container.querySelector( '[data-testid="issue-chat-composer-work-mode-toggle"]', ) as HTMLButtonElement | null; expect(chip).not.toBeNull(); expect(chip?.getAttribute("data-pending-work-mode")).toBe("standard"); - expect(chip?.textContent).toContain("Agent mode"); + expect(chip?.textContent).toContain("Auto mode"); const composer = container.querySelector('[data-testid="issue-chat-composer"]'); expect(composer?.getAttribute("data-pending-work-mode")).toBe("standard"); @@ -743,7 +743,7 @@ describe("IssueChatThread", () => { }); expect(composer?.getAttribute("data-pending-work-mode")).toBe("standard"); - expect(chip?.textContent).toContain("Agent mode"); + expect(chip?.textContent).toContain("Auto mode"); act(() => { root.unmount(); diff --git a/ui/src/components/NewIssueDialog.test.tsx b/ui/src/components/NewIssueDialog.test.tsx index 11c4b6ba69..1d1474351e 100644 --- a/ui/src/components/NewIssueDialog.test.tsx +++ b/ui/src/components/NewIssueDialog.test.tsx @@ -959,6 +959,7 @@ describe("NewIssueDialog", () => { const modeChip = () => container.querySelector("[data-issue-work-mode-chip]"); expect(modeChip()?.getAttribute("data-issue-work-mode-chip")).toBe("standard"); + expect(modeChip()?.textContent).toContain("Auto mode"); await act(async () => { modeChip()?.dispatchEvent(new KeyboardEvent("keydown", { @@ -969,6 +970,7 @@ describe("NewIssueDialog", () => { })); }); expect(modeChip()?.getAttribute("data-issue-work-mode-chip")).toBe("planning"); + expect(modeChip()?.textContent).toContain("Plan mode"); await act(async () => { modeChip()?.dispatchEvent(new KeyboardEvent("keydown", { @@ -979,6 +981,7 @@ describe("NewIssueDialog", () => { })); }); expect(modeChip()?.getAttribute("data-issue-work-mode-chip")).toBe("ask"); + expect(modeChip()?.textContent).toContain("Ask mode"); await act(async () => { modeChip()?.dispatchEvent(new KeyboardEvent("keydown", { @@ -1417,13 +1420,13 @@ describe("NewIssueDialog", () => { return button?.querySelector("svg")?.getAttribute("class") ?? ""; } - it("uses agent-mode labels and brand status hues by default", async () => { + it("uses auto-mode labels and brand status hues by default", async () => { const { root } = renderDialog(container); await waitForAssertion(() => { - expect(workModeOption("standard")?.textContent).toContain("Agent mode"); + expect(workModeOption("standard")?.textContent).toContain("Auto mode"); }); - expect(workModeOption("standard")?.textContent).toContain("Agent mode"); + expect(workModeOption("standard")?.textContent).toContain("Auto mode"); expect(workModeOption("ask")?.textContent).toContain("Ask mode"); expect(workModeOption("planning")?.textContent).toContain("Plan mode"); diff --git a/ui/src/components/NewIssueDialog.tsx b/ui/src/components/NewIssueDialog.tsx index 82fcaefb7e..f5652ee784 100644 --- a/ui/src/components/NewIssueDialog.tsx +++ b/ui/src/components/NewIssueDialog.tsx @@ -2239,7 +2239,7 @@ export function NewIssueDialog() { )} > - {currentWorkMode.shortLabel} + {currentWorkMode.label} diff --git a/ui/src/components/task-chat/TaskChatComposer.test.tsx b/ui/src/components/task-chat/TaskChatComposer.test.tsx index 8e3155c947..e904a8c45a 100644 --- a/ui/src/components/task-chat/TaskChatComposer.test.tsx +++ b/ui/src/components/task-chat/TaskChatComposer.test.tsx @@ -319,7 +319,7 @@ describe("TaskChatComposer", () => { const chip = container.querySelector('[data-testid="task-chat-composer-mode"]')!; expect(chip.getAttribute("data-pending-work-mode")).toBe("standard"); - expect(chip.textContent).toContain("Agent"); + expect(chip.textContent).toContain("Auto"); pressKey("Tab", { shiftKey: true }); expect(chip.getAttribute("data-pending-work-mode")).toBe("planning"); diff --git a/ui/src/components/task-chat/task-chat-fixtures.ts b/ui/src/components/task-chat/task-chat-fixtures.ts index 36c7b03f30..d50030a451 100644 --- a/ui/src/components/task-chat/task-chat-fixtures.ts +++ b/ui/src/components/task-chat/task-chat-fixtures.ts @@ -39,7 +39,7 @@ export function buildScenario(id: TaskChatStateId): TaskChatScenario { return { surface: "thread", items: [ - { id: "mk-start", kind: "marker", variant: "session_start", label: "Session started", detail: "claude · Agent mode" }, + { id: "mk-start", kind: "marker", variant: "session_start", label: "Session started", detail: "claude · Auto mode" }, ...exchangePrefix(), ], }; diff --git a/ui/src/lib/work-mode-meta.test.ts b/ui/src/lib/work-mode-meta.test.ts index bec8a42320..6c3e671822 100644 --- a/ui/src/lib/work-mode-meta.test.ts +++ b/ui/src/lib/work-mode-meta.test.ts @@ -3,19 +3,19 @@ import { describe, expect, it } from "vitest"; import { nextWorkMode, titleForPendingWorkMode, workModeMetaList } from "./work-mode-meta"; describe("work mode metadata", () => { - it("orders issue work modes as agent, planning, then ask", () => { + it("orders issue work modes as auto, planning, then ask", () => { expect(workModeMetaList().map((mode) => mode.value)).toEqual(["standard", "planning", "ask"]); - expect(workModeMetaList().map((mode) => mode.shortLabel)).toEqual(["Agent", "Plan", "Ask"]); + expect(workModeMetaList().map((mode) => mode.label)).toEqual(["Auto mode", "Plan mode", "Ask mode"]); }); - it("cycles issue work modes as agent, planning, ask, then agent", () => { + it("cycles issue work modes as auto, planning, ask, then auto", () => { expect(nextWorkMode("standard")).toBe("planning"); expect(nextWorkMode("planning")).toBe("ask"); expect(nextWorkMode("ask")).toBe("standard"); }); it("uses graduated tooltip copy", () => { - expect(titleForPendingWorkMode("standard")).toBe("Agent mode for this submission. Click to change."); + expect(titleForPendingWorkMode("standard")).toBe("Auto mode for this submission. Click to change."); expect(titleForPendingWorkMode("planning")).toBe("Plan mode is on for this submission. Click to change."); }); }); diff --git a/ui/src/lib/work-mode-meta.ts b/ui/src/lib/work-mode-meta.ts index 19a8404d39..3a40a07b58 100644 --- a/ui/src/lib/work-mode-meta.ts +++ b/ui/src/lib/work-mode-meta.ts @@ -6,7 +6,6 @@ export type WorkModeTone = "neutral" | "ask" | "planning"; export interface WorkModeMeta { value: IssueWorkMode; label: string; - shortLabel: string; icon: LucideIcon; tone: WorkModeTone; classes: { @@ -46,8 +45,7 @@ export function workModeMetaList(): WorkModeMeta[] { return [ { value: "standard", - label: "Agent mode", - shortLabel: "Agent", + label: "Auto mode", icon: Hammer, tone: "neutral", classes: STANDARD_CLASSES, @@ -55,7 +53,6 @@ export function workModeMetaList(): WorkModeMeta[] { { value: "planning", label: "Plan mode", - shortLabel: "Plan", icon: ClipboardList, tone: "planning", classes: PLANNING_CLASSES, @@ -63,7 +60,6 @@ export function workModeMetaList(): WorkModeMeta[] { { value: "ask", label: "Ask mode", - shortLabel: "Ask", icon: MessageCircleQuestion, tone: "ask", classes: ASK_CLASSES, @@ -89,5 +85,5 @@ export function titleForPendingWorkMode(mode: IssueWorkMode): string { if (mode === "planning") { return "Plan mode is on for this submission. Click to change."; } - return "Agent mode for this submission. Click to change."; + return "Auto mode for this submission. Click to change."; }