From 2598d98f34b85eb071d4118ecf5c89dfdfb5a524 Mon Sep 17 00:00:00 2001 From: Prateek Date: Sun, 1 Mar 2026 19:56:23 +0530 Subject: [PATCH] fix: address bugbot review comments on lifecycle JSONL detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pass config.readyThresholdMs to getActivityState() for consistency - Fix idle-but-running test to exercise fallback path (getActivityState → null) - Deduplicate identical exited tests; replace duplicate with fallback-path test Co-Authored-By: Claude Opus 4.6 --- packages/core/src/__tests__/lifecycle-manager.test.ts | 11 +++++++---- packages/core/src/lifecycle-manager.ts | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/core/src/__tests__/lifecycle-manager.test.ts b/packages/core/src/__tests__/lifecycle-manager.test.ts index 5fc9c0e76..bd7cf5985 100644 --- a/packages/core/src/__tests__/lifecycle-manager.test.ts +++ b/packages/core/src/__tests__/lifecycle-manager.test.ts @@ -227,7 +227,7 @@ describe("check (single session)", () => { expect(lm.getStates().get("app-1")).toBe("killed"); }); - it("detects killed state when agent process exits (idle terminal + dead process)", async () => { + it("detects killed state when getActivityState returns exited", async () => { vi.mocked(mockAgent.getActivityState).mockResolvedValue({ state: "exited" }); const session = makeSession({ status: "working" }); @@ -251,8 +251,10 @@ describe("check (single session)", () => { expect(lm.getStates().get("app-1")).toBe("killed"); }); - it("detects killed state when agent process exits (active terminal + dead process)", async () => { - vi.mocked(mockAgent.getActivityState).mockResolvedValue({ state: "exited" }); + it("detects killed via terminal fallback when getActivityState returns null", async () => { + vi.mocked(mockAgent.getActivityState).mockResolvedValue(null); + vi.mocked(mockAgent.detectActivity).mockReturnValue("idle"); + vi.mocked(mockAgent.isProcessRunning).mockResolvedValue(false); const session = makeSession({ status: "working" }); vi.mocked(mockSessionManager.get).mockResolvedValue(session); @@ -275,7 +277,8 @@ describe("check (single session)", () => { expect(lm.getStates().get("app-1")).toBe("killed"); }); - it("stays working when agent is idle but process is still running", async () => { + it("stays working when agent is idle but process is still running (fallback path)", async () => { + vi.mocked(mockAgent.getActivityState).mockResolvedValue(null); vi.mocked(mockAgent.detectActivity).mockReturnValue("idle"); vi.mocked(mockAgent.isProcessRunning).mockResolvedValue(true); diff --git a/packages/core/src/lifecycle-manager.ts b/packages/core/src/lifecycle-manager.ts index 264d07954..663fd7488 100644 --- a/packages/core/src/lifecycle-manager.ts +++ b/packages/core/src/lifecycle-manager.ts @@ -200,7 +200,7 @@ export function createLifecycleManager(deps: LifecycleManagerDeps): LifecycleMan if (agent && session.runtimeHandle) { try { // Try JSONL-based activity detection first (reads agent's session files directly) - const activityState = await agent.getActivityState(session); + const activityState = await agent.getActivityState(session, config.readyThresholdMs); if (activityState) { if (activityState.state === "waiting_input") return "needs_input"; if (activityState.state === "exited") return "killed";