@@ -870,6 +870,42 @@ describe('groupMessagesIntoSnapshot (cold path)', () => {
870870 expect ( turn . attachmentIds ) . toEqual ( [ 'att_1' ] ) ;
871871 } ) ;
872872
873+ it . each ( [ 'user' , 'skill_activation' ] as const ) (
874+ 'filters malformed origin file attachments on %s messages' ,
875+ ( kind ) => {
876+ const snapshot = groupMessagesIntoSnapshot ( [
877+ {
878+ role : 'user' ,
879+ content : [ { type : 'text' , text : 'attached files' } ] ,
880+ toolCalls : [ ] ,
881+ origin : {
882+ kind,
883+ ...( kind === 'skill_activation' ? { trigger : 'user-slash' } : { } ) ,
884+ attachments : [
885+ null ,
886+ { name : 'wrong-size.txt' , mediaType : 'text/plain' , size : '12' } ,
887+ { name : 'note.txt' , mediaType : 'text/plain' , size : 12 , path : '/data/note.txt' } ,
888+ { name : 'wrong-path.txt' , mediaType : 'text/plain' , size : 12 , path : 42 } ,
889+ ] ,
890+ } as { kind : string ; trigger ?: string ; attachments : unknown } ,
891+ } ,
892+ { role : 'assistant' , content : [ { type : 'text' , text : 'done' } ] , toolCalls : [ ] } ,
893+ ] ) ;
894+
895+ expect ( snapshot . attachments ) . toEqual ( [
896+ {
897+ attachmentId : 'att_1' ,
898+ mediaType : 'text/plain' ,
899+ name : 'note.txt' ,
900+ size : 12 ,
901+ } ,
902+ ] ) ;
903+ const turn = snapshot . items . find ( ( item ) => item . kind === 'turn' ) ;
904+ if ( turn ?. kind !== 'turn' ) throw new Error ( 'expected turn' ) ;
905+ expect ( turn . attachmentIds ) . toEqual ( [ 'att_1' ] ) ;
906+ } ,
907+ ) ;
908+
873909 it ( 'maps persisted pythinker-file media refs to attachments' , ( ) => {
874910 const snapshot = groupMessagesIntoSnapshot ( [
875911 {
0 commit comments