perf(sidebar): stop re-inspecting the setup-script prompt on every worktree revisit (#29514)

Refs #26785
This commit is contained in:
Neil
2026-10-16 00:25:01 -07:00
committed by GitHub
parent 723c258a23
commit 78849b2312
2 changed files with 57 additions and 2 deletions
@@ -5,7 +5,10 @@ import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useAppStore } from '@/store'
import type { Repo } from '../../../../shared/repo-types'
import { useSetupScriptPromptRevalidation } from './useSetupScriptPromptRevalidation'
import {
SETUP_PROMPT_REVISIT_REVALIDATION_INTERVAL_MS,
useSetupScriptPromptRevalidation
} from './useSetupScriptPromptRevalidation'
import type { SetupScriptPromptState } from './setup-script-prompt-render-state'
import { getRepoHostIdentityForParts } from '@/store/slices/repo-host-identity'
@@ -261,6 +264,35 @@ describe('useSetupScriptPromptRevalidation', () => {
expect(requestRevalidation).toHaveBeenCalledTimes(1)
})
it('re-inspects each worktree once on first activation, not on every revisit', async () => {
const now = vi.spyOn(Date, 'now').mockReturnValue(1_000_000)
const requestRevalidation = vi.fn()
await render({
activeRepo: GIT_REPO,
isDismissed: false,
sidebarOpen: true,
promptState: missingSetup('repo-1'),
requestRevalidation
})
// Before: every one of these 20 switches cost a hooksCheck + setupScriptImports pair.
for (let round = 0; round < 10; round += 1) {
await setActiveWorktree('worktree-2')
await setActiveWorktree('worktree-1')
}
expect(requestRevalidation).toHaveBeenCalledTimes(1)
await setActiveWorktree('worktree-3')
expect(requestRevalidation).toHaveBeenCalledTimes(2)
now.mockReturnValue(1_000_000 + SETUP_PROMPT_REVISIT_REVALIDATION_INTERVAL_MS)
await setActiveWorktree('worktree-1')
expect(requestRevalidation).toHaveBeenCalledTimes(3)
await setActiveWorktree('worktree-2')
expect(requestRevalidation).toHaveBeenCalledTimes(3)
now.mockRestore()
})
it('re-inspects when the repo runtime reconnects', async () => {
const requestRevalidation = vi.fn()
await setRuntimeConnectionGeneration(1)
@@ -6,6 +6,9 @@ import { getRepoHostIdentity } from '@/store/slices/repo-host-identity'
import { getRepoExecutionHostId, parseExecutionHostId } from '../../../../shared/execution-host'
import type { SetupScriptPromptState } from './setup-script-prompt-render-state'
/** Revisiting an already-activated worktree re-inspects at most this often. */
export const SETUP_PROMPT_REVISIT_REVALIDATION_INTERVAL_MS = 30_000
/**
* Re-runs the setup-script prompt inspection when a shared `orca.yaml` setup hook
* can have become effective outside SetupScriptPromptCard's reactive inputs, so a
@@ -72,6 +75,12 @@ export function useSetupScriptPromptRevalidation(input: {
// card nulls it for the whole inspection round trip). Remember them instead of
// dropping them, then replay once a revalidatable result exists.
const pendingRevalidationRef = useRef(false)
// Why: a worktree's first activation is when its creation-time setup hook can have landed.
// Re-inspecting on every revisit cost two host round trips per click on remote repos (#26785).
const activatedWorktreeIdsRef = useRef(
new Set<string>(activeWorktreeId ? [activeWorktreeId] : [])
)
const lastActivationRevalidationAtRef = useRef(Number.NEGATIVE_INFINITY)
useEffect(() => {
const worktreeChanged = previousWorktreeIdRef.current !== activeWorktreeId
@@ -85,8 +94,21 @@ export function useSetupScriptPromptRevalidation(input: {
if (hostChanged) {
// A repo/host switch re-runs the card's own inspection, so no extra pass is owed.
pendingRevalidationRef.current = false
} else if (worktreeChanged || reconnected) {
} else if (reconnected) {
pendingRevalidationRef.current = true
} else if (worktreeChanged) {
const firstActivation =
activeWorktreeId !== null && !activatedWorktreeIdsRef.current.has(activeWorktreeId)
if (activeWorktreeId !== null) {
activatedWorktreeIdsRef.current.add(activeWorktreeId)
}
if (
firstActivation ||
Date.now() - lastActivationRevalidationAtRef.current >=
SETUP_PROMPT_REVISIT_REVALIDATION_INTERVAL_MS
) {
pendingRevalidationRef.current = true
}
}
if (
@@ -100,6 +122,7 @@ export function useSetupScriptPromptRevalidation(input: {
return
}
pendingRevalidationRef.current = false
lastActivationRevalidationAtRef.current = Date.now()
requestRevalidation()
}, [
activeRepo,