From fcff01cc825179fea70367abb400edff2329bda6 Mon Sep 17 00:00:00 2001 From: Yung-Chen Tang <46495124+yungchentang@users.noreply.github.com> Date: Sun, 28 Jun 2026 20:46:54 +0200 Subject: [PATCH] fix: archive role-ordering reset transcripts (#97544) * fix: archive role-ordering reset transcripts * test: fix session reset archive lint --- src/config/sessions/session-accessor.test.ts | 12 ++++++- src/config/sessions/session-accessor.ts | 36 +++----------------- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/src/config/sessions/session-accessor.test.ts b/src/config/sessions/session-accessor.test.ts index cfee7fe945a..cb91688ed91 100644 --- a/src/config/sessions/session-accessor.test.ts +++ b/src/config/sessions/session-accessor.test.ts @@ -1358,7 +1358,7 @@ describe("session accessor file-backed seam", () => { ).toHaveLength(1); }); - it("persists reset lifecycle entry changes with transcript replay and cleanup", async () => { + it("persists reset lifecycle entry changes with transcript replay and archive", async () => { const now = Date.now(); const sessionKey = "agent:main:main"; const previousTranscript = path.join(tempDir, "previous-session.jsonl"); @@ -1410,6 +1410,16 @@ describe("session accessor file-backed seam", () => { expect(result.replayedMessages).toBe(2); expect(loadSessionEntry({ sessionKey, storePath })).toMatchObject(nextEntry); expect(fs.existsSync(previousTranscript)).toBe(false); + const archivedPreviousTranscripts = fs + .readdirSync(tempDir) + .filter((file) => file.startsWith("previous-session.jsonl.reset.")); + expect(archivedPreviousTranscripts).toHaveLength(1); + const [archivedPreviousTranscriptName] = archivedPreviousTranscripts; + const archivedPreviousTranscript = path.join(tempDir, archivedPreviousTranscriptName); + expect(fs.readFileSync(archivedPreviousTranscript, "utf-8")).toContain( + '"id":"previous-session"', + ); + expect(fs.readFileSync(archivedPreviousTranscript, "utf-8")).toContain('"content":"hi"'); expect(fs.readFileSync(nextTranscript, "utf-8")).toContain('"content":"hello"'); }); diff --git a/src/config/sessions/session-accessor.ts b/src/config/sessions/session-accessor.ts index 7f1741335f0..fc207091462 100644 --- a/src/config/sessions/session-accessor.ts +++ b/src/config/sessions/session-accessor.ts @@ -1632,10 +1632,12 @@ export async function persistSessionResetLifecycle(params: { }); if (params.cleanupPreviousTranscript && params.previousSessionId) { - cleanupPreviousResetTranscripts({ + await archivePreviousSessionTranscript({ agentId: params.agentId ?? resolveAgentIdFromSessionKey(params.sessionKey), - previousEntry: params.previousEntry, - previousSessionId: params.previousSessionId, + previousEntry: + params.previousEntry.sessionId === params.previousSessionId + ? params.previousEntry + : { ...params.previousEntry, sessionId: params.previousSessionId }, storePath: params.storePath, }); } @@ -2709,34 +2711,6 @@ async function restoreTemporarySessionMapping( } } -function cleanupPreviousResetTranscripts(params: { - agentId: string; - previousEntry: SessionEntry; - previousSessionId: string; - storePath: string; -}): void { - const transcriptCandidates = new Set(); - const resolved = resolveSessionFilePath( - params.previousSessionId, - params.previousEntry, - resolveSessionFilePathOptions({ - agentId: params.agentId, - storePath: params.storePath, - }), - ); - if (resolved) { - transcriptCandidates.add(resolved); - } - transcriptCandidates.add(resolveSessionTranscriptPath(params.previousSessionId, params.agentId)); - for (const candidate of transcriptCandidates) { - try { - fs.unlinkSync(candidate); - } catch { - // Best-effort cleanup. - } - } -} - async function archivePreviousSessionTranscript(params: { agentId: string; onArchiveError?: (error: unknown, sourcePath: string) => void;