feat(dashboard): add agent status search board (#11042)

* feat(dashboard): add agent status search board

* fix(dashboard): keep idle controls reachable

* chore: drop merge-only formatting drift

* fix(dashboard): compare sparse subagent snapshots safely

* fix(dashboard): satisfy settings handler lint

* fix(dashboard): address review feedback

* fix(dashboard): complete search and localized status copy

* fix(dashboard): pad active filter row

* fix(dashboard): keep idle control in board settings

* fix(dashboard): source filters from workspace state

* fix(dashboard): clarify PR and MR status filter

* fix(dashboard): preserve review and board parity
This commit is contained in:
Brennan Benson
2026-07-28 15:51:43 -07:00
committed by GitHub
parent 5753cf6c5c
commit 13c193a00a
33 changed files with 1894 additions and 155 deletions
+1
View File
@@ -97,6 +97,7 @@ describe('getDefaultSettings', () => {
it('keeps the agent dashboard popout disabled by default', () => {
expect(getDefaultSettings('/tmp').experimentalAgentDashboardPopout).toBe(false)
expect(getDefaultSettings('/tmp').experimentalAgentDashboardShowIdle).toBe(false)
})
it('routes fresh Codex profiles through the real-home rollout by default', () => {})
+1
View File
@@ -351,6 +351,7 @@ export function getDefaultSettings(homedir: string): GlobalSettings {
experimentalAgentDashboardPopout: false,
// Why: in-window screen popover is the default surface; users opt into a separate pop-out window.
experimentalAgentDashboardMode: 'in-window',
experimentalAgentDashboardShowIdle: false,
experimentalActivityDefaultedOffForAllUsers: true,
experimentalTerminalAttention: false,
experimentalAgentHibernation: false,
+43 -9
View File
@@ -8,20 +8,31 @@ import type { RepoIcon } from './repo-icon'
* Every field must be structured-clone-safe (no functions / class instances).
*/
/** The three kanban columns. "Idle" is everything that isn't actively working
* and isn't blocking you — this includes explicitly-completed ('done') agents,
* which Orca only reports when a completion hook fires, so they're folded in
* rather than split into a separate, inconsistently-populated column. */
export type DashboardBucket = 'attention' | 'working' | 'idle'
/** Agent lifecycle columns; idle is optional while completed agents remain visible. */
export type DashboardBucket = 'attention' | 'working' | 'done' | 'idle'
/** Column order shared by producer and pop-out so they never drift. */
export const DASHBOARD_BUCKET_ORDER: readonly DashboardBucket[] = ['attention', 'working', 'idle']
export const DASHBOARD_BUCKET_ORDER: readonly DashboardBucket[] = [
'attention',
'working',
'done',
'idle'
]
/** Precise per-card state marker (drives AgentStateDot). Kept distinct from
* `bucket` so the "Needs You" column can still show amber (waiting/permission)
* vs red (blocked) dots. */
/** Kept distinct from `bucket` so attention cards retain their precise dot state. */
export type DashboardCardDotState = 'working' | 'blocked' | 'waiting' | 'done' | 'idle'
export type DashboardCardReview = {
number: number
state: 'open' | 'closed' | 'merged' | 'draft'
}
export type DashboardCardSubagent = {
id: string
name: string
dotState: DashboardCardDotState
}
export type DashboardCard = {
/** Stable identity for React keys. */
paneKey: string
@@ -44,6 +55,13 @@ export type DashboardCard = {
leafId: string | null
repoName: string
worktreeName: string
workspaceStatusId?: string
workspaceStatusLabel?: string
workspaceStatusColor?: string
/** True when the workspace links a review whose live state is not cached yet. */
hasReview?: boolean
review?: DashboardCardReview
subagents?: DashboardCardSubagent[]
/** "Started … ago" display. */
startedAt: number
/** When the agent last entered `done`, or null if it never finished. Drives
@@ -64,9 +82,24 @@ export type DashboardCard = {
conversationName?: string
}
export type DashboardFilterOption = {
id: string
label: string
color?: string
}
export type DashboardFilterOptions = {
projects: DashboardFilterOption[]
workspaceStatuses: DashboardFilterOption[]
}
export type DashboardSnapshot = {
generatedAt: number
cards: DashboardCard[]
showIdle?: boolean
/** Available filter dimensions are store-derived so zero-card projects and
* statuses remain selectable. Optional for preload-version compatibility. */
filterOptions?: DashboardFilterOptions
/** Icons for the repos the cards belong to. Keyed by repoId rather than
* carried per card: image icons are data URLs up to 400KB, and the snapshot
* is republished several times a second. Optional so a pop-out running
@@ -77,6 +110,7 @@ export type DashboardSnapshot = {
export const EMPTY_DASHBOARD_SNAPSHOT: DashboardSnapshot = {
generatedAt: 0,
cards: [],
filterOptions: { projects: [], workspaceStatuses: [] },
repoIconsByRepoId: {}
}
+2
View File
@@ -2976,6 +2976,8 @@ export type GlobalSettings = {
experimentalAgentDashboardPopout?: boolean
/** How the Agent Dashboard opens: an in-window companion board or a separate pop-out window. Defaults to in-window. */
experimentalAgentDashboardMode?: AgentDashboardMode
/** Includes stale quiet agents as a fourth Agent Dashboard column. */
experimentalAgentDashboardShowIdle?: boolean
/** One-shot migration guard for defaulting the Agents view off; later explicit opt-ins persist normally. */
experimentalActivityDefaultedOffForAllUsers?: boolean
/** Experimental: persistent terminal-pane attention ring for bell + agent-completion events. Opt-in while tuning signal/noise. */