From d97e3983832d320b9a869db07c94bccaa34b6f87 Mon Sep 17 00:00:00 2001 From: Turtle Date: Thu, 20 Aug 2026 22:01:50 +0800 Subject: [PATCH] fix(jsonl): warn when repairing torn tails --- packages/session/session-persistence-jsonl/src/index.ts | 1 + packages/session/session-persistence-jsonl/tests/zstd.spec.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/session/session-persistence-jsonl/src/index.ts b/packages/session/session-persistence-jsonl/src/index.ts index 5113746fec..f8c1a86bef 100644 --- a/packages/session/session-persistence-jsonl/src/index.ts +++ b/packages/session/session-persistence-jsonl/src/index.ts @@ -441,6 +441,7 @@ export class JsonlSessionPersistence extends SessionPersistence implements Persi if (tornMarker !== undefined) await this.repair(meta, tornMarker.truncateTo) const repairedEvents = [...(tornMarker?.recoveredEvents ?? []), ...closers] if (repairedEvents.length > 0) await this.appendLines(meta, repairedEvents) + if (tornMarker !== undefined) this.ctx.logger.warn(`${this.name}: session "${meta.id}" recovered from a torn tail; incomplete tail bytes were discarded`) } /** List valid unique stored sessions' metadata (header line only — no full-log parse). */ diff --git a/packages/session/session-persistence-jsonl/tests/zstd.spec.ts b/packages/session/session-persistence-jsonl/tests/zstd.spec.ts index b9cced0087..01695e3488 100644 --- a/packages/session/session-persistence-jsonl/tests/zstd.spec.ts +++ b/packages/session/session-persistence-jsonl/tests/zstd.spec.ts @@ -539,6 +539,7 @@ describe('JsonlSessionPersistence: default Zstandard encoding', () => { const root = await freshRoot() const ctx = await mount(root) const header = meta('recover-torn', '/proj') + const warn = vi.spyOn(ctx.logger, 'warn').mockImplementation(() => undefined) await ctx.sessionPersistence.create(header) await ctx.sessionPersistence.append(header.id, oneTurnLog()) const path = logPath(root, header.cwd, header.id, 'zstd') @@ -562,6 +563,7 @@ describe('JsonlSessionPersistence: default Zstandard encoding', () => { expect(loaded.events.some(event => event.type === 'assistant/chunk' && event.seq === 8)).toBe(false) expect(loaded.events[8]?.type).toBe('step/end') expect(loaded.events[9]?.type).toBe('turn/end') + expect(warn).toHaveBeenCalledWith('session-persistence-jsonl: session "recover-torn" recovered from a torn tail; incomplete tail bytes were discarded') const repaired = await readFile(path) expect(repaired.subarray(0, committed.length)).toEqual(committed)