From 2f85dda1830aae404beabe147649f43f8e992d80 Mon Sep 17 00:00:00 2001 From: m4air Date: Thu, 13 Aug 2026 14:56:50 -0700 Subject: [PATCH] Narrow paired browser link fix to registration race --- .../lib/workspace-browser-tab-open.test.ts | 40 +++++++------------ .../src/lib/workspace-browser-tab-open.ts | 6 +-- .../src/runtime/web-runtime-session.ts | 1 + 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/renderer/src/lib/workspace-browser-tab-open.test.ts b/src/renderer/src/lib/workspace-browser-tab-open.test.ts index 5d28024597d..3e8b93a6726 100644 --- a/src/renderer/src/lib/workspace-browser-tab-open.test.ts +++ b/src/renderer/src/lib/workspace-browser-tab-open.test.ts @@ -6,7 +6,6 @@ import { } from '../../../shared/execution-host' import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../shared/constants' import { BROWSER_SCREENCAST_RUNTIME_CAPABILITY } from '../../../shared/protocol-version' -import * as clientCreationActionPolicy from './client-creation-action-policy' import { canOpenWorkspaceBrowserTabOnRuntime, openWorkspaceBrowserTab @@ -132,7 +131,7 @@ describe('openWorkspaceBrowserTab', () => { expect(createBrowserTab).not.toHaveBeenCalled() }) - it('keeps an asserted paired-runtime link on the runtime when client policy selects local', async () => { + it('waits for host registration before reconciling an asserted runtime link', async () => { const createBrowserTab = vi.fn() mocks.state = { ...ownerState(toRuntimeExecutionHostId('hub-a')), @@ -141,32 +140,21 @@ describe('openWorkspaceBrowserTab', () => { defaultBrowserSessionProfileId: 'client-profile', defaultBrowserSessionProfileIdByHostId: {} } - const policySpy = vi - .spyOn(clientCreationActionPolicy, 'getClientCreationActionPolicy') - .mockReturnValue({ - 'managed-browser': { state: 'enabled', provider: 'local-client' }, - 'mobile-emulator': { state: 'enabled', provider: 'local-client' } - }) + await openWorkspaceBrowserTab({ + workspaceId: WORKSPACE_ID, + url: 'https://example.com/pinned', + intent: { kind: 'url' }, + expectedRuntimeEnvironmentId: 'hub-a' + }) - try { - await openWorkspaceBrowserTab({ - workspaceId: WORKSPACE_ID, - url: 'https://example.com/pinned', - intent: { kind: 'url' }, - expectedRuntimeEnvironmentId: 'hub-a' + expect(mocks.createRemote).toHaveBeenCalledWith( + expect.objectContaining({ + environmentId: 'hub-a', + waitForRegistration: true, + worktreeId: WORKSPACE_ID }) - - expect(mocks.createRemote).toHaveBeenCalledWith( - expect.objectContaining({ - environmentId: 'hub-a', - waitForRegistration: true, - worktreeId: WORKSPACE_ID - }) - ) - expect(createBrowserTab).not.toHaveBeenCalled() - } finally { - policySpy.mockRestore() - } + ) + expect(createBrowserTab).not.toHaveBeenCalled() }) it('fails closed when the workspace route swaps away from the pane runtime before opening', async () => { diff --git a/src/renderer/src/lib/workspace-browser-tab-open.ts b/src/renderer/src/lib/workspace-browser-tab-open.ts index fe5f7b21217..52416b75739 100644 --- a/src/renderer/src/lib/workspace-browser-tab-open.ts +++ b/src/renderer/src/lib/workspace-browser-tab-open.ts @@ -212,9 +212,7 @@ export async function openWorkspaceBrowserTab( `host ${route.executionHostId} does not own runtime ${environmentId}` ) } - // A terminal link is pinned to its source runtime after the assertion above; - // provider policy may describe the client surface rather than that owner. - if (expectedEnvironmentId === null && availability.provider === 'local-client') { + if (availability.provider === 'local-client') { const localHostId = host && host.kind !== 'runtime' ? host.id : LOCAL_EXECUTION_HOST_ID createClientBrowserTab(state, request, localHostId, presentation) return @@ -226,7 +224,7 @@ export async function openWorkspaceBrowserTab( environmentId, url: request.url, targetGroupId: request.targetGroupId, - // Pinned terminal links must wait for the host tab to publish before reconciling the client. + // Owner-pinned links need the host tab published before client reconciliation. ...(expectedEnvironmentId !== null ? { waitForRegistration: true } : {}), // Why: the tab is opened from this workspace's tab bar, so surface that // workspace — otherwise a background worktree looks like nothing happened. diff --git a/src/renderer/src/runtime/web-runtime-session.ts b/src/renderer/src/runtime/web-runtime-session.ts index b4818a36afe..164edbed4b7 100644 --- a/src/renderer/src/runtime/web-runtime-session.ts +++ b/src/renderer/src/runtime/web-runtime-session.ts @@ -463,6 +463,7 @@ export async function createWebRuntimeSessionBrowserTab(args: { clientTargetGroupId?: string clientTargetGroupCreated?: boolean focusOnCreate?: boolean + /** Wait until a renderer-backed host can publish the new page in its session snapshot. */ waitForRegistration?: boolean selectWorktree?: boolean stagedTitle?: string