From 8cdd18fa64a1ab51b9f3230ed56e9b7860d67bd9 Mon Sep 17 00:00:00 2001 From: JD Date: Sat, 24 Oct 2026 18:56:37 -0400 Subject: [PATCH] test(deepseek): stop pinning Node's one-shot zstd decoder to the first frame The frame-walking test asserted that zlib.zstdDecompressSync returns only the first of 40 concatenated frames. That was true when the walker was written, but nodejs/node#65865 (shipped in 26.10.0 and in 24.22.0 LTS) makes Node decode every frame, so the assertion fails on current Node 24 LTS and 26 while the walker itself is still correct. The assertion tested Node, not Codeman: the walker's own 40-frame checks stay, and the comments now say which Node versions stop at the first frame, since the supported range (>=22) still includes them. --- docs/deepseek-integration.md | 7 ++++--- src/deepseek-transcript.ts | 9 +++++---- test/deepseek-transcript.test.ts | 13 +++++-------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/deepseek-integration.md b/docs/deepseek-integration.md index 874f6fd15..5f1072a74 100644 --- a/docs/deepseek-integration.md +++ b/docs/deepseek-integration.md @@ -235,9 +235,10 @@ worker's first answer reads as an answer. Three things about the file shaped the reader (`src/deepseek-transcript.ts`): - **It is one zstd FRAME per append, not one zstd stream.** `zstd -dc` decodes all - of them, Node's `zlib` zstd decoder stops at the first: a real 56-line - transcript came back as 1 line. The reader walks frame headers itself. On a Node - older than 22.15 (no zstd at all) the mode falls back to the pane, as before. + of them, Node's `zlib` zstd decoder before 24.22 and 26.10 stops at the first: + a real 56-line transcript came back as 1 line. The reader walks frame headers + itself, which stays correct on a Node that decodes every frame + (nodejs/node#65865). On a Node older than 22.15 (no zstd at all) the mode falls back to the pane, as before. - **Not every `user/message` is the user.** Each turn also records a plugin-sourced runtime-context snapshot; only `source.kind === 'user'` is a prompt. diff --git a/src/deepseek-transcript.ts b/src/deepseek-transcript.ts index dc374f101..7fbdcdd16 100644 --- a/src/deepseek-transcript.ts +++ b/src/deepseek-transcript.ts @@ -26,10 +26,11 @@ * **1. One zstd FRAME per append, not one zstd stream.** The file is * `session.jsonl.zstd`, and dsh appends by compressing each batch of lines into * its own frame and writing it at the end. `zstd -dc` handles that (frames - * concatenate by definition), but Node's `zlib.zstdDecompress()` and - * `createZstdDecompress()` both stop at the first frame end: measured on a real - * 56-line transcript, Node returned 158 bytes / 1 line where the CLI returned - * 43,747 bytes / 56 lines. That is a silent truncation to the session header — + * concatenate by definition), but before Node 24.22 and 26.10 + * (nodejs/node#65865) `zlib.zstdDecompress()` and `createZstdDecompress()` both + * stop at the first frame end, and the supported range still includes those + * versions: measured on a real 56-line transcript, Node returned 158 bytes / + * 1 line where the CLI returned 43,747 bytes / 56 lines. That is a silent truncation to the session header — * every call would have reported "no answer yet" forever. `decodeZstdFrames()` * below walks the frame headers itself and decompresses each frame, and * `test/deepseek-transcript.test.ts` pins it against multi-frame fixtures. diff --git a/test/deepseek-transcript.test.ts b/test/deepseek-transcript.test.ts index e0837070d..292aac14c 100644 --- a/test/deepseek-transcript.test.ts +++ b/test/deepseek-transcript.test.ts @@ -4,10 +4,11 @@ * Two of these assertions exist because the obvious implementation was measured * to be wrong against real files: * - * - dsh appends ONE ZSTD FRAME PER WRITE, and Node's `zlib` zstd decoder stops - * at the first frame end. A 56-line transcript decoded as 1 line / 158 bytes, - * which reads as "the worker never answered" rather than as an error. The - * multi-frame fixtures below are the guard. + * - dsh appends ONE ZSTD FRAME PER WRITE, and Node's `zlib` zstd decoder + * before 24.22 and 26.10 stops at the first frame end. A 56-line transcript + * decoded as 1 line / 158 bytes, which reads as "the worker never answered" + * rather than as an error. Newer Node decodes every frame (nodejs/node#65865), + * so the multi-frame fixtures below pin the walker itself, not Node's decoder. * - a fresh worker in a case directory that had been used before answered its * first `last-response` with the PREVIOUS session's reply. Session-to- * transcript pairing is therefore its own describe block. @@ -67,10 +68,6 @@ describe.skipIf(!zstdSupported())('zstd frame walking', () => { const lines = Array.from({ length: 40 }, (_, i) => JSON.stringify({ type: 'noise', seq: i })); const buf = framed(lines); - // The one-shot decoder is what this module had to replace. - const oneShot = (zlib as unknown as { zstdDecompressSync?: (b: Buffer) => Buffer }).zstdDecompressSync!(buf); - expect(oneShot.toString('utf8').trim().split('\n')).toHaveLength(1); - expect(zstdFrameRanges(buf)).toHaveLength(40); expect(decodeZstdFrames(buf).trim().split('\n')).toHaveLength(40); });