@@ -6520,6 +6520,135 @@ func TestProcessOverrideSaveHandlerWritesToDefaultProject(t *testing.T) {
65206520 }
65216521}
65226522
6523+ // TestHandleSearchPersonalScopeIgnoresCWDProject verifies that when scope=personal
6524+ // and no explicit project is given, handleSearch returns personal memories from
6525+ // ALL projects rather than filtering to the cwd-detected project (issue #391).
6526+ func TestHandleSearchPersonalScopeIgnoresCWDProject (t * testing.T ) {
6527+ s := newMCPTestStore (t )
6528+
6529+ // Create sessions and personal observations in two distinct projects.
6530+ if err := s .CreateSession ("sess-proj-a" , "project-alpha" , "/tmp/project-alpha" ); err != nil {
6531+ t .Fatalf ("create session project-alpha: %v" , err )
6532+ }
6533+ if err := s .CreateSession ("sess-proj-b" , "project-beta" , "/tmp/project-beta" ); err != nil {
6534+ t .Fatalf ("create session project-beta: %v" , err )
6535+ }
6536+
6537+ _ , err := s .AddObservation (store.AddObservationParams {
6538+ SessionID : "sess-proj-a" ,
6539+ Type : "decision" ,
6540+ Title : "personal cross-project preference" ,
6541+ Content : "always use structured logging" ,
6542+ Project : "project-alpha" ,
6543+ Scope : "personal" ,
6544+ })
6545+ if err != nil {
6546+ t .Fatalf ("add personal observation project-alpha: %v" , err )
6547+ }
6548+
6549+ _ , err = s .AddObservation (store.AddObservationParams {
6550+ SessionID : "sess-proj-b" ,
6551+ Type : "decision" ,
6552+ Title : "personal note from beta" ,
6553+ Content : "prefer context-based cancellation" ,
6554+ Project : "project-beta" ,
6555+ Scope : "personal" ,
6556+ })
6557+ if err != nil {
6558+ t .Fatalf ("add personal observation project-beta: %v" , err )
6559+ }
6560+
6561+ // Simulate cwd being project-alpha's directory; the handler should NOT filter
6562+ // results to project-alpha when scope=personal is requested without an explicit project.
6563+ dir := t .TempDir ()
6564+ t .Chdir (dir )
6565+
6566+ h := handleSearch (s , MCPConfig {}, NewSessionActivity (10 * time .Minute ))
6567+ res , err := h (context .Background (), mcppkg.CallToolRequest {Params : mcppkg.CallToolParams {Arguments : map [string ]any {
6568+ "query" : "personal" ,
6569+ "scope" : "personal" ,
6570+ // no "project" argument — must NOT default to cwd project
6571+ }}})
6572+ if err != nil {
6573+ t .Fatalf ("search handler error: %v" , err )
6574+ }
6575+ if res .IsError {
6576+ t .Fatalf ("unexpected error: %s" , callResultText (t , res ))
6577+ }
6578+
6579+ text := callResultText (t , res )
6580+ // Both personal memories must be visible regardless of cwd project.
6581+ if ! strings .Contains (text , "personal cross-project preference" ) {
6582+ t .Errorf ("expected personal memory from project-alpha in results; got: %s" , text )
6583+ }
6584+ if ! strings .Contains (text , "personal note from beta" ) {
6585+ t .Errorf ("expected personal memory from project-beta in results; got: %s" , text )
6586+ }
6587+ }
6588+
6589+ // TestHandleContextPersonalScopeIgnoresCWDProject verifies that when scope=personal
6590+ // and no explicit project is given, handleContext returns personal observations from
6591+ // ALL projects rather than filtering to the cwd-detected project (issue #391).
6592+ func TestHandleContextPersonalScopeIgnoresCWDProject (t * testing.T ) {
6593+ s := newMCPTestStore (t )
6594+
6595+ if err := s .CreateSession ("ctx-sess-a" , "ctx-alpha" , "/tmp/ctx-alpha" ); err != nil {
6596+ t .Fatalf ("create session ctx-alpha: %v" , err )
6597+ }
6598+ if err := s .CreateSession ("ctx-sess-b" , "ctx-beta" , "/tmp/ctx-beta" ); err != nil {
6599+ t .Fatalf ("create session ctx-beta: %v" , err )
6600+ }
6601+
6602+ _ , err := s .AddObservation (store.AddObservationParams {
6603+ SessionID : "ctx-sess-a" ,
6604+ Type : "pattern" ,
6605+ Title : "personal pattern from alpha" ,
6606+ Content : "use table-driven tests everywhere" ,
6607+ Project : "ctx-alpha" ,
6608+ Scope : "personal" ,
6609+ })
6610+ if err != nil {
6611+ t .Fatalf ("add personal observation ctx-alpha: %v" , err )
6612+ }
6613+
6614+ _ , err = s .AddObservation (store.AddObservationParams {
6615+ SessionID : "ctx-sess-b" ,
6616+ Type : "pattern" ,
6617+ Title : "personal pattern from beta" ,
6618+ Content : "prefer explicit error wrapping" ,
6619+ Project : "ctx-beta" ,
6620+ Scope : "personal" ,
6621+ })
6622+ if err != nil {
6623+ t .Fatalf ("add personal observation ctx-beta: %v" , err )
6624+ }
6625+
6626+ // Simulate cwd being ctx-alpha's directory.
6627+ dir := t .TempDir ()
6628+ t .Chdir (dir )
6629+
6630+ h := handleContext (s , MCPConfig {}, NewSessionActivity (10 * time .Minute ))
6631+ res , err := h (context .Background (), mcppkg.CallToolRequest {Params : mcppkg.CallToolParams {Arguments : map [string ]any {
6632+ "scope" : "personal" ,
6633+ // no "project" argument — must NOT default to cwd project
6634+ }}})
6635+ if err != nil {
6636+ t .Fatalf ("context handler error: %v" , err )
6637+ }
6638+ if res .IsError {
6639+ t .Fatalf ("unexpected error: %s" , callResultText (t , res ))
6640+ }
6641+
6642+ text := callResultText (t , res )
6643+ // Both personal observations must appear in the context output.
6644+ if ! strings .Contains (text , "personal pattern from alpha" ) {
6645+ t .Errorf ("expected personal memory from ctx-alpha in context; got: %s" , text )
6646+ }
6647+ if ! strings .Contains (text , "personal pattern from beta" ) {
6648+ t .Errorf ("expected personal memory from ctx-beta in context; got: %s" , text )
6649+ }
6650+ }
6651+
65236652// ─── #403/#413: handleSessionSummary process-override tests ──────────────────
65246653
65256654// TestSessionSummary_ProcessOverrideWritesToDefaultProject verifies that when
0 commit comments