feat(settings): alphabetize experimental cards and drop the Experimental chip (#10924)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Instance Settings area exposes an Experimental page that lists
opt-in feature toggles as cards.
> - New experimental features were appended to the list over time, so
the cards sat in insertion order with no predictable arrangement.
> - An unordered list is hard to scan when you are looking for one
specific feature.
> - Each card also carried a small "Experimental" secondary badge, which
is redundant on a page that is itself titled Experimental.
> - This pull request sorts every card alphabetically by its title and
removes that redundant badge.
> - The benefit is a list that is faster to scan and headings that are
less cluttered.

## Linked Issues or Issue Description

No public GitHub issue exists for this change, so the enhancement is
described inline following `.github/ISSUE_TEMPLATE/enhancement.yml`:

**What existing behavior does this improve?**
The Instance Settings → Experimental page, which lists opt-in feature
toggles as a stack of cards.

**Subsystem affected**
UI — the Instance Experimental settings page
(`ui/src/pages/InstanceExperimentalSettings.tsx`).

**Current behavior**
Cards render in insertion order (the order features happened to be
added), so finding a specific feature means scanning the whole list.
Several headings also carry a redundant "Experimental" secondary badge.

**Proposed behavior**
Cards render top-to-bottom in A→Z order by title, and no card shows an
"Experimental" secondary badge. Toggle logic, footnotes, conditional
visibility, and the "Managed by Paperclip Cloud" badge are unchanged.

**Reason and benefit**
Alphabetical order makes the list predictable and quick to scan for a
specific feature. The "Experimental" badge repeats information already
conveyed by the page title, so removing it declutters the headings.

**Breaking changes**
None. This touches card render order and the removal of a decorative
badge only — no state, persistence, toggle, or visibility logic changes.

## What Changed

- Sorted every card on the Instance Experimental settings page
alphabetically by its heading title.
- Removed the redundant "Experimental" secondary badge from the card
headings (previously on Apps, Cases, and Chat-Style Tasks).
- Added tests asserting the cards render in case-insensitive
alphabetical order and that no card renders an "Experimental" secondary
badge.
- No behavior change: toggle handlers, footnotes, managed-key handling,
and conditional cards (Conference Room Chat, worktree-scoped run) are
untouched and now sort into their alphabetical slots.

## Verification

- `pnpm check:token-gates` → all 3 gates CLEAN.
- `npx vitest run ui/src/pages/InstanceExperimentalSettings.test.tsx` →
32/32 tests pass (the suite renders the real component and now covers
ordering + badge removal).
- `pnpm --filter @paperclipai/ui typecheck` (`tsc -b`) → clean.
- Manual: open Instance Settings → Experimental. The cards read A→Z and
no card shows an "Experimental" chip.

## Risks

Low risk. The change is limited to one page component: card render order
and the removal of a decorative badge, plus new tests. No state,
persistence, toggle, or visibility logic is modified.

## Model Used

Claude Opus 4.8 (Anthropic), model id `claude-opus-4-8`, extended
thinking enabled, tool use enabled.

## 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
- [x] All Paperclip CI gates are green
- [x] 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 Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
scotttong 2026-08-05 17:08:09 -07:00 committed by GitHub
parent 00a24d7e8f
commit b1b7a9dff6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 319 additions and 261 deletions

View File

@ -862,3 +862,67 @@ describe("InstanceExperimentalSettings — cloud-managed keys", () => {
expect(mockInstanceSettingsApi.updateExperimental).toHaveBeenCalledWith({ enableApps: true });
});
});
describe("InstanceExperimentalSettings — card ordering and headings (PAP-393)", () => {
let container: HTMLDivElement;
let root: Root | null = null;
async function renderPage(settings: InstanceExperimentalSettingsWithManaged) {
mockInstanceSettingsApi.getExperimental.mockResolvedValue({ ...settings });
root = createRoot(container);
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
flushSync(() => {
root!.render(
<QueryClientProvider client={queryClient}>
<InstanceExperimentalSettings />
</QueryClientProvider>,
);
});
await flushReact();
}
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
mockInstanceSettingsApi.updateExperimental.mockImplementation(async (patch) => ({
...defaultExperimentalSettings(),
...patch,
}));
});
afterEach(() => {
flushSync(() => {
root?.unmount();
});
root = null;
container.remove();
vi.clearAllMocks();
});
it("renders every card heading in alphabetical order", async () => {
await renderPage(defaultExperimentalSettings());
const headings = [...container.querySelectorAll("h2")].map(
(heading) => heading.textContent ?? "",
);
// Sanity: the page rendered a meaningful set of cards, not an empty list.
expect(headings.length).toBeGreaterThan(10);
const alphabetical = [...headings].sort((a, b) =>
a.localeCompare(b, undefined, { sensitivity: "base" }),
);
expect(headings).toEqual(alphabetical);
});
it("no longer renders an 'Experimental' secondary badge on any card", async () => {
await renderPage(defaultExperimentalSettings());
const badges = [...container.querySelectorAll('[data-slot="badge"]')].map(
(badge) => badge.textContent?.trim(),
);
expect(badges).not.toContain("Experimental");
});
});

View File

@ -87,7 +87,6 @@ function ManagedByCloudBadge() {
function ExperimentalToggleCard({
title,
experimental = false,
description,
footnote,
checked,
@ -97,7 +96,6 @@ function ExperimentalToggleCard({
ariaLabel,
}: {
title: string;
experimental?: boolean;
description: string;
footnote?: string;
checked: boolean;
@ -113,7 +111,6 @@ function ExperimentalToggleCard({
<div className="space-y-1.5">
<div className="flex flex-wrap items-center gap-2">
<h2 className="text-sm font-semibold">{title}</h2>
{experimental ? <Badge variant="secondary">Experimental</Badge> : null}
{isManaged ? <ManagedByCloudBadge /> : null}
</div>
<p className="max-w-2xl text-sm text-muted-foreground">{description}</p>
@ -460,66 +457,8 @@ export function InstanceExperimentalSettings() {
</div>
)}
{inWorktree ? (
<Card className="block p-5">
<div className="flex flex-col gap-4">
<div className="flex items-start justify-between gap-4">
<div className="space-y-1.5">
<div className="flex flex-wrap items-center gap-2">
<h2 className="text-sm font-semibold">Run tasks in this worktree</h2>
{worktreeRunExecutionManaged ? <ManagedByCloudBadge /> : null}
</div>
<p className="max-w-2xl text-sm text-muted-foreground">
This is an isolated git-worktree preview instance. Turn this on to let the scheduler execute runs
here. Only tasks created after enabling will run automatically copied/pre-existing tasks stay
parked. Toggling off and on resets the cutoff.
</p>
</div>
<ToggleSwitch
checked={enableWorktreeRunExecution}
onCheckedChange={(checked) => {
if (worktreeRunExecutionManaged) return;
toggleMutation.mutate({ enableWorktreeRunExecution: checked });
}}
disabled={toggleMutation.isPending || worktreeRunExecutionManaged}
aria-label="Toggle worktree run execution setting"
/>
</div>
{worktreeRunExecutionState.kind === "armed" ? (
<div className="flex items-center gap-2 rounded-md border border-emerald-500/30 bg-emerald-500/5 px-3 py-2 text-sm text-foreground">
<Play className="h-4 w-4 shrink-0 text-emerald-600" />
<span>
Running tasks created after{" "}
<span className="font-medium">
{formatActivationTimestamp(worktreeRunExecutionState.activatedAt)}
</span>
.
</span>
</div>
) : null}
{worktreeRunExecutionState.kind === "fail_closed" ? (
<div className="flex items-start gap-2 rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-sm">
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-700" />
<div className="space-y-0.5">
<p className="font-medium text-foreground">Execution is suppressed effectively off.</p>
<p className="text-muted-foreground">
{worktreeRunExecutionState.reason === "instance_mismatch"
? "This setting was armed in a different instance and copied here, so no tasks run automatically."
: "This setting is missing its activation cutoff, so no tasks run automatically."}{" "}
Toggle it off and back on to arm execution for tasks created here.
</p>
</div>
</div>
) : null}
</div>
</Card>
) : null}
<ExperimentalToggleCard
title="Apps"
experimental
description="Show the Apps navigation and allow access to app connections, gateways, and advanced app tooling."
checked={enableApps}
onCheckedChange={(checked) => toggleMutation.mutate({ enableApps: checked })}
@ -528,206 +467,6 @@ export function InstanceExperimentalSettings() {
ariaLabel="Toggle apps experimental setting"
/>
<ExperimentalToggleCard
title="Cases"
experimental
description="Durable work products (blog posts, tweet storms…) that tasks create and iterate on. Adds the Cases tab and the agent case API."
footnote="Turning Cases off hides the tab and blocks the case API; existing case data is kept."
checked={enableCases}
onCheckedChange={(checked) => toggleMutation.mutate({ enableCases: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableCases}
ariaLabel="Toggle cases experimental setting"
/>
<ExperimentalToggleCard
title="Enable Environments"
description="Show environment management in company settings and allow project and agent environment assignment controls."
checked={enableEnvironments}
onCheckedChange={(checked) => toggleMutation.mutate({ enableEnvironments: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableEnvironments}
ariaLabel="Toggle environments experimental setting"
/>
<ExperimentalToggleCard
title="Built-in Agents"
description="Show Paperclip-managed built-in agent surfaces, including built-in roster badges, the Built-in agents tab, and built-in agent setup controls."
checked={enableBuiltInAgents}
onCheckedChange={(checked) => toggleMutation.mutate({ enableBuiltInAgents: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableBuiltInAgents}
ariaLabel="Toggle built-in agents experimental setting"
/>
<ExperimentalToggleCard
title="Beta skills"
description="Allow agents to pin beta releases of the Paperclip core skill. Disabling this returns every agent to the default live skill without removing saved pins."
checked={enableBetaSkills}
onCheckedChange={(checked) => toggleMutation.mutate({ enableBetaSkills: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableBetaSkills}
ariaLabel="Toggle beta skills experimental setting"
/>
<ExperimentalToggleCard
title="Summaries"
description="Show Summarizer-generated status slots on project and workspace pages, with on-demand refresh and revision history. Existing summary data is kept when this is disabled."
footnote="Status Cards requires Summaries. Disabling Summaries also disables Status Cards."
checked={enableSummaries}
onCheckedChange={(checked) =>
toggleMutation.mutate(
checked || !enableStatusCards
? { enableSummaries: checked }
: { enableSummaries: false, enableStatusCards: false },
)
}
disabled={toggleMutation.isPending || summariesRequiredByManagedStatusCards}
managed={managedKeys.enableSummaries}
ariaLabel="Toggle summaries experimental setting"
/>
<ExperimentalToggleCard
title="Experimental File Viewer"
description="Show task detail controls for browsing and previewing workspace files relative to a task."
checked={enableExperimentalFileViewer}
onCheckedChange={(checked) => toggleMutation.mutate({ enableExperimentalFileViewer: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableExperimentalFileViewer}
ariaLabel="Toggle experimental file viewer setting"
/>
<ExperimentalToggleCard
title="Status Cards"
description="Enable the experimental shared status-card board and its gated API. Existing card data is kept when this is disabled."
footnote="Enabling Status Cards also enables Summaries."
checked={enableStatusCards}
onCheckedChange={(checked) =>
toggleMutation.mutate(
checked
? { enableSummaries: true, enableStatusCards: true }
: { enableStatusCards: false },
)
}
disabled={toggleMutation.isPending || statusCardsBlockedByManagedSummaries}
managed={managedKeys.enableStatusCards}
ariaLabel="Toggle status cards experimental setting"
/>
<ExperimentalToggleCard
title="Enable External Objects"
description="Detect external URLs in issues and show resolved status for pull requests, tickets, and other referenced work objects."
checked={enableExternalObjects}
onCheckedChange={(checked) => toggleMutation.mutate({ enableExternalObjects: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableExternalObjects}
ariaLabel="Toggle external objects experimental setting"
/>
<ExperimentalToggleCard
title="Decisions"
description="Show the Decisions item in the main sidebar — the attention home that surfaces the tasks awaiting your input — while the surface is still being evaluated."
checked={enableDecisions}
onCheckedChange={(checked) => toggleMutation.mutate({ enableDecisions: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableDecisions}
ariaLabel="Toggle decisions experimental setting"
/>
<ExperimentalToggleCard
title="Goals Sidebar Link"
description="Restore the Goals item in the main sidebar while the goals surface is being evaluated."
checked={enableGoalsSidebarLink}
onCheckedChange={(checked) => toggleMutation.mutate({ enableGoalsSidebarLink: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableGoalsSidebarLink}
ariaLabel="Toggle goals sidebar link experimental setting"
/>
<ExperimentalToggleCard
title="Enable Isolated Workspaces"
description="Show execution workspace controls in project configuration and allow isolated workspace behavior for new and existing task runs."
checked={enableIsolatedWorkspaces}
onCheckedChange={(checked) => toggleMutation.mutate({ enableIsolatedWorkspaces: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableIsolatedWorkspaces}
ariaLabel="Toggle isolated workspaces experimental setting"
/>
{SHOW_CONFERENCE_ROOM_EXPERIMENTAL_SETTING ? (
<ExperimentalToggleCard
title="Conference Room Chat"
description="Adds a Conference Room — one chat where you and your whole team work together — plus the live activity feed and the redesigned onboarding. Also restyles task threads as chat bubbles. Turn off anytime to restore the classic UI."
checked={enableConferenceRoomChat}
onCheckedChange={(checked) => toggleMutation.mutate({ enableConferenceRoomChat: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableConferenceRoomChat}
ariaLabel="Toggle conference room chat experimental setting"
/>
) : null}
<ExperimentalToggleCard
title="Task Plan Decomposition Panel"
description="Show accepted-plan decomposition history on task detail pages. Intended for debugging and validating subtask creation behavior while the presentation is still being refined."
checked={enableIssuePlanDecompositions}
onCheckedChange={(checked) => toggleMutation.mutate({ enableIssuePlanDecompositions: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableIssuePlanDecompositions}
ariaLabel="Toggle task plan decomposition panel experimental setting"
/>
<ExperimentalToggleCard
title="Chat-Style Tasks"
experimental
description="Reimagines the task detail page as a live conversation with your agents: chat bubbles for people and agents, streaming activity — thinking, tool calls, diffs — that folds into a one-line summary when a turn finishes, inline plan/question/permission cards, a three-mode composer (Agent · Plan · Ask), and a resizable Properties · Plan · Artifacts pane."
footnote="Turning this off instantly restores the classic task page. No task data is affected."
checked={enableTaskChatRedesign}
onCheckedChange={(checked) => toggleMutation.mutate({ enableTaskChatRedesign: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableTaskChatRedesign}
ariaLabel="Toggle chat-style tasks experimental setting"
/>
<ExperimentalToggleCard
title="Task Watchdogs"
description="Show task detail controls for configuring watchdog agents that verify stopped task subtrees and restore live paths when work should continue."
checked={enableTaskWatchdogs}
onCheckedChange={(checked) => toggleMutation.mutate({ enableTaskWatchdogs: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableTaskWatchdogs}
ariaLabel="Toggle task watchdogs experimental setting"
/>
<ExperimentalToggleCard
title="Server Info Debug View"
description='Show a "Server" section in the account drawer with the current server restart time and running commit.'
checked={enableServerInfoDebugView}
onCheckedChange={(checked) => toggleMutation.mutate({ enableServerInfoDebugView: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableServerInfoDebugView}
ariaLabel="Toggle server info debug view experimental setting"
/>
<ExperimentalToggleCard
title="Smoke Lab"
description='Add a "Smoke Lab" tab under Apps → Developer and an "Integration smoke" card on the dashboard for exercising every integration path against deterministic local fixtures (fake OAuth provider + loopback MCP servers). Private (non-public) deployments only.'
checked={enableSmokeLab}
onCheckedChange={(checked) => toggleMutation.mutate({ enableSmokeLab: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableSmokeLab}
ariaLabel="Toggle smoke lab experimental setting"
/>
<ExperimentalToggleCard
title="Auto-Restart Dev Server When Idle"
description="In `pnpm dev:once`, wait for all queued and running local agent runs to finish, then restart the server automatically when backend changes or migrations make the current boot stale."
checked={autoRestartDevServerWhenIdle}
onCheckedChange={(checked) => toggleMutation.mutate({ autoRestartDevServerWhenIdle: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.autoRestartDevServerWhenIdle}
ariaLabel="Toggle guarded dev-server auto-restart"
/>
<Card className="block p-5">
<div className="flex flex-col gap-5">
<div className="flex items-start justify-between gap-4">
@ -818,6 +557,261 @@ export function InstanceExperimentalSettings() {
</div>
</Card>
<ExperimentalToggleCard
title="Auto-Restart Dev Server When Idle"
description="In `pnpm dev:once`, wait for all queued and running local agent runs to finish, then restart the server automatically when backend changes or migrations make the current boot stale."
checked={autoRestartDevServerWhenIdle}
onCheckedChange={(checked) => toggleMutation.mutate({ autoRestartDevServerWhenIdle: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.autoRestartDevServerWhenIdle}
ariaLabel="Toggle guarded dev-server auto-restart"
/>
<ExperimentalToggleCard
title="Beta skills"
description="Allow agents to pin beta releases of the Paperclip core skill. Disabling this returns every agent to the default live skill without removing saved pins."
checked={enableBetaSkills}
onCheckedChange={(checked) => toggleMutation.mutate({ enableBetaSkills: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableBetaSkills}
ariaLabel="Toggle beta skills experimental setting"
/>
<ExperimentalToggleCard
title="Built-in Agents"
description="Show Paperclip-managed built-in agent surfaces, including built-in roster badges, the Built-in agents tab, and built-in agent setup controls."
checked={enableBuiltInAgents}
onCheckedChange={(checked) => toggleMutation.mutate({ enableBuiltInAgents: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableBuiltInAgents}
ariaLabel="Toggle built-in agents experimental setting"
/>
<ExperimentalToggleCard
title="Cases"
description="Durable work products (blog posts, tweet storms…) that tasks create and iterate on. Adds the Cases tab and the agent case API."
footnote="Turning Cases off hides the tab and blocks the case API; existing case data is kept."
checked={enableCases}
onCheckedChange={(checked) => toggleMutation.mutate({ enableCases: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableCases}
ariaLabel="Toggle cases experimental setting"
/>
<ExperimentalToggleCard
title="Chat-Style Tasks"
description="Reimagines the task detail page as a live conversation with your agents: chat bubbles for people and agents, streaming activity — thinking, tool calls, diffs — that folds into a one-line summary when a turn finishes, inline plan/question/permission cards, a three-mode composer (Agent · Plan · Ask), and a resizable Properties · Plan · Artifacts pane."
footnote="Turning this off instantly restores the classic task page. No task data is affected."
checked={enableTaskChatRedesign}
onCheckedChange={(checked) => toggleMutation.mutate({ enableTaskChatRedesign: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableTaskChatRedesign}
ariaLabel="Toggle chat-style tasks experimental setting"
/>
{SHOW_CONFERENCE_ROOM_EXPERIMENTAL_SETTING ? (
<ExperimentalToggleCard
title="Conference Room Chat"
description="Adds a Conference Room — one chat where you and your whole team work together — plus the live activity feed and the redesigned onboarding. Also restyles task threads as chat bubbles. Turn off anytime to restore the classic UI."
checked={enableConferenceRoomChat}
onCheckedChange={(checked) => toggleMutation.mutate({ enableConferenceRoomChat: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableConferenceRoomChat}
ariaLabel="Toggle conference room chat experimental setting"
/>
) : null}
<ExperimentalToggleCard
title="Decisions"
description="Show the Decisions item in the main sidebar — the attention home that surfaces the tasks awaiting your input — while the surface is still being evaluated."
checked={enableDecisions}
onCheckedChange={(checked) => toggleMutation.mutate({ enableDecisions: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableDecisions}
ariaLabel="Toggle decisions experimental setting"
/>
<ExperimentalToggleCard
title="Enable Environments"
description="Show environment management in company settings and allow project and agent environment assignment controls."
checked={enableEnvironments}
onCheckedChange={(checked) => toggleMutation.mutate({ enableEnvironments: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableEnvironments}
ariaLabel="Toggle environments experimental setting"
/>
<ExperimentalToggleCard
title="Enable External Objects"
description="Detect external URLs in issues and show resolved status for pull requests, tickets, and other referenced work objects."
checked={enableExternalObjects}
onCheckedChange={(checked) => toggleMutation.mutate({ enableExternalObjects: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableExternalObjects}
ariaLabel="Toggle external objects experimental setting"
/>
<ExperimentalToggleCard
title="Enable Isolated Workspaces"
description="Show execution workspace controls in project configuration and allow isolated workspace behavior for new and existing task runs."
checked={enableIsolatedWorkspaces}
onCheckedChange={(checked) => toggleMutation.mutate({ enableIsolatedWorkspaces: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableIsolatedWorkspaces}
ariaLabel="Toggle isolated workspaces experimental setting"
/>
<ExperimentalToggleCard
title="Experimental File Viewer"
description="Show task detail controls for browsing and previewing workspace files relative to a task."
checked={enableExperimentalFileViewer}
onCheckedChange={(checked) => toggleMutation.mutate({ enableExperimentalFileViewer: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableExperimentalFileViewer}
ariaLabel="Toggle experimental file viewer setting"
/>
<ExperimentalToggleCard
title="Goals Sidebar Link"
description="Restore the Goals item in the main sidebar while the goals surface is being evaluated."
checked={enableGoalsSidebarLink}
onCheckedChange={(checked) => toggleMutation.mutate({ enableGoalsSidebarLink: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableGoalsSidebarLink}
ariaLabel="Toggle goals sidebar link experimental setting"
/>
{inWorktree ? (
<Card className="block p-5">
<div className="flex flex-col gap-4">
<div className="flex items-start justify-between gap-4">
<div className="space-y-1.5">
<div className="flex flex-wrap items-center gap-2">
<h2 className="text-sm font-semibold">Run tasks in this worktree</h2>
{worktreeRunExecutionManaged ? <ManagedByCloudBadge /> : null}
</div>
<p className="max-w-2xl text-sm text-muted-foreground">
This is an isolated git-worktree preview instance. Turn this on to let the scheduler execute runs
here. Only tasks created after enabling will run automatically copied/pre-existing tasks stay
parked. Toggling off and on resets the cutoff.
</p>
</div>
<ToggleSwitch
checked={enableWorktreeRunExecution}
onCheckedChange={(checked) => {
if (worktreeRunExecutionManaged) return;
toggleMutation.mutate({ enableWorktreeRunExecution: checked });
}}
disabled={toggleMutation.isPending || worktreeRunExecutionManaged}
aria-label="Toggle worktree run execution setting"
/>
</div>
{worktreeRunExecutionState.kind === "armed" ? (
<div className="flex items-center gap-2 rounded-md border border-emerald-500/30 bg-emerald-500/5 px-3 py-2 text-sm text-foreground">
<Play className="h-4 w-4 shrink-0 text-emerald-600" />
<span>
Running tasks created after{" "}
<span className="font-medium">
{formatActivationTimestamp(worktreeRunExecutionState.activatedAt)}
</span>
.
</span>
</div>
) : null}
{worktreeRunExecutionState.kind === "fail_closed" ? (
<div className="flex items-start gap-2 rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-sm">
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-700" />
<div className="space-y-0.5">
<p className="font-medium text-foreground">Execution is suppressed effectively off.</p>
<p className="text-muted-foreground">
{worktreeRunExecutionState.reason === "instance_mismatch"
? "This setting was armed in a different instance and copied here, so no tasks run automatically."
: "This setting is missing its activation cutoff, so no tasks run automatically."}{" "}
Toggle it off and back on to arm execution for tasks created here.
</p>
</div>
</div>
) : null}
</div>
</Card>
) : null}
<ExperimentalToggleCard
title="Server Info Debug View"
description='Show a "Server" section in the account drawer with the current server restart time and running commit.'
checked={enableServerInfoDebugView}
onCheckedChange={(checked) => toggleMutation.mutate({ enableServerInfoDebugView: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableServerInfoDebugView}
ariaLabel="Toggle server info debug view experimental setting"
/>
<ExperimentalToggleCard
title="Smoke Lab"
description='Add a "Smoke Lab" tab under Apps → Developer and an "Integration smoke" card on the dashboard for exercising every integration path against deterministic local fixtures (fake OAuth provider + loopback MCP servers). Private (non-public) deployments only.'
checked={enableSmokeLab}
onCheckedChange={(checked) => toggleMutation.mutate({ enableSmokeLab: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableSmokeLab}
ariaLabel="Toggle smoke lab experimental setting"
/>
<ExperimentalToggleCard
title="Status Cards"
description="Enable the experimental shared status-card board and its gated API. Existing card data is kept when this is disabled."
footnote="Enabling Status Cards also enables Summaries."
checked={enableStatusCards}
onCheckedChange={(checked) =>
toggleMutation.mutate(
checked
? { enableSummaries: true, enableStatusCards: true }
: { enableStatusCards: false },
)
}
disabled={toggleMutation.isPending || statusCardsBlockedByManagedSummaries}
managed={managedKeys.enableStatusCards}
ariaLabel="Toggle status cards experimental setting"
/>
<ExperimentalToggleCard
title="Summaries"
description="Show Summarizer-generated status slots on project and workspace pages, with on-demand refresh and revision history. Existing summary data is kept when this is disabled."
footnote="Status Cards requires Summaries. Disabling Summaries also disables Status Cards."
checked={enableSummaries}
onCheckedChange={(checked) =>
toggleMutation.mutate(
checked || !enableStatusCards
? { enableSummaries: checked }
: { enableSummaries: false, enableStatusCards: false },
)
}
disabled={toggleMutation.isPending || summariesRequiredByManagedStatusCards}
managed={managedKeys.enableSummaries}
ariaLabel="Toggle summaries experimental setting"
/>
<ExperimentalToggleCard
title="Task Plan Decomposition Panel"
description="Show accepted-plan decomposition history on task detail pages. Intended for debugging and validating subtask creation behavior while the presentation is still being refined."
checked={enableIssuePlanDecompositions}
onCheckedChange={(checked) => toggleMutation.mutate({ enableIssuePlanDecompositions: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableIssuePlanDecompositions}
ariaLabel="Toggle task plan decomposition panel experimental setting"
/>
<ExperimentalToggleCard
title="Task Watchdogs"
description="Show task detail controls for configuring watchdog agents that verify stopped task subtrees and restore live paths when work should continue."
checked={enableTaskWatchdogs}
onCheckedChange={(checked) => toggleMutation.mutate({ enableTaskWatchdogs: checked })}
disabled={toggleMutation.isPending}
managed={managedKeys.enableTaskWatchdogs}
ariaLabel="Toggle task watchdogs experimental setting"
/>
{previewDialogOpen && !autoRecoveryManaged ? (
<RecoveryPreviewDialog
open