From bae64c6c23c1b1d70331dcfc7467d2cba62c6b45 Mon Sep 17 00:00:00 2001 From: catoncat Date: Fri, 26 Jun 2026 14:19:54 +0800 Subject: [PATCH] Add source adapter format-drift smoke tests --- src/sources/claude-code.test.ts | 60 +++++++++++++++++++++++++++++++++ src/sources/pi.test.ts | 58 +++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/src/sources/claude-code.test.ts b/src/sources/claude-code.test.ts index 6b26615..fcea16c 100644 --- a/src/sources/claude-code.test.ts +++ b/src/sources/claude-code.test.ts @@ -134,6 +134,66 @@ describe("claude-code source adapter", () => { expect(searchableProjection).not.toContain("attachment text must not leak"); }); + test("sync skips malformed and unsupported records without leaking format-drift text", async () => { + const { root } = writeClaudeFixture("format-drift", [ + "{this is not json", + claudeLine({ + type: "system", + sessionId: "unsupported-session-must-not-win", + cwd: "/tmp/unsupported-cwd-must-not-win", + timestamp: "1999-01-01T00:00:00.000Z", + message: { content: "unsupported claude text must not leak" }, + }), + claudeLine({ + type: "user", + sessionId: "format-drift-session", + cwd: "/tmp/claude-format-cwd", + timestamp: "2026-06-10T00:00:00.000Z", + message: { content: "accepted claude format drift needle" }, + }), + "{\"type\":\"assistant\",\"message\":", + claudeLine({ + type: "assistant", + sessionId: "format-drift-session", + cwd: "/tmp/claude-format-cwd", + timestamp: "2026-06-10T00:00:01.000Z", + message: { + content: [ + { type: "text", text: "accepted claude format drift answer" }, + { type: "attachment", text: "format drift attachment must not leak" }, + ], + }, + }), + ]); + const dbPath = join(root, "index.sqlite"); + + const summary = await syncSessions({ + dbPath, + sourceId: "claude-code", + selector: { source: "claude-code", kind: "all", root }, + }); + + expect(summary.errors).toBe(0); + expect(summary.added).toBe(1); + expect(summary.coverage.sourceFileCount).toBe(1); + expect(summary.coverage.indexedSessionCount).toBe(1); + + const foundAccepted = findSessions(dbPath, "accepted claude format drift needle", 10, { source: "claude-code", kind: "all", root }, { sourceId: "claude-code" }); + expect(foundAccepted.results.map((result) => result.sessionUuid)).toEqual(["claude-code:format-drift-session"]); + + const foundUnsupported = findSessions(dbPath, "unsupported claude text", 10, { source: "claude-code", kind: "all", root }, { sourceId: "claude-code" }); + expect(foundUnsupported.results).toEqual([]); + + const page = getMessagePage(dbPath, "claude-code:format-drift-session", 0, 10); + expect(page.session.cwd).toBe("/tmp/claude-format-cwd"); + expect(page.messages.map((message) => message.contentText)).toEqual([ + "accepted claude format drift needle", + "accepted claude format drift answer", + ]); + expect(JSON.stringify(page)).not.toContain("unsupported claude text must not leak"); + expect(JSON.stringify(page)).not.toContain("format drift attachment must not leak"); + }); + test("ignores skipped records when deriving inventory grouping dates and snapshot file metadata", async () => { const { root, filePath } = writeClaudeFixture("inventory-policy", [ claudeLine({ diff --git a/src/sources/pi.test.ts b/src/sources/pi.test.ts index a7059cb..557ea3a 100644 --- a/src/sources/pi.test.ts +++ b/src/sources/pi.test.ts @@ -141,6 +141,64 @@ describe("pi source adapter", () => { expect(searchableProjection).not.toContain("tool call must not leak"); }); + test("sync skips malformed and unsupported records without leaking format-drift text", async () => { + const { root } = writePiFixture("format-drift", [ + "{this is not json", + piLine({ type: "session", id: "pi-format-drift-session", cwd: "/tmp/pi-format-cwd", timestamp: "2026-06-10T00:00:00.000Z" }), + piLine({ type: "future_event", timestamp: "1999-01-01T00:00:00.000Z", text: "unsupported pi text must not leak" }), + piLine({ + type: "message", + timestamp: "2026-06-10T00:00:01.000Z", + message: { role: "user", content: [{ type: "text", text: "accepted pi format drift needle" }], timestamp: "2026-06-10T00:00:01.000Z" }, + }), + "{\"type\":\"message\",\"message\":", + piLine({ + type: "message", + timestamp: "2026-06-10T00:00:02.000Z", + message: { + role: "assistant", + content: [ + { type: "text", text: "accepted pi format drift answer" }, + { type: "toolCall", name: "bash", arguments: { command: "format drift tool call must not leak" } }, + ], + timestamp: "2026-06-10T00:00:02.000Z", + }, + }), + piLine({ type: "compaction", id: "c1", timestamp: "2026-06-10T00:00:03.000Z", summary: "accepted pi format drift summary" }), + ]); + const dbPath = join(root, "index.sqlite"); + + const summary = await syncSessions({ + dbPath, + sourceId: "pi", + selector: { source: "pi", kind: "all", root }, + }); + + expect(summary.errors).toBe(0); + expect(summary.added).toBe(1); + expect(summary.coverage.sourceFileCount).toBe(1); + expect(summary.coverage.indexedSessionCount).toBe(1); + + const foundAccepted = findSessions(dbPath, "accepted pi format drift needle", 10, { source: "pi", kind: "all", root }, { sourceId: "pi" }); + expect(foundAccepted.results.map((result) => result.sessionUuid)).toEqual(["pi:pi-format-drift-session"]); + + const foundCompaction = findSessions(dbPath, "accepted pi format drift summary", 10, { source: "pi", kind: "all", root }, { sourceId: "pi" }); + expect(foundCompaction.results.map((result) => result.sessionUuid)).toEqual(["pi:pi-format-drift-session"]); + expect(foundCompaction.results[0]?.matchSource).toBe("session"); + + const foundUnsupported = findSessions(dbPath, "unsupported pi text", 10, { source: "pi", kind: "all", root }, { sourceId: "pi" }); + expect(foundUnsupported.results).toEqual([]); + + const page = getMessagePage(dbPath, "pi:pi-format-drift-session", 0, 10); + expect(page.session.cwd).toBe("/tmp/pi-format-cwd"); + expect(page.messages.map((message) => message.contentText)).toEqual([ + "accepted pi format drift needle", + "accepted pi format drift answer", + ]); + expect(JSON.stringify(page)).not.toContain("unsupported pi text must not leak"); + expect(JSON.stringify(page)).not.toContain("format drift tool call must not leak"); + }); + test("uses the latest Pi model_change as session model", async () => { const { filePath } = writePiFixture("latest-model", [ piLine({ type: "session", id: "pi-model-session", cwd: "/tmp/pi-model-cwd", timestamp: "2026-06-06T00:00:00.000Z" }),