diff --git a/scripts/run-vitest-stable.mjs b/scripts/run-vitest-stable.mjs index a3ef4ba4c0b..42f13cddcff 100644 --- a/scripts/run-vitest-stable.mjs +++ b/scripts/run-vitest-stable.mjs @@ -55,6 +55,11 @@ const generalWorkspacesBGroupName = "general-workspaces-b"; const generalWorkspacesAProjects = ["@paperclipai/ui", "paperclipai"]; const generalWorkspacesBProjects = nonServerProjects.filter((project) => !generalWorkspacesAProjects.includes(project)); const generalGroupNames = [generalServerGroupName, generalWorkspacesAGroupName, generalWorkspacesBGroupName]; +const serializedServerVitestArgs = [ + "--no-file-parallelism", + "--maxWorkers=1", + "--minWorkers=1", +]; function walk(dir) { const entries = readdirSync(dir); @@ -241,6 +246,7 @@ function runVitest(args, label) { // Keep per-run paths compact so Unix socket fixtures stay under macOS path limits. const env = { ...process.env, + NODE_ENV: "test", PAPERCLIP_HOME: path.join(testRoot, "h"), PAPERCLIP_INSTANCE_ID: `vt-${process.pid}-${invocationIndex}`, TMPDIR: path.join(testRoot, "t"), @@ -277,7 +283,12 @@ function runGeneralGroup(routeTests, groupName) { if (groupName === generalServerGroupName) { const excludeRouteArgs = routeTests.flatMap((file) => ["--exclude", file.serverPath]); runVitest( - ["--project", "@paperclipai/server", ...excludeRouteArgs], + [ + "--project", + "@paperclipai/server", + ...serializedServerVitestArgs, + ...excludeRouteArgs, + ], `${groupName} server suites excluding ${routeTests.length} serialized suites`, ); return; diff --git a/server/src/__tests__/health-dev-server-token.test.ts b/server/src/__tests__/health-dev-server-token.test.ts index 536ef66c3be..e50b0930f11 100644 --- a/server/src/__tests__/health-dev-server-token.test.ts +++ b/server/src/__tests__/health-dev-server-token.test.ts @@ -96,6 +96,7 @@ describe("GET /health dev-server supervisor access", () => { expect(res.body).toEqual({ status: "ok", deploymentMode: "authenticated", + deploymentExposure: "private", bootstrapStatus: "ready", bootstrapInviteActive: false, devServer: { diff --git a/server/src/__tests__/heartbeat-comment-wake-batching.test.ts b/server/src/__tests__/heartbeat-comment-wake-batching.test.ts index 606f69bca95..117ae4bb35e 100644 --- a/server/src/__tests__/heartbeat-comment-wake-batching.test.ts +++ b/server/src/__tests__/heartbeat-comment-wake-batching.test.ts @@ -442,12 +442,18 @@ describe("heartbeat comment wake batching", () => { gateway.releaseFirstWait(); await waitFor(() => gateway.getAgentPayloads().length === 2); + const secondPayload = gateway.getAgentPayloads()[1] ?? {}; + const secondRunId = typeof secondPayload.idempotencyKey === "string" ? secondPayload.idempotencyKey : null; + if (!secondRunId) { + throw new Error("Expected forwarded gateway payload to include an idempotencyKey run id"); + } + await waitFor(async () => { const runs = await db.select().from(heartbeatRuns).where(eq(heartbeatRuns.agentId, agentId)); - return runs.length === 2 && runs.every((run) => run.status === "succeeded"); + const statusesByRunId = new Map(runs.map((run) => [run.id, run.status])); + return statusesByRunId.get(firstRun!.id) === "succeeded" && statusesByRunId.get(secondRunId) === "succeeded"; }, 90_000); - const secondPayload = gateway.getAgentPayloads()[1] ?? {}; expect(secondPayload.paperclip).toMatchObject({ wake: { commentIds: [comment2.id, comment3.id],