feat(ui): rename "Agent mode" to "Auto mode" and show full work-mode labels (#11866)
## 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 <noreply@anthropic.com>
This commit is contained in:
parent
38d8f37172
commit
a7e689b3c3
|
|
@ -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`,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -2239,7 +2239,7 @@ export function NewIssueDialog() {
|
|||
)}
|
||||
>
|
||||
<CurrentWorkModeIcon className="h-3 w-3" />
|
||||
{currentWorkMode.shortLabel}
|
||||
{currentWorkMode.label}
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-36 p-1" align="start">
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ describe("TaskChatComposer", () => {
|
|||
|
||||
const chip = container.querySelector<HTMLButtonElement>('[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");
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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.";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue