@remnic/core 10.0.17 → 10.0.19

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.
Files changed (203) hide show
  1. package/dist/access-admin-ops-surface.js +15 -15
  2. package/dist/access-authorization-probe.js +16 -16
  3. package/dist/access-boundary.js +15 -15
  4. package/dist/access-cli.js +56 -56
  5. package/dist/access-extraction-force-flush.js +15 -15
  6. package/dist/access-http-briefing.js +16 -16
  7. package/dist/access-http-query.js +17 -17
  8. package/dist/access-http.js +32 -32
  9. package/dist/access-identity-continuity-surface.js +15 -15
  10. package/dist/access-lcm-surface.js +15 -15
  11. package/dist/access-mcp.js +25 -25
  12. package/dist/access-namespace-preflight.js +15 -15
  13. package/dist/access-observe-write-surface.js +15 -15
  14. package/dist/access-operations-batch.js +16 -16
  15. package/dist/access-operations.js +23 -23
  16. package/dist/access-recall-concurrency.js +15 -15
  17. package/dist/access-recall-diagnostics.js +2 -2
  18. package/dist/access-recall-response.js +15 -15
  19. package/dist/access-recall-surface.js +15 -15
  20. package/dist/access-service.js +15 -15
  21. package/dist/access-surface-catalog.js +17 -17
  22. package/dist/active-recall.js +2 -2
  23. package/dist/briefing.js +3 -3
  24. package/dist/causal-consolidation.js +4 -4
  25. package/dist/{chunk-2PYHLSXK.js → chunk-2C5YAVHA.js} +2 -2
  26. package/dist/{chunk-GWVNGDJW.js → chunk-2I3OREMR.js} +2 -2
  27. package/dist/{chunk-GCVDFX66.js → chunk-2JGBX5XY.js} +2 -2
  28. package/dist/{chunk-PEF5LHQU.js → chunk-32FVH5OQ.js} +5 -5
  29. package/dist/{chunk-XYGQSDTH.js → chunk-3K6J5GO5.js} +3 -3
  30. package/dist/{chunk-3MO4LWYU.js → chunk-466EGMFQ.js} +1 -1
  31. package/dist/{chunk-3MO4LWYU.js.map → chunk-466EGMFQ.js.map} +1 -1
  32. package/dist/{chunk-HQSK2INQ.js → chunk-4OEBL5T3.js} +2 -2
  33. package/dist/{chunk-IJMDBYCO.js → chunk-5JXNXKKV.js} +2 -2
  34. package/dist/{chunk-CQOIWJ5E.js → chunk-5NO42IYF.js} +3 -3
  35. package/dist/{chunk-NHUX6GXA.js → chunk-62CRBI5B.js} +2 -2
  36. package/dist/{chunk-5ATSXCAG.js → chunk-6VWCL2IZ.js} +3 -3
  37. package/dist/{chunk-CXOYUANR.js → chunk-7UHCV5B3.js} +2 -2
  38. package/dist/{chunk-BK2BVLZW.js → chunk-A2IJEV5L.js} +2 -2
  39. package/dist/{chunk-EH4BQ7LT.js → chunk-AAQ77A44.js} +2 -2
  40. package/dist/{chunk-R2H4ZFBJ.js → chunk-BI3CIDIH.js} +3 -3
  41. package/dist/{chunk-GFWRXPF6.js → chunk-CA2R2AD4.js} +12 -12
  42. package/dist/{chunk-4SCZZ3U7.js → chunk-D42L5SQF.js} +2 -2
  43. package/dist/{chunk-C6JMGAMO.js → chunk-DJMGVSST.js} +2 -2
  44. package/dist/{chunk-H5IUN433.js → chunk-EML6HJE6.js} +2 -2
  45. package/dist/{chunk-ZZTOURJI.js → chunk-EVWDNKQA.js} +13 -4
  46. package/dist/chunk-EVWDNKQA.js.map +1 -0
  47. package/dist/{chunk-MJIOGYKX.js → chunk-FBNL4BYD.js} +2 -2
  48. package/dist/{chunk-5KGYTX5O.js → chunk-GXVLEXIX.js} +2 -2
  49. package/dist/{chunk-6YEPGWUP.js → chunk-HVIXRLXJ.js} +2 -2
  50. package/dist/{chunk-AZDTDWS2.js → chunk-IBGRIAE5.js} +2 -2
  51. package/dist/{chunk-YDBIWGNI.js → chunk-IIK2PD3F.js} +8 -2
  52. package/dist/{chunk-YDBIWGNI.js.map → chunk-IIK2PD3F.js.map} +1 -1
  53. package/dist/{chunk-YR4COAEC.js → chunk-INBB7D3V.js} +2 -2
  54. package/dist/{chunk-VW6VIJOS.js → chunk-IVUCF3QO.js} +2 -2
  55. package/dist/{chunk-UGYUBENJ.js → chunk-LDZD3OQG.js} +2 -2
  56. package/dist/{chunk-VNZMZPAC.js → chunk-LT4SMGE4.js} +2 -2
  57. package/dist/{chunk-7VQ6AI7H.js → chunk-N36PBG4A.js} +2 -2
  58. package/dist/{chunk-G3UUAQOD.js → chunk-NFB5QTOH.js} +2 -2
  59. package/dist/{chunk-F2772ATT.js → chunk-NIS3FOMD.js} +2 -2
  60. package/dist/{chunk-4PDTVVSW.js → chunk-O6ADSFGY.js} +2 -2
  61. package/dist/{chunk-MAVYEZKM.js → chunk-OFQOOLQQ.js} +2 -2
  62. package/dist/{chunk-O2YPCFJT.js → chunk-OPNSIFFU.js} +7 -7
  63. package/dist/{chunk-W3FVQBGF.js → chunk-PDFAX4PK.js} +2 -2
  64. package/dist/{chunk-NAGMQXWV.js → chunk-QC5TJUSP.js} +2 -2
  65. package/dist/{chunk-2PTH4PRL.js → chunk-QZ7WOCME.js} +2 -2
  66. package/dist/{chunk-5MLGY6IY.js → chunk-RQMSD4CN.js} +56 -35
  67. package/dist/chunk-RQMSD4CN.js.map +1 -0
  68. package/dist/{chunk-TN4EA4X4.js → chunk-RTV3DB4I.js} +2 -2
  69. package/dist/{chunk-NZCKG25S.js → chunk-SSUTJLCF.js} +2 -2
  70. package/dist/{chunk-GUY6L6LL.js → chunk-TXE55Z3X.js} +2 -2
  71. package/dist/{chunk-XKRXN63M.js → chunk-UHBZK3CK.js} +2 -2
  72. package/dist/{chunk-PRU7OF3Y.js → chunk-UXXLP2PD.js} +3 -3
  73. package/dist/{chunk-V3TXIXXY.js → chunk-VOEBHBWG.js} +2 -2
  74. package/dist/{chunk-RI2KCQHP.js → chunk-VUBVNY3W.js} +2 -2
  75. package/dist/{chunk-QSEUUQUF.js → chunk-VVSPHTSU.js} +2 -2
  76. package/dist/{chunk-OXNTOHL6.js → chunk-VYVQZRXF.js} +2 -2
  77. package/dist/{chunk-L6AZOEXV.js → chunk-W3GFSWKE.js} +4 -4
  78. package/dist/{chunk-MXV2MY6C.js → chunk-W7NVMERN.js} +2 -2
  79. package/dist/{chunk-Q7DWEXG2.js → chunk-XKPLERHV.js} +19 -19
  80. package/dist/{chunk-KLJVTZ3R.js → chunk-YRKKW4KT.js} +3 -3
  81. package/dist/{chunk-DQR2LD3V.js → chunk-YW4ZYASS.js} +2 -2
  82. package/dist/{chunk-QS3OLP5I.js → chunk-ZDDDWTC7.js} +2 -2
  83. package/dist/{chunk-JZTEOBOR.js → chunk-ZDUMF4H6.js} +12 -12
  84. package/dist/{chunk-H6FREOYX.js → chunk-ZUCNOTNF.js} +7 -7
  85. package/dist/cli.js +43 -43
  86. package/dist/coding/export-okf-codegraph.js +2 -2
  87. package/dist/compounding/engine.js +4 -4
  88. package/dist/config.js +2 -2
  89. package/dist/connectors/codex-materialize-runner.js +3 -3
  90. package/dist/connectors/index.js +3 -3
  91. package/dist/convergence-refresh.js +5 -5
  92. package/dist/corpus-watermark.js +5 -5
  93. package/dist/entity-retrieval.js +3 -3
  94. package/dist/external-wiki-access.js +16 -16
  95. package/dist/extraction.js +3 -3
  96. package/dist/harmonic-retrieval.js +3 -3
  97. package/dist/index.js +56 -56
  98. package/dist/location/index.js +5 -5
  99. package/dist/maintenance/memory-governance.js +3 -3
  100. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  101. package/dist/maintenance/rebuild-memory-projection-runner.js +5 -5
  102. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  103. package/dist/memory-browse-operations.js +16 -16
  104. package/dist/namespaces/migrate.js +4 -4
  105. package/dist/namespaces/storage.js +3 -3
  106. package/dist/operator-doctor-corpus.js +6 -6
  107. package/dist/operator-toolkit.js +11 -11
  108. package/dist/orchestration/maintenance.js +13 -13
  109. package/dist/orchestration/recall-rerank-coordinator.d.ts.map +1 -1
  110. package/dist/orchestrator.js +56 -56
  111. package/dist/preferences/drift-recall.d.ts.map +1 -1
  112. package/dist/reasoning-trace-recall.d.ts +2 -0
  113. package/dist/reasoning-trace-recall.d.ts.map +1 -1
  114. package/dist/reasoning-trace-recall.js +1 -1
  115. package/dist/recall-explain-renderer.js +3 -3
  116. package/dist/recall-mmr.d.ts +5 -0
  117. package/dist/recall-mmr.d.ts.map +1 -1
  118. package/dist/recall-mmr.js +1 -1
  119. package/dist/recall-navigate-access.js +2 -2
  120. package/dist/recall-navigate-disclosure.js +2 -2
  121. package/dist/recall-navigate.js +2 -2
  122. package/dist/recall-navigation-operations.js +16 -16
  123. package/dist/recall-navigation.js +15 -15
  124. package/dist/recall-xray-cli.js +4 -4
  125. package/dist/recall-xray-renderer.js +3 -3
  126. package/dist/recall-xray.js +2 -2
  127. package/dist/resume-bundles.js +2 -2
  128. package/dist/semantic-consolidation.js +4 -4
  129. package/dist/semantic-rule-promotion.js +3 -3
  130. package/dist/semantic-rule-verifier.js +3 -3
  131. package/dist/source-agent-qualifier.js +3 -3
  132. package/dist/standup/build.js +3 -3
  133. package/dist/storage.js +2 -2
  134. package/dist/support-passport/index.js +18 -18
  135. package/dist/transfer/export-okf.js +3 -3
  136. package/dist/types.d.ts +5 -0
  137. package/dist/types.d.ts.map +1 -1
  138. package/dist/types.js +1 -1
  139. package/dist/verified-recall.js +3 -3
  140. package/dist/who-knows-cli.js +4 -4
  141. package/dist/who-knows.js +3 -3
  142. package/package.json +2 -2
  143. package/src/orchestration/recall-rerank-coordinator.ts +46 -14
  144. package/src/preferences/drift-recall.ts +14 -8
  145. package/src/preferences/preference-drift.test.ts +15 -0
  146. package/src/reasoning-trace-recall.ts +33 -8
  147. package/src/recall-mmr.ts +17 -1
  148. package/src/recall-rerank-coordinator.test.ts +275 -0
  149. package/src/types.ts +5 -0
  150. package/dist/chunk-5MLGY6IY.js.map +0 -1
  151. package/dist/chunk-ZZTOURJI.js.map +0 -1
  152. /package/dist/{chunk-2PYHLSXK.js.map → chunk-2C5YAVHA.js.map} +0 -0
  153. /package/dist/{chunk-GWVNGDJW.js.map → chunk-2I3OREMR.js.map} +0 -0
  154. /package/dist/{chunk-GCVDFX66.js.map → chunk-2JGBX5XY.js.map} +0 -0
  155. /package/dist/{chunk-PEF5LHQU.js.map → chunk-32FVH5OQ.js.map} +0 -0
  156. /package/dist/{chunk-XYGQSDTH.js.map → chunk-3K6J5GO5.js.map} +0 -0
  157. /package/dist/{chunk-HQSK2INQ.js.map → chunk-4OEBL5T3.js.map} +0 -0
  158. /package/dist/{chunk-IJMDBYCO.js.map → chunk-5JXNXKKV.js.map} +0 -0
  159. /package/dist/{chunk-CQOIWJ5E.js.map → chunk-5NO42IYF.js.map} +0 -0
  160. /package/dist/{chunk-NHUX6GXA.js.map → chunk-62CRBI5B.js.map} +0 -0
  161. /package/dist/{chunk-5ATSXCAG.js.map → chunk-6VWCL2IZ.js.map} +0 -0
  162. /package/dist/{chunk-CXOYUANR.js.map → chunk-7UHCV5B3.js.map} +0 -0
  163. /package/dist/{chunk-BK2BVLZW.js.map → chunk-A2IJEV5L.js.map} +0 -0
  164. /package/dist/{chunk-EH4BQ7LT.js.map → chunk-AAQ77A44.js.map} +0 -0
  165. /package/dist/{chunk-R2H4ZFBJ.js.map → chunk-BI3CIDIH.js.map} +0 -0
  166. /package/dist/{chunk-GFWRXPF6.js.map → chunk-CA2R2AD4.js.map} +0 -0
  167. /package/dist/{chunk-4SCZZ3U7.js.map → chunk-D42L5SQF.js.map} +0 -0
  168. /package/dist/{chunk-C6JMGAMO.js.map → chunk-DJMGVSST.js.map} +0 -0
  169. /package/dist/{chunk-H5IUN433.js.map → chunk-EML6HJE6.js.map} +0 -0
  170. /package/dist/{chunk-MJIOGYKX.js.map → chunk-FBNL4BYD.js.map} +0 -0
  171. /package/dist/{chunk-5KGYTX5O.js.map → chunk-GXVLEXIX.js.map} +0 -0
  172. /package/dist/{chunk-6YEPGWUP.js.map → chunk-HVIXRLXJ.js.map} +0 -0
  173. /package/dist/{chunk-AZDTDWS2.js.map → chunk-IBGRIAE5.js.map} +0 -0
  174. /package/dist/{chunk-YR4COAEC.js.map → chunk-INBB7D3V.js.map} +0 -0
  175. /package/dist/{chunk-VW6VIJOS.js.map → chunk-IVUCF3QO.js.map} +0 -0
  176. /package/dist/{chunk-UGYUBENJ.js.map → chunk-LDZD3OQG.js.map} +0 -0
  177. /package/dist/{chunk-VNZMZPAC.js.map → chunk-LT4SMGE4.js.map} +0 -0
  178. /package/dist/{chunk-7VQ6AI7H.js.map → chunk-N36PBG4A.js.map} +0 -0
  179. /package/dist/{chunk-G3UUAQOD.js.map → chunk-NFB5QTOH.js.map} +0 -0
  180. /package/dist/{chunk-F2772ATT.js.map → chunk-NIS3FOMD.js.map} +0 -0
  181. /package/dist/{chunk-4PDTVVSW.js.map → chunk-O6ADSFGY.js.map} +0 -0
  182. /package/dist/{chunk-MAVYEZKM.js.map → chunk-OFQOOLQQ.js.map} +0 -0
  183. /package/dist/{chunk-O2YPCFJT.js.map → chunk-OPNSIFFU.js.map} +0 -0
  184. /package/dist/{chunk-W3FVQBGF.js.map → chunk-PDFAX4PK.js.map} +0 -0
  185. /package/dist/{chunk-NAGMQXWV.js.map → chunk-QC5TJUSP.js.map} +0 -0
  186. /package/dist/{chunk-2PTH4PRL.js.map → chunk-QZ7WOCME.js.map} +0 -0
  187. /package/dist/{chunk-TN4EA4X4.js.map → chunk-RTV3DB4I.js.map} +0 -0
  188. /package/dist/{chunk-NZCKG25S.js.map → chunk-SSUTJLCF.js.map} +0 -0
  189. /package/dist/{chunk-GUY6L6LL.js.map → chunk-TXE55Z3X.js.map} +0 -0
  190. /package/dist/{chunk-XKRXN63M.js.map → chunk-UHBZK3CK.js.map} +0 -0
  191. /package/dist/{chunk-PRU7OF3Y.js.map → chunk-UXXLP2PD.js.map} +0 -0
  192. /package/dist/{chunk-V3TXIXXY.js.map → chunk-VOEBHBWG.js.map} +0 -0
  193. /package/dist/{chunk-RI2KCQHP.js.map → chunk-VUBVNY3W.js.map} +0 -0
  194. /package/dist/{chunk-QSEUUQUF.js.map → chunk-VVSPHTSU.js.map} +0 -0
  195. /package/dist/{chunk-OXNTOHL6.js.map → chunk-VYVQZRXF.js.map} +0 -0
  196. /package/dist/{chunk-L6AZOEXV.js.map → chunk-W3GFSWKE.js.map} +0 -0
  197. /package/dist/{chunk-MXV2MY6C.js.map → chunk-W7NVMERN.js.map} +0 -0
  198. /package/dist/{chunk-Q7DWEXG2.js.map → chunk-XKPLERHV.js.map} +0 -0
  199. /package/dist/{chunk-KLJVTZ3R.js.map → chunk-YRKKW4KT.js.map} +0 -0
  200. /package/dist/{chunk-DQR2LD3V.js.map → chunk-YW4ZYASS.js.map} +0 -0
  201. /package/dist/{chunk-QS3OLP5I.js.map → chunk-ZDDDWTC7.js.map} +0 -0
  202. /package/dist/{chunk-JZTEOBOR.js.map → chunk-ZDUMF4H6.js.map} +0 -0
  203. /package/dist/{chunk-H6FREOYX.js.map → chunk-ZUCNOTNF.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RECALL_DISCLOSURE_LEVELS
3
- } from "./chunk-3MO4LWYU.js";
3
+ } from "./chunk-466EGMFQ.js";
4
4
 
5
5
  // src/recall-navigate.ts
6
6
  var RECALL_NAV_LINK_TYPES = [
@@ -48,4 +48,4 @@ export {
48
48
  expandRecallNode,
49
49
  traverseRecallLink
50
50
  };
51
- //# sourceMappingURL=chunk-HQSK2INQ.js.map
51
+ //# sourceMappingURL=chunk-4OEBL5T3.js.map
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  computeCorpusWatermarks,
6
6
  resolveCorpusNamespaceRoots
7
- } from "./chunk-QSEUUQUF.js";
7
+ } from "./chunk-VVSPHTSU.js";
8
8
 
9
9
  // src/operator-doctor-corpus.ts
10
10
  var DIGEST_PREFIX_LENGTH = 12;
@@ -78,4 +78,4 @@ export {
78
78
  corpusWatermarksFromCheck,
79
79
  summarizeCorpusAndReplica
80
80
  };
81
- //# sourceMappingURL=chunk-IJMDBYCO.js.map
81
+ //# sourceMappingURL=chunk-5JXNXKKV.js.map
@@ -21,13 +21,13 @@ import {
21
21
  defineOperation,
22
22
  parseNamespacePreflightWriteOp,
23
23
  resolveAuthorizedNamespaceWritablePreflight
24
- } from "./chunk-GFWRXPF6.js";
24
+ } from "./chunk-CA2R2AD4.js";
25
25
  import {
26
26
  parseSharedWriteOutputControls
27
27
  } from "./chunk-IFBSZGW3.js";
28
28
  import {
29
29
  validateBriefingFormat
30
- } from "./chunk-VNZMZPAC.js";
30
+ } from "./chunk-LT4SMGE4.js";
31
31
  import {
32
32
  parseDeepRecallMaxSteps
33
33
  } from "./chunk-A7AISUJI.js";
@@ -603,4 +603,4 @@ defineOperation({ name: "graph_events", description: "SSE graph events.", schema
603
603
  defineOperation({ name: "chat_message", description: "Chat message.", schema: strictSchema({ message: S.str, chatSessionId: S.str }), handler: async (_i, _ctx) => ({ result: { ok: true } }) });
604
604
  defineOperation({ name: "chat_events", description: "SSE chat events.", schema: strictSchema({}), handler: async (_i, _ctx) => ({ result: { stream: "sse" } }) });
605
605
  defineOperation({ name: "adapters_status", description: "Adapter registry metadata (issue #1850 round 5). Marker op: the HTTP transport builds the response from its own adapterRegistry, but the op still must be registered so it appears in listRegisteredOperations and enforceTokenOp can gate it for scoped tokens.", schema: strictSchema({}), handler: async (_i, _ctx) => ({ result: { ok: true } }) });
606
- //# sourceMappingURL=chunk-CQOIWJ5E.js.map
606
+ //# sourceMappingURL=chunk-5NO42IYF.js.map
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-LXATZLSC.js";
12
12
  import {
13
13
  StorageManager
14
- } from "./chunk-4SCZZ3U7.js";
14
+ } from "./chunk-D42L5SQF.js";
15
15
  import {
16
16
  isValidityExpiredNow
17
17
  } from "./chunk-6CIAGZ6X.js";
@@ -416,4 +416,4 @@ export {
416
416
  readProjectedHarmonicGraph,
417
417
  searchHarmonicRetrieval
418
418
  };
419
- //# sourceMappingURL=chunk-NHUX6GXA.js.map
419
+ //# sourceMappingURL=chunk-62CRBI5B.js.map
@@ -7,10 +7,10 @@ import {
7
7
  import {
8
8
  listMemoryGovernanceRuns,
9
9
  readMemoryGovernanceRunArtifact
10
- } from "./chunk-C6JMGAMO.js";
10
+ } from "./chunk-DJMGVSST.js";
11
11
  import {
12
12
  StorageManager
13
- } from "./chunk-4SCZZ3U7.js";
13
+ } from "./chunk-D42L5SQF.js";
14
14
  import {
15
15
  normalizeProjectionPreview,
16
16
  normalizeProjectionTags
@@ -1156,4 +1156,4 @@ export {
1156
1156
  verifyMemoryProjection,
1157
1157
  repairMemoryProjection
1158
1158
  };
1159
- //# sourceMappingURL=chunk-5ATSXCAG.js.map
1159
+ //# sourceMappingURL=chunk-6VWCL2IZ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineOperation
3
- } from "./chunk-GFWRXPF6.js";
3
+ } from "./chunk-CA2R2AD4.js";
4
4
  import {
5
5
  EngramAccessInputError
6
6
  } from "./chunk-3MUKQQ7A.js";
@@ -92,4 +92,4 @@ defineOperation({
92
92
  };
93
93
  }
94
94
  });
95
- //# sourceMappingURL=chunk-CXOYUANR.js.map
95
+ //# sourceMappingURL=chunk-7UHCV5B3.js.map
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-3UXOZBHV.js";
15
15
  import {
16
16
  StorageManager
17
- } from "./chunk-4SCZZ3U7.js";
17
+ } from "./chunk-D42L5SQF.js";
18
18
  import {
19
19
  OKF_PROFILE_TYPE,
20
20
  okfTypeForMemory
@@ -272,4 +272,4 @@ export {
272
272
  exportOkfBundle,
273
273
  firstHeading
274
274
  };
275
- //# sourceMappingURL=chunk-BK2BVLZW.js.map
275
+ //# sourceMappingURL=chunk-A2IJEV5L.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4Q26RNSR.js";
4
4
  import {
5
5
  isRecallDisclosure
6
- } from "./chunk-3MO4LWYU.js";
6
+ } from "./chunk-466EGMFQ.js";
7
7
  import {
8
8
  EngramAccessInputError
9
9
  } from "./chunk-3MUKQQ7A.js";
@@ -165,4 +165,4 @@ export {
165
165
  handleRecallWhyHttpQuery,
166
166
  handleRecallXrayHttpQuery
167
167
  };
168
- //# sourceMappingURL=chunk-EH4BQ7LT.js.map
168
+ //# sourceMappingURL=chunk-AAQ77A44.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  parseXrayFormat
3
- } from "./chunk-OXNTOHL6.js";
3
+ } from "./chunk-VYVQZRXF.js";
4
4
  import {
5
5
  RECALL_DISCLOSURE_LEVELS,
6
6
  isRecallDisclosure
7
- } from "./chunk-3MO4LWYU.js";
7
+ } from "./chunk-466EGMFQ.js";
8
8
 
9
9
  // src/recall-xray-cli.ts
10
10
  function parseXrayDisclosureFlag(value) {
@@ -50,4 +50,4 @@ export {
50
50
  parseXrayBudgetFlag,
51
51
  parseXrayCliOptions
52
52
  };
53
- //# sourceMappingURL=chunk-R2H4ZFBJ.js.map
53
+ //# sourceMappingURL=chunk-BI3CIDIH.js.map
@@ -41,7 +41,7 @@ import {
41
41
  computeWhoKnows,
42
42
  loadWhoKnowsEntities,
43
43
  validateWhoKnowsInput
44
- } from "./chunk-4PDTVVSW.js";
44
+ } from "./chunk-O6ADSFGY.js";
45
45
  import {
46
46
  getTrustZoneStoreStatus,
47
47
  isTrustZoneName,
@@ -77,7 +77,7 @@ import {
77
77
  } from "./chunk-KIW3OOZE.js";
78
78
  import {
79
79
  planDisclosureStep
80
- } from "./chunk-QS3OLP5I.js";
80
+ } from "./chunk-ZDDDWTC7.js";
81
81
  import {
82
82
  DEFAULT_TRAVERSE_LIMIT,
83
83
  selectTraverseNeighbors
@@ -87,11 +87,11 @@ import {
87
87
  } from "./chunk-7O5EW7KX.js";
88
88
  import {
89
89
  toRecallExplainJson
90
- } from "./chunk-OXNTOHL6.js";
90
+ } from "./chunk-VYVQZRXF.js";
91
91
  import {
92
92
  estimateRecallTokens,
93
93
  summarizeDisclosureTokens
94
- } from "./chunk-VW6VIJOS.js";
94
+ } from "./chunk-IVUCF3QO.js";
95
95
  import {
96
96
  takeNavigateBudget
97
97
  } from "./chunk-VYDGHJIN.js";
@@ -100,7 +100,7 @@ import {
100
100
  } from "./chunk-H7XKCNR6.js";
101
101
  import {
102
102
  readAggregateExtractionWatermark
103
- } from "./chunk-DQR2LD3V.js";
103
+ } from "./chunk-YW4ZYASS.js";
104
104
  import {
105
105
  ReplicaDivergenceMonitor
106
106
  } from "./chunk-E6UNM67F.js";
@@ -130,7 +130,7 @@ import {
130
130
  } from "./chunk-DMDWFQMR.js";
131
131
  import {
132
132
  readProjectedHarmonicGraph
133
- } from "./chunk-NHUX6GXA.js";
133
+ } from "./chunk-62CRBI5B.js";
134
134
  import {
135
135
  wrapWorkLayerContext
136
136
  } from "./chunk-EI6V5UXY.js";
@@ -175,7 +175,7 @@ import {
175
175
  import {
176
176
  CorpusWatermarkCache,
177
177
  computeServiceCorpusCensus
178
- } from "./chunk-QSEUUQUF.js";
178
+ } from "./chunk-VVSPHTSU.js";
179
179
  import {
180
180
  CrossNamespaceBudget,
181
181
  toBudgetWarning
@@ -187,7 +187,7 @@ import {
187
187
  listMemoryGovernanceRuns,
188
188
  readMemoryGovernanceRunArtifact,
189
189
  runMemoryGovernance
190
- } from "./chunk-C6JMGAMO.js";
190
+ } from "./chunk-DJMGVSST.js";
191
191
  import {
192
192
  defaultCapsulesDir
193
193
  } from "./chunk-ZY2MNJR6.js";
@@ -197,7 +197,7 @@ import {
197
197
  enqueuePassiveCorrectionNotification,
198
198
  parseBriefingFocus,
199
199
  parseBriefingWindow
200
- } from "./chunk-VNZMZPAC.js";
200
+ } from "./chunk-LT4SMGE4.js";
201
201
  import {
202
202
  ExtractionDeadlineError
203
203
  } from "./chunk-LO76EF3Y.js";
@@ -256,7 +256,7 @@ import {
256
256
  qmdCollectionPathParts,
257
257
  qmdResultPathCandidates,
258
258
  selfDeps
259
- } from "./chunk-4SCZZ3U7.js";
259
+ } from "./chunk-D42L5SQF.js";
260
260
  import {
261
261
  namespaceCollectionName
262
262
  } from "./chunk-MWWAQXZ6.js";
@@ -291,7 +291,7 @@ import {
291
291
  import {
292
292
  DEFAULT_RECALL_DISCLOSURE,
293
293
  isRecallDisclosure
294
- } from "./chunk-3MO4LWYU.js";
294
+ } from "./chunk-466EGMFQ.js";
295
295
  import {
296
296
  extractJsonCandidates
297
297
  } from "./chunk-YBA52OKG.js";
@@ -18737,4 +18737,4 @@ export {
18737
18737
  EngramAccessService,
18738
18738
  AccessAdminOpsSurface
18739
18739
  };
18740
- //# sourceMappingURL=chunk-GFWRXPF6.js.map
18740
+ //# sourceMappingURL=chunk-CA2R2AD4.js.map
@@ -162,7 +162,7 @@ import {
162
162
  import {
163
163
  SPECULATIVE_TTL_DAYS,
164
164
  confidenceTier
165
- } from "./chunk-3MO4LWYU.js";
165
+ } from "./chunk-466EGMFQ.js";
166
166
  import {
167
167
  composeMemoryEnvelope,
168
168
  isSealedMemoryEnvelope,
@@ -11579,4 +11579,4 @@ export {
11579
11579
  isValidBufferSurpriseEvent,
11580
11580
  StorageManager3 as StorageManager
11581
11581
  };
11582
- //# sourceMappingURL=chunk-4SCZZ3U7.js.map
11582
+ //# sourceMappingURL=chunk-D42L5SQF.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-TBBDFYXW.js";
4
4
  import {
5
5
  StorageManager
6
- } from "./chunk-4SCZZ3U7.js";
6
+ } from "./chunk-D42L5SQF.js";
7
7
  import {
8
8
  bumpMemoryCorpusVersionForDir
9
9
  } from "./chunk-M5GVCJSJ.js";
@@ -769,4 +769,4 @@ export {
769
769
  listMemoryGovernanceRuns,
770
770
  readMemoryGovernanceRunArtifact
771
771
  };
772
- //# sourceMappingURL=chunk-C6JMGAMO.js.map
772
+ //# sourceMappingURL=chunk-DJMGVSST.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-B7RWBZXW.js";
4
4
  import {
5
5
  StorageManager
6
- } from "./chunk-4SCZZ3U7.js";
6
+ } from "./chunk-D42L5SQF.js";
7
7
  import {
8
8
  getCachedEpisodeMap,
9
9
  setCachedEpisodeMap
@@ -109,4 +109,4 @@ export {
109
109
  compareVerifiedEpisodeResults,
110
110
  searchVerifiedEpisodes
111
111
  };
112
- //# sourceMappingURL=chunk-H5IUN433.js.map
112
+ //# sourceMappingURL=chunk-EML6HJE6.js.map
@@ -46,6 +46,12 @@ function isReasoningTracePath(candidatePath) {
46
46
  return /(^|[\\/])reasoning-traces([\\/]|$)/.test(candidatePath);
47
47
  }
48
48
  var DEFAULT_REASONING_TRACE_BOOST = 0.15;
49
+ function comparisonRelevance(row) {
50
+ if (typeof row.effectiveScore === "number" && Number.isFinite(row.effectiveScore)) {
51
+ return row.effectiveScore;
52
+ }
53
+ return typeof row.score === "number" && Number.isFinite(row.score) ? row.score : 0;
54
+ }
49
55
  function applyReasoningTraceBoost(results, options) {
50
56
  if (!options.enabled) return [...results];
51
57
  if (!Array.isArray(results) || results.length === 0) return [...results];
@@ -57,7 +63,10 @@ function applyReasoningTraceBoost(results, options) {
57
63
  if (isReasoningTracePath(r.path)) {
58
64
  changed = true;
59
65
  const baseScore = typeof r.score === "number" && Number.isFinite(r.score) ? r.score : 0;
60
- boosted.push({ ...r, score: baseScore + boostAmount });
66
+ const effective = typeof r.effectiveScore === "number" && Number.isFinite(r.effectiveScore) ? r.effectiveScore + boostAmount : void 0;
67
+ boosted.push(
68
+ effective === void 0 ? { ...r, score: baseScore + boostAmount } : { ...r, score: baseScore + boostAmount, effectiveScore: effective }
69
+ );
61
70
  } else {
62
71
  boosted.push(r);
63
72
  }
@@ -67,12 +76,12 @@ function applyReasoningTraceBoost(results, options) {
67
76
  for (let i = 0; i < out.length; i++) {
68
77
  if (!isReasoningTracePath(out[i].path)) continue;
69
78
  const trace = out[i];
70
- const traceScore = typeof trace.score === "number" && Number.isFinite(trace.score) ? trace.score : 0;
79
+ const traceScore = comparisonRelevance(trace);
71
80
  let j = i;
72
81
  while (j > 0) {
73
82
  const prev = out[j - 1];
74
83
  if (isReasoningTracePath(prev.path)) break;
75
- const prevScore = typeof prev.score === "number" && Number.isFinite(prev.score) ? prev.score : 0;
84
+ const prevScore = comparisonRelevance(prev);
76
85
  if (prevScore >= traceScore) break;
77
86
  out[j] = prev;
78
87
  j -= 1;
@@ -88,4 +97,4 @@ export {
88
97
  DEFAULT_REASONING_TRACE_BOOST,
89
98
  applyReasoningTraceBoost
90
99
  };
91
- //# sourceMappingURL=chunk-ZZTOURJI.js.map
100
+ //# sourceMappingURL=chunk-EVWDNKQA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/reasoning-trace-recall.ts"],"sourcesContent":["/**\n * Reasoning-trace recall boost (issue #564 PR 3).\n *\n * Pure helpers for:\n * - detecting whether a user query looks like a problem-solving ask\n * (\"how do I…\", \"step by step\", etc.)\n * - boosting stored reasoning_trace memories within a result list when that\n * condition matches.\n *\n * Callers gate these helpers behind the `recallReasoningTraceBoostEnabled`\n * config flag (default false); the helpers themselves are also no-ops when\n * `enabled` is false so they can be safely chained into the recall pipeline.\n */\n\n/**\n * Heuristic: does the incoming query read like the user wants a stored\n * solution chain (reasoning trace)?\n *\n * Positive signals:\n * - starts with \"how do I\", \"how can I\", \"how would I\", \"how to\"\n * - contains \"step by step\", \"walk me through\", \"work through\"\n * - contains \"reasoning\", \"think through\", \"figure out\", \"debug\"\n * - explicitly mentions \"trace\" or \"chain of thought\"\n *\n * This is intentionally conservative — the boost is OFF by default, so false\n * negatives are cheap, but false positives would shift retrieval for ordinary\n * queries on an opt-in install.\n */\nexport function looksLikeProblemSolvingQuery(query: string): boolean {\n if (typeof query !== \"string\") return false;\n const q = query.trim().toLowerCase();\n if (q.length === 0) return false;\n\n // Starts-with patterns.\n const startsWithPatterns = [\n /^how\\s+do\\s+i\\b/,\n /^how\\s+can\\s+i\\b/,\n /^how\\s+would\\s+i\\b/,\n /^how\\s+should\\s+i\\b/,\n /^how\\s+to\\b/,\n /^what'?s?\\s+the\\s+best\\s+way\\s+to\\b/,\n /^can\\s+you\\s+walk\\s+me\\s+through\\b/,\n /^walk\\s+me\\s+through\\b/,\n /^help\\s+me\\s+debug\\b/,\n /^help\\s+me\\s+figure\\s+out\\b/,\n /^why\\s+(does|is|did)\\b/,\n ];\n for (const re of startsWithPatterns) {\n if (re.test(q)) return true;\n }\n\n // Anywhere-in-string phrases. These mirror the doc-comment's stated\n // positive signals: broader variants (\"work through\", \"figure out\",\n // \"debug this\") are included so \"how do I debug this\" doesn't have to\n // lean on the `help me debug` starts-with entry alone, and so queries\n // like \"work through the problem\" or \"figure out why it broke\" trigger\n // the heuristic as the docstring claims.\n const phrases = [\n \"step by step\",\n \"step-by-step\",\n \"work through\",\n \"walk through\",\n \"walk me through\",\n \"reason through\",\n \"think through\",\n \"figure out\",\n \"chain of thought\",\n \"reasoning trace\",\n \"solution chain\",\n \"troubleshoot\",\n \"debug this\",\n \"debug the\",\n \" debug \",\n ];\n for (const phrase of phrases) {\n if (q.includes(phrase)) return true;\n }\n\n return false;\n}\n\n/**\n * Minimal shape the boost helper needs to read from a recall result. Matches\n * QmdSearchResult as of issue #564 but kept structural so tests and future\n * callers don't have to import orchestrator-level types.\n */\nexport interface BoostableResult {\n path: string;\n score: number;\n docid?: string;\n /** Effective relevance carried forward by an upstream rerank stage. */\n effectiveScore?: number;\n}\n\n/**\n * Path-based marker for memories that live in the dedicated\n * reasoning-traces/ subtree. Using a path segment keeps this cheap: no\n * frontmatter parsing or extra I/O is needed.\n */\nexport function isReasoningTracePath(candidatePath: string): boolean {\n if (typeof candidatePath !== \"string\") return false;\n // Match \"/reasoning-traces/\" as a full path segment to avoid false\n // positives like \"my-reasoning-traces-notes/\".\n return /(^|[\\\\/])reasoning-traces([\\\\/]|$)/.test(candidatePath);\n}\n\n/**\n * Default additive boost applied to a reasoning_trace candidate when the\n * current query looks like a problem-solving ask.\n *\n * Chosen to be roughly the same magnitude as the existing CATEGORY_BOOSTS\n * entry for reasoning_trace (0.09 in importance scoring), keeping the signal\n * visible but not overwhelming stronger lexical/vector matches.\n */\nexport const DEFAULT_REASONING_TRACE_BOOST = 0.15;\n\nexport interface ApplyReasoningTraceBoostOptions {\n enabled: boolean;\n query: string;\n boost?: number;\n}\n\n/**\n * The relevance a row is compared on: its effective relevance when a rerank\n * stage left one (MMR ranks on the same basis), else the raw retrieval score.\n */\nfunction comparisonRelevance(row: BoostableResult): number {\n if (typeof row.effectiveScore === \"number\" && Number.isFinite(row.effectiveScore)) {\n return row.effectiveScore;\n }\n return typeof row.score === \"number\" && Number.isFinite(row.score) ? row.score : 0;\n}\n\n/**\n * Apply a score boost to results whose path sits under reasoning-traces/\n * when the query looks like a problem-solving ask. Returns a new array;\n * the input array is not mutated.\n *\n * Ordering policy: the helper walks the results in order, boosts every\n * matching reasoning trace in place, then promotes each boosted trace\n * upward PAST any non-boosted neighbor whose score is strictly lower\n * than the trace's boosted score. Non-matching results keep their\n * incoming relative order — so reranker-driven path ordering and any\n * other upstream nudges on non-trace items are preserved. We do NOT\n * re-sort the full list, which would wipe out rerank priority on\n * non-trace items (whose numeric scores may have been left stale by the\n * rerank pass). This matters because MMR runs immediately after and\n * truncates to a topN window — globally re-sorting would silently drop\n * reranker-promoted items below the cutoff.\n *\n * No-ops (returns a copy of the input unchanged) when:\n * - `enabled` is false,\n * - `query` is empty / not a problem-solving ask,\n * - the result list contains no reasoning-trace paths.\n *\n * Note on legacy paths: this helper intentionally only matches paths\n * under the dedicated `reasoning-traces/` subtree introduced by PR 3.\n * Historical reasoning_trace memories (if any) written before that\n * subtree existed were routed to `facts/<date>/` and are NOT\n * boost-eligible. Operators upgrading across that boundary should run\n * the migration CLI or rewrite old paths before enabling the boost.\n */\nexport function applyReasoningTraceBoost<R extends BoostableResult>(\n results: readonly R[],\n options: ApplyReasoningTraceBoostOptions,\n): R[] {\n if (!options.enabled) return [...results];\n if (!Array.isArray(results) || results.length === 0) return [...results];\n if (!looksLikeProblemSolvingQuery(options.query)) return [...results];\n\n const boostAmount =\n typeof options.boost === \"number\" && Number.isFinite(options.boost) && options.boost >= 0\n ? options.boost\n : DEFAULT_REASONING_TRACE_BOOST;\n\n // Step 1: boost the scores of matching traces, preserving positions.\n const boosted: R[] = [];\n let changed = false;\n for (const r of results) {\n if (isReasoningTracePath(r.path)) {\n changed = true;\n const baseScore = typeof r.score === \"number\" && Number.isFinite(r.score) ? r.score : 0;\n // Compose the boost into the effective relevance too: a downstream MMR\n // pass prefers it over the raw score, so a stale value would drop the\n // boost.\n const effective =\n typeof r.effectiveScore === \"number\" && Number.isFinite(r.effectiveScore)\n ? r.effectiveScore + boostAmount\n : undefined;\n boosted.push(\n effective === undefined\n ? ({ ...r, score: baseScore + boostAmount } as R)\n : ({ ...r, score: baseScore + boostAmount, effectiveScore: effective } as R),\n );\n } else {\n boosted.push(r);\n }\n }\n if (!changed) return boosted;\n\n // Step 2: promote each boosted trace upward past any non-trace neighbor\n // whose relevance is strictly lower than the boosted trace's. The\n // comparison uses the SAME basis MMR ranks on — the effective relevance a\n // rerank stage left behind, else the raw score — so the boost cannot\n // promote a trace the pipeline deliberately demoted. Non-trace items never\n // move past each other, so reranker-driven ordering on non-trace items is\n // preserved.\n const out = boosted.slice();\n for (let i = 0; i < out.length; i++) {\n if (!isReasoningTracePath(out[i].path)) continue;\n const trace = out[i];\n const traceScore = comparisonRelevance(trace);\n let j = i;\n while (j > 0) {\n const prev = out[j - 1];\n if (isReasoningTracePath(prev.path)) break; // don't reorder traces vs each other\n const prevScore = comparisonRelevance(prev);\n if (prevScore >= traceScore) break;\n out[j] = prev;\n j -= 1;\n }\n if (j !== i) out[j] = trace;\n }\n\n return out;\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isNamespaceKind
3
- } from "./chunk-GWVNGDJW.js";
3
+ } from "./chunk-2I3OREMR.js";
4
4
  import {
5
5
  EngramAccessInputError
6
6
  } from "./chunk-3MUKQQ7A.js";
@@ -40,4 +40,4 @@ export {
40
40
  positiveIntQueryParam,
41
41
  optionalNamespaceKindQueryParam
42
42
  };
43
- //# sourceMappingURL=chunk-MJIOGYKX.js.map
43
+ //# sourceMappingURL=chunk-FBNL4BYD.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseFrontmatter
3
- } from "./chunk-4SCZZ3U7.js";
3
+ } from "./chunk-D42L5SQF.js";
4
4
  import {
5
5
  activityDigestPath,
6
6
  isValidActivityDate
@@ -199,4 +199,4 @@ export {
199
199
  buildStandup,
200
200
  standupHelp
201
201
  };
202
- //# sourceMappingURL=chunk-5KGYTX5O.js.map
202
+ //# sourceMappingURL=chunk-GXVLEXIX.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-7T4TOGMS.js";
4
4
  import {
5
5
  defineOperation
6
- } from "./chunk-GFWRXPF6.js";
6
+ } from "./chunk-CA2R2AD4.js";
7
7
 
8
8
  // src/external-wiki-access.ts
9
9
  import { z } from "zod";
@@ -26,4 +26,4 @@ var externalWikiSearchOperation = defineOperation({
26
26
  export {
27
27
  externalWikiSearchOperation
28
28
  };
29
- //# sourceMappingURL=chunk-6YEPGWUP.js.map
29
+ //# sourceMappingURL=chunk-HVIXRLXJ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineOperation
3
- } from "./chunk-GFWRXPF6.js";
3
+ } from "./chunk-CA2R2AD4.js";
4
4
  import {
5
5
  EngramAccessInputError
6
6
  } from "./chunk-3MUKQQ7A.js";
@@ -71,4 +71,4 @@ defineOperation({
71
71
  })
72
72
  })
73
73
  });
74
- //# sourceMappingURL=chunk-AZDTDWS2.js.map
74
+ //# sourceMappingURL=chunk-IBGRIAE5.js.map
@@ -242,7 +242,7 @@ function reorderRecallResultsWithMmr(results, options = {}) {
242
242
  const candidates = results.map((r, index) => ({
243
243
  id: makeRecallKey(r, index),
244
244
  content: r.snippet ?? "",
245
- score: typeof r.score === "number" ? r.score : 0,
245
+ score: effectiveRelevance(r),
246
246
  embedding: null
247
247
  }));
248
248
  const indexById = /* @__PURE__ */ new Map();
@@ -282,6 +282,12 @@ function reorderRecallResultsWithMmr(results, options = {}) {
282
282
  );
283
283
  return { reordered, diversity, lambda };
284
284
  }
285
+ function effectiveRelevance(r) {
286
+ if (typeof r.effectiveScore === "number" && Number.isFinite(r.effectiveScore)) {
287
+ return r.effectiveScore;
288
+ }
289
+ return typeof r.score === "number" ? r.score : 0;
290
+ }
285
291
  function makeRecallKey(r, index) {
286
292
  const baseKey = r.path || r.docid || "";
287
293
  return `${baseKey}::${index}`;
@@ -295,4 +301,4 @@ export {
295
301
  normalizeTokens,
296
302
  reorderRecallResultsWithMmr
297
303
  };
298
- //# sourceMappingURL=chunk-YDBIWGNI.js.map
304
+ //# sourceMappingURL=chunk-IIK2PD3F.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/recall-mmr.ts"],"sourcesContent":["/**\n * Maximal Marginal Relevance (MMR) re-selection for recall candidates.\n *\n * After the reranker produces its ordered candidate list, we run an MMR pass\n * over the top N candidates (per-section) so that a cluster of near-duplicate\n * high-scoring facts cannot dominate the injected context.\n *\n * MMR(d) = λ * sim(d, query) − (1 − λ) * max_{d' ∈ selected} sim(d, d')\n *\n * - λ defaults to 0.7 (tilted toward relevance, with meaningful diversity).\n * - Similarity uses cosine over pre-computed embeddings when available, and\n * falls back to Jaccard over normalized tokens (lowercased alphanumerics)\n * when embeddings are missing.\n * - Per-section application is the caller's responsibility: pass each\n * section's ordered candidate slice independently so one cluster in one\n * section cannot starve another section.\n *\n * Pure, deterministic, no IO. Input arrays are never mutated.\n */\n\n/** Minimal candidate shape used by MMR. Callers may wrap their own records. */\nexport interface MmrCandidate {\n /** Stable identifier for the candidate. Only used for tie-breaking. */\n id: string;\n /** Text content used for the Jaccard similarity fallback. */\n content: string;\n /**\n * Relevance score from the upstream ranker (e.g. rerank score or RRF).\n * Used as the `sim(d, query)` term when no query embedding is available.\n */\n score: number;\n /** Optional pre-computed embedding vector for cosine similarity. */\n embedding?: readonly number[] | null;\n}\n\nexport interface ApplyMmrOptions<C extends MmrCandidate> {\n /** Ordered candidate list (most relevant first). */\n candidates: readonly C[];\n /** Optional query embedding. If provided and candidates carry embeddings,\n * relevance is measured by cosine similarity to the query. Otherwise\n * candidate `score` is normalized and used. */\n queryEmbedding?: readonly number[] | null;\n /** λ ∈ [0, 1]. 1 = pure relevance, 0 = pure diversity. Default 0.7. */\n lambda?: number;\n /** Apply MMR only over the top N candidates. Default 40. */\n topN?: number;\n /** Maximum number of candidates to select. Default = candidates length. */\n budget?: number;\n}\n\nexport interface MmrDiversityReport {\n /**\n * Total number of candidates MMR considered (the full input pool, pre-MMR).\n * Previously this mirrored `kept` and was therefore uninformative; it now\n * reflects the true pool size so `kept/considered` logs carry signal even\n * though MMR is reorder-only.\n */\n considered: number;\n /**\n * Number of candidates present in the MMR output. With the current\n * orchestrator pipeline MMR is reorder-only (no drops), so this is the\n * same as `considered`. It's still reported separately so a future\n * drop-mode MMR can distinguish them without another schema change.\n */\n kept: number;\n /**\n * Head-of-list positions whose candidate identity changed between the\n * pre-MMR and post-MMR slices. This is the *actionable* diversity signal:\n * it tells the caller how many of the top `sampleSize` results MMR\n * promoted or demoted. Zero means MMR had no head-of-list effect; a value\n * greater than zero means at least one diverse candidate was swapped in.\n */\n headReorderCount: number;\n /** Average pairwise similarity of the head-of-list input slice (pre-MMR). */\n avgPairwiseSimBefore: number;\n /** Average pairwise similarity of the head-of-list MMR output slice. */\n avgPairwiseSimAfter: number;\n}\n\nexport const DEFAULT_LAMBDA = 0.7;\nexport const DEFAULT_TOP_N = 40;\n/**\n * Default number of head-of-list candidates compared by\n * {@link summarizeMmrDiversity}. Small on purpose: we want to measure whether\n * MMR actually *changed* the head of the list. Comparing the full top-N slice\n * is meaningless when `budget >= candidates.length` because both slices\n * contain the same set (just reordered), making pairwise-similarity\n * order-independent and identical before vs after.\n */\nconst DEFAULT_DIVERSITY_SAMPLE_SIZE = 10;\n\n/**\n * Pure MMR re-selection over an ordered candidate list.\n *\n * Returns a new array — the input is never mutated. When `candidates.length`\n * is `<= 1` or `budget <= 0`, a defensive copy is returned as a no-op.\n */\nexport function applyMmrToCandidates<C extends MmrCandidate>(\n opts: ApplyMmrOptions<C>,\n): C[] {\n const candidates = Array.isArray(opts.candidates) ? opts.candidates : [];\n if (candidates.length === 0) return [];\n\n const lambda = clampLambda(opts.lambda);\n const topN = clampPositiveInt(opts.topN, DEFAULT_TOP_N);\n const budget = clampPositiveInt(opts.budget, candidates.length);\n\n if (budget <= 0) return [];\n if (candidates.length === 1) return [candidates[0]!];\n\n // Only reorder the top-N slice; anything past it keeps its original position\n // appended at the end (but will not be selected unless budget > topN).\n const pool = candidates.slice(0, topN);\n const tail = candidates.slice(topN);\n\n // Relevance scores as `sim(d, query)`. Prefer cosine to the query embedding\n // when we can compute it; otherwise fall back to the candidate's own score\n // normalized into [0, 1] across the pool.\n const relevance = computeRelevanceScores(pool, opts.queryEmbedding);\n\n // Pre-compute pairwise candidate-candidate similarity lazily as needed.\n const pairSim = new Map<string, number>();\n const pairKey = (i: number, j: number): string =>\n i < j ? `${i}:${j}` : `${j}:${i}`;\n const sim = (i: number, j: number): number => {\n if (i === j) return 1;\n const key = pairKey(i, j);\n const cached = pairSim.get(key);\n if (cached !== undefined) return cached;\n const a = pool[i]!;\n const b = pool[j]!;\n const s = similarity(a, b);\n pairSim.set(key, s);\n return s;\n };\n\n const selectedIdx: number[] = [];\n const remaining = new Set<number>();\n for (let i = 0; i < pool.length; i += 1) remaining.add(i);\n\n while (selectedIdx.length < budget && remaining.size > 0) {\n let bestIdx = -1;\n let bestMmr = Number.NEGATIVE_INFINITY;\n for (const idx of remaining) {\n const rel = relevance[idx] ?? 0;\n let maxSimToSelected = 0;\n if (selectedIdx.length > 0) {\n for (const s of selectedIdx) {\n const pairwise = sim(idx, s);\n if (pairwise > maxSimToSelected) maxSimToSelected = pairwise;\n }\n }\n const mmr = lambda * rel - (1 - lambda) * maxSimToSelected;\n if (\n mmr > bestMmr ||\n // Stable tie-breaker: prefer the earlier original position.\n (mmr === bestMmr && (bestIdx < 0 || idx < bestIdx))\n ) {\n bestMmr = mmr;\n bestIdx = idx;\n }\n }\n if (bestIdx < 0) break;\n selectedIdx.push(bestIdx);\n remaining.delete(bestIdx);\n }\n\n const selected: C[] = selectedIdx.map((i) => pool[i]!);\n\n // If the caller set a budget larger than topN, append tail candidates in\n // their original order until budget is filled. This keeps MMR scoped to the\n // top-N slice while still respecting the caller's requested size.\n if (selected.length < budget && tail.length > 0) {\n for (const c of tail) {\n if (selected.length >= budget) break;\n selected.push(c);\n }\n }\n\n return selected;\n}\n\n/**\n * Summarize how much MMR reshuffled the head of the candidate list, for\n * logging. Optional — callers can skip this if they don't care about metrics.\n *\n * IMPORTANT: `before` should be the score-ordered input (the same ordering the\n * upstream reranker emitted, *not* the MMR output), and `after` should be the\n * MMR-reordered list. Both are truncated to `sampleSize` before their pairwise\n * similarity is averaged.\n *\n * The sample size intentionally defaults to a small number\n * ({@link DEFAULT_DIVERSITY_SAMPLE_SIZE}) so that when the caller uses\n * `budget >= candidates.length` (i.e. MMR only reorders without dropping), the\n * head-of-list comparison still reflects whether MMR promoted diverse\n * candidates. Passing a sample size `>= candidates.length` in that situation\n * makes `avgPairwiseSimBefore` and `avgPairwiseSimAfter` trivially equal\n * because pairwise similarity is order-independent.\n */\nexport function summarizeMmrDiversity<C extends MmrCandidate>(\n before: readonly C[],\n after: readonly C[],\n sampleSize: number = DEFAULT_DIVERSITY_SAMPLE_SIZE,\n): MmrDiversityReport {\n const n = clampPositiveInt(sampleSize, DEFAULT_DIVERSITY_SAMPLE_SIZE);\n const beforeSlice = before.slice(0, n);\n const afterSlice = after.slice(0, n);\n // Count how many head-of-list positions MMR actually changed. A zero value\n // means MMR left the head untouched; a positive value is the actionable\n // \"MMR promoted N diverse candidates\" signal the previous metric lacked.\n let headReorderCount = 0;\n const compareLength = Math.min(beforeSlice.length, afterSlice.length);\n for (let i = 0; i < compareLength; i += 1) {\n if (beforeSlice[i]!.id !== afterSlice[i]!.id) headReorderCount += 1;\n }\n return {\n considered: before.length,\n kept: after.length,\n headReorderCount,\n avgPairwiseSimBefore: averagePairwiseSimilarity(beforeSlice),\n avgPairwiseSimAfter: averagePairwiseSimilarity(afterSlice),\n };\n}\n\n// -----------------------------------------------------------------------------\n// Internals\n// -----------------------------------------------------------------------------\n\nfunction clampLambda(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return DEFAULT_LAMBDA;\n if (value < 0) return 0;\n if (value > 1) return 1;\n return value;\n}\n\nfunction clampPositiveInt(\n value: number | undefined,\n fallback: number,\n): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n if (value <= 0) return 0;\n return Math.floor(value);\n}\n\nfunction computeRelevanceScores<C extends MmrCandidate>(\n pool: readonly C[],\n queryEmbedding: readonly number[] | null | undefined,\n): number[] {\n // If we have a query embedding, use cosine against each candidate embedding\n // where possible. Candidates without embeddings fall back to normalized score.\n const canUseQueryEmbedding =\n Array.isArray(queryEmbedding) && queryEmbedding.length > 0;\n\n if (canUseQueryEmbedding) {\n const scores: number[] = [];\n for (const c of pool) {\n if (Array.isArray(c.embedding) && c.embedding.length > 0) {\n scores.push(cosineSimilarity(queryEmbedding!, c.embedding));\n } else {\n // Fall back to the upstream relevance score for this one candidate.\n scores.push(normalizeFinite(c.score));\n }\n }\n return normalizeVector(scores);\n }\n\n // No query embedding — use normalized candidate scores.\n const raw = pool.map((c) => normalizeFinite(c.score));\n return normalizeVector(raw);\n}\n\nfunction similarity<C extends MmrCandidate>(a: C, b: C): number {\n if (\n Array.isArray(a.embedding) &&\n a.embedding.length > 0 &&\n Array.isArray(b.embedding) &&\n b.embedding.length > 0 &&\n a.embedding.length === b.embedding.length\n ) {\n return cosineSimilarity(a.embedding, b.embedding);\n }\n return jaccardSimilarity(a.content ?? \"\", b.content ?? \"\");\n}\n\nfunction cosineSimilarity(\n a: readonly number[],\n b: readonly number[],\n): number {\n if (a.length === 0 || b.length === 0) return 0;\n const len = Math.min(a.length, b.length);\n let dot = 0;\n let na = 0;\n let nb = 0;\n for (let i = 0; i < len; i += 1) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n dot += av * bv;\n na += av * av;\n nb += bv * bv;\n }\n if (na === 0 || nb === 0) return 0;\n const cos = dot / (Math.sqrt(na) * Math.sqrt(nb));\n // Clamp to [0, 1]. Negative cosines (opposite directions) are treated as 0\n // for MMR purposes — two embeddings pointing opposite ways should be\n // \"maximally diverse\", not discouraged further.\n if (cos < 0) return 0;\n if (cos > 1) return 1;\n return cos;\n}\n\nexport function normalizeTokens(text: string): Set<string> {\n if (!text) return new Set();\n // Unicode-aware normalization. We lowercase and replace any character that\n // is NOT a Unicode letter or number with a space, then split on whitespace.\n // This preserves non-Latin scripts (Cyrillic, Greek, Hebrew, Arabic, etc.)\n // so the Jaccard fallback still detects near-duplicates in multilingual\n // snippets. Without this fix, `[^a-z0-9]+` strips all non-ASCII and two\n // identical Chinese/Japanese/Cyrillic snippets both collapse to the empty\n // set, returning similarity 0 and letting duplicates dominate recall.\n const cleaned = text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, \" \")\n .trim();\n if (cleaned.length === 0) {\n // CJK fallback: scripts like Chinese/Japanese/Korean do not use word\n // breaks, so after the Unicode strip the above split-on-whitespace yields\n // one big token. The Latin-style split is a bad match for these scripts;\n // use per-codepoint character tokens instead, which approximates a\n // unigram shingle and is accurate enough for near-duplicate detection.\n const chars = new Set<string>();\n for (const ch of text.toLowerCase()) {\n if (/\\s/.test(ch)) continue;\n chars.add(ch);\n }\n return chars;\n }\n const tokens = new Set<string>();\n for (const token of cleaned.split(/\\s+/)) {\n if (!token) continue;\n // A single \"token\" that is actually a run of CJK codepoints (no spaces in\n // the source) should still be split into per-character tokens so the\n // Jaccard overlap works. Latin/Cyrillic/etc. keep their word-level tokens.\n if (token.length >= 2 && hasUnsegmentableScript(token)) {\n for (const ch of token) tokens.add(ch);\n } else {\n tokens.add(token);\n }\n }\n return tokens;\n}\n\n/**\n * Returns true when `token` contains at least one codepoint in a script that\n * does not use whitespace for word segmentation (CJK Unified Ideographs,\n * Hiragana, Katakana, Hangul). These are tokenized per-character so Jaccard\n * similarity can still detect near-duplicate snippets.\n */\nfunction hasUnsegmentableScript(token: string): boolean {\n return /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u.test(\n token,\n );\n}\n\nfunction jaccardSimilarity(a: string, b: string): number {\n const ta = normalizeTokens(a);\n const tb = normalizeTokens(b);\n if (ta.size === 0 && tb.size === 0) return 0;\n let intersection = 0;\n for (const t of ta) if (tb.has(t)) intersection += 1;\n const union = ta.size + tb.size - intersection;\n if (union === 0) return 0;\n return intersection / union;\n}\n\nfunction normalizeFinite(value: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n return value;\n}\n\nfunction normalizeVector(values: number[]): number[] {\n if (values.length === 0) return values;\n // Intentionally *not* min-max normalized. Min-max maps the lowest score to\n // 0 and the highest to 1, which amplifies tiny relevance gaps (e.g. a tight\n // reranker cluster like [0.93, 0.94, 0.95]) into the full [0, 1] range.\n // That lets a near-duplicate at the top permanently beat a diverse\n // candidate at the bottom because `lambda * 0 - (1 - lambda) * 0 = 0` is\n // always worse than `lambda * 1 - (1 - lambda) * maxSim` for any\n // maxSim < lambda / (1 - lambda). MMR is supposed to escape exactly that\n // scenario; min-max defeats it.\n //\n // Instead we preserve the relative score gaps by scaling only if the\n // scores leave the MMR-friendly `[0, 1]` range. Negative or out-of-range\n // scores are clamped to `[0, 1]` by dividing by the max absolute value; if\n // everything is already inside `[0, 1]`, we pass through untouched so\n // tight clusters stay tight and MMR can promote a diverse candidate from\n // the bottom of the cluster.\n let max = 0;\n let min = Number.POSITIVE_INFINITY;\n for (const v of values) {\n if (!Number.isFinite(v)) continue;\n const a = Math.abs(v);\n if (a > max) max = a;\n if (v < min) min = v;\n }\n if (!Number.isFinite(min)) {\n return values.map(() => 0);\n }\n if (max === 0) {\n // All scores are zero — give everyone 1 so diversity fully drives\n // selection (otherwise every candidate has `lambda * 0 = 0` and the\n // first-found wins trivially, hiding any diversity benefit).\n return values.map(() => 1);\n }\n // If scores already live in [0, 1], pass them through so tight clusters\n // (e.g. [0.93, 0.94, 0.95]) stay tight and the (1 - lambda) * maxSim term\n // can actually outweigh a 0.01 relevance gap, which is the whole point of\n // MMR. Otherwise divide by `max` to bring the top score to 1 while\n // preserving *relative* gaps (e.g. [100, 200, 300] -> [0.33, 0.67, 1.0]).\n if (min >= 0 && max <= 1) {\n return values.map((v) =>\n Number.isFinite(v) ? (v < 0 ? 0 : v > 1 ? 1 : v) : 0,\n );\n }\n return values.map((v) => {\n if (!Number.isFinite(v)) return 0;\n const scaled = v / max;\n if (scaled < 0) return 0;\n if (scaled > 1) return 1;\n return scaled;\n });\n}\n\nfunction averagePairwiseSimilarity<C extends MmrCandidate>(\n candidates: readonly C[],\n): number {\n if (candidates.length < 2) return 0;\n let sum = 0;\n let count = 0;\n for (let i = 0; i < candidates.length; i += 1) {\n for (let j = i + 1; j < candidates.length; j += 1) {\n sum += similarity(candidates[i]!, candidates[j]!);\n count += 1;\n }\n }\n if (count === 0) return 0;\n return sum / count;\n}\n\n// -----------------------------------------------------------------------------\n// Orchestration helper: MMR for recall results keyed by path-first\n// -----------------------------------------------------------------------------\n\n/**\n * Minimum shape the recall-MMR orchestration helper expects from a result.\n * Any richer result type (e.g. {@link QmdSearchResult}) satisfies this.\n */\nexport interface MmrRecallResult {\n readonly docid?: string;\n readonly path?: string;\n readonly snippet?: string;\n readonly score?: number;\n}\n\nexport interface ReorderRecallResultsOptions {\n readonly lambda?: number;\n readonly topN?: number;\n /**\n * Head-of-list sample size used by the diversity metric. Defaults to\n * {@link DEFAULT_DIVERSITY_SAMPLE_SIZE}. Intentionally small so the metric\n * reflects head-of-list changes even when `budget >= results.length`.\n */\n readonly diversitySampleSize?: number;\n}\n\nexport interface ReorderRecallResultsOutcome<R extends MmrRecallResult> {\n readonly reordered: R[];\n readonly diversity: MmrDiversityReport;\n readonly lambda: number;\n}\n\n/**\n * Apply MMR to an ordered list of recall results and return the reordered\n * list plus a head-of-list diversity report.\n *\n * This helper is the single source of truth for the orchestrator's\n * per-section MMR pass. It is pure and deterministic so it can be unit\n * tested without constructing an Orchestrator.\n *\n * Key invariants:\n * 1. **No silent drops.** Candidates are keyed by a stable unique key derived\n * from `path` first, falling back to `docid`, and always suffixed with the\n * candidate's original index. Two results that share a basename-style\n * docid but differ in path are treated as distinct candidates and both\n * survive the reorder.\n * 2. **No mutation.** The input array is never mutated; a new array is\n * returned.\n * 3. **Diversity metric is meaningful.** The report compares the *head of\n * list* before and after MMR using a small sample size, so it reflects\n * whether MMR promoted diverse candidates even when\n * `budget >= results.length`.\n */\nexport function reorderRecallResultsWithMmr<R extends MmrRecallResult>(\n results: readonly R[],\n options: ReorderRecallResultsOptions = {},\n): ReorderRecallResultsOutcome<R> {\n const emptyReport: MmrDiversityReport = {\n considered: 0,\n kept: 0,\n headReorderCount: 0,\n avgPairwiseSimBefore: 0,\n avgPairwiseSimAfter: 0,\n };\n const lambda = clampLambda(options.lambda);\n\n if (!Array.isArray(results) || results.length === 0) {\n return { reordered: [], diversity: emptyReport, lambda };\n }\n if (results.length < 2) {\n // Single-element input: MMR is a trivial no-op but the diversity report\n // must still reflect the real pool size so external callers see\n // `considered=1 kept=1` rather than the `0/0` sentinel used for the\n // empty case. This is also the exact path the orchestrator short-circuits\n // past, but the helper is a public export and external callers cannot\n // rely on that invariant.\n return {\n reordered: [results[0]!],\n diversity: {\n considered: 1,\n kept: 1,\n headReorderCount: 0,\n avgPairwiseSimBefore: 0,\n avgPairwiseSimAfter: 0,\n },\n lambda,\n };\n }\n\n const topN = clampPositiveInt(options.topN, DEFAULT_TOP_N);\n\n // Build a per-result *unique* key so distinct results with colliding\n // docids or paths are never silently collapsed by id-based lookups.\n // Keys are always suffixed with the original input index so two results\n // that share the same `path` (or share the same `docid` when `path` is\n // empty) still get distinct identities.\n const candidates: MmrCandidate[] = results.map((r, index) => ({\n id: makeRecallKey(r, index),\n content: r.snippet ?? \"\",\n score: typeof r.score === \"number\" ? r.score : 0,\n embedding: null,\n }));\n // Index lookup by id so we can map MMR-selected candidates back to their\n // *original* position (and therefore their original `candidates[i]` object,\n // which preserves its `id` across the reorder). Reusing those original\n // candidate objects in the diversity comparison means\n // `headReorderCount` works correctly even when two results in the input\n // share the same base key: a swap at the same head position shows up\n // because their original-index-suffixed ids still differ.\n const indexById = new Map<string, number>();\n for (let i = 0; i < candidates.length; i += 1) {\n indexById.set(candidates[i]!.id, i);\n }\n\n const selectedMmr = applyMmrToCandidates({\n candidates,\n lambda,\n topN,\n budget: results.length,\n });\n\n const reordered: R[] = [];\n // Parallel array of the *original* candidate objects in the new (post-MMR)\n // order. Used for a faithful diversity comparison that preserves each\n // candidate's original identity.\n const reorderedCandidates: MmrCandidate[] = [];\n const seen = new Set<string>();\n for (const c of selectedMmr) {\n if (seen.has(c.id)) continue;\n const origIndex = indexById.get(c.id);\n if (origIndex === undefined) continue;\n seen.add(c.id);\n reordered.push(results[origIndex]!);\n reorderedCandidates.push(candidates[origIndex]!);\n }\n // Safety: append any candidates MMR did not select so nothing is dropped.\n if (reordered.length < results.length) {\n for (let i = 0; i < results.length; i += 1) {\n const origCandidate = candidates[i]!;\n if (seen.has(origCandidate.id)) continue;\n seen.add(origCandidate.id);\n reordered.push(results[i]!);\n reorderedCandidates.push(origCandidate);\n }\n }\n\n const diversity = summarizeMmrDiversity(\n candidates,\n reorderedCandidates,\n options.diversitySampleSize,\n );\n\n return { reordered, diversity, lambda };\n}\n\nfunction makeRecallKey(r: MmrRecallResult, index: number): string {\n const baseKey = r.path || r.docid || \"\";\n return `${baseKey}::${index}`;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/recall-mmr.ts"],"sourcesContent":["/**\n * Maximal Marginal Relevance (MMR) re-selection for recall candidates.\n *\n * After the reranker produces its ordered candidate list, we run an MMR pass\n * over the top N candidates (per-section) so that a cluster of near-duplicate\n * high-scoring facts cannot dominate the injected context.\n *\n * MMR(d) = λ * sim(d, query) − (1 − λ) * max_{d' ∈ selected} sim(d, d')\n *\n * - λ defaults to 0.7 (tilted toward relevance, with meaningful diversity).\n * - Similarity uses cosine over pre-computed embeddings when available, and\n * falls back to Jaccard over normalized tokens (lowercased alphanumerics)\n * when embeddings are missing.\n * - Per-section application is the caller's responsibility: pass each\n * section's ordered candidate slice independently so one cluster in one\n * section cannot starve another section.\n *\n * Pure, deterministic, no IO. Input arrays are never mutated.\n */\n\n/** Minimal candidate shape used by MMR. Callers may wrap their own records. */\nexport interface MmrCandidate {\n /** Stable identifier for the candidate. Only used for tie-breaking. */\n id: string;\n /** Text content used for the Jaccard similarity fallback. */\n content: string;\n /**\n * Relevance score from the upstream ranker (e.g. rerank score or RRF).\n * Used as the `sim(d, query)` term when no query embedding is available.\n */\n score: number;\n /** Optional pre-computed embedding vector for cosine similarity. */\n embedding?: readonly number[] | null;\n}\n\nexport interface ApplyMmrOptions<C extends MmrCandidate> {\n /** Ordered candidate list (most relevant first). */\n candidates: readonly C[];\n /** Optional query embedding. If provided and candidates carry embeddings,\n * relevance is measured by cosine similarity to the query. Otherwise\n * candidate `score` is normalized and used. */\n queryEmbedding?: readonly number[] | null;\n /** λ ∈ [0, 1]. 1 = pure relevance, 0 = pure diversity. Default 0.7. */\n lambda?: number;\n /** Apply MMR only over the top N candidates. Default 40. */\n topN?: number;\n /** Maximum number of candidates to select. Default = candidates length. */\n budget?: number;\n}\n\nexport interface MmrDiversityReport {\n /**\n * Total number of candidates MMR considered (the full input pool, pre-MMR).\n * Previously this mirrored `kept` and was therefore uninformative; it now\n * reflects the true pool size so `kept/considered` logs carry signal even\n * though MMR is reorder-only.\n */\n considered: number;\n /**\n * Number of candidates present in the MMR output. With the current\n * orchestrator pipeline MMR is reorder-only (no drops), so this is the\n * same as `considered`. It's still reported separately so a future\n * drop-mode MMR can distinguish them without another schema change.\n */\n kept: number;\n /**\n * Head-of-list positions whose candidate identity changed between the\n * pre-MMR and post-MMR slices. This is the *actionable* diversity signal:\n * it tells the caller how many of the top `sampleSize` results MMR\n * promoted or demoted. Zero means MMR had no head-of-list effect; a value\n * greater than zero means at least one diverse candidate was swapped in.\n */\n headReorderCount: number;\n /** Average pairwise similarity of the head-of-list input slice (pre-MMR). */\n avgPairwiseSimBefore: number;\n /** Average pairwise similarity of the head-of-list MMR output slice. */\n avgPairwiseSimAfter: number;\n}\n\nexport const DEFAULT_LAMBDA = 0.7;\nexport const DEFAULT_TOP_N = 40;\n/**\n * Default number of head-of-list candidates compared by\n * {@link summarizeMmrDiversity}. Small on purpose: we want to measure whether\n * MMR actually *changed* the head of the list. Comparing the full top-N slice\n * is meaningless when `budget >= candidates.length` because both slices\n * contain the same set (just reordered), making pairwise-similarity\n * order-independent and identical before vs after.\n */\nconst DEFAULT_DIVERSITY_SAMPLE_SIZE = 10;\n\n/**\n * Pure MMR re-selection over an ordered candidate list.\n *\n * Returns a new array — the input is never mutated. When `candidates.length`\n * is `<= 1` or `budget <= 0`, a defensive copy is returned as a no-op.\n */\nexport function applyMmrToCandidates<C extends MmrCandidate>(\n opts: ApplyMmrOptions<C>,\n): C[] {\n const candidates = Array.isArray(opts.candidates) ? opts.candidates : [];\n if (candidates.length === 0) return [];\n\n const lambda = clampLambda(opts.lambda);\n const topN = clampPositiveInt(opts.topN, DEFAULT_TOP_N);\n const budget = clampPositiveInt(opts.budget, candidates.length);\n\n if (budget <= 0) return [];\n if (candidates.length === 1) return [candidates[0]!];\n\n // Only reorder the top-N slice; anything past it keeps its original position\n // appended at the end (but will not be selected unless budget > topN).\n const pool = candidates.slice(0, topN);\n const tail = candidates.slice(topN);\n\n // Relevance scores as `sim(d, query)`. Prefer cosine to the query embedding\n // when we can compute it; otherwise fall back to the candidate's own score\n // normalized into [0, 1] across the pool.\n const relevance = computeRelevanceScores(pool, opts.queryEmbedding);\n\n // Pre-compute pairwise candidate-candidate similarity lazily as needed.\n const pairSim = new Map<string, number>();\n const pairKey = (i: number, j: number): string =>\n i < j ? `${i}:${j}` : `${j}:${i}`;\n const sim = (i: number, j: number): number => {\n if (i === j) return 1;\n const key = pairKey(i, j);\n const cached = pairSim.get(key);\n if (cached !== undefined) return cached;\n const a = pool[i]!;\n const b = pool[j]!;\n const s = similarity(a, b);\n pairSim.set(key, s);\n return s;\n };\n\n const selectedIdx: number[] = [];\n const remaining = new Set<number>();\n for (let i = 0; i < pool.length; i += 1) remaining.add(i);\n\n while (selectedIdx.length < budget && remaining.size > 0) {\n let bestIdx = -1;\n let bestMmr = Number.NEGATIVE_INFINITY;\n for (const idx of remaining) {\n const rel = relevance[idx] ?? 0;\n let maxSimToSelected = 0;\n if (selectedIdx.length > 0) {\n for (const s of selectedIdx) {\n const pairwise = sim(idx, s);\n if (pairwise > maxSimToSelected) maxSimToSelected = pairwise;\n }\n }\n const mmr = lambda * rel - (1 - lambda) * maxSimToSelected;\n if (\n mmr > bestMmr ||\n // Stable tie-breaker: prefer the earlier original position.\n (mmr === bestMmr && (bestIdx < 0 || idx < bestIdx))\n ) {\n bestMmr = mmr;\n bestIdx = idx;\n }\n }\n if (bestIdx < 0) break;\n selectedIdx.push(bestIdx);\n remaining.delete(bestIdx);\n }\n\n const selected: C[] = selectedIdx.map((i) => pool[i]!);\n\n // If the caller set a budget larger than topN, append tail candidates in\n // their original order until budget is filled. This keeps MMR scoped to the\n // top-N slice while still respecting the caller's requested size.\n if (selected.length < budget && tail.length > 0) {\n for (const c of tail) {\n if (selected.length >= budget) break;\n selected.push(c);\n }\n }\n\n return selected;\n}\n\n/**\n * Summarize how much MMR reshuffled the head of the candidate list, for\n * logging. Optional — callers can skip this if they don't care about metrics.\n *\n * IMPORTANT: `before` should be the score-ordered input (the same ordering the\n * upstream reranker emitted, *not* the MMR output), and `after` should be the\n * MMR-reordered list. Both are truncated to `sampleSize` before their pairwise\n * similarity is averaged.\n *\n * The sample size intentionally defaults to a small number\n * ({@link DEFAULT_DIVERSITY_SAMPLE_SIZE}) so that when the caller uses\n * `budget >= candidates.length` (i.e. MMR only reorders without dropping), the\n * head-of-list comparison still reflects whether MMR promoted diverse\n * candidates. Passing a sample size `>= candidates.length` in that situation\n * makes `avgPairwiseSimBefore` and `avgPairwiseSimAfter` trivially equal\n * because pairwise similarity is order-independent.\n */\nexport function summarizeMmrDiversity<C extends MmrCandidate>(\n before: readonly C[],\n after: readonly C[],\n sampleSize: number = DEFAULT_DIVERSITY_SAMPLE_SIZE,\n): MmrDiversityReport {\n const n = clampPositiveInt(sampleSize, DEFAULT_DIVERSITY_SAMPLE_SIZE);\n const beforeSlice = before.slice(0, n);\n const afterSlice = after.slice(0, n);\n // Count how many head-of-list positions MMR actually changed. A zero value\n // means MMR left the head untouched; a positive value is the actionable\n // \"MMR promoted N diverse candidates\" signal the previous metric lacked.\n let headReorderCount = 0;\n const compareLength = Math.min(beforeSlice.length, afterSlice.length);\n for (let i = 0; i < compareLength; i += 1) {\n if (beforeSlice[i]!.id !== afterSlice[i]!.id) headReorderCount += 1;\n }\n return {\n considered: before.length,\n kept: after.length,\n headReorderCount,\n avgPairwiseSimBefore: averagePairwiseSimilarity(beforeSlice),\n avgPairwiseSimAfter: averagePairwiseSimilarity(afterSlice),\n };\n}\n\n// -----------------------------------------------------------------------------\n// Internals\n// -----------------------------------------------------------------------------\n\nfunction clampLambda(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return DEFAULT_LAMBDA;\n if (value < 0) return 0;\n if (value > 1) return 1;\n return value;\n}\n\nfunction clampPositiveInt(\n value: number | undefined,\n fallback: number,\n): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n if (value <= 0) return 0;\n return Math.floor(value);\n}\n\nfunction computeRelevanceScores<C extends MmrCandidate>(\n pool: readonly C[],\n queryEmbedding: readonly number[] | null | undefined,\n): number[] {\n // If we have a query embedding, use cosine against each candidate embedding\n // where possible. Candidates without embeddings fall back to normalized score.\n const canUseQueryEmbedding =\n Array.isArray(queryEmbedding) && queryEmbedding.length > 0;\n\n if (canUseQueryEmbedding) {\n const scores: number[] = [];\n for (const c of pool) {\n if (Array.isArray(c.embedding) && c.embedding.length > 0) {\n scores.push(cosineSimilarity(queryEmbedding!, c.embedding));\n } else {\n // Fall back to the upstream relevance score for this one candidate.\n scores.push(normalizeFinite(c.score));\n }\n }\n return normalizeVector(scores);\n }\n\n // No query embedding — use normalized candidate scores.\n const raw = pool.map((c) => normalizeFinite(c.score));\n return normalizeVector(raw);\n}\n\nfunction similarity<C extends MmrCandidate>(a: C, b: C): number {\n if (\n Array.isArray(a.embedding) &&\n a.embedding.length > 0 &&\n Array.isArray(b.embedding) &&\n b.embedding.length > 0 &&\n a.embedding.length === b.embedding.length\n ) {\n return cosineSimilarity(a.embedding, b.embedding);\n }\n return jaccardSimilarity(a.content ?? \"\", b.content ?? \"\");\n}\n\nfunction cosineSimilarity(\n a: readonly number[],\n b: readonly number[],\n): number {\n if (a.length === 0 || b.length === 0) return 0;\n const len = Math.min(a.length, b.length);\n let dot = 0;\n let na = 0;\n let nb = 0;\n for (let i = 0; i < len; i += 1) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n dot += av * bv;\n na += av * av;\n nb += bv * bv;\n }\n if (na === 0 || nb === 0) return 0;\n const cos = dot / (Math.sqrt(na) * Math.sqrt(nb));\n // Clamp to [0, 1]. Negative cosines (opposite directions) are treated as 0\n // for MMR purposes — two embeddings pointing opposite ways should be\n // \"maximally diverse\", not discouraged further.\n if (cos < 0) return 0;\n if (cos > 1) return 1;\n return cos;\n}\n\nexport function normalizeTokens(text: string): Set<string> {\n if (!text) return new Set();\n // Unicode-aware normalization. We lowercase and replace any character that\n // is NOT a Unicode letter or number with a space, then split on whitespace.\n // This preserves non-Latin scripts (Cyrillic, Greek, Hebrew, Arabic, etc.)\n // so the Jaccard fallback still detects near-duplicates in multilingual\n // snippets. Without this fix, `[^a-z0-9]+` strips all non-ASCII and two\n // identical Chinese/Japanese/Cyrillic snippets both collapse to the empty\n // set, returning similarity 0 and letting duplicates dominate recall.\n const cleaned = text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, \" \")\n .trim();\n if (cleaned.length === 0) {\n // CJK fallback: scripts like Chinese/Japanese/Korean do not use word\n // breaks, so after the Unicode strip the above split-on-whitespace yields\n // one big token. The Latin-style split is a bad match for these scripts;\n // use per-codepoint character tokens instead, which approximates a\n // unigram shingle and is accurate enough for near-duplicate detection.\n const chars = new Set<string>();\n for (const ch of text.toLowerCase()) {\n if (/\\s/.test(ch)) continue;\n chars.add(ch);\n }\n return chars;\n }\n const tokens = new Set<string>();\n for (const token of cleaned.split(/\\s+/)) {\n if (!token) continue;\n // A single \"token\" that is actually a run of CJK codepoints (no spaces in\n // the source) should still be split into per-character tokens so the\n // Jaccard overlap works. Latin/Cyrillic/etc. keep their word-level tokens.\n if (token.length >= 2 && hasUnsegmentableScript(token)) {\n for (const ch of token) tokens.add(ch);\n } else {\n tokens.add(token);\n }\n }\n return tokens;\n}\n\n/**\n * Returns true when `token` contains at least one codepoint in a script that\n * does not use whitespace for word segmentation (CJK Unified Ideographs,\n * Hiragana, Katakana, Hangul). These are tokenized per-character so Jaccard\n * similarity can still detect near-duplicate snippets.\n */\nfunction hasUnsegmentableScript(token: string): boolean {\n return /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u.test(\n token,\n );\n}\n\nfunction jaccardSimilarity(a: string, b: string): number {\n const ta = normalizeTokens(a);\n const tb = normalizeTokens(b);\n if (ta.size === 0 && tb.size === 0) return 0;\n let intersection = 0;\n for (const t of ta) if (tb.has(t)) intersection += 1;\n const union = ta.size + tb.size - intersection;\n if (union === 0) return 0;\n return intersection / union;\n}\n\nfunction normalizeFinite(value: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n return value;\n}\n\nfunction normalizeVector(values: number[]): number[] {\n if (values.length === 0) return values;\n // Intentionally *not* min-max normalized. Min-max maps the lowest score to\n // 0 and the highest to 1, which amplifies tiny relevance gaps (e.g. a tight\n // reranker cluster like [0.93, 0.94, 0.95]) into the full [0, 1] range.\n // That lets a near-duplicate at the top permanently beat a diverse\n // candidate at the bottom because `lambda * 0 - (1 - lambda) * 0 = 0` is\n // always worse than `lambda * 1 - (1 - lambda) * maxSim` for any\n // maxSim < lambda / (1 - lambda). MMR is supposed to escape exactly that\n // scenario; min-max defeats it.\n //\n // Instead we preserve the relative score gaps by scaling only if the\n // scores leave the MMR-friendly `[0, 1]` range. Negative or out-of-range\n // scores are clamped to `[0, 1]` by dividing by the max absolute value; if\n // everything is already inside `[0, 1]`, we pass through untouched so\n // tight clusters stay tight and MMR can promote a diverse candidate from\n // the bottom of the cluster.\n let max = 0;\n let min = Number.POSITIVE_INFINITY;\n for (const v of values) {\n if (!Number.isFinite(v)) continue;\n const a = Math.abs(v);\n if (a > max) max = a;\n if (v < min) min = v;\n }\n if (!Number.isFinite(min)) {\n return values.map(() => 0);\n }\n if (max === 0) {\n // All scores are zero — give everyone 1 so diversity fully drives\n // selection (otherwise every candidate has `lambda * 0 = 0` and the\n // first-found wins trivially, hiding any diversity benefit).\n return values.map(() => 1);\n }\n // If scores already live in [0, 1], pass them through so tight clusters\n // (e.g. [0.93, 0.94, 0.95]) stay tight and the (1 - lambda) * maxSim term\n // can actually outweigh a 0.01 relevance gap, which is the whole point of\n // MMR. Otherwise divide by `max` to bring the top score to 1 while\n // preserving *relative* gaps (e.g. [100, 200, 300] -> [0.33, 0.67, 1.0]).\n if (min >= 0 && max <= 1) {\n return values.map((v) =>\n Number.isFinite(v) ? (v < 0 ? 0 : v > 1 ? 1 : v) : 0,\n );\n }\n return values.map((v) => {\n if (!Number.isFinite(v)) return 0;\n const scaled = v / max;\n if (scaled < 0) return 0;\n if (scaled > 1) return 1;\n return scaled;\n });\n}\n\nfunction averagePairwiseSimilarity<C extends MmrCandidate>(\n candidates: readonly C[],\n): number {\n if (candidates.length < 2) return 0;\n let sum = 0;\n let count = 0;\n for (let i = 0; i < candidates.length; i += 1) {\n for (let j = i + 1; j < candidates.length; j += 1) {\n sum += similarity(candidates[i]!, candidates[j]!);\n count += 1;\n }\n }\n if (count === 0) return 0;\n return sum / count;\n}\n\n// -----------------------------------------------------------------------------\n// Orchestration helper: MMR for recall results keyed by path-first\n// -----------------------------------------------------------------------------\n\n/**\n * Minimum shape the recall-MMR orchestration helper expects from a result.\n * Any richer result type (e.g. {@link QmdSearchResult}) satisfies this.\n */\nexport interface MmrRecallResult {\n readonly docid?: string;\n readonly path?: string;\n readonly snippet?: string;\n readonly score?: number;\n /**\n * Effective relevance carried forward by the rerank stage that last\n * adjusted the result. Preferred over `score` for MMR's relevance term.\n */\n readonly effectiveScore?: number;\n}\n\nexport interface ReorderRecallResultsOptions {\n readonly lambda?: number;\n readonly topN?: number;\n /**\n * Head-of-list sample size used by the diversity metric. Defaults to\n * {@link DEFAULT_DIVERSITY_SAMPLE_SIZE}. Intentionally small so the metric\n * reflects head-of-list changes even when `budget >= results.length`.\n */\n readonly diversitySampleSize?: number;\n}\n\nexport interface ReorderRecallResultsOutcome<R extends MmrRecallResult> {\n readonly reordered: R[];\n readonly diversity: MmrDiversityReport;\n readonly lambda: number;\n}\n\n/**\n * Apply MMR to an ordered list of recall results and return the reordered\n * list plus a head-of-list diversity report.\n *\n * This helper is the single source of truth for the orchestrator's\n * per-section MMR pass. It is pure and deterministic so it can be unit\n * tested without constructing an Orchestrator.\n *\n * Key invariants:\n * 1. **No silent drops.** Candidates are keyed by a stable unique key derived\n * from `path` first, falling back to `docid`, and always suffixed with the\n * candidate's original index. Two results that share a basename-style\n * docid but differ in path are treated as distinct candidates and both\n * survive the reorder.\n * 2. **No mutation.** The input array is never mutated; a new array is\n * returned.\n * 3. **Diversity metric is meaningful.** The report compares the *head of\n * list* before and after MMR using a small sample size, so it reflects\n * whether MMR promoted diverse candidates even when\n * `budget >= results.length`.\n */\nexport function reorderRecallResultsWithMmr<R extends MmrRecallResult>(\n results: readonly R[],\n options: ReorderRecallResultsOptions = {},\n): ReorderRecallResultsOutcome<R> {\n const emptyReport: MmrDiversityReport = {\n considered: 0,\n kept: 0,\n headReorderCount: 0,\n avgPairwiseSimBefore: 0,\n avgPairwiseSimAfter: 0,\n };\n const lambda = clampLambda(options.lambda);\n\n if (!Array.isArray(results) || results.length === 0) {\n return { reordered: [], diversity: emptyReport, lambda };\n }\n if (results.length < 2) {\n // Single-element input: MMR is a trivial no-op but the diversity report\n // must still reflect the real pool size so external callers see\n // `considered=1 kept=1` rather than the `0/0` sentinel used for the\n // empty case. This is also the exact path the orchestrator short-circuits\n // past, but the helper is a public export and external callers cannot\n // rely on that invariant.\n return {\n reordered: [results[0]!],\n diversity: {\n considered: 1,\n kept: 1,\n headReorderCount: 0,\n avgPairwiseSimBefore: 0,\n avgPairwiseSimAfter: 0,\n },\n lambda,\n };\n }\n\n const topN = clampPositiveInt(options.topN, DEFAULT_TOP_N);\n\n // Build a per-result *unique* key so distinct results with colliding\n // docids or paths are never silently collapsed by id-based lookups.\n // Keys are always suffixed with the original input index so two results\n // that share the same `path` (or share the same `docid` when `path` is\n // empty) still get distinct identities.\n const candidates: MmrCandidate[] = results.map((r, index) => ({\n id: makeRecallKey(r, index),\n content: r.snippet ?? \"\",\n score: effectiveRelevance(r),\n embedding: null,\n }));\n // Index lookup by id so we can map MMR-selected candidates back to their\n // *original* position (and therefore their original `candidates[i]` object,\n // which preserves its `id` across the reorder). Reusing those original\n // candidate objects in the diversity comparison means\n // `headReorderCount` works correctly even when two results in the input\n // share the same base key: a swap at the same head position shows up\n // because their original-index-suffixed ids still differ.\n const indexById = new Map<string, number>();\n for (let i = 0; i < candidates.length; i += 1) {\n indexById.set(candidates[i]!.id, i);\n }\n\n const selectedMmr = applyMmrToCandidates({\n candidates,\n lambda,\n topN,\n budget: results.length,\n });\n\n const reordered: R[] = [];\n // Parallel array of the *original* candidate objects in the new (post-MMR)\n // order. Used for a faithful diversity comparison that preserves each\n // candidate's original identity.\n const reorderedCandidates: MmrCandidate[] = [];\n const seen = new Set<string>();\n for (const c of selectedMmr) {\n if (seen.has(c.id)) continue;\n const origIndex = indexById.get(c.id);\n if (origIndex === undefined) continue;\n seen.add(c.id);\n reordered.push(results[origIndex]!);\n reorderedCandidates.push(candidates[origIndex]!);\n }\n // Safety: append any candidates MMR did not select so nothing is dropped.\n if (reordered.length < results.length) {\n for (let i = 0; i < results.length; i += 1) {\n const origCandidate = candidates[i]!;\n if (seen.has(origCandidate.id)) continue;\n seen.add(origCandidate.id);\n reordered.push(results[i]!);\n reorderedCandidates.push(origCandidate);\n }\n }\n\n const diversity = summarizeMmrDiversity(\n candidates,\n reorderedCandidates,\n options.diversitySampleSize,\n );\n\n return { reordered, diversity, lambda };\n}\n\n/**\n * Relevance for MMR's `sim(d, query)` term: the effective relevance an\n * upstream rerank stage carried forward, else the raw retrieval score.\n */\nfunction effectiveRelevance(r: MmrRecallResult): number {\n if (typeof r.effectiveScore === \"number\" && Number.isFinite(r.effectiveScore)) {\n return r.effectiveScore;\n }\n return typeof r.score === \"number\" ? r.score : 0;\n}\n\nfunction makeRecallKey(r: MmrRecallResult, index: number): string {\n const baseKey = r.path || r.docid || \"\";\n return `${baseKey}::${index}`;\n}\n"],"mappings":"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","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  getOperation,
4
4
  operationRequiresAuthorizedNamespace,
5
5
  operationUsesPrincipalNamespace
6
- } from "./chunk-GFWRXPF6.js";
6
+ } from "./chunk-CA2R2AD4.js";
7
7
  import {
8
8
  assertOperationAuthorizationAllowed
9
9
  } from "./chunk-IG747LRN.js";
@@ -60,4 +60,4 @@ export {
60
60
  authorizationProbeNamespaces,
61
61
  authorizationProbeRequiresPrincipalNamespace
62
62
  };
63
- //# sourceMappingURL=chunk-YR4COAEC.js.map
63
+ //# sourceMappingURL=chunk-INBB7D3V.js.map