Harden Cmd+J incomplete hydration re-rank latch

Clear the provisional order latch when the ranked list goes empty so a
brief tab wipe cannot freeze an empty Recent section, and assert that a
user-moved selection survives the incomplete→complete re-rank.
This commit is contained in:
Jinjing
2026-08-07 18:59:26 -07:00
parent 25fe6cbccf
commit c2e64eef04
2 changed files with 11 additions and 14 deletions
@@ -769,7 +769,7 @@ describe('WorktreeJumpPalette recent chats & terminals', () => {
it('re-ranks once when terminal entities hydrate after unified tabs', async () => {
// Why split hydration: unified tabs can land before tabsByWorktree; without a re-capture every
// row ranks IDLE and the blocked chat stays under focus recency until reopen.
// row ranks IDLE. A deliberate second-row highlight must survive that one re-rank.
const hydrated = makeRecentTabState({
agentStatusByPaneKey: {
[`term-alpha:${LEAF_ID}`]: makeAgentEntry('term-alpha', 'blocked', Date.now())
@@ -778,23 +778,17 @@ describe('WorktreeJumpPalette recent chats & terminals', () => {
})
await renderPalette({ ...hydrated, tabsByWorktree: {} })
expect(getTabRowIds()).toEqual(['tab-beta', 'tab-alpha'])
const movedTo = `workspace-tab:${getTabRowIds()[1]}`
await act(async () => {
setCommandSelection?.(movedTo)
})
await flushEffects()
await act(async () => {
useAppStore.setState({ tabsByWorktree: hydrated.tabsByWorktree } as Partial<AppState>)
})
await flushEffects()
expect(getTabRowIds()).toEqual(['tab-alpha', 'tab-beta'])
// Why: incomplete→complete re-rank is one-shot — later status churn still freezes positions.
await act(async () => {
useAppStore.setState({
agentStatusByPaneKey: {
[`term-beta:${LEAF_ID}`]: makeAgentEntry('term-beta', 'blocked', Date.now())
}
} as Partial<AppState>)
})
await flushEffects()
expect(getTabRowIds()).toEqual(['tab-alpha', 'tab-beta'])
expect(getCommandValue()).toBe(movedTo)
})
it('ranks a blocked agent above a more recently visited idle tab', async () => {
@@ -1098,7 +1098,10 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
if (order.length === 0) {
// Why: tabs can arrive after the palette opens (cold start, session restore, a late tab
// mirror). Latching an empty snapshot would leave Recent dead — and digits inert — until
// close+reopen, so stay unlatched; the stable empty ref keeps this a no-op re-render.
// close+reopen. Also clear a provisional latch: incomplete→complete fallthrough can hit empty
// if open tabs briefly vanish, and keeping captured would freeze an empty Recent forever.
recentTabOrderCapturedRef.current = false
recentTabOrderAttentionReadyRef.current = false
setRecentTabOrder(EMPTY_RECENT_TAB_ORDER)
return
}