fix(agents): treat Agent Dashboard as strictly opt-in

Flip renderer reads from `showAgentDashboard !== false` to `=== true` so
undefined/missing values read as off. Combined with the default-off in
constants.ts, the dashboard panel never appears unless the user explicitly
enables it.

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
brennanb2025
2026-04-28 17:03:09 -07:00
co-authored by Orca
parent 4c619a0fe5
commit 9f2c6760ee
3 changed files with 12 additions and 19 deletions
@@ -124,12 +124,11 @@ function RightSidebarInner(): React.JSX.Element {
const checksStatus = useAppStore(getActiveChecksStatus)
const activityBarPosition = useAppStore((s) => s.activityBarPosition)
const setActivityBarPosition = useAppStore((s) => s.setActivityBarPosition)
// Why: the bottom-docked agent dashboard is opt-out via Settings → Agents,
// AND gated behind the experimental opt-in setting. Users who prefer a
// quieter sidebar can hide the panel without losing any in-terminal agent
// status — the per-tab status indicators remain. While settings are still
// loading, render the panel so it doesn't flash in once settings arrive.
const showAgentDashboard = useAppStore((s) => s.settings?.showAgentDashboard !== false)
// Why: the bottom-docked agent dashboard is opt-in via Settings → Agents
// AND gated behind the experimental opt-in setting. Undefined/missing
// settings (first hydrate, never-toggled) must read as off so the panel
// doesn't flash in before settings load.
const showAgentDashboard = useAppStore((s) => s.settings?.showAgentDashboard === true)
const dashboardExperimentEnabled = useAppStore(
(s) => s.settings?.experimentalAgentDashboard === true
)
@@ -246,11 +246,10 @@ export function AgentsPane({ settings, updateSettings }: AgentsPaneProps): React
defaultAgent === null || (defaultAgent !== 'blank' && !detectedIds?.has(defaultAgent))
const isBlankDefault = defaultAgent === 'blank'
// Why: match right-sidebar's `s.settings?.showAgentDashboard !== false` read.
// Persisted settings from older versions may be missing this field — treating
// `undefined` as "on" here keeps the toggle's displayed state in sync with
// the sidebar's actual rendering, so the UI never contradicts itself.
const showDashboard = settings.showAgentDashboard !== false
// Why: match right-sidebar's `s.settings?.showAgentDashboard === true` read
// so the toggle's displayed state stays in sync with the sidebar's actual
// rendering. Undefined reads as off (opt-in).
const showDashboard = settings.showAgentDashboard === true
return (
<div className="space-y-8">
+3 -8
View File
@@ -920,14 +920,9 @@ export type GlobalSettings = {
/** Whether to show the live agent activity count badge in the titlebar. */
showTitlebarAgentActivity: boolean
/** Whether to show the Agent Dashboard panel at the bottom of the right sidebar.
* Why: optional because readers use the `settings?.showAgentDashboard !== false`
* idiom (right-sidebar/index.tsx, AgentsPane.tsx) which presumes the field may
* be undefined — e.g. on first hydrate before main-process defaults apply, or
* when migrating settings persisted before this field existed. A required
* `boolean` here would make those readers' fallback branches dead-on-paper
* while still being reached at runtime, which is exactly the kind of type
* hack that drifts silently. Aligning the declaration with reader intent
* keeps the contract honest. */
* Why: optional because renderer readers use `settings?.showAgentDashboard === true`
* — the field may be undefined on first hydrate before main-process defaults
* apply, and undefined must read as off (opt-in). */
showAgentDashboard?: boolean
/** Why: the Tasks sidebar label can be kept cleaner for users who do not
* actively use the GitHub/Linear integrations behind it. */