@@ -130,7 +130,7 @@ describe("createCtxMemoryTool", () => {
130130 }
131131 } ) ;
132132
133- it ( "updates a foreign workspace memory under the target identity " , async ( ) => {
133+ it ( "rejects updating a foreign workspace memory even when the category is shared " , async ( ) => {
134134 const db = createTestDb ( ) ;
135135 try {
136136 const primary = createCtxMemoryTool ( {
@@ -141,54 +141,46 @@ describe("createCtxMemoryTool", () => {
141141 } ) ;
142142 const ctx = fakeContext ( "ses-memory" ) as never ;
143143 const ownIdentity = resolveProjectIdentity ( ( ctx as { cwd : string } ) . cwd ) ;
144- // Default workspace shares CONSTRAINTS; this test exercises
145- // target-identity routing, so use a shared category (foreign memory
146- // visible) and verify the mutation routes under the target identity.
147144 db . exec ( `
148145 INSERT INTO workspaces (id, name, created_at, updated_at) VALUES (1, 'ws', 1, 1);
149146 INSERT INTO workspace_members (workspace_id, project_path, display_name, display_path, added_at)
150147 VALUES (1, '${ ownIdentity } ', 'Own', '${ ownIdentity } ', 1),
151148 (1, 'git:foreign', 'Foreign', '/foreign', 1);
152149 ` ) ;
153- insertMemory ( db , {
154- projectPath : ownIdentity ,
155- category : "CONSTRAINTS" ,
156- content : "Use the shared formatter." ,
157- } ) ;
158150 const foreign = insertMemory ( db , {
159151 projectPath : "git:foreign" ,
160152 category : "CONSTRAINTS" ,
161- content : "Old foreign directive ." ,
153+ content : "Old foreign shared constraint ." ,
162154 } ) ;
163155
164156 const result = await primary . execute (
165157 "call-u" ,
166158 {
167159 action : "update" ,
168160 ids : [ foreign . id ] ,
169- content : "Use the shared formatter ." ,
161+ content : "Updated foreign shared constraint ." ,
170162 } ,
171163 new AbortController ( ) . signal ,
172164 undefined ,
173165 ctx ,
174166 ) ;
175167
176- expect ( result . isError ) . toBeUndefined ( ) ;
168+ expect ( result . isError ) . toBe ( true ) ;
169+ expect ( result . content [ 0 ] ?. text ) . toBe (
170+ `Error: Memory with ID ${ foreign . id } was not found.` ,
171+ ) ;
177172 expect ( getMemoryById ( db , foreign . id ) ?. content ) . toBe (
178- "Use the shared formatter ." ,
173+ "Old foreign shared constraint ." ,
179174 ) ;
180- expect (
181- getMemoryMutationsForRender ( db , ownIdentity , 0 , [ foreign . id ] ) ,
182- ) . toHaveLength ( 0 ) ;
183175 expect (
184176 getMemoryMutationsForRender ( db , "git:foreign" , 0 , [ foreign . id ] ) ,
185- ) . toHaveLength ( 1 ) ;
177+ ) . toHaveLength ( 0 ) ;
186178 } finally {
187179 closeQuietly ( db ) ;
188180 }
189181 } ) ;
190182
191- it ( "archives a foreign workspace memory under the target identity " , async ( ) => {
183+ it ( "rejects archiving a foreign workspace memory even when the category is shared " , async ( ) => {
192184 const db = createTestDb ( ) ;
193185 try {
194186 const primary = createCtxMemoryTool ( {
@@ -199,8 +191,6 @@ describe("createCtxMemoryTool", () => {
199191 } ) ;
200192 const ctx = fakeContext ( "ses-memory" ) as never ;
201193 const ownIdentity = resolveProjectIdentity ( ( ctx as { cwd : string } ) . cwd ) ;
202- // Default workspace shares CONSTRAINTS; this test exercises
203- // target-identity routing, so use a shared category (foreign visible).
204194 db . exec ( `
205195 INSERT INTO workspaces (id, name, created_at, updated_at) VALUES (1, 'ws', 1, 1);
206196 INSERT INTO workspace_members (workspace_id, project_path, display_name, display_path, added_at)
@@ -210,7 +200,7 @@ describe("createCtxMemoryTool", () => {
210200 const foreign = insertMemory ( db , {
211201 projectPath : "git:foreign" ,
212202 category : "CONSTRAINTS" ,
213- content : "Foreign issue ." ,
203+ content : "Foreign shared constraint ." ,
214204 } ) ;
215205
216206 const result = await primary . execute (
@@ -221,11 +211,14 @@ describe("createCtxMemoryTool", () => {
221211 ctx ,
222212 ) ;
223213
224- expect ( result . isError ) . toBeUndefined ( ) ;
225- expect ( getMemoryById ( db , foreign . id ) ?. status ) . toBe ( "archived" ) ;
214+ expect ( result . isError ) . toBe ( true ) ;
215+ expect ( result . content [ 0 ] ?. text ) . toBe (
216+ `Error: Memory with ID ${ foreign . id } was not found.` ,
217+ ) ;
218+ expect ( getMemoryById ( db , foreign . id ) ?. status ) . toBe ( "active" ) ;
226219 expect (
227220 getMemoryMutationsForRender ( db , "git:foreign" , 0 , [ foreign . id ] ) ,
228- ) . toHaveLength ( 1 ) ;
221+ ) . toHaveLength ( 0 ) ;
229222 } finally {
230223 closeQuietly ( db ) ;
231224 }
@@ -271,7 +264,7 @@ describe("createCtxMemoryTool", () => {
271264 }
272265 } ) ;
273266
274- it ( "archives a foreign memory in a SHARED category (P0 parity) " , async ( ) => {
267+ it ( "rejects archiving a foreign memory in a SHARED category" , async ( ) => {
275268 const db = createTestDb ( ) ;
276269 try {
277270 const primary = createCtxMemoryTool ( {
@@ -302,8 +295,11 @@ describe("createCtxMemoryTool", () => {
302295 ctx ,
303296 ) ;
304297
305- expect ( result . isError ) . toBeUndefined ( ) ;
306- expect ( getMemoryById ( db , foreignShared . id ) ?. status ) . toBe ( "archived" ) ;
298+ expect ( result . isError ) . toBe ( true ) ;
299+ expect ( result . content [ 0 ] ?. text ) . toBe (
300+ `Error: Memory with ID ${ foreignShared . id } was not found.` ,
301+ ) ;
302+ expect ( getMemoryById ( db , foreignShared . id ) ?. status ) . toBe ( "active" ) ;
307303 } finally {
308304 closeQuietly ( db ) ;
309305 }
@@ -424,7 +420,7 @@ describe("createCtxMemoryTool", () => {
424420 }
425421 } ) ;
426422
427- it ( "allows a PRIMARY merge of a foreign SHARED-category memory (P0 parity) " , async ( ) => {
423+ it ( "rejects a PRIMARY merge of a foreign SHARED-category memory" , async ( ) => {
428424 const db = createTestDb ( ) ;
429425 try {
430426 const primary = createCtxMemoryTool ( {
@@ -465,12 +461,12 @@ describe("createCtxMemoryTool", () => {
465461 ctx ,
466462 ) ;
467463
468- // New merged content matches neither source, so a FRESH canonical is
469- // inserted and both sources are superseded → archived (parity with
470- // OpenCode's shared-merge test).
471- expect ( result . isError ) . toBeUndefined ( ) ;
472- expect ( getMemoryById ( db , own . id ) ?. status ) . toBe ( "archived " ) ;
473- expect ( getMemoryById ( db , foreignShared . id ) ?. status ) . toBe ( "archived " ) ;
464+ expect ( result . isError ) . toBe ( true ) ;
465+ expect ( result . content [ 0 ] ?. text ) . toBe (
466+ `Error: Memory with ID ${ foreignShared . id } was not found.` ,
467+ ) ;
468+ expect ( getMemoryById ( db , own . id ) ?. status ) . toBe ( "active " ) ;
469+ expect ( getMemoryById ( db , foreignShared . id ) ?. status ) . toBe ( "active " ) ;
474470 } finally {
475471 closeQuietly ( db ) ;
476472 }
@@ -575,6 +571,58 @@ describe("createCtxMemoryTool", () => {
575571 }
576572 } ) ;
577573
574+ it ( "REFUSES a DREAMER merge when workspace share_categories is malformed" , async ( ) => {
575+ const db = createTestDb ( ) ;
576+ try {
577+ const dreamer = createCtxMemoryTool ( {
578+ db,
579+ memoryEnabled : true ,
580+ embeddingEnabled : false ,
581+ allowDreamerActions : true ,
582+ } ) ;
583+ const ctx = fakeContext ( "ses-dreamer" ) as never ;
584+ const ownIdentity = resolveProjectIdentity ( ( ctx as { cwd : string } ) . cwd ) ;
585+ db . exec ( `
586+ INSERT INTO workspaces (id, name, created_at, updated_at, share_categories) VALUES (1, 'ws', 1, 1, 'not-json');
587+ INSERT INTO workspace_members (workspace_id, project_path, display_name, display_path, added_at)
588+ VALUES (1, '${ ownIdentity } ', 'Own', '${ ownIdentity } ', 1),
589+ (1, 'git:foreign', 'Foreign', '/foreign', 1);
590+ ` ) ;
591+ const own = insertMemory ( db , {
592+ projectPath : ownIdentity ,
593+ category : "CONSTRAINTS" ,
594+ content : "Own constraint malformed policy." ,
595+ } ) ;
596+ const foreign = insertMemory ( db , {
597+ projectPath : "git:foreign" ,
598+ category : "CONSTRAINTS" ,
599+ content : "Foreign constraint hidden by malformed policy." ,
600+ } ) ;
601+
602+ const result = await dreamer . execute (
603+ "call-d1-malformed" ,
604+ {
605+ action : "merge" ,
606+ ids : [ own . id , foreign . id ] ,
607+ content : "Merged malformed policy constraint." ,
608+ category : "CONSTRAINTS" ,
609+ } ,
610+ new AbortController ( ) . signal ,
611+ undefined ,
612+ ctx ,
613+ ) ;
614+
615+ expect ( result . isError ) . toBe ( true ) ;
616+ expect ( result . content [ 0 ] ?. text ) . toContain (
617+ "not shared with this workspace member" ,
618+ ) ;
619+ expect ( getMemoryById ( db , own . id ) ?. status ) . toBe ( "active" ) ;
620+ expect ( getMemoryById ( db , foreign . id ) ?. status ) . toBe ( "active" ) ;
621+ } finally {
622+ closeQuietly ( db ) ;
623+ }
624+ } ) ;
625+
578626 it ( "ALLOWS a DREAMER merge of a foreign SHARED-category memory INSIDE a workspace (D1 parity)" , async ( ) => {
579627 const db = createTestDb ( ) ;
580628 try {
0 commit comments