diff --git a/packages/coding-agent/test/sdk-session-isolation.test.ts b/packages/coding-agent/test/sdk-session-isolation.test.ts index 826898550..515507417 100644 --- a/packages/coding-agent/test/sdk-session-isolation.test.ts +++ b/packages/coding-agent/test/sdk-session-isolation.test.ts @@ -13,6 +13,7 @@ import { AgentRegistry } from "@oh-my-pi/pi-coding-agent/registry/agent-registry import { createAgentSession } from "@oh-my-pi/pi-coding-agent/sdk"; import * as secrets from "@oh-my-pi/pi-coding-agent/secrets"; import { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage"; +import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session"; import { SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager"; import { VibeSessionRegistry } from "@oh-my-pi/pi-coding-agent/vibe/runtime"; import { getSessionsDir, removeSyncWithRetries, Snowflake } from "@oh-my-pi/pi-utils"; @@ -233,6 +234,59 @@ describe("createAgentSession session storage isolation", () => { expect(replacement).toMatchObject({ status: "idle", session: null }); }); + it("reclaims an unrevivable parked generation before a fresh same-id spawn", async () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), `pi-sdk-generation-corpse-${Snowflake.next()}-`)); + tempDirs.push(tempDir); + const cwd = path.join(tempDir, "project"); + fs.mkdirSync(cwd, { recursive: true }); + AgentLifecycleManager.resetGlobalForTests(); + AgentRegistry.resetGlobalForTests(); + const lifecycle = AgentLifecycleManager.global(); + const registry = AgentRegistry.global(); + const corpse = registry.register({ + id: "reused-worker", + displayName: "dead generation", + kind: "sub", + parentId: "Main", + session: null, + sessionFile: path.join(tempDir, "old-worker.jsonl"), + status: "parked", + }); + + let session: AgentSession | undefined; + try { + ({ session } = await createAgentSession({ + cwd, + agentDir: path.join(tempDir, "agent"), + modelRegistry: sharedModelRegistry, + settings: Settings.isolated(), + disableExtensionDiscovery: true, + skills: [], + contextFiles: [], + promptTemplates: [], + slashCommands: [], + enableMCP: false, + enableLsp: false, + agentRegistry: registry, + agentId: "reused-worker", + agentDisplayName: "fresh generation", + parentTaskPrefix: "reused-worker", + parentAgentId: "Main", + taskDepth: 1, + expectedAgentRef: null, + })); + const replacement = registry.get("reused-worker"); + expect(replacement).toBeDefined(); + expect(replacement).not.toBe(corpse); + expect(replacement?.session).toBe(session); + } finally { + await session?.dispose(); + await lifecycle.dispose(); + AgentLifecycleManager.resetGlobalForTests(); + AgentRegistry.resetGlobalForTests(); + } + }); + it("reuses the exact parked ref authorized for revival", async () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), `pi-sdk-generation-revive-${Snowflake.next()}-`)); tempDirs.push(tempDir);