diff --git a/packages/cli/src/commands/migrate.test.ts b/packages/cli/src/commands/migrate.test.ts index 67e3c41..436427b 100644 --- a/packages/cli/src/commands/migrate.test.ts +++ b/packages/cli/src/commands/migrate.test.ts @@ -183,7 +183,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", () => { diff --git a/packages/plugin/src/config/index.test.ts b/packages/plugin/src/config/index.test.ts index c7f406e..e5ec764 100644 --- a/packages/plugin/src/config/index.test.ts +++ b/packages/plugin/src/config/index.test.ts @@ -42,8 +42,16 @@ function loadWithUserConfig(configText: string, extraEnv: Record 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 */ + } } } @@ -81,8 +89,16 @@ 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 */ + } } } diff --git a/packages/plugin/src/config/variable.test.ts b/packages/plugin/src/config/variable.test.ts index cf52a70..d7db1e6 100644 --- a/packages/plugin/src/config/variable.test.ts +++ b/packages/plugin/src/config/variable.test.ts @@ -14,7 +14,11 @@ 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 }; }); diff --git a/packages/plugin/src/features/magic-context/boundary-execution-cas-race.test.ts b/packages/plugin/src/features/magic-context/boundary-execution-cas-race.test.ts index 3391b31..9a5c876 100644 --- a/packages/plugin/src/features/magic-context/boundary-execution-cas-race.test.ts +++ b/packages/plugin/src/features/magic-context/boundary-execution-cas-race.test.ts @@ -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, @@ -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); + 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 + } } }); }); diff --git a/packages/plugin/src/features/magic-context/compartment-lease.test.ts b/packages/plugin/src/features/magic-context/compartment-lease.test.ts index 6dd1e2c..676ad89 100644 --- a/packages/plugin/src/features/magic-context/compartment-lease.test.ts +++ b/packages/plugin/src/features/magic-context/compartment-lease.test.ts @@ -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); @@ -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); @@ -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", @@ -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); @@ -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 + } } }); @@ -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`)}); @@ -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 + } } }); }); diff --git a/packages/plugin/src/features/magic-context/compartment-storage-v6.test.ts b/packages/plugin/src/features/magic-context/compartment-storage-v6.test.ts index a8a1f1b..7d77482 100644 --- a/packages/plugin/src/features/magic-context/compartment-storage-v6.test.ts +++ b/packages/plugin/src/features/magic-context/compartment-storage-v6.test.ts @@ -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; }); diff --git a/packages/plugin/src/features/magic-context/compression-depth-storage.test.ts b/packages/plugin/src/features/magic-context/compression-depth-storage.test.ts index fced84c..7eb5ee7 100644 --- a/packages/plugin/src/features/magic-context/compression-depth-storage.test.ts +++ b/packages/plugin/src/features/magic-context/compression-depth-storage.test.ts @@ -31,7 +31,11 @@ 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; }); diff --git a/packages/plugin/src/features/magic-context/key-files/project-key-files.test.ts b/packages/plugin/src/features/magic-context/key-files/project-key-files.test.ts index 36a6dff..a0977a8 100644 --- a/packages/plugin/src/features/magic-context/key-files/project-key-files.test.ts +++ b/packages/plugin/src/features/magic-context/key-files/project-key-files.test.ts @@ -30,7 +30,12 @@ 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; }); diff --git a/packages/plugin/src/features/magic-context/memory/embedding.test.ts b/packages/plugin/src/features/magic-context/memory/embedding.test.ts index cc879ce..8b051ae 100644 --- a/packages/plugin/src/features/magic-context/memory/embedding.test.ts +++ b/packages/plugin/src/features/magic-context/memory/embedding.test.ts @@ -132,7 +132,11 @@ 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; }); diff --git a/packages/plugin/src/features/magic-context/migrations-v11.test.ts b/packages/plugin/src/features/magic-context/migrations-v11.test.ts index 2bdd395..17d7752 100644 --- a/packages/plugin/src/features/magic-context/migrations-v11.test.ts +++ b/packages/plugin/src/features/magic-context/migrations-v11.test.ts @@ -1,3 +1,5 @@ +/// + import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; @@ -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; }); diff --git a/packages/plugin/src/features/magic-context/migrations-v12.test.ts b/packages/plugin/src/features/magic-context/migrations-v12.test.ts index 206945c..c9af1c4 100644 --- a/packages/plugin/src/features/magic-context/migrations-v12.test.ts +++ b/packages/plugin/src/features/magic-context/migrations-v12.test.ts @@ -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; }); diff --git a/packages/plugin/src/features/magic-context/migrations-v13.test.ts b/packages/plugin/src/features/magic-context/migrations-v13.test.ts index 38a9713..b25637f 100644 --- a/packages/plugin/src/features/magic-context/migrations-v13.test.ts +++ b/packages/plugin/src/features/magic-context/migrations-v13.test.ts @@ -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; }); diff --git a/packages/plugin/src/features/magic-context/migrations-v16.test.ts b/packages/plugin/src/features/magic-context/migrations-v16.test.ts index 24ffd68..e6e6a28 100644 --- a/packages/plugin/src/features/magic-context/migrations-v16.test.ts +++ b/packages/plugin/src/features/magic-context/migrations-v16.test.ts @@ -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; }); diff --git a/packages/plugin/src/features/magic-context/migrations-v18-pi-marker.test.ts b/packages/plugin/src/features/magic-context/migrations-v18-pi-marker.test.ts index 87bafca..6330379 100644 --- a/packages/plugin/src/features/magic-context/migrations-v18-pi-marker.test.ts +++ b/packages/plugin/src/features/magic-context/migrations-v18-pi-marker.test.ts @@ -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; }); diff --git a/packages/plugin/src/features/magic-context/migrations-v20.test.ts b/packages/plugin/src/features/magic-context/migrations-v20.test.ts index da895f5..6790a55 100644 --- a/packages/plugin/src/features/magic-context/migrations-v20.test.ts +++ b/packages/plugin/src/features/magic-context/migrations-v20.test.ts @@ -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 + } } }); }); diff --git a/packages/plugin/src/features/magic-context/migrations-v21.test.ts b/packages/plugin/src/features/magic-context/migrations-v21.test.ts index 0dd7718..057c9f8 100644 --- a/packages/plugin/src/features/magic-context/migrations-v21.test.ts +++ b/packages/plugin/src/features/magic-context/migrations-v21.test.ts @@ -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 + } } }); }); diff --git a/packages/plugin/src/features/magic-context/project-embedding-registry.test.ts b/packages/plugin/src/features/magic-context/project-embedding-registry.test.ts index a2c2ca2..1be92a4 100644 --- a/packages/plugin/src/features/magic-context/project-embedding-registry.test.ts +++ b/packages/plugin/src/features/magic-context/project-embedding-registry.test.ts @@ -64,7 +64,11 @@ 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; }); diff --git a/packages/plugin/src/features/magic-context/resolve-subagent-fallback.test.ts b/packages/plugin/src/features/magic-context/resolve-subagent-fallback.test.ts index 3ed2b3b..ce0547d 100644 --- a/packages/plugin/src/features/magic-context/resolve-subagent-fallback.test.ts +++ b/packages/plugin/src/features/magic-context/resolve-subagent-fallback.test.ts @@ -51,7 +51,11 @@ 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", () => { diff --git a/packages/plugin/src/features/magic-context/sticky-injection-cas-race.test.ts b/packages/plugin/src/features/magic-context/sticky-injection-cas-race.test.ts index 3474b26..a1da0a5 100644 --- a/packages/plugin/src/features/magic-context/sticky-injection-cas-race.test.ts +++ b/packages/plugin/src/features/magic-context/sticky-injection-cas-race.test.ts @@ -36,7 +36,11 @@ 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 */ + } } }); @@ -51,7 +55,11 @@ 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 */ + } } }); @@ -70,7 +78,11 @@ 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 */ + } } }); @@ -93,7 +105,11 @@ 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 */ + } } }); }); diff --git a/packages/plugin/src/features/magic-context/storage-db-migration.test.ts b/packages/plugin/src/features/magic-context/storage-db-migration.test.ts index 7c9461c..7828437 100644 --- a/packages/plugin/src/features/magic-context/storage-db-migration.test.ts +++ b/packages/plugin/src/features/magic-context/storage-db-migration.test.ts @@ -38,7 +38,11 @@ describe("storage-db legacy migration", () => { delete process.env.XDG_DATA_HOME; } try { - rmSync(tmpRoot, { recursive: true, force: true }); + try { + rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } } catch { // Non-fatal — tests on locked Windows file handles can leave temp // dirs that the OS will clean up later. diff --git a/packages/plugin/src/features/magic-context/storage-db.test.ts b/packages/plugin/src/features/magic-context/storage-db.test.ts index 5b5ad64..322aa0d 100644 --- a/packages/plugin/src/features/magic-context/storage-db.test.ts +++ b/packages/plugin/src/features/magic-context/storage-db.test.ts @@ -34,7 +34,11 @@ 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; }); diff --git a/packages/plugin/src/features/magic-context/storage.test.ts b/packages/plugin/src/features/magic-context/storage.test.ts index a89eba6..e071e26 100644 --- a/packages/plugin/src/features/magic-context/storage.test.ts +++ b/packages/plugin/src/features/magic-context/storage.test.ts @@ -61,7 +61,11 @@ 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; }); diff --git a/packages/plugin/src/features/magic-context/tagger-recovery.test.ts b/packages/plugin/src/features/magic-context/tagger-recovery.test.ts index 56cf83c..1408b1b 100644 --- a/packages/plugin/src/features/magic-context/tagger-recovery.test.ts +++ b/packages/plugin/src/features/magic-context/tagger-recovery.test.ts @@ -414,7 +414,11 @@ describe("initFromDb signature cache", () => { dbA.close(); } } finally { - rmSync(tmpDir, { recursive: true, force: true }); + try { + rmSync(tmpDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } } }); diff --git a/packages/plugin/src/features/magic-context/tool-owner-backfill.test.ts b/packages/plugin/src/features/magic-context/tool-owner-backfill.test.ts index c25ae85..6fef38a 100644 --- a/packages/plugin/src/features/magic-context/tool-owner-backfill.test.ts +++ b/packages/plugin/src/features/magic-context/tool-owner-backfill.test.ts @@ -27,7 +27,11 @@ const originalXdgDataHome = process.env.XDG_DATA_HOME; 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; }); diff --git a/packages/plugin/src/hooks/auto-update-checker/index.test.ts b/packages/plugin/src/hooks/auto-update-checker/index.test.ts index 38169b4..dbe7b25 100644 --- a/packages/plugin/src/hooks/auto-update-checker/index.test.ts +++ b/packages/plugin/src/hooks/auto-update-checker/index.test.ts @@ -61,7 +61,11 @@ afterEach(() => { const dir = tempDirs.pop(); if (!dir) continue; try { - rmSync(dir, { recursive: true, force: true }); + try { + rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } } catch { // Best-effort cleanup } diff --git a/packages/plugin/src/hooks/magic-context/apply-operations.tool-drop.test.ts b/packages/plugin/src/hooks/magic-context/apply-operations.tool-drop.test.ts index 36d6a72..c7cb342 100644 --- a/packages/plugin/src/hooks/magic-context/apply-operations.tool-drop.test.ts +++ b/packages/plugin/src/hooks/magic-context/apply-operations.tool-drop.test.ts @@ -29,7 +29,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/compaction-marker-consistency.test.ts b/packages/plugin/src/hooks/magic-context/compaction-marker-consistency.test.ts index 2f16787..53749e9 100644 --- a/packages/plugin/src/hooks/magic-context/compaction-marker-consistency.test.ts +++ b/packages/plugin/src/hooks/magic-context/compaction-marker-consistency.test.ts @@ -60,7 +60,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/compaction-marker-manager.test.ts b/packages/plugin/src/hooks/magic-context/compaction-marker-manager.test.ts index 7868a49..0e0eeb8 100644 --- a/packages/plugin/src/hooks/magic-context/compaction-marker-manager.test.ts +++ b/packages/plugin/src/hooks/magic-context/compaction-marker-manager.test.ts @@ -98,7 +98,11 @@ afterEach(() => { 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; }); @@ -255,7 +259,7 @@ describe("applyDeferredCompactionMarker — outcomes", () => { // No user message exists at or before the boundary → inject returns // null → retryable-failure. expect(outcome.kind).toBe("retryable-failure"); - // Persisted state remains absent (we never wrote a marker) + // Persisted state remains absent ( we never wrote a marker) const persisted = getPersistedCompactionMarkerState(db, "ses-1"); expect(persisted).toBeNull(); }); diff --git a/packages/plugin/src/hooks/magic-context/compartment-runner-drop-queue.test.ts b/packages/plugin/src/hooks/magic-context/compartment-runner-drop-queue.test.ts index 33a94c1..82ad17f 100644 --- a/packages/plugin/src/hooks/magic-context/compartment-runner-drop-queue.test.ts +++ b/packages/plugin/src/hooks/magic-context/compartment-runner-drop-queue.test.ts @@ -37,7 +37,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/compartment-runner-timeout.test.ts b/packages/plugin/src/hooks/magic-context/compartment-runner-timeout.test.ts index 5ed149b..49f4649 100644 --- a/packages/plugin/src/hooks/magic-context/compartment-runner-timeout.test.ts +++ b/packages/plugin/src/hooks/magic-context/compartment-runner-timeout.test.ts @@ -19,7 +19,11 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/compartment-runner.test.ts b/packages/plugin/src/hooks/magic-context/compartment-runner.test.ts index 268adb5..a2d9513 100644 --- a/packages/plugin/src/hooks/magic-context/compartment-runner.test.ts +++ b/packages/plugin/src/hooks/magic-context/compartment-runner.test.ts @@ -55,13 +55,21 @@ 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; // Clean up historian debug dumps created during tests const dumpDir = join(tmpdir(), "magic-context-historian"); - rmSync(dumpDir, { recursive: true, force: true }); + try { + rmSync(dumpDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + // Ignore EBUSY on Windows + } }); describe("executeContextRecomp", () => { diff --git a/packages/plugin/src/hooks/magic-context/compartment-trigger.test.ts b/packages/plugin/src/hooks/magic-context/compartment-trigger.test.ts index 1ce0a18..adbd757 100644 --- a/packages/plugin/src/hooks/magic-context/compartment-trigger.test.ts +++ b/packages/plugin/src/hooks/magic-context/compartment-trigger.test.ts @@ -22,7 +22,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/event-handler.test.ts b/packages/plugin/src/hooks/magic-context/event-handler.test.ts index 4b848d1..aea509a 100644 --- a/packages/plugin/src/hooks/magic-context/event-handler.test.ts +++ b/packages/plugin/src/hooks/magic-context/event-handler.test.ts @@ -53,7 +53,11 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/historian-state-file.test.ts b/packages/plugin/src/hooks/magic-context/historian-state-file.test.ts index 425a9c6..297e252 100644 --- a/packages/plugin/src/hooks/magic-context/historian-state-file.test.ts +++ b/packages/plugin/src/hooks/magic-context/historian-state-file.test.ts @@ -15,7 +15,11 @@ beforeEach(() => { }); afterEach(() => { - rmSync(tempProjectDir, { recursive: true, force: true }); + try { + rmSync(tempProjectDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } }); describe("maybeWriteHistorianStateFile", () => { diff --git a/packages/plugin/src/hooks/magic-context/hook.test.ts b/packages/plugin/src/hooks/magic-context/hook.test.ts index 15ea16d..79d9ea6 100644 --- a/packages/plugin/src/hooks/magic-context/hook.test.ts +++ b/packages/plugin/src/hooks/magic-context/hook.test.ts @@ -46,7 +46,11 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/nudger.test.ts b/packages/plugin/src/hooks/magic-context/nudger.test.ts index 22354c0..f27de46 100644 --- a/packages/plugin/src/hooks/magic-context/nudger.test.ts +++ b/packages/plugin/src/hooks/magic-context/nudger.test.ts @@ -23,7 +23,11 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/read-session-chunk.test.ts b/packages/plugin/src/hooks/magic-context/read-session-chunk.test.ts index 5e32af5..99a5e47 100644 --- a/packages/plugin/src/hooks/magic-context/read-session-chunk.test.ts +++ b/packages/plugin/src/hooks/magic-context/read-session-chunk.test.ts @@ -20,7 +20,11 @@ const originalXdgDataHome = process.env.XDG_DATA_HOME; 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; }); diff --git a/packages/plugin/src/hooks/magic-context/read-session-db.test.ts b/packages/plugin/src/hooks/magic-context/read-session-db.test.ts index 081563c..dcff47b 100644 --- a/packages/plugin/src/hooks/magic-context/read-session-db.test.ts +++ b/packages/plugin/src/hooks/magic-context/read-session-db.test.ts @@ -21,7 +21,11 @@ afterEach(() => { closeReadOnlySessionDb(); 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; }); diff --git a/packages/plugin/src/hooks/magic-context/system-prompt-hash.test.ts b/packages/plugin/src/hooks/magic-context/system-prompt-hash.test.ts index 627f094..e677cf7 100644 --- a/packages/plugin/src/hooks/magic-context/system-prompt-hash.test.ts +++ b/packages/plugin/src/hooks/magic-context/system-prompt-hash.test.ts @@ -41,7 +41,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/tag-messages-collision.test.ts b/packages/plugin/src/hooks/magic-context/tag-messages-collision.test.ts index 99d8a9f..b934130 100644 --- a/packages/plugin/src/hooks/magic-context/tag-messages-collision.test.ts +++ b/packages/plugin/src/hooks/magic-context/tag-messages-collision.test.ts @@ -30,7 +30,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/tool-input-preservation.test.ts b/packages/plugin/src/hooks/magic-context/tool-input-preservation.test.ts index cc8c83f..7ff80bb 100644 --- a/packages/plugin/src/hooks/magic-context/tool-input-preservation.test.ts +++ b/packages/plugin/src/hooks/magic-context/tool-input-preservation.test.ts @@ -15,7 +15,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform-cache-busting-signals.test.ts b/packages/plugin/src/hooks/magic-context/transform-cache-busting-signals.test.ts index 7d5d866..b250806 100644 --- a/packages/plugin/src/hooks/magic-context/transform-cache-busting-signals.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-cache-busting-signals.test.ts @@ -79,7 +79,11 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform-compartment-phase.test.ts b/packages/plugin/src/hooks/magic-context/transform-compartment-phase.test.ts index 4a95ce8..5e809d2 100644 --- a/packages/plugin/src/hooks/magic-context/transform-compartment-phase.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-compartment-phase.test.ts @@ -84,7 +84,12 @@ beforeEach(() => { afterEach(() => { closeDatabase(); process.env.XDG_DATA_HOME = originalXdgDataHome; - if (tempDir) rmSync(tempDir, { recursive: true, force: true }); + if (tempDir) + try { + rmSync(tempDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } }); describe("runCompartmentPhase - 95% emergency notification idempotency", () => { diff --git a/packages/plugin/src/hooks/magic-context/transform-context-state.test.ts b/packages/plugin/src/hooks/magic-context/transform-context-state.test.ts index 82d041b..a9d09c5 100644 --- a/packages/plugin/src/hooks/magic-context/transform-context-state.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-context-state.test.ts @@ -20,7 +20,11 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform-heuristic-cleanup-persistence.test.ts b/packages/plugin/src/hooks/magic-context/transform-heuristic-cleanup-persistence.test.ts index 99cb6ea..bad9279 100644 --- a/packages/plugin/src/hooks/magic-context/transform-heuristic-cleanup-persistence.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-heuristic-cleanup-persistence.test.ts @@ -118,7 +118,11 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform-index-staleness.test.ts b/packages/plugin/src/hooks/magic-context/transform-index-staleness.test.ts index 05166d0..6b2a012 100644 --- a/packages/plugin/src/hooks/magic-context/transform-index-staleness.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-index-staleness.test.ts @@ -38,7 +38,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform-nudge-cache.test.ts b/packages/plugin/src/hooks/magic-context/transform-nudge-cache.test.ts index 9f12f34..bded1b5 100644 --- a/packages/plugin/src/hooks/magic-context/transform-nudge-cache.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-nudge-cache.test.ts @@ -35,7 +35,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform-operations.test.ts b/packages/plugin/src/hooks/magic-context/transform-operations.test.ts index aaf33f4..d047359 100644 --- a/packages/plugin/src/hooks/magic-context/transform-operations.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-operations.test.ts @@ -33,7 +33,11 @@ afterEach(() => { 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform-todo-state.test.ts b/packages/plugin/src/hooks/magic-context/transform-todo-state.test.ts index 3de86f0..59de33d 100644 --- a/packages/plugin/src/hooks/magic-context/transform-todo-state.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform-todo-state.test.ts @@ -43,7 +43,12 @@ 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; }); diff --git a/packages/plugin/src/hooks/magic-context/transform.test.ts b/packages/plugin/src/hooks/magic-context/transform.test.ts index ac88195..78471f7 100644 --- a/packages/plugin/src/hooks/magic-context/transform.test.ts +++ b/packages/plugin/src/hooks/magic-context/transform.test.ts @@ -77,7 +77,11 @@ afterEach(() => { else process.env.XDG_CACHE_HOME = originalXdgCacheHome; 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; }); diff --git a/packages/plugin/src/shared/announcement.test.ts b/packages/plugin/src/shared/announcement.test.ts index a76a97e..032b4aa 100644 --- a/packages/plugin/src/shared/announcement.test.ts +++ b/packages/plugin/src/shared/announcement.test.ts @@ -35,7 +35,8 @@ afterEach(() => { process.env.XDG_DATA_HOME = originalXdg; } try { - fs.rmSync(tmpRoot, { recursive: true, force: true }); + // maxRetries/retryDelay ride out transient EBUSY/EPERM on Windows. + fs.rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); } catch { // best-effort } diff --git a/packages/plugin/src/shared/conflict-detector.test.ts b/packages/plugin/src/shared/conflict-detector.test.ts index 1a297c0..67b51a1 100644 --- a/packages/plugin/src/shared/conflict-detector.test.ts +++ b/packages/plugin/src/shared/conflict-detector.test.ts @@ -46,8 +46,21 @@ describe("detectConflicts", () => { else process.env[k] = v; } // Test directories live under tmpdir(); cleanup is best-effort. - rmSync(projectDir, { recursive: true, force: true }); - rmSync(userConfigDir, { recursive: true, force: true }); + try { + rmSync(projectDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } + try { + rmSync(userConfigDir, { + recursive: true, + force: true, + maxRetries: 10, + retryDelay: 100, + }); + } catch { + /* Ignore EBUSY on Windows */ + } }); function writeProjectConfig(plugins: Array): void { diff --git a/packages/plugin/src/shared/conflict-fixer.test.ts b/packages/plugin/src/shared/conflict-fixer.test.ts index 744a80a..0a3d56d 100644 --- a/packages/plugin/src/shared/conflict-fixer.test.ts +++ b/packages/plugin/src/shared/conflict-fixer.test.ts @@ -38,7 +38,11 @@ describe("fixConflicts", () => { if (value === undefined) delete process.env[key]; else process.env[key] = value; } - rmSync(root, { recursive: true, force: true }); + try { + rmSync(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } }); it("preserves JSONC comments and tuple plugin entries while removing canonical DCP", () => { diff --git a/packages/plugin/src/shared/models-dev-cache.test.ts b/packages/plugin/src/shared/models-dev-cache.test.ts index 18b58af..09b6f51 100644 --- a/packages/plugin/src/shared/models-dev-cache.test.ts +++ b/packages/plugin/src/shared/models-dev-cache.test.ts @@ -39,7 +39,11 @@ describe("models-dev-cache", () => { if (v === undefined) delete process.env[k]; else process.env[k] = v; } - rmSync(tempDir, { recursive: true, force: true }); + try { + rmSync(tempDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } clearModelsDevCache(); }); diff --git a/packages/plugin/src/shared/opencode-compaction-detector.test.ts b/packages/plugin/src/shared/opencode-compaction-detector.test.ts index 5f64da7..748e39a 100644 --- a/packages/plugin/src/shared/opencode-compaction-detector.test.ts +++ b/packages/plugin/src/shared/opencode-compaction-detector.test.ts @@ -18,7 +18,11 @@ describe("opencode-compaction-detector", () => { }); afterEach(() => { - rmSync(tmpDir, { recursive: true, force: true }); + try { + rmSync(tmpDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } delete process.env.OPENCODE_DISABLE_AUTOCOMPACT; }); @@ -30,7 +34,11 @@ describe("opencode-compaction-detector", () => { const result = isOpenCodeAutoCompactionEnabled(emptyDir); expect(result).toBe(true); - rmSync(emptyDir, { recursive: true, force: true }); + try { + rmSync(emptyDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } }); }); diff --git a/packages/plugin/src/shared/rpc-client.test.ts b/packages/plugin/src/shared/rpc-client.test.ts index ed123b0..155e014 100644 --- a/packages/plugin/src/shared/rpc-client.test.ts +++ b/packages/plugin/src/shared/rpc-client.test.ts @@ -20,7 +20,11 @@ afterEach(async () => { await server.close(); } for (const dir of tempDirs.splice(0)) { - rmSync(dir, { recursive: true, force: true }); + try { + rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + /* Ignore EBUSY on Windows */ + } } });