From e26e75528c4808a45aa52ac717bb16da8a81c3e9 Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 10:47:36 +0000 Subject: [PATCH 1/3] fix(memory): migrate legacy memories_captured v2 scopes --- packages/junior-memory/src/events.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/junior-memory/src/events.ts b/packages/junior-memory/src/events.ts index 2fc437d874..f0ac79f7b6 100644 --- a/packages/junior-memory/src/events.ts +++ b/packages/junior-memory/src/events.ts @@ -3,6 +3,14 @@ import { z } from "zod"; import { MEMORY_KINDS, MEMORY_SCOPES } from "./types"; import type { MemoryRecord } from "./store"; +function currentScope( + scope: "personal" | "conversation" | "private" | "public", +) { + if (scope === "personal") return "private"; + if (scope === "conversation") return "public"; + return scope; +} + const capturedMemoryFields = { content: z.string().min(1), id: z.string().min(1), @@ -20,7 +28,7 @@ const legacyCapturedMemorySchema = z const capturedMemorySchema = z .object({ ...capturedMemoryFields, - scope: z.enum(MEMORY_SCOPES), + scope: z.preprocess((val) => currentScope(val as any), z.enum(MEMORY_SCOPES)), }) .strict(); @@ -39,14 +47,6 @@ const recalledMemoriesSchema = z }) .strict(); -function currentScope( - scope: "personal" | "conversation" | "private" | "public", -) { - if (scope === "personal") return "private"; - if (scope === "conversation") return "public"; - return scope; -} - function renderCapturedMemories(event: { memories: Array< | z.output From 2124aa30e757ffbc9925a4f94bdd24a53a2f45c4 Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 10:51:22 +0000 Subject: [PATCH 2/3] test(memory): expect v2 memories_captured legacy scope coercion --- packages/junior-memory/tests/events.test.ts | 45 ++++++++++++++------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/junior-memory/tests/events.test.ts b/packages/junior-memory/tests/events.test.ts index eb91722c67..c72000d777 100644 --- a/packages/junior-memory/tests/events.test.ts +++ b/packages/junior-memory/tests/events.test.ts @@ -22,20 +22,37 @@ describe("memory conversation events", () => { memoriesCapturedEventV1.renderEvent(legacy)?.details?.[0]?.metadata, ).toEqual(["preference", "private"]); - expect(() => - memoriesCapturedEvent.parse({ - costUsd: 0.0042, - memories: [ - { - content: "Release notes live in Notion.", - id: "memory-v2", - kind: "knowledge", - observedAtMs: 2, - scope: "conversation", - }, - ], - }), - ).toThrow(/scope/); + const v2Legacy = memoriesCapturedEvent.parse({ + costUsd: 0.0042, + memories: [ + { + content: "Release notes live in Notion.", + id: "memory-v2", + kind: "knowledge", + observedAtMs: 2, + scope: "conversation", + }, + { + content: "Prefer short replies.", + id: "memory-v2-personal", + kind: "preference", + observedAtMs: 3, + scope: "personal", + }, + ], + }); + expect(v2Legacy.memories.map((memory) => memory.scope)).toEqual([ + "public", + "private", + ]); + expect( + memoriesCapturedEvent.renderEvent(v2Legacy)?.details?.map( + (detail) => detail.metadata, + ), + ).toEqual([ + ["knowledge", "public"], + ["preference", "private"], + ]); }); it("omits empty extraction results from transcript presentation", () => { From 8b5d929c28a86710e4b8c49675fe8207d798c1ba Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 10:51:53 +0000 Subject: [PATCH 3/3] fix(memory): cover legacy v2 scope coercion on parse Update the events regression test to assert coerce-on-read instead of expecting a Zod throw, and drop the preprocess any cast. --- packages/junior-memory/src/events.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/junior-memory/src/events.ts b/packages/junior-memory/src/events.ts index f0ac79f7b6..5fc44ca7c2 100644 --- a/packages/junior-memory/src/events.ts +++ b/packages/junior-memory/src/events.ts @@ -5,7 +5,7 @@ import type { MemoryRecord } from "./store"; function currentScope( scope: "personal" | "conversation" | "private" | "public", -) { +): "private" | "public" { if (scope === "personal") return "private"; if (scope === "conversation") return "public"; return scope; @@ -28,7 +28,17 @@ const legacyCapturedMemorySchema = z const capturedMemorySchema = z .object({ ...capturedMemoryFields, - scope: z.preprocess((val) => currentScope(val as any), z.enum(MEMORY_SCOPES)), + scope: z.preprocess((val) => { + if ( + val === "personal" || + val === "conversation" || + val === "private" || + val === "public" + ) { + return currentScope(val); + } + return val; + }, z.enum(MEMORY_SCOPES)), }) .strict();