perf: reduce redundant sidebar agent status subscriptions (#29840)

* perf: reduce sidebar agent status subscription work

* test: align sidebar store mocks with subscription API

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-10-16 14:32:29 -07:00
committed by GitHub
co-authored by OrcaWin
parent 804cffde0f
commit ea451aa50a
17 changed files with 728 additions and 307 deletions
@@ -20,38 +20,43 @@ const sleepMocks = vi.hoisted(() => ({
let worktreeCardProperties: WorktreeCardProperty[] = ['status', 'comment']
let settings: Partial<GlobalSettings> | null = null
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
browserTabsByWorktree: {},
createBrowserTab: vi.fn(),
deleteFolderWorkspace: vi.fn(),
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch: vi.fn(),
fetchIssue: vi.fn(),
fetchLinearIssue: vi.fn(),
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
openTaskPage: vi.fn(),
projectGroups: [],
ptyIdsByTabId: {},
remoteBranchConflictByWorktreeId: {},
renamingWorktreeId: null,
setActiveWorktree: vi.fn(),
setRemoteBrowserPageHandle: vi.fn(),
setRenamingWorktreeId,
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
tabsByWorktree: {},
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
browserTabsByWorktree: {},
createBrowserTab: vi.fn(),
deleteFolderWorkspace: vi.fn(),
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch: vi.fn(),
fetchIssue: vi.fn(),
fetchLinearIssue: vi.fn(),
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
openTaskPage: vi.fn(),
projectGroups: [],
ptyIdsByTabId: {},
remoteBranchConflictByWorktreeId: {},
renamingWorktreeId: null,
setActiveWorktree: vi.fn(),
setRemoteBrowserPageHandle: vi.fn(),
setRenamingWorktreeId,
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
tabsByWorktree: {},
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/components/ui/hover-card', () => ({
HoverCard: ({ children }: { children: ReactNode }) => <>{children}</>,
@@ -23,33 +23,38 @@ let worktreesByRepo: Record<string, Worktree[]> = {}
let worktreeCardProperties: WorktreeCardProperty[] = ['status']
let deleteStateByWorktreeId: Record<string, { isDeleting: boolean; error: string | null }> = {}
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId,
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
runtimeEnvironments,
runtimeStatusByEnvironmentId,
removedSshTargetLabels,
settings: null,
sshConnectionStates,
sshStateByEnvironment,
sshTargetLabels,
sshTargetsHydrated: true,
updateWorktreeMeta,
worktreesByRepo,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId,
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
runtimeEnvironments,
runtimeStatusByEnvironmentId,
removedSshTargetLabels,
settings: null,
sshConnectionStates,
sshStateByEnvironment,
sshTargetLabels,
sshTargetsHydrated: true,
updateWorktreeMeta,
worktreesByRepo,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/worktree-activation', () => ({
activateAndRevealWorktree: vi.fn()
@@ -20,28 +20,33 @@ let worktreeCardProperties: WorktreeCardProperty[] = []
let settings: Partial<GlobalSettings> | null = null
const WORKTREE_CARD_IMPORT_TIMEOUT_MS = 15_000
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/worktree-activation', () => ({
activateAndRevealWorktree: vi.fn()
@@ -17,34 +17,39 @@ let worktreeCardProperties: WorktreeCardProperty[] = ['status']
let root: Root | null = null
let container: HTMLDivElement | null = null
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {
'local::repo-1::feature/branch': {
data: null,
fetchedAt: Date.now(),
linkedReviewHintKey: ''
}
},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings: { experimentalNewWorktreeCardStyle: true },
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {
'local::repo-1::feature/branch': {
data: null,
fetchedAt: Date.now(),
linkedReviewHintKey: ''
}
},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings: { experimentalNewWorktreeCardStyle: true },
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/sidebar-worktree-activation', () => ({
activateWorktreeFromSidebar: vi.fn()
@@ -14,27 +14,32 @@ const updateWorktreeMeta = vi.fn()
let worktreeCardProperties: WorktreeCardProperty[] = []
const WORKTREE_CARD_IMPORT_TIMEOUT_MS = 15_000
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings: null,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings: null,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/worktree-activation', () => ({ activateAndRevealWorktree: vi.fn() }))
@@ -19,29 +19,34 @@ let hostedReviewCache: Record<string, unknown> = {}
let prCache: Record<string, unknown> = {}
let settings: Partial<GlobalSettings> | null = null
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache,
issueCache: {},
linearIssueCache: {},
openModal,
prCache,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache,
issueCache: {},
linearIssueCache: {},
openModal,
prCache,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/worktree-activation', () => ({
activateAndRevealWorktree: vi.fn()
@@ -16,28 +16,33 @@ let worktreeCardProperties: WorktreeCardProperty[] = []
let settings: Partial<GlobalSettings> | null = null
const WORKTREE_CARD_IMPORT_TIMEOUT_MS = 15_000
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/worktree-activation', () => ({
activateAndRevealWorktree: vi.fn()
@@ -24,28 +24,33 @@ let workspaceDeleteModifierPressed = false
let gitConflictOperationByWorktree: Record<string, GitConflictOperation> = {}
let WorktreeCard: typeof WorktreeCardComponent
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
gitConflictOperationByWorktree,
hostedReviewCache: {},
issueCache: {},
openModal,
projectGroups,
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
browserTabsByWorktree,
ptyIdsByTabId,
tabsByWorktree,
updateWorktreeMeta,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
gitConflictOperationByWorktree,
hostedReviewCache: {},
issueCache: {},
openModal,
projectGroups,
remoteBranchConflictByWorktreeId: {},
settings,
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
browserTabsByWorktree,
ptyIdsByTabId,
tabsByWorktree,
updateWorktreeMeta,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/worktree-activation', () => ({
activateAndRevealWorktree: vi.fn()
@@ -22,33 +22,38 @@ let sshStateByEnvironment = new Map()
let worktreesByRepo: Record<string, Worktree[]> = {}
let worktreeCardProperties: WorktreeCardProperty[] = ['status']
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
selector({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
runtimeEnvironments,
runtimeStatusByEnvironmentId,
removedSshTargetLabels,
settings: null,
sshConnectionStates,
sshStateByEnvironment,
sshTargetLabels,
sshTargetsHydrated: true,
updateWorktreeMeta,
worktreesByRepo,
worktreeCardProperties
vi.mock('@/store', () => {
const getState = () => ({
deleteStateByWorktreeId: {},
fetchHostedReviewForBranch,
fetchIssue,
fetchLinearIssue,
gitConflictOperationByWorktree: {},
hostedReviewCache: {},
issueCache: {},
linearIssueCache: {},
openModal,
projectGroups: [],
remoteBranchConflictByWorktreeId: {},
runtimeEnvironments,
runtimeStatusByEnvironmentId,
removedSshTargetLabels,
settings: null,
sshConnectionStates,
sshStateByEnvironment,
sshTargetLabels,
sshTargetsHydrated: true,
updateWorktreeMeta,
worktreesByRepo,
worktreeCardProperties
})
return {
useAppStore: Object.assign((selector: (state: unknown) => unknown) => selector(getState()), {
getState,
subscribe: () => () => {}
})
}))
}
})
vi.mock('@/lib/worktree-activation', () => ({
activateAndRevealWorktree: vi.fn()
@@ -47,16 +47,15 @@ type WorktreeListComponent = React.ComponentType<{
let WorktreeList: WorktreeListComponent
vi.mock('@/store', () => {
const useAppStore = ((selector: (state: Record<string, unknown>) => unknown) =>
selector(mockStore.state)) as ((
selector: (state: Record<string, unknown>) => unknown
) => unknown) & {
getState: () => Record<string, unknown>
}
useAppStore.getState = () => mockStore.state
return { useAppStore }
})
vi.mock('@/store', () => ({
useAppStore: Object.assign(
(selector: (state: Record<string, unknown>) => unknown) => selector(mockStore.state),
{
getState: () => mockStore.state,
subscribe: () => () => {}
}
)
}))
// Why: honor the real getItemKey so each virtual row's React key equals
// getRenderRowKey(row). This is what makes the parent card remount when it
@@ -51,16 +51,15 @@ function makeFolderWorkspacePathStatusMockState(): Record<string, unknown> {
}
}
vi.mock('@/store', () => {
const useAppStore = ((selector: (state: Record<string, unknown>) => unknown) =>
selector(mockStore.state)) as ((
selector: (state: Record<string, unknown>) => unknown
) => unknown) & {
getState: () => Record<string, unknown>
}
useAppStore.getState = () => mockStore.state
return { useAppStore }
})
vi.mock('@/store', () => ({
useAppStore: Object.assign(
(selector: (state: Record<string, unknown>) => unknown) => selector(mockStore.state),
{
getState: () => mockStore.state,
subscribe: () => () => {}
}
)
}))
vi.mock('@tanstack/react-virtual', () => ({
defaultRangeExtractor: ({ startIndex, endIndex }: { startIndex: number; endIndex: number }) =>
@@ -52,16 +52,15 @@ function makeFolderWorkspacePathStatusMockState(): Record<string, unknown> {
}
}
vi.mock('@/store', () => {
const useAppStore = ((selector: (state: Record<string, unknown>) => unknown) =>
selector(mockStore.state)) as ((
selector: (state: Record<string, unknown>) => unknown
) => unknown) & {
getState: () => Record<string, unknown>
}
useAppStore.getState = () => mockStore.state
return { useAppStore }
})
vi.mock('@/store', () => ({
useAppStore: Object.assign(
(selector: (state: Record<string, unknown>) => unknown) => selector(mockStore.state),
{
getState: () => mockStore.state,
subscribe: () => () => {}
}
)
}))
vi.mock('@tanstack/react-virtual', () => ({
defaultRangeExtractor: ({ startIndex, endIndex }: { startIndex: number; endIndex: number }) =>
@@ -0,0 +1,222 @@
// @vitest-environment happy-dom
import { act } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useAppStore } from '@/store'
import { readStoreListenerCount } from '@/store/store-listener-census'
import { makeTab } from '@/store/slices/store-test-helpers'
import type { AppState } from '@/store/types'
import type { DashboardAgentRow } from '@/components/dashboard/useDashboardData'
import { makePaneKey } from '../../../../shared/stable-pane-id'
import {
AGENT_STATUS_STALE_AFTER_MS,
type AgentStatusEntry
} from '../../../../shared/agent-status-types'
import { useWorktreeAgentRows } from './useWorktreeAgentRows'
Reflect.set(globalThis, 'IS_REACT_ACT_ENVIRONMENT', true)
const LEAF = '11111111-1111-4111-8111-111111111111'
const KEY_A = makePaneKey('tab-a', LEAF)
const KEY_B = makePaneKey('tab-b', LEAF)
const original = useAppStore.getState()
let root: Root
let container: HTMLDivElement
let rows: DashboardAgentRow[]
let renders: number
function Probe({
worktreeId = 'folder-a',
active = true
}: {
worktreeId?: string
active?: boolean
}) {
rows = useWorktreeAgentRows(worktreeId, active)
renders += 1
return null
}
function entry(key: string, worktreeId: string): AgentStatusEntry {
return {
paneKey: key,
worktreeId,
state: 'working',
agentType: 'claude',
prompt: worktreeId,
updatedAt: Date.now(),
stateStartedAt: Date.now(),
stateHistory: []
}
}
function patch(update: Partial<AppState>) {
act(() => useAppStore.setState(update))
}
beforeEach(() => {
vi.useFakeTimers()
vi.setSystemTime(2_000_000)
useAppStore.setState({
tabsByWorktree: {
'folder-a': [makeTab({ id: 'tab-a', worktreeId: 'folder-a' })],
'ssh-b': [makeTab({ id: 'tab-b', worktreeId: 'ssh-b' })]
},
unifiedTabsByWorktree: {},
agentStatusByPaneKey: {
[KEY_A]: entry(KEY_A, 'folder-a'),
[KEY_B]: { ...entry(KEY_B, 'ssh-b'), connectionId: 'ssh:host' }
},
retainedAgentsByPaneKey: {},
migrationUnsupportedByPtyId: {},
runtimePaneTitlesByTabId: {},
ptyIdsByTabId: {},
terminalLayoutsByTabId: {},
runtimeAgentOrchestrationByPaneKey: {},
paneForegroundAgentByPaneKey: {}
})
renders = 0
container = document.createElement('div')
document.body.appendChild(container)
root = createRoot(container)
})
afterEach(() => {
act(() => root.unmount())
container.remove()
useAppStore.setState(original, true)
vi.useRealTimers()
})
describe('mounted worktree agent row subscriptions', () => {
it('listens once while active and releases its listener while inactive', () => {
const baseline = readStoreListenerCount() ?? 0
act(() => root.render(<Probe />))
expect(readStoreListenerCount()).toBe(baseline + 1)
expect(rows[0].entry.prompt).toBe('folder-a')
act(() => root.render(<Probe active={false} />))
expect(readStoreListenerCount()).toBe(baseline)
expect(rows).toEqual([])
const before = renders
patch({ activeWorktreeId: 'ssh-b' })
expect(renders).toBe(before)
patch({
agentStatusByPaneKey: {
...useAppStore.getState().agentStatusByPaneKey,
[KEY_A]: { ...entry(KEY_A, 'folder-a'), prompt: 'changed while disabled' }
}
})
act(() => root.render(<Probe />))
expect(rows[0].entry.prompt).toBe('changed while disabled')
expect(readStoreListenerCount()).toBe(baseline + 1)
})
it('switches worktrees and applies an SSH status update immediately', () => {
act(() => root.render(<Probe />))
act(() => root.render(<Probe worktreeId="ssh-b" />))
expect(rows[0].paneKey).toBe(KEY_B)
act(() =>
useAppStore
.getState()
.setAgentStatus(
KEY_B,
{ state: 'blocked', agentType: 'claude', prompt: 'remote permission' },
undefined,
{ updatedAt: Date.now() + 1 },
{ tabId: 'tab-b', worktreeId: 'ssh-b', connectionId: 'ssh:host' }
)
)
expect(rows[0].entry.prompt).toBe('remote permission')
expect(rows[0].state).toBe('blocked')
})
it('keeps unrelated cards stable while a working agent reports new tool output', () => {
act(() => root.render(<Probe />))
const beforeRows = rows
const before = renders
act(() =>
useAppStore
.getState()
.setAgentStatus(
KEY_B,
{ state: 'working', agentType: 'claude', prompt: 'new output', toolName: 'Read' },
undefined,
{ updatedAt: Date.now() + 1 },
{ tabId: 'tab-b', worktreeId: 'ssh-b', connectionId: 'ssh:host' }
)
)
expect(rows).toBe(beforeRows)
expect(renders).toBe(before)
act(() =>
useAppStore
.getState()
.setAgentStatus(
KEY_A,
{ state: 'working', agentType: 'claude', prompt: 'local output', toolName: 'Edit' },
undefined,
{ updatedAt: Date.now() + 2 },
{ tabId: 'tab-a', worktreeId: 'folder-a' }
)
)
expect(rows[0].entry.toolName).toBe('Edit')
expect(renders).toBe(before + 1)
})
it('decays on an epoch-only freshness tick', () => {
act(() => root.render(<Probe />))
expect(rows[0].state).toBe('working')
vi.setSystemTime(Date.now() + AGENT_STATUS_STALE_AFTER_MS + 1)
patch({ agentStatusEpoch: useAppStore.getState().agentStatusEpoch + 1 })
expect(rows[0].state).toBe('idle')
})
it('observes title, PTY, layout, orchestration, foreground, migration and retention inputs', () => {
act(() => root.render(<Probe />))
const updates: Partial<AppState>[] = [
{ runtimePaneTitlesByTabId: { 'tab-a': { 0: 'Claude Code' } } },
{ ptyIdsByTabId: { 'tab-a': ['pty-a'] } },
{
terminalLayoutsByTabId: {
'tab-a': {
root: { type: 'leaf', leafId: LEAF },
activeLeafId: LEAF,
expandedLeafId: null
}
}
},
{
runtimeAgentOrchestrationByPaneKey: {
[KEY_A]: { taskId: 'task', dispatchId: 'dispatch', taskTitle: 'New task' }
}
},
{ paneForegroundAgentByPaneKey: { [KEY_A]: { agent: 'claude', shellForeground: false } } },
{
migrationUnsupportedByPtyId: {
legacy: {
ptyId: 'legacy',
worktreeId: 'folder-a',
tabId: 'tab-a',
leafId: LEAF,
paneKey: KEY_A,
reason: 'legacy-numeric-pane-key',
source: 'local',
updatedAt: Date.now()
}
}
},
{
retainedAgentsByPaneKey: {
[KEY_B]: {
entry: entry(KEY_B, 'folder-a'),
worktreeId: 'folder-a',
tab: makeTab({ id: 'tab-b', worktreeId: 'folder-a' }),
agentType: 'claude',
startedAt: Date.now()
}
}
}
]
for (const update of updates) {
const before = rows
patch(update)
expect(rows).not.toBe(before)
}
})
})
@@ -1,9 +1,9 @@
import { useMemo } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { useCallback, useMemo, useSyncExternalStore } from 'react'
import type { DashboardAgentRow } from '@/components/dashboard/useDashboardData'
import { applyAgentRowLineage } from '@/components/dashboard/agent-row-lineage'
import { migrationUnsupportedToAgentStatusEntry } from '@/lib/migration-unsupported-agent-entry'
import { useAppStore } from '@/store'
import type { AppState } from '@/store/types'
import {
EMPTY_LIVE_PTY_IDS,
EMPTY_PANE_FOREGROUND_AGENTS,
@@ -33,6 +33,7 @@ import {
// Why frozen: shared by every inactive card, and callers only read these rows.
const EMPTY_AGENT_ROWS = Object.freeze([]) as unknown as DashboardAgentRow[]
const subscribeToNothing = (): (() => void) => () => {}
export { buildWorktreeAgentRows } from './worktree-agent-rows'
export {
@@ -53,63 +54,57 @@ export {
* selector work on high-frequency agent status pings.
*/
export function useWorktreeAgentRows(worktreeId: string, active = true): DashboardAgentRow[] {
const selectAgentFreshness = useMemo(
() => createWorktreeAgentFreshnessSelector(worktreeId),
[worktreeId]
)
const tabs = useAppStore((s) => (active ? s.tabsByWorktree[worktreeId] : EMPTY_TABS))
// Why: narrow the subscriptions to only THIS worktree's entries via
// useShallow. Subscribing to the whole agentStatusByPaneKey map would make
// every on-screen card re-render on any agent-status update anywhere —
// O(worktrees²) render amplification. Pre-filtering here means the card
// only re-renders when something relevant to THIS worktree changes.
const liveEntries = useAppStore(
useShallow((s) =>
active ? selectLiveAgentStatusEntriesForWorktree(s, worktreeId) : EMPTY_LIVE_ENTRIES
)
)
// Why: keep the store selector limited to stable raw records. Converting
// migration entries creates fresh objects with Date.now(), which breaks
// useSyncExternalStore's cached-snapshot contract and can blank Electron.
const migrationUnsupported = useAppStore(
useShallow((s) =>
active
? selectMigrationUnsupportedEntriesForWorktree(s, worktreeId)
: EMPTY_MIGRATION_UNSUPPORTED_ENTRIES
)
)
const retained = useAppStore(
useShallow((s) =>
active ? selectRetainedAgentEntriesForWorktree(s, worktreeId) : EMPTY_RETAINED
)
)
const runtimePaneTitlesByTabId = useAppStore(
useShallow((s) =>
active ? selectRuntimePaneTitlesForWorktree(s, worktreeId) : EMPTY_RUNTIME_PANE_TITLES
)
)
const ptyIdsByTabId = useAppStore(
useShallow((s) => (active ? selectLivePtyIdsForWorktree(s, worktreeId) : EMPTY_LIVE_PTY_IDS))
)
const terminalLayoutsByTabId = useAppStore(
useShallow((s) =>
active ? selectTerminalLayoutsForWorktree(s, worktreeId) : EMPTY_TERMINAL_LAYOUTS
)
)
const runtimeAgentOrchestrationByPaneKey = useAppStore(
useShallow((s) =>
active
? selectRuntimeAgentOrchestrationForWorktree(s, worktreeId)
: EMPTY_WORKTREE_AGENT_ORCHESTRATION
)
)
const paneForegroundAgentByPaneKey = useAppStore(
useShallow((s) =>
active ? selectPaneForegroundAgentsForWorktree(s, worktreeId) : EMPTY_PANE_FOREGROUND_AGENTS
)
)
const agentFreshnessSignature = useAppStore((s) =>
active ? selectAgentFreshness(s) : EMPTY_WORKTREE_AGENT_FRESHNESS_SIGNATURE
const selectInputs = useMemo(() => {
const selectAgentFreshness = createWorktreeAgentFreshnessSelector(worktreeId)
const readInputs = (state: AppState) =>
[
active ? state.tabsByWorktree[worktreeId] : EMPTY_TABS,
active ? selectLiveAgentStatusEntriesForWorktree(state, worktreeId) : EMPTY_LIVE_ENTRIES,
active
? selectMigrationUnsupportedEntriesForWorktree(state, worktreeId)
: EMPTY_MIGRATION_UNSUPPORTED_ENTRIES,
active ? selectRetainedAgentEntriesForWorktree(state, worktreeId) : EMPTY_RETAINED,
active ? selectRuntimePaneTitlesForWorktree(state, worktreeId) : EMPTY_RUNTIME_PANE_TITLES,
active ? selectLivePtyIdsForWorktree(state, worktreeId) : EMPTY_LIVE_PTY_IDS,
active ? selectTerminalLayoutsForWorktree(state, worktreeId) : EMPTY_TERMINAL_LAYOUTS,
active
? selectRuntimeAgentOrchestrationForWorktree(state, worktreeId)
: EMPTY_WORKTREE_AGENT_ORCHESTRATION,
active
? selectPaneForegroundAgentsForWorktree(state, worktreeId)
: EMPTY_PANE_FOREGROUND_AGENTS,
active ? selectAgentFreshness(state) : EMPTY_WORKTREE_AGENT_FRESHNESS_SIGNATURE
] as const
let previous: ReturnType<typeof readInputs> | undefined
return (state: AppState) => {
if (!active && previous) {
return previous
}
const next = readInputs(state)
// The indexed selectors preserve equal records; compare references without allocating shallow-comparison maps.
if (previous && next.every((value, index) => Object.is(value, previous?.[index]))) {
return previous
}
previous = next
return next
}
}, [worktreeId, active])
const getInputs = useCallback(() => selectInputs(useAppStore.getState()), [selectInputs])
const [
tabs,
liveEntries,
migrationUnsupported,
retained,
runtimePaneTitlesByTabId,
ptyIdsByTabId,
terminalLayoutsByTabId,
runtimeAgentOrchestrationByPaneKey,
paneForegroundAgentByPaneKey,
agentFreshnessSignature
] = useSyncExternalStore(
active ? useAppStore.subscribe : subscribeToNothing,
getInputs,
getInputs
)
return useMemo<DashboardAgentRow[]>(() => {
@@ -0,0 +1,132 @@
// @vitest-environment happy-dom
import { act } from 'react'
import { createRoot } from 'react-dom/client'
import { writeFileSync } from 'node:fs'
import { expect, it } from 'vitest'
import { useAppStore } from '@/store'
import { readStoreListenerCount } from '@/store/store-listener-census'
import { makeTab } from '@/store/slices/store-test-helpers'
import { makePaneKey } from '../../../../shared/stable-pane-id'
import type { AgentStatusEntry } from '../../../../shared/agent-status-types'
import { useWorktreeAgentRows } from './useWorktreeAgentRows'
import { useShallow } from 'zustand/react/shallow'
import { selectAcknowledgedAgentTimes } from './worktree-card-agent-ack-inputs'
Reflect.set(globalThis, 'IS_REACT_ACT_ENVIRONMENT', true)
type Round = { elapsedMs: number; cpuMs: number; renders: number }
type Result = { active: boolean; listeners: number; rounds: Round[] }
const LEAF = '11111111-1111-4111-8111-111111111111'
const CARDS = Number(process.env.ORCA_BENCH_CARDS ?? 100)
const WRITES = Number(process.env.ORCA_BENCH_WRITES ?? 500)
it.skipIf(!process.env.ORCA_AGENT_ROWS_BENCH)(
'measures mounted agent row subscriptions',
() => {
const original = useAppStore.getState()
const tabsByWorktree = Object.fromEntries(
Array.from({ length: CARDS }, (_, index) => {
const worktreeId = `wt-${index}`
return [worktreeId, [makeTab({ id: `tab-${index}`, worktreeId })]]
})
)
const entries: Record<string, AgentStatusEntry> = {}
for (let index = 0; index < CARDS; index += 1) {
const paneKey = makePaneKey(`tab-${index}`, LEAF)
entries[paneKey] = {
paneKey,
tabId: `tab-${index}`,
worktreeId: `wt-${index}`,
state: 'working',
agentType: 'claude',
prompt: 'Do work',
updatedAt: Date.now(),
stateStartedAt: Date.now(),
stateHistory: []
}
}
useAppStore.setState({
tabsByWorktree,
agentStatusByPaneKey: entries,
unifiedTabsByWorktree: {},
runtimePaneTitlesByTabId: {},
ptyIdsByTabId: {},
terminalLayoutsByTabId: {},
retainedAgentsByPaneKey: {},
runtimeAgentOrchestrationByPaneKey: {},
paneForegroundAgentByPaneKey: {}
})
const container = document.createElement('div')
document.body.appendChild(container)
const root = createRoot(container)
const results: Result[] = []
try {
// A visible compact card uses both hooks; hidden details keep only the inactive hook.
for (const active of [true, false]) {
let renders = 0
function VisibleProbe({ index }: { index: number }) {
const rows = useWorktreeAgentRows(`wt-${index}`, true)
useWorktreeAgentRows(`wt-${index}`, false)
useAppStore(useShallow((state) => selectAcknowledgedAgentTimes(state, rows)))
renders += 1
return null
}
function HiddenProbe({ index }: { index: number }) {
useWorktreeAgentRows(`wt-${index}`, false)
renders += 1
return null
}
const Probe = active ? VisibleProbe : HiddenProbe
const baselineListeners = readStoreListenerCount() ?? 0
act(() =>
root.render(
Array.from({ length: CARDS }, (_, index) => <Probe key={index} index={index} />)
)
)
const listeners = (readStoreListenerCount() ?? 0) - baselineListeners
const rounds: Round[] = []
for (let round = 0; round < 6; round += 1) {
const beforeRenders = renders
const cpuStart = process.cpuUsage()
const start = performance.now()
for (let index = 0; index < WRITES; index += 1) {
const key = makePaneKey(`tab-${index % CARDS}`, LEAF)
act(() => {
const previous = useAppStore.getState().agentStatusByPaneKey
useAppStore.setState({
agentStatusByPaneKey: {
...previous,
[key]: { ...previous[key], updatedAt: Date.now(), toolName: `tool-${index}` }
}
})
})
}
const elapsedMs = performance.now() - start
const cpu = process.cpuUsage(cpuStart)
expect(renders - beforeRenders).toBe(active ? WRITES : 0)
if (round > 0) {
rounds.push({
elapsedMs,
cpuMs: (cpu.user + cpu.system) / 1000,
renders: renders - beforeRenders
})
}
}
results.push({ active, listeners, rounds })
act(() => root.render(null))
expect(readStoreListenerCount()).toBe(baselineListeners)
}
const report = { cards: CARDS, writes: WRITES, results }
console.log(JSON.stringify(report))
if (process.env.ORCA_BENCH_OUTPUT) {
writeFileSync(process.env.ORCA_BENCH_OUTPUT, `${JSON.stringify(report, null, 2)}\n`)
}
} finally {
act(() => root.unmount())
container.remove()
useAppStore.setState(original, true)
}
},
120_000
)
@@ -75,6 +75,16 @@ describe('selectAcknowledgedAgentTimes', () => {
expect(shallow(after, before)).toBe(true)
})
it('reuses the projection across status-only publications and handles a different row list', () => {
const state = { acknowledgedAgentsByPaneKey: { 'tab-a:leaf-a': 11, 'tab-a:leaf-b': 22 } }
const first = selectAcknowledgedAgentTimes(state, AGENTS)
expect(selectAcknowledgedAgentTimes({ ...state }, AGENTS)).toBe(first)
expect(selectAcknowledgedAgentTimes(state, [AGENTS[1], AGENTS[0]])).toEqual([22, 11])
expect(selectAcknowledgedAgentTimes({ acknowledgedAgentsByPaneKey: {} }, AGENTS)).toEqual([
0, 0
])
})
it('updates when one of this card rows is acknowledged', () => {
const initialTimes = selectedTimes
act(() => {
@@ -3,10 +3,30 @@ import type { AppState } from '@/store/types'
type AcknowledgedAgentTimesState = Pick<AppState, 'acknowledgedAgentsByPaneKey'>
type AcknowledgedAgentRows = readonly Pick<DashboardAgentRow, 'paneKey'>[]
// Both keys are weak so departed rows and old acknowledgement snapshots can be collected.
const projections = new WeakMap<
AcknowledgedAgentTimesState['acknowledgedAgentsByPaneKey'],
WeakMap<AcknowledgedAgentRows, readonly number[]>
>()
/** Projects only the acknowledgement timestamps rendered by one card. */
export function selectAcknowledgedAgentTimes(
state: AcknowledgedAgentTimesState,
agents: readonly Pick<DashboardAgentRow, 'paneKey'>[]
): number[] {
return agents.map((agent) => state.acknowledgedAgentsByPaneKey[agent.paneKey] ?? 0)
agents: AcknowledgedAgentRows
): readonly number[] {
const source = state.acknowledgedAgentsByPaneKey
let byRows = projections.get(source)
if (!byRows) {
byRows = new WeakMap()
projections.set(source, byRows)
}
const cached = byRows.get(agents)
if (cached) {
return cached
}
const times = Object.freeze(agents.map((agent) => source[agent.paneKey] ?? 0))
byRows.set(agents, times)
return times
}