From 964c64b0cc65f547d04337cb13ffb58b3dc180d9 Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Tue, 27 Oct 2026 11:03:23 -0700 Subject: [PATCH] test: remove 64 low-value file, terminal and language tests (#34482) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> --- config/reliability-gates.jsonc | 17 +- config/scripts/ci-shard-timings.json | 3 - .../textmate-language-registration.test.ts | 90 ----- .../monaco-languages/zig-highlighting.test.ts | 10 - ...emote-runtime-terminal-end-verdict.test.ts | 50 --- .../runtime-file-drop-staging-ignore.test.ts | 80 ----- ...ntime-file-write-disk-precondition.test.ts | 132 ------- .../runtime-legacy-inventory-budget.test.ts | 29 +- ...legacy-quick-open-inventory-expiry.test.ts | 25 -- .../runtime/runtime-paged-file-read.test.ts | 60 +--- ...e-quick-open-version-compatibility.test.ts | 227 +----------- .../runtime-terminal-artifact-write.test.ts | 92 +---- .../runtime-terminal-inspection.test.ts | 327 ------------------ .../runtime/runtime-terminal-stream.test.ts | 192 +--------- .../runtime-terminal-verified-input.test.ts | 125 ------- 15 files changed, 8 insertions(+), 1451 deletions(-) delete mode 100644 src/renderer/src/lib/monaco-languages/textmate-language-registration.test.ts delete mode 100644 src/renderer/src/runtime/remote-runtime-terminal-end-verdict.test.ts delete mode 100644 src/renderer/src/runtime/runtime-terminal-verified-input.test.ts diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc index 0be92f7a94e..45445eb7c8e 100644 --- a/config/reliability-gates.jsonc +++ b/config/reliability-gates.jsonc @@ -681,7 +681,7 @@ "invariant": "A prompt occurrence leaves the input region only when an accepted reply answers it (a current host's provider acknowledgment, or an older host's whole-write acceptance as before) or the user collapses it to a strip above the composer, which writes nothing and keeps the card mounted with its partial answer; status-backed occurrences are told apart by the host wait's start, so view toggles and remounts preserve them while real clear/replacement supersedes them, and a transcript-only one is dropped when the view stops observing it; obsolete results cannot change replacements; selector groups wait for complete writes before pacing; refusal or unknown handoff never causes replay; a card retires an unsubmitted composer send without writing under it or losing its text, and the hidden composer cannot send or interrupt; Collapse or Escape folds a card without writing, never during an in-flight answer, and a new occurrence shows expanded again; the phone blocks only Send while a card is expanded and shows one card per occurrence; cancellation stops unsent groups and active dictation can stop.", "oracle": "After acknowledged phone replies with stale host status, the exact card disappears and Send is enabled; unknown, refused or unverifiable-settlement replies retain enabled choices, while an older host's accepted reply dismisses like an acknowledged one; a same-occurrence view toggle retains pending acknowledgment and real replacements discard it. A slow 32 KiB SSH answer completes all chunks before Enter; cancellation preserves issued bytes but omits remaining groups. Paired settlement invokes the actual provider and lost callbacks remain unknown; older hosts deliver ordinary messages, launch and selector groups once and their accepted answers dismiss as before. An answered card stays hidden across a view remount; a collapsed card is a strip that frees the composer and expands back; an identical question in a new wait shows again; a composer send caught by a new card keeps its bubble without submitting or clearing the line under it.", "commands": [ - "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/renderer/src/components/native-chat/NativeChatInteractiveCard.test.tsx src/renderer/src/components/native-chat/use-native-chat-interactive-send.test.tsx src/renderer/src/components/native-chat/native-chat-observed-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send-launch-draft.test.ts src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-input.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-composer.test.tsx src/renderer/src/components/native-chat/use-native-chat-prompt-card-presentation.test.ts src/renderer/src/runtime/runtime-terminal-verified-input.test.ts src/renderer/src/components/native-chat/NativeChatComposer.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.turn-status.test.tsx src/renderer/src/components/native-chat/NativeChatApprovalCard.test.tsx src/renderer/src/components/native-chat/native-chat-interactive-prompt.test.ts src/renderer/src/runtime/runtime-terminal-inspection.test.ts src/renderer/src/lib/agent-paste-draft.test.ts src/renderer/src/lib/agent-paste-draft-submit-retry.test.ts src/renderer/src/lib/agent-followup-delivery.test.ts src/main/ipc/pty/ipc/write-input-acceptance.test.ts src/main/ipc/pty/ipc/write-input-user-input.test.ts src/main/ipc/pty/ipc/write-input-chunk-yield.test.ts src/main/ipc/pty/pty-write-ipc-validation.test.ts src/main/daemon/daemon-pty-write-settlement-recovery.test.ts src/main/runtime/runtime-terminal-writer.test.ts src/main/runtime/rpc/terminal-send.test.ts src/main/runtime/rpc/terminal-send-launch-draft-resolution.test.ts src/main/runtime/terminal-send-stale-leaf-liveness.test.ts src/renderer/src/lib/agent-paste-draft-readiness-budget.test.ts tests/e2e/native-chat-ssh-delivery.unit.test.ts --maxWorkers=2", + "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/renderer/src/components/native-chat/NativeChatInteractiveCard.test.tsx src/renderer/src/components/native-chat/use-native-chat-interactive-send.test.tsx src/renderer/src/components/native-chat/native-chat-observed-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send-launch-draft.test.ts src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-input.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-composer.test.tsx src/renderer/src/components/native-chat/use-native-chat-prompt-card-presentation.test.ts src/renderer/src/components/native-chat/NativeChatComposer.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.turn-status.test.tsx src/renderer/src/components/native-chat/NativeChatApprovalCard.test.tsx src/renderer/src/components/native-chat/native-chat-interactive-prompt.test.ts src/renderer/src/runtime/runtime-terminal-inspection.test.ts src/renderer/src/lib/agent-paste-draft.test.ts src/renderer/src/lib/agent-paste-draft-submit-retry.test.ts src/renderer/src/lib/agent-followup-delivery.test.ts src/main/ipc/pty/ipc/write-input-acceptance.test.ts src/main/ipc/pty/ipc/write-input-user-input.test.ts src/main/ipc/pty/ipc/write-input-chunk-yield.test.ts src/main/ipc/pty/pty-write-ipc-validation.test.ts src/main/daemon/daemon-pty-write-settlement-recovery.test.ts src/main/runtime/runtime-terminal-writer.test.ts src/main/runtime/rpc/terminal-send.test.ts src/main/runtime/rpc/terminal-send-launch-draft-resolution.test.ts src/main/runtime/terminal-send-stale-leaf-liveness.test.ts src/renderer/src/lib/agent-paste-draft-readiness-budget.test.ts tests/e2e/native-chat-ssh-delivery.unit.test.ts --maxWorkers=2", "ORCA_BACKGROUND_LAUNCH=1 mobile/node_modules/.bin/vitest run --config mobile/vitest.config.ts mobile/src/session/MobileNativeChatView.prompt-presentation.test.ts mobile/src/session/use-mobile-native-chat-controller.test.ts mobile/src/session/native-chat/input/use-mobile-native-chat-ask-dismiss.test.ts mobile/src/session/MobileNativeChatView.stop.test.ts mobile/src/session/MobileNativeChatView.failure-banner.test.ts mobile/src/session/MobileNativeChatView.rows.test.ts mobile/src/session/MobileNativeChatView.composer-lock.test.ts mobile/src/session/MobileNativeChatView.tail-follow.test.ts mobile/src/session/MobileNativeChatView.history-paging.test.ts mobile/src/session/mobile-prompt-controller.test.ts mobile/src/session/native-chat/input/mobile-native-chat-permission-send.test.ts mobile/src/session/native-chat/input/use-mobile-native-chat-cancel-ask.test.ts mobile/src/session/native-chat/input/use-mobile-native-chat-answer-send.test.ts mobile/src/session/native-chat/transcript/use-mobile-native-chat-message-send.test.ts mobile/src/session/native-chat/mobile-native-chat-send.test.ts mobile/src/session/MobileNativeChatCardHeaderAction.test.tsx mobile/src/session/native-chat/input/MobileNativeChatPromptCard.test.tsx --maxWorkers=2", "ORCA_BACKGROUND_LAUNCH=1 pnpm test tests/e2e/cross-version-wire/cross-version-terminal-wire.unit.test.ts --maxWorkers=1", "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/renderer/src/components/native-chat/NativeChatInteractiveCard.test.tsx src/renderer/src/components/native-chat/use-native-chat-interactive-send.test.tsx src/renderer/src/components/native-chat/native-chat-observed-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send-launch-draft.test.ts src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-input.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.turn-status.test.tsx src/renderer/src/components/native-chat/NativeChatApprovalCard.test.tsx src/renderer/src/components/native-chat/native-chat-interactive-prompt.test.ts src/renderer/src/runtime/runtime-terminal-inspection.test.ts src/renderer/src/lib/agent-paste-draft.test.ts src/renderer/src/lib/agent-paste-draft-submit-retry.test.ts src/renderer/src/lib/agent-followup-delivery.test.ts src/main/ipc/pty/ipc/write-input-acceptance.test.ts src/main/ipc/pty/ipc/write-input-user-input.test.ts src/main/ipc/pty/ipc/write-input-chunk-yield.test.ts src/main/ipc/pty/pty-write-ipc-validation.test.ts src/main/daemon/daemon-pty-write-settlement-recovery.test.ts --maxWorkers=2", @@ -696,7 +696,6 @@ "src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-input.test.tsx", "src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-composer.test.tsx", "src/renderer/src/components/native-chat/use-native-chat-prompt-card-presentation.test.ts", - "src/renderer/src/runtime/runtime-terminal-verified-input.test.ts", "src/renderer/src/components/native-chat/NativeChatComposer.test.tsx", "src/renderer/src/components/native-chat/NativeChatResolvedView.turn-status.test.tsx", "src/renderer/src/components/native-chat/NativeChatApprovalCard.test.tsx", @@ -838,7 +837,7 @@ "runner": "local", "platform": "macos", "command": "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/renderer/src/components/native-chat/NativeChatInteractiveCard.test.tsx src/renderer/src/components/native-chat/use-native-chat-interactive-send.test.tsx src/renderer/src/components/native-chat/native-chat-observed-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send-launch-draft.test.ts src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-input.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-composer.test.tsx src/renderer/src/components/native-chat/use-native-chat-prompt-card-presentation.test.ts src/renderer/src/runtime/runtime-terminal-verified-input.test.ts src/renderer/src/components/native-chat/NativeChatComposer.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.turn-status.test.tsx src/renderer/src/components/native-chat/NativeChatApprovalCard.test.tsx src/renderer/src/components/native-chat/native-chat-interactive-prompt.test.ts src/renderer/src/runtime/runtime-terminal-inspection.test.ts src/renderer/src/lib/agent-paste-draft.test.ts src/renderer/src/lib/agent-paste-draft-submit-retry.test.ts src/renderer/src/lib/agent-followup-delivery.test.ts src/main/ipc/pty/ipc/write-input-acceptance.test.ts src/main/ipc/pty/ipc/write-input-user-input.test.ts src/main/ipc/pty/ipc/write-input-chunk-yield.test.ts src/main/ipc/pty-write-ipc-validation.test.ts src/main/daemon/daemon-pty-write-settlement-recovery.test.ts src/main/runtime/runtime-terminal-writer.test.ts src/main/runtime/rpc/terminal-send.test.ts src/main/runtime/rpc/terminal-send-launch-draft-resolution.test.ts src/main/runtime/terminal-send-stale-leaf-liveness.test.ts src/renderer/src/lib/agent-paste-draft-readiness-budget.test.ts tests/e2e/native-chat-ssh-delivery.unit.test.ts --maxWorkers=2", - "currentCommand": "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/renderer/src/components/native-chat/NativeChatInteractiveCard.test.tsx src/renderer/src/components/native-chat/use-native-chat-interactive-send.test.tsx src/renderer/src/components/native-chat/native-chat-observed-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send-launch-draft.test.ts src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-input.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-composer.test.tsx src/renderer/src/components/native-chat/use-native-chat-prompt-card-presentation.test.ts src/renderer/src/runtime/runtime-terminal-verified-input.test.ts src/renderer/src/components/native-chat/NativeChatComposer.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.turn-status.test.tsx src/renderer/src/components/native-chat/NativeChatApprovalCard.test.tsx src/renderer/src/components/native-chat/native-chat-interactive-prompt.test.ts src/renderer/src/runtime/runtime-terminal-inspection.test.ts src/renderer/src/lib/agent-paste-draft.test.ts src/renderer/src/lib/agent-paste-draft-submit-retry.test.ts src/renderer/src/lib/agent-followup-delivery.test.ts src/main/ipc/pty/ipc/write-input-acceptance.test.ts src/main/ipc/pty/ipc/write-input-user-input.test.ts src/main/ipc/pty/ipc/write-input-chunk-yield.test.ts src/main/ipc/pty/pty-write-ipc-validation.test.ts src/main/daemon/daemon-pty-write-settlement-recovery.test.ts src/main/runtime/runtime-terminal-writer.test.ts src/main/runtime/rpc/terminal-send.test.ts src/main/runtime/rpc/terminal-send-launch-draft-resolution.test.ts src/main/runtime/terminal-send-stale-leaf-liveness.test.ts src/renderer/src/lib/agent-paste-draft-readiness-budget.test.ts tests/e2e/native-chat-ssh-delivery.unit.test.ts --maxWorkers=2", + "currentCommand": "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/renderer/src/components/native-chat/NativeChatInteractiveCard.test.tsx src/renderer/src/components/native-chat/use-native-chat-interactive-send.test.tsx src/renderer/src/components/native-chat/native-chat-observed-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send.test.ts src/renderer/src/components/native-chat/native-chat-runtime-send-launch-draft.test.ts src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-input.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.prompt-card-composer.test.tsx src/renderer/src/components/native-chat/use-native-chat-prompt-card-presentation.test.ts src/renderer/src/components/native-chat/NativeChatComposer.test.tsx src/renderer/src/components/native-chat/NativeChatResolvedView.turn-status.test.tsx src/renderer/src/components/native-chat/NativeChatApprovalCard.test.tsx src/renderer/src/components/native-chat/native-chat-interactive-prompt.test.ts src/renderer/src/runtime/runtime-terminal-inspection.test.ts src/renderer/src/lib/agent-paste-draft.test.ts src/renderer/src/lib/agent-paste-draft-submit-retry.test.ts src/renderer/src/lib/agent-followup-delivery.test.ts src/main/ipc/pty/ipc/write-input-acceptance.test.ts src/main/ipc/pty/ipc/write-input-user-input.test.ts src/main/ipc/pty/ipc/write-input-chunk-yield.test.ts src/main/ipc/pty/pty-write-ipc-validation.test.ts src/main/daemon/daemon-pty-write-settlement-recovery.test.ts src/main/runtime/runtime-terminal-writer.test.ts src/main/runtime/rpc/terminal-send.test.ts src/main/runtime/rpc/terminal-send-launch-draft-resolution.test.ts src/main/runtime/terminal-send-stale-leaf-liveness.test.ts src/renderer/src/lib/agent-paste-draft-readiness-budget.test.ts tests/e2e/native-chat-ssh-delivery.unit.test.ts --maxWorkers=2", "result": "passed", "durationSeconds": 14.53, "summary": "391 tests passed across 29 explicit files after the round-4 review fix, including older-host acceptance, the inert hidden composer, collapse that keeps a partial answer and returns focus to the composer, pane-scoped card focus, wait-start occurrence identity and the pane remount signal." @@ -10569,12 +10568,6 @@ "explicit stop, real exit status, and genuine successful completion remain distinct" ] }, - { - "file": "src/renderer/src/runtime/runtime-terminal-inspection.test.ts", - "assertions": [ - "direct SSH terminals use strict main-process inspection rather than lax split IPC evidence" - ] - }, { "file": "src/renderer/src/components/terminal-pane/pty-connection-completion-and-notification.test.ts", "assertions": [ @@ -17544,12 +17537,6 @@ "malformed frames, malformed transformed output, disposal, late parse, renderer delivery failure, and ACK transport failure release credit or close the owning stream without reordering output" ] }, - { - "file": "src/renderer/src/runtime/runtime-terminal-stream.test.ts", - "assertions": [ - "drops output only from the armed stream when its replacement reuses the stream ID" - ] - }, { "file": "src/main/runtime/rpc/terminal-multiplex-flow-control.bench.test.ts", "assertions": [ diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index 5ffb642ea82..43ba14a19c6 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -10677,7 +10677,6 @@ "src/renderer/src/lib/monaco-languages/register-svelte.test.ts": 121, "src/renderer/src/lib/monaco-languages/register-vue.test.ts": 157, "src/renderer/src/lib/monaco-languages/register-zig.test.ts": 3891, - "src/renderer/src/lib/monaco-languages/textmate-language-registration.test.ts": 37, "src/renderer/src/lib/monaco-languages/textmate-token-provider.test.ts": 233, "src/renderer/src/lib/monaco-languages/zig-highlighting.test.ts": 4871, "src/renderer/src/lib/monaco-setup-steps.test.ts": 48, @@ -11192,7 +11191,6 @@ "src/renderer/src/runtime/remote-runtime-session-tabs-inflight.test.ts": 26, "src/renderer/src/runtime/remote-runtime-snapshot-outcome.test.ts": 226, "src/renderer/src/runtime/remote-runtime-terminal-color-push.test.ts": 179, - "src/renderer/src/runtime/remote-runtime-terminal-end-verdict.test.ts": 278, "src/renderer/src/runtime/remote-runtime-terminal-frame-drop-resync.test.ts": 214, "src/renderer/src/runtime/remote-runtime-terminal-parse-backpressure.test.ts": 998, "src/renderer/src/runtime/remote-runtime-terminal-paused-output-drop.test.ts": 169, @@ -11263,7 +11261,6 @@ "src/renderer/src/runtime/runtime-terminal-artifact-read.test.ts": 196, "src/renderer/src/runtime/runtime-terminal-inspection.test.ts": 1950, "src/renderer/src/runtime/runtime-terminal-stream.test.ts": 638, - "src/renderer/src/runtime/runtime-terminal-verified-input.test.ts": 1206, "src/renderer/src/runtime/runtime-usage-credentials-client.test.ts": 37, "src/renderer/src/runtime/runtime-worktree-selector.test.ts": 130, "src/renderer/src/runtime/server-browser-profile-reuse.test.ts": 1580, diff --git a/src/renderer/src/lib/monaco-languages/textmate-language-registration.test.ts b/src/renderer/src/lib/monaco-languages/textmate-language-registration.test.ts deleted file mode 100644 index 8f84379d938..00000000000 --- a/src/renderer/src/lib/monaco-languages/textmate-language-registration.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import { registerTextMateLanguage } from './textmate-language-registration' - -function createMonacoMock(registeredLanguages: { id: string }[] = []) { - let tokensProviderFactory: { create: () => unknown } | undefined - const monaco = { - languages: { - getLanguages: vi.fn(() => registeredLanguages), - register: vi.fn(), - setLanguageConfiguration: vi.fn(), - registerTokensProviderFactory: vi.fn( - (_languageId: string, factory: { create: () => unknown }) => { - tokensProviderFactory = factory - return { dispose: vi.fn() } - } - ) - } - } - - return { - monaco, - createTokensProvider() { - if (!tokensProviderFactory) { - throw new Error('Tokens provider factory was not registered') - } - return tokensProviderFactory.create() - } - } -} - -describe('registerTextMateLanguage', () => { - it('registers metadata and lazily installs the TextMate tokens provider', async () => { - const { monaco, createTokensProvider } = createMonacoMock() - const provider = { - getInitialState: vi.fn(), - tokenize: vi.fn() - } - const createTextMateTokensProvider = vi.fn(async () => provider) - const loadProviderModule = vi.fn(async () => ({ createTextMateTokensProvider })) - const loadGrammar = vi.fn() - const configuration = { comments: { lineComment: '#' } } - - registerTextMateLanguage(monaco as never, { - language: { - id: 'nim', - extensions: ['.nim'], - aliases: ['Nim'] - }, - configuration, - loadGrammar, - loadProviderModule - }) - - expect(monaco.languages.register).toHaveBeenCalledWith({ - id: 'nim', - extensions: ['.nim'], - aliases: ['Nim'] - }) - expect(monaco.languages.setLanguageConfiguration).toHaveBeenCalledWith('nim', configuration) - expect(monaco.languages.registerTokensProviderFactory).toHaveBeenCalledWith( - 'nim', - expect.objectContaining({ create: expect.any(Function) }) - ) - expect(loadProviderModule).not.toHaveBeenCalled() - - const providerPromise = createTokensProvider() - expect(createTokensProvider()).toBe(providerPromise) - - await expect(providerPromise).resolves.toBe(provider) - expect(createTokensProvider()).toBe(providerPromise) - expect(loadProviderModule).toHaveBeenCalledTimes(1) - expect(createTextMateTokensProvider).toHaveBeenCalledTimes(1) - expect(createTextMateTokensProvider).toHaveBeenCalledWith({ loadGrammar }) - }) - - it('does not register duplicate language ids', () => { - const { monaco } = createMonacoMock([{ id: 'nim' }]) - - registerTextMateLanguage(monaco as never, { - language: { - id: 'nim', - extensions: ['.nim'] - }, - loadGrammar: vi.fn() - }) - - expect(monaco.languages.register).not.toHaveBeenCalled() - expect(monaco.languages.registerTokensProviderFactory).not.toHaveBeenCalled() - }) -}) diff --git a/src/renderer/src/lib/monaco-languages/zig-highlighting.test.ts b/src/renderer/src/lib/monaco-languages/zig-highlighting.test.ts index bc0e867096c..1e2b6fc061c 100644 --- a/src/renderer/src/lib/monaco-languages/zig-highlighting.test.ts +++ b/src/renderer/src/lib/monaco-languages/zig-highlighting.test.ts @@ -46,14 +46,4 @@ describe('Zig highlighting through production Monaco setup', () => { expect(tokens[6].map((token) => token.type)).toContain('keyword.zig') expect(tokens[6].map((token) => token.type)).not.toContain('string.multiline.zig') }) - - it('keeps unrelated languages and unclaimed Zig object notation unchanged', async () => { - expect(detectLanguage('build.zig.zon')).toBe('plaintext') - expect(detectLanguage('main.rs')).toBe('rust') - expect(detectLanguage('main.c')).toBe('c') - await monaco.editor.colorize('const answer = 42', 'typescript', {}) - expect( - monaco.editor.tokenize('const answer = 42', 'typescript')[0].map((token) => token.type) - ).toEqual(expect.arrayContaining(['keyword.ts', 'number.ts'])) - }) }) diff --git a/src/renderer/src/runtime/remote-runtime-terminal-end-verdict.test.ts b/src/renderer/src/runtime/remote-runtime-terminal-end-verdict.test.ts deleted file mode 100644 index 646b1e3a6e8..00000000000 --- a/src/renderer/src/runtime/remote-runtime-terminal-end-verdict.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { stubRuntimeEnvironmentBridge } from './runtime-environment-bridge-fixture' - -type RuntimeSubscriptionCallbacks = { - onResponse: (response: unknown) => void -} - -describe('remote runtime terminal end verdict', () => { - let callbacks: RuntimeSubscriptionCallbacks | null = null - - beforeEach(() => { - vi.resetModules() - callbacks = null - stubRuntimeEnvironmentBridge({ - subscribe: vi.fn(async (_args, nextCallbacks: RuntimeSubscriptionCallbacks) => { - callbacks = nextCallbacks - queueMicrotask(() => { - callbacks?.onResponse({ ok: true, result: { type: 'ready' } }) - }) - return { unsubscribe: vi.fn(), sendBinary: vi.fn() } - }) - }) - }) - - afterEach(() => { - vi.unstubAllGlobals() - }) - - it.each([ - ['an explicit host verdict', { verdict: 'exited' }, 'exited'], - ['a legacy bare end', {}, 'unverifiable'], - ['an unknown future verdict', { verdict: 'unknown' }, 'unverifiable'] - ])('maps %s to %s', async (_case, fields, expected) => { - const { getRemoteRuntimeTerminalMultiplexer } = - await import('./remote-runtime-terminal-multiplexer') - const onEnd = vi.fn() - const stream = await getRemoteRuntimeTerminalMultiplexer('env-1').subscribeTerminal({ - terminal: 'terminal-1', - client: { id: 'desktop-1', type: 'desktop' }, - callbacks: { onData: vi.fn(), onSnapshot: vi.fn(), onEnd } - }) - - callbacks?.onResponse({ - ok: true, - result: { type: 'end', streamId: stream.streamId, ...fields } - }) - - expect(onEnd).toHaveBeenCalledWith(expected) - }) -}) diff --git a/src/renderer/src/runtime/runtime-file-drop-staging-ignore.test.ts b/src/renderer/src/runtime/runtime-file-drop-staging-ignore.test.ts index c8536060523..5785a51f13a 100644 --- a/src/renderer/src/runtime/runtime-file-drop-staging-ignore.test.ts +++ b/src/renderer/src/runtime/runtime-file-drop-staging-ignore.test.ts @@ -22,13 +22,6 @@ const notFoundResponse = (id: string): unknown => ({ _meta: { runtimeId: 'remote-runtime' } }) -const failedResponse = (id: string): unknown => ({ - id, - ok: false, - error: { code: 'permission_denied', message: 'read-only file system' }, - _meta: { runtimeId: 'remote-runtime' } -}) - const statResponse = (id: string): unknown => ({ id, ok: true, @@ -121,66 +114,6 @@ describe('drop staging ignore file', () => { expect(methods.indexOf('files.write')).toBeLessThan(methods.indexOf('files.commitUpload')) }) - it('leaves an existing ignore file alone', async () => { - stageOneFile() - runtimeEnvironmentCall - .mockResolvedValueOnce(statResponse('stat-orca-hit')) - .mockResolvedValueOnce(statResponse('stat-drops-hit')) - .mockResolvedValueOnce(statResponse('stat-ignore-hit')) - .mockResolvedValueOnce(notFoundResponse('stat-file-miss')) - .mockResolvedValueOnce(okResponse('commit-upload')) - .mockResolvedValueOnce(okResponse('delete-temp')) - - await importExternalPathsToRuntime(CONTEXT, ['/Users/me/shot.png'], '/remote/repo/.orca/drops') - - expect(calledMethods().some((call) => call.method === 'files.write')).toBe(false) - }) - - it('still uploads the drop when the ignore file cannot be written', async () => { - stageOneFile() - runtimeEnvironmentCall - .mockResolvedValueOnce(statResponse('stat-orca-hit')) - .mockResolvedValueOnce(statResponse('stat-drops-hit')) - .mockResolvedValueOnce(notFoundResponse('stat-ignore-miss')) - .mockResolvedValueOnce(failedResponse('write-ignore-denied')) - .mockResolvedValueOnce(notFoundResponse('stat-file-miss')) - .mockResolvedValueOnce(okResponse('commit-upload')) - .mockResolvedValueOnce(okResponse('delete-temp')) - - const { results } = await importExternalPathsToRuntime( - CONTEXT, - ['/Users/me/shot.png'], - '/remote/repo/.orca/drops' - ) - - expect(results).toEqual([expect.objectContaining({ status: 'imported' })]) - }) - - it('recognizes the drops folder of a Windows worktree', async () => { - stageOneFile() - runtimeEnvironmentCall - .mockResolvedValueOnce(statResponse('stat-orca-hit')) - .mockResolvedValueOnce(statResponse('stat-drops-hit')) - .mockResolvedValueOnce(notFoundResponse('stat-ignore-miss')) - .mockResolvedValueOnce(okResponse('write-ignore')) - .mockResolvedValueOnce(notFoundResponse('stat-file-miss')) - .mockResolvedValueOnce(okResponse('commit-upload')) - .mockResolvedValueOnce(okResponse('delete-temp')) - - await importExternalPathsToRuntime( - { ...CONTEXT, worktreePath: 'C:\\Users\\me\\repo' }, - ['/Users/me/shot.png'], - 'C:\\Users\\me\\repo\\.orca\\drops' - ) - - expect(calledMethods().filter((call) => call.method === 'files.write')).toEqual([ - { - method: 'files.write', - params: expect.objectContaining({ relativePath: '.orca/drops/.gitignore', content: '*\n' }) - } - ]) - }) - // Why: the ignore step swallows its own errors, and a drop with nothing staged never re-checks. it('reports a host that went stale during the ignore step even when nothing was staged', async () => { fsStageExternalPathsForRuntimeUpload.mockResolvedValue({ @@ -207,17 +140,4 @@ describe('drop staging ignore file', () => { }) ).rejects.toThrow('runtime owner generation changed') }) - - it('never writes an ignore file into a folder the user picked', async () => { - stageOneFile() - runtimeEnvironmentCall - .mockResolvedValueOnce(statResponse('stat-uploads-hit')) - .mockResolvedValueOnce(notFoundResponse('stat-file-miss')) - .mockResolvedValueOnce(okResponse('commit-upload')) - .mockResolvedValueOnce(okResponse('delete-temp')) - - await importExternalPathsToRuntime(CONTEXT, ['/Users/me/shot.png'], '/remote/repo/uploads') - - expect(calledMethods().some((call) => call.method === 'files.write')).toBe(false) - }) }) diff --git a/src/renderer/src/runtime/runtime-file-write-disk-precondition.test.ts b/src/renderer/src/runtime/runtime-file-write-disk-precondition.test.ts index 738fc8a817a..ea3077d2bd3 100644 --- a/src/renderer/src/runtime/runtime-file-write-disk-precondition.test.ts +++ b/src/renderer/src/runtime/runtime-file-write-disk-precondition.test.ts @@ -13,7 +13,6 @@ import { getDiskBaselineSignature } from '../../../shared/disk-baseline-signatur import { advanceRuntimeEnvironmentConnectionGeneration } from '@/store/slices/runtime-status-connection-generation' import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' import { - fsWriteFile, installRuntimeFileClientEnvironment, runtimeEnvironmentCall, runtimeEnvironmentTransportCall, @@ -91,23 +90,6 @@ function writeCalls(): RuntimeRpcRequest[] { } describe('writeRuntimeFile disk precondition', () => { - it('sends the precondition to a local writer and returns its refusal', async () => { - fsWriteFile.mockResolvedValue({ ok: false, diskConflict: 'changed' }) - - const result = await writeRuntimeFile( - { target: { kind: 'local' }, worktreeId: 'wt-1', worktreePath: '/repo' }, - '/repo/file.ts', - 'edited', - undefined, - precondition - ) - - expect(result).toEqual({ ok: false, diskConflict: 'changed' }) - expect(fsWriteFile).toHaveBeenCalledWith( - expect.objectContaining({ diskPrecondition: precondition }) - ) - }) - it('cannot write through an older server reached after a supporting server was probed', async () => { // The shared socket reconnected to an older server between the capability verdict and the send. serveHost({ enforcesPrecondition: true }) @@ -131,26 +113,6 @@ describe('writeRuntimeFile disk precondition', () => { expect(unguardedWrites).toHaveLength(0) }) - it('lets a host that enforces the precondition compare at write time', async () => { - serveHost({ enforcesPrecondition: true }) - runtimeEnvironmentCall.mockResolvedValue(rpcOk({ ok: false, diskConflict: 'missing' })) - - const result = await writeRuntimeFile( - remoteContext, - '/remote/repo/file.ts', - 'edited', - undefined, - precondition - ) - - expect(result).toEqual({ ok: false, diskConflict: 'missing' }) - expect(writeCalls()).toHaveLength(1) - expect(writeCalls()[0]?.params).toMatchObject({ diskPrecondition: precondition }) - expect(runtimeEnvironmentTransportCall).not.toHaveBeenCalledWith( - expect.objectContaining({ method: 'files.read' }) - ) - }) - it('compares from the client before writing through an older host', async () => { serveHost({ enforcesPrecondition: false, diskContent: 'original' }) runtimeEnvironmentCall.mockResolvedValue(rpcOk({ ok: true })) @@ -168,28 +130,6 @@ describe('writeRuntimeFile disk precondition', () => { expect(writeCalls()[0]?.params).not.toHaveProperty('diskPrecondition') }) - it("decides support from the write path's own status probe, one per save", async () => { - serveHost({ enforcesPrecondition: false, diskContent: 'original' }) - runtimeEnvironmentCall.mockResolvedValue(rpcOk({ ok: true })) - - for (let save = 0; save < 3; save += 1) { - await writeRuntimeFile( - remoteContext, - '/remote/repo/file.ts', - 'edited', - undefined, - precondition - ) - } - - const statusCalls = runtimeEnvironmentTransportCall.mock.calls.filter( - ([args]) => args.method === 'status.get' - ) - // One ownership probe per save plus the read client's one-time compatibility probe. - expect(statusCalls).toHaveLength(4) - expect(writeCalls()).toHaveLength(3) - }) - it('refuses without writing when an older host holds newer disk content', async () => { serveHost({ enforcesPrecondition: false, diskContent: 'agent rewrite' }) @@ -205,22 +145,6 @@ describe('writeRuntimeFile disk precondition', () => { expect(writeCalls()).toHaveLength(0) }) - it('skips writing through an older host whose changed disk already holds the text', async () => { - serveHost({ enforcesPrecondition: false, diskContent: 'edited' }) - runtimeEnvironmentCall.mockResolvedValue(rpcOk({ ok: true })) - - const result = await writeRuntimeFile( - remoteContext, - '/remote/repo/file.ts', - 'edited', - undefined, - precondition - ) - - expect(result).toEqual({ ok: true, unchanged: true }) - expect(writeCalls()).toHaveLength(0) - }) - it.each(['original', 'edited'])( 'skips identical content on a v1 guarded host for an automatic save (baseline %s)', async (baseline) => { @@ -235,32 +159,6 @@ describe('writeRuntimeFile disk precondition', () => { } ) - it('keeps the v1 host guard for non-identical automatic saves after comparing locally', async () => { - serveHost({ enforcesPrecondition: true, identicalNoop: false, diskContent: 'original' }) - runtimeEnvironmentCall.mockResolvedValue(rpcOk({ ok: false, diskConflict: 'changed' })) - expect( - await writeRuntimeFile(remoteContext, '/remote/repo/file.ts', 'edited', undefined, { - ...precondition, - requireLosslessUtf8: true - }) - ).toEqual({ ok: false, diskConflict: 'changed' }) - expect(writeCalls()[0]?.method).toBe('files.writeIfUnchanged') - }) - - it('sends an explicit save straight to a v1 guarded host without reading first', async () => { - let reads = 0 - serveHost({ - enforcesPrecondition: true, - identicalNoop: false, - diskContent: 'edited', - onRead: () => (reads += 1) - }) - runtimeEnvironmentCall.mockResolvedValue(rpcOk({ ok: true })) - await writeRuntimeFile(remoteContext, '/remote/repo/file.ts', 'edited', undefined, precondition) - expect(reads).toBe(0) - expect(writeCalls()[0]?.method).toBe('files.writeIfUnchanged') - }) - it('refuses an ambiguous automatic baseline before sending to a v1 host', async () => { serveHost({ enforcesPrecondition: true, identicalNoop: false, diskContent: 'a�' }) expect( @@ -318,36 +216,6 @@ describe('writeRuntimeFile disk precondition', () => { expect(writeCalls()).toHaveLength(0) }) - it('reports a file an older host can no longer send as changed', async () => { - serveHost({ - enforcesPrecondition: false, - readError: 'File too large: 60.0MB exceeds 50MB limit' - }) - - const result = await writeRuntimeFile( - remoteContext, - '/remote/repo/file.ts', - 'edited', - undefined, - { - ...precondition, - allowMissing: true - } - ) - - expect(result).toEqual({ ok: false, diskConflict: 'changed' }) - expect(writeCalls()).toHaveLength(0) - }) - - it('binds a guarded write to the runtime whose capabilities were probed', async () => { - serveHost({ enforcesPrecondition: true }) - runtimeEnvironmentCall.mockResolvedValue(rpcOk({ ok: true })) - - await writeRuntimeFile(remoteContext, '/remote/repo/file.ts', 'edited', undefined, precondition) - - expect(writeCalls()[0]).toMatchObject({ expectedEnvironmentRuntimeId: 'remote-runtime' }) - }) - it('refuses to send when the runtime connection changes after the probe', async () => { serveHost({ enforcesPrecondition: false, diff --git a/src/renderer/src/runtime/runtime-legacy-inventory-budget.test.ts b/src/renderer/src/runtime/runtime-legacy-inventory-budget.test.ts index d274e668fc0..9795586b86f 100644 --- a/src/renderer/src/runtime/runtime-legacy-inventory-budget.test.ts +++ b/src/renderer/src/runtime/runtime-legacy-inventory-budget.test.ts @@ -1,8 +1,5 @@ import { describe, expect, it } from 'vitest' -import { - decodeLegacyQuickOpenInventory, - pruneLegacyInventoryCache -} from './runtime-legacy-inventory-budget' +import { decodeLegacyQuickOpenInventory } from './runtime-legacy-inventory-budget' function inventory(count = 1) { return { @@ -37,28 +34,4 @@ describe('complete legacy inventory retention', () => { value.files[0].relativePath = 'x'.repeat(65_537) expect(() => decodeLegacyQuickOpenInventory(value)).toThrow('too large') }) - it.each([ - null, - { files: [] }, - { ...inventory(), totalCount: 0 }, - { ...inventory(), files: [{ relativePath: 12 }] } - ])('rejects malformed responses %j', (value) => { - expect(() => decodeLegacyQuickOpenInventory(value)).toThrow('Invalid remote file inventory') - }) - it('evicts in access order under a shared byte allowance and releases removed accounting', () => { - const cache = new Map([ - ['one', { retainedBytes: 60 }], - ['two', { retainedBytes: 60 }] - ]) - pruneLegacyInventoryCache(cache, 8, 100) - expect([...cache.keys()]).toEqual(['two']) - cache.delete('two') - cache.set('three', { retainedBytes: 100 }) - pruneLegacyInventoryCache(cache, 8, 100) - expect([...cache.keys()]).toEqual(['three']) - cache.set('three', { retainedBytes: 10 }) - cache.set('owner-changed', { retainedBytes: 90 }) - pruneLegacyInventoryCache(cache, 8, 100) - expect(cache.size).toBe(2) - }) }) diff --git a/src/renderer/src/runtime/runtime-legacy-quick-open-inventory-expiry.test.ts b/src/renderer/src/runtime/runtime-legacy-quick-open-inventory-expiry.test.ts index bba392e47b4..2ae2a451534 100644 --- a/src/renderer/src/runtime/runtime-legacy-quick-open-inventory-expiry.test.ts +++ b/src/renderer/src/runtime/runtime-legacy-quick-open-inventory-expiry.test.ts @@ -164,20 +164,6 @@ describe('legacy Quick Open inventory expiry', () => { expect(vi.getTimerCount()).toBe(1) }) - it('starts the settled deadline when the inventory arrives', async () => { - const load = queueLoad() - const pending = search() - expect(vi.getTimerCount()).toBe(0) - vi.advanceTimersByTime(5_000) - load.resolve(listing()) - await pending - vi.advanceTimersByTime(29_999) - expect(cached()).toBe(true) - vi.advanceTimersByTime(1) - expect(cached()).toBe(false) - expect(vi.getTimerCount()).toBe(0) - }) - it('sweeps settled responses while leaving shared pending loads valid', async () => { call.mockResolvedValueOnce(listing('settled')) await search('settled') @@ -286,17 +272,6 @@ describe('legacy Quick Open inventory expiry', () => { expect(vi.getTimerCount()).toBe(1) }) - it('retries failed requests without keeping an expiry timer for their response', async () => { - call.mockRejectedValueOnce(new Error('host failed')) - await expect(search()).rejects.toThrow('host failed') - expect(cached()).toBe(false) - expect(vi.getTimerCount()).toBe(0) - call.mockResolvedValueOnce(listing()) - await search() - expect(cached()).toBe(true) - expect(vi.getTimerCount()).toBe(1) - }) - it('replaces a longer armed deadline after a backward clock change and a new settlement', async () => { const timeout = vi.spyOn(globalThis, 'setTimeout') call.mockImplementation(async () => listing()) diff --git a/src/renderer/src/runtime/runtime-paged-file-read.test.ts b/src/renderer/src/runtime/runtime-paged-file-read.test.ts index faabd93cc4d..39fb36cf70c 100644 --- a/src/renderer/src/runtime/runtime-paged-file-read.test.ts +++ b/src/renderer/src/runtime/runtime-paged-file-read.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { readRuntimeFileContent, readRuntimeFilePreview } from './runtime-file-read-client' +import { readRuntimeFileContent } from './runtime-file-read-client' import { writeRuntimeFile } from './runtime-file-mutation-client' import { installRuntimeFileClientEnvironment, @@ -7,7 +7,6 @@ import { type RuntimeRpcRequest } from './runtime-file-client-test-harness' import { REMOTE_FILE_CHANGED_DURING_READ_MESSAGE } from './runtime-paged-file-read' -import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' installRuntimeFileClientEnvironment() @@ -168,19 +167,6 @@ describe('remote reads larger than one RPC reply', () => { expect(methodCalls('files.readChunk').length > 0).toBe(sizeMb * MB > PREVIEW_CAP) }) - it('pages an image preview too large for one reply', async () => { - const bytes = patternedBytes(5 * MB) - serveRemoteFile('shot.png', { bytes }) - - const result = await readRuntimeFilePreview( - { target: remote('shot.png').target, worktreeId: 'wt-1', worktreePath: '/remote/repo' }, - '/remote/repo/shot.png' - ) - - expect(result).toMatchObject({ isBinary: true, isImage: true, mimeType: 'image/png' }) - expect(Buffer.from(result.content, 'base64').equals(bytes)).toBe(true) - }) - it('leaves a large PDF alone for readers that discard binary content', async () => { serveRemoteFile('paper.pdf', { bytes: patternedBytes(5 * MB) }) @@ -256,43 +242,6 @@ describe('remote reads larger than one RPC reply', () => { ) }) - it('pins every call of one paged read to the pairing it started on', async () => { - replaceRuntimeEnvironmentRevisions([{ id: 'env-1', createdAt: 1, pairingRevision: 7 }]) - const bytes = htmlBytes(2 * MB) - serveRemoteFile('report.html', { - bytes, - readChunk: (params, file) => { - // A re-pair mid-read must not retarget the remaining chunks. - replaceRuntimeEnvironmentRevisions([{ id: 'env-1', createdAt: 1, pairingRevision: 8 }]) - return sliceChunk(params, file) - } - }) - - await readRuntimeFileContent(remote('report.html')) - - const paged = [...methodCalls('files.stat'), ...methodCalls('files.readChunk')] - expect(paged.length).toBeGreaterThan(2) - expect(paged.every((call) => call.expectedEnvironmentPairingRevision === 7)).toBe(true) - }) - - it('keeps the pairing of the first read when a re-pair lands during it', async () => { - replaceRuntimeEnvironmentRevisions([{ id: 'env-1', createdAt: 1, pairingRevision: 7 }]) - serveRemoteFile('report.html', { bytes: htmlBytes(2 * MB) }) - const serve = runtimeEnvironmentCall.getMockImplementation() - runtimeEnvironmentCall.mockImplementation((request: RuntimeRpcRequest) => { - if (request.method === 'files.read') { - replaceRuntimeEnvironmentRevisions([{ id: 'env-1', createdAt: 1, pairingRevision: 8 }]) - } - return serve?.(request) - }) - - await readRuntimeFileContent(remote('report.html')) - - const calls = runtimeEnvironmentCall.mock.calls.map(([request]) => request) - expect(calls.length).toBeGreaterThan(3) - expect(calls.every((call) => call.expectedEnvironmentPairingRevision === 7)).toBe(true) - }) - it('stops when the host never reports EOF', async () => { const bytes = htmlBytes(2 * MB) serveRemoteFile('report.html', { @@ -325,13 +274,6 @@ describe('remote saves larger than one request frame', () => { worktreePath: '/remote/repo' } - it('refuses a save the host would answer by closing the connection', async () => { - await expect( - writeRuntimeFile(context, '/remote/repo/report.html', htmlBytes(2 * MB).toString('utf8')) - ).rejects.toThrow('File is too large to save to a remote Orca server') - expect(runtimeEnvironmentCall).not.toHaveBeenCalled() - }) - it('counts JSON escaping, not just characters', async () => { await expect( writeRuntimeFile(context, '/remote/repo/quotes.txt', '"'.repeat(400 * 1024)) diff --git a/src/renderer/src/runtime/runtime-quick-open-version-compatibility.test.ts b/src/renderer/src/runtime/runtime-quick-open-version-compatibility.test.ts index 35ad9186249..26308e23676 100644 --- a/src/renderer/src/runtime/runtime-quick-open-version-compatibility.test.ts +++ b/src/renderer/src/runtime/runtime-quick-open-version-compatibility.test.ts @@ -1,4 +1,4 @@ -import { expect, it, vi } from 'vitest' +import { expect, it } from 'vitest' import { searchRuntimeFilePaths, listRuntimeFiles } from './runtime-file-search-client' import { installRuntimeFileClientEnvironment, @@ -7,30 +7,6 @@ import { } from './runtime-file-client-test-harness' installRuntimeFileClientEnvironment() -it('accepts a future compatible search version rather than falling back on exact-version inequality', async () => { - runtimeEnvironmentCall.mockResolvedValue({ - id: 'compat', - ok: true, - _meta: { runtimeId: 'host' }, - result: { - files: [{ relativePath: 'apps/late/.env' }], - truncated: false, - quickOpenSearchVersion: 4 - } - }) - await expect( - searchRuntimeFilePaths( - { - target: { kind: 'environment' as const, environmentId: 'env-1' }, - worktreeId: 'future-host', - worktreePath: '/host/repo' - }, - { query: '.env late' } - ) - ).resolves.toEqual({ files: ['apps/late/.env'], truncated: false }) - expect(runtimeEnvironmentCall).toHaveBeenCalledOnce() -}) - it('validates default-policy recent paths on a version-two host through complete legacy inventory', async () => { runtimeEnvironmentCall.mockImplementation(({ method }) => Promise.resolve({ @@ -66,34 +42,6 @@ it('validates default-policy recent paths on a version-two host through complete expect(fsListFiles).not.toHaveBeenCalled() }) -it('sends bounded candidates only after a compatible host advertises their semantics', async () => { - runtimeEnvironmentCall.mockImplementation(({ method }) => - Promise.resolve({ - id: 'compat', - ok: true, - _meta: { runtimeId: 'host' }, - result: - method === 'files.searchPaths' - ? { files: [], truncated: false, quickOpenSearchVersion: 3 } - : ['src/recent.ts'] - }) - ) - await expect( - listRuntimeFiles( - { - target: { kind: 'environment' as const, environmentId: 'env-1' }, - worktreeId: 'recent-new', - worktreePath: '/host/repo' - }, - { rootPath: '/host/repo', candidatePaths: ['src/recent.ts'], maxResults: 1 } - ) - ).resolves.toEqual(['src/recent.ts']) - expect(runtimeEnvironmentCall.mock.calls[1][0]).toMatchObject({ - method: 'files.listAll', - params: { worktree: 'id:recent-new', candidatePaths: ['src/recent.ts'], maxResults: 1 } - }) -}) - it('refuses to infer recent eligibility from a truncated old-host inventory', async () => { runtimeEnvironmentCall.mockImplementation(({ method }) => Promise.resolve({ @@ -125,179 +73,6 @@ it('refuses to infer recent eligibility from a truncated old-host inventory', as expect(fsListFiles).not.toHaveBeenCalled() }) -it.each(['missing-search', 'old-search'] as const)( - 'translates only unavailable inventory errors after %s', - async (route) => { - const context = { - target: { kind: 'environment' as const, environmentId: 'env-1' }, - worktreeId: 'fallback-errors', - worktreePath: '/host/repo' - } - for (const code of ['method_not_found', 'forbidden', 'remote_runtime_unavailable']) { - runtimeEnvironmentCall.mockImplementation(({ method }) => - Promise.resolve({ - id: 'compat', - _meta: { runtimeId: 'host' }, - ...(method === 'files.searchPaths' && route === 'old-search' - ? { ok: true, result: { files: [], truncated: false, quickOpenSearchVersion: 1 } } - : { - ok: false, - error: { - code: method === 'files.searchPaths' ? 'method_not_found' : code, - message: 'inventory failed' - } - }) - }) - ) - const search = searchRuntimeFilePaths(context, { query: 'two terms' }) - await (route === 'old-search' - ? expect(search).resolves.toEqual({ files: [], truncated: false }) - : expect(search).rejects.toThrow( - code === 'method_not_found' ? 'Update the remote host' : 'inventory failed' - )) - } - } -) - -it('preserves raw errors when joining a cached pending legacy inventory', async () => { - const context = { - target: { kind: 'environment' as const, environmentId: 'env-1' }, - worktreeId: 'cached-errors', - worktreePath: '/host/repo' - } - const inventory = Promise.withResolvers() - runtimeEnvironmentCall.mockImplementation(({ method }) => - method === 'files.list' - ? inventory.promise - : Promise.resolve({ - id: 'compat', - ok: false, - _meta: { runtimeId: 'host' }, - error: { code: 'method_not_found', message: 'search unavailable' } - }) - ) - const first = searchRuntimeFilePaths(context, { query: 'two terms' }) - const translated = expect(first).rejects.toThrow('Update the remote host') - await vi.waitFor(() => - expect(runtimeEnvironmentCall.mock.calls.map(([request]) => request.method)).toContain( - 'files.list' - ) - ) - const cached = searchRuntimeFilePaths(context, { query: 'other terms' }) - const raw = expect(cached).rejects.toThrow('raw cached failure') - inventory.resolve({ - id: 'compat', - ok: false, - _meta: { runtimeId: 'host' }, - error: { code: 'method_not_found', message: 'raw cached failure' } - }) - await Promise.all([translated, raw]) - expect(runtimeEnvironmentCall.mock.calls.map(([request]) => request.method)).toEqual([ - 'files.searchPaths', - 'files.list' - ]) -}) - -it.each(['method_not_found', 'file_inventory_capacity', 'remote_runtime_unavailable'])( - 'does not require optional inventory to return existing old-host punctuation matches (%s)', - async (code) => { - runtimeEnvironmentCall.mockImplementation(({ method }) => - Promise.resolve({ - id: 'compat', - _meta: { runtimeId: 'host' }, - ...(method === 'files.searchPaths' - ? { - ok: true, - result: { - rootPath: '/host/repo', - files: [{ relativePath: 'late/package-lock.json' }], - truncated: false, - quickOpenSearchVersion: 1 - } - } - : { ok: false, error: { code, message: 'inventory unavailable' } }) - }) - ) - await expect( - searchRuntimeFilePaths( - { - target: { kind: 'environment' as const, environmentId: 'env-1' }, - worktreeId: `punctuation-${code}`, - worktreePath: '/host/repo' - }, - { query: 'package-lock' } - ) - ).resolves.toEqual({ files: ['late/package-lock.json'], truncated: false }) - expect(runtimeEnvironmentCall).toHaveBeenCalledOnce() - } -) - -it.each([{ includeIgnored: false }, { followSymlinks: true }])( - 'uses discovery preferences on a version-two paired host: %j', - async (options) => { - runtimeEnvironmentCall.mockResolvedValue({ - id: 'compat', - _meta: { runtimeId: 'host' }, - ok: true, - result: { - rootPath: '/repo', - files: [{ relativePath: 'src/file.ts' }], - truncated: false, - quickOpenSearchVersion: 2 - } - }) - await expect( - searchRuntimeFilePaths( - { - target: { kind: 'environment' as const, environmentId: 'env-1' }, - worktreeId: 'v2-options', - worktreePath: '/repo' - }, - { query: 'file', ...options } - ) - ).resolves.toEqual({ files: ['src/file.ts'], truncated: false }) - } -) - -it('keeps inherited ignored-file visibility from disabling an older paired host', async () => { - runtimeEnvironmentCall.mockImplementation(({ method }) => - Promise.resolve({ - id: 'compat', - _meta: { runtimeId: 'host' }, - ok: true, - result: - method === 'files.listAll' - ? ['src/file.ts'] - : { - rootPath: '/repo', - files: [{ relativePath: 'src/file.ts' }], - truncated: false, - quickOpenSearchVersion: 1 - } - }) - ) - const context = { - target: { kind: 'environment' as const, environmentId: 'env-1' }, - worktreeId: 'legacy-ignored', - worktreePath: '/repo' - } - await expect( - searchRuntimeFilePaths(context, { - query: 'file', - includeIgnored: false, - allowLegacyIncludeIgnored: true - }) - ).resolves.toEqual({ files: ['src/file.ts'], truncated: false }) - await expect( - listRuntimeFiles(context, { - rootPath: '/repo', - includeIgnored: false, - allowLegacyIncludeIgnored: true - }) - ).resolves.toEqual(['src/file.ts']) - expect(runtimeEnvironmentCall.mock.calls.at(-1)?.[0].params).not.toHaveProperty('includeIgnored') -}) - it('does not reuse unfiltered recent inventory after enabling supported ignore filtering', async () => { runtimeEnvironmentCall.mockImplementation(({ method }) => Promise.resolve({ diff --git a/src/renderer/src/runtime/runtime-terminal-artifact-write.test.ts b/src/renderer/src/runtime/runtime-terminal-artifact-write.test.ts index 96826906635..75d70d5e019 100644 --- a/src/renderer/src/runtime/runtime-terminal-artifact-write.test.ts +++ b/src/renderer/src/runtime/runtime-terminal-artifact-write.test.ts @@ -1,13 +1,11 @@ -import { describe, expect, it, vi } from 'vitest' +import { describe, expect, it } from 'vitest' import { writeRuntimeTerminalArtifactFile } from './runtime-terminal-artifact-write' import { - fsWriteFile, runtimeEnvironmentCall, installRuntimeFileClientEnvironment, type RuntimeRpcRequest } from './runtime-file-client-test-harness' import { getDiskBaselineSignature } from '../../../shared/disk-baseline-signature' -import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' installRuntimeFileClientEnvironment() @@ -55,23 +53,6 @@ function callsTo(method: string): RuntimeRpcRequest[] { } describe('saving a granted host file outside every workspace', () => { - it('writes through the grant when the host still holds the opened text', async () => { - runtimeEnvironmentCall.mockImplementation(async ({ method }) => - method === 'files.readTerminalArtifact' ? read('# old') : ok({ ok: true }) - ) - - await expect(save('# new', '# old')).resolves.toEqual({ ok: true }) - - expect(callsTo('files.writeTerminalArtifact')[0]?.params).toEqual({ - worktree: 'id:wt-1', - grantId: 'g-1', - absolutePath: PATH, - content: '# new' - }) - // Why: a host path must never become a write of this computer's same path. - expect(fsWriteFile).not.toHaveBeenCalled() - }) - it('refuses to overwrite text that changed on the host', async () => { runtimeEnvironmentCall.mockImplementation(async ({ method }) => method === 'files.readTerminalArtifact' ? read('# theirs') : ok({ ok: true }) @@ -81,31 +62,6 @@ describe('saving a granted host file outside every workspace', () => { expect(callsTo('files.writeTerminalArtifact')).toHaveLength(0) }) - it('renews an expired grant and still checks the host text first', async () => { - runtimeEnvironmentCall.mockImplementation(async ({ method, params }) => { - if (method === 'files.resolveTerminalPath') { - return granted('g-2') - } - const grantId = grantIdOf(params) - if (grantId === 'g-1') { - return refused('terminal_file_grant_expired') - } - return method === 'files.readTerminalArtifact' ? read('# old') : ok({ ok: true }) - }) - - const onGrantRenewed = vi.fn() - await expect(save('# new', '# old', onGrantRenewed)).resolves.toEqual({ ok: true }) - - expect(onGrantRenewed).toHaveBeenCalledWith('g-2') - expect(callsTo('files.resolveTerminalPath')[0]?.params).toEqual({ - worktree: 'id:wt-1', - pathText: PATH - }) - expect(callsTo('files.writeTerminalArtifact').map((c) => c.params)).toEqual([ - expect.objectContaining({ grantId: 'g-2', content: '# new' }) - ]) - }) - // Why: a host change stales the grant; the renewed read must still raise the conflict banner. it('reports a host-side change behind a stale grant as a conflict', async () => { runtimeEnvironmentCall.mockImplementation(async ({ method, params }) => { @@ -122,38 +78,6 @@ describe('saving a granted host file outside every workspace', () => { expect(callsTo('files.writeTerminalArtifact')).toHaveLength(0) }) - it('reports a file deleted on its host as missing', async () => { - runtimeEnvironmentCall.mockImplementation(async () => - refused("ENOENT: no such file or directory, open '/private/tmp/handoff.md'") - ) - - await expect(save('# new', '# old')).resolves.toEqual({ ok: false, diskConflict: 'missing' }) - expect(callsTo('files.writeTerminalArtifact')).toHaveLength(0) - }) - - // Why: a same-id re-pair mid-save must not let a renewed grant write the replacement host's file. - it('pins every step of a save to the pairing it started on', async () => { - replaceRuntimeEnvironmentRevisions([{ id: 'env-1', createdAt: 1, pairingRevision: 7 }]) - runtimeEnvironmentCall.mockImplementation(async ({ method, params }) => { - if (method === 'files.resolveTerminalPath') { - return granted('g-2') - } - if (grantIdOf(params) === 'g-1') { - replaceRuntimeEnvironmentRevisions([{ id: 'env-1', createdAt: 2, pairingRevision: 8 }]) - return refused('terminal_file_grant_expired') - } - return method === 'files.readTerminalArtifact' ? read('# old') : ok({ ok: true }) - }) - - await save('# new', '# old').catch(() => undefined) - - const revisions = runtimeEnvironmentCall.mock.calls - .map(([call]) => call) - .filter((call) => call.method !== 'status.get') - .map((call) => call.expectedEnvironmentPairingRevision) - expect(new Set(revisions)).toEqual(new Set([7])) - }) - // Why: a quoted path can spell "not found"; only the error itself proves absence. it('surfaces a permission failure on a path that mentions not found', async () => { runtimeEnvironmentCall.mockImplementation(async () => @@ -182,20 +106,6 @@ describe('saving a granted host file outside every workspace', () => { expect(callsTo('files.writeTerminalArtifact')).toHaveLength(0) }) - // Why: a committed write whose reply was lost must still settle the save, or the next one conflicts. - it('treats a lost reply as saved when the host already holds the new text', async () => { - let written = false - runtimeEnvironmentCall.mockImplementation(async ({ method }) => { - if (method === 'files.writeTerminalArtifact') { - written = true - throw new Error('Request timed out') - } - return read(written ? '# new' : '# old') - }) - - await expect(save('# new', '# old')).resolves.toEqual({ ok: true }) - }) - it('reads back through a fresh grant when the dropped reply also revoked the old one', async () => { let written = false runtimeEnvironmentCall.mockImplementation(async ({ method, params }) => { diff --git a/src/renderer/src/runtime/runtime-terminal-inspection.test.ts b/src/renderer/src/runtime/runtime-terminal-inspection.test.ts index 9057f0f2c4a..0918cdfeb13 100644 --- a/src/renderer/src/runtime/runtime-terminal-inspection.test.ts +++ b/src/renderer/src/runtime/runtime-terminal-inspection.test.ts @@ -11,10 +11,6 @@ import { clearRuntimeCompatibilityCacheForTests } from './runtime-rpc-client' import { TERMINAL_INPUT_MAX_BYTES } from '../../../shared/terminal-input' import { useAppStore } from '../store' import type { RemoteForegroundEvidence } from '../../../shared/foreground-process-evidence' -import { - clientOnlyUnverifiableInspection, - type ClientOnlyUnverifiableInspection -} from '../../../shared/terminal-process-inspection' const LEAF_ID = '11111111-1111-4111-8111-111111111111' const PANE_KEY = `tab-1:${LEAF_ID}` @@ -47,8 +43,6 @@ describe('runtime terminal owner routing', () => { const runtimeTransportCall = vi.fn() const localWrite = vi.fn() const localWriteAccepted = vi.fn() - const localForeground = vi.fn() - const localHasChildren = vi.fn() const localInspect = vi.fn() beforeEach(() => { @@ -74,8 +68,6 @@ describe('runtime terminal owner routing', () => { pty: { write: localWrite, writeAccepted: localWriteAccepted, - getForegroundProcess: localForeground, - hasChildProcesses: localHasChildren, inspectProcess: localInspect } } @@ -105,81 +97,6 @@ describe('runtime terminal owner routing', () => { expect(useAppStore.getState().lastTerminalInputAtByPaneKey[PANE_KEY]).toBe(123) }) - it('sends input through the PTY owning environment instead of the active one', async () => { - expect(sendRuntimePtyInput('remote:env-1@@terminal-1', 'x', 'driving')).toBe(true) - - await vi.waitFor(() => { - expect(runtimeCall).toHaveBeenCalledWith({ - selector: 'env-1', - method: 'terminal.send', - params: { - terminal: 'terminal-1', - text: 'x', - client: { id: 'orca-desktop', type: 'desktop' } - }, - timeoutMs: 15_000 - }) - }) - expect(localWrite).not.toHaveBeenCalled() - }) - - it('inspects the PTY owning environment instead of the active one', async () => { - await expect(inspectRuntimeTerminalProcess('remote:env-1@@terminal-1')).resolves.toMatchObject({ - foregroundProcess: 'bash', - hasChildProcesses: true - }) - - expect(runtimeCall).toHaveBeenCalledWith({ - selector: 'env-1', - method: 'terminal.inspectProcess', - params: { terminal: 'terminal-1' }, - timeoutMs: 15_000 - }) - expect(localForeground).not.toHaveBeenCalled() - expect(localHasChildren).not.toHaveBeenCalled() - }) - - // Forward close guards’ real-process-read option or hosts return unverifiable and confirm every idle remote Windows close (#18591). - it('forwards scanChildProcesses to the PTY owning environment', async () => { - await inspectRuntimeTerminalProcess('remote:env-1@@terminal-1', { scanChildProcesses: true }) - - expect(runtimeCall).toHaveBeenCalledWith({ - selector: 'env-1', - method: 'terminal.inspectProcess', - params: { terminal: 'terminal-1', scanChildProcesses: true }, - timeoutMs: 15_000 - }) - }) - - it('forwards scanChildProcesses alongside the incarnation fence', async () => { - await inspectRuntimeTerminalProcess('remote:env-1@@terminal-1', { - expectedIncarnationId: 'incarnation-1', - scanChildProcesses: true - }) - - expect(runtimeCall).toHaveBeenCalledWith({ - selector: 'env-1', - method: 'terminal.inspectProcess', - params: { - terminal: 'terminal-1', - expectedIncarnationId: 'incarnation-1', - scanChildProcesses: true - }, - timeoutMs: 15_000 - }) - }) - - it('omits scanChildProcesses when the caller is only polling', async () => { - await inspectRuntimeTerminalProcess('remote:env-1@@terminal-1') - - expect(runtimeCall).toHaveBeenCalledWith({ - selector: 'env-1', - method: 'terminal.inspectProcess', - params: { terminal: 'terminal-1' }, - timeoutMs: 15_000 - }) - }) - it('maps an old host inspection to client-only unverifiable', async () => { runtimeCall.mockResolvedValue({ ok: true, @@ -197,22 +114,6 @@ describe('runtime terminal owner routing', () => { }) }) - it('uses strict main-process inspection for a direct SSH PTY', async () => { - localInspect.mockResolvedValue({ - foregroundProcess: 'codex', - hasChildProcesses: true, - foregroundProcessEvidence: liveEvidence('pty-1', 'codex') - }) - - await expect(inspectRuntimeTerminalProcess('ssh:host@@pty-1')).resolves.toMatchObject({ - foregroundProcess: 'codex', - hasChildProcesses: true - }) - expect(localInspect).toHaveBeenCalledExactlyOnceWith('ssh:host@@pty-1') - expect(localForeground).not.toHaveBeenCalled() - expect(localHasChildren).not.toHaveBeenCalled() - }) - it('maps an old direct SSH host to client-only unverifiable', async () => { localInspect.mockResolvedValue({ foregroundProcess: null, @@ -261,23 +162,6 @@ describe('runtime terminal owner routing', () => { ).resolves.toMatchObject({ verdict: 'unverifiable', reason: 'timeout' }) }) - it('keeps client-only unverifiable free of host metadata', () => { - type HostFieldsCannotBeConstructed = ClientOnlyUnverifiableInspection extends { - authorityGeneration?: never - observationEpoch?: never - capturedAgeMs?: never - ptyId?: never - ptyIncarnationId?: never - } - ? true - : false - const typeProof: HostFieldsCannotBeConstructed = true - expect(typeProof).toBe(true) - const result = clientOnlyUnverifiableInspection('transport_loss') - expect(result).not.toHaveProperty('authorityGeneration') - expect(result).not.toHaveProperty('foregroundProcessEvidence') - }) - it('still throws an unclassified programming error', async () => { runtimeCall.mockRejectedValueOnce(new Error('inspection invariant violated')) await expect(inspectRuntimeTerminalProcess('remote:env-1@@terminal-bug')).rejects.toThrow( @@ -285,33 +169,6 @@ describe('runtime terminal owner routing', () => { ) }) - it('records accepted fire-and-forget runtime input against the owning pane key', async () => { - runtimeCall.mockResolvedValue({ - ok: true, - result: { send: { handle: 'terminal-1', accepted: true, bytesWritten: 1 } }, - _meta: { runtimeId: 'runtime-1' } - }) - useAppStore.setState({ - settings: { experimentalAgentHibernation: true } as never, - terminalLayoutsByTabId: { - 'tab-1': { - root: { type: 'leaf', leafId: LEAF_ID }, - activeLeafId: LEAF_ID, - expandedLeafId: null, - ptyIdsByLeafId: { [LEAF_ID]: 'remote:env-1@@terminal-1' } - } - } - }) - - expect(sendRuntimePtyInput('remote:env-1@@terminal-1', 'x', 'driving')).toBe(true) - - await vi.waitFor(() => { - expect(useAppStore.getState().lastTerminalInputAtByPaneKey[PANE_KEY]).toEqual( - expect.any(Number) - ) - }) - }) - it('attributes a delayed runtime acknowledgement to the current layout owner', async () => { const pendingSend = Promise.withResolvers<{ ok: true @@ -357,75 +214,6 @@ describe('runtime terminal owner routing', () => { }) }) - it('does not record declined fire-and-forget runtime input', async () => { - runtimeCall.mockResolvedValue({ - ok: true, - result: { send: { handle: 'terminal-1', accepted: false, bytesWritten: 0 } }, - _meta: { runtimeId: 'runtime-1' } - }) - useAppStore.setState({ - settings: { experimentalAgentHibernation: true } as never, - terminalLayoutsByTabId: { - 'tab-1': { - root: { type: 'leaf', leafId: LEAF_ID }, - activeLeafId: LEAF_ID, - expandedLeafId: null, - ptyIdsByLeafId: { [LEAF_ID]: 'remote:env-1@@terminal-1' } - } - } - }) - - expect(sendRuntimePtyInput('remote:env-1@@terminal-1', 'x', 'driving')).toBe(true) - - await vi.waitFor(() => { - expect(runtimeCall).toHaveBeenCalled() - }) - expect(useAppStore.getState().lastTerminalInputAtByPaneKey[PANE_KEY]).toBeUndefined() - }) - - it('reports stale remote terminal handles as rejected during verified send', async () => { - runtimeCall.mockResolvedValue({ - ok: false, - error: { code: 'terminal_handle_stale', message: 'terminal_handle_stale' } - }) - - await expect( - sendRuntimePtyInputVerified('remote:env-1@@terminal-stale', 'x', 'driving') - ).resolves.toBe(false) - }) - - it('reports declined remote terminal sends as rejected during verified send', async () => { - runtimeCall.mockResolvedValue({ - ok: true, - result: { send: { handle: 'terminal-1', accepted: false, bytesWritten: 0 } }, - _meta: { runtimeId: 'runtime-1' } - }) - - await expect( - sendRuntimePtyInputVerified('remote:env-1@@terminal-1', 'x', 'driving') - ).resolves.toBe(false) - - expect(runtimeCall).toHaveBeenCalledWith({ - selector: 'env-1', - method: 'terminal.send', - params: { - terminal: 'terminal-1', - text: 'x', - client: { id: 'orca-desktop', type: 'desktop' } - }, - timeoutMs: 15_000 - }) - }) - - it('uses accepted local writes for verified input', async () => { - localWriteAccepted.mockResolvedValue(true) - - await expect(sendRuntimePtyInputVerified('local-pty', 'x', 'driving')).resolves.toBe(true) - - expect(localWriteAccepted).toHaveBeenCalledWith('local-pty', 'x', 'driving') - expect(localWrite).not.toHaveBeenCalled() - }) - it('rejects oversized fire-and-forget local input before IPC writes', () => { const text = 'x'.repeat(TERMINAL_INPUT_MAX_BYTES + 1) @@ -435,15 +223,6 @@ describe('runtime terminal owner routing', () => { expect(localWriteAccepted).not.toHaveBeenCalled() }) - it('rejects oversized fire-and-forget remote input before runtime RPC', () => { - const text = 'x'.repeat(TERMINAL_INPUT_MAX_BYTES + 1) - - expect(sendRuntimePtyInput('remote:env-1@@terminal-1', text, 'driving')).toBe(false) - - expect(runtimeTransportCall).not.toHaveBeenCalled() - expect(localWrite).not.toHaveBeenCalled() - }) - it('yields while validating large fire-and-forget local input before IPC writes', async () => { vi.useFakeTimers() try { @@ -632,110 +411,4 @@ describe('runtime terminal owner routing', () => { ] ).toBe(1_000_000) }) - - it('reindexes a PTY when the immutable layout identity changes', () => { - const nextLeafId = '22222222-2222-4222-8222-222222222222' - useAppStore.setState({ - terminalLayoutsByTabId: { - 'tab-1': { - root: { type: 'leaf', leafId: LEAF_ID }, - activeLeafId: LEAF_ID, - expandedLeafId: null, - ptyIdsByLeafId: { [LEAF_ID]: 'rebound-pty' } - } - } - }) - recordRuntimeTerminalInputForPtyId('rebound-pty', 123) - - useAppStore.setState({ - terminalLayoutsByTabId: { - 'tab-2': { - root: { type: 'leaf', leafId: nextLeafId }, - activeLeafId: nextLeafId, - expandedLeafId: null, - ptyIdsByLeafId: { [nextLeafId]: 'rebound-pty' } - } - } - }) - recordRuntimeTerminalInputForPtyId('rebound-pty', 1_000) - - expect(useAppStore.getState().lastTerminalInputAtByPaneKey).toEqual({ - [PANE_KEY]: 123, - [`tab-2:${nextLeafId}`]: 1_000 - }) - }) - - it('reindexes stale owners without caching misses within the same layout identity', () => { - const nextLeafId = '22222222-2222-4222-8222-222222222222' - useAppStore.setState({ - terminalLayoutsByTabId: { - 'tab-1': { - root: { type: 'leaf', leafId: LEAF_ID }, - activeLeafId: LEAF_ID, - expandedLeafId: null, - ptyIdsByLeafId: { [LEAF_ID]: 'rebound-pty' } - } - } - }) - const layouts = useAppStore.getState().terminalLayoutsByTabId - recordRuntimeTerminalInputForPtyId('rebound-pty', 123) - recordRuntimeTerminalInputForPtyId('late-pty', 456) - - const firstLayout = layouts['tab-1'] - expect(firstLayout).toBeDefined() - if (!firstLayout) { - return - } - firstLayout.ptyIdsByLeafId = Object.create({ [LEAF_ID]: 'rebound-pty' }) - Object.setPrototypeOf(layouts, { 'tab-1': firstLayout }) - delete layouts['tab-1'] - layouts['tab-2'] = { - root: { type: 'leaf', leafId: nextLeafId }, - activeLeafId: nextLeafId, - expandedLeafId: null, - ptyIdsByLeafId: { [nextLeafId]: 'rebound-pty', [LEAF_ID]: 'late-pty' } - } - recordRuntimeTerminalInputForPtyId('rebound-pty', 1_000) - recordRuntimeTerminalInputForPtyId('late-pty', 2_000) - - expect(useAppStore.getState().terminalLayoutsByTabId).toBe(layouts) - expect(useAppStore.getState().lastTerminalInputAtByPaneKey).toEqual({ - [PANE_KEY]: 123, - [`tab-2:${nextLeafId}`]: 1_000, - [`tab-2:${LEAF_ID}`]: 2_000 - }) - }) - - it('preserves a malformed first match instead of routing a duplicate PTY', () => { - const nextLeafId = '22222222-2222-4222-8222-222222222222' - useAppStore.setState({ - terminalLayoutsByTabId: { - 'legacy:tab': { - root: { type: 'leaf', leafId: LEAF_ID }, - activeLeafId: LEAF_ID, - expandedLeafId: null, - ptyIdsByLeafId: { [LEAF_ID]: 'duplicate-pty' } - }, - 'tab-2': { - root: { type: 'leaf', leafId: nextLeafId }, - activeLeafId: nextLeafId, - expandedLeafId: null, - ptyIdsByLeafId: { [nextLeafId]: 'duplicate-pty' } - } - } - }) - - recordRuntimeTerminalInputForPtyId('duplicate-pty', 123) - - expect(useAppStore.getState().lastTerminalInputAtByPaneKey).toEqual({}) - }) - - it('reports success after fallback fire-and-forget writes when local acceptance cannot be verified', async () => { - localWriteAccepted.mockResolvedValue(false) - - await expect(sendRuntimePtyInputVerified('local-pty', 'x', 'driving')).resolves.toBe(true) - - expect(localWriteAccepted).toHaveBeenCalledWith('local-pty', 'x', 'driving') - expect(localWrite).toHaveBeenCalledWith('local-pty', 'x', 'driving') - }) }) diff --git a/src/renderer/src/runtime/runtime-terminal-stream.test.ts b/src/renderer/src/runtime/runtime-terminal-stream.test.ts index 727923aa788..40b3270aa9e 100644 --- a/src/renderer/src/runtime/runtime-terminal-stream.test.ts +++ b/src/renderer/src/runtime/runtime-terminal-stream.test.ts @@ -11,36 +11,10 @@ import { _getRemoteRuntimeTerminalMultiplexerCountForTest, resetRemoteRuntimeTerminalMultiplexersForTests } from './remote-runtime-terminal-multiplexer' -import { - getRemoteRuntimePtyEnvironmentId, - getRemoteRuntimeTerminalHandle, - subscribeToRuntimeTerminalData -} from './runtime-terminal-stream' -import { toRemoteRuntimePtyId } from '../../../shared/remote-runtime/remote-runtime-pty-id' +import { subscribeToRuntimeTerminalData } from './runtime-terminal-stream' + import { stubRuntimeEnvironmentBridge } from './runtime-environment-bridge-fixture' -describe('remote runtime terminal ids', () => { - it('encodes and decodes the owning runtime environment', () => { - const ptyId = toRemoteRuntimePtyId('terminal:one', 'env-1') - - expect(ptyId).toBe('remote:env-1@@terminal%3Aone') - expect(getRemoteRuntimePtyEnvironmentId(ptyId)).toBe('env-1') - expect(getRemoteRuntimeTerminalHandle(ptyId)).toBe('terminal:one') - }) - - it('keeps legacy remote ids readable', () => { - expect(getRemoteRuntimePtyEnvironmentId('remote:terminal-1')).toBeNull() - expect(getRemoteRuntimeTerminalHandle('remote:terminal-1')).toBe('terminal-1') - }) - - it('treats malformed encoded ids as invalid instead of throwing', () => { - const malformed = 'remote:%E0%A4%A@@terminal-1' - - expect(getRemoteRuntimePtyEnvironmentId(malformed)).toBeNull() - expect(getRemoteRuntimeTerminalHandle(malformed)).toBeNull() - }) -}) - describe('remote runtime terminal data subscriptions', () => { const runtimeSubscribe = vi.fn() const sendBinary = vi.fn() @@ -347,168 +321,6 @@ describe('remote runtime terminal multiplex ACK gate', () => { vi.resetModules() }) - it('holds and releases ACKs for selected remote terminal streams only', async () => { - const { getRemoteRuntimeTerminalMultiplexer, resetRemoteRuntimeTerminalMultiplexersForTests } = - await import('./remote-runtime-terminal-multiplexer') - resetRemoteRuntimeTerminalMultiplexersForTests() - - const multiplexer = getRemoteRuntimeTerminalMultiplexer('env-ack-gate') - const heldTerminal = await multiplexer.subscribeTerminal({ - terminal: 'terminal-held', - client: { id: 'desktop-held', type: 'desktop' }, - callbacks: { - onData: vi.fn(), - onSnapshot: vi.fn() - } - }) - const liveTerminal = await multiplexer.subscribeTerminal({ - terminal: 'terminal-live', - client: { id: 'desktop-live', type: 'desktop' }, - callbacks: { - onData: vi.fn(), - onSnapshot: vi.fn() - } - }) - - await vi.waitFor(() => expect(sendBinary).toHaveBeenCalledTimes(2)) - const heldStreamId = heldTerminal.streamId - const liveStreamId = liveTerminal.streamId - const gate = ( - window as typeof window & { - __remoteTerminalMultiplexAckGate?: { - hold: (terminals: string[]) => void - release: () => void - snapshot: () => { - heldTerminalCount: number - heldStreamCount: number - heldAckChars: number - releasedAckChars: number - } - } - } - ).__remoteTerminalMultiplexAckGate - expect(gate).toBeDefined() - gate?.hold(['terminal-held']) - sendBinary.mockClear() - - callbacks?.onBinary?.( - encodeTerminalStreamFrame({ - opcode: TerminalStreamOpcode.Output, - streamId: heldStreamId, - seq: 1, - payload: encodeTerminalStreamText('held-output') - }) - ) - callbacks?.onBinary?.( - encodeTerminalStreamFrame({ - opcode: TerminalStreamOpcode.Output, - streamId: liveStreamId, - seq: 2, - payload: encodeTerminalStreamText('live-output') - }) - ) - - await vi.waitFor(() => - expect( - sendBinary.mock.calls - .map((call) => decodeTerminalStreamFrame(call[0])) - .filter((frame) => frame?.opcode === TerminalStreamOpcode.Ack) - ).toHaveLength(1) - ) - const immediateAckFrames = sendBinary.mock.calls - .map((call) => decodeTerminalStreamFrame(call[0])) - .filter((frame) => frame?.opcode === TerminalStreamOpcode.Ack) - expect(immediateAckFrames).toHaveLength(1) - expect(immediateAckFrames[0]?.streamId).toBe(liveStreamId) - expect(gate?.snapshot()).toMatchObject({ - heldTerminalCount: 1, - heldStreamCount: 1, - heldAckChars: 'held-output'.length - }) - - gate?.release() - await vi.waitFor(() => - expect( - sendBinary.mock.calls - .map((call) => decodeTerminalStreamFrame(call[0])) - .filter((frame) => frame?.opcode === TerminalStreamOpcode.Ack) - ).toHaveLength(2) - ) - const allAckFrames = sendBinary.mock.calls - .map((call) => decodeTerminalStreamFrame(call[0])) - .filter((frame) => frame?.opcode === TerminalStreamOpcode.Ack) - const releasedAck = allAckFrames.find((frame) => frame?.streamId === heldStreamId) - expect(releasedAck && decodeTerminalStreamJson(releasedAck.payload)).toEqual({ - bytes: 'held-output'.length - }) - expect(gate?.snapshot()).toMatchObject({ - heldTerminalCount: 0, - heldStreamCount: 0, - heldAckChars: 0, - releasedAckChars: 'held-output'.length - }) - - heldTerminal.close() - liveTerminal.close() - }) - - it('drops output only from the armed stream when its replacement reuses the stream ID', async () => { - const { getRemoteRuntimeTerminalMultiplexer, resetRemoteRuntimeTerminalMultiplexersForTests } = - await import('./remote-runtime-terminal-multiplexer') - resetRemoteRuntimeTerminalMultiplexersForTests() - - const oldData = vi.fn() - const oldStream = await getRemoteRuntimeTerminalMultiplexer( - 'env-output-drop-gate' - ).subscribeTerminal({ - terminal: 'terminal-reused-stream-id', - client: { id: 'desktop-old', type: 'desktop' }, - callbacks: { onData: oldData, onSnapshot: vi.fn() } - }) - const gate = ( - window as typeof window & { - __remoteTerminalMultiplexAckGate?: { - dropOutputUntilResubscribe: (terminals: string[]) => number - release: () => void - } - } - ).__remoteTerminalMultiplexAckGate - expect(gate?.dropOutputUntilResubscribe(['terminal-reused-stream-id'])).toBe(1) - - callbacks?.onBinary?.( - encodeTerminalStreamFrame({ - opcode: TerminalStreamOpcode.Output, - streamId: oldStream.streamId, - seq: 7, - payload: encodeTerminalStreamText('dropped') - }) - ) - expect(oldData).not.toHaveBeenCalled() - oldStream.close() - - const replacementData = vi.fn() - const replacement = await getRemoteRuntimeTerminalMultiplexer( - 'env-output-drop-gate' - ).subscribeTerminal({ - terminal: 'terminal-reused-stream-id', - client: { id: 'desktop-new', type: 'desktop' }, - callbacks: { onData: replacementData, onSnapshot: vi.fn() } - }) - expect(replacement.streamId).toBe(oldStream.streamId) - callbacks?.onBinary?.( - encodeTerminalStreamFrame({ - opcode: TerminalStreamOpcode.Output, - streamId: replacement.streamId, - seq: 9, - payload: encodeTerminalStreamText('delivered') - }) - ) - - expect(replacementData).toHaveBeenCalledWith('delivered', { seq: 9, rawLength: 9 }) - gate?.release() - replacement.close() - }) - it('applies mid-session recovery snapshots without re-subscribing', async () => { const { getRemoteRuntimeTerminalMultiplexer } = await import('./remote-runtime-terminal-multiplexer') diff --git a/src/renderer/src/runtime/runtime-terminal-verified-input.test.ts b/src/renderer/src/runtime/runtime-terminal-verified-input.test.ts deleted file mode 100644 index 43cb5bca5a3..00000000000 --- a/src/renderer/src/runtime/runtime-terminal-verified-input.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' -import { sendRuntimePtyInputVerified } from './runtime-terminal-verified-input' -import { - createCompatibleRuntimeStatusResponseIfNeeded, - type RuntimeEnvironmentCallRequest -} from './runtime-compatibility-test-fixture' -import { clearRuntimeCompatibilityCacheForTests } from './runtime-rpc-client' - -const REMOTE_PTY = 'remote:env-1@@terminal-1' -const runtimeSend = vi.fn() -const localWrite = vi.fn() -const localWriteAccepted = vi.fn() - -beforeEach(() => { - clearRuntimeCompatibilityCacheForTests() - vi.clearAllMocks() - vi.stubGlobal('window', { - api: { - runtimeEnvironments: { - call: (args: RuntimeEnvironmentCallRequest) => - createCompatibleRuntimeStatusResponseIfNeeded(args) ?? runtimeSend(args) - }, - pty: { write: localWrite, writeAccepted: localWriteAccepted } - } - }) -}) - -function hostReply(send: Record) { - runtimeSend.mockResolvedValue({ - ok: true, - result: { send: { handle: 'terminal-1', bytesWritten: 1, ...send } }, - _meta: { runtimeId: 'runtime-1' } - }) -} - -describe('verified input that requires provider settlement', () => { - it.each([ - ['older host whole-write', { accepted: true }, true], - ['acknowledged', { accepted: true, writeSettlement: { outcome: 'accepted' } }, true], - [ - 'refused', - { accepted: false, writeSettlement: { outcome: 'refused', reason: 'endpoint_disconnected' } }, - false - ] - ] as const)('reads the %s remote verdict', async (_label, send, accepted) => { - hostReply(send) - await expect( - sendRuntimePtyInputVerified(REMOTE_PTY, 'x', 'driving', { - requireWriteSettlement: true - }) - ).resolves.toBe(accepted) - expect(runtimeSend).toHaveBeenCalledWith( - expect.objectContaining({ - method: 'terminal.send', - params: expect.objectContaining({ requireWriteSettlement: true }) - }) - ) - }) - - it('rejects a remote send whose settlement is unverifiable, without a fallback write', async () => { - hostReply({ - accepted: false, - writeSettlement: { - outcome: 'unverifiable', - reason: 'transport_settlement_lost', - bytesHandedToTransport: true - } - }) - await expect( - sendRuntimePtyInputVerified(REMOTE_PTY, 'x', 'driving', { - requireWriteSettlement: true - }) - ).rejects.toThrow('acknowledgment unavailable') - expect(localWrite).not.toHaveBeenCalled() - expect(runtimeSend).toHaveBeenCalledOnce() - }) -}) - -describe('local verified input', () => { - it('keeps the fire-and-forget fallback for ordinary input the provider cannot accept', async () => { - localWriteAccepted.mockResolvedValue(false) - await expect(sendRuntimePtyInputVerified('ssh:conn-1@@pty-1', 'x', 'driving')).resolves.toBe( - true - ) - expect(localWriteAccepted).toHaveBeenCalledWith('ssh:conn-1@@pty-1', 'x', 'driving') - expect(localWrite).toHaveBeenCalledWith('ssh:conn-1@@pty-1', 'x', 'driving') - }) - - it('never falls back to an unacknowledged write when settlement is required', async () => { - const settled = { requireWriteSettlement: true } as const - localWriteAccepted.mockResolvedValueOnce(true) - await expect( - sendRuntimePtyInputVerified('ssh:conn-1@@pty-1', 'answer', 'driving', settled) - ).resolves.toBe(true) - localWriteAccepted.mockResolvedValueOnce(false) - await expect( - sendRuntimePtyInputVerified('ssh:conn-1@@pty-1', '1', 'driving', settled) - ).resolves.toBe(false) - localWriteAccepted.mockRejectedValueOnce(new Error('acknowledgment unavailable')) - await expect( - sendRuntimePtyInputVerified('ssh:conn-1@@pty-1', '\r', 'driving', settled) - ).rejects.toThrow('acknowledgment unavailable') - expect(localWriteAccepted).toHaveBeenCalledWith('ssh:conn-1@@pty-1', '\r', 'driving', settled) - expect(localWrite).not.toHaveBeenCalled() - }) -}) - -describe('owner of the PTY', () => { - it('never dials a server for a remote id that names no owner', async () => { - localWriteAccepted.mockResolvedValue(false) - // Why: this id used to reach whichever server was focused, even when another one owned it. - await sendRuntimePtyInputVerified('remote:terminal-1', 'x', 'driving', { - requireWriteSettlement: true - }) - expect(runtimeSend).not.toHaveBeenCalled() - }) - - it('sends to the server the id names', async () => { - hostReply({ accepted: true }) - await sendRuntimePtyInputVerified(REMOTE_PTY, 'x', 'driving') - expect(runtimeSend).toHaveBeenCalledWith( - expect.objectContaining({ selector: 'env-1', method: 'terminal.send' }) - ) - }) -})