From 818a25d430787c456e17afedda40aef590dcd580 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Tue, 20 Oct 2026 22:01:13 -0700 Subject: [PATCH] test(vitest): derive the Node SQLite test list from imports (#30647) * test(vitest): derive the Node SQLite test list from imports instead of a hand-kept list The two SQLite list files held ~511 test paths that every PR adding a SQLite test had to edit, which caused frequent merge conflicts. The vitest config now finds tests that directly import a SQLite module or harness when it loads, using the classifier the boundary test already had, with a modification-time cache so unchanged files skip parsing. The 42 tests that reach SQLite only through a shared helper or a dynamic import stay listed in the Node runtime list. * test(vitest): skip unused SQLite derivation and reject malformed cache entries * test(vitest): use typed test convention for cache contract --- config/scripts/ci-shard-assignment.test.mjs | 6 +- .../vitest-node-runtime-boundary.test.ts | 4 +- config/scripts/vitest-node-runtime-files.mjs | 59 +++- .../scripts/vitest-runtime-boundary.test.ts | 8 +- .../vitest-sqlite-database-runtime-files.mjs | 212 ------------ .../vitest-sqlite-runtime-boundary.test.ts | 82 +---- .../vitest-sqlite-runtime-cache.test.ts | 34 ++ .../scripts/vitest-sqlite-runtime-files.mjs | 306 ------------------ config/scripts/vitest-sqlite-runtime-scan.mjs | 132 ++++++++ config/vitest.config.ts | 7 +- 10 files changed, 243 insertions(+), 607 deletions(-) delete mode 100644 config/scripts/vitest-sqlite-database-runtime-files.mjs create mode 100644 config/scripts/vitest-sqlite-runtime-cache.test.ts delete mode 100644 config/scripts/vitest-sqlite-runtime-files.mjs create mode 100644 config/scripts/vitest-sqlite-runtime-scan.mjs diff --git a/config/scripts/ci-shard-assignment.test.mjs b/config/scripts/ci-shard-assignment.test.mjs index a2c4729cade..440112d865b 100644 --- a/config/scripts/ci-shard-assignment.test.mjs +++ b/config/scripts/ci-shard-assignment.test.mjs @@ -8,7 +8,7 @@ import { discoverE2eFiles, planE2e, verifyE2eSelection } from './ci-e2e-shard-pl import { parseTimingLog } from './ci-shard-timing-import.mjs' import TimingSequencer from './ci-unit-sequencer.mjs' import { UNIT_INCLUDE, UNIT_EXCLUDE } from './ci-unit-files.mjs' -import { NODE_RUNTIME_INCLUDE } from './vitest-node-runtime-files.mjs' +import { getNodeRuntimeInclude } from './vitest-node-runtime-files.mjs' import { nodeRuntimePool } from './vitest-node-runtime-pool' const directories = [] @@ -107,12 +107,12 @@ describe('timing-weighted shard selection', () => { } const ordinaryNode = ordinary.find((project) => project.test.name !== 'bun') expect(ordinaryNode.test.include).toEqual( - process.versions.bun ? NODE_RUNTIME_INCLUDE : UNIT_INCLUDE + process.versions.bun ? getNodeRuntimeInclude() : UNIT_INCLUDE ) const ordinaryBun = ordinary.find((project) => project.test.name === 'bun') if (process.versions.bun) { expect(ordinaryBun.test.exclude).toEqual( - expect.arrayContaining([...NODE_RUNTIME_INCLUDE, measurementFile]) + expect.arrayContaining([...getNodeRuntimeInclude(), measurementFile]) ) } }) diff --git a/config/scripts/vitest-node-runtime-boundary.test.ts b/config/scripts/vitest-node-runtime-boundary.test.ts index 2832d03c438..845ecb24267 100644 --- a/config/scripts/vitest-node-runtime-boundary.test.ts +++ b/config/scripts/vitest-node-runtime-boundary.test.ts @@ -3,7 +3,7 @@ import { resolve } from 'node:path' import ts from 'typescript-api' import { expect, it } from 'vitest' import { discoverUnitFiles } from './ci-unit-files.mjs' -import { NODE_RUNTIME_INCLUDE } from './vitest-node-runtime-files.mjs' +import { getNodeRuntimeInclude } from './vitest-node-runtime-files.mjs' it('runs Node runtime contracts in Node even when the coordinator uses Bun', () => { expect(process.versions.bun).toBeUndefined() @@ -25,7 +25,7 @@ function isGlobalThis(expression: ts.Expression): boolean { it('keeps exposed-GC heap measurements in the Node runtime project', () => { const root = process.cwd() - const nodeFiles = new Set(globSync(NODE_RUNTIME_INCLUDE).map((file) => resolve(root, file))) + const nodeFiles = new Set(globSync(getNodeRuntimeInclude()).map((file) => resolve(root, file))) const missing: string[] = [] for (const file of discoverUnitFiles(root)) { if (nodeFiles.has(resolve(root, file))) { diff --git a/config/scripts/vitest-node-runtime-files.mjs b/config/scripts/vitest-node-runtime-files.mjs index 61e9c531448..b967d6b44d5 100644 --- a/config/scripts/vitest-node-runtime-files.mjs +++ b/config/scripts/vitest-node-runtime-files.mjs @@ -1,7 +1,7 @@ -import { SQLITE_RUNTIME_INCLUDE } from './vitest-sqlite-runtime-files.mjs' +import { findSqliteRuntimeTests } from './vitest-sqlite-runtime-scan.mjs' // SQLite publication, native bindings, worker IPC, socket liveness, and V8 retention use Node. -export const NODE_RUNTIME_INCLUDE = [ +const NODE_RUNTIME_INCLUDE = [ 'src/main/runtime/structured-agent-cli-writers.test.ts', 'config/scripts/vitest-sqlite-runtime-boundary.test.ts', 'config/scripts/cloud-security-history-workflow.test.mjs', @@ -28,7 +28,56 @@ export const NODE_RUNTIME_INCLUDE = [ 'src/renderer/src/components/terminal-pane/pty-input-write-queue.test.ts', 'src/renderer/src/lib/react-commit-cascade-observer.test.ts', 'src/renderer/src/lib/react-commit-cascade-telemetry.test.ts', - ...SQLITE_RUNTIME_INCLUDE, + // These reach Node SQLite through a shared helper or a dynamic import, which the scan skips. + 'tests/e2e/native-chat-startup-option-pickers.unit.test.ts', + 'src/main/ai-vault/session-document-consumer-replacement.test.ts', + 'src/main/ai-vault-search/session-search-dependent-transcripts.test.ts', + 'src/main/ai-vault-search/session-search-list-reparse.test.ts', + 'src/main/ai-vault-search/session-search-transcript-dependencies.test.ts', + 'src/main/native-chat/structured-agent-cli-conversation-adoption.test.ts', + 'src/main/runtime/orchestration-cli-subprocess.test.ts', + 'src/main/runtime/orchestration-mailbox-delivery.test.ts', + 'src/main/runtime/orchestration-mailbox-routing.test.ts', + 'src/main/runtime/worker-terminal-archive-release.test.ts', + 'src/main/runtime/worker-terminal-archive-screen.test.ts', + 'src/main/runtime/worker-terminal-wrap-provenance.test.ts', + 'tests/e2e/cross-version-wire/agent-session-clear-old-client.unit.test.ts', + 'tests/e2e/cross-version-wire/agent-session-clear-old-tab-mirror.unit.test.ts', + 'src/main/acp/acp-structured-host-live-listing.test.ts', + 'src/main/acp/acp-structured-host-configured-default.test.ts', + 'src/main/pi/rpc-session-adapter.test.ts', + 'src/main/pi/rpc-session-startup.test.ts', + 'src/main/acp/acp-structured-publish-at-spawn.test.ts', + 'src/main/acp/acp-structured-omp-recordings.test.ts', + 'src/main/acp/acp-text-stream-identity.test.ts', + 'src/main/acp/acp-text-message-ownership.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-clear-queued-command.test.ts', + 'src/main/acp/acp-structured-sign-in.test.ts', + 'src/main/acp/acp-structured-auth.test.ts', + 'src/main/acp/acp-structured-prompt-failure.test.ts', + 'src/main/acp/acp-timeline-turn-failures.test.ts', + 'src/main/acp/acp-structured-session-adapter.test.ts', + 'src/main/acp/acp-structured-session-adapter-resume.test.ts', + 'src/main/acp/acp-structured-host-start-aborts.test.ts', + 'src/main/acp/acp-conversation-copy.test.ts', + 'src/main/pi/rpc-turn-races.test.ts', + 'src/main/acp/acp-structured-child-session-end.test.ts', + 'src/main/acp/acp-structured-child-stop.test.ts', + 'src/main/acp/acp-structured-child-work-admission.test.ts', + 'src/main/acp/acp-structured-child-work.test.ts', + 'src/main/acp/acp-structured-host-subagent-stop.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-background-stop-unreadable.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-exit-delivery.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-provider-open.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-ready-operation-order.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-message-choices.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.test.ts', + 'src/main/native-chat/agent-session-wire/structured-agent-session-send.test.ts', + 'src/main/orcad/serve-profile-ssh-targets.test.ts', + 'src/main/runtime/orca-runtime.test.ts', + 'src/main/runtime/worktree-agent-first-surface.test.ts', + 'src/main/runtime/runtime-client-agent-launch-settings-durability.test.ts', + 'tests/e2e/host-agent-launch-settings-hook-bookkeeping.unit.test.ts', 'src/cli/**/*.test.ts', 'src/main/persistence/**/*.test.ts', 'src/main/persistence*.test.ts', @@ -127,3 +176,7 @@ export const NODE_RUNTIME_INCLUDE = [ 'config/scripts/vitest-node-runtime-boundary.test.ts', 'config/scripts/vitest-node-runtime-pool.test.ts' ] + +export function getNodeRuntimeInclude() { + return [...NODE_RUNTIME_INCLUDE, ...findSqliteRuntimeTests()] +} diff --git a/config/scripts/vitest-runtime-boundary.test.ts b/config/scripts/vitest-runtime-boundary.test.ts index 737bd193c37..5df6cc63078 100644 --- a/config/scripts/vitest-runtime-boundary.test.ts +++ b/config/scripts/vitest-runtime-boundary.test.ts @@ -1,6 +1,6 @@ import { expect, it } from 'vitest' import { access } from 'node:fs/promises' -import { NODE_RUNTIME_INCLUDE } from './vitest-node-runtime-files.mjs' +import { getNodeRuntimeInclude } from './vitest-node-runtime-files.mjs' import { runProcessSync } from '@orca/process-host' it('uses Bun for ordinary suites when the Bun project is selected', () => { @@ -23,7 +23,7 @@ it('launches application child fixtures under Node even when Vitest runs under B }) it('routes native-chat journal and record-store SQLite contracts through Node', () => { - expect(NODE_RUNTIME_INCLUDE).toEqual( + expect(getNodeRuntimeInclude()).toEqual( expect.arrayContaining([ 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.test.ts', 'src/main/native-chat/agent-session-wire/structured-agent-session-status-first-input-identity.test.ts', @@ -35,5 +35,7 @@ it('routes native-chat journal and record-store SQLite contracts through Node', }) it('runs plugin reconciliation with its native watcher under Node', () => { - expect(NODE_RUNTIME_INCLUDE).toContain('src/main/plugins/plugin-service-reconciliation.test.ts') + expect(getNodeRuntimeInclude()).toContain( + 'src/main/plugins/plugin-service-reconciliation.test.ts' + ) }) diff --git a/config/scripts/vitest-sqlite-database-runtime-files.mjs b/config/scripts/vitest-sqlite-database-runtime-files.mjs deleted file mode 100644 index 9af339e9cf7..00000000000 --- a/config/scripts/vitest-sqlite-database-runtime-files.mjs +++ /dev/null @@ -1,212 +0,0 @@ -// Database opening and lifecycle fixtures exercise Node SQLite behavior. -export const SQLITE_DATABASE_RUNTIME_INCLUDE = [ - 'src/main/ai-vault-search/session-search-write-buffer.test.ts', - 'src/main/ai-vault/session-document-consumer-replacement.test.ts', - 'src/main/ai-vault-search/session-search-dependent-transcripts.test.ts', - 'src/main/ai-vault-search/session-search-file-write.test.ts', - 'src/main/ai-vault-search/session-search-live-transcript.test.ts', - 'src/main/ai-vault-search/session-search-list-reparse.test.ts', - 'src/main/ai-vault-search/session-search-transcript-dependencies.test.ts', - 'src/main/ai-vault/session-scanner-devin-contention.test.ts', - 'src/main/ai-vault/session-scanner-opencode-native-worker.test.ts', - 'src/main/ai-vault/session-scanner-opencode-sqlite-bounds.test.ts', - 'src/main/ai-vault/session-scanner-opencode-sqlite-coexistence.test.ts', - 'src/main/ai-vault/session-scanner-opencode-sqlite-open.test.ts', - 'src/main/ai-vault/session-scanner-opencode-sqlite-process.test.ts', - 'src/main/ai-vault/session-scanner-opencode-sqlite.test.ts', - 'src/main/ai-vault/session-scanner-opencode2-sqlite.test.ts', - 'src/main/ai-vault/session-scanner-zcode.test.ts', - 'src/main/codex/codex-account-session-bridge.test.ts', - 'src/main/codex/codex-index-heal-binary-contract.test.ts', - 'src/main/codex/codex-state-db.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-stop-row.test.ts', - 'src/main/native-chat/structured-agent-cli-conversation-adoption.test.ts', - 'src/main/native-chat/transcript-opencode-semantic-fidelity.test.ts', - 'src/main/native-chat/transcript-opencode-sqlite-query.test.ts', - 'src/main/native-chat/transcript-opencode-subscribe.test.ts', - 'src/main/native-chat/transcript-zcode.test.ts', - 'src/main/native-chat/transcript-opencode2-sqlite.test.ts', - 'src/main/opencode-usage/cache-read-reproduction.test.ts', - 'src/main/opencode-usage/opencode2-session-usage.test.ts', - 'src/main/opencode-usage/scanner-windows-data-directory.test.ts', - 'src/main/opencode-usage/scanner.test.ts', - 'src/main/rate-limits/opencode-go-api-key-source.test.ts', - 'src/main/rate-limits/opencode-go-managed-account-source.test.ts', - 'src/main/runtime/agent-session-record-store-slot.test.ts', - 'src/main/runtime/claude-structured-exit-mid-response.test.ts', - 'src/main/runtime/claude-structured-failed-start-resume.test.ts', - 'src/main/runtime/claude-structured-resumed-start-failure.test.ts', - 'src/main/runtime/claude-structured-send-during-startup.test.ts', - 'src/main/runtime/claude-structured-send-restart-dies-before-dispatch.test.ts', - 'src/main/runtime/claude-structured-session-integration.test.ts', - 'src/main/runtime/claude-structured-startup-fault-is-not-an-exit.test.ts', - 'src/main/runtime/exit-provenance-audit.test.ts', - 'src/main/runtime/orca-runtime-files-artifact-facade.test.ts', - 'src/main/runtime/orchestration-cli-subprocess.test.ts', - 'src/main/runtime/orchestration-mailbox-delivery.test.ts', - 'src/main/runtime/orchestration-mailbox-routing.test.ts', - 'src/main/runtime/orchestration-mailbox-notification-consistency.test.ts', - 'src/main/runtime/orchestration-message-delivery-identity.test.ts', - 'src/main/runtime/orchestration-messages-fake-parity.test.ts', - 'src/main/runtime/orchestration/agent-facing-parity.test.ts', - 'src/main/runtime/orchestration/coordinator-decision-gates.test.ts', - 'src/main/runtime/orchestration/coordinator-dispatch-unobserved-prompt.test.ts', - 'src/main/runtime/orchestration/coordinator-drift-probe-coalescing.test.ts', - 'src/main/runtime/orchestration/coordinator-escalation-triage.test.ts', - 'src/main/runtime/orchestration/coordinator-terminal-census-unavailable.test.ts', - 'src/main/runtime/orchestration/coordinator.test.ts', - 'src/main/runtime/orchestration/db-empty-dispatch-shortcircuit.benchmark.test.ts', - 'src/main/runtime/orchestration/db-heartbeat-straggler-guard.test.ts', - 'src/main/runtime/orchestration/db-message-timestamp.test.ts', - 'src/main/runtime/orchestration/db-messages.test.ts', - 'src/main/runtime/orchestration/db-stopping-worker-task-guard.test.ts', - 'src/main/runtime/orchestration/db-task-create-readiness.test.ts', - 'src/main/runtime/orchestration/db-task-dispatch-invariant.test.ts', - 'src/main/runtime/orchestration/db-task-dispatch-lifecycle-guards.test.ts', - 'src/main/runtime/orchestration/db-task-dispatch-races.test.ts', - 'src/main/runtime/orchestration/db-task-promotion-projection.test.ts', - 'src/main/runtime/orchestration/db-undelivered-mailboxes.test.ts', - 'src/main/runtime/orchestration/db.test.ts', - 'src/main/runtime/orchestration/db/attempt-outcome-projection.test.ts', - 'src/main/runtime/orchestration/db/dispatch-depth.test.ts', - 'src/main/runtime/orchestration/db/dispatch-mailbox-consumer-fencing.test.ts', - 'src/main/runtime/orchestration/db/federation/federated-dispatch-observation-fence.test.ts', - 'src/main/runtime/orchestration/db/federation/remote-dispatch-attachment-release.test.ts', - 'src/main/runtime/orchestration/db/hot-path-statement-compilation.test.ts', - 'src/main/runtime/orchestration/db/lifecycle-transition.test.ts', - 'src/main/runtime/orchestration/db/messages/mailbox-consumer-lifecycle-fencing.test.ts', - 'src/main/runtime/orchestration/db/remaining-dispatch-statement-compilation.test.ts', - 'src/main/runtime/orchestration/db/row-column-lists.test.ts', - 'src/main/runtime/orchestration/db/runs/run-coordinator-orca-session-binding.test.ts', - 'src/main/runtime/orchestration/db/schema/derived-delivery-migration.test.ts', - 'src/main/runtime/orchestration/db/schema/federated-home-run-migration.test.ts', - 'src/main/runtime/orchestration/db/schema/structured-pointer-schema-migration.test.ts', - 'src/main/runtime/orchestration/db/schema/structured-worker-orca-session-backfill.test.ts', - 'src/main/runtime/orchestration/db/worker-dispatch/failed-start-circuit-breaker.test.ts', - 'src/main/runtime/orchestration/db/worker-dispatch/worker-dispatch-abandon.test.ts', - 'src/main/runtime/orchestration/db/worker-dispatch/worker-dispatch-assignee-orca-session.test.ts', - 'src/main/runtime/orchestration/db/writer-run-required.test.ts', - 'src/main/runtime/orchestration/dispatch-consumer-generation-migration.test.ts', - 'src/main/runtime/orchestration/dispatch-creator-identity-migration.test.ts', - 'src/main/runtime/orchestration/dispatch-failure-idempotency.test.ts', - 'src/main/runtime/orchestration/federation-acknowledgment-integrity.test.ts', - 'src/main/runtime/orchestration/federation-acknowledgment-migration.test.ts', - 'src/main/runtime/orchestration/federation-sync.test.ts', - 'src/main/runtime/orchestration/lifecycle-caller-edges.test.ts', - 'src/main/runtime/orchestration/lifecycle-reconciliation.test.ts', - 'src/main/runtime/orchestration/lightweight-run-worker-exit-escalation.test.ts', - 'src/main/runtime/orchestration/mailbox-pointer-eligibility.test.ts', - 'src/main/runtime/orchestration/mailbox-pointer-release-query.test.ts', - 'src/main/runtime/orchestration/mailbox-pointer-stage.test.ts', - 'src/main/runtime/orchestration/mailbox-pointer-submit.test.ts', - 'src/main/runtime/orchestration/message-batch-atomicity.test.ts', - 'src/main/runtime/orchestration/mutation-receipt-capacity.test.ts', - 'src/main/runtime/orchestration/nested-worker-depth-migration.test.ts', - 'src/main/runtime/orchestration/orchestration-adopted-run-binding.test.ts', - 'src/main/runtime/orchestration/orchestration-all-start-versions-migration.test.ts', - 'src/main/runtime/orchestration/orchestration-creator-authority-performance.test.ts', - 'src/main/runtime/orchestration/orchestration-db-permissions.test.ts', - 'src/main/runtime/orchestration/orchestration-delivery-consumption.test.ts', - 'src/main/runtime/orchestration/orchestration-derived-delivery.test.ts', - 'src/main/runtime/orchestration/orchestration-federated-legacy-probe.test.ts', - 'src/main/runtime/orchestration/orchestration-legacy-coordinator-authority-db.test.ts', - 'src/main/runtime/orchestration/orchestration-legacy-question-migration-db.test.ts', - 'src/main/runtime/orchestration/orchestration-legacy-storage-db.test.ts', - 'src/main/runtime/orchestration/orchestration-mutation-question-db.test.ts', - 'src/main/runtime/orchestration/orchestration-orca-session-column-migration.test.ts', - 'src/main/runtime/orchestration/orchestration-party-location.test.ts', - 'src/main/runtime/orchestration/orchestration-reset-db.test.ts', - 'src/main/runtime/orchestration/orchestration-run-delivery-db.test.ts', - 'src/main/runtime/orchestration/orchestration-run-list-compatibility.test.ts', - 'src/main/runtime/orchestration/orchestration-version-skew-migration.test.ts', - 'src/main/runtime/orchestration/orchestration-worker-dispatch-db.test.ts', - 'src/main/runtime/orchestration/r1-identity-migration.test.ts', - 'src/main/runtime/orchestration/run-coordinator-handle-migration.test.ts', - 'src/main/runtime/orchestration/run-coordinator-orca-session-address.test.ts', - 'src/main/runtime/orchestration/settled-question-threads-migration.test.ts', - 'src/main/runtime/orchestration/worker-dispatch-repair-safety.test.ts', - 'src/main/runtime/orchestration/worker-dispatch-settlement.test.ts', - 'src/main/runtime/orchestration/worker-start-unobserved-prompt-settlement.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-instant-tab.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-restart-replay.test.ts', - 'src/main/runtime/rpc/methods/native-chat-opencode-semantic-pages.test.ts', - 'src/main/runtime/rpc/methods/native-chat-opencode-wire-page-budget.test.ts', - 'src/main/runtime/rpc/methods/orchestration-dispatch-error-codes.test.ts', - 'src/main/runtime/rpc/methods/orchestration-structured-worker-redrive.test.ts', - 'src/main/runtime/rpc/methods/orchestration-worker-mode-opacity.test.ts', - 'src/main/runtime/rpc/methods/orchestration-worker-release-incarnation-fallback.test.ts', - 'src/main/runtime/rpc/methods/orchestration-worker-start-mode-selection.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federated-message-targeting.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federated-release-safety.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federated-worker-start-receipt.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-agent-launch.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-control-mail.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-folder-placement.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-launched-agent-readiness.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-lifecycle-settlement.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-liveness-verdict.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-output.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-setup.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-start-prompt-budget.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-worker-brief-agent-in-front.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation.test.ts', - 'src/main/runtime/rpc/methods/orchestration/messaging/check-worker-federated-attachment.test.ts', - 'src/main/runtime/rpc/methods/orchestration/runs/migration-behavior.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/agent-status-producer-census.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/failed-start-retry-release.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/manual-dispatch-observation.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/manual-dispatch-release.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/worker-interactive-wait.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/worker-list-pagination.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/worker-release-recovery.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/worker-start-prompt-contract.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/worker-stop-liveness-verdict.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/worker-terminal-custody-at-creation.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/workers-new-worktree.test.ts', - 'src/main/runtime/rpc/methods/orchestration/worker/workers-recovery.test.ts', - 'src/main/runtime/rpc/methods/structured-worker-stop-receipt.test.ts', - 'src/main/runtime/rpc/orchestration-11745-regression-verification.test.ts', - 'src/main/runtime/rpc/orchestration-commit-notify-characterization.test.ts', - 'src/main/runtime/rpc/orchestration-contract-fence.test.ts', - 'src/main/runtime/rpc/orchestration-legacy-coordinator-race.test.ts', - 'src/main/runtime/rpc/orchestration-legacy-question-takeover.test.ts', - 'src/main/runtime/rpc/orchestration-legacy-takeover-delivery.test.ts', - 'src/main/runtime/rpc/orchestration-legacy-takeover-dispatcher.test.ts', - 'src/main/runtime/rpc/orchestration-mutation-executor.test.ts', - 'src/main/runtime/rpc/orchestration-mutation-ledger.test.ts', - 'src/main/runtime/rpc/orchestration-mutation-request-show.test.ts', - 'src/main/runtime/rpc/orchestration-runtime-update-settlement.test.ts', - 'src/main/runtime/rpc/orchestration-task-dispatch-invariant.test.ts', - 'src/main/runtime/rpc/terminal-prompt-delivery-receipt.test.ts', - 'src/main/runtime/runtime-orchestration-sender-names.test.ts', - 'src/main/runtime/runtime-rpc-long-poll-transport.test.ts', - 'src/main/runtime/runtime-orchestration-sender-names.test.ts', - 'src/main/runtime/runtime-rpc-orchestration-db-migration.test.ts', - 'src/main/runtime/runtime-rpc-request-authorization.test.ts', - 'src/main/runtime/runtime-rpc-websocket-long-poll-caps.test.ts', - 'src/main/runtime/settled-worker-process-replacement.test.ts', - 'src/main/runtime/structured-agent-launch-args-wiring.test.ts', - 'src/main/runtime/structured-agent-session-codex-compact-exit.test.ts', - 'src/main/runtime/structured-agent-session-codex-held-sends.test.ts', - 'src/main/runtime/structured-agent-session-codex-stopped-send-order.test.ts', - 'src/main/runtime/structured-agent-session-codex-turn-end-settlement.test.ts', - 'src/main/runtime/structured-agent-session-held-signal.test.ts', - 'src/main/runtime/structured-agent-session-host-refusal.test.ts', - 'src/main/runtime/structured-agent-session-install-failure.test.ts', - 'src/main/runtime/structured-agent-session-install-reservation.test.ts', - 'src/main/runtime/structured-agent-session-legacy-send-behind-command.test.ts', - 'src/main/runtime/structured-agent-session-mobile-restore.test.ts', - 'src/main/runtime/structured-agent-session-runtime-exit.test.ts', - 'src/main/runtime/structured-agent-session-runtime-provider-started.test.ts', - 'src/main/runtime/structured-agent-session-runtime.test.ts', - 'src/main/runtime/structured-child-records-switch.test.ts', - 'src/main/runtime/structured-claude-auth-policy-wiring.test.ts', - 'src/main/runtime/structured-codex-child-work-runtime.test.ts', - 'src/main/runtime/structured-worker-at-rest.test.ts', - 'src/main/runtime/worker-terminal-archive-release.test.ts', - 'src/main/runtime/worker-terminal-archive-screen.test.ts', - 'src/main/runtime/worker-terminal-wrap-provenance.test.ts', - 'tests/e2e/completed-worker-retirement-resume.unit.test.ts', - 'tests/e2e/cross-version-wire/agent-session-clear-old-client.unit.test.ts', - 'tests/e2e/cross-version-wire/agent-session-clear-old-tab-mirror.unit.test.ts' -] diff --git a/config/scripts/vitest-sqlite-runtime-boundary.test.ts b/config/scripts/vitest-sqlite-runtime-boundary.test.ts index 4c86e8a57b8..c53b7547cda 100644 --- a/config/scripts/vitest-sqlite-runtime-boundary.test.ts +++ b/config/scripts/vitest-sqlite-runtime-boundary.test.ts @@ -1,57 +1,11 @@ -import { globSync, readFileSync } from 'node:fs' -import { basename, dirname, resolve } from 'node:path' -import ts from 'typescript-api' +import { existsSync } from 'node:fs' import { expect, it } from 'vitest' -import { discoverUnitFiles } from './ci-unit-files.mjs' -import { NODE_RUNTIME_INCLUDE } from './vitest-node-runtime-files.mjs' +import { importsSqliteRuntime, SQLITE_MODULES } from './vitest-sqlite-runtime-scan.mjs' -const sqliteHarnesses = new Set([ - 'persistence-test-harness', - 'agent-session-record-store-test-harness', - 'structured-agent-session-rest-test-rig', - 'journal-host-database-test-support' -]) -const sqliteModules = new Set([ - resolve('src/main/sqlite/sync-database'), - resolve('src/main/native-chat/agent-session-journal/journal-host-database'), - resolve('src/main/runtime/orchestration/db'), - resolve('src/main/runtime/orchestration/db/orchestration-db'), - resolve('src/main/runtime/structured-agent-session-runtime'), - resolve('src/main/runtime/agent-session-record-store-slot') -]) - -/** Type-only names do not erase a default binding or an empty import's side effects. */ -function importsSqliteRuntime(file: string, source: string): boolean { - const module = ts.createSourceFile(file, source, ts.ScriptTarget.Latest) - return module.statements.some((statement) => { - if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) { - return false - } - const clause = statement.importClause - const bindings = clause?.namedBindings - if ( - clause?.isTypeOnly || - (!clause?.name && - bindings && - ts.isNamedImports(bindings) && - bindings.elements.length > 0 && - bindings.elements.every((name) => name.isTypeOnly)) - ) { - return false - } - return ( - sqliteHarnesses.has( - basename(statement.moduleSpecifier.text).replace(/\.[cm]?[jt]sx?$/, '') - ) || - sqliteModules.has( - resolve( - dirname(resolve(file)), - statement.moduleSpecifier.text.replace(/\.[cm]?[jt]sx?$/, '') - ) - ) - ) - }) -} +// A moved module would silently send its importers back to Bun. +it.each(SQLITE_MODULES)('scans for a SQLite module that still exists: %s', (module) => { + expect(existsSync(`${module}.ts`)).toBe(true) +}) it.each([ ['import { createRestTestRig } from "./structured-agent-session-rest-test-rig"', true], @@ -61,32 +15,10 @@ it.each([ ['import "./sync-database"', true], ['import { Database } from "./sync-database"', true], ['import * as Database from "./sync-database"', true], + ['import { OrchestrationDb } from "../runtime/orchestration/db"', true], ['import type Database from "./sync-database"', false], ['import type { Options } from "./sync-database"', false], ['import { type Options } from "./sync-database"', false] ])('classifies the runtime dependency in %s', (source, runtime) => { expect(importsSqliteRuntime('src/main/sqlite/example.test.ts', source)).toBe(runtime) }) - -it('keeps real SQLite fixtures and database consumers in the Node runtime project', () => { - const root = process.cwd() - const nodeFiles = new Set(globSync(NODE_RUNTIME_INCLUDE).map((file) => resolve(root, file))) - const missing: string[] = [] - for (const file of discoverUnitFiles(root)) { - const source = readFileSync(resolve(root, file), 'utf8') - if ( - ![...sqliteHarnesses].some((name) => source.includes(name)) && - !source.includes('sync-database') && - !source.includes('journal-host-database') && - !source.includes('structured-agent-session-runtime') && - !source.includes('agent-session-record-store-slot') && - !source.includes('db') - ) { - continue - } - if (importsSqliteRuntime(file, source) && !nodeFiles.has(resolve(root, file))) { - missing.push(file) - } - } - expect(missing).toEqual([]) -}) diff --git a/config/scripts/vitest-sqlite-runtime-cache.test.ts b/config/scripts/vitest-sqlite-runtime-cache.test.ts new file mode 100644 index 00000000000..cef4a816fa5 --- /dev/null +++ b/config/scripts/vitest-sqlite-runtime-cache.test.ts @@ -0,0 +1,34 @@ +import { createHash } from 'node:crypto' +import type * as FileSystem from 'node:fs' +import { readFileSync } from 'node:fs' +import { expect, it, vi } from 'vitest' + +it('re-derives SQLite assignments from malformed disposable cache data', async () => { + const version = createHash('sha256') + .update(readFileSync(new URL('./vitest-sqlite-runtime-scan.mjs', import.meta.url))) + .digest('hex') + for (const files of [null, { 'fixture.test.ts': [1, 2, 'false'] }]) { + vi.doMock('node:fs', async (original) => ({ + ...(await original()), + globSync: () => ['fixture.test.ts'], + statSync: () => ({ mtimeMs: 1, size: 2 }), + readFileSync: (path: Parameters[0]) => + String(path).endsWith('.json') + ? JSON.stringify({ version, files }) + : String(path).endsWith('fixture.test.ts') + ? 'export {}' + : readFileSync(path), + mkdirSync: vi.fn(), + writeFileSync: vi.fn(), + renameSync: vi.fn() + })) + vi.resetModules() + try { + const { findSqliteRuntimeTests } = await import('./vitest-sqlite-runtime-scan.mjs') + expect(findSqliteRuntimeTests()).toEqual([]) + } finally { + vi.doUnmock('node:fs') + vi.resetModules() + } + } +}) diff --git a/config/scripts/vitest-sqlite-runtime-files.mjs b/config/scripts/vitest-sqlite-runtime-files.mjs deleted file mode 100644 index a189678f545..00000000000 --- a/config/scripts/vitest-sqlite-runtime-files.mjs +++ /dev/null @@ -1,306 +0,0 @@ -import { SQLITE_DATABASE_RUNTIME_INCLUDE } from './vitest-sqlite-database-runtime-files.mjs' - -// Real SQLite fixtures keep Node publication and close semantics. -export const SQLITE_RUNTIME_INCLUDE = [ - 'src/main/pi/rpc-session-adapter.test.ts', - 'src/main/pi/rpc-session-startup.test.ts', - 'src/main/acp/acp-structured-publish-at-spawn.test.ts', - 'tests/e2e/native-chat-startup-option-pickers.unit.test.ts', - ...SQLITE_DATABASE_RUNTIME_INCLUDE, - 'src/main/ipc/repos/project-host-setup-wsl-move-fence.test.ts', - 'src/main/ipc/repos/repo-ipc-wsl-move-fence.test.ts', - 'src/main/runtime/runtime-managed-worktree-metadata-wsl-move.test.ts', - 'src/main/persistence/moving-wsl-projects/wsl-move-session-freeze.test.ts', - 'src/main/wsl-move-scan-pruning.test.ts', - 'src/main/repo-backfill-wsl-move.test.ts', - 'src/main/acp/acp-structured-host-live-listing.test.ts', - 'src/main/acp/acp-structured-host-configured-default.test.ts', - 'src/main/acp/acp-structured-omp-recordings.test.ts', - 'src/main/acp/acp-text-stream-identity.test.ts', - 'src/main/acp/acp-text-message-ownership.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-clear-queued-command.test.ts', - 'src/main/acp/acp-structured-sign-in.test.ts', - 'src/main/acp/acp-structured-auth.test.ts', - 'src/main/acp/acp-structured-prompt-failure.test.ts', - 'src/main/acp/acp-timeline-turn-failures.test.ts', - 'src/main/acp/acp-structured-session-adapter.test.ts', - 'src/main/acp/acp-structured-session-adapter-resume.test.ts', - 'src/main/acp/acp-structured-host-start-aborts.test.ts', - 'src/main/acp/acp-conversation-copy.test.ts', - 'src/main/pi/rpc-turn-races.test.ts', - 'src/main/acp/acp-structured-child-session-end.test.ts', - 'src/main/acp/acp-structured-child-stop.test.ts', - 'src/main/acp/acp-structured-child-work-admission.test.ts', - 'src/main/acp/acp-structured-child-work.test.ts', - 'src/main/acp/acp-structured-host-subagent-stop.test.ts', - 'src/main/acp/acp-timeline-grok-subagent-retention.test.ts', - 'src/main/acp/acp-scripted-child-runtime.test.ts', - 'src/main/active-view-persistence-boundary.test.ts', - 'src/main/automations/automation-dispatch-host-fence.test.ts', - 'src/main/automations/automation-owner-fencing.test.ts', - 'src/main/automations/automation-skip-coalescing.test.ts', - 'src/main/automations/automation-update-host-retarget.test.ts', - 'src/main/automations/automation-workspace-host-attribution.test.ts', - 'src/main/automations/automation-wsl-move-refusal.test.ts', - 'src/main/automations/automation-zero-grace-tick-latency.test.ts', - 'src/main/automations/retained-run-reconciliation.test.ts', - 'src/main/automations/run-completion-watcher.test.ts', - 'src/main/automations/service-precheck.test.ts', - 'src/main/automations/service.test.ts', - 'src/main/claude/claude-api-retry-idle-sweep.test.ts', - 'src/main/claude/claude-api-retry-row.test.ts', - 'src/main/claude/claude-context-usage-restart.test.ts', - 'src/main/claude/claude-context-usage-unloaded-turn.test.ts', - 'src/main/claude/claude-informational-row.test.ts', - 'src/main/claude/claude-stream-json-connection.test.ts', - 'src/main/claude/claude-structured-journal-translation.test.ts', - 'src/main/claude/claude-structured-provider-fallback.test.ts', - 'src/main/claude/claude-subagent-permission-request.test.ts', - 'src/main/claude/claude-subagent-resume-after-restart.test.ts', - 'src/main/codex/codex-provider-retry-idle-sweep.test.ts', - 'src/main/codex/codex-structured-journal-context-usage.test.ts', - 'src/main/codex/codex-structured-journal-exit-convergence.test.ts', - 'src/main/codex/codex-structured-journal-goal-revision.test.ts', - 'src/main/codex/codex-structured-journal-repeated-questions.test.ts', - 'src/main/codex/codex-structured-journal-settlement-rollback.test.ts', - 'src/main/codex/codex-structured-journal-subagent-readers.test.ts', - 'src/main/codex/codex-structured-journal-translation-turn-lifecycle.test.ts', - 'src/main/codex/codex-structured-journal-turn-settles-once-journal.test.ts', - 'src/main/ipc/repos/folder-workspace-attachment-handlers.test.ts', - 'src/main/ipc/ssh/ssh-host-server-on-connect-wiring.test.ts', - 'src/main/native-chat/agent-session-attachments/agent-session-attachment-claims.test.ts', - 'src/main/native-chat/agent-session-attachments/agent-session-attachment-sweep.test.ts', - 'src/main/native-chat/agent-session-wire/agent-session-bounded-frames.test.ts', - 'src/main/native-chat/agent-session-wire/agent-session-history-byte-accounting.test.ts', - 'src/main/native-chat/agent-session-wire/agent-session-history-conversation-window.test.ts', - 'src/main/native-chat/agent-session-wire/agent-session-history-forward-read-budget.test.ts', - 'src/main/native-chat/agent-session-wire/agent-session-history-page.test.ts', - 'src/main/native-chat/agent-session-wire/agent-session-stop-note-projection.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-accept-then-deliver.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-acquire-isolation.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-adopted-import.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-append-delivery.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-at-rest-commands.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-attach-reconciliation.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-attachment-admission.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-background-stop-unreadable.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-compact-stop.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-echo-working.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-hung-start-stop.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-opening-send-hold.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-queued-stop.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-root-exit.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-ends-session.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-exit-ends-record.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-subagent-row.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-note-end.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-turn-end.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-close-aborts-start.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-close-verdict.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-codex-stop-note-end.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-codex-stop-row.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-command-publication.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-conversation-stop.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-conversations.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-crash-mid-start.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-crash-turn-end.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-create.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-dead-generation-settlement.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-event-sink.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-failed-create-owner-verdict.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-current-work.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-forget-status.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-fork-rewind.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-held-child-lease-renewal.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-host-runtime-state.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-host.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-idle-sweep.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-journal-corruption.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-late-proof-tool-ends.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-late-settlement.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-lease-renewer.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-exit-delivery.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-ended-prompt-cancel.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-legacy-handoff-record.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-live-turn-window.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-message-choices.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-newer-content-host.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-send-options.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-owed-work-release.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-processless-reservation.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-prompt-answer-receipts.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-prompt-cancel.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-provider-open.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-ready-operation-order.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-action-receipts.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-gate.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-newer-orca.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-pause-lift.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-queued-repeat-press.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-read-restore.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-readable-restorer.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-reasoning-sweep.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-recovered-turn-clock.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-recovery-exits.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-recovery-resolution.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-repeated-stop.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-resend-answer.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-replaced-server-turn.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-resend-ledger-refusal.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-resolved-append.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-resumed-child-owner.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-restart-offer-newer-orca.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-restart-offer-withdrawal.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-restart-provider-output.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-restart-recovery-output.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-restart-restore.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-restart-stream-duration.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-rewind-at-rest.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-rewind-live-send.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-rewind-provenance.test.ts', - 'src/main/native-chat/agent-session-wire/structured-rewind-cut.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-rewind.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-clear-rewind.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-send-idempotency.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-send-open-stale-turn.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-send.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-send-restarts-failed-start.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-shutdown-cut-row.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-stale-turn-verdict.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-stale-turn-open.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-start-admission.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-start-failure-writer.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-startup-attempt-host.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-startup-attempt-registrations.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-startup-reconcile-failure.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed-child-work.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed-child.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed-children.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed-clock.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed-launch-directory.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed-stopping.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-status-reentry.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-stop-note-opened-turn.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-stop-note-withdrawn-send.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-stop-receipts.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-stopping-journal.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-subagent-recency.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-subagent-rows.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-subscriber-background-tasks.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-subscribers.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-target-reconcile.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-thread-goal.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-transition.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-turns.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-unnamed-stop-races.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-unopened-tab.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-unsent-send-hold.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-view-start-after-failed-start.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-wedged-profile-migration.test.ts', - 'src/main/native-chat/agent-session-wire/structured-agent-session-wire-admission.test.ts', - 'src/main/native-chat/agent-session-wire/structured-conversation-command.test.ts', - 'src/main/native-chat/agent-session-wire/structured-conversation-compaction.test.ts', - 'src/main/opencode/opencode-acp-stored-messages.test.ts', - 'src/main/orcad/orcad-automations.test.ts', - 'src/main/orcad/orcad-local-serve-selection.test.ts', - 'src/main/orcad/orcad-managed-idle-exit-chat-provider.test.ts', - 'src/main/orcad/serve-profile-ssh-targets.test.ts', - 'src/main/pi/rpc-launch-resolution.test.ts', - 'src/main/runtime/agent-session-conversation-clear-commit.test.ts', - 'src/main/runtime/agent-session-conversation-name-store.test.ts', - 'src/main/runtime/agent-session-death-evidence-persistence.test.ts', - 'src/main/runtime/agent-session-launch-directory.test.ts', - 'src/main/runtime/agent-session-launch-env-admission.test.ts', - 'src/main/runtime/agent-session-lease-renewal.test.ts', - 'src/main/runtime/agent-session-record-store-tab-table.test.ts', - 'src/main/runtime/agent-session-record-store.test.ts', - 'src/main/runtime/agent-session-permission-backfill.test.ts', - 'src/main/runtime/agent-session-released-reservation-replay.test.ts', - 'src/main/runtime/agent-session-runtime-attribution.test.ts', - 'src/main/runtime/agent-session-store-transactions.test.ts', - 'src/main/runtime/agent-session-unsaved-creation-supersession.test.ts', - 'src/main/runtime/automation-change-publication.test.ts', - 'src/main/runtime/host-terminal-close-persistence-durability.test.ts', - 'src/main/runtime/orca-runtime-terminal-close-records.test.ts', - 'src/main/runtime/orca-runtime-terminal-surface-close.test.ts', - 'src/main/runtime/runtime-terminal-orphan-adoption-rollback.test.ts', - 'src/main/runtime/orchestration/mailbox-owner.test.ts', - 'src/main/runtime/orchestration/orchestration-party-location.test.ts', - 'src/main/runtime/orchestration/structured-worker-journal-page.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-at-rest.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-caller-selection.test.ts', - 'src/main/runtime/rpc/methods/orchestration/federation/federation-agent-death-liveness.test.ts', - 'tests/e2e/agent-launch-cli.unit.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-folder-workspace-create.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-instant-tab.test.ts', - 'src/main/runtime/orca-runtime.test.ts', - 'src/main/runtime/worktree-agent-first-surface.test.ts', - 'tests/e2e/agent-launch-setup-choice.unit.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-pane-reservation.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-prestart-failure.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-replay.test.ts', - 'src/main/runtime/rpc/methods/agent-launch-session-reservation.test.ts', - 'src/main/runtime/rpc/methods/structured-agent-session-adoption-replay.test.ts', - 'src/main/runtime/rpc/methods/structured-agent-session-at-rest.test.ts', - 'src/main/runtime/rpc/methods/structured-agent-session-close-before-create.test.ts', - 'src/main/runtime/rpc/methods/structured-agent-session-create-message.test.ts', - 'src/main/runtime/rpc/methods/structured-agent-session-options-workspace-scope.test.ts', - 'src/main/runtime/rpc/methods/structured-agent-session-restart-unregistered-agent.test.ts', - 'src/main/runtime/rpc/methods/structured-agent-session-unsubscribe.test.ts', - 'src/main/runtime/rpc/methods/structured-chat-tab-table.test.ts', - 'src/main/runtime/runtime-managed-worktree-metadata-sweep.test.ts', - 'src/main/runtime/runtime-orchestration-sender-names.test.ts', - 'src/main/runtime/runtime-worktree-agent-rows-verdict.test.ts', - 'src/main/runtime/runtime-worktree-structured-agent-rows-liveness.test.ts', - 'src/main/runtime/structured-agent-session-codex-interrupt-order.test.ts', - 'src/main/runtime/structured-agent-session-codex-opening-send-hold.test.ts', - 'src/main/runtime/runtime-client-agent-launch-settings-durability.test.ts', - 'src/main/runtime/structured-agent-session-codex-scripted-child.test.ts', - 'src/main/runtime/structured-agent-session-codex-start-deadline.test.ts', - 'src/main/runtime/structured-agent-session-pi-startup.test.ts', - 'src/main/runtime/structured-agent-session-pi-signed-out-start.test.ts', - 'src/main/runtime/structured-agent-session-adapter-start-failure.test.ts', - 'src/main/runtime/structured-agent-session-provider-operations-while-starting.test.ts', - 'src/main/runtime/structured-agent-session-codex-settlement-order.test.ts', - 'src/main/runtime/structured-agent-session-integration-replay.test.ts', - 'src/main/runtime/structured-agent-session-integration.test.ts', - 'src/main/runtime/structured-agent-session-mobile-restore.test.ts', - 'src/main/runtime/structured-agent-session-paired-caller.test.ts', - 'src/main/runtime/structured-agent-session-rollback-compatibility.test.ts', - 'src/main/runtime/structured-agent-session-spawn-token-descendants.test.ts', - 'src/main/runtime/structured-agent-session-startup-reconcile.test.ts', - 'src/main/runtime/structured-claude-attachment-grant.test.ts', - 'src/main/runtime/structured-claude-pending-rewind.test.ts', - 'src/main/runtime/structured-foreground-command-strip.test.ts', - 'src/main/ssh-expired-lease-pane-readoption.test.ts', - 'src/main/ssh-reattach-pane-cardinality.test.ts', - 'src/main/ssh/legacy-relay/legacy-relay-cli-call-limits.test.ts', - 'src/main/ssh/legacy-relay/legacy-relay-cli-legacy-records.test.ts', - 'src/main/ssh/legacy-relay/legacy-relay-cli-server.test.ts', - 'src/main/ssh/orcad-migration-cutover-coordinator.test.ts', - 'src/main/ssh/orcad-migration-delta-move.test.ts', - 'src/main/ssh/orcad-migration-delta-snapshot.test.ts', - 'src/main/ssh/orcad-migration-repository-link.test.ts', - 'src/main/ssh/orcad-migration-snapshot-resume.test.ts', - 'src/main/ssh/orcad-migration-source-fence.test.ts', - 'src/main/ssh/orcad-migration-ssh-relay-source.test.ts', - 'src/main/ssh/orcad-migration-stuck-host-profiles.test.ts', - 'src/main/managed-server/lifecycle/orcad-runtime-conversion.test.ts', - 'src/main/ssh/orcad-unreachable-setup-release.test.ts', - 'src/main/ssh/targets/ssh-target-orcad-preflight.test.ts', - 'src/main/worktree-identity-persistence.test.ts', - 'src/main/worktree-removal-close-records.test.ts', - 'src/main/worktree-removal-session-partition-fencing.test.ts', - 'tests/e2e/codex-child-approval-activity-row.unit.test.ts', - 'tests/e2e/cross-version-wire/agent-session-newer-chat-refusal.unit.test.ts', - 'tests/e2e/cross-version-wire/agent-session-stop-event-downgrade.unit.test.ts', - 'tests/e2e/cross-version-wire/cross-version-agent-session-wire.unit.test.ts', - 'tests/e2e/cross-version-wire/submission-positions-downgrade.unit.test.ts', - 'tests/e2e/folder-upgrade-identity-persistence.unit.test.ts', - 'tests/e2e/host-agent-launch-settings-hook-bookkeeping.unit.test.ts', - 'tests/e2e/structured-agent-session-read-owner.unit.test.ts', - 'tests/e2e/structured-chat-owner-status-activation.unit.test.ts' -] diff --git a/config/scripts/vitest-sqlite-runtime-scan.mjs b/config/scripts/vitest-sqlite-runtime-scan.mjs new file mode 100644 index 00000000000..4fbf7c5b0eb --- /dev/null +++ b/config/scripts/vitest-sqlite-runtime-scan.mjs @@ -0,0 +1,132 @@ +import { createHash } from 'node:crypto' +import { globSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs' +import { createRequire } from 'node:module' +import { basename, dirname, join, resolve } from 'node:path' +import { defaultExclude } from 'vitest/config' +import { UNIT_INCLUDE } from './ci-unit-files.mjs' + +const require = createRequire(import.meta.url) +const root = resolve(import.meta.dirname, '../..') +// Keyed by checkout, since worktrees can share one node_modules. +const CACHE_FILE = join( + root, + 'node_modules', + '.cache', + `orca-vitest-sqlite-runtime-${createHash('sha256').update(root).digest('hex').slice(0, 16)}.json` +) +const SOURCE_EXTENSION = /\.[cm]?[jt]sx?$/ +const SQLITE_HARNESSES = new Set([ + 'persistence-test-harness', + 'agent-session-record-store-test-harness', + 'structured-agent-session-rest-test-rig', + 'journal-host-database-test-support' +]) +export const SQLITE_MODULES = [ + 'src/main/sqlite/sync-database', + 'src/main/native-chat/agent-session-journal/journal-host-database', + 'src/main/runtime/orchestration/db', + 'src/main/runtime/orchestration/db/orchestration-db', + 'src/main/runtime/structured-agent-session-runtime', + 'src/main/runtime/agent-session-record-store-slot' +] +const SQLITE_MODULE_PATHS = new Set(SQLITE_MODULES.map((module) => resolve(root, module))) +// A cheap superset of the parse below; a bare 'db' would match nearly every file. +const SQLITE_MODULE_NAMES = [ + ...SQLITE_HARNESSES, + ...SQLITE_MODULES.map((module) => basename(module)) +].filter((name) => name !== 'db') +const DB_MODULE_SPECIFIER = /\/db(?:\.[cm]?[jt]sx?)?['"]/ + +function namesSqliteModule(source) { + return ( + SQLITE_MODULE_NAMES.some((name) => source.includes(name)) || DB_MODULE_SPECIFIER.test(source) + ) +} + +/** Type-only names do not erase a default binding or an empty import's side effects. */ +export function importsSqliteRuntime(file, source) { + if (!namesSqliteModule(source)) { + return false + } + // Loaded on demand so a warm cache skips the compiler entirely. + const ts = require('typescript-api') + const module = ts.createSourceFile(file, source, ts.ScriptTarget.Latest) + return module.statements.some((statement) => { + if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) { + return false + } + const clause = statement.importClause + const bindings = clause?.namedBindings + if ( + clause?.isTypeOnly || + (!clause?.name && + bindings && + ts.isNamedImports(bindings) && + bindings.elements.length > 0 && + bindings.elements.every((name) => name.isTypeOnly)) + ) { + return false + } + const specifier = statement.moduleSpecifier.text.replace(SOURCE_EXTENSION, '') + return ( + SQLITE_HARNESSES.has(basename(specifier)) || + SQLITE_MODULE_PATHS.has(resolve(root, dirname(file), specifier)) + ) + }) +} + +function readCache(version) { + try { + const cache = JSON.parse(readFileSync(CACHE_FILE, 'utf8')) + return cache.version === version && cache.files && typeof cache.files === 'object' + ? cache.files + : {} + } catch { + return {} + } +} + +/** Unit tests that load Node SQLite through a direct import, as repo-relative paths. */ +export function findSqliteRuntimeTests() { + // Why: reading every test costs about a second; unchanged files reuse their last verdict. + const version = createHash('sha256') + .update(readFileSync(import.meta.filename)) + .digest('hex') + const cached = readCache(version) + const files = {} + let changed = false + for (const file of globSync(UNIT_INCLUDE, { cwd: root, exclude: defaultExclude })) { + const path = file.replaceAll('\\', '/') + const { mtimeMs, size } = statSync(resolve(root, path)) + const entry = cached[path] + if ( + Array.isArray(entry) && + entry[0] === mtimeMs && + entry[1] === size && + typeof entry[2] === 'boolean' + ) { + files[path] = entry + continue + } + files[path] = [ + mtimeMs, + size, + importsSqliteRuntime(path, readFileSync(resolve(root, path), 'utf8')) + ] + changed = true + } + if (changed || Object.keys(cached).length !== Object.keys(files).length) { + try { + mkdirSync(dirname(CACHE_FILE), { recursive: true }) + const temporary = `${CACHE_FILE}.${process.pid}` + writeFileSync(temporary, JSON.stringify({ version, files })) + // Why: parallel runs each rename a whole file, so a reader never sees a partial write. + renameSync(temporary, CACHE_FILE) + } catch { + // The cache only saves time; the verdicts above are already complete. + } + } + return Object.keys(files) + .filter((path) => files[path][2]) + .sort() +} diff --git a/config/vitest.config.ts b/config/vitest.config.ts index 49ef5ffcfca..a590717b7e6 100644 --- a/config/vitest.config.ts +++ b/config/vitest.config.ts @@ -4,10 +4,11 @@ import { defaultExclude, defineConfig } from 'vitest/config' import { UNIT_INCLUDE, UNIT_EXCLUDE } from './scripts/ci-unit-files.mjs' import TimingSequencer from './scripts/ci-unit-sequencer.mjs' import RuntimeSequencer from './scripts/vitest-runtime-sequencer.mjs' -import { NODE_RUNTIME_INCLUDE } from './scripts/vitest-node-runtime-files.mjs' +import { getNodeRuntimeInclude } from './scripts/vitest-node-runtime-files.mjs' import { nodeRuntimePool } from './scripts/vitest-node-runtime-pool' import { createWorkspaceSourceResolver } from './scripts/workspace-source-exports.mjs' +const nodeRuntimeInclude = process.versions.bun ? getNodeRuntimeInclude() : [] const balancedShards = process.env.ORCA_BALANCE_UNIT_SHARDS === '1' const measurementFile = 'src/main/foreign-sqlite-readers/foreign-sqlite-reader-event-loop.test.ts' const paletteMeasurementFile = @@ -64,7 +65,7 @@ const nodeProject = { ...testOptions, name: process.versions.bun ? 'node-runtime' : 'node', env: { ORCA_VITEST_RUNTIME: process.versions.bun ? 'node-runtime' : 'node' }, - include: process.versions.bun ? NODE_RUNTIME_INCLUDE : UNIT_INCLUDE, + include: process.versions.bun ? nodeRuntimeInclude : UNIT_INCLUDE, exclude: [...testOptions.exclude, ...measurementFiles], sequence: { groupOrder: 1 }, ...(process.versions.bun @@ -80,7 +81,7 @@ const bunProject = { name: 'bun', env: { ORCA_VITEST_RUNTIME: 'bun' }, pool: 'forks', - exclude: [...testOptions.exclude, ...NODE_RUNTIME_INCLUDE, ...measurementFiles], + exclude: [...testOptions.exclude, ...nodeRuntimeInclude, ...measurementFiles], sequence: { groupOrder: 1 } } }