@@ -6,7 +6,6 @@ import { member } from '@sim/db/schema'
66import { queueTableRows , resetDbChainMock } from '@sim/testing'
77import { beforeEach , describe , expect , it , vi } from 'vitest'
88import { OrchestrationError } from '@/lib/core/orchestration/types'
9- import { EXACT_EMPTY_DURABLE_SECRET_PROVENANCE } from '@/lib/execution/durable-secret-provenance'
109
1110const mocks = vi . hoisted ( ( ) => ( {
1211 resolveWorkspace : vi . fn ( ) ,
@@ -188,143 +187,65 @@ describe('knowledge search application use case', () => {
188187 expect ( result . totalResults ) . toBe ( 0 )
189188 } )
190189
191- it ( 'uses provider-reported rerank units for the returned usage cost' , async ( ) => {
192- mocks . rerank . mockResolvedValue ( {
193- results : [ { item : { id : 'embedding-1' } , relevanceScore : 0.9 } ] ,
194- isBYOK : false ,
195- billedSearchUnits : 3 ,
196- } )
197- const result = await searchKnowledge . execute ( {
198- principal : { kind : 'session' , userId : 'user-1' , sessionId : 'session-1' } ,
199- input : {
200- workspaceId : 'workspace-1' ,
201- knowledgeBaseIds : [ 'knowledge-1' ] ,
202- query : 'answer' ,
203- topK : 5 ,
204- rerankerEnabled : true ,
205- rerankerModel : 'rerank-v4.0-fast' ,
206- } ,
190+ describe . each ( [ 'workspace' , 'organization' ] as const ) ( '%s ranking policy' , ( scope ) => {
191+ beforeEach ( ( ) => {
192+ if ( scope === 'organization' ) {
193+ mocks . getKnowledgeBase . mockResolvedValue ( {
194+ ...knowledgeBase ,
195+ workspaceId : null ,
196+ organizationId : 'org-canonical' ,
197+ isSearchIndex : true ,
198+ } )
199+ queueTableRows ( member , [ { role : 'member' } ] )
200+ }
207201 } )
208- expect ( result . cost ?. rerankerSearchUnits ) . toBe ( 3 )
209- expect ( result . cost ?. rerankerCost ) . toBe ( 3 * 0.002 )
210- expect ( mocks . rerank ) . toHaveBeenCalledWith (
211- 'answer' ,
212- [ { id : 'embedding-1' , text : 'answer' } ] ,
213- expect . objectContaining ( { timeoutMs : undefined } )
214- )
215- } )
216202
217- describe ( 'organization reranking' , ( ) => {
218- beforeEach ( ( ) => {
219- mocks . getKnowledgeBase . mockResolvedValue ( {
220- ...knowledgeBase ,
221- workspaceId : null ,
222- organizationId : 'org-canonical' ,
223- isSearchIndex : true ,
224- } )
225- queueTableRows ( member , [ { role : 'member' } ] )
226- mocks . importProvenance . mockResolvedValue ( {
227- imported : true ,
228- unrecordedCount : 0 ,
229- documentMetadata : {
230- 'document-1' : {
231- filename : 'REV-781 approval' ,
232- sourceUrl : null ,
233- provenance : EXACT_EMPTY_DURABLE_SECRET_PROVENANCE ,
203+ const principal = { kind : 'session' , userId : 'user-1' , sessionId : 'session-1' } as const
204+ const input = { knowledgeBaseIds : [ 'knowledge-1' ] , query : 'answer' , topK : 10 }
205+
206+ it . each ( [ undefined , false ] ) (
207+ 'preserves retrieval without reranking when enabled is %s' ,
208+ async ( rerankerEnabled ) => {
209+ const result = await searchKnowledge . execute ( {
210+ principal,
211+ input : {
212+ ...input ,
213+ ...( rerankerEnabled === undefined ? { } : { rerankerEnabled } ) ,
234214 } ,
235- } ,
236- } )
237- mocks . rerank . mockResolvedValue ( {
215+ } )
216+
217+ expect ( mocks . executeSearch ) . toHaveBeenCalledWith ( expect . objectContaining ( { topK : 10 } ) )
218+ expect ( mocks . rerank ) . not . toHaveBeenCalled ( )
219+ expect ( mocks . importProvenance ) . not . toHaveBeenCalled ( )
220+ expect ( result . rerankerStatus ) . toBe ( 'not_requested' )
221+ expect ( result . cost ?. rerankerSearchUnits ) . toBeUndefined ( )
222+ expect ( result . results [ 0 ] ) . toMatchObject ( { embeddingId : 'embedding-1' , content : 'answer' } )
223+ }
224+ )
225+
226+ it ( 'preserves the existing explicit reranking option' , async ( ) => {
227+ mocks . rerank . mockResolvedValueOnce ( {
238228 results : [ { item : { id : 'embedding-1' } , relevanceScore : 0.9 } ] ,
239229 isBYOK : false ,
240- billedSearchUnits : 1 ,
241230 } )
242- } )
243-
244- const principal = { kind : 'session' , userId : 'user-1' , sessionId : 'session-1' } as const
245- const input = { knowledgeBaseIds : [ 'knowledge-1' ] , query : 'approval' , topK : 10 }
246231
247- it ( 'uses the canonical organization owner to apply bounded title-aware reranking' , async ( ) => {
248- const result = await searchKnowledge . execute ( { principal, input } )
249- expect ( mocks . executeSearch ) . toHaveBeenCalledWith ( expect . objectContaining ( { topK : 50 } ) )
250- expect ( mocks . importProvenance ) . toHaveBeenCalledWith (
251- expect . objectContaining ( { includeDocumentNames : true } )
252- )
253- expect ( mocks . rerank ) . toHaveBeenCalledWith (
254- 'approval' ,
255- [ { id : 'embedding-1' , text : 'Title: REV-781 approval\n\nanswer' } ] ,
256- expect . objectContaining ( { model : 'rerank-v4.0-fast' , topN : 10 , timeoutMs : 3_000 } )
257- )
258- expect ( result . rerankerStatus ) . toBe ( 'applied' )
259- expect ( result . results [ 0 ] . documentName ) . toBe ( 'REV-781 approval' )
260- expect ( result . cost ?. rerankerModel ) . toBe ( 'rerank-v4.0-fast' )
261- } )
262-
263- it ( 'honors an explicit opt-out without expanding candidates or importing titles' , async ( ) => {
264232 const result = await searchKnowledge . execute ( {
265233 principal,
266- input : { ...input , rerankerEnabled : false } ,
234+ input : {
235+ ...input ,
236+ rerankerEnabled : true ,
237+ rerankerModel : 'rerank-v4.0-pro' ,
238+ rerankerInputCount : 20 ,
239+ } ,
267240 } )
268- expect ( mocks . executeSearch ) . toHaveBeenCalledWith ( expect . objectContaining ( { topK : 10 } ) )
269- expect ( mocks . rerank ) . not . toHaveBeenCalled ( )
270- expect ( mocks . importProvenance ) . not . toHaveBeenCalled ( )
271- expect ( result . rerankerStatus ) . toBe ( 'not_requested' )
272- } )
273241
274- it ( 'preserves explicit model and candidate choices within the organization latency budget' , async ( ) => {
275- await searchKnowledge . execute ( {
276- principal,
277- input : { ...input , rerankerModel : 'rerank-v4.0-pro' , rerankerInputCount : 20 } ,
278- } )
279242 expect ( mocks . executeSearch ) . toHaveBeenCalledWith ( expect . objectContaining ( { topK : 20 } ) )
280243 expect ( mocks . rerank ) . toHaveBeenCalledWith (
281- expect . anything ( ) ,
282- expect . anything ( ) ,
283- expect . objectContaining ( { model : 'rerank-v4.0-pro' , timeoutMs : 3_000 } )
284- )
285- } )
286-
287- it ( 'does not send a title to a model when its provenance snapshot is missing' , async ( ) => {
288- mocks . importProvenance . mockResolvedValue ( {
289- imported : true ,
290- unrecordedCount : 0 ,
291- documentMetadata : { } ,
292- } )
293- await expect ( searchKnowledge . execute ( { principal, input } ) ) . rejects . toThrow (
294- 'Knowledge result secret provenance is unavailable'
244+ 'answer' ,
245+ [ { id : 'embedding-1' , text : 'answer' } ] ,
246+ expect . objectContaining ( { model : 'rerank-v4.0-pro' , topN : 10 } )
295247 )
296- expect ( mocks . rerank ) . not . toHaveBeenCalled ( )
297- } )
298-
299- it ( 'does not disguise a provenance refusal as provider fallback' , async ( ) => {
300- mocks . importProvenance . mockResolvedValue ( {
301- imported : false ,
302- unrecordedCount : 0 ,
303- documentMetadata : { } ,
304- } )
305- await expect ( searchKnowledge . execute ( { principal, input } ) ) . rejects . toThrow (
306- 'Knowledge result secret provenance is unavailable'
307- )
308- expect ( mocks . rerank ) . not . toHaveBeenCalled ( )
309- } )
310-
311- it ( 'preserves authorized results and reports provider failure' , async ( ) => {
312- mocks . rerank . mockRejectedValue ( new Error ( 'Reranker unavailable' ) )
313- const result = await searchKnowledge . execute ( { principal, input } )
314- expect ( result . rerankerStatus ) . toBe ( 'unavailable' )
315- expect ( result . results ) . toHaveLength ( 1 )
316- expect ( result . results [ 0 ] . rerankerScore ) . toBeUndefined ( )
317- expect ( result . cost ?. rerankerSearchUnits ) . toBeUndefined ( )
318- } )
319-
320- it ( 'skips reranking when retrieval finds no authorized candidates' , async ( ) => {
321- mocks . executeSearch . mockResolvedValue ( [ ] )
322- const result = await searchKnowledge . execute ( {
323- principal,
324- input,
325- } )
326- expect ( mocks . rerank ) . not . toHaveBeenCalled ( )
327- expect ( result . rerankerStatus ) . toBe ( 'skipped' )
248+ expect ( result . rerankerStatus ) . toBe ( 'applied' )
328249 } )
329250 } )
330251
@@ -671,7 +592,6 @@ describe('knowledge search application use case', () => {
671592
672593 expect ( mocks . importProvenance ) . toHaveBeenCalledWith ( {
673594 registry,
674- includeDocumentNames : false ,
675595 results : expect . arrayContaining ( [
676596 expect . objectContaining ( { id : 'embedding-1' , documentId : 'document-1' } ) ,
677597 ] ) ,
@@ -755,6 +675,22 @@ describe('knowledge search application use case', () => {
755675 expect ( result . results [ 0 ] ) . not . toHaveProperty ( 'rerankerScore' )
756676 } )
757677
678+ /**
679+ * A resolved call with an empty ordering leaves the caller in the same place a
680+ * thrown one does — vector order, no `rerankerScore` — so it reports the same
681+ * status. It is not "the reranker matched nothing": `rerank` sends a non-empty
682+ * document list and asks for `top_n` of it, so an empty array means the
683+ * response carried nothing usable rather than a legitimate empty ranking.
684+ */
685+ it ( 'reports unavailable when the call resolves without a usable ordering' , async ( ) => {
686+ mocks . rerank . mockResolvedValueOnce ( { results : [ ] , isBYOK : false } )
687+
688+ const result = await rerankedSearch ( true )
689+
690+ expect ( result . rerankerStatus ) . toBe ( 'unavailable' )
691+ expect ( result . results [ 0 ] ) . not . toHaveProperty ( 'rerankerScore' )
692+ } )
693+
758694 it ( 'reports skipped for a tag-only search, which has no query to rank against' , async ( ) => {
759695 mocks . getTagDefinitions . mockResolvedValue ( [
760696 { tagSlot : 'tag1' , displayName : 'team' , fieldType : 'text' } ,
0 commit comments