fix(terminal): retain renames before renderer pane hydration

This commit is contained in:
Neil
2026-09-14 05:40:12 -07:00
parent b87a6c0f23
commit 7add03c19b
2 changed files with 73 additions and 1 deletions
@@ -134,7 +134,13 @@ export class OrcaRuntimeWithResolveWorktreeRemovalTarget extends OrcaRuntimeWith
return { handle, tabId: leaf.tabId, title }
}
}
return { handle, tabId: pty.pty.tabId ?? pty.record.tabId, title }
const tabId = pty.pty.tabId ?? pty.record.tabId
// A notifier can exist before its pane graph; retain the rename on the known tab.
if (this.notifier?.renameTerminal && tabId) {
this.persistHeadlessTerminalTitle(pty.pty.worktreeId, tabId, title)
this.notifier.renameTerminal(tabId, title)
}
return { handle, tabId, title }
}
this.assertGraphReady()
const { leaf } = this.getLiveLeafForHandle(handle)
@@ -0,0 +1,66 @@
import './orca-runtime-test-lifecycle.spec'
import type { RuntimeStore } from './runtime-store-contract'
import { describe, expect, it, vi } from 'vitest'
import { OrcaRuntimeService } from './orca-runtime-test-mocks.spec'
import {
HEADLESS_LEAF_ID,
TEST_WORKTREE_ID,
makeRuntimeStoreWithWorkspaceSession,
makeWorkspaceSessionWithHeadlessTerminal
} from './orca-runtime-test-fixtures.spec'
describe('terminal rename before renderer graph hydration', () => {
it.each(['Media Engine Orch', null])(
'persists and forwards title %s across PTY replacement',
async (title) => {
const session = makeWorkspaceSessionWithHeadlessTerminal()
session.tabsByWorktree[TEST_WORKTREE_ID][0].customTitle = 'Previous name'
const { runtimeStore, getSession } = makeRuntimeStoreWithWorkspaceSession(session)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The shared fixture supplies RuntimeStore methods; its legacy Mock return type loses callable signatures.
const checkedStore = runtimeStore as RuntimeStore
const runtime = new OrcaRuntimeService(checkedStore)
const renameTerminal = vi.fn()
runtime.setPtyController({
spawn: vi.fn(async () => ({ id: 'omp-initial-pty' })),
write: () => true,
kill: () => true,
getForegroundProcess: async () => null
})
runtime.setNotifier({
worktreesChanged: vi.fn(),
reposChanged: vi.fn(),
activateWorktree: vi.fn(),
createTerminal: vi.fn(),
splitTerminal: vi.fn(),
renameTerminal,
focusTerminal: vi.fn(),
closeTerminal: vi.fn(),
sleepWorktree: vi.fn(),
terminalFitOverrideChanged: vi.fn(),
terminalDriverChanged: vi.fn()
})
const created = await runtime.createTerminal(`id:${TEST_WORKTREE_ID}`, {
tabId: 'host-tab',
leafId: HEADLESS_LEAF_ID
})
await runtime.renameTerminal(created.handle, title)
expect(getSession().tabsByWorktree[TEST_WORKTREE_ID][0].customTitle).toBe(title)
expect(renameTerminal).toHaveBeenCalledWith('host-tab', title)
runtime.onPtyExit('omp-initial-pty', 0)
const restored = new OrcaRuntimeService(checkedStore)
restored.setPtyController({
spawn: vi.fn(async () => ({ id: 'omp-replacement-pty' })),
write: () => true,
kill: () => true,
getForegroundProcess: async () => null
})
await restored.createTerminal(`id:${TEST_WORKTREE_ID}`, {
tabId: 'host-tab',
leafId: HEADLESS_LEAF_ID
})
expect(getSession().tabsByWorktree[TEST_WORKTREE_ID][0].customTitle).toBe(title)
}
)
})