From 6e96b6663b26ba0495b668cc1b7b82a4afa6afa3 Mon Sep 17 00:00:00 2001 From: Endri Bezati Date: Mon, 9 Nov 2026 09:48:25 +0100 Subject: [PATCH 1/2] test: sessions sorted by time are created at distinct times session-manager.test.ts expected ['Session 1', 'Session 3'] from a sort by updatedAt, most recent first, as its own comment says. That held only when all three sessions were created within one millisecond: the sort then kept insertion order. On a runner where the clock ticked between them, Session 3 came first and the test failed, as on main's CI after #142 (a changelog-only change). The test now creates each session at its own fixed time (fake Date only) and expects the most recent first. With distinct times the old expectation fails every time; the new one passes every time. Claude-Session: https://claude.ai/code/session_01EToj6RJRMSSHQiqGNMU9wv --- .../test/session-manager.test.ts | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/extension-core/test/session-manager.test.ts b/packages/extension-core/test/session-manager.test.ts index 8ee541b..6001442 100644 --- a/packages/extension-core/test/session-manager.test.ts +++ b/packages/extension-core/test/session-manager.test.ts @@ -247,17 +247,28 @@ describe('SessionManager', () => { describe('getSessionsForWorkflow', () => { it('should return sessions for specific workflow', async () => { - await sessionManager.createSession('/test/workflow1.py', 'Session 1'); - mockACPClient.createSession.mockResolvedValue('session-2'); - await sessionManager.createSession('/test/workflow2.py', 'Session 2'); - mockACPClient.createSession.mockResolvedValue('session-3'); - await sessionManager.createSession('/test/workflow1.py', 'Session 3'); + // Each session at its own time. The expectation used to hold only when + // all three were created within one millisecond (the sort then kept + // insertion order), and failed on a runner where the clock ticked. + vi.useFakeTimers({ toFake: ['Date'] }); + try { + vi.setSystemTime(1_000); + await sessionManager.createSession('/test/workflow1.py', 'Session 1'); + vi.setSystemTime(2_000); + mockACPClient.createSession.mockResolvedValue('session-2'); + await sessionManager.createSession('/test/workflow2.py', 'Session 2'); + vi.setSystemTime(3_000); + mockACPClient.createSession.mockResolvedValue('session-3'); + await sessionManager.createSession('/test/workflow1.py', 'Session 3'); + } finally { + vi.useRealTimers(); + } const sessions = sessionManager.getSessionsForWorkflow('/test/workflow1.py'); expect(sessions).toHaveLength(2); // Sessions are sorted by updatedAt descending (most recent first) - expect(sessions.map((s) => s.name)).toEqual(['Session 1', 'Session 3']); + expect(sessions.map((s) => s.name)).toEqual(['Session 3', 'Session 1']); }); it('should return empty array for workflow with no sessions', () => { From f3ebc6e646b0444bedd7c8a7c6d406b7e1972669 Mon Sep 17 00:00:00 2001 From: Endri Bezati Date: Mon, 9 Nov 2026 09:50:56 +0100 Subject: [PATCH 2/2] fix: sessions with the same time list the later one first Review of #143: the sort by updatedAt had no tie-breaker, so two sessions created (or restored) in the same millisecond came back oldest first, and the chat's delete fallback took the older one as the most recent sibling. Equal times now fall back to createdAt, then to the later one added. A test pins equal times (it fails without the tie-breaker); the first test's comment says what it needs rather than its history. Claude-Session: https://claude.ai/code/session_01EToj6RJRMSSHQiqGNMU9wv --- .../src/extension/session-manager.ts | 10 ++++++++-- .../test/session-manager.test.ts | 18 +++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/extension-core/src/extension/session-manager.ts b/packages/extension-core/src/extension/session-manager.ts index 9d51a7c..da3b6bf 100644 --- a/packages/extension-core/src/extension/session-manager.ts +++ b/packages/extension-core/src/extension/session-manager.ts @@ -186,9 +186,15 @@ export class SessionManager { * Get all sessions for a specific workflow file */ getSessionsForWorkflow(workflowFile: string): SessionData[] { + // Most recent first; between equal times (created or restored in the same + // millisecond), the one added later. return Array.from(this.sessions.values()) - .filter((s) => s.workflowFile === workflowFile) - .sort((a, b) => b.updatedAt - a.updatedAt); + .map((session, order) => ({ session, order })) + .filter(({ session }) => session.workflowFile === workflowFile) + .sort((a, b) => b.session.updatedAt - a.session.updatedAt + || b.session.createdAt - a.session.createdAt + || b.order - a.order) + .map(({ session }) => session); } /** diff --git a/packages/extension-core/test/session-manager.test.ts b/packages/extension-core/test/session-manager.test.ts index 6001442..7f4de88 100644 --- a/packages/extension-core/test/session-manager.test.ts +++ b/packages/extension-core/test/session-manager.test.ts @@ -247,9 +247,7 @@ describe('SessionManager', () => { describe('getSessionsForWorkflow', () => { it('should return sessions for specific workflow', async () => { - // Each session at its own time. The expectation used to hold only when - // all three were created within one millisecond (the sort then kept - // insertion order), and failed on a runner where the clock ticked. + // Each session at its own time, so the order is the updatedAt sort's. vi.useFakeTimers({ toFake: ['Date'] }); try { vi.setSystemTime(1_000); @@ -271,6 +269,20 @@ describe('SessionManager', () => { expect(sessions.map((s) => s.name)).toEqual(['Session 3', 'Session 1']); }); + it('should put the later of two sessions with the same time first', async () => { + vi.useFakeTimers({ toFake: ['Date'] }); + try { + vi.setSystemTime(5_000); + await sessionManager.createSession('/test/same.py', 'Earlier'); + mockACPClient.createSession.mockResolvedValue('session-later'); + await sessionManager.createSession('/test/same.py', 'Later'); + } finally { + vi.useRealTimers(); + } + + expect(sessionManager.getSessionsForWorkflow('/test/same.py').map((s) => s.name)).toEqual(['Later', 'Earlier']); + }); + it('should return empty array for workflow with no sessions', () => { const sessions = sessionManager.getSessionsForWorkflow('/test/no-sessions.py');