diff --git a/src/main/ipc/pty/runtime/inventory-operations.ts b/src/main/ipc/pty/runtime/inventory-operations.ts index 7fadb456d8c..55bf1545e38 100644 --- a/src/main/ipc/pty/runtime/inventory-operations.ts +++ b/src/main/ipc/pty/runtime/inventory-operations.ts @@ -16,7 +16,7 @@ function markSshInventoryUnverifiable( } export async function listProcessesWithHostScopeFromRuntimeController( - deps: PtyRuntimeControllerDeps, + deps: Pick, opts?: { deadlineMs?: number; includeForegroundProcessEvidence?: boolean } ): Promise<{ processes: PtyProcessInfo[]; hostIds: ExecutionHostId[] }> { const providerSessions = await Promise.all( diff --git a/src/main/ipc/pty/runtime/queried-host-kinds.test.ts b/src/main/ipc/pty/runtime/queried-host-kinds.test.ts index 63567909f5e..af475e893af 100644 --- a/src/main/ipc/pty/runtime/queried-host-kinds.test.ts +++ b/src/main/ipc/pty/runtime/queried-host-kinds.test.ts @@ -1,14 +1,24 @@ -import { describe, expect, it } from 'vitest' +import { afterEach, describe, expect, it, vi } from 'vitest' import { listProcessesWithHostScopeFromRuntimeController } from './inventory-operations' -import type { PtyRuntimeControllerDeps } from './controller-deps' +import { localProvider } from '../provider/registry' + +afterEach(() => vi.restoreAllMocks()) -/** Inventory coverage must name only queried hosts; this process has no paired-runtime provider to query runtime: hosts. */ describe('the hosts a PTY inventory can report having queried', () => { - it('emits only this machine, never a paired-runtime host', async () => { - const { hostIds } = await listProcessesWithHostScopeFromRuntimeController({ - runtime: null - } as unknown as PtyRuntimeControllerDeps) + it('reports the local query results and propagates a failed query', async () => { + const listProcesses = vi + .spyOn(localProvider, 'listProcesses') + .mockResolvedValue([{ id: 'pty-local', cwd: '/workspace', title: 'Local terminal' }]) - expect(hostIds).toEqual(['local']) + expect(await listProcessesWithHostScopeFromRuntimeController({})).toEqual({ + processes: [{ id: 'pty-local', cwd: '/workspace', title: 'Local terminal' }], + hostIds: ['local'] + }) + expect(listProcesses).toHaveBeenCalledOnce() + + listProcesses.mockRejectedValueOnce(new Error('Local inventory unavailable')) + await expect(listProcessesWithHostScopeFromRuntimeController({})).rejects.toThrow( + 'Local inventory unavailable' + ) }) }) diff --git a/src/shared/migration-unsupported-agent-entry.test.ts b/src/shared/migration-unsupported-agent-entry.test.ts index 168896b41c8..c5672f1d51b 100644 --- a/src/shared/migration-unsupported-agent-entry.test.ts +++ b/src/shared/migration-unsupported-agent-entry.test.ts @@ -16,10 +16,16 @@ describe('migrationUnsupportedToAgentStatusEntry', () => { const second = migrationUnsupportedToAgentStatusEntry(unsupported) expect(second).toBe(first) - expect(first?.updatedAt).toBe(Number.MAX_SAFE_INTEGER) + expect(first).toMatchObject({ + state: 'blocked', + agentType: 'unknown', + paneKey: unsupported.paneKey, + stateStartedAt: 1234, + updatedAt: Number.MAX_SAFE_INTEGER + }) }) - it('caches null for records that cannot be projected to a pane key', () => { + it('returns null for records that cannot be projected to a pane key', () => { const unsupported: MigrationUnsupportedPtyEntry = { ptyId: 'pty-1', reason: 'legacy-numeric-pane-key', @@ -28,6 +34,5 @@ describe('migrationUnsupportedToAgentStatusEntry', () => { } expect(migrationUnsupportedToAgentStatusEntry(unsupported)).toBeNull() - expect(migrationUnsupportedToAgentStatusEntry(unsupported)).toBeNull() }) }) diff --git a/src/shared/physical-exit-tracker.test.ts b/src/shared/physical-exit-tracker.test.ts index 10de6fe4443..0b7d43485b8 100644 --- a/src/shared/physical-exit-tracker.test.ts +++ b/src/shared/physical-exit-tracker.test.ts @@ -4,7 +4,7 @@ import { PhysicalExitTracker } from './physical-exit-tracker' describe('PhysicalExitTracker', () => { afterEach(() => vi.useRealTimers()) - it('removes timed-out waiters while later retries can still observe exit', async () => { + it('lets a later retry observe exit after an earlier wait times out', async () => { vi.useFakeTimers() const tracker = new PhysicalExitTracker() const first = tracker.waitForExit(10, () => new Error('first deadline')) diff --git a/src/shared/plugins/plugin-consent-request.test.ts b/src/shared/plugins/plugin-consent-request.test.ts index 84cbf53bce5..496a0bb71a1 100644 --- a/src/shared/plugins/plugin-consent-request.test.ts +++ b/src/shared/plugins/plugin-consent-request.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest' import { pluginConsentRequestSchema } from './plugin-consent-request' describe('pluginConsentRequestSchema', () => { - it('requires the exact reviewed consent fingerprint', () => { + it('requires a nonempty reviewed consent fingerprint', () => { expect( pluginConsentRequestSchema.safeParse({ pluginKey: 'orca-samples.demo', diff --git a/src/shared/plugins/plugin-install-lockfile.test.ts b/src/shared/plugins/plugin-install-lockfile.test.ts index 3a47c3ce6d5..805cbd45ec5 100644 --- a/src/shared/plugins/plugin-install-lockfile.test.ts +++ b/src/shared/plugins/plugin-install-lockfile.test.ts @@ -31,18 +31,35 @@ describe('pluginInstallSourceSchema marketplace provenance', () => { }) it('requires pinned refs and an exact marketplace snapshot commit', () => { + const source = { + kind: 'marketplace', + marketplace: { + url: 'https://github.com/stablyai/orca-plugins.git', + ref: 'main', + resolvedCommit: 'a'.repeat(40) + }, + plugin: { + url: 'https://github.com/stablyai/orca-skills.git', + ref: 'v1.0.0' + } + } + expect( pluginInstallSourceSchema.safeParse({ - kind: 'marketplace', - marketplace: { - url: 'https://github.com/stablyai/orca-plugins.git', - ref: '', - resolvedCommit: 'main' - }, - plugin: { - url: 'https://github.com/stablyai/orca-skills.git', - ref: '' - } + ...source, + marketplace: { ...source.marketplace, ref: '' } + }).success + ).toBe(false) + expect( + pluginInstallSourceSchema.safeParse({ + ...source, + marketplace: { ...source.marketplace, resolvedCommit: 'main' } + }).success + ).toBe(false) + expect( + pluginInstallSourceSchema.safeParse({ + ...source, + plugin: { ...source.plugin, ref: '' } }).success ).toBe(false) }) diff --git a/src/shared/plugins/plugin-panel-call-admission.test.ts b/src/shared/plugins/plugin-panel-call-admission.test.ts index 7201562a83a..6c0bd2e158b 100644 --- a/src/shared/plugins/plugin-panel-call-admission.test.ts +++ b/src/shared/plugins/plugin-panel-call-admission.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest' import { createPluginPanelCallAdmission } from './plugin-panel-call-admission' describe('createPluginPanelCallAdmission', () => { - it('shares the rate budget across panel sessions for one plugin', () => { + it('shares the rate budget across calls for one plugin', () => { let now = 0 const admission = createPluginPanelCallAdmission({ limits: { maxMessages: 2, perMs: 1_000 }, diff --git a/src/shared/remote-runtime/control/remote-runtime-shared-control-reconnect.test.ts b/src/shared/remote-runtime/control/remote-runtime-shared-control-reconnect.test.ts index bb816ef86b1..c8c492e1b65 100644 --- a/src/shared/remote-runtime/control/remote-runtime-shared-control-reconnect.test.ts +++ b/src/shared/remote-runtime/control/remote-runtime-shared-control-reconnect.test.ts @@ -15,8 +15,9 @@ describe('SharedControlReconnectScheduler', () => { expect(scheduler.retryNow()).toBe(true) expect(scheduler.retryNow()).toBe(false) expect(open).toHaveBeenCalledTimes(1) + expect(vi.getTimerCount()).toBe(0) - await vi.advanceTimersByTimeAsync(30_000) + await vi.advanceTimersByTimeAsync(36_000) expect(open).toHaveBeenCalledTimes(1) }) diff --git a/src/shared/repro-7732-gitlab-job-id-dropped.test.ts b/src/shared/repro-7732-gitlab-job-id-dropped.test.ts deleted file mode 100644 index c79258de0b7..00000000000 --- a/src/shared/repro-7732-gitlab-job-id-dropped.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { gitLabPipelineJobsToPRChecks } from './gitlab-pipeline-checks' -import type { GitLabPipelineJob } from './gitlab-types' - -// GitLab job traces require the numeric jobId preserved by check-row mapping (#7732). -function numericHandles(value: Record): number[] { - return Object.values(value).filter((v): v is number => typeof v === 'number') -} - -describe('#7732 GitLab pipeline job -> check row mapping', () => { - const failedJob: GitLabPipelineJob = { - id: 42, - name: 'Purchase API Component Tests', - stage: 'Component Tests', - status: 'failed', - webUrl: 'https://gitlab.com/acme/orca/-/jobs/42', - duration: 31 - } - - it('keeps the GitLab job id so the panel can fetch the job trace', () => { - const [check] = gitLabPipelineJobsToPRChecks([failedJob]) - - expect(check.name).toBe('Component Tests: Purchase API Component Tests') - expect(check.conclusion).toBe('failure') - // The id is the only handle gitlab:jobTrace accepts; without it the expand path has nothing to send. - expect(numericHandles(check)).toContain(42) - }) -}) diff --git a/src/shared/review-refresh-policy.test.ts b/src/shared/review-refresh-policy.test.ts index 0f5981db25e..3094228c86f 100644 --- a/src/shared/review-refresh-policy.test.ts +++ b/src/shared/review-refresh-policy.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { REVIEW_REFRESH_COOLDOWN_MS, reviewRefreshIntervalMs } from './review-refresh-policy' +import { reviewRefreshIntervalMs } from './review-refresh-policy' describe('review refresh intervals', () => { it.each([ @@ -22,8 +22,4 @@ describe('review refresh intervals', () => { ] as const)('uses %j → %s', (input, expected) => { expect(reviewRefreshIntervalMs(input)).toBe(expected) }) - - it('keeps exposure cooldown separate from periodic refresh cadence', () => { - expect(REVIEW_REFRESH_COOLDOWN_MS).toBe(10_000) - }) })