@@ -155,6 +155,120 @@ describe('PineconeClient', () => {
155155 expect ( out . degraded ) . toBe ( false ) ;
156156 } ) ;
157157
158+ it ( 'reports hybrid_leg_failed and degraded when dense fails and sparse returns empty' , async ( ) => {
159+ const testClient = stubPineconeClient ( client ) ;
160+ const denseRef = { } as SearchableIndex ;
161+ const sparseRef = { } as SearchableIndex ;
162+
163+ testClient . ensureIndexes = async ( ) => ( {
164+ denseIndex : denseRef ,
165+ sparseIndex : sparseRef ,
166+ } ) ;
167+
168+ testClient . searchIndex = async ( index ) => {
169+ if ( index === denseRef ) {
170+ throw new Error ( 'dense failure' ) ;
171+ }
172+ return [ ] ;
173+ } ;
174+
175+ const out = await client . query ( {
176+ query : 'hybrid search' ,
177+ namespace : 'test' ,
178+ topK : 5 ,
179+ useReranking : false ,
180+ } ) ;
181+
182+ expect ( out . results ) . toHaveLength ( 0 ) ;
183+ expect ( out . hybrid_leg_failed ) . toBe ( 'dense' ) ;
184+ expect ( out . degraded ) . toBe ( true ) ;
185+ expect ( out . degradation_reason ) . toBe ( 'dense_leg_failed' ) ;
186+ } ) ;
187+
188+ it ( 'reports hybrid_leg_failed and degraded when sparse fails and dense returns empty' , async ( ) => {
189+ const testClient = stubPineconeClient ( client ) ;
190+ const denseRef = { } as SearchableIndex ;
191+ const sparseRef = { } as SearchableIndex ;
192+
193+ testClient . ensureIndexes = async ( ) => ( {
194+ denseIndex : denseRef ,
195+ sparseIndex : sparseRef ,
196+ } ) ;
197+
198+ testClient . searchIndex = async ( index ) => {
199+ if ( index === sparseRef ) {
200+ throw new Error ( 'sparse failure' ) ;
201+ }
202+ return [ ] ;
203+ } ;
204+
205+ const out = await client . query ( {
206+ query : 'hybrid search' ,
207+ namespace : 'test' ,
208+ topK : 5 ,
209+ useReranking : false ,
210+ } ) ;
211+
212+ expect ( out . results ) . toHaveLength ( 0 ) ;
213+ expect ( out . hybrid_leg_failed ) . toBe ( 'sparse' ) ;
214+ expect ( out . degraded ) . toBe ( true ) ;
215+ expect ( out . degradation_reason ) . toBe ( 'sparse_leg_failed' ) ;
216+ } ) ;
217+
218+ it ( 'returns no degradation when both legs succeed with empty hits' , async ( ) => {
219+ const testClient = stubPineconeClient ( client ) ;
220+ testClient . ensureIndexes = async ( ) => ( {
221+ denseIndex : { } as SearchableIndex ,
222+ sparseIndex : { } as SearchableIndex ,
223+ } ) ;
224+ testClient . searchIndex = async ( ) => [ ] ;
225+
226+ const out = await client . query ( {
227+ query : 'hybrid search' ,
228+ namespace : 'test' ,
229+ topK : 5 ,
230+ useReranking : false ,
231+ } ) ;
232+
233+ expect ( out . results ) . toHaveLength ( 0 ) ;
234+ expect ( out . hybrid_leg_failed ) . toBeNull ( ) ;
235+ expect ( out . degraded ) . toBe ( false ) ;
236+ expect ( out . degradation_reason ) . toBeUndefined ( ) ;
237+ } ) ;
238+
239+ it ( 'prioritizes leg-failure degradation_reason over rerank_skipped_no_model when both apply' , async ( ) => {
240+ const noModelClient = new PineconeClient ( {
241+ apiKey : 'test-api-key' ,
242+ indexName : 'test-index' ,
243+ } ) ;
244+ const testClient = stubPineconeClient ( noModelClient ) ;
245+ const denseRef = { } as SearchableIndex ;
246+ const sparseRef = { } as SearchableIndex ;
247+
248+ testClient . ensureIndexes = async ( ) => ( {
249+ denseIndex : denseRef ,
250+ sparseIndex : sparseRef ,
251+ } ) ;
252+ testClient . searchIndex = async ( index ) => {
253+ if ( index === denseRef ) {
254+ throw new Error ( 'dense failure' ) ;
255+ }
256+ return [ ] ;
257+ } ;
258+
259+ const out = await noModelClient . query ( {
260+ query : 'hybrid search' ,
261+ namespace : 'test' ,
262+ topK : 5 ,
263+ useReranking : true ,
264+ } ) ;
265+
266+ expect ( out . hybrid_leg_failed ) . toBe ( 'dense' ) ;
267+ expect ( out . degraded ) . toBe ( true ) ;
268+ expect ( out . degradation_reason ) . toBe ( 'dense_leg_failed' ) ;
269+ expect ( out . rerank_skipped_reason ) . toBe ( 'no_model' ) ;
270+ } ) ;
271+
158272 it ( 'should throw when both dense and sparse searches fail' , async ( ) => {
159273 const testClient = stubPineconeClient ( client ) ;
160274 stubDualLegSearchFailure ( testClient , new Error ( 'index failure' ) ) ;
0 commit comments