@absolutejs/absolute 0.19.0-beta.641 → 0.19.0-beta.643

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ai/index.js CHANGED
@@ -2933,21 +2933,40 @@ var formatTraceCountDelta = (value) => `${value >= 0 ? "+" : ""}${value}`;
2933
2933
  var buildComparisonOverviewPresentation = (input) => {
2934
2934
  const winnerLabel = input.resolveLabel(input.summary.bestByPassingRate);
2935
2935
  const winnerEntry = input.resolveEntry(input.summary.bestByPassingRate);
2936
+ const rows = [
2937
+ {
2938
+ label: "Best passing rate",
2939
+ value: input.resolveLabel(input.summary.bestByPassingRate)
2940
+ },
2941
+ {
2942
+ label: "Best average F1",
2943
+ value: input.resolveLabel(input.summary.bestByAverageF1)
2944
+ },
2945
+ {
2946
+ label: "Fastest",
2947
+ value: input.resolveLabel(input.summary.fastest)
2948
+ }
2949
+ ];
2950
+ if (input.summary.bestByMultivectorCollapsedCases) {
2951
+ rows.push({
2952
+ label: "Best multivector collapse",
2953
+ value: input.resolveLabel(input.summary.bestByMultivectorCollapsedCases)
2954
+ });
2955
+ }
2956
+ if (input.summary.bestByMultivectorLexicalHitCases) {
2957
+ rows.push({
2958
+ label: "Best multivector lexical hits",
2959
+ value: input.resolveLabel(input.summary.bestByMultivectorLexicalHitCases)
2960
+ });
2961
+ }
2962
+ if (input.summary.bestByMultivectorVectorHitCases) {
2963
+ rows.push({
2964
+ label: "Best multivector vector hits",
2965
+ value: input.resolveLabel(input.summary.bestByMultivectorVectorHitCases)
2966
+ });
2967
+ }
2936
2968
  return {
2937
- rows: [
2938
- {
2939
- label: "Best passing rate",
2940
- value: input.resolveLabel(input.summary.bestByPassingRate)
2941
- },
2942
- {
2943
- label: "Best average F1",
2944
- value: input.resolveLabel(input.summary.bestByAverageF1)
2945
- },
2946
- {
2947
- label: "Fastest",
2948
- value: input.resolveLabel(input.summary.fastest)
2949
- }
2950
- ],
2969
+ rows,
2951
2970
  winnerLabel,
2952
2971
  summary: winnerEntry ? `passing ${formatEvaluationPassingRate(winnerEntry.response.passingRate)} \xB7 f1 ${winnerEntry.response.summary.averageF1.toFixed(3)} \xB7 latency ${winnerEntry.response.summary.averageLatencyMs.toFixed(1)}ms` : "Stored benchmark comparison"
2953
2972
  };
@@ -2995,6 +3014,9 @@ var buildRAGComparisonTraceSummaryRows = (entry) => {
2995
3014
  }, {
2996
3015
  label: "Variants",
2997
3016
  value: formatTraceRatio(trace.variantCases, trace.totalCases)
3017
+ }, {
3018
+ label: "Multivector",
3019
+ value: `${formatTraceRatio(trace.multiVectorCases, trace.totalCases)} \xB7 collapse ${formatTraceRatio(trace.multiVectorCollapsedCases, trace.totalCases)} \xB7 lexical ${formatTraceRatio(trace.multiVectorLexicalHitCases, trace.totalCases)} \xB7 vector ${formatTraceRatio(trace.multiVectorVectorHitCases, trace.totalCases)}`
2998
3020
  }, {
2999
3021
  label: "TopK",
3000
3022
  value: `${trace.averageCandidateTopK.toFixed(1)} / ${trace.averageLexicalTopK.toFixed(1)}`
@@ -4051,6 +4073,15 @@ var evaluateRetrievalComparisonGate = ({
4051
4073
  if (typeof policy.maxElapsedMsDelta === "number" && delta.elapsedMsDelta > policy.maxElapsedMsDelta) {
4052
4074
  reasons.push(`elapsed ms delta ${delta.elapsedMsDelta} exceeds ${policy.maxElapsedMsDelta}`);
4053
4075
  }
4076
+ if (typeof policy.minMultiVectorCollapsedCasesDelta === "number" && (delta.multiVectorCollapsedCasesDelta ?? 0) < policy.minMultiVectorCollapsedCasesDelta) {
4077
+ reasons.push(`multivector collapsed delta ${delta.multiVectorCollapsedCasesDelta ?? 0} is below ${policy.minMultiVectorCollapsedCasesDelta}`);
4078
+ }
4079
+ if (typeof policy.minMultiVectorLexicalHitCasesDelta === "number" && (delta.multiVectorLexicalHitCasesDelta ?? 0) < policy.minMultiVectorLexicalHitCasesDelta) {
4080
+ reasons.push(`multivector lexical-hit delta ${delta.multiVectorLexicalHitCasesDelta ?? 0} is below ${policy.minMultiVectorLexicalHitCasesDelta}`);
4081
+ }
4082
+ if (typeof policy.minMultiVectorVectorHitCasesDelta === "number" && (delta.multiVectorVectorHitCasesDelta ?? 0) < policy.minMultiVectorVectorHitCasesDelta) {
4083
+ reasons.push(`multivector vector-hit delta ${delta.multiVectorVectorHitCasesDelta ?? 0} is below ${policy.minMultiVectorVectorHitCasesDelta}`);
4084
+ }
4054
4085
  if (reasons.length === 0) {
4055
4086
  return {
4056
4087
  policy,
@@ -4553,6 +4584,34 @@ var buildTraceSummaryAggregate = ({
4553
4584
  direction: "flat",
4554
4585
  metric: "variantCases",
4555
4586
  previous: 0
4587
+ },
4588
+ {
4589
+ current: 0,
4590
+ delta: 0,
4591
+ direction: "flat",
4592
+ metric: "multiVectorCases",
4593
+ previous: 0
4594
+ },
4595
+ {
4596
+ current: 0,
4597
+ delta: 0,
4598
+ direction: "flat",
4599
+ metric: "multiVectorVectorHitCases",
4600
+ previous: 0
4601
+ },
4602
+ {
4603
+ current: 0,
4604
+ delta: 0,
4605
+ direction: "flat",
4606
+ metric: "multiVectorLexicalHitCases",
4607
+ previous: 0
4608
+ },
4609
+ {
4610
+ current: 0,
4611
+ delta: 0,
4612
+ direction: "flat",
4613
+ metric: "multiVectorCollapsedCases",
4614
+ previous: 0
4556
4615
  }
4557
4616
  ];
4558
4617
  return {
@@ -4647,6 +4706,34 @@ var buildTraceSummaryAggregate = ({
4647
4706
  direction: buildTraceSummaryDirection(latest.variantCases - previous.variantCases),
4648
4707
  metric: "variantCases",
4649
4708
  previous: previous.variantCases
4709
+ },
4710
+ {
4711
+ current: latest.multiVectorCases,
4712
+ delta: latest.multiVectorCases - previous.multiVectorCases,
4713
+ direction: buildTraceSummaryDirection(latest.multiVectorCases - previous.multiVectorCases),
4714
+ metric: "multiVectorCases",
4715
+ previous: previous.multiVectorCases
4716
+ },
4717
+ {
4718
+ current: latest.multiVectorVectorHitCases,
4719
+ delta: latest.multiVectorVectorHitCases - previous.multiVectorVectorHitCases,
4720
+ direction: buildTraceSummaryDirection(latest.multiVectorVectorHitCases - previous.multiVectorVectorHitCases),
4721
+ metric: "multiVectorVectorHitCases",
4722
+ previous: previous.multiVectorVectorHitCases
4723
+ },
4724
+ {
4725
+ current: latest.multiVectorLexicalHitCases,
4726
+ delta: latest.multiVectorLexicalHitCases - previous.multiVectorLexicalHitCases,
4727
+ direction: buildTraceSummaryDirection(latest.multiVectorLexicalHitCases - previous.multiVectorLexicalHitCases),
4728
+ metric: "multiVectorLexicalHitCases",
4729
+ previous: previous.multiVectorLexicalHitCases
4730
+ },
4731
+ {
4732
+ current: latest.multiVectorCollapsedCases,
4733
+ delta: latest.multiVectorCollapsedCases - previous.multiVectorCollapsedCases,
4734
+ direction: buildTraceSummaryDirection(latest.multiVectorCollapsedCases - previous.multiVectorCollapsedCases),
4735
+ metric: "multiVectorCollapsedCases",
4736
+ previous: previous.multiVectorCollapsedCases
4650
4737
  }
4651
4738
  ];
4652
4739
  const absoluteSorted = [...aggregate].sort((left, right) => Math.abs(right.delta) - Math.abs(left.delta) || left.metric.localeCompare(right.metric));
@@ -4697,6 +4784,10 @@ var summarizeRetrievalTraces = (traces) => {
4697
4784
  let roundRobinCases = 0;
4698
4785
  let transformedCases = 0;
4699
4786
  let variantCases = 0;
4787
+ let multiVectorCases = 0;
4788
+ let multiVectorVectorHitCases = 0;
4789
+ let multiVectorLexicalHitCases = 0;
4790
+ let multiVectorCollapsedCases = 0;
4700
4791
  let finalCountSum = 0;
4701
4792
  let vectorCountSum = 0;
4702
4793
  let lexicalCountSum = 0;
@@ -4723,6 +4814,18 @@ var summarizeRetrievalTraces = (traces) => {
4723
4814
  if (trace.variantQueries.length > 0) {
4724
4815
  variantCases += 1;
4725
4816
  }
4817
+ if (trace.multiVector?.configured) {
4818
+ multiVectorCases += 1;
4819
+ }
4820
+ if ((trace.multiVector?.vectorVariantHits ?? 0) > 0) {
4821
+ multiVectorVectorHitCases += 1;
4822
+ }
4823
+ if ((trace.multiVector?.lexicalVariantHits ?? 0) > 0) {
4824
+ multiVectorLexicalHitCases += 1;
4825
+ }
4826
+ if ((trace.multiVector?.collapsedParents ?? 0) > 0) {
4827
+ multiVectorCollapsedCases += 1;
4828
+ }
4726
4829
  finalCountSum += trace.resultCounts.final;
4727
4830
  vectorCountSum += trace.resultCounts.vector;
4728
4831
  lexicalCountSum += trace.resultCounts.lexical;
@@ -4744,6 +4847,10 @@ var summarizeRetrievalTraces = (traces) => {
4744
4847
  totalCases,
4745
4848
  transformedCases,
4746
4849
  variantCases,
4850
+ multiVectorCases,
4851
+ multiVectorVectorHitCases,
4852
+ multiVectorLexicalHitCases,
4853
+ multiVectorCollapsedCases,
4747
4854
  vectorCases
4748
4855
  };
4749
4856
  };
@@ -8326,13 +8433,19 @@ var buildRAGRetrievalComparisonDecisionSummary = ({
8326
8433
  const delta = baselineEntry && candidateEntry ? {
8327
8434
  averageF1Delta: candidateEntry.response.summary.averageF1 - baselineEntry.response.summary.averageF1,
8328
8435
  elapsedMsDelta: candidateEntry.response.elapsedMs - baselineEntry.response.elapsedMs,
8329
- passingRateDelta: candidateEntry.response.passingRate - baselineEntry.response.passingRate
8436
+ passingRateDelta: candidateEntry.response.passingRate - baselineEntry.response.passingRate,
8437
+ multiVectorCollapsedCasesDelta: (candidateEntry.traceSummary?.multiVectorCollapsedCases ?? 0) - (baselineEntry.traceSummary?.multiVectorCollapsedCases ?? 0),
8438
+ multiVectorLexicalHitCasesDelta: (candidateEntry.traceSummary?.multiVectorLexicalHitCases ?? 0) - (baselineEntry.traceSummary?.multiVectorLexicalHitCases ?? 0),
8439
+ multiVectorVectorHitCasesDelta: (candidateEntry.traceSummary?.multiVectorVectorHitCases ?? 0) - (baselineEntry.traceSummary?.multiVectorVectorHitCases ?? 0)
8330
8440
  } : undefined;
8331
8441
  return {
8332
8442
  baseline: baselineEntry ? {
8333
8443
  averageF1: baselineEntry.response.summary.averageF1,
8334
8444
  elapsedMs: baselineEntry.response.elapsedMs,
8335
8445
  label: baselineEntry.label,
8446
+ multiVectorCollapsedCases: baselineEntry.traceSummary?.multiVectorCollapsedCases,
8447
+ multiVectorLexicalHitCases: baselineEntry.traceSummary?.multiVectorLexicalHitCases,
8448
+ multiVectorVectorHitCases: baselineEntry.traceSummary?.multiVectorVectorHitCases,
8336
8449
  passingRate: baselineEntry.response.passingRate,
8337
8450
  retrievalId: baselineEntry.retrievalId
8338
8451
  } : undefined,
@@ -8341,6 +8454,9 @@ var buildRAGRetrievalComparisonDecisionSummary = ({
8341
8454
  averageF1: candidateEntry.response.summary.averageF1,
8342
8455
  elapsedMs: candidateEntry.response.elapsedMs,
8343
8456
  label: candidateEntry.label,
8457
+ multiVectorCollapsedCases: candidateEntry.traceSummary?.multiVectorCollapsedCases,
8458
+ multiVectorLexicalHitCases: candidateEntry.traceSummary?.multiVectorLexicalHitCases,
8459
+ multiVectorVectorHitCases: candidateEntry.traceSummary?.multiVectorVectorHitCases,
8344
8460
  passingRate: candidateEntry.response.passingRate,
8345
8461
  retrievalId: candidateEntry.retrievalId
8346
8462
  } : undefined,
@@ -8349,7 +8465,10 @@ var buildRAGRetrievalComparisonDecisionSummary = ({
8349
8465
  fastest: comparison.summary.fastest,
8350
8466
  gate: evaluateRetrievalComparisonGate({ delta, policy }),
8351
8467
  winnerByAverageF1: comparison.summary.bestByAverageF1,
8352
- winnerByPassingRate: comparison.summary.bestByPassingRate
8468
+ winnerByPassingRate: comparison.summary.bestByPassingRate,
8469
+ winnerByMultivectorCollapsedCases: comparison.summary.bestByMultivectorCollapsedCases,
8470
+ winnerByMultivectorLexicalHitCases: comparison.summary.bestByMultivectorLexicalHitCases,
8471
+ winnerByMultivectorVectorHitCases: comparison.summary.bestByMultivectorVectorHitCases
8353
8472
  };
8354
8473
  };
8355
8474
  var loadRAGSearchTracePruneHistory = async ({
@@ -9011,6 +9130,32 @@ var summarizeEvaluationResponseComparison = (entries, idKey) => {
9011
9130
  fastest: getId(byLatency[0])
9012
9131
  };
9013
9132
  };
9133
+ var selectComparisonEntryByTraceMetric = (entries, idKey, metric) => {
9134
+ const ranked = [...entries].sort((left, right) => {
9135
+ const leftMetric = left.traceSummary?.[metric] ?? 0;
9136
+ const rightMetric = right.traceSummary?.[metric] ?? 0;
9137
+ if (rightMetric !== leftMetric) {
9138
+ return rightMetric - leftMetric;
9139
+ }
9140
+ const leftEvidenceScore = (left.traceSummary?.multiVectorCollapsedCases ?? 0) + (left.traceSummary?.multiVectorLexicalHitCases ?? 0) + (left.traceSummary?.multiVectorVectorHitCases ?? 0);
9141
+ const rightEvidenceScore = (right.traceSummary?.multiVectorCollapsedCases ?? 0) + (right.traceSummary?.multiVectorLexicalHitCases ?? 0) + (right.traceSummary?.multiVectorVectorHitCases ?? 0);
9142
+ if (rightEvidenceScore !== leftEvidenceScore) {
9143
+ return rightEvidenceScore - leftEvidenceScore;
9144
+ }
9145
+ if (right.response.passingRate !== left.response.passingRate) {
9146
+ return right.response.passingRate - left.response.passingRate;
9147
+ }
9148
+ if (right.response.summary.averageF1 !== left.response.summary.averageF1) {
9149
+ return right.response.summary.averageF1 - left.response.summary.averageF1;
9150
+ }
9151
+ return left.response.summary.averageLatencyMs - right.response.summary.averageLatencyMs;
9152
+ });
9153
+ const winner = ranked[0];
9154
+ if (!winner || (winner.traceSummary?.[metric] ?? 0) === 0) {
9155
+ return;
9156
+ }
9157
+ return typeof winner[idKey] === "string" ? winner[idKey] : undefined;
9158
+ };
9014
9159
  var resolveRetrievalMode = (candidate) => {
9015
9160
  if (!candidate.retrieval) {
9016
9161
  return "vector";
@@ -9100,7 +9245,11 @@ var compareRAGRetrievalTraceSummaries = (current, previous) => ({
9100
9245
  totalCasesDelta: current.totalCases - previous.totalCases,
9101
9246
  transformedCasesDelta: current.transformedCases - previous.transformedCases,
9102
9247
  vectorCasesDelta: current.vectorCases - previous.vectorCases,
9103
- variantCasesDelta: current.variantCases - previous.variantCases
9248
+ variantCasesDelta: current.variantCases - previous.variantCases,
9249
+ multiVectorCasesDelta: current.multiVectorCases - previous.multiVectorCases,
9250
+ multiVectorVectorHitCasesDelta: current.multiVectorVectorHitCases - previous.multiVectorVectorHitCases,
9251
+ multiVectorLexicalHitCasesDelta: current.multiVectorLexicalHitCases - previous.multiVectorLexicalHitCases,
9252
+ multiVectorCollapsedCasesDelta: current.multiVectorCollapsedCases - previous.multiVectorCollapsedCases
9104
9253
  });
9105
9254
  var buildSearchTraceResultSnapshots = (results) => results.map((result) => ({
9106
9255
  chunkId: result.chunkId,
@@ -9665,7 +9814,12 @@ var summarizeRAGEvaluationCase = ({
9665
9814
  var summarizeRAGRerankerComparison = (entries) => {
9666
9815
  return summarizeEvaluationResponseComparison(entries, "rerankerId");
9667
9816
  };
9668
- var summarizeRAGRetrievalComparison = (entries) => summarizeEvaluationResponseComparison(entries, "retrievalId");
9817
+ var summarizeRAGRetrievalComparison = (entries) => ({
9818
+ ...summarizeEvaluationResponseComparison(entries, "retrievalId"),
9819
+ bestByMultivectorCollapsedCases: selectComparisonEntryByTraceMetric(entries, "retrievalId", "multiVectorCollapsedCases"),
9820
+ bestByMultivectorLexicalHitCases: selectComparisonEntryByTraceMetric(entries, "retrievalId", "multiVectorLexicalHitCases"),
9821
+ bestByMultivectorVectorHitCases: selectComparisonEntryByTraceMetric(entries, "retrievalId", "multiVectorVectorHitCases")
9822
+ });
9669
9823
  // src/ai/providers/openai.ts
9670
9824
  var DEFAULT_BASE_URL = "https://api.openai.com";
9671
9825
  var SSE_DATA_PREFIX_LENGTH = 6;
@@ -12780,6 +12934,43 @@ var scoreStructuredEvidenceMatch = (query, queryTokens, result) => {
12780
12934
  }
12781
12935
  return score;
12782
12936
  };
12937
+ var scoreMultivectorEvidenceMatch = (query, queryTokens, result) => {
12938
+ const metadata = result.metadata ?? {};
12939
+ const matchedVariantCount = typeof metadata.multivectorMatchedVariantCount === "number" ? metadata.multivectorMatchedVariantCount : 0;
12940
+ const matchedVariantLabel = metadataString(metadata.multivectorMatchedVariantLabel);
12941
+ const matchedVariantText = metadataString(metadata.multivectorMatchedVariantText);
12942
+ if (matchedVariantCount === 0 && !matchedVariantLabel && !matchedVariantText) {
12943
+ return 0;
12944
+ }
12945
+ let score = 0;
12946
+ const exactPhraseIntent = queryHasAnyToken(queryTokens, [
12947
+ "phrase",
12948
+ "phrasing",
12949
+ "wording",
12950
+ "verbatim",
12951
+ "quote",
12952
+ "quoted",
12953
+ "precise",
12954
+ "exact"
12955
+ ]);
12956
+ if (matchedVariantCount > 0) {
12957
+ score += Math.min(0.18, matchedVariantCount * 0.06);
12958
+ }
12959
+ if (matchedVariantLabel) {
12960
+ score += 0.18 * scoreLoosePhraseMatch2(query, matchedVariantLabel);
12961
+ if (exactPhraseIntent && queryTokens.some((token) => matchedVariantLabel.includes(token))) {
12962
+ score += 0.08;
12963
+ }
12964
+ }
12965
+ if (matchedVariantText) {
12966
+ const phraseScore = scoreLoosePhraseMatch2(query, matchedVariantText);
12967
+ score += exactPhraseIntent ? 1.1 * phraseScore : 0.6 * phraseScore;
12968
+ if (queryHasQuotedPhraseMatch(query, matchedVariantText)) {
12969
+ score += 0.45;
12970
+ }
12971
+ }
12972
+ return score;
12973
+ };
12783
12974
  var scoreHeuristicMatch = ({
12784
12975
  query,
12785
12976
  queryTokens,
@@ -12797,7 +12988,8 @@ var scoreHeuristicMatch = ({
12797
12988
  const sourcePathBoost = typeof result.source === "string" && queryTokens.some((token) => result.source?.toLowerCase().includes(token)) ? 0.5 : 0;
12798
12989
  const metadataBoost = metadataValues.length > 0 ? queryTokens.filter((token) => metadataValues.some((value) => value.toLowerCase().includes(token))).length / queryTokens.length : 0;
12799
12990
  const structuredEvidenceBoost = scoreStructuredEvidenceMatch(query, queryTokens, result);
12800
- return result.score + overlapBoost + exactPhraseBoost + sourcePathBoost + metadataBoost + structuredEvidenceBoost;
12991
+ const multivectorEvidenceBoost = scoreMultivectorEvidenceMatch(query, queryTokens, result);
12992
+ return result.score + overlapBoost + exactPhraseBoost + sourcePathBoost + metadataBoost + structuredEvidenceBoost + multivectorEvidenceBoost;
12801
12993
  };
12802
12994
  var normalizeText = (value) => tokenize3(value).join(" ");
12803
12995
  var applyRAGReranking = async ({
@@ -16711,6 +16903,13 @@ var prepareRAGDirectoryDocuments = async (input) => prepareRAGDocuments(await lo
16711
16903
 
16712
16904
  // src/ai/rag/collection.ts
16713
16905
  var DEFAULT_TOP_K2 = 6;
16906
+ var MULTIVECTOR_VARIANT_CHUNK_DELIMITER = "__mv__";
16907
+ var MULTIVECTOR_PARENT_CHUNK_ID = "absoluteMultivectorParentChunkId";
16908
+ var MULTIVECTOR_VARIANT_ID = "absoluteMultivectorVariantId";
16909
+ var MULTIVECTOR_VARIANT_LABEL = "absoluteMultivectorVariantLabel";
16910
+ var MULTIVECTOR_VARIANT_TEXT = "absoluteMultivectorVariantText";
16911
+ var MULTIVECTOR_VARIANT_METADATA = "absoluteMultivectorVariantMetadata";
16912
+ var MULTIVECTOR_PRIMARY = "absoluteMultivectorPrimary";
16714
16913
  var resolveNativeQueryProfile = (input) => {
16715
16914
  if (!input.profile) {
16716
16915
  return;
@@ -16752,6 +16951,29 @@ var queryIncludesTraceCue = (query, value) => {
16752
16951
  const normalizedValue = normalizeTraceCueText(value);
16753
16952
  return normalizedQuery.length > 0 && normalizedValue.length > 0 && normalizedQuery.includes(normalizedValue);
16754
16953
  };
16954
+ var queryIncludesLooseTraceCue = (query, value) => {
16955
+ if (typeof value !== "string" || value.trim().length === 0) {
16956
+ return false;
16957
+ }
16958
+ const normalizedQuery = normalizeTraceCueText(query);
16959
+ const normalizedValue = normalizeTraceCueText(value);
16960
+ if (normalizedQuery.length === 0 || normalizedValue.length === 0) {
16961
+ return false;
16962
+ }
16963
+ if (normalizedValue.includes(normalizedQuery)) {
16964
+ return true;
16965
+ }
16966
+ const words = normalizedQuery.split(" ").filter(Boolean);
16967
+ for (let size = Math.min(5, words.length);size >= 2; size -= 1) {
16968
+ for (let index = 0;index <= words.length - size; index += 1) {
16969
+ const phrase = words.slice(index, index + size).join(" ");
16970
+ if (phrase.length > 0 && normalizedValue.includes(phrase)) {
16971
+ return true;
16972
+ }
16973
+ }
16974
+ }
16975
+ return false;
16976
+ };
16755
16977
  var queryHasAnyTraceToken = (query, candidates) => {
16756
16978
  const normalizedQuery = normalizeTraceCueText(query);
16757
16979
  return candidates.some((candidate) => normalizedQuery.includes(normalizeTraceCueText(candidate)));
@@ -16803,6 +17025,33 @@ var buildMediaRerankTraceMetadata = (query, result) => {
16803
17025
  }
16804
17026
  return traceMetadata;
16805
17027
  };
17028
+ var buildMultivectorRerankTraceMetadata = (query, result) => {
17029
+ if (!result?.metadata) {
17030
+ return {};
17031
+ }
17032
+ const metadata = result.metadata;
17033
+ const traceMetadata = {};
17034
+ const matchedVariantId = typeof metadata.multivectorMatchedVariantId === "string" ? metadata.multivectorMatchedVariantId : undefined;
17035
+ const matchedVariantLabel = typeof metadata.multivectorMatchedVariantLabel === "string" ? metadata.multivectorMatchedVariantLabel : undefined;
17036
+ const matchedVariantText = typeof metadata.multivectorMatchedVariantText === "string" ? metadata.multivectorMatchedVariantText : undefined;
17037
+ const matchedVariantCount = typeof metadata.multivectorMatchedVariantCount === "number" ? metadata.multivectorMatchedVariantCount : null;
17038
+ if (!matchedVariantId && !matchedVariantLabel && !matchedVariantText) {
17039
+ return {};
17040
+ }
17041
+ traceMetadata.leadMultivectorVariantCount = matchedVariantCount;
17042
+ traceMetadata.leadMultivectorVariantId = matchedVariantId ?? null;
17043
+ traceMetadata.leadMultivectorVariantLabel = matchedVariantLabel ?? null;
17044
+ if (queryIncludesQuotedTraceCue(query, matchedVariantText)) {
17045
+ traceMetadata.leadMultivectorVariantCue = "quoted_match";
17046
+ } else if (queryIncludesLooseTraceCue(query, matchedVariantText) || queryIncludesTraceCue(query, matchedVariantText)) {
17047
+ traceMetadata.leadMultivectorVariantCue = "phrase_match";
17048
+ } else if (queryIncludesTraceCue(query, matchedVariantLabel)) {
17049
+ traceMetadata.leadMultivectorVariantCue = "label_match";
17050
+ } else {
17051
+ traceMetadata.leadMultivectorVariantCue = "variant_match";
17052
+ }
17053
+ return traceMetadata;
17054
+ };
16806
17055
  var mergeQueryResults = (results) => {
16807
17056
  const merged = new Map;
16808
17057
  for (const result of results) {
@@ -16826,6 +17075,111 @@ var mergeQueryResults = (results) => {
16826
17075
  return left.chunkId.localeCompare(right.chunkId);
16827
17076
  });
16828
17077
  };
17078
+ var getMultivectorParentChunkId = (result) => typeof result.metadata?.[MULTIVECTOR_PARENT_CHUNK_ID] === "string" ? result.metadata[MULTIVECTOR_PARENT_CHUNK_ID] : undefined;
17079
+ var stripMultivectorInternalMetadata = (metadata) => {
17080
+ if (!metadata) {
17081
+ return;
17082
+ }
17083
+ const cleaned = { ...metadata };
17084
+ delete cleaned[MULTIVECTOR_PARENT_CHUNK_ID];
17085
+ delete cleaned[MULTIVECTOR_VARIANT_ID];
17086
+ delete cleaned[MULTIVECTOR_VARIANT_LABEL];
17087
+ delete cleaned[MULTIVECTOR_VARIANT_TEXT];
17088
+ delete cleaned[MULTIVECTOR_VARIANT_METADATA];
17089
+ delete cleaned[MULTIVECTOR_PRIMARY];
17090
+ return cleaned;
17091
+ };
17092
+ var collapseMultivectorResults = (results) => {
17093
+ const grouped = new Map;
17094
+ for (const result of results) {
17095
+ const parentChunkId = getMultivectorParentChunkId(result) ?? result.chunkId;
17096
+ const existing = grouped.get(parentChunkId);
17097
+ const nextVariantHits = getMultivectorParentChunkId(result) ? 1 : 0;
17098
+ if (existing) {
17099
+ existing.results.push(result);
17100
+ existing.variantHits += nextVariantHits;
17101
+ continue;
17102
+ }
17103
+ grouped.set(parentChunkId, {
17104
+ parentChunkId,
17105
+ results: [result],
17106
+ variantHits: nextVariantHits
17107
+ });
17108
+ }
17109
+ let variantHits = 0;
17110
+ let collapsedParents = 0;
17111
+ const collapsed = [...grouped.values()].map((entry) => {
17112
+ variantHits += entry.variantHits;
17113
+ if (entry.variantHits > 0) {
17114
+ collapsedParents += 1;
17115
+ }
17116
+ const preferred = entry.results.reduce((best, current) => current.score > best.score ? current : best);
17117
+ const variantMatches = entry.results.map((result) => {
17118
+ const variantId = result.metadata?.[MULTIVECTOR_VARIANT_ID];
17119
+ if (typeof variantId !== "string") {
17120
+ return;
17121
+ }
17122
+ return {
17123
+ id: variantId,
17124
+ label: typeof result.metadata?.[MULTIVECTOR_VARIANT_LABEL] === "string" ? String(result.metadata?.[MULTIVECTOR_VARIANT_LABEL]) : undefined,
17125
+ text: typeof result.metadata?.[MULTIVECTOR_VARIANT_TEXT] === "string" ? String(result.metadata?.[MULTIVECTOR_VARIANT_TEXT]) : undefined,
17126
+ score: result.score
17127
+ };
17128
+ }).filter((value) => value !== undefined).sort((left, right) => right.score - left.score);
17129
+ const cleanedMetadata = stripMultivectorInternalMetadata(preferred.metadata);
17130
+ return {
17131
+ ...preferred,
17132
+ chunkId: entry.parentChunkId,
17133
+ metadata: {
17134
+ ...cleanedMetadata ?? {},
17135
+ multivectorMatchedVariantCount: variantMatches.length,
17136
+ multivectorMatchedVariantId: variantMatches[0]?.id,
17137
+ multivectorMatchedVariantLabel: variantMatches[0]?.label,
17138
+ multivectorMatchedVariantText: variantMatches[0]?.text,
17139
+ multivectorMatchedVariants: variantMatches.length > 0 ? variantMatches.map((match) => ({
17140
+ id: match.id,
17141
+ label: match.label,
17142
+ text: match.text,
17143
+ score: match.score
17144
+ })) : undefined
17145
+ }
17146
+ };
17147
+ }).sort((left, right) => {
17148
+ if (right.score !== left.score) {
17149
+ return right.score - left.score;
17150
+ }
17151
+ return left.chunkId.localeCompare(right.chunkId);
17152
+ });
17153
+ return {
17154
+ collapsed,
17155
+ collapsedParents,
17156
+ variantHits
17157
+ };
17158
+ };
17159
+ var expandChunkForMultivectorStorage = (chunk) => {
17160
+ const expanded = [{ ...chunk }];
17161
+ for (const variant of chunk.embeddingVariants ?? []) {
17162
+ if (!variant.id) {
17163
+ continue;
17164
+ }
17165
+ expanded.push({
17166
+ ...chunk,
17167
+ chunkId: `${chunk.chunkId}${MULTIVECTOR_VARIANT_CHUNK_DELIMITER}${variant.id}`,
17168
+ embedding: variant.embedding,
17169
+ metadata: {
17170
+ ...chunk.metadata ?? {},
17171
+ [MULTIVECTOR_PARENT_CHUNK_ID]: chunk.chunkId,
17172
+ [MULTIVECTOR_PRIMARY]: false,
17173
+ [MULTIVECTOR_VARIANT_ID]: variant.id,
17174
+ ...variant.label ? { [MULTIVECTOR_VARIANT_LABEL]: variant.label } : {},
17175
+ ...variant.text ? { [MULTIVECTOR_VARIANT_TEXT]: variant.text } : {},
17176
+ ...variant.metadata ? { [MULTIVECTOR_VARIANT_METADATA]: variant.metadata } : {}
17177
+ },
17178
+ text: variant.text ?? chunk.text
17179
+ });
17180
+ }
17181
+ return expanded;
17182
+ };
16829
17183
  var getRAGSourceDiversityKey = (result) => {
16830
17184
  const documentId = typeof result.metadata?.documentId === "string" ? result.metadata.documentId : undefined;
16831
17185
  return result.source ?? documentId ?? result.title ?? result.chunkId;
@@ -17272,23 +17626,34 @@ var createRAGCollection = (options) => {
17272
17626
  topK: lexicalTopK
17273
17627
  }) ?? Promise.resolve([]) : Promise.resolve([])
17274
17628
  ]);
17629
+ const annotatedLexicalResults = annotateRetrievalQueryOrigin({
17630
+ inputQuery: input.query,
17631
+ query,
17632
+ queryIndex,
17633
+ results: weightQueryResults(lexicalResults2, queryIndex),
17634
+ transformedQuery: transformed.query
17635
+ });
17636
+ const annotatedVectorResults = annotateRetrievalQueryOrigin({
17637
+ inputQuery: input.query,
17638
+ query,
17639
+ queryIndex,
17640
+ results: weightQueryResults(vectorResults2, queryIndex),
17641
+ transformedQuery: transformed.query
17642
+ });
17643
+ const collapsedLexicalResults = collapseMultivectorResults(annotatedLexicalResults);
17644
+ const collapsedVectorResults = collapseMultivectorResults(annotatedVectorResults);
17275
17645
  return {
17276
- lexicalResults: annotateRetrievalQueryOrigin({
17277
- inputQuery: input.query,
17278
- query,
17279
- queryIndex,
17280
- results: weightQueryResults(lexicalResults2, queryIndex),
17281
- transformedQuery: transformed.query
17282
- }),
17283
- vectorResults: annotateRetrievalQueryOrigin({
17284
- inputQuery: input.query,
17285
- query,
17286
- queryIndex,
17287
- results: weightQueryResults(vectorResults2, queryIndex),
17288
- transformedQuery: transformed.query
17289
- })
17646
+ lexicalResults: collapsedLexicalResults.collapsed,
17647
+ lexicalVariantHits: collapsedLexicalResults.variantHits,
17648
+ lexicalCollapsedParents: collapsedLexicalResults.collapsedParents,
17649
+ vectorResults: collapsedVectorResults.collapsed,
17650
+ vectorVariantHits: collapsedVectorResults.variantHits,
17651
+ vectorCollapsedParents: collapsedVectorResults.collapsedParents
17290
17652
  };
17291
17653
  }));
17654
+ const vectorVariantHits = resultGroups.reduce((total, group) => total + group.vectorVariantHits, 0);
17655
+ const lexicalVariantHits = resultGroups.reduce((total, group) => total + group.lexicalVariantHits, 0);
17656
+ const collapsedParents = resultGroups.reduce((total, group) => total + Math.max(group.vectorCollapsedParents, group.lexicalCollapsedParents), 0);
17292
17657
  const vectorResults = mergeQueryResults(resultGroups.flatMap((group) => group.vectorResults));
17293
17658
  if (runVector) {
17294
17659
  const vectorPlanMetadata = buildStoreQueryPlanTraceMetadata(options.store);
@@ -17296,6 +17661,8 @@ var createRAGCollection = (options) => {
17296
17661
  count: vectorResults.length,
17297
17662
  label: "Collected vector candidates",
17298
17663
  metadata: {
17664
+ collapsedParents,
17665
+ multiVectorVariantHits: vectorVariantHits,
17299
17666
  queryCount: searchQueries.length,
17300
17667
  topK: candidateTopK,
17301
17668
  ...vectorPlanMetadata
@@ -17311,6 +17678,8 @@ var createRAGCollection = (options) => {
17311
17678
  count: lexicalResults.length,
17312
17679
  label: "Collected lexical candidates",
17313
17680
  metadata: {
17681
+ collapsedParents,
17682
+ multiVectorVariantHits: lexicalVariantHits,
17314
17683
  queryCount: searchQueries.length,
17315
17684
  topK: lexicalTopK
17316
17685
  },
@@ -17356,7 +17725,8 @@ var createRAGCollection = (options) => {
17356
17725
  label: hasReranker ? "Reranked retrieval candidates" : "Skipped reranking and kept retrieval order",
17357
17726
  metadata: {
17358
17727
  applied: hasReranker,
17359
- ...buildMediaRerankTraceMetadata(transformed.query, reranked[0])
17728
+ ...buildMediaRerankTraceMetadata(transformed.query, reranked[0]),
17729
+ ...buildMultivectorRerankTraceMetadata(transformed.query, reranked[0])
17360
17730
  },
17361
17731
  sectionCounts: buildTraceSectionCounts(reranked),
17362
17732
  sectionScores: buildTraceSectionScores(reranked),
@@ -17419,6 +17789,12 @@ var createRAGCollection = (options) => {
17419
17789
  queryTransformLabel: transformed.label,
17420
17790
  queryTransformProvider: resolvedQueryTransform?.providerName,
17421
17791
  queryTransformReason: transformed.reason,
17792
+ multiVector: {
17793
+ collapsedParents,
17794
+ configured: vectorVariantHits > 0 || lexicalVariantHits > 0,
17795
+ lexicalVariantHits,
17796
+ vectorVariantHits
17797
+ },
17422
17798
  resultCounts: {
17423
17799
  final: limited.length,
17424
17800
  fused: results.length,
@@ -17475,6 +17851,12 @@ var createRAGCollection = (options) => {
17475
17851
  queryTransformLabel: transformed.label,
17476
17852
  queryTransformProvider: resolvedQueryTransform?.providerName,
17477
17853
  queryTransformReason: transformed.reason,
17854
+ multiVector: {
17855
+ collapsedParents,
17856
+ configured: vectorVariantHits > 0 || lexicalVariantHits > 0,
17857
+ lexicalVariantHits,
17858
+ vectorVariantHits
17859
+ },
17478
17860
  resultCounts: {
17479
17861
  final: filtered.length,
17480
17862
  fused: results.length,
@@ -17502,19 +17884,31 @@ var createRAGCollection = (options) => {
17502
17884
  return result.results;
17503
17885
  };
17504
17886
  const ingest = async (input) => {
17505
- const chunks = await Promise.all(input.chunks.map(async (chunk) => {
17506
- if (chunk.embedding) {
17507
- validateRAGEmbeddingDimensions(chunk.embedding, getExpectedDimensions(), "chunk");
17508
- return chunk;
17509
- }
17510
- return {
17511
- ...chunk,
17512
- embedding: await embed({
17887
+ const chunks = (await Promise.all(input.chunks.map(async (chunk) => {
17888
+ const normalizedEmbedding = chunk.embedding ? (validateRAGEmbeddingDimensions(chunk.embedding, getExpectedDimensions(), "chunk"), chunk.embedding) : await embed({
17889
+ model: options.defaultModel,
17890
+ text: chunk.text
17891
+ }, "chunk");
17892
+ const normalizedVariants = chunk.embeddingVariants ? await Promise.all(chunk.embeddingVariants.map(async (variant) => {
17893
+ const embedding = variant.embedding ? (validateRAGEmbeddingDimensions(variant.embedding, getExpectedDimensions(), "chunk"), variant.embedding) : await embed({
17513
17894
  model: options.defaultModel,
17514
- text: chunk.text
17515
- }, "chunk")
17516
- };
17517
- }));
17895
+ text: variant.text ?? chunk.text
17896
+ }, "chunk");
17897
+ return {
17898
+ ...variant,
17899
+ embedding
17900
+ };
17901
+ })) : undefined;
17902
+ return expandChunkForMultivectorStorage({
17903
+ ...chunk,
17904
+ embedding: normalizedEmbedding,
17905
+ embeddingVariants: normalizedVariants,
17906
+ metadata: {
17907
+ ...chunk.metadata ?? {},
17908
+ [MULTIVECTOR_PRIMARY]: true
17909
+ }
17910
+ });
17911
+ }))).flat();
17518
17912
  await options.store.upsert({ chunks });
17519
17913
  };
17520
17914
  return {
@@ -17723,11 +18117,25 @@ var renderMaintenancePanel = (input) => {
17723
18117
  const route = input.path ? `${input.path}/status/maintenance` : undefined;
17724
18118
  return route ? `<div id="rag-status-maintenance-panel" hx-get="${escapeHtml2(route)}" hx-trigger="load, rag:mutated from:body" hx-swap="outerHTML">${content}</div>` : `<div id="rag-status-maintenance-panel">${content}</div>`;
17725
18119
  };
18120
+ var renderRetrievalGovernancePanel = (retrievalComparisons) => {
18121
+ if (!retrievalComparisons?.latest && !retrievalComparisons?.alerts?.length) {
18122
+ return "";
18123
+ }
18124
+ const latest = retrievalComparisons.latest;
18125
+ const alerts = (retrievalComparisons.alerts ?? []).slice(0, 3);
18126
+ const releaseGroups = (retrievalComparisons.releaseGroups ?? []).slice(0, 2);
18127
+ const formatClassification = (classification) => classification === "multivector" ? "multivector regression" : classification === "general" ? "general regression" : undefined;
18128
+ return `<section class="rag-status-governance"><h3>Retrieval governance</h3>` + (latest ? `<dl class="rag-status">` + `<div><dt>Latest comparison</dt><dd>${escapeHtml2(latest.label)}</dd></div>` + (latest.bestByPassingRate ? `<div><dt>Best passing rate</dt><dd>${escapeHtml2(latest.bestByPassingRate)}</dd></div>` : "") + (latest.bestByAverageF1 ? `<div><dt>Best average F1</dt><dd>${escapeHtml2(latest.bestByAverageF1)}</dd></div>` : "") + (latest.bestByMultivectorCollapsedCases ? `<div><dt>Best multivector collapse</dt><dd>${escapeHtml2(latest.bestByMultivectorCollapsedCases)}</dd></div>` : "") + (latest.bestByMultivectorLexicalHitCases ? `<div><dt>Best multivector lexical hits</dt><dd>${escapeHtml2(latest.bestByMultivectorLexicalHitCases)}</dd></div>` : "") + (latest.bestByMultivectorVectorHitCases ? `<div><dt>Best multivector vector hits</dt><dd>${escapeHtml2(latest.bestByMultivectorVectorHitCases)}</dd></div>` : "") + (latest.decisionSummary?.gate?.status ? `<div><dt>Gate</dt><dd>${escapeHtml2(latest.decisionSummary.gate.status)}</dd></div>` : "") + (latest.releaseVerdict?.status ? `<div><dt>Verdict</dt><dd>${escapeHtml2(latest.releaseVerdict.status)}</dd></div>` : "") + `</dl>` : "") + `<h4>Active alerts</h4>` + (alerts.length > 0 ? `<ul class="rag-status-capabilities">${alerts.map((alert) => `<li><strong>${escapeHtml2(alert.kind)}</strong>${formatClassification(alert.classification) ? ` <span>${escapeHtml2(formatClassification(alert.classification) ?? "")}</span>` : ""} ${escapeHtml2(alert.message)}</li>`).join("")}</ul>` : `<p class="rag-empty">No active retrieval comparison alerts.</p>`) + (releaseGroups.length > 0 ? `<h4>Release groups</h4><ul class="rag-status-capabilities">${releaseGroups.map((group) => {
18129
+ const reasons = group.recommendedActionReasons?.slice(0, 2).join("; ") ?? "No recommended action.";
18130
+ return `<li><strong>${escapeHtml2(group.groupKey)}</strong>${formatClassification(group.classification) ? ` <span>${escapeHtml2(formatClassification(group.classification) ?? "")}</span>` : ""} ${escapeHtml2(group.recommendedAction ?? "monitor")} \xB7 ${escapeHtml2(reasons)}</li>`;
18131
+ }).join("")}</ul>` : "") + `</section>`;
18132
+ };
17726
18133
  var defaultStatus = ({
17727
18134
  admin,
17728
18135
  adminActions,
17729
18136
  adminJobs,
17730
18137
  maintenance,
18138
+ retrievalComparisons,
17731
18139
  path,
17732
18140
  status,
17733
18141
  capabilities,
@@ -17736,7 +18144,7 @@ var defaultStatus = ({
17736
18144
  if (!status) {
17737
18145
  return renderEmptyState("status");
17738
18146
  }
17739
- return `<section class="rag-status-panel">` + `<dl class="rag-status">` + `<div><dt>Backend</dt><dd>${escapeHtml2(status.backend)}</dd></div>` + `<div><dt>Vector mode</dt><dd>${escapeHtml2(status.vectorMode)}</dd></div>` + `<div><dt>Embedding dimensions</dt><dd>${status.dimensions ?? "n/a"}</dd></div>` + `<div><dt>Vector acceleration</dt><dd>${status.native?.active ? "active" : "inactive"}</dd></div>` + `<div><dt>Documents</dt><dd>${documents?.total ?? "n/a"}</dd></div>` + `<div><dt>Total chunks</dt><dd>${documents?.chunkCount ?? "n/a"}</dd></div>` + `<div><dt>Seed docs</dt><dd>${documents?.byKind.seed ?? 0}</dd></div>` + `<div><dt>Custom docs</dt><dd>${documents?.byKind.custom ?? 0}</dd></div>` + `</dl>${renderPostgresNativeStatus(status)}${renderSQLiteNativeStatus(status)}${renderMaintenancePanel({
18147
+ return `<section class="rag-status-panel">` + `<dl class="rag-status">` + `<div><dt>Backend</dt><dd>${escapeHtml2(status.backend)}</dd></div>` + `<div><dt>Vector mode</dt><dd>${escapeHtml2(status.vectorMode)}</dd></div>` + `<div><dt>Embedding dimensions</dt><dd>${status.dimensions ?? "n/a"}</dd></div>` + `<div><dt>Vector acceleration</dt><dd>${status.native?.active ? "active" : "inactive"}</dd></div>` + `<div><dt>Documents</dt><dd>${documents?.total ?? "n/a"}</dd></div>` + `<div><dt>Total chunks</dt><dd>${documents?.chunkCount ?? "n/a"}</dd></div>` + `<div><dt>Seed docs</dt><dd>${documents?.byKind.seed ?? 0}</dd></div>` + `<div><dt>Custom docs</dt><dd>${documents?.byKind.custom ?? 0}</dd></div>` + `</dl>${renderPostgresNativeStatus(status)}${renderSQLiteNativeStatus(status)}${renderRetrievalGovernancePanel(retrievalComparisons)}${renderMaintenancePanel({
17740
18148
  admin,
17741
18149
  adminActions,
17742
18150
  adminJobs,
@@ -18233,6 +18641,20 @@ var parseRAGRetrieval = (value) => {
18233
18641
  return retrieval;
18234
18642
  };
18235
18643
  var getNumericStatus = (status) => typeof status === "number" ? status : HTTP_STATUS_OK;
18644
+ var classifyGovernanceReasons = (reasons) => (reasons ?? []).some((reason) => reason.toLowerCase().includes("multivector")) ? "multivector" : "general";
18645
+ var buildRegressionRemediationLabel = (classification) => classification === "multivector" ? "Inspect multivector coverage deltas, variant-hit traces, and collapsed-parent recovery before promotion." : "Inspect the latest retrieval comparison deltas and resolve the gate failure before promotion.";
18646
+ var summarizeIncidentClassifications = (incidents) => {
18647
+ const allIncidents = incidents ?? [];
18648
+ const countBy = (status, classification) => allIncidents.filter((entry) => entry.status === status && (entry.classification ?? "general") === classification).length;
18649
+ return {
18650
+ openGeneralCount: countBy("open", "general"),
18651
+ openMultiVectorCount: countBy("open", "multivector"),
18652
+ resolvedGeneralCount: countBy("resolved", "general"),
18653
+ resolvedMultiVectorCount: countBy("resolved", "multivector"),
18654
+ totalGeneralCount: allIncidents.filter((entry) => (entry.classification ?? "general") === "general").length,
18655
+ totalMultiVectorCount: allIncidents.filter((entry) => (entry.classification ?? "general") === "multivector").length
18656
+ };
18657
+ };
18236
18658
  var getBooleanProperty = (value, key) => {
18237
18659
  if (!isObjectRecord2(value)) {
18238
18660
  return;
@@ -19944,6 +20366,7 @@ var ragChat = (config) => {
19944
20366
  return existing.find((entry) => entry.groupKey === groupKey && typeof entry.corpusGroupKey === "string")?.corpusGroupKey ?? comparisonRunCorpusGroups.find((entry) => entry.groupKey === groupKey && typeof entry.corpusGroupKey === "string")?.corpusGroupKey ?? baselineCorpusGroups.find((entry) => entry.groupKey === groupKey && typeof entry.corpusGroupKey === "string")?.corpusGroupKey ?? releaseDecisionCorpusGroups.find((entry) => entry.groupKey === groupKey && typeof entry.corpusGroupKey === "string")?.corpusGroupKey;
19945
20367
  };
19946
20368
  const nextByKey = new Map;
20369
+ const classifyPromotionIncident = (reasons) => (reasons ?? []).some((reason) => reason.toLowerCase().includes("multivector")) ? "multivector" : "general";
19947
20370
  for (const candidate of input.promotionCandidates) {
19948
20371
  if (!candidate.groupKey || !candidate.targetRolloutLabel) {
19949
20372
  continue;
@@ -19961,6 +20384,7 @@ var ragChat = (config) => {
19961
20384
  id: key,
19962
20385
  kind,
19963
20386
  message: candidate.reasons[0] ?? candidate.sortReason ?? "release action required",
20387
+ classification: classifyPromotionIncident(candidate.reasons),
19964
20388
  severity: getRetrievalReleaseIncidentSeverity(candidate.targetRolloutLabel),
19965
20389
  sourceRunId: candidate.sourceRunId,
19966
20390
  status: "open",
@@ -20135,7 +20559,7 @@ var ragChat = (config) => {
20135
20559
  actions.add("Renew or record the required approval for this rollout lane.");
20136
20560
  }
20137
20561
  if (reason.includes("gate") || reason.includes("passing rate") || reason.includes("average")) {
20138
- actions.add("Inspect the latest retrieval comparison deltas and resolve the gate failure before promotion.");
20562
+ actions.add(buildRegressionRemediationLabel(classifyGovernanceReasons([reason])));
20139
20563
  }
20140
20564
  if (reason.includes("source comparison run was not found")) {
20141
20565
  actions.add("Re-run the comparison so the rollout action has a valid source run.");
@@ -20168,7 +20592,7 @@ var ragChat = (config) => {
20168
20592
  if (reason.includes("gate") || reason.includes("passing rate") || reason.includes("average")) {
20169
20593
  steps.push({
20170
20594
  kind: "inspect_gate",
20171
- label: "Inspect the latest retrieval comparison deltas and resolve the gate failure before promotion.",
20595
+ label: buildRegressionRemediationLabel(classifyGovernanceReasons([reason])),
20172
20596
  actions: buildRemediationStepActions({
20173
20597
  candidateRetrievalId: input.retrievalId,
20174
20598
  groupKey: input.groupKey,
@@ -20225,6 +20649,7 @@ var ragChat = (config) => {
20225
20649
  const base = {
20226
20650
  baselineRetrievalId,
20227
20651
  candidateRetrievalId: input.retrievalId,
20652
+ classification: input.baseline ? "general" : undefined,
20228
20653
  effectiveBaselineGatePolicy: targetRolloutLabel || input.groupKey ? getDefaultRetrievalBaselineGatePolicy(input.groupKey, targetRolloutLabel) : undefined,
20229
20654
  effectiveReleasePolicy: getRetrievalReleasePolicy(input.groupKey, targetRolloutLabel),
20230
20655
  groupKey: input.groupKey,
@@ -20281,6 +20706,7 @@ var ragChat = (config) => {
20281
20706
  if (!sourceRun) {
20282
20707
  return {
20283
20708
  ...base,
20709
+ classification: "general",
20284
20710
  reasons: [
20285
20711
  "source comparison run was not found for this rollout action"
20286
20712
  ],
@@ -20316,6 +20742,7 @@ var ragChat = (config) => {
20316
20742
  return {
20317
20743
  baselineRetrievalId: state.baselineRetrievalId ?? baselineRetrievalId,
20318
20744
  candidateRetrievalId: state.candidateRetrievalId ?? input.retrievalId,
20745
+ classification: classifyGovernanceReasons(state.reasons),
20319
20746
  effectiveBaselineGatePolicy: state.effectiveBaselineGatePolicy,
20320
20747
  effectiveReleasePolicy: state.effectiveReleasePolicy,
20321
20748
  gateStatus: state.gateStatus,
@@ -21775,13 +22202,15 @@ var ragChat = (config) => {
21775
22202
  };
21776
22203
  const handleRetrievalReleaseIncidentStatus = async (request) => {
21777
22204
  const ops = await buildOperationsPayload(request);
22205
+ const recentIncidents = ops.retrievalComparisons?.recentIncidents;
21778
22206
  return {
22207
+ incidentClassificationSummary: summarizeIncidentClassifications(recentIncidents),
21779
22208
  incidentRemediationExecutionSummary: ops.retrievalComparisons?.incidentRemediationExecutionSummary,
21780
22209
  incidentSummary: ops.retrievalComparisons?.incidentSummary,
21781
22210
  ok: true,
21782
22211
  recentIncidentRemediationDecisions: ops.retrievalComparisons?.recentIncidentRemediationDecisions,
21783
22212
  recentIncidentRemediationExecutions: ops.retrievalComparisons?.recentIncidentRemediationExecutions,
21784
- recentIncidents: ops.retrievalComparisons?.recentIncidents,
22213
+ recentIncidents,
21785
22214
  recentReleaseLaneEscalationPolicyHistory: ops.retrievalComparisons?.recentReleaseLaneEscalationPolicyHistory,
21786
22215
  releaseLaneIncidentSummaries: ops.retrievalComparisons?.releaseLaneIncidentSummaries
21787
22216
  };
@@ -21811,6 +22240,7 @@ var ragChat = (config) => {
21811
22240
  const handleRetrievalIncidentRemediationStatus = async (request) => {
21812
22241
  const ops = await buildOperationsPayload(request);
21813
22242
  return {
22243
+ incidentClassificationSummary: summarizeIncidentClassifications(ops.retrievalComparisons?.recentIncidents),
21814
22244
  incidentRemediationExecutionSummary: ops.retrievalComparisons?.incidentRemediationExecutionSummary,
21815
22245
  ok: true,
21816
22246
  recentIncidentRemediationExecutions: ops.retrievalComparisons?.recentIncidentRemediationExecutions
@@ -23037,8 +23467,9 @@ var ragChat = (config) => {
23037
23467
  ];
23038
23468
  const recommendedActionReasons = (() => {
23039
23469
  if (groupCandidates.some((entry) => entry.priority === "gate_fail")) {
23470
+ const gateFailReason = groupCandidates.find((entry) => entry.priority === "gate_fail" && entry.reasons[0])?.reasons[0];
23040
23471
  return [
23041
- "candidate regressed or failed the active gate and should be investigated"
23472
+ gateFailReason ?? "candidate regressed or failed the active gate and should be investigated"
23042
23473
  ];
23043
23474
  }
23044
23475
  if (groupCandidates.some((entry) => entry.reviewStatus === "needs_review")) {
@@ -23056,6 +23487,11 @@ var ragChat = (config) => {
23056
23487
  }
23057
23488
  return ["continue monitoring release state"];
23058
23489
  })();
23490
+ const classification = classifyGovernanceReasons([
23491
+ ...blockedReasons,
23492
+ ...actionRequiredReasons,
23493
+ ...recommendedActionReasons
23494
+ ]);
23059
23495
  const recommendedAction = groupCandidates.some((entry) => entry.priority === "gate_fail") ? "investigate_regression" : groupCandidates.some((entry) => entry.reviewStatus === "needs_review") ? "renew_approval" : groupCandidates.some((entry) => entry.requiresApproval && entry.approved !== true && entry.reviewStatus === "blocked") ? "await_approval" : groupCandidates.some((entry) => entry.ready) ? "promote_candidate" : "monitor";
23060
23496
  const escalationSeverity = groupCandidates.some((entry) => entry.priority === "gate_fail") ? "critical" : groupCandidates.some((entry) => entry.reviewStatus === "needs_review" || entry.priority === "gate_warn") ? "warning" : actionRequiredReasons.length > 0 ? "info" : "none";
23061
23497
  return {
@@ -23068,6 +23504,7 @@ var ragChat = (config) => {
23068
23504
  approvalMaxAgeMs: getRetrievalReleasePolicy(groupKey).approvalMaxAgeMs,
23069
23505
  approvalRequired: getRetrievalReleasePolicy(groupKey).requireApprovalBeforePromotion === true,
23070
23506
  blockedReasons,
23507
+ classification,
23071
23508
  corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
23072
23509
  escalationSeverity,
23073
23510
  groupKey,
@@ -23089,6 +23526,7 @@ var ragChat = (config) => {
23089
23526
  return {
23090
23527
  ...group,
23091
23528
  acknowledgedOpenIncidentCount,
23529
+ classification: groupOpenIncidents.some((entry) => entry.classification === "multivector") ? "multivector" : group.classification,
23092
23530
  openIncidentCount: groupOpenIncidents.length,
23093
23531
  unacknowledgedOpenIncidentCount: groupOpenIncidents.length - acknowledgedOpenIncidentCount
23094
23532
  };
@@ -23296,9 +23734,11 @@ var ragChat = (config) => {
23296
23734
  ] : candidate?.ready ? [
23297
23735
  "latest candidate is ready to promote"
23298
23736
  ] : ["continue monitoring release state"];
23737
+ const classification = candidate?.reasons?.length ? classifyGovernanceReasons(candidate.reasons) : (recentIncidents ?? []).some((entry) => entry.groupKey === group.groupKey && entry.targetRolloutLabel === targetRolloutLabel && entry.classification === "multivector") ? "multivector" : "general";
23299
23738
  summaries.push({
23300
23739
  baselineRetrievalId: candidate?.baselineRetrievalId,
23301
23740
  candidateRetrievalId: candidate?.candidateRetrievalId,
23741
+ classification,
23302
23742
  effectiveBaselineGatePolicy: candidate?.effectiveBaselineGatePolicy,
23303
23743
  effectiveReleasePolicy: candidate?.effectiveReleasePolicy,
23304
23744
  gateStatus: candidate?.gateStatus,
@@ -23306,10 +23746,12 @@ var ragChat = (config) => {
23306
23746
  ready: candidate?.ready ?? false,
23307
23747
  recommendedAction,
23308
23748
  recommendedActionReasons,
23309
- remediationActions: [...recommendedActionReasons],
23749
+ remediationActions: recommendedAction === "investigate_regression" ? [
23750
+ buildRegressionRemediationLabel(classification)
23751
+ ] : [...recommendedActionReasons],
23310
23752
  remediationSteps: recommendedActionReasons.map((label) => ({
23311
23753
  kind: recommendedAction === "renew_approval" ? "renew_approval" : recommendedAction === "await_approval" ? "record_approval" : recommendedAction === "investigate_regression" ? "inspect_gate" : recommendedAction === "promote_candidate" ? "monitor_lane" : "review_readiness",
23312
- label,
23754
+ label: recommendedAction === "investigate_regression" ? buildRegressionRemediationLabel(classification) : label,
23313
23755
  actions: buildRemediationStepActions({
23314
23756
  candidateRetrievalId: candidate?.candidateRetrievalId,
23315
23757
  groupKey: group.groupKey,
@@ -23752,6 +24194,7 @@ var ragChat = (config) => {
23752
24194
  if (!latestRetrievalComparisonRun) {
23753
24195
  return alerts;
23754
24196
  }
24197
+ const classifyRetrievalRegression = (input) => (input.reasons ?? []).some((reason) => reason.toLowerCase().includes("multivector")) || typeof input.delta?.multiVectorCollapsedCasesDelta === "number" || typeof input.delta?.multiVectorLexicalHitCasesDelta === "number" || typeof input.delta?.multiVectorVectorHitCasesDelta === "number" ? "multivector" : "general";
23755
24198
  const latestWinner = latestRetrievalComparisonRun.comparison.summary.bestByPassingRate;
23756
24199
  if (latestWinner && stableWinnerByPassingRate?.retrievalId && stableWinnerByPassingRate.retrievalId !== latestWinner) {
23757
24200
  alerts.push({
@@ -23777,11 +24220,13 @@ var ragChat = (config) => {
23777
24220
  kind: "baseline_regression",
23778
24221
  latestRunId: latestRetrievalComparisonRun.id,
23779
24222
  message: "Candidate retrieval regressed against the baseline on the latest persisted comparison run.",
24223
+ classification: classifyRetrievalRegression({ delta }),
23780
24224
  severity: "warning",
23781
24225
  tag: latestRetrievalComparisonRun.tags?.[0]
23782
24226
  });
23783
24227
  }
23784
24228
  if (gate && gate.status !== "pass") {
24229
+ const gateReasonText = gate.reasons.length > 0 ? ` ${gate.reasons.join("; ")}` : "";
23785
24230
  alerts.push({
23786
24231
  baselineRetrievalId: latestRetrievalComparisonRun.decisionSummary?.baselineRetrievalId,
23787
24232
  candidateRetrievalId: latestRetrievalComparisonRun.decisionSummary?.candidateRetrievalId,
@@ -23791,7 +24236,11 @@ var ragChat = (config) => {
23791
24236
  groupKey: latestRetrievalComparisonRun.groupKey,
23792
24237
  kind: "baseline_gate_failed",
23793
24238
  latestRunId: latestRetrievalComparisonRun.id,
23794
- message: gate.status === "warn" ? "Candidate retrieval triggered a baseline gate warning." : "Candidate retrieval failed the active baseline gate.",
24239
+ message: gate.status === "warn" ? `Candidate retrieval triggered a baseline gate warning.${gateReasonText}` : `Candidate retrieval failed the active baseline gate.${gateReasonText}`,
24240
+ classification: classifyRetrievalRegression({
24241
+ delta,
24242
+ reasons: gate.reasons
24243
+ }),
23795
24244
  severity: gate.status === "warn" ? "warning" : "warning",
23796
24245
  tag: latestRetrievalComparisonRun.tags?.[0]
23797
24246
  });
@@ -23925,6 +24374,9 @@ var ragChat = (config) => {
23925
24374
  configured: Boolean(retrievalComparisonHistoryStore),
23926
24375
  latest: latestRetrievalComparisonRun ? {
23927
24376
  bestByAverageF1: latestRetrievalComparisonRun.comparison.summary.bestByAverageF1,
24377
+ bestByMultivectorCollapsedCases: latestRetrievalComparisonRun.comparison.summary.bestByMultivectorCollapsedCases,
24378
+ bestByMultivectorLexicalHitCases: latestRetrievalComparisonRun.comparison.summary.bestByMultivectorLexicalHitCases,
24379
+ bestByMultivectorVectorHitCases: latestRetrievalComparisonRun.comparison.summary.bestByMultivectorVectorHitCases,
23928
24380
  bestByPassingRate: latestRetrievalComparisonRun.comparison.summary.bestByPassingRate,
23929
24381
  corpusGroupKey: latestRetrievalComparisonRun.corpusGroupKey,
23930
24382
  elapsedMs: latestRetrievalComparisonRun.elapsedMs,
@@ -25437,6 +25889,7 @@ var ragChat = (config) => {
25437
25889
  capabilities: result.capabilities,
25438
25890
  documents: result.documents,
25439
25891
  maintenance: result.maintenance,
25892
+ retrievalComparisons: result.retrievalComparisons,
25440
25893
  path,
25441
25894
  status: result.status
25442
25895
  }));
@@ -25545,6 +25998,7 @@ var ragChat = (config) => {
25545
25998
  capabilities: result.capabilities,
25546
25999
  documents: result.documents,
25547
26000
  maintenance: result.maintenance,
26001
+ retrievalComparisons: result.retrievalComparisons,
25548
26002
  path,
25549
26003
  status: result.status
25550
26004
  }));
@@ -25919,6 +26373,28 @@ var createRAGHTMXWorkflowRenderConfig = (config) => config;
25919
26373
  // src/ai/rag/retrievalStrategies.ts
25920
26374
  var tokenize4 = (value) => value.toLowerCase().split(/[^a-z0-9]+/i).map((token) => token.trim()).filter((token) => token.length > 0);
25921
26375
  var hasAnyToken2 = (tokens, values) => values.some((value) => tokens.includes(value));
26376
+ var buildSelectorMetadata = (selector, extra = {}) => ({
26377
+ selector,
26378
+ ...extra
26379
+ });
26380
+ var countLongTokens = (tokens) => tokens.filter((token) => token.length >= 5).length;
26381
+ var hasExactPhraseIntent = (tokens) => {
26382
+ const exactPhraseCue = hasAnyToken2(tokens, [
26383
+ "phrase",
26384
+ "phrasing",
26385
+ "wording",
26386
+ "verbatim",
26387
+ "quoted",
26388
+ "quote",
26389
+ "snippet",
26390
+ "precise",
26391
+ "exact"
26392
+ ]);
26393
+ if (!exactPhraseCue) {
26394
+ return false;
26395
+ }
26396
+ return tokens.length >= 6 || countLongTokens(tokens) >= 4;
26397
+ };
25922
26398
  var createHeuristicRAGRetrievalStrategy = (options = {}) => ({
25923
26399
  defaultLabel: options.defaultLabel ?? "Heuristic retrieval routing",
25924
26400
  providerName: options.providerName ?? "heuristic_retrieval_strategy",
@@ -25930,24 +26406,32 @@ var createHeuristicRAGRetrievalStrategy = (options = {}) => ({
25930
26406
  label: "Scoped direct route",
25931
26407
  mode: "vector",
25932
26408
  reason: scopedDocumentId ? "documentId filter narrows retrieval to one target document" : "source filter narrows retrieval to one source family",
25933
- metadata: {
25934
- selector: "scoped_direct_route"
25935
- }
26409
+ metadata: buildSelectorMetadata("scoped_direct_route")
25936
26410
  };
25937
26411
  }
25938
26412
  const tokens = tokenize4(input.query);
25939
26413
  const transformedTokens = tokenize4(input.transformedQuery);
25940
26414
  const combined = Array.from(new Set([...tokens, ...transformedTokens]));
25941
26415
  const hasVariants = input.variantQueries.length > 0;
26416
+ const exactPhraseHybrid = !hasVariants && hasExactPhraseIntent(combined);
25942
26417
  const supportLexical = hasAnyToken2(combined, ["faq", "policy", "password", "billing"]) && !hasVariants;
25943
26418
  if (supportLexical) {
25944
26419
  return {
25945
26420
  label: "Support lexical route",
25946
26421
  mode: "lexical",
25947
26422
  reason: "faq/support phrase matched",
25948
- metadata: {
25949
- selector: "support_lexical"
25950
- }
26423
+ metadata: buildSelectorMetadata("support_lexical")
26424
+ };
26425
+ }
26426
+ if (exactPhraseHybrid && input.retrieval.mode === "vector") {
26427
+ return {
26428
+ label: "Exact phrase hybrid route",
26429
+ mode: "hybrid",
26430
+ lexicalTopK: Math.max(input.topK, Math.floor(input.retrieval.lexicalTopK ?? input.candidateTopK)),
26431
+ reason: "exact sub-span wording benefits from lexical evidence",
26432
+ metadata: buildSelectorMetadata("exact_phrase_hybrid", {
26433
+ exactPhraseIntent: true
26434
+ })
25951
26435
  };
25952
26436
  }
25953
26437
  const sourceNativeHybrid = hasVariants || hasAnyToken2(combined, [
@@ -25966,9 +26450,7 @@ var createHeuristicRAGRetrievalStrategy = (options = {}) => ({
25966
26450
  mode: "hybrid",
25967
26451
  lexicalTopK: Math.max(input.topK, Math.floor(input.retrieval.lexicalTopK ?? input.candidateTopK)),
25968
26452
  reason: hasVariants ? "query expansion introduced source-native variants" : "source-native terminology benefits from hybrid retrieval",
25969
- metadata: {
25970
- selector: "source_native_hybrid"
25971
- }
26453
+ metadata: buildSelectorMetadata("source_native_hybrid")
25972
26454
  };
25973
26455
  }
25974
26456
  return;
@@ -33909,5 +34391,5 @@ export {
33909
34391
  addRAGEvaluationSuiteCase
33910
34392
  };
33911
34393
 
33912
- //# debugId=27461AB67370F55164756E2164756E21
34394
+ //# debugId=E1F755AF5BA36E2664756E2164756E21
33913
34395
  //# sourceMappingURL=index.js.map