From f6c665742d7daf65d32940dc45d86b16cf0690e9 Mon Sep 17 00:00:00 2001 From: ishaan1124 Date: Sat, 15 Aug 2026 00:57:18 +0530 Subject: [PATCH 1/2] test: wait for containment teardown causally --- .../project/authority-process-ledger.test.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/backend/cli/test/project/authority-process-ledger.test.ts b/backend/cli/test/project/authority-process-ledger.test.ts index 85781e71..014b72ee 100644 --- a/backend/cli/test/project/authority-process-ledger.test.ts +++ b/backend/cli/test/project/authority-process-ledger.test.ts @@ -120,14 +120,19 @@ async function scenario(kind: "pty" | "biology", action: "trust" | "filesystem" owner.kill("SIGKILL") await owner.exited - // Both fixtures ignore terminal hangup so the independently sandboxed - // leader and its escaped descendant genuinely outlive the killed server. - await Bun.sleep(100) - const survivedOwner = await AuthorityProcessLedger.owns(entry.pid, entry.identity) - // macOS responsibility supervision and Linux bubblewrap's parent-death PID - // namespace both tear down immediately. The durable ledger remains so a - // fresh server can verify the dead tree and clear ownership atomically. - expect(survivedOwner).toBe(process.platform !== "darwin" && !(process.platform === "linux" && entry.sandboxed)) + // Both fixtures ignore terminal hangup, so any death below must come from + // the platform containment rather than directly from the killed server. + const contained = process.platform === "darwin" || (process.platform === "linux" && entry.sandboxed) + if (contained) { + // The macOS responsibility supervisor and Linux bubblewrap namespace + // observe owner death asynchronously. Prove their causal teardown to a + // bounded deadline instead of treating 100 ms as a lifecycle contract. + expect(await gone(entry)).toBe(true) + expect(await gone(entry.descendant)).toBe(true) + } else { + await Bun.sleep(100) + expect(await AuthorityProcessLedger.owns(entry.pid, entry.identity)).toBe(true) + } await run( root, From 17e350eb012ad41c0135af681b019fe05db2bb3e Mon Sep 17 00:00:00 2001 From: ishaan1124 Date: Sat, 15 Aug 2026 01:02:29 +0530 Subject: [PATCH 2/2] test: tolerate Windows migration sharing contention --- backend/cli/test/global/data-dir.test.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/backend/cli/test/global/data-dir.test.ts b/backend/cli/test/global/data-dir.test.ts index b17c5206..01da474a 100644 --- a/backend/cli/test/global/data-dir.test.ts +++ b/backend/cli/test/global/data-dir.test.ts @@ -27,6 +27,21 @@ async function root() { return value } +function rewriteRacingFile(filepath: string, content: string) { + try { + fsSync.writeFileSync(filepath, content) + return true + } catch (error) { + const code = (error as NodeJS.ErrnoException).code + // This fixture deliberately writes while migration reads the same file. + // Windows may transiently deny that competing open; skipping one timer + // tick preserves the race without turning a sharing violation into an + // unhandled test-runner error and cleanup cascade. + if (process.platform === "win32" && (code === "EBUSY" || code === "EACCES" || code === "EPERM")) return false + throw error + } +} + async function artifact(root: string, key: string) { const dir = path.join(root, "artifact-store") await fs.mkdir(path.join(dir, "blobs"), { recursive: true }) @@ -245,10 +260,14 @@ describe("OpenScience data directory", () => { // verification. Only that file may be dropped. const torn = path.join(legacy, "storage", "session", "ses_b.json") const original = fsSync.readFileSync(torn) - const watcher = setInterval(() => fsSync.writeFileSync(torn, `{"id":"b","n":${Math.random()}}`), 1) + let rewrites = 0 + const watcher = setInterval(() => { + if (rewriteRacingFile(torn, `{"id":"b","n":${Math.random()}}`)) rewrites++ + }, 1) const result = await resolveDataDirectory({ home, legacy }).finally(() => clearInterval(watcher)) expect(result.path).toBe(target) + expect(rewrites).toBeGreaterThan(0) expect(await fs.readFile(path.join(target, "openscience-session.json"), "utf8")).toContain("kept") expect(JSON.parse(await fs.readFile(path.join(target, "auth.json"), "utf8"))["openai-codex"].access).toBe("kept") for (const id of ["a", "c"])