Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/cli/src/commands/migrate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,13 @@ function makeCortexkitDb() {

afterEach(() => {
for (const db of databases.splice(0)) db.close();
for (const dir of tempDirs.splice(0)) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs.splice(0)) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
});

describe("migrateOpenCodeSessionToPi", () => {
Expand Down
9 changes: 7 additions & 2 deletions packages/pi-plugin/src/system-prompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ function countOccurrences(haystack: string, needle: string): number {
describe("buildMagicContextBlock", () => {
afterEach(() => {
setAftAvailabilityOverride(null);
for (const dir of tempDirs.splice(0))
rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs.splice(0)) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
});

it("returns null when no memories, session history, or docs exist (guidance off)", () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/plugin/src/config/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ function loadWithUserConfig(configText: string, extraEnv: Record<string, string>
if (v === undefined) delete process.env[k];
else process.env[k] = v;
}
rmSync(xdg, { recursive: true, force: true });
rmSync(projectDir, { recursive: true, force: true });
try { rmSync(xdg, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
try { rmSync(projectDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
}

Expand Down Expand Up @@ -81,8 +81,8 @@ function loadWithUserAndProjectConfig(
if (v === undefined) delete process.env[k];
else process.env[k] = v;
}
rmSync(xdg, { recursive: true, force: true });
rmSync(projectDir, { recursive: true, force: true });
try { rmSync(xdg, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
try { rmSync(projectDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/plugin/src/config/variable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe("substituteConfigVariables", () => {
});

afterEach(() => {
rmSync(tmpDir, { recursive: true, force: true });
try { rmSync(tmpDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
process.env = { ...ORIGINAL_ENV };
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { Database } from "../../shared/sqlite";
import { closeQuietly } from "../../shared/sqlite-helpers";
import {
type DeferredExecutePayload,
peekDeferredExecutePending,
Expand Down Expand Up @@ -50,16 +51,22 @@ function payload(id: string): DeferredExecutePayload {
describe("deferred execute CAS race", () => {
it("15. one WAL handle wins set-if-absent and the other no-ops", () => {
const dir = mkdtempSync(join(tmpdir(), "boundary-exec-race-"));
const path = join(dir, "context.db");
const a = createRaceDb(path);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Move createRaceDb calls back inside try to preserve teardown guarantee. If createRaceDb throws on b, a leaks and the temp dir is never deleted.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/plugin/src/features/magic-context/boundary-execution-cas-race.test.ts, line 55:

<comment>Move `createRaceDb` calls back inside `try` to preserve teardown guarantee. If `createRaceDb` throws on `b`, `a` leaks and the temp dir is never deleted.</comment>

<file context>
@@ -50,16 +51,22 @@ function payload(id: string): DeferredExecutePayload {
     it("15. one WAL handle wins set-if-absent and the other no-ops", () => {
         const dir = mkdtempSync(join(tmpdir(), "boundary-exec-race-"));
+        const path = join(dir, "context.db");
+        const a = createRaceDb(path);
+        const b = createRaceDb(path);
         try {
</file context>
Fix with Cubic

const b = createRaceDb(path);
try {
const path = join(dir, "context.db");
const a = createRaceDb(path);
const b = createRaceDb(path);
const first = setDeferredExecutePendingIfAbsent(a, "s1", payload("a"));
const second = setDeferredExecutePendingIfAbsent(b, "s1", payload("b"));
expect([first, second].filter(Boolean)).toHaveLength(1);
expect(peekDeferredExecutePending(a, "s1")?.id).toBe(first ? "a" : "b");
} finally {
rmSync(dir, { recursive: true, force: true });
closeQuietly(a);
closeQuietly(b);
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ describe("compartment state lease", () => {
const db = makeDb();
const first = acquireCompartmentLease(db, "ses", "holder-a");
expect(first).not.toBeNull();

db.prepare("UPDATE compartment_state_lease SET expires_at = ? WHERE session_id = ?").run(
Date.now() + 1_000,
"ses",
);

const second = acquireCompartmentLease(db, "ses", "holder-a");
expect(second).not.toBeNull();
expect(second!.expiresAt).toBeGreaterThan(first!.acquiredAt + 1_000);
Expand All @@ -56,10 +58,12 @@ describe("compartment state lease", () => {
it("lets another holder reclaim an expired lease", () => {
const db = makeDb();
expect(acquireCompartmentLease(db, "ses", "holder-a")).not.toBeNull();

db.prepare("UPDATE compartment_state_lease SET expires_at = ? WHERE session_id = ?").run(
Date.now() - 1,
"ses",
);

expect(acquireCompartmentLease(db, "ses", "holder-b")).not.toBeNull();
expect(isCompartmentLeaseHeld(db, "ses", "holder-b")).toBe(true);
expect(isCompartmentLeaseHeld(db, "ses", "holder-a")).toBe(false);
Expand All @@ -70,6 +74,7 @@ describe("compartment state lease", () => {
const db = makeDb();
expect(acquireCompartmentLease(db, "ses", "holder-a")).not.toBeNull();
expect(renewCompartmentLease(db, "ses", "holder-b")).toBe(false);

db.prepare("UPDATE compartment_state_lease SET expires_at = ? WHERE session_id = ?").run(
Date.now() - 1,
"ses",
Expand All @@ -81,10 +86,12 @@ describe("compartment state lease", () => {
it("release is a no-op after another holder reclaims the row", () => {
const db = makeDb();
expect(acquireCompartmentLease(db, "ses", "holder-a")).not.toBeNull();

db.prepare("UPDATE compartment_state_lease SET expires_at = ? WHERE session_id = ?").run(
Date.now() - 1,
"ses",
);

expect(acquireCompartmentLease(db, "ses", "holder-b")).not.toBeNull();
releaseCompartmentLease(db, "ses", "holder-a");
expect(isCompartmentLeaseHeld(db, "ses", "holder-b")).toBe(true);
Expand All @@ -105,7 +112,11 @@ describe("compartment state lease", () => {
} finally {
closeQuietly(dbA);
closeQuietly(dbB);
rmSync(dir, { recursive: true, force: true });
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
});

Expand All @@ -114,10 +125,13 @@ describe("compartment state lease", () => {
const path = join(dir, "context.db");
const setup = makeDb(path);
closeQuietly(setup);

try {
const pluginRoot = process.cwd().endsWith("/packages/plugin")
? process.cwd()
: join(process.cwd(), "packages", "plugin");
const projectRoot = process.cwd().includes("packages")
? join(process.cwd(), "..", "..")
: process.cwd();
const pluginRoot = join(projectRoot, "packages", "plugin");

const script = `
const sqlite = await import(${JSON.stringify(`file://${pluginRoot}/src/shared/sqlite.ts`)});
const storageDb = await import(${JSON.stringify(`file://${pluginRoot}/src/features/magic-context/storage-db.ts`)});
Expand All @@ -128,13 +142,18 @@ describe("compartment state lease", () => {
db.close();
console.log(JSON.stringify({ ok }));
`;

const [a, b] = await Promise.all([
$`bun -e ${script} holder-a`.json() as Promise<{ ok: boolean }>,
$`bun -e ${script} holder-b`.json() as Promise<{ ok: boolean }>,
]);
expect([a.ok, b.ok].filter(Boolean)).toHaveLength(1);
} finally {
rmSync(dir, { recursive: true, force: true });
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ function useTempDataHome(prefix: string): string {

afterEach(() => {
closeDatabase();
for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
tempDirs.length = 0;
process.env.XDG_DATA_HOME = undefined;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ afterEach(() => {
process.env.XDG_DATA_HOME = originalXdgDataHome;

for (const dir of tempDirs) {
rmSync(dir, { recursive: true, force: true });
try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
tempDirs.length = 0;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const originalHome = process.env.HOME;
afterEach(() => {
setAftAvailabilityOverride(null);
process.env.HOME = originalHome;
for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs) try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
tempDirs.length = 0;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ describe("embedding module", () => {
_resetEmbeddingSweepGuard();
process.env.XDG_DATA_HOME = originalXdgDataHome;
for (const dir of tempDirs) {
rmSync(dir, { recursive: true, force: true });
try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
tempDirs.length = 0;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/// <reference types="bun-types" />

import { afterEach, describe, expect, test } from "bun:test";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
Expand Down Expand Up @@ -27,7 +29,13 @@ function useTempDataHome(prefix: string): string {

afterEach(() => {
closeDatabase();
for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows where closeDatabase doesn't synchronously release locks
}
}
tempDirs.length = 0;
process.env.XDG_DATA_HOME = undefined;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ function count(db: Database, table: string): number {

afterEach(() => {
closeDatabase();
for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
tempDirs.length = 0;
process.env.XDG_DATA_HOME = undefined;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ function useTempDataHome(prefix: string): string {

afterEach(() => {
closeDatabase();
for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
tempDirs.length = 0;
process.env.XDG_DATA_HOME = undefined;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ function useTempDataHome(prefix: string): void {

afterEach(() => {
closeDatabase();
for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
tempDirs.length = 0;
process.env.XDG_DATA_HOME = undefined;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ function useTempDataHome(prefix: string): void {

afterEach(() => {
closeDatabase();
for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true });
for (const dir of tempDirs) {
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
tempDirs.length = 0;
process.env.XDG_DATA_HOME = undefined;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ describe("migration v20", () => {
} finally {
closeDatabase();
process.env.XDG_DATA_HOME = undefined;
rmSync(dir, { recursive: true, force: true });
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ describe("migration v21", () => {
} finally {
closeDatabase();
process.env.XDG_DATA_HOME = undefined;
rmSync(dir, { recursive: true, force: true });
try {
rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
} catch {
// Ignore EBUSY on Windows
}
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe("project embedding registry", () => {
closeDatabase();
process.env.XDG_DATA_HOME = originalXdgDataHome;
for (const dir of tempDirs) {
rmSync(dir, { recursive: true, force: true });
try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
tempDirs.length = 0;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe("resolveIsSubagentFromOpenCodeDb", () => {
} else {
process.env.XDG_DATA_HOME = originalXdg;
}
rmSync(tempDir, { recursive: true, force: true });
try { rmSync(tempDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
});

it("returns true for a child session with a non-empty parent_id", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe("sticky-injection CAS helpers", () => {
{ messageId: "m2", text: "text-2" },
]);
} finally {
rmSync(dir, { recursive: true, force: true });
try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
});

Expand All @@ -51,7 +51,7 @@ describe("sticky-injection CAS helpers", () => {
expect(pruneNoteNudgeAnchors(a, "s1", new Set(["m2"]))).toBe(1);
expect(getNoteNudgeAnchors(b, "s1")).toEqual([{ messageId: "m2", text: "text-2" }]);
} finally {
rmSync(dir, { recursive: true, force: true });
try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
});

Expand All @@ -70,7 +70,7 @@ describe("sticky-injection CAS helpers", () => {
});
expect(getNoteNudgeAnchors(db, "s1")).toEqual([{ messageId: "m1", text: "text-1" }]);
} finally {
rmSync(dir, { recursive: true, force: true });
try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
});

Expand All @@ -93,7 +93,7 @@ describe("sticky-injection CAS helpers", () => {
}),
).toEqual({ ok: true, kind: "already-present", decision: stored });
} finally {
rmSync(dir, { recursive: true, force: true });
try { rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { /* Ignore EBUSY on Windows */ };
}
});
});
Loading