@@ -54,6 +54,60 @@ describe("memory search async sync", () => {
5454 expect ( queryMock ) . toHaveBeenCalledTimes ( 1 ) ;
5555 } ) ;
5656
57+ it ( "keeps vector-only results unweighted when FTS is unavailable" , async ( ) => {
58+ const vectorResult = {
59+ id : "memory-alpha" ,
60+ path : "memory/alpha.md" ,
61+ startLine : 1 ,
62+ endLine : 1 ,
63+ score : 0.9 ,
64+ snippet : "Alpha memory" ,
65+ source : "memory" as const ,
66+ } ;
67+ const mergeHybridResults = vi . fn ( async ( ) => [ ] ) ;
68+ const manager = Object . create ( MemoryIndexManager . prototype ) as MemoryIndexManager ;
69+ Object . assign ( manager as unknown as Record < string , unknown > , {
70+ providerRequirement : { mode : "optional" , provider : "openai" } ,
71+ providerLifecycle : { mode : "ready" } ,
72+ provider : { id : "mock" , model : "mock-embed" } ,
73+ settings : {
74+ sync : { onSearch : false } ,
75+ query : {
76+ minScore : 0.8 ,
77+ maxResults : 5 ,
78+ hybrid : {
79+ enabled : true ,
80+ candidateMultiplier : 2 ,
81+ vectorWeight : 0.5 ,
82+ textWeight : 0.5 ,
83+ temporalDecay : { enabled : false , halfLifeDays : 30 } ,
84+ } ,
85+ } ,
86+ } ,
87+ sources : new Set ( [ "memory" ] ) ,
88+ dirty : false ,
89+ sessionsDirty : false ,
90+ workspaceDir : "" ,
91+ drainReindex : vi . fn ( async ( ) => { } ) ,
92+ hasIndexedContentForSearch : vi . fn ( async ( ) => true ) ,
93+ warmSession : vi . fn ( ) ,
94+ sync : vi . fn ( async ( ) => { } ) ,
95+ ensureProviderInitialized : vi . fn ( async ( ) => { } ) ,
96+ assertRequiredProviderAvailable : vi . fn ( ) ,
97+ refreshSearchIndexIdentityDirty : vi . fn ( async ( ) => ( { status : "valid" } ) ) ,
98+ searchKeywordWithFallback : vi . fn ( async ( ) => [ ] ) ,
99+ embedQueryWithRetry : vi . fn ( async ( ) => [ 1 , 0 ] ) ,
100+ searchVector : vi . fn ( async ( ) => [ vectorResult ] ) ,
101+ hasKeywordSearchAvailable : vi . fn ( async ( ) => false ) ,
102+ mergeHybridResults,
103+ } ) ;
104+
105+ const results = await manager . search ( "alpha" ) ;
106+
107+ expect ( results ) . toEqual ( [ vectorResult ] ) ;
108+ expect ( mergeHybridResults ) . not . toHaveBeenCalled ( ) ;
109+ } ) ;
110+
57111 it ( "waits for in-flight search sync during close" , async ( ) => {
58112 let releaseSync = ( ) => { } ;
59113 const pendingSync = new Promise < void > ( ( resolve ) => {
0 commit comments