From f04fae4c6a37aefbc205e0040e1aebb6fd53bf2f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 8 May 2026 13:32:17 +0100 Subject: [PATCH] refactor: stop creating jsonl compaction successors --- .../compaction-successor-transcript.test.ts | 19 ++++++++++ .../compaction-successor-transcript.ts | 37 ++++++++----------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/agents/pi-embedded-runner/compaction-successor-transcript.test.ts b/src/agents/pi-embedded-runner/compaction-successor-transcript.test.ts index 0429bac9a4c..935700bb024 100644 --- a/src/agents/pi-embedded-runner/compaction-successor-transcript.test.ts +++ b/src/agents/pi-embedded-runner/compaction-successor-transcript.test.ts @@ -281,6 +281,25 @@ describe("rotateTranscriptAfterCompaction", () => { expect(result.reason).toBe("no compaction entry"); }); + it("does not create legacy jsonl successor files for unmigrated transcripts", async () => { + const dir = await createTmpDir(); + const { manager } = createCompactedSession(dir); + + const result = await rotateTranscriptAfterCompaction({ + sessionManager: manager, + sessionFile: path.join(dir, "legacy-session.jsonl"), + now: () => new Date("2026-04-27T12:15:00.000Z"), + }); + + expect(result).toMatchObject({ + rotated: false, + reason: "transcript not in SQLite", + }); + await expect( + fs.stat(path.join(dir, "2026-04-27T12-15-00-000Z_legacy-session.jsonl")), + ).rejects.toMatchObject({ code: "ENOENT" }); + }); + it("uses a refreshed manager after manual boundary hardening", async () => { const dir = await createTmpDir(); const manager = SessionManager.create(dir); diff --git a/src/agents/pi-embedded-runner/compaction-successor-transcript.ts b/src/agents/pi-embedded-runner/compaction-successor-transcript.ts index 93eb3c66939..326298b0624 100644 --- a/src/agents/pi-embedded-runner/compaction-successor-transcript.ts +++ b/src/agents/pi-embedded-runner/compaction-successor-transcript.ts @@ -1,5 +1,4 @@ import { randomUUID } from "node:crypto"; -import path from "node:path"; import { createSqliteSessionTranscriptLocator, isSqliteSessionTranscriptLocator, @@ -52,6 +51,9 @@ export async function rotateTranscriptAfterCompaction(params: { if (!sessionFile) { return { rotated: false, reason: "missing session file" }; } + if (!isSqliteSessionTranscriptLocator(sessionFile)) { + return { rotated: false, reason: "transcript not in SQLite" }; + } const branch = params.sessionManager.getBranch(); const latestCompactionIndex = findLatestCompactionIndex(branch); @@ -62,10 +64,14 @@ export async function rotateTranscriptAfterCompaction(params: { const compaction = branch[latestCompactionIndex] as CompactionEntry; const timestamp = (params.now?.() ?? new Date()).toISOString(); const sessionId = randomUUID(); + const sourceScope = resolveSourceTranscriptScope({ + agentId: params.agentId, + transcriptPath: sessionFile, + }); const successorTranscriptPath = resolveSuccessorTranscriptPath({ transcriptPath: sessionFile, sessionId, - timestamp, + agentId: sourceScope.agentId, }); const successorEntries = buildSuccessorEntries({ allEntries: params.sessionManager.getEntries(), @@ -83,10 +89,6 @@ export async function rotateTranscriptAfterCompaction(params: { cwd: params.sessionManager.getCwd(), parentSession: sessionFile, }); - const sourceScope = resolveSourceTranscriptScope({ - agentId: params.agentId, - transcriptPath: sessionFile, - }); replaceSqliteSessionTranscriptEvents({ agentId: sourceScope.agentId, sessionId, @@ -360,20 +362,13 @@ function buildSuccessorHeader(params: { function resolveSuccessorTranscriptPath(params: { transcriptPath: string; sessionId: string; - timestamp: string; + agentId: string; }): string { - if (isSqliteSessionTranscriptLocator(params.transcriptPath)) { - const existing = resolveSqliteSessionTranscriptScopeForPath({ - transcriptPath: params.transcriptPath, - }); - return createSqliteSessionTranscriptLocator({ - agentId: existing?.agentId, - sessionId: params.sessionId, - }); - } - const fileTimestamp = params.timestamp.replace(/[:.]/g, "-"); - return path.join( - path.dirname(params.transcriptPath), - `${fileTimestamp}_${params.sessionId}.jsonl`, - ); + const existing = resolveSqliteSessionTranscriptScopeForPath({ + transcriptPath: params.transcriptPath, + }); + return createSqliteSessionTranscriptLocator({ + agentId: params.agentId || existing?.agentId || DEFAULT_AGENT_ID, + sessionId: params.sessionId, + }); }