test: remove the no-op sequential describe modifier (#15286)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip runs the server and runner test suites with Vitest.
> - Vitest 5 removes the deprecated `describe.sequential` property, so
the pending Vitest 5 upgrade fails the type-check and test jobs.
> - `describe.sequential` only changes behaviour inside a
`describe.concurrent` suite, or when `sequence.concurrent` is on.
> - This repository has neither, so the modifier changed nothing at run
time.
> - The benefit is that the Vitest 5 upgrade can land, and the test
files lose a modifier that did no work.

## Linked Issues or Issue Description

Refs: #12969

## What Changed

- Replace every `describe.sequential` use with a plain `describe` call.
- Drop the `{ concurrent: false }` suite option from the two runner test
files.
- Add a comment to `server/vitest.config.ts` that records why these
suites must run one test at a time.
- Leave the package manifests and the lockfile unchanged.

## Why the modifier did nothing

The Vitest documentation states that `describe.sequential` is useful to
run tests in sequence inside a `describe.concurrent` suite, or with the
`--sequence.concurrent` option. `sequence.concurrent` defaults to
`false`.

This repository satisfies neither condition:

- No test file uses `describe.concurrent`, `it.concurrent`, or
`test.concurrent`.
- `server/vitest.config.ts` sets `sequence.concurrent: false`, with
`maxWorkers: 1`, `maxConcurrency: 1`, and `isolate: true`.
- `packages/paperclip-runner/vitest.config.ts` sets no `sequence` block,
so the `false` default applies.

`packages/db` and `cli` already run the same embedded-Postgres suites
with a plain `describe`, and those jobs are green. The server package
was the only outlier.

The modifier did carry one real piece of knowledge: these suites need
their tests to run one at a time. The new comment in
`server/vitest.config.ts` records that reason next to the setting that
enforces it.

## Verification

- `git grep` for `describe.sequential` returns nothing outside
`node_modules`.
- The author ran the changed server test files under the installed
Vitest 4, and the results match the results without this change.
- Two very large embedded-Postgres test files exceeded the author's
local memory limit, so the CI test jobs cover those two.
- The two changed runner test files have pre-existing local failures
caused by a missing Rust toolchain and a missing global `pnpm` binary.
The failures are identical with and without this change.
- The author type-checked the changed files and found no new error.
- CI must pass the typecheck, build, server test, and runner verify
jobs.

## Risks

- Low risk. Suite execution stays serial, because the Vitest config
enforces it.
- The change adds no dependency and changes no package manifest or
lockfile.
- A future change that turns `sequence.concurrent` on would break these
suites. The new config comment warns against it.

## Model Used

- Claude Sonnet 5 — code edits and local verification.
- OpenAI Codex, GPT-5 — the earlier revision of this branch.

## Test plan

- [x] Every CI check reaches a terminal green state. A pending or queued
check is not a pass.
- [x] The `Typecheck + Release Registry` job passes. This change must
not introduce a type error.
- [x] The `Build` job passes.
- [x] The server test jobs and the runner verify jobs pass.
- [x] Greptile re-reviews this commit set and posts a passing verdict.
The dependabot waiver does not apply to this pull request.
- [x] `mergeable` reads `MERGEABLE` as a terminal value.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have linked the related public issue with `Refs: #12969`
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-Authored-By: Priya Raman <priya.raman@paperclip.ing>

---------

Co-authored-by: Priya Raman <priya.raman@paperclip.ing>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: nickyleach <331803+nickyleach@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-10-06 07:19:15 -07:00
1 parent 90182b4f8b
commit 1477d1ecea
46 files changed
+52 -49

No files matched your search

@@ -1445,7 +1445,7 @@ it("refuses a processing-drain absence claim while local or remote ingress remai
}
});
describe.sequential("DurablePrpControlPlane", () => {
describe("DurablePrpControlPlane", () => {
it.each(["pending_first", "all_pending", "completed_first"] as const)(
"retains unanswered semantic input across the bounded event window (%s)",
async (mode) => {
@@ -13,7 +13,7 @@ import {
startLocalRunnerScenario,
} from "./local-runner.js";
describe.sequential("Local runner and fake harness", () => {
describe("Local runner and fake harness", () => {
it("runs lifecycle, tool, file, structured-result, and process-exit events", async () => {
const trace = await runLocalRunnerScenario({ scenario: "happy-path", delayMs: 1 });
const eventTypes = trace.events.map((event) => event.eventType);
+1 -1
View File
@@ -101,7 +101,7 @@ async function requestApp(
}
}
describe.sequential("activity routes", () => {
describe("activity routes", () => {
beforeEach(() => {
for (const mock of Object.values(mockActivityService)) mock.mockReset();
for (const mock of Object.values(mockHeartbeatService)) mock.mockReset();
@@ -258,7 +258,7 @@ function resetInstalledExternalAdapterState() {
setOverridePaused("claude_local", false);
}
describe.sequential("adapter management route authorization", () => {
describe("adapter management route authorization", () => {
beforeEach(async () => {
vi.resetModules();
vi.doUnmock("../services/adapter-plugin-store.js");
@@ -343,7 +343,7 @@ function resetMockDefaults() {
mockLogActivity.mockImplementation(async () => undefined);
}
describe.sequential("agent cross-tenant route authorization", () => {
describe("agent cross-tenant route authorization", () => {
beforeEach(() => {
resetMockDefaults();
});
@@ -267,7 +267,7 @@ async function requestApp(
}
}
describe.sequential("agent permission routes", () => {
describe("agent permission routes", () => {
const routeModules = hoistModuleGraph(registerModuleMocks, async () => {
const [{ errorHandler }, { agentRoutes }] = await Promise.all([
vi.importActual<typeof import("../middleware/index.js")>("../middleware/index.js"),
@@ -249,7 +249,7 @@ function makeAgent(adapterType: string) {
};
}
describe.sequential("agent skill routes", () => {
describe("agent skill routes", () => {
beforeEach(async () => {
vi.resetModules();
vi.doUnmock("../routes/agents.js");
+1 -1
View File
@@ -51,7 +51,7 @@ function createApp(actor: Express.Request["actor"], row: Record<string, unknown>
return app;
}
describe.sequential("auth routes", () => {
describe("auth routes", () => {
const baseUser = {
id: "user-1",
name: "Jane Example",
+1 -1
View File
@@ -37,7 +37,7 @@ import { instanceSettingsService } from "../services/instance-settings.js";
import type { StorageService } from "../storage/types.js";
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -198,7 +198,7 @@ const embeddedPostgresSupport = externalTestDatabaseUrl
? { supported: true }
: await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported
? describe.sequential
? describe
: describe.skip;
if (!embeddedPostgresSupport.supported) {
+1 -1
View File
@@ -90,7 +90,7 @@ async function createApp(actor: any, db: any = {} as any) {
return app;
}
describe.sequential("cli auth routes", () => {
describe("cli auth routes", () => {
beforeEach(() => {
vi.resetModules();
vi.doUnmock("../services/index.js");
@@ -215,7 +215,7 @@ function boardActor(input: {
};
}
describe.sequential("company route cross-company authorization", () => {
describe("company route cross-company authorization", () => {
beforeEach(() => {
vi.resetModules();
vi.doUnmock("../routes/authz.js");
@@ -89,7 +89,7 @@ vi.mock("../services/company-import-transfers.js", async (importOriginal) => {
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported
? describe.sequential
? describe
: describe.skip;
const companyId = "11111111-1111-4111-8111-111111111111";
@@ -334,7 +334,7 @@ const importMeta = {
collisionStrategy: importRequest.collisionStrategy,
};
describe.sequential("company portability routes", () => {
describe("company portability routes", () => {
beforeEach(() => {
vi.clearAllMocks();
mockAgentService.getById.mockImplementation(async (id: string) => ({
@@ -26,7 +26,7 @@ import { errorHandler } from "../middleware/error-handler.js";
import { companySkillRoutes } from "../routes/company-skills.js";
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -164,7 +164,7 @@ async function closeServer(server: Server | null) {
});
}
describe.sequential("execution environment route guards", () => {
describe("execution environment route guards", () => {
afterAll(async () => {
await closeServer(projectServer);
await closeServer(issueServer);
@@ -236,7 +236,7 @@ function mockVerifiedReseed(
* stable 409 while a control is genuinely live, and a start that fails must leave the workspace
* stopped and retryable instead of "desired running" with residue.
*/
describe.sequential("execution workspace runtime control conflict and failure reconciliation", () => {
describe("execution workspace runtime control conflict and failure reconciliation", () => {
beforeEach(() => {
vi.clearAllMocks();
mockSpawn.mockReset();
@@ -88,7 +88,7 @@ function createApp(actor: Record<string, unknown> = {
return app;
}
describe.sequential("execution workspace routes", () => {
describe("execution workspace routes", () => {
beforeEach(() => {
vi.clearAllMocks();
mockAccessService.decide.mockResolvedValue({
@@ -22,7 +22,7 @@ import {
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
describeEmbeddedPostgres.sequential("GitHub connection event delivery", () => {
describeEmbeddedPostgres("GitHub connection event delivery", () => {
let db!: ReturnType<typeof createDb>;
let tempDb: Awaited<ReturnType<typeof startEmbeddedPostgresTestDatabase>> | null = null;
@@ -74,7 +74,7 @@ async function createApp(
return app;
}
describe.sequential("GET /invites/:token/test-resolution", () => {
describe("GET /invites/:token/test-resolution", () => {
beforeEach(() => {
vi.clearAllMocks();
});
@@ -204,7 +204,7 @@ async function assertNoBackgroundClearWithinRetryWindow() {
expect(mockExecutionWorkspaceService.clearReopenPendingConsumptionForUnconsumedReopen).not.toHaveBeenCalled();
}
describe.sequential("closed isolated workspace issue routes", () => {
describe("closed isolated workspace issue routes", () => {
const routeModules = hoistModuleGraph(registerServiceMocks, async () => {
const [{ issueRoutes }, { errorHandler }] = await Promise.all([
vi.importActual<typeof import("../routes/issues.js")>("../routes/issues.js"),
@@ -191,7 +191,7 @@ function makeComment(overrides: Record<string, unknown> = {}) {
};
}
describe.sequential("issue comment cancel routes", () => {
describe("issue comment cancel routes", () => {
const routeModules = hoistModuleGraph(registerModuleMocks, async () => {
const [{ issueRoutes }, { errorHandler }] = await Promise.all([
vi.importActual<typeof import("../routes/issues.js")>("../routes/issues.js"),
@@ -43,7 +43,7 @@ const embeddedPostgresSupport = externalTestDatabaseUrl
? { supported: true }
: await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported
? describe.sequential
? describe
: describe.skip;
if (!embeddedPostgresSupport.supported) {
@@ -317,7 +317,7 @@ async function waitForWakeup(assertion: () => void) {
await vi.waitFor(assertion);
}
describe.sequential("issue comment reopen routes", () => {
describe("issue comment reopen routes", () => {
beforeEach(() => {
vi.clearAllMocks();
mockIssueService.getById.mockReset();
@@ -45,7 +45,7 @@ vi.mock("../services/native-runtime/native-session-executor.js", async (importOr
const { NativeSessionSteeringError } = await import("../services/native-runtime/native-session-executor.js");
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -308,7 +308,7 @@ async function resolveMockInteraction(
return interaction;
}
describe.sequential("issue thread interaction routes", () => {
describe("issue thread interaction routes", () => {
beforeEach(async () => {
vi.resetModules();
vi.doUnmock("../routes/issues.js");
@@ -190,7 +190,7 @@ const projectGoal = {
updatedAt: new Date("2026-03-20T00:00:00Z"),
};
describe.sequential("issue goal context routes", () => {
describe("issue goal context routes", () => {
beforeEach(() => {
vi.clearAllMocks();
mockAccessService.decide.mockResolvedValue({
@@ -134,7 +134,7 @@ describe("merged pull-request confirmation extraction", () => {
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
describeEmbeddedPostgres.sequential("merged pull-request confirmation sweep", () => {
describeEmbeddedPostgres("merged pull-request confirmation sweep", () => {
let db!: ReturnType<typeof createDb>;
let tempDb: Awaited<ReturnType<typeof startEmbeddedPostgresTestDatabase>> | null = null;
@@ -12,7 +12,7 @@ import { issueRoutes } from "../routes/issues.js";
import type { StorageService } from "../storage/types.js";
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -126,7 +126,7 @@ function createApp(actor: Record<string, unknown>, db: Record<string, unknown>)
return app;
}
describe.sequential("POST /companies/:companyId/openclaw/invite-prompt", () => {
describe("POST /companies/:companyId/openclaw/invite-prompt", () => {
const companyBranding = {
name: "Acme AI",
logoAssetId: "logo-1",
@@ -73,7 +73,7 @@ function idleStream<T>(): TypedEventStream<T> {
async () => close(),
);
}
describe.sequential("iMessage Photon channel control plane", () => {
describe("iMessage Photon channel control plane", () => {
let database: Awaited<ReturnType<typeof startEmbeddedPostgresTestDatabase>>;
let db: ReturnType<typeof createDb>;
let secrets: string;
@@ -46,7 +46,7 @@ import {
import { instanceSettingsService } from "../services/instance-settings.js";
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -38,7 +38,7 @@ vi.mock("../services/live-events.js", () => ({
}));
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -43,7 +43,7 @@ vi.mock("../services/live-events.js", () => ({
}));
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -144,7 +144,7 @@ function readyPlugin() {
});
}
describe.sequential("plugin install and upgrade authz", () => {
describe("plugin install and upgrade authz", () => {
beforeEach(() => {
vi.clearAllMocks();
});
@@ -410,7 +410,7 @@ describe.sequential("plugin install and upgrade authz", () => {
}, 20_000);
});
describe.sequential("scoped plugin API routes", () => {
describe("scoped plugin API routes", () => {
beforeEach(() => {
vi.clearAllMocks();
});
@@ -476,7 +476,7 @@ describe.sequential("scoped plugin API routes", () => {
}, 20_000);
});
describe.sequential("plugin local folder routes", () => {
describe("plugin local folder routes", () => {
beforeEach(() => {
vi.clearAllMocks();
mockRegistry.getCompanySettings.mockResolvedValue(null);
@@ -531,7 +531,7 @@ describe.sequential("plugin local folder routes", () => {
});
});
describe.sequential("plugin tool and bridge authz", () => {
describe("plugin tool and bridge authz", () => {
beforeEach(() => {
vi.clearAllMocks();
});
@@ -1104,7 +1104,7 @@ describe.sequential("plugin tool and bridge authz", () => {
});
});
describe.sequential("operator-hidden plugin management floor", () => {
describe("operator-hidden plugin management floor", () => {
beforeEach(() => {
vi.clearAllMocks();
process.env.PAPERCLIP_HIDDEN_SETTINGS = "instance.plugins";
@@ -94,7 +94,7 @@ async function createApp(input: {
return { app, workerManager };
}
describe.sequential("plugin scoped API routes", () => {
describe("plugin scoped API routes", () => {
const pluginId = "11111111-1111-4111-8111-111111111111";
const companyId = "22222222-2222-4222-8222-222222222222";
const agentId = "33333333-3333-4333-8333-333333333333";
@@ -23,7 +23,7 @@ import { secretService } from "../services/secrets.js";
const pluginId = "11111111-1111-4111-8111-111111111111";
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
+1 -1
View File
@@ -87,7 +87,7 @@ function registerRoutineServiceMock() {
}
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -12,7 +12,7 @@ import {
import { teamsCatalogService } from "../services/teams-catalog.js";
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe.sequential : describe.skip;
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
if (!embeddedPostgresSupport.supported) {
console.warn(
@@ -202,7 +202,7 @@ function buildExecutionWorkspace(overrides: Record<string, unknown> = {}) {
};
}
describe.sequential("workspace runtime service route authorization", () => {
describe("workspace runtime service route authorization", () => {
const projectId = "11111111-1111-4111-8111-111111111111";
const workspaceId = "22222222-2222-4222-8222-222222222222";
const executionWorkspaceId = "33333333-3333-4333-8333-333333333333";
@@ -116,7 +116,7 @@ function resetMocks() {
mockGetTelemetryClient.mockReturnValue({ track: vi.fn() });
}
describe.sequential("write-path membership checks (viewer / inactive)", () => {
describe("write-path membership checks (viewer / inactive)", () => {
beforeEach(() => {
resetMocks();
});
@@ -32,7 +32,7 @@ const external = process.env.PAPERCLIP_TEST_DATABASE_URL;
const support = external
? { supported: true }
: await getEmbeddedPostgresTestSupport();
const suite = support.supported ? describe.sequential : describe.skip;
const suite = support.supported ? describe : describe.skip;
const token = "PRIVATE-DISCORD-REGISTRATION-TOKEN";
let serial = 0n;
const appId = () =>
@@ -29,7 +29,7 @@ const external = process.env.PAPERCLIP_TEST_DATABASE_URL;
const support = external
? { supported: true }
: await getEmbeddedPostgresTestSupport();
const suite = support.supported ? describe.sequential : describe.skip;
const suite = support.supported ? describe : describe.skip;
suite("Teams same-transaction publication projection (real PostgreSQL)", () => {
let db: ReturnType<typeof createDb>;
let temporary:
@@ -48,7 +48,7 @@ const external = process.env.PAPERCLIP_TEST_DATABASE_URL;
const support = external
? { supported: true }
: await getEmbeddedPostgresTestSupport();
const suite = support.supported ? describe.sequential : describe.skip;
const suite = support.supported ? describe : describe.skip;
const bytes = Buffer.from("Exact Teams file bytes\n");
const uploadUrl =
"https://tenant-my.sharepoint.com/personal/user/_api/upload?token=PRIVATE-TEAMS-UPLOAD-CANARY";
@@ -44,7 +44,7 @@ const managedFixtureDirectory =
process.env.PAPERCLIP_WARM_TRANSITION_MANAGED_FIXTURE_DIRECTORY;
const databaseUrl = process.env.PAPERCLIP_TEST_DATABASE_URL;
const generated =
fixtureDirectory && databaseUrl ? describe.sequential : describe.skip;
fixtureDirectory && databaseUrl ? describe : describe.skip;
type Identity = {
runnerInstanceId: string;
+3
View File
@@ -39,6 +39,9 @@ export default defineConfig({
maxWorkers: 1,
minWorkers: 1,
pool: "forks",
// Server suites share process state and one embedded Postgres instance,
// so tests inside a file must run one at a time. Do not set
// sequence.concurrent to true.
sequence: {
concurrent: false,
hooks: "list",