fix(terminal): stamp ORCA_WORKSPACE_ID on every terminal main creates, not only folder ones (#31608)

The window stamps it (equal to ORCA_WORKTREE_ID) for every workspace kind and agent
wrappers forward it; terminals started from the phone, the CLI or a server's own create
in a git worktree lacked it.
This commit is contained in:
Jinwoo Hong
2026-10-21 15:53:36 -04:00
committed by GitHub
parent 7a06b6579b
commit 1db95e308a
6 changed files with 54 additions and 5 deletions
@@ -193,7 +193,10 @@ export function expectedHostProvider(c: HostLaunchCase): Record<string, unknown>
env: {},
...provider,
...(c.os === 'win32' ? { terminalWindowsWslDistro } : {}),
// main today: the host lane stamps ORCA_WORKSPACE_ID on folders only.
orcaEnv: c.workspace.kind === 'folder' ? [...FOLDER_ENV_KEYS, ...HOST_ENV_KEYS] : HOST_ENV_KEYS
// Like the window lane, the host lane stamps ORCA_WORKSPACE_ID for every workspace kind.
orcaEnv:
c.workspace.kind === 'folder'
? [...FOLDER_ENV_KEYS, ...HOST_ENV_KEYS]
: ['ORCA_WORKSPACE_ID', ...HOST_ENV_KEYS]
}
}
+1
View File
@@ -278,6 +278,7 @@ describe('host lane: producer call -> runtime controller -> provider', () => {
// The host stamps its own pane identity (the window lane's stale-key case is below).
const spawned = recordOf(lanes.provider.mock.calls.at(-1)?.[0])
expect(recordOf(spawned.env).ORCA_PANE_KEY).toBe(spawned.paneKey)
expect(recordOf(spawned.env).ORCA_WORKSPACE_ID).toBe(launchWorkspaceId(c.workspace))
expect(trackMock.mock.calls).toEqual(c.telemetry ? [['agent_started', c.telemetry]] : [])
expect(lanes.persistPtyBinding.mock.calls[0]?.[0]).toMatchObject({
placement: { kind: 'new-tab' }
@@ -328,7 +328,8 @@ describe('OrcaRuntimeService', () => {
worktreeId: FLOATING_TERMINAL_WORKTREE_ID
})
expect(spawnedPtyEnv(spawnCall).ORCA_WORKTREE_ID).toBe(FLOATING_TERMINAL_WORKTREE_ID)
expect(spawnCall?.env?.ORCA_WORKSPACE_ID).toBeUndefined()
// The window's floating panes carry the sentinel as their workspace id too.
expect(spawnCall?.env?.ORCA_WORKSPACE_ID).toBe(FLOATING_TERMINAL_WORKTREE_ID)
expect(spawnCall?.env?.ORCA_PROJECT_GROUP_ID).toBeUndefined()
expect(spawnCall?.env?.ORCA_WORKSPACE_ROOT).toBeUndefined()
})
@@ -0,0 +1,41 @@
import { describe, expect, it, vi } from 'vitest'
import { OrcaRuntimeService } from '../orca-runtime-test-mocks.spec'
import { TEST_WORKTREE_ID, spawnedPtyEnv, store } from '../orca-runtime-test-fixtures.spec'
function makeRuntime(): { runtime: OrcaRuntimeService; spawn: ReturnType<typeof vi.fn> } {
const spawn = vi.fn().mockResolvedValue({ id: 'pty-workspace-id' })
const runtime = new OrcaRuntimeService(store)
runtime.setPtyController({
spawn,
write: () => true,
kill: () => true,
getForegroundProcess: async () => null
})
return { runtime, spawn }
}
// Why: the window stamps ORCA_WORKSPACE_ID on every pane and agent wrappers forward it, so a
// terminal main creates (phone, CLI, or a remote server's own create) must carry the same value.
describe('OrcaRuntimeService terminal ORCA_WORKSPACE_ID', () => {
it('stamps the worktree id on a git worktree terminal, as the window does', async () => {
const { runtime, spawn } = makeRuntime()
await runtime.createTerminal(`id:${TEST_WORKTREE_ID}`, { title: 'phone shell' })
const env = spawnedPtyEnv(spawn.mock.calls[0]?.[0])
expect(env.ORCA_WORKSPACE_ID).toBe(TEST_WORKTREE_ID)
expect(env.ORCA_WORKSPACE_ID).toBe(env.ORCA_WORKTREE_ID)
})
// A window attached to a remote server sends its pane env with the create; the host's own
// workspace id wins, as it already does for folders.
it('replaces a client-sent value with the host workspace id', async () => {
const { runtime, spawn } = makeRuntime()
await runtime.createTerminal(`id:${TEST_WORKTREE_ID}`, {
env: { ORCA_WORKSPACE_ID: 'stale-client-id' }
})
expect(spawnedPtyEnv(spawn.mock.calls[0]?.[0]).ORCA_WORKSPACE_ID).toBe(TEST_WORKTREE_ID)
})
})
+1
View File
@@ -46,6 +46,7 @@ await import('./orca-runtime-tests/agent-status-and-waits-part-03.spec')
await import('./orca-runtime-tests/terminal-creation-and-readiness.spec')
await import('./orca-runtime-tests/terminal-creation-and-readiness-part-02.spec')
await import('./orca-runtime-tests/terminal-creation-and-readiness-part-03.spec')
await import('./orca-runtime-tests/terminal-workspace-id-env.spec')
await import('./orca-runtime-tests/terminal-creation-and-readiness-part-04.spec')
await import('./orca-runtime-tests/terminal-creation-and-readiness-part-05.spec')
await import('./orca-runtime-tests/terminal-creation-and-readiness-part-06.spec')
@@ -198,17 +198,19 @@ export abstract class OrcaRuntimeWithResolveBrowserNetworkExecutionHostForWorktr
delete cleanBaseEnv[key]
}
// Pane identity (ORCA_PANE_KEY/TAB_ID/WORKTREE_ID, jcode dir) is stamped by the spawn step from the spawn's ids.
// Why: the window stamps ORCA_WORKSPACE_ID (its ORCA_WORKTREE_ID) for every workspace kind,
// and agent wrappers forward it.
const env = {
...cleanBaseEnv,
...agentTeamsEnv,
...this.buildAgentHookPtyEnv?.()
...this.buildAgentHookPtyEnv?.(),
ORCA_WORKSPACE_ID: scope.id
}
if (!scope.folderWorkspace) {
return env
}
return {
...env,
ORCA_WORKSPACE_ID: scope.id,
ORCA_PROJECT_GROUP_ID: scope.folderWorkspace.projectGroupId,
ORCA_WORKSPACE_ROOT: scope.folderWorkspace.folderPath
}