diff --git a/src/tools/agent-teams/team-config-store.test.ts b/src/tools/agent-teams/team-config-store.test.ts new file mode 100644 index 000000000..466f96e71 --- /dev/null +++ b/src/tools/agent-teams/team-config-store.test.ts @@ -0,0 +1,48 @@ +/// +import { afterEach, beforeEach, describe, expect, test } from "bun:test" +import { mkdtempSync, rmSync } from "node:fs" +import { tmpdir } from "node:os" +import { join } from "node:path" +import { acquireLock } from "../../features/claude-tasks/storage" +import { getTeamDir } from "./paths" +import { createTeamConfig, deleteTeamData, teamExists } from "./team-config-store" + +describe("agent-teams team config store", () => { + let originalCwd: string + let tempProjectDir: string + + beforeEach(() => { + originalCwd = process.cwd() + tempProjectDir = mkdtempSync(join(tmpdir(), "agent-teams-config-store-")) + process.chdir(tempProjectDir) + createTeamConfig("core", "Core team", "ses-main", tempProjectDir, "sisyphus") + }) + + afterEach(() => { + if (teamExists("core")) { + deleteTeamData("core") + } + process.chdir(originalCwd) + rmSync(tempProjectDir, { recursive: true, force: true }) + }) + + test("deleteTeamData waits for team lock before removing team files", () => { + //#given + const lock = acquireLock(getTeamDir("core")) + expect(lock.acquired).toBe(true) + + //#when + const deleteWhileLocked = () => deleteTeamData("core") + + //#then + expect(deleteWhileLocked).toThrow("team_lock_unavailable") + expect(teamExists("core")).toBe(true) + + //#when + lock.release() + deleteTeamData("core") + + //#then + expect(teamExists("core")).toBe(false) + }) +}) diff --git a/src/tools/agent-teams/team-config-store.ts b/src/tools/agent-teams/team-config-store.ts index 707659fe6..a57d0b47b 100644 --- a/src/tools/agent-teams/team-config-store.ts +++ b/src/tools/agent-teams/team-config-store.ts @@ -173,14 +173,16 @@ export function assignNextColor(config: TeamConfig): string { export function deleteTeamData(teamName: string): void { assertValidTeamName(teamName) - const teamDir = getTeamDir(teamName) - const taskDir = getTeamTaskDir(teamName) + withTeamLock(teamName, () => { + const teamDir = getTeamDir(teamName) + const taskDir = getTeamTaskDir(teamName) - if (existsSync(teamDir)) { - rmSync(teamDir, { recursive: true, force: true }) - } + if (existsSync(teamDir)) { + rmSync(teamDir, { recursive: true, force: true }) + } - if (existsSync(taskDir)) { - rmSync(taskDir, { recursive: true, force: true }) - } + if (existsSync(taskDir)) { + rmSync(taskDir, { recursive: true, force: true }) + } + }) }