@remnic/core 1.1.0 → 1.1.2

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 (308) hide show
  1. package/dist/access-audit.d.ts +56 -0
  2. package/dist/access-audit.js +9 -0
  3. package/dist/access-cli.js +70 -53
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +16 -9
  6. package/dist/access-http.js +26 -18
  7. package/dist/access-mcp.d.ts +16 -9
  8. package/dist/access-mcp.js +30 -8
  9. package/dist/access-schema.d.ts +124 -33
  10. package/dist/access-schema.js +5 -1
  11. package/dist/{access-service-HmO1Trrx.d.ts → access-service-Br8ZydTK.d.ts} +158 -63
  12. package/dist/access-service.d.ts +13 -6
  13. package/dist/access-service.js +23 -14
  14. package/dist/bootstrap.d.ts +6 -3
  15. package/dist/briefing.d.ts +1 -0
  16. package/dist/briefing.js +8 -6
  17. package/dist/buffer-surprise-report.d.ts +70 -0
  18. package/dist/buffer-surprise-report.js +7 -0
  19. package/dist/buffer-surprise-report.js.map +1 -0
  20. package/dist/buffer-surprise.d.ts +98 -0
  21. package/dist/buffer-surprise.js +11 -0
  22. package/dist/buffer-surprise.js.map +1 -0
  23. package/dist/buffer.d.ts +100 -2
  24. package/dist/buffer.js +1 -1
  25. package/dist/calibration.js +6 -6
  26. package/dist/causal-behavior.js +4 -4
  27. package/dist/causal-chain.js +2 -2
  28. package/dist/causal-consolidation.js +19 -18
  29. package/dist/causal-consolidation.js.map +1 -1
  30. package/dist/causal-retrieval.js +4 -4
  31. package/dist/causal-trajectory.js +1 -1
  32. package/dist/{chunk-QNJMBKFK.js → chunk-2LGMW3DJ.js} +3 -2
  33. package/dist/chunk-2LGMW3DJ.js.map +1 -0
  34. package/dist/{chunk-QDYXG4CS.js → chunk-3FPTCC3Z.js} +4 -3
  35. package/dist/chunk-3FPTCC3Z.js.map +1 -0
  36. package/dist/chunk-3GPTTA4J.js +57 -0
  37. package/dist/chunk-3GPTTA4J.js.map +1 -0
  38. package/dist/{chunk-ITRLGI2T.js → chunk-3OGMS3PE.js} +2 -2
  39. package/dist/{chunk-DEPL3635.js → chunk-3YGHKTBF.js} +1446 -196
  40. package/dist/chunk-3YGHKTBF.js.map +1 -0
  41. package/dist/{chunk-BLKTA7MM.js → chunk-4HQS2HPX.js} +54 -21
  42. package/dist/chunk-4HQS2HPX.js.map +1 -0
  43. package/dist/chunk-54V4BZWP.js +139 -0
  44. package/dist/chunk-54V4BZWP.js.map +1 -0
  45. package/dist/chunk-5JRF2PZA.js +67 -0
  46. package/dist/chunk-5JRF2PZA.js.map +1 -0
  47. package/dist/chunk-64NJRYU2.js +332 -0
  48. package/dist/chunk-64NJRYU2.js.map +1 -0
  49. package/dist/{chunk-OIT5QGG4.js → chunk-6AUUAZEX.js} +72 -2
  50. package/dist/chunk-6AUUAZEX.js.map +1 -0
  51. package/dist/{chunk-3QHL5ABG.js → chunk-6YJHX2DL.js} +191 -10
  52. package/dist/chunk-6YJHX2DL.js.map +1 -0
  53. package/dist/chunk-AJU4PJGY.js +126 -0
  54. package/dist/chunk-AJU4PJGY.js.map +1 -0
  55. package/dist/chunk-ASAITVLA.js +64 -0
  56. package/dist/chunk-ASAITVLA.js.map +1 -0
  57. package/dist/{chunk-44ICJRF3.js → chunk-AYXIPSZO.js} +5 -5
  58. package/dist/{chunk-MBJHSA7F.js → chunk-BECYBZLX.js} +265 -20
  59. package/dist/chunk-BECYBZLX.js.map +1 -0
  60. package/dist/chunk-C4SQJZAF.js +486 -0
  61. package/dist/chunk-C4SQJZAF.js.map +1 -0
  62. package/dist/{chunk-6UJ47TVX.js → chunk-CUPFXL3J.js} +2 -2
  63. package/dist/chunk-DF3RVK3X.js +119 -0
  64. package/dist/chunk-DF3RVK3X.js.map +1 -0
  65. package/dist/{chunk-N42IWANG.js → chunk-DG6YMRDC.js} +3 -3
  66. package/dist/chunk-DGVM5SFL.js +69 -0
  67. package/dist/chunk-DGVM5SFL.js.map +1 -0
  68. package/dist/{chunk-3SV6CQHO.js → chunk-DIXB44VE.js} +102 -66
  69. package/dist/chunk-DIXB44VE.js.map +1 -0
  70. package/dist/chunk-EIR5VLIH.js +90 -0
  71. package/dist/chunk-EIR5VLIH.js.map +1 -0
  72. package/dist/{chunk-GV6NLQ4X.js → chunk-F5VP6YCB.js} +374 -16
  73. package/dist/chunk-F5VP6YCB.js.map +1 -0
  74. package/dist/{chunk-6ZH4TU6I.js → chunk-FAAFWE4G.js} +2 -1
  75. package/dist/chunk-FAAFWE4G.js.map +1 -0
  76. package/dist/{chunk-7WQ6SLIE.js → chunk-FVA6TGI3.js} +2 -2
  77. package/dist/{chunk-PAORGQRI.js → chunk-GA5P7RST.js} +37 -23
  78. package/dist/chunk-GA5P7RST.js.map +1 -0
  79. package/dist/chunk-GDFS42HT.js +206 -0
  80. package/dist/chunk-GDFS42HT.js.map +1 -0
  81. package/dist/chunk-IISBCCWR.js +52 -0
  82. package/dist/chunk-IISBCCWR.js.map +1 -0
  83. package/dist/chunk-JBMSGZEQ.js +441 -0
  84. package/dist/chunk-JBMSGZEQ.js.map +1 -0
  85. package/dist/{chunk-J4IYOZZ5.js → chunk-JXS5PDQ7.js} +3 -1
  86. package/dist/chunk-JXS5PDQ7.js.map +1 -0
  87. package/dist/chunk-KVBLZUKV.js +173 -0
  88. package/dist/chunk-KVBLZUKV.js.map +1 -0
  89. package/dist/{chunk-4LACOVZX.js → chunk-L7IXWRYE.js} +10 -5
  90. package/dist/chunk-L7IXWRYE.js.map +1 -0
  91. package/dist/chunk-LBLXEFWK.js +51 -0
  92. package/dist/chunk-LBLXEFWK.js.map +1 -0
  93. package/dist/{chunk-WBSAYXVI.js → chunk-LOIMBRDE.js} +201 -45
  94. package/dist/chunk-LOIMBRDE.js.map +1 -0
  95. package/dist/{chunk-3WHVNEN7.js → chunk-LTCGGW2D.js} +1 -1
  96. package/dist/chunk-LTCGGW2D.js.map +1 -0
  97. package/dist/{chunk-ZVBB3T7V.js → chunk-NBVAS5MT.js} +25 -23
  98. package/dist/chunk-NBVAS5MT.js.map +1 -0
  99. package/dist/{chunk-UEYA6UC7.js → chunk-NZLQTHS5.js} +25 -2
  100. package/dist/chunk-NZLQTHS5.js.map +1 -0
  101. package/dist/{chunk-NQEVYWX6.js → chunk-OC5OXUQ4.js} +211 -7
  102. package/dist/chunk-OC5OXUQ4.js.map +1 -0
  103. package/dist/{chunk-LK6SGL53.js → chunk-OR64ZGRZ.js} +3 -2
  104. package/dist/chunk-OR64ZGRZ.js.map +1 -0
  105. package/dist/{chunk-SYUK3VLY.js → chunk-PVICZTKG.js} +117 -5
  106. package/dist/chunk-PVICZTKG.js.map +1 -0
  107. package/dist/chunk-PVPWZSSI.js +37 -0
  108. package/dist/chunk-PVPWZSSI.js.map +1 -0
  109. package/dist/{chunk-JL2PU6AI.js → chunk-R2XRID2N.js} +2 -2
  110. package/dist/{chunk-4NRAJUDS.js → chunk-RBBWYEFJ.js} +1 -1
  111. package/dist/chunk-RFYAYKTD.js +146 -0
  112. package/dist/chunk-RFYAYKTD.js.map +1 -0
  113. package/dist/chunk-SOBJ6NEY.js +18 -0
  114. package/dist/chunk-SOBJ6NEY.js.map +1 -0
  115. package/dist/{chunk-JIU55F3X.js → chunk-SPI27QT6.js} +2 -2
  116. package/dist/{chunk-MVTHXUBX.js → chunk-STGWEHYR.js} +479 -20
  117. package/dist/chunk-STGWEHYR.js.map +1 -0
  118. package/dist/{chunk-6LX5ORAS.js → chunk-TMYO7B5P.js} +4 -4
  119. package/dist/chunk-TVVEYCNW.js +65 -0
  120. package/dist/chunk-TVVEYCNW.js.map +1 -0
  121. package/dist/chunk-ULYOGL6R.js +322 -0
  122. package/dist/chunk-ULYOGL6R.js.map +1 -0
  123. package/dist/{chunk-37UIFYWO.js → chunk-UWB5LMWY.js} +108 -9
  124. package/dist/chunk-UWB5LMWY.js.map +1 -0
  125. package/dist/{chunk-47UU5PU2.js → chunk-VBVG2M5G.js} +18 -3
  126. package/dist/chunk-VBVG2M5G.js.map +1 -0
  127. package/dist/{chunk-7ECD5ATE.js → chunk-VDX363PS.js} +2 -2
  128. package/dist/{chunk-O5ETUNBT.js → chunk-VTU2B4VF.js} +7 -3
  129. package/dist/chunk-VTU2B4VF.js.map +1 -0
  130. package/dist/{chunk-MTLYEMJB.js → chunk-WCLICCGB.js} +18 -3
  131. package/dist/chunk-WCLICCGB.js.map +1 -0
  132. package/dist/chunk-X6GF3FX2.js +26 -0
  133. package/dist/chunk-X6GF3FX2.js.map +1 -0
  134. package/dist/{chunk-3QFQGRHO.js → chunk-XMHBH5H6.js} +4 -4
  135. package/dist/{chunk-DHHP2Z4X.js → chunk-XXVWLXSG.js} +2 -2
  136. package/dist/{chunk-XZ2TIKGC.js → chunk-Y7R2XJ5Q.js} +25 -9
  137. package/dist/chunk-Y7R2XJ5Q.js.map +1 -0
  138. package/dist/{chunk-ALXMCZEU.js → chunk-Z2E7VW55.js} +6 -3
  139. package/dist/chunk-Z2E7VW55.js.map +1 -0
  140. package/dist/chunk-ZAIM4TUE.js +488 -0
  141. package/dist/chunk-ZAIM4TUE.js.map +1 -0
  142. package/dist/chunk-ZZTOURJI.js +91 -0
  143. package/dist/chunk-ZZTOURJI.js.map +1 -0
  144. package/dist/{cli-BneVIEvh.d.ts → cli-BkeRaYfk.d.ts} +2 -2
  145. package/dist/cli.d.ts +13 -6
  146. package/dist/cli.js +42 -31
  147. package/dist/config.js +2 -2
  148. package/dist/consolidation-operator.d.ts +41 -0
  149. package/dist/consolidation-operator.js +11 -0
  150. package/dist/consolidation-operator.js.map +1 -0
  151. package/dist/consolidation-provenance-check.d.ts +68 -0
  152. package/dist/consolidation-provenance-check.js +9 -0
  153. package/dist/consolidation-provenance-check.js.map +1 -0
  154. package/dist/consolidation-undo.d.ts +123 -0
  155. package/dist/consolidation-undo.js +426 -0
  156. package/dist/consolidation-undo.js.map +1 -0
  157. package/dist/{contradiction-scan-GR33PONM.js → contradiction-scan-E3GJTI4F.js} +43 -7
  158. package/dist/contradiction-scan-E3GJTI4F.js.map +1 -0
  159. package/dist/cross-namespace-budget.d.ts +133 -0
  160. package/dist/cross-namespace-budget.js +9 -0
  161. package/dist/cross-namespace-budget.js.map +1 -0
  162. package/dist/direct-answer-wiring.js +5 -70
  163. package/dist/direct-answer-wiring.js.map +1 -1
  164. package/dist/embedding-fallback.js +2 -1
  165. package/dist/{engine-5TIQBYZR.js → engine-72LSIWQP.js} +8 -7
  166. package/dist/engine-72LSIWQP.js.map +1 -0
  167. package/dist/entity-retrieval.d.ts +1 -0
  168. package/dist/entity-retrieval.js +7 -6
  169. package/dist/explicit-capture.d.ts +6 -3
  170. package/dist/explicit-capture.js +2 -2
  171. package/dist/extraction-judge-telemetry.d.ts +113 -0
  172. package/dist/extraction-judge-telemetry.js +14 -0
  173. package/dist/extraction-judge-telemetry.js.map +1 -0
  174. package/dist/extraction-judge-training.d.ts +85 -0
  175. package/dist/extraction-judge-training.js +16 -0
  176. package/dist/extraction-judge-training.js.map +1 -0
  177. package/dist/extraction-judge.d.ts +124 -2
  178. package/dist/extraction-judge.js +11 -1
  179. package/dist/extraction.js +10 -9
  180. package/dist/fallback-llm.js +3 -3
  181. package/dist/graph-recall.d.ts +100 -0
  182. package/dist/graph-recall.js +8 -0
  183. package/dist/graph-recall.js.map +1 -0
  184. package/dist/graph-retrieval.d.ts +271 -0
  185. package/dist/graph-retrieval.js +21 -0
  186. package/dist/graph-retrieval.js.map +1 -0
  187. package/dist/importance.js +1 -1
  188. package/dist/index.d.ts +585 -20
  189. package/dist/index.js +542 -344
  190. package/dist/index.js.map +1 -1
  191. package/dist/local-llm.js +2 -2
  192. package/dist/memory-worth-bench.d.ts +51 -0
  193. package/dist/memory-worth-bench.js +131 -0
  194. package/dist/memory-worth-bench.js.map +1 -0
  195. package/dist/memory-worth-filter.d.ts +128 -0
  196. package/dist/memory-worth-filter.js +10 -0
  197. package/dist/memory-worth-filter.js.map +1 -0
  198. package/dist/memory-worth-outcomes.d.ts +118 -0
  199. package/dist/memory-worth-outcomes.js +9 -0
  200. package/dist/memory-worth-outcomes.js.map +1 -0
  201. package/dist/memory-worth.d.ts +102 -0
  202. package/dist/memory-worth.js +7 -0
  203. package/dist/memory-worth.js.map +1 -0
  204. package/dist/operator-toolkit.d.ts +40 -1
  205. package/dist/operator-toolkit.js +25 -16
  206. package/dist/{orchestrator-DRYA6_lW.d.ts → orchestrator-CmJ-NTdJ.d.ts} +233 -8
  207. package/dist/orchestrator.d.ts +6 -3
  208. package/dist/orchestrator.js +54 -44
  209. package/dist/page-versioning.d.ts +12 -1
  210. package/dist/page-versioning.js +5 -3
  211. package/dist/{port-C1GZFv8h.d.ts → port-BADbLZU5.d.ts} +2 -2
  212. package/dist/qmd-recall-cache.d.ts +1 -1
  213. package/dist/qmd.d.ts +5 -3
  214. package/dist/qmd.js +3 -3
  215. package/dist/reasoning-trace-recall.d.ts +90 -0
  216. package/dist/reasoning-trace-recall.js +13 -0
  217. package/dist/reasoning-trace-recall.js.map +1 -0
  218. package/dist/reasoning-trace-types.d.ts +54 -0
  219. package/dist/reasoning-trace-types.js +17 -0
  220. package/dist/reasoning-trace-types.js.map +1 -0
  221. package/dist/recall-audit-anomaly.d.ts +112 -0
  222. package/dist/recall-audit-anomaly.js +11 -0
  223. package/dist/recall-audit-anomaly.js.map +1 -0
  224. package/dist/recall-audit.js +5 -44
  225. package/dist/recall-audit.js.map +1 -1
  226. package/dist/recall-explain-renderer.d.ts +49 -0
  227. package/dist/recall-explain-renderer.js +18 -0
  228. package/dist/recall-explain-renderer.js.map +1 -0
  229. package/dist/recall-state.d.ts +12 -1
  230. package/dist/recall-state.js +1 -1
  231. package/dist/recall-xray-cli.d.ts +40 -0
  232. package/dist/recall-xray-cli.js +11 -0
  233. package/dist/recall-xray-cli.js.map +1 -0
  234. package/dist/recall-xray-renderer.d.ts +44 -0
  235. package/dist/recall-xray-renderer.js +18 -0
  236. package/dist/recall-xray-renderer.js.map +1 -0
  237. package/dist/recall-xray.d.ts +179 -0
  238. package/dist/recall-xray.js +13 -0
  239. package/dist/recall-xray.js.map +1 -0
  240. package/dist/resolve-provider-secret.d.ts +5 -1
  241. package/dist/resolve-provider-secret.js +3 -1
  242. package/dist/resume-bundles.js +6 -6
  243. package/dist/retrieval-agents.d.ts +1 -1
  244. package/dist/retrieval-tiers.d.ts +17 -0
  245. package/dist/retrieval-tiers.js +9 -0
  246. package/dist/retrieval-tiers.js.map +1 -0
  247. package/dist/schemas.d.ts +309 -53
  248. package/dist/schemas.js +1 -1
  249. package/dist/{semantic-consolidation-DrvSYRdB.d.ts → semantic-consolidation-CxJU6MJk.d.ts} +62 -1
  250. package/dist/semantic-consolidation.d.ts +2 -1
  251. package/dist/semantic-consolidation.js +22 -7
  252. package/dist/semantic-rule-promotion.js +7 -6
  253. package/dist/semantic-rule-verifier.js +7 -6
  254. package/dist/storage.d.ts +82 -1
  255. package/dist/storage.js +6 -5
  256. package/dist/summarizer.js +6 -6
  257. package/dist/temporal-supersession.d.ts +1 -0
  258. package/dist/tier-migration.d.ts +2 -1
  259. package/dist/tokens.js +2 -1
  260. package/dist/types.d.ts +276 -2
  261. package/dist/types.js +1 -1
  262. package/dist/verified-recall.js +7 -6
  263. package/package.json +1 -1
  264. package/dist/chunk-37UIFYWO.js.map +0 -1
  265. package/dist/chunk-3QHL5ABG.js.map +0 -1
  266. package/dist/chunk-3SV6CQHO.js.map +0 -1
  267. package/dist/chunk-3WHVNEN7.js.map +0 -1
  268. package/dist/chunk-47UU5PU2.js.map +0 -1
  269. package/dist/chunk-4LACOVZX.js.map +0 -1
  270. package/dist/chunk-6ZH4TU6I.js.map +0 -1
  271. package/dist/chunk-ALXMCZEU.js.map +0 -1
  272. package/dist/chunk-BLKTA7MM.js.map +0 -1
  273. package/dist/chunk-DEPL3635.js.map +0 -1
  274. package/dist/chunk-GV6NLQ4X.js.map +0 -1
  275. package/dist/chunk-J4IYOZZ5.js.map +0 -1
  276. package/dist/chunk-LAYN4LDC.js +0 -267
  277. package/dist/chunk-LAYN4LDC.js.map +0 -1
  278. package/dist/chunk-LK6SGL53.js.map +0 -1
  279. package/dist/chunk-MBJHSA7F.js.map +0 -1
  280. package/dist/chunk-MTLYEMJB.js.map +0 -1
  281. package/dist/chunk-MVTHXUBX.js.map +0 -1
  282. package/dist/chunk-NQEVYWX6.js.map +0 -1
  283. package/dist/chunk-O5ETUNBT.js.map +0 -1
  284. package/dist/chunk-OIT5QGG4.js.map +0 -1
  285. package/dist/chunk-PAORGQRI.js.map +0 -1
  286. package/dist/chunk-QDYXG4CS.js.map +0 -1
  287. package/dist/chunk-QNJMBKFK.js.map +0 -1
  288. package/dist/chunk-SYUK3VLY.js.map +0 -1
  289. package/dist/chunk-UEYA6UC7.js.map +0 -1
  290. package/dist/chunk-UVJFDP7P.js +0 -202
  291. package/dist/chunk-UVJFDP7P.js.map +0 -1
  292. package/dist/chunk-WBSAYXVI.js.map +0 -1
  293. package/dist/chunk-XZ2TIKGC.js.map +0 -1
  294. package/dist/chunk-ZVBB3T7V.js.map +0 -1
  295. package/dist/contradiction-scan-GR33PONM.js.map +0 -1
  296. /package/dist/{engine-5TIQBYZR.js.map → access-audit.js.map} +0 -0
  297. /package/dist/{chunk-ITRLGI2T.js.map → chunk-3OGMS3PE.js.map} +0 -0
  298. /package/dist/{chunk-44ICJRF3.js.map → chunk-AYXIPSZO.js.map} +0 -0
  299. /package/dist/{chunk-6UJ47TVX.js.map → chunk-CUPFXL3J.js.map} +0 -0
  300. /package/dist/{chunk-N42IWANG.js.map → chunk-DG6YMRDC.js.map} +0 -0
  301. /package/dist/{chunk-7WQ6SLIE.js.map → chunk-FVA6TGI3.js.map} +0 -0
  302. /package/dist/{chunk-JL2PU6AI.js.map → chunk-R2XRID2N.js.map} +0 -0
  303. /package/dist/{chunk-4NRAJUDS.js.map → chunk-RBBWYEFJ.js.map} +0 -0
  304. /package/dist/{chunk-JIU55F3X.js.map → chunk-SPI27QT6.js.map} +0 -0
  305. /package/dist/{chunk-6LX5ORAS.js.map → chunk-TMYO7B5P.js.map} +0 -0
  306. /package/dist/{chunk-7ECD5ATE.js.map → chunk-VDX363PS.js.map} +0 -0
  307. /package/dist/{chunk-3QFQGRHO.js.map → chunk-XMHBH5H6.js.map} +0 -0
  308. /package/dist/{chunk-DHHP2Z4X.js.map → chunk-XXVWLXSG.js.map} +0 -0
@@ -2,7 +2,7 @@ import {
2
2
  CompoundingEngine,
3
3
  SharedContextManager,
4
4
  defaultTierMigrationCycleBudget
5
- } from "./chunk-DHHP2Z4X.js";
5
+ } from "./chunk-XXVWLXSG.js";
6
6
  import {
7
7
  extractTopics
8
8
  } from "./chunk-UHGBNIOS.js";
@@ -11,9 +11,6 @@ import {
11
11
  applyUtilityRankingRuntimeDelta,
12
12
  loadUtilityRuntimeValues
13
13
  } from "./chunk-FSFEQI74.js";
14
- import {
15
- HourlySummarizer
16
- } from "./chunk-N42IWANG.js";
17
14
  import {
18
15
  applyTemporalSupersession,
19
16
  normalizeSupersessionKey,
@@ -32,11 +29,8 @@ import {
32
29
  SessionObserverState
33
30
  } from "./chunk-JR4ZC3G4.js";
34
31
  import {
35
- semanticChunkContent
36
- } from "./chunk-KVE7R4CG.js";
37
- import {
38
- findUnresolvedEntityRefs
39
- } from "./chunk-X7XN6YU4.js";
32
+ HourlySummarizer
33
+ } from "./chunk-DG6YMRDC.js";
40
34
  import {
41
35
  RelevanceStore
42
36
  } from "./chunk-5NPGSAVB.js";
@@ -66,10 +60,19 @@ import {
66
60
  applyRuntimeRetrievalPolicy
67
61
  } from "./chunk-5IZL4DCV.js";
68
62
  import {
69
- buildQmdRecallCacheKey,
70
- getCachedQmdRecall,
71
- setCachedQmdRecall
72
- } from "./chunk-YCN4BVDK.js";
63
+ LastRecallStore,
64
+ TierMigrationStatusStore,
65
+ clampGraphRecallExpandedEntries
66
+ } from "./chunk-VBVG2M5G.js";
67
+ import {
68
+ buildXraySnapshot
69
+ } from "./chunk-KVBLZUKV.js";
70
+ import {
71
+ findUnresolvedEntityRefs
72
+ } from "./chunk-X7XN6YU4.js";
73
+ import {
74
+ applyReasoningTraceBoost
75
+ } from "./chunk-ZZTOURJI.js";
73
76
  import {
74
77
  reorderRecallResultsWithMmr
75
78
  } from "./chunk-YDBIWGNI.js";
@@ -77,10 +80,10 @@ import {
77
80
  createRecallSectionMetricRecorder
78
81
  } from "./chunk-7DHTMOND.js";
79
82
  import {
80
- LastRecallStore,
81
- TierMigrationStatusStore,
82
- clampGraphRecallExpandedEntries
83
- } from "./chunk-47UU5PU2.js";
83
+ buildQmdRecallCacheKey,
84
+ getCachedQmdRecall,
85
+ setCachedQmdRecall
86
+ } from "./chunk-YCN4BVDK.js";
84
87
  import {
85
88
  NegativeExampleStore
86
89
  } from "./chunk-D654IBA6.js";
@@ -88,8 +91,9 @@ import {
88
91
  evaluateMemoryActionPolicy
89
92
  } from "./chunk-H63EDPFJ.js";
90
93
  import {
91
- classifyMemoryKind
92
- } from "./chunk-YAZNBMNF.js";
94
+ applyMemoryWorthFilter,
95
+ buildMemoryWorthCounterMap
96
+ } from "./chunk-3GPTTA4J.js";
93
97
  import {
94
98
  hasBroadGraphIntent,
95
99
  inferIntentFromText,
@@ -98,16 +102,28 @@ import {
98
102
  planRecallMode
99
103
  } from "./chunk-GGD5W7TB.js";
100
104
  import {
105
+ classifyMemoryKind
106
+ } from "./chunk-YAZNBMNF.js";
107
+ import {
108
+ EXTRACTION_JUDGE_VERDICT_CATEGORY,
109
+ recordJudgeVerdict
110
+ } from "./chunk-AJU4PJGY.js";
111
+ import {
112
+ recordJudgeTrainingPair
113
+ } from "./chunk-DF3RVK3X.js";
114
+ import {
115
+ createDeferCountMap,
101
116
  createVerdictCache,
117
+ getVerdictKind,
102
118
  judgeFactDurability,
103
119
  validateProcedureExtraction
104
- } from "./chunk-LAYN4LDC.js";
120
+ } from "./chunk-C4SQJZAF.js";
105
121
  import {
106
122
  ExtractionEngine
107
- } from "./chunk-3SV6CQHO.js";
123
+ } from "./chunk-DIXB44VE.js";
108
124
  import {
109
125
  parseMemoryActionEligibilityContext
110
- } from "./chunk-UEYA6UC7.js";
126
+ } from "./chunk-NZLQTHS5.js";
111
127
  import {
112
128
  ProfilingCollector
113
129
  } from "./chunk-NBNN5GOB.js";
@@ -116,31 +132,35 @@ import {
116
132
  } from "./chunk-FEMOX5AD.js";
117
133
  import {
118
134
  LocalLlmClient
119
- } from "./chunk-JL2PU6AI.js";
135
+ } from "./chunk-R2XRID2N.js";
120
136
  import {
121
- formatDaySummaryMemories
122
- } from "./chunk-GZCUW5IC.js";
137
+ tryDirectAnswer
138
+ } from "./chunk-6AUUAZEX.js";
123
139
  import {
124
140
  EmbeddingFallback
125
- } from "./chunk-ALXMCZEU.js";
141
+ } from "./chunk-Z2E7VW55.js";
126
142
  import {
127
143
  buildEntityRecallSection,
128
144
  entityRecentTranscriptLookbackHours,
129
145
  readRecentEntityTranscriptEntries
130
- } from "./chunk-7WQ6SLIE.js";
146
+ } from "./chunk-FVA6TGI3.js";
147
+ import {
148
+ formatDaySummaryMemories
149
+ } from "./chunk-GZCUW5IC.js";
131
150
  import {
132
151
  RoutingRulesStore,
152
+ expandTildePath,
133
153
  normalizeReplaySessionKey
134
- } from "./chunk-PAORGQRI.js";
154
+ } from "./chunk-GA5P7RST.js";
135
155
  import {
136
156
  searchVerifiedEpisodes
137
- } from "./chunk-6UJ47TVX.js";
157
+ } from "./chunk-CUPFXL3J.js";
138
158
  import {
139
159
  ThreadingManager
140
160
  } from "./chunk-JRNQ3RNA.js";
141
161
  import {
142
162
  searchVerifiedSemanticRules
143
- } from "./chunk-JIU55F3X.js";
163
+ } from "./chunk-SPI27QT6.js";
144
164
  import {
145
165
  searchWorkProductLedgerEntries
146
166
  } from "./chunk-CULXMQJH.js";
@@ -154,10 +174,10 @@ import {
154
174
  createConversationIndexRuntime,
155
175
  createSearchBackend,
156
176
  writeConversationChunks
157
- } from "./chunk-ZVBB3T7V.js";
177
+ } from "./chunk-NBVAS5MT.js";
158
178
  import {
159
179
  parseQmdExplain
160
- } from "./chunk-BLKTA7MM.js";
180
+ } from "./chunk-4HQS2HPX.js";
161
181
  import {
162
182
  PolicyRuntimeManager
163
183
  } from "./chunk-EABGC2TL.js";
@@ -170,7 +190,10 @@ import {
170
190
  import {
171
191
  isAboveImportanceThreshold,
172
192
  scoreImportance
173
- } from "./chunk-J4IYOZZ5.js";
193
+ } from "./chunk-JXS5PDQ7.js";
194
+ import {
195
+ launchProcessSync
196
+ } from "./chunk-OR64ZGRZ.js";
174
197
  import {
175
198
  collectNativeKnowledgeChunks,
176
199
  formatNativeKnowledgeSection,
@@ -179,6 +202,9 @@ import {
179
202
  import {
180
203
  recordEvalShadowRecall
181
204
  } from "./chunk-K6WK37A6.js";
205
+ import {
206
+ GraphIndex
207
+ } from "./chunk-C2EFFULQ.js";
182
208
  import {
183
209
  CODEX_THREAD_KEY_PREFIX
184
210
  } from "./chunk-3PG3H5TD.js";
@@ -191,22 +217,28 @@ import {
191
217
  refineCompressionGuidelineCandidateSemantically,
192
218
  renderCompressionGuidelinesMarkdown
193
219
  } from "./chunk-2NMMFZ5T.js";
220
+ import {
221
+ semanticChunkContent
222
+ } from "./chunk-KVE7R4CG.js";
223
+ import {
224
+ chunkContent
225
+ } from "./chunk-4WMCPJWX.js";
226
+ import {
227
+ SmartBuffer
228
+ } from "./chunk-JBMSGZEQ.js";
194
229
  import {
195
230
  buildConsolidationPrompt,
196
231
  buildExtensionsBlockForConsolidation,
232
+ buildOperatorAwareConsolidationPrompt,
233
+ chooseConsolidationOperator,
197
234
  findSimilarClusters,
198
235
  materializeAfterSemanticConsolidation,
199
- parseConsolidationResponse
200
- } from "./chunk-SYUK3VLY.js";
236
+ parseConsolidationResponse,
237
+ parseOperatorAwareConsolidationResponse
238
+ } from "./chunk-PVICZTKG.js";
201
239
  import {
202
240
  FallbackLlmClient
203
- } from "./chunk-44ICJRF3.js";
204
- import {
205
- GraphIndex
206
- } from "./chunk-C2EFFULQ.js";
207
- import {
208
- chunkContent
209
- } from "./chunk-4WMCPJWX.js";
241
+ } from "./chunk-AYXIPSZO.js";
210
242
  import {
211
243
  buildRecallQueryPolicy
212
244
  } from "./chunk-6HZ6AO2P.js";
@@ -217,38 +249,33 @@ import {
217
249
  import {
218
250
  BootstrapEngine
219
251
  } from "./chunk-N53K2EXC.js";
220
- import {
221
- BoxBuilder
222
- } from "./chunk-URB2WSKZ.js";
223
- import {
224
- SmartBuffer
225
- } from "./chunk-UVJFDP7P.js";
226
252
  import {
227
253
  isDisagreementPrompt
228
254
  } from "./chunk-XYIK4LF6.js";
255
+ import {
256
+ BoxBuilder
257
+ } from "./chunk-URB2WSKZ.js";
229
258
  import {
230
259
  abortError,
231
260
  isAbortError,
232
261
  throwIfAborted
233
262
  } from "./chunk-PVGDJXVK.js";
234
263
  import {
235
- resolveHomeDir
236
- } from "./chunk-MARWOCVP.js";
237
- import {
264
+ listTrustZoneRecords,
238
265
  searchTrustZoneRecords
239
266
  } from "./chunk-EQINRHYR.js";
267
+ import {
268
+ buildProcedurePersistBody
269
+ } from "./chunk-QDW3E4RD.js";
240
270
  import {
241
271
  shouldSkipImplicitExtraction
242
- } from "./chunk-QDYXG4CS.js";
272
+ } from "./chunk-3FPTCC3Z.js";
243
273
  import {
244
274
  selectRouteRule
245
- } from "./chunk-QNJMBKFK.js";
246
- import {
247
- buildProcedurePersistBody
248
- } from "./chunk-QDW3E4RD.js";
275
+ } from "./chunk-2LGMW3DJ.js";
249
276
  import {
250
277
  searchCausalTrajectories
251
- } from "./chunk-4NRAJUDS.js";
278
+ } from "./chunk-RBBWYEFJ.js";
252
279
  import {
253
280
  canReadNamespace,
254
281
  defaultNamespaceForPrincipal,
@@ -267,10 +294,10 @@ import {
267
294
  normalizeAttributePairs,
268
295
  normalizeEntityName,
269
296
  parseEntityFile
270
- } from "./chunk-GV6NLQ4X.js";
297
+ } from "./chunk-F5VP6YCB.js";
271
298
  import {
272
299
  confidenceTier
273
- } from "./chunk-3WHVNEN7.js";
300
+ } from "./chunk-LTCGGW2D.js";
274
301
  import {
275
302
  attachCitation,
276
303
  hasCitationForTemplate,
@@ -286,26 +313,28 @@ import {
286
313
  import {
287
314
  sanitizeMemoryContent
288
315
  } from "./chunk-M62O4P4T.js";
316
+ import {
317
+ resolveHomeDir
318
+ } from "./chunk-MARWOCVP.js";
289
319
  import {
290
320
  log
291
321
  } from "./chunk-2ODBA7MQ.js";
292
322
 
293
323
  // src/orchestrator.ts
294
- import path5 from "path";
324
+ import path7 from "path";
295
325
  import os from "os";
296
326
  import { createHash as createHash2, randomBytes } from "crypto";
297
327
  import { existsSync as existsSync2 } from "fs";
298
328
  import {
299
- mkdir as mkdir4,
329
+ mkdir as mkdir5,
300
330
  readdir as readdir3,
301
- readFile as readFile3,
331
+ readFile as readFile4,
302
332
  stat as stat3,
303
333
  unlink as unlink2,
304
- writeFile as writeFile3
334
+ writeFile as writeFile4
305
335
  } from "fs/promises";
306
336
 
307
337
  // src/migrate/from-engram.ts
308
- import { execFileSync } from "child_process";
309
338
  import { createHash } from "crypto";
310
339
  import path from "path";
311
340
  import {
@@ -341,7 +370,14 @@ function resolveLogger(options) {
341
370
  }
342
371
  function resolveExec(options) {
343
372
  return options?.execCommand ?? ((command, args) => {
344
- execFileSync(command, args, { stdio: "ignore" });
373
+ const result = launchProcessSync(command, args, { stdio: "ignore" });
374
+ if (result.error) {
375
+ throw result.error;
376
+ }
377
+ if (result.status !== 0) {
378
+ const reason = result.status === null ? `signal ${result.signal ?? "unknown"}` : `exit code ${result.status}`;
379
+ throw new Error(`migration command failed: ${command} ${args.join(" ")} (${reason})`);
380
+ }
345
381
  });
346
382
  }
347
383
  function remnicRoot(homeDir) {
@@ -878,7 +914,7 @@ async function buildProcedureRecallSection(storage, prompt, config) {
878
914
  10,
879
915
  Math.max(
880
916
  1,
881
- typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) : 3
917
+ typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) : 2
882
918
  )
883
919
  );
884
920
  const all = await storage.readAllMemories();
@@ -1119,12 +1155,253 @@ async function decideSemanticDedup(content, lookup, options) {
1119
1155
  };
1120
1156
  }
1121
1157
 
1122
- // src/lcm/schema.ts
1158
+ // src/taxonomy/default-taxonomy.ts
1159
+ var DEFAULT_TAXONOMY = {
1160
+ version: 1,
1161
+ categories: [
1162
+ {
1163
+ id: "corrections",
1164
+ name: "Corrections",
1165
+ description: "Corrections to previously stored information",
1166
+ filingRules: ["Any update that supersedes a prior fact"],
1167
+ priority: 10,
1168
+ memoryCategories: ["correction"]
1169
+ },
1170
+ {
1171
+ id: "principles",
1172
+ name: "Principles",
1173
+ description: "Rules, guidelines, and recurring patterns",
1174
+ filingRules: ["A guiding principle, rule, or skill"],
1175
+ priority: 20,
1176
+ memoryCategories: ["principle", "rule", "skill"]
1177
+ },
1178
+ {
1179
+ id: "procedures",
1180
+ name: "Procedures",
1181
+ description: "Ordered multi-step workflows the user repeats",
1182
+ filingRules: ["A repeatable sequence of steps or commands for a task"],
1183
+ priority: 25,
1184
+ memoryCategories: ["procedure"]
1185
+ },
1186
+ {
1187
+ id: "entities",
1188
+ name: "Entities",
1189
+ description: "People, organizations, places, projects",
1190
+ filingRules: ["Named entity with attributes"],
1191
+ priority: 30,
1192
+ memoryCategories: ["entity", "relationship"]
1193
+ },
1194
+ {
1195
+ id: "decisions",
1196
+ name: "Decisions",
1197
+ description: "Choices made and their rationale",
1198
+ filingRules: ["A decision or commitment with reasoning"],
1199
+ priority: 35,
1200
+ memoryCategories: ["decision", "commitment"]
1201
+ },
1202
+ {
1203
+ id: "preferences",
1204
+ name: "Preferences",
1205
+ description: "User likes, dislikes, and style choices",
1206
+ filingRules: ["Anything expressing a preference or taste"],
1207
+ priority: 40,
1208
+ memoryCategories: ["preference"]
1209
+ },
1210
+ {
1211
+ id: "facts",
1212
+ name: "Facts",
1213
+ description: "Objective statements about the world",
1214
+ filingRules: ["Any factual claim or piece of information"],
1215
+ priority: 50,
1216
+ memoryCategories: ["fact"]
1217
+ },
1218
+ {
1219
+ id: "moments",
1220
+ name: "Moments",
1221
+ description: "Significant events or experiences",
1222
+ filingRules: ["A specific event worth remembering"],
1223
+ priority: 60,
1224
+ memoryCategories: ["moment"]
1225
+ },
1226
+ {
1227
+ id: "reasoning-traces",
1228
+ name: "Reasoning Traces",
1229
+ description: "Stored intermediate reasoning / solution chains for a problem the agent previously solved",
1230
+ filingRules: [
1231
+ "A multi-step reasoning chain or solution walkthrough the agent can replay for a similar problem"
1232
+ ],
1233
+ priority: 55,
1234
+ memoryCategories: ["reasoning_trace"]
1235
+ }
1236
+ ]
1237
+ };
1238
+
1239
+ // src/taxonomy/resolver-doc-generator.ts
1240
+ function generateResolverDocument(taxonomy) {
1241
+ const sorted = [...taxonomy.categories].sort((a, b) => {
1242
+ if (a.priority !== b.priority) return a.priority - b.priority;
1243
+ return a.id.localeCompare(b.id);
1244
+ });
1245
+ const lines = [
1246
+ "# Memory Filing Resolver",
1247
+ "",
1248
+ "Given a new piece of knowledge, follow this tree to determine where it belongs.",
1249
+ ""
1250
+ ];
1251
+ let step = 1;
1252
+ for (const cat of sorted) {
1253
+ lines.push(`## Step ${step}: ${cat.description}?`);
1254
+ lines.push("");
1255
+ for (const rule of cat.filingRules) {
1256
+ lines.push(`- ${rule}`);
1257
+ }
1258
+ lines.push("");
1259
+ lines.push(
1260
+ `> YES: File under **${cat.id}/** (priority ${cat.priority})`
1261
+ );
1262
+ lines.push("");
1263
+ step++;
1264
+ }
1265
+ lines.push("## Tie-breaking");
1266
+ lines.push("");
1267
+ lines.push(
1268
+ "If a fact could go in multiple categories, file under the one with the **lowest priority number**."
1269
+ );
1270
+ lines.push("");
1271
+ lines.push(`---`);
1272
+ lines.push(`*Generated from taxonomy v${taxonomy.version}*`);
1273
+ lines.push("");
1274
+ return lines.join("\n");
1275
+ }
1276
+
1277
+ // src/taxonomy/taxonomy-loader.ts
1278
+ import { readFile as readFile3, mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
1123
1279
  import path3 from "path";
1124
- import { mkdir as mkdir3 } from "fs/promises";
1280
+ var TAXONOMY_DIR = ".taxonomy";
1281
+ var TAXONOMY_FILE = "taxonomy.json";
1282
+ var MAX_SLUG_LENGTH = 32;
1283
+ var SLUG_RE = /^[a-z][a-z0-9-]*$/;
1284
+ function validateSlug(slug) {
1285
+ if (slug.length === 0) {
1286
+ throw new Error("Taxonomy category ID must not be empty");
1287
+ }
1288
+ if (slug.length > MAX_SLUG_LENGTH) {
1289
+ throw new Error(
1290
+ `Taxonomy category ID "${slug}" exceeds ${MAX_SLUG_LENGTH} characters`
1291
+ );
1292
+ }
1293
+ if (!SLUG_RE.test(slug)) {
1294
+ throw new Error(
1295
+ `Taxonomy category ID "${slug}" is invalid: must be lowercase letters, digits, and hyphens, starting with a letter`
1296
+ );
1297
+ }
1298
+ }
1299
+ function validateTaxonomy(taxonomy) {
1300
+ if (typeof taxonomy.version !== "number" || taxonomy.version < 1) {
1301
+ throw new Error("Taxonomy version must be a positive integer");
1302
+ }
1303
+ if (!Array.isArray(taxonomy.categories)) {
1304
+ throw new Error("Taxonomy categories must be an array");
1305
+ }
1306
+ const seenIds = /* @__PURE__ */ new Set();
1307
+ for (const cat of taxonomy.categories) {
1308
+ validateSlug(cat.id);
1309
+ if (seenIds.has(cat.id)) {
1310
+ throw new Error(`Duplicate taxonomy category ID: "${cat.id}"`);
1311
+ }
1312
+ seenIds.add(cat.id);
1313
+ if (typeof cat.name !== "string" || cat.name.trim().length === 0) {
1314
+ throw new Error(`Taxonomy category "${cat.id}" must have a non-empty name`);
1315
+ }
1316
+ if (typeof cat.description !== "string" || cat.description.trim().length === 0) {
1317
+ throw new Error(`Taxonomy category "${cat.id}" must have a non-empty description`);
1318
+ }
1319
+ if (!Array.isArray(cat.filingRules)) {
1320
+ throw new Error(`Taxonomy category "${cat.id}" filingRules must be an array`);
1321
+ }
1322
+ if (typeof cat.priority !== "number" || !Number.isFinite(cat.priority)) {
1323
+ throw new Error(`Taxonomy category "${cat.id}" must have a finite numeric priority`);
1324
+ }
1325
+ if (!Array.isArray(cat.memoryCategories)) {
1326
+ throw new Error(`Taxonomy category "${cat.id}" memoryCategories must be an array`);
1327
+ }
1328
+ if (cat.parentId !== void 0) {
1329
+ if (typeof cat.parentId !== "string") {
1330
+ throw new Error(`Taxonomy category "${cat.id}" parentId must be a string if set`);
1331
+ }
1332
+ }
1333
+ }
1334
+ for (const cat of taxonomy.categories) {
1335
+ if (cat.parentId !== void 0 && !seenIds.has(cat.parentId)) {
1336
+ throw new Error(
1337
+ `Taxonomy category "${cat.id}" references unknown parentId "${cat.parentId}"`
1338
+ );
1339
+ }
1340
+ }
1341
+ }
1342
+ async function loadTaxonomy(memoryDir) {
1343
+ const taxonomyPath = path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1344
+ let raw;
1345
+ try {
1346
+ raw = await readFile3(taxonomyPath, "utf-8");
1347
+ } catch (err) {
1348
+ if (err instanceof Error && err.code === "ENOENT") {
1349
+ return structuredClone(DEFAULT_TAXONOMY);
1350
+ }
1351
+ throw err;
1352
+ }
1353
+ const parsed = JSON.parse(raw);
1354
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1355
+ throw new Error("taxonomy.json must be a JSON object");
1356
+ }
1357
+ const obj = parsed;
1358
+ const userVersion = typeof obj.version === "number" ? obj.version : DEFAULT_TAXONOMY.version;
1359
+ const userCategories = Array.isArray(obj.categories) ? obj.categories : [];
1360
+ const userIdCounts = /* @__PURE__ */ new Map();
1361
+ for (const cat of userCategories) {
1362
+ const id = typeof cat.id === "string" ? cat.id : String(cat.id);
1363
+ userIdCounts.set(id, (userIdCounts.get(id) ?? 0) + 1);
1364
+ }
1365
+ const duplicateIds = [...userIdCounts.entries()].filter(([, count]) => count > 1).map(([id]) => id);
1366
+ if (duplicateIds.length > 0) {
1367
+ throw new Error(
1368
+ `Duplicate category IDs in taxonomy.json: ${duplicateIds.map((id) => `"${id}"`).join(", ")}`
1369
+ );
1370
+ }
1371
+ const mergedMap = /* @__PURE__ */ new Map();
1372
+ for (const cat of DEFAULT_TAXONOMY.categories) {
1373
+ mergedMap.set(cat.id, { ...cat });
1374
+ }
1375
+ for (const cat of userCategories) {
1376
+ mergedMap.set(cat.id, cat);
1377
+ }
1378
+ const merged = {
1379
+ version: userVersion,
1380
+ categories: [...mergedMap.values()]
1381
+ };
1382
+ validateTaxonomy(merged);
1383
+ return merged;
1384
+ }
1385
+ async function saveTaxonomy(memoryDir, taxonomy) {
1386
+ validateTaxonomy(taxonomy);
1387
+ const dir = path3.join(memoryDir, TAXONOMY_DIR);
1388
+ await mkdir3(dir, { recursive: true });
1389
+ const filePath = path3.join(dir, TAXONOMY_FILE);
1390
+ await writeFile3(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
1391
+ }
1392
+ function getTaxonomyDir(memoryDir) {
1393
+ return path3.join(memoryDir, TAXONOMY_DIR);
1394
+ }
1395
+ function getTaxonomyFilePath(memoryDir) {
1396
+ return path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1397
+ }
1398
+
1399
+ // src/lcm/schema.ts
1400
+ import path4 from "path";
1401
+ import { mkdir as mkdir4 } from "fs/promises";
1125
1402
  var LCM_SCHEMA_VERSION = 1;
1126
1403
  function openLcmDatabase(memoryDir) {
1127
- const dbPath = path3.join(memoryDir, "state", "lcm.sqlite");
1404
+ const dbPath = path4.join(memoryDir, "state", "lcm.sqlite");
1128
1405
  const db = openBetterSqlite3(dbPath);
1129
1406
  db.pragma("journal_mode = WAL");
1130
1407
  db.pragma("busy_timeout = 5000");
@@ -1133,7 +1410,7 @@ function openLcmDatabase(memoryDir) {
1133
1410
  return db;
1134
1411
  }
1135
1412
  async function ensureLcmStateDir(memoryDir) {
1136
- await mkdir3(path3.join(memoryDir, "state"), { recursive: true });
1413
+ await mkdir4(path4.join(memoryDir, "state"), { recursive: true });
1137
1414
  }
1138
1415
  function applySchema(db) {
1139
1416
  const versionRow = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_meta'").get();
@@ -2397,7 +2674,7 @@ function chunkTranscriptEntries(sessionKey, entries, opts) {
2397
2674
 
2398
2675
  // src/conversation-index/cleanup.ts
2399
2676
  import { readdir as readdir2, rm as rm3 } from "fs/promises";
2400
- import path4 from "path";
2677
+ import path5 from "path";
2401
2678
  async function cleanupConversationChunks(rootDir, retentionDays) {
2402
2679
  if (!Number.isFinite(retentionDays) || retentionDays <= 0) return;
2403
2680
  const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1e3;
@@ -2405,7 +2682,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
2405
2682
  const sessions = await readdir2(rootDir, { withFileTypes: true });
2406
2683
  for (const s of sessions) {
2407
2684
  if (!s.isDirectory()) continue;
2408
- const sessionDir = path4.join(rootDir, s.name);
2685
+ const sessionDir = path5.join(rootDir, s.name);
2409
2686
  const dayDirs = await readdir2(sessionDir, { withFileTypes: true });
2410
2687
  for (const d of dayDirs) {
2411
2688
  if (!d.isDirectory()) continue;
@@ -2413,7 +2690,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
2413
2690
  const dayMs = (/* @__PURE__ */ new Date(d.name + "T00:00:00.000Z")).getTime();
2414
2691
  if (!Number.isFinite(dayMs)) continue;
2415
2692
  if (dayMs < cutoffMs) {
2416
- await rm3(path4.join(sessionDir, d.name), { recursive: true, force: true });
2693
+ await rm3(path5.join(sessionDir, d.name), { recursive: true, force: true });
2417
2694
  }
2418
2695
  }
2419
2696
  try {
@@ -2429,6 +2706,264 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
2429
2706
  }
2430
2707
  }
2431
2708
 
2709
+ // src/coding/git-context.ts
2710
+ import path6 from "path";
2711
+ var DEFAULT_GIT_TIMEOUT_MS = 2e3;
2712
+ function defaultGitInvoker() {
2713
+ return (cwd, args) => {
2714
+ const result = launchProcessSync("git", args, {
2715
+ cwd,
2716
+ encoding: "utf-8",
2717
+ timeout: DEFAULT_GIT_TIMEOUT_MS,
2718
+ shell: false
2719
+ });
2720
+ if (result.error) {
2721
+ return { stdout: "", exitCode: 127 };
2722
+ }
2723
+ return {
2724
+ stdout: typeof result.stdout === "string" ? result.stdout : "",
2725
+ exitCode: typeof result.status === "number" ? result.status : 1
2726
+ };
2727
+ };
2728
+ }
2729
+ function stableHash(input) {
2730
+ let hash = 2166136261;
2731
+ for (let i = 0; i < input.length; i++) {
2732
+ hash ^= input.charCodeAt(i);
2733
+ hash = Math.imul(hash, 16777619) >>> 0;
2734
+ }
2735
+ return hash.toString(16).padStart(8, "0");
2736
+ }
2737
+ function normalizeOriginUrl(rawUrl) {
2738
+ let url = rawUrl.trim();
2739
+ if (!url) return "";
2740
+ if (/\.git$/i.test(url)) url = url.slice(0, -4);
2741
+ if (/^[A-Za-z]:[\\/]/.test(url)) {
2742
+ return url.toLowerCase();
2743
+ }
2744
+ const protoMatch = /^[a-z][a-z0-9+.-]*:\/\/(?:[^@/]+@)?(\[[^\]]+\]|[^/:]*)(?::(\d+))?(\/.*)?$/i.exec(url);
2745
+ if (protoMatch) {
2746
+ let host = protoMatch[1] ?? "";
2747
+ const wasBracketed = host.startsWith("[") && host.endsWith("]");
2748
+ if (wasBracketed) host = host.slice(1, -1);
2749
+ const port = protoMatch[2];
2750
+ const repoPath = (protoMatch[3] ?? "").replace(/^\/+/, "");
2751
+ const hostPort = port ? wasBracketed ? `[${host}]:${port}` : `${host}:${port}` : host;
2752
+ const prefix = hostPort.length > 0 ? hostPort : "localhost";
2753
+ return `${prefix}/${repoPath}`.toLowerCase();
2754
+ }
2755
+ const scpMatch = /^(?:([^@\s/]+)@)?(\[[^\]]+\]|[^:@\s/]+):(.+)$/.exec(url);
2756
+ if (scpMatch) {
2757
+ let host = scpMatch[2] ?? "";
2758
+ if (host.startsWith("[") && host.endsWith("]")) host = host.slice(1, -1);
2759
+ const repoPath = scpMatch[3] ?? "";
2760
+ if (repoPath.startsWith("//")) {
2761
+ return url.toLowerCase();
2762
+ }
2763
+ return `${host}/${repoPath.replace(/^\/+/, "")}`.toLowerCase();
2764
+ }
2765
+ return url.toLowerCase();
2766
+ }
2767
+ async function resolveGitContext(cwd, options = {}) {
2768
+ try {
2769
+ if (typeof cwd !== "string" || cwd.length === 0) return null;
2770
+ const expanded = expandTildePath(cwd);
2771
+ if (!path6.isAbsolute(expanded)) return null;
2772
+ const invoker = options.invoker ?? defaultGitInvoker();
2773
+ const topLevel = invoker(expanded, ["rev-parse", "--show-toplevel"]);
2774
+ if (topLevel.exitCode !== 0) return null;
2775
+ const rootPath = topLevel.stdout.trim();
2776
+ if (!rootPath) return null;
2777
+ const branchResult = invoker(rootPath, ["rev-parse", "--abbrev-ref", "HEAD"]);
2778
+ let branch = null;
2779
+ if (branchResult.exitCode === 0) {
2780
+ const raw = branchResult.stdout.trim();
2781
+ branch = raw && raw !== "HEAD" ? raw : null;
2782
+ } else {
2783
+ const unbornRef = invoker(rootPath, ["symbolic-ref", "--quiet", "HEAD"]);
2784
+ if (unbornRef.exitCode === 0) {
2785
+ const raw = unbornRef.stdout.trim();
2786
+ const prefix = "refs/heads/";
2787
+ if (raw.startsWith(prefix)) {
2788
+ const candidate = raw.slice(prefix.length);
2789
+ if (candidate) branch = candidate;
2790
+ }
2791
+ }
2792
+ }
2793
+ const originResult = invoker(rootPath, ["remote", "get-url", "origin"]);
2794
+ let projectId;
2795
+ if (originResult.exitCode === 0) {
2796
+ const normalized = normalizeOriginUrl(originResult.stdout);
2797
+ projectId = normalized ? `origin:${stableHash(normalized)}` : `root:${stableHash(rootPath)}`;
2798
+ } else {
2799
+ projectId = `root:${stableHash(rootPath)}`;
2800
+ }
2801
+ const headRef = invoker(rootPath, ["symbolic-ref", "--quiet", "refs/remotes/origin/HEAD"]);
2802
+ let defaultBranch = null;
2803
+ if (headRef.exitCode === 0) {
2804
+ const raw = headRef.stdout.trim();
2805
+ const prefix = "refs/remotes/origin/";
2806
+ if (raw.startsWith(prefix)) {
2807
+ const candidate = raw.slice(prefix.length);
2808
+ if (candidate) defaultBranch = candidate;
2809
+ }
2810
+ }
2811
+ return {
2812
+ projectId,
2813
+ branch,
2814
+ rootPath,
2815
+ defaultBranch
2816
+ };
2817
+ } catch {
2818
+ return null;
2819
+ }
2820
+ }
2821
+
2822
+ // src/coding/coding-namespace.ts
2823
+ function sanitizeFragment(input) {
2824
+ if (typeof input !== "string") return "";
2825
+ const trimmed = input.trim().toLowerCase();
2826
+ let out = "";
2827
+ let prevIsDash = true;
2828
+ for (let i = 0; i < trimmed.length; i += 1) {
2829
+ const c = trimmed[i];
2830
+ const cc = trimmed.charCodeAt(i);
2831
+ const isSafe = cc >= 48 && cc <= 57 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
2832
+ if (isSafe) {
2833
+ out += c;
2834
+ prevIsDash = false;
2835
+ } else if (!prevIsDash) {
2836
+ out += "-";
2837
+ prevIsDash = true;
2838
+ }
2839
+ }
2840
+ if (out.endsWith("-")) out = out.slice(0, -1);
2841
+ return out;
2842
+ }
2843
+ var MAX_NAMESPACE_LEN = 64;
2844
+ var HASH_SUFFIX_LEN = 9;
2845
+ function capLength(value) {
2846
+ if (value.length <= MAX_NAMESPACE_LEN) return value;
2847
+ const hash = stableHash(value);
2848
+ let end = MAX_NAMESPACE_LEN - HASH_SUFFIX_LEN;
2849
+ while (end > 0 && value.charCodeAt(end - 1) === 45) end -= 1;
2850
+ return `${value.slice(0, end)}-${hash}`;
2851
+ }
2852
+ function projectNamespaceName(projectId) {
2853
+ const frag = sanitizeFragment(projectId);
2854
+ return capLength(`project-${frag || "unknown"}`);
2855
+ }
2856
+ function sanitizeBaseFragment(input) {
2857
+ if (typeof input !== "string") return "";
2858
+ const trimmed = input.trim();
2859
+ let out = "";
2860
+ let prevIsDash = true;
2861
+ for (let i = 0; i < trimmed.length; i += 1) {
2862
+ const c = trimmed[i];
2863
+ const cc = trimmed.charCodeAt(i);
2864
+ const isSafe = cc >= 48 && cc <= 57 || cc >= 65 && cc <= 90 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
2865
+ if (isSafe) {
2866
+ out += c;
2867
+ prevIsDash = false;
2868
+ } else if (!prevIsDash) {
2869
+ out += "-";
2870
+ prevIsDash = true;
2871
+ }
2872
+ }
2873
+ if (out.endsWith("-")) out = out.slice(0, -1);
2874
+ return out;
2875
+ }
2876
+ function combineNamespaces(base, overlay) {
2877
+ const baseFrag = sanitizeBaseFragment(base);
2878
+ const overlayFrag = sanitizeFragment(overlay);
2879
+ if (!baseFrag) return capLength(overlayFrag || "unknown");
2880
+ if (!overlayFrag) return capLength(baseFrag);
2881
+ return capLength(`${baseFrag}-${overlayFrag}`);
2882
+ }
2883
+ function branchNamespaceName(projectId, branch) {
2884
+ const projectFrag = sanitizeFragment(projectId);
2885
+ const trimmedBranch = branch.trim();
2886
+ const branchFrag = sanitizeFragment(trimmedBranch);
2887
+ const disambig = trimmedBranch.length > 0 && branchFrag !== trimmedBranch;
2888
+ const base = `project-${projectFrag || "unknown"}-branch-${branchFrag || "unknown"}`;
2889
+ const suffixed = disambig ? `${base}-${stableHash(trimmedBranch)}` : base;
2890
+ return capLength(suffixed);
2891
+ }
2892
+ function resolveCodingNamespaceOverlay(codingContext, config) {
2893
+ if (!codingContext) return null;
2894
+ if (!config.projectScope) return null;
2895
+ const projectId = typeof codingContext.projectId === "string" ? codingContext.projectId.trim() : "";
2896
+ if (!projectId) return null;
2897
+ const projectNs = projectNamespaceName(projectId);
2898
+ if (config.branchScope && typeof codingContext.branch === "string" && codingContext.branch.length > 0) {
2899
+ const branchNs = branchNamespaceName(projectId, codingContext.branch);
2900
+ return {
2901
+ namespace: branchNs,
2902
+ readFallbacks: [projectNs],
2903
+ scope: "branch"
2904
+ };
2905
+ }
2906
+ return {
2907
+ namespace: projectNs,
2908
+ readFallbacks: [],
2909
+ scope: "project"
2910
+ };
2911
+ }
2912
+ function describeCodingScope(codingContext, config) {
2913
+ const projectId = codingContext?.projectId ?? null;
2914
+ const branch = codingContext?.branch ?? null;
2915
+ if (!codingContext) {
2916
+ return {
2917
+ scope: "none",
2918
+ projectId: null,
2919
+ branch: null,
2920
+ effectiveNamespace: null,
2921
+ readFallbacks: [],
2922
+ disabledReason: "no-context"
2923
+ };
2924
+ }
2925
+ if (!config.projectScope) {
2926
+ return {
2927
+ scope: "none",
2928
+ projectId,
2929
+ branch,
2930
+ effectiveNamespace: null,
2931
+ readFallbacks: [],
2932
+ disabledReason: "disabled"
2933
+ };
2934
+ }
2935
+ const trimmedId = typeof projectId === "string" ? projectId.trim() : "";
2936
+ if (!trimmedId) {
2937
+ return {
2938
+ scope: "none",
2939
+ projectId,
2940
+ branch,
2941
+ effectiveNamespace: null,
2942
+ readFallbacks: [],
2943
+ disabledReason: "empty-project"
2944
+ };
2945
+ }
2946
+ const overlay = resolveCodingNamespaceOverlay(codingContext, config);
2947
+ if (!overlay) {
2948
+ return {
2949
+ scope: "none",
2950
+ projectId,
2951
+ branch,
2952
+ effectiveNamespace: null,
2953
+ readFallbacks: [],
2954
+ disabledReason: "disabled"
2955
+ };
2956
+ }
2957
+ return {
2958
+ scope: overlay.scope,
2959
+ projectId,
2960
+ branch,
2961
+ effectiveNamespace: overlay.namespace,
2962
+ readFallbacks: overlay.readFallbacks,
2963
+ disabledReason: null
2964
+ };
2965
+ }
2966
+
2432
2967
  // src/orchestrator.ts
2433
2968
  function dedupeEntitySynthesisEvidenceEntries(entries) {
2434
2969
  const dedupedEvidenceEntries = [];
@@ -2493,6 +3028,20 @@ function fingerprintEntitySynthesisEvidence(entity) {
2493
3028
  fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? "");
2494
3029
  return fingerprint.digest("hex");
2495
3030
  }
3031
+ function mapRecallSourceToXrayServedBy(source) {
3032
+ switch (source) {
3033
+ case "recent_scan":
3034
+ return "recent-scan";
3035
+ case "hot_qmd":
3036
+ case "hot_embedding":
3037
+ case "cold_fallback":
3038
+ case "none":
3039
+ return "hybrid";
3040
+ }
3041
+ const _exhaustive = source;
3042
+ void _exhaustive;
3043
+ return "hybrid";
3044
+ }
2496
3045
  var abortRecallError = abortError;
2497
3046
  function throwIfRecallAborted(signal, message = "recall aborted") {
2498
3047
  throwIfAborted(signal, message);
@@ -2515,7 +3064,7 @@ async function raceRecallAbort(promise, signal, message = "recall aborted") {
2515
3064
  }
2516
3065
  var COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1e3;
2517
3066
  function defaultWorkspaceDir() {
2518
- return path5.join(os.homedir(), ".openclaw", "workspace");
3067
+ return path7.join(os.homedir(), ".openclaw", "workspace");
2519
3068
  }
2520
3069
  function sanitizeSessionKeyForFilename(sessionKey) {
2521
3070
  const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
@@ -2683,11 +3232,11 @@ function mergeGraphExpandedResults(primary, expanded) {
2683
3232
  return Array.from(mergedByPath.values());
2684
3233
  }
2685
3234
  function graphPathRelativeToStorage(storageDir, candidatePath) {
2686
- const absolutePath = path5.isAbsolute(candidatePath) ? candidatePath : path5.resolve(storageDir, candidatePath);
2687
- const rel = path5.relative(storageDir, absolutePath);
3235
+ const absolutePath = path7.isAbsolute(candidatePath) ? candidatePath : path7.resolve(storageDir, candidatePath);
3236
+ const rel = path7.relative(storageDir, absolutePath);
2688
3237
  if (!rel || rel === ".") return null;
2689
3238
  if (rel.startsWith("..")) return null;
2690
- return rel.split(path5.sep).join("/");
3239
+ return rel.split(path7.sep).join("/");
2691
3240
  }
2692
3241
  function normalizeGraphActivationScore(score) {
2693
3242
  const bounded = Number.isFinite(score) && score > 0 ? score : 0;
@@ -2829,7 +3378,7 @@ function buildMemoryPathById(allMemsForGraph, storageDir) {
2829
3378
  for (const mem of allMemsForGraph ?? []) {
2830
3379
  const id = mem.frontmatter.id;
2831
3380
  if (!id) continue;
2832
- pathById.set(id, path5.relative(storageDir, mem.path));
3381
+ pathById.set(id, path7.relative(storageDir, mem.path));
2833
3382
  }
2834
3383
  return pathById;
2835
3384
  }
@@ -2837,7 +3386,7 @@ function appendMemoryToGraphContext(options) {
2837
3386
  if (!Array.isArray(options.allMemsForGraph)) return;
2838
3387
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
2839
3388
  options.allMemsForGraph.push({
2840
- path: path5.join(options.storageDir, options.memoryRelPath),
3389
+ path: path7.join(options.storageDir, options.memoryRelPath),
2841
3390
  content: options.content,
2842
3391
  frontmatter: {
2843
3392
  id: options.memoryId,
@@ -2857,15 +3406,16 @@ function resolvePersistedMemoryRelativePath(options) {
2857
3406
  const persisted = options.pathById.get(options.memoryId);
2858
3407
  if (persisted) return persisted;
2859
3408
  if (options.category === "correction") {
2860
- return path5.join("corrections", `${options.memoryId}.md`);
3409
+ return path7.join("corrections", `${options.memoryId}.md`);
2861
3410
  }
3411
+ const subtree = options.category === "procedure" ? "procedures" : options.category === "reasoning_trace" ? "reasoning-traces" : "facts";
2862
3412
  const idParts = options.memoryId.split("-");
2863
3413
  const maybeTimestamp = Number(idParts[1]);
2864
3414
  if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
2865
3415
  const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
2866
- return path5.join("facts", day, `${options.memoryId}.md`);
3416
+ return path7.join(subtree, day, `${options.memoryId}.md`);
2867
3417
  }
2868
- return path5.join("facts", `${options.memoryId}.md`);
3418
+ return path7.join(subtree, `${options.memoryId}.md`);
2869
3419
  }
2870
3420
  var Orchestrator = class _Orchestrator {
2871
3421
  storage;
@@ -2884,12 +3434,39 @@ var Orchestrator = class _Orchestrator {
2884
3434
  localLlm;
2885
3435
  fastLlm;
2886
3436
  judgeVerdictCache;
2887
- fastGatewayLlm;
3437
+ /**
3438
+ * Per-orchestrator defer-counter map (issue #562, PR 2). Tracks how many
3439
+ * times the judge has returned `"defer"` for a given candidate content
3440
+ * hash so the defer cap can be enforced.
3441
+ */
3442
+ judgeDeferCounts;
3443
+ /**
3444
+ * Side-channel: number of facts deferred in the most recent
3445
+ * `persistExtraction` call (issue #562, PR 2). The caller reads this after
3446
+ * `persistExtraction` returns to decide whether to retain buffer turns for
3447
+ * the next extraction pass. Not part of the return signature because many
3448
+ * callers already destructure `persistedIds` by position.
3449
+ */
3450
+ lastPersistExtractionDeferredCount = 0;
3451
+ _fastGatewayLlm;
3452
+ get fastGatewayLlm() {
3453
+ return this._fastGatewayLlm;
3454
+ }
2888
3455
  modelRegistry;
2889
3456
  relevance;
2890
3457
  negatives;
2891
3458
  lastRecall;
2892
3459
  tierMigrationStatus;
3460
+ /**
3461
+ * In-memory X-ray snapshot from the most recent `recall()` call that
3462
+ * was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is
3463
+ * per-process; later slices add CLI/HTTP/MCP surfaces that consume
3464
+ * this via the shared renderer. `null` until the first capture, and
3465
+ * NEVER overwritten by a recall that did not request capture —
3466
+ * requests without the flag leave prior captures intact so the
3467
+ * capturing caller can still read their snapshot back.
3468
+ */
3469
+ lastXraySnapshot = null;
2893
3470
  embeddingFallback;
2894
3471
  conversationIndexDir;
2895
3472
  extraction;
@@ -2905,6 +3482,16 @@ var Orchestrator = class _Orchestrator {
2905
3482
  /** Lossless Context Management engine — proactive session archive + DAG summarization. */
2906
3483
  lcmEngine = null;
2907
3484
  rerankCache = new RerankCache();
3485
+ /**
3486
+ * Short-TTL cache for Memory Worth counter lookups so interactive recall
3487
+ * doesn't trigger a full `readAllMemories` scan per query. Keyed by
3488
+ * namespace; the filter unions across namespaces at query time. The TTL
3489
+ * is intentionally short (seconds, not minutes) because counters are
3490
+ * mutated by `recordMemoryOutcome` asynchronously and we'd rather serve
3491
+ * a 30-second-stale worth score than a stable-but-wrong one.
3492
+ */
3493
+ memoryWorthCounterCache = /* @__PURE__ */ new Map();
3494
+ static MEMORY_WORTH_CACHE_TTL_MS = 3e4;
2908
3495
  /**
2909
3496
  * Per-session workspace overrides keyed by sessionKey.
2910
3497
  * Set by the before_agent_start hook so recall() uses the correct
@@ -2912,6 +3499,14 @@ var Orchestrator = class _Orchestrator {
2912
3499
  * Using a Map prevents concurrent sessions from overwriting each other.
2913
3500
  */
2914
3501
  _recallWorkspaceOverrides = /* @__PURE__ */ new Map();
3502
+ /**
3503
+ * Per-session coding-agent context (issue #569). Populated by connectors at
3504
+ * session-start (PRs 5/6/7) via `setCodingContextForSession`. Used by both
3505
+ * the recall path and the write path so that memory routing respects the
3506
+ * project/branch scope a session is operating in (rule 42 — read + write
3507
+ * through the same namespace layer).
3508
+ */
3509
+ _codingContextBySession = /* @__PURE__ */ new Map();
2915
3510
  routingRulesStore = null;
2916
3511
  contentHashIndex = null;
2917
3512
  artifactSourceStatusCache = /* @__PURE__ */ new WeakMap();
@@ -2945,6 +3540,10 @@ var Orchestrator = class _Orchestrator {
2945
3540
  runtimePolicyValues = null;
2946
3541
  utilityRuntimeValues = null;
2947
3542
  evalShadowWriteChain = Promise.resolve();
3543
+ // Pending background observation-mode direct-answer annotations (#518).
3544
+ // Tracks fire-and-forget `annotateDirectAnswerTier` calls so callers (tests,
3545
+ // waitForDirectAnswerObservationIdle) can await settlement.
3546
+ directAnswerObservationChain = Promise.resolve();
2948
3547
  // Initialization gate: recall() awaits this before proceeding
2949
3548
  initPromise = null;
2950
3549
  resolveInit = null;
@@ -2983,6 +3582,9 @@ var Orchestrator = class _Orchestrator {
2983
3582
  this.deferredInitAbort = null;
2984
3583
  }
2985
3584
  }
3585
+ async disposeSearchBackendIfNeeded() {
3586
+ await this.qmd.dispose?.();
3587
+ }
2986
3588
  /** Set per-session workspace for the next recall() call (compaction reset). @internal */
2987
3589
  setRecallWorkspaceOverride(sessionKey, dir) {
2988
3590
  this._recallWorkspaceOverrides.set(sessionKey, dir);
@@ -2995,10 +3597,96 @@ var Orchestrator = class _Orchestrator {
2995
3597
  return resolvePrincipal(sessionKey, this.config);
2996
3598
  }
2997
3599
  resolveSelfNamespace(sessionKey) {
2998
- return defaultNamespaceForPrincipal(
3600
+ const base = defaultNamespaceForPrincipal(
2999
3601
  this.resolvePrincipal(sessionKey),
3000
3602
  this.config
3001
3603
  );
3604
+ return this.applyCodingNamespaceOverlay(sessionKey, base);
3605
+ }
3606
+ /**
3607
+ * Attach a coding-agent context to a session (issue #569). Called by the
3608
+ * Claude Code / Codex / Cursor connectors at session start after
3609
+ * `resolveGitContext(cwd)`. The context is consulted by the recall path
3610
+ * and the write path so that memories route to a project- (and optionally
3611
+ * branch-) scoped namespace.
3612
+ *
3613
+ * Pass `null` to clear.
3614
+ */
3615
+ setCodingContextForSession(sessionKey, codingContext) {
3616
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
3617
+ if (!this._codingContextBySession) {
3618
+ this._codingContextBySession = /* @__PURE__ */ new Map();
3619
+ }
3620
+ if (codingContext === null) {
3621
+ this._codingContextBySession.delete(sessionKey);
3622
+ return;
3623
+ }
3624
+ this._codingContextBySession.set(sessionKey, codingContext);
3625
+ }
3626
+ /**
3627
+ * Read-only accessor for the coding context attached to a session. Returns
3628
+ * `null` when none is set. Used by `remnic doctor` and by tests.
3629
+ *
3630
+ * Defensive `_codingContextBySession` lookup — legacy orchestrator-flush
3631
+ * tests use `Object.create(Orchestrator.prototype)` which does not run
3632
+ * class-field initializers, so the Map may be undefined on stubs.
3633
+ */
3634
+ getCodingContextForSession(sessionKey) {
3635
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
3636
+ return this._codingContextBySession?.get(sessionKey) ?? null;
3637
+ }
3638
+ /**
3639
+ * Shared helper used by both the recall path and the write path (rule 42).
3640
+ *
3641
+ * Given a base namespace computed from the principal, returns the overlaid
3642
+ * coding namespace when the session has a coding context AND
3643
+ * `codingMode.projectScope` is true AND `namespacesEnabled` is true.
3644
+ * Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.
3645
+ *
3646
+ * Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with
3647
+ * the principal-derived `baseNamespace` rather than replacing it, so two
3648
+ * principals working in the same repository do not share memories through
3649
+ * a common `project-*` namespace.
3650
+ *
3651
+ * Namespaces-disabled gate: when `namespacesEnabled` is false, the
3652
+ * storage router maps every namespace to the same `memoryDir`. Returning
3653
+ * `project-*` in that mode would create apparent route separation with
3654
+ * no actual storage isolation — a false-isolation trap. In that mode we
3655
+ * return `baseNamespace` unchanged so coding mode degrades to the existing
3656
+ * unscoped behavior.
3657
+ *
3658
+ * @internal
3659
+ */
3660
+ applyCodingNamespaceOverlay(sessionKey, baseNamespace) {
3661
+ if (!this.config.namespacesEnabled) return baseNamespace;
3662
+ const codingContext = this.getCodingContextForSession(sessionKey);
3663
+ const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
3664
+ if (!overlay) return baseNamespace;
3665
+ return combineNamespaces(baseNamespace, overlay.namespace);
3666
+ }
3667
+ /**
3668
+ * Read-side overlay: returns the list of namespaces a session should read
3669
+ * from, including any read fallbacks (branch → project asymmetry lands in
3670
+ * PR 3; PR 2 returns an empty fallbacks list).
3671
+ *
3672
+ * Returns `null` when:
3673
+ * - `namespacesEnabled` is false (overlay would create false isolation)
3674
+ * - no context attached to the session
3675
+ * - `codingMode.projectScope` is false (CLAUDE.md #30 escape hatch)
3676
+ *
3677
+ * The returned `namespace` / `readFallbacks` are RAW overlay fragments
3678
+ * (e.g. `project-origin-ab12`). Callers MUST combine them with the
3679
+ * principal-derived base through `combineNamespaces()` before passing to
3680
+ * storage, so principal isolation is preserved (rule 42).
3681
+ *
3682
+ * @internal
3683
+ */
3684
+ applyCodingRecallOverlay(sessionKey) {
3685
+ if (!this.config.namespacesEnabled) return null;
3686
+ const codingContext = this.getCodingContextForSession(sessionKey);
3687
+ const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
3688
+ if (!overlay) return null;
3689
+ return { namespace: overlay.namespace, readFallbacks: overlay.readFallbacks };
3002
3690
  }
3003
3691
  async getStorageForNamespace(namespace) {
3004
3692
  const ns = typeof namespace === "string" && namespace.trim().length > 0 ? namespace.trim() : this.config.defaultNamespace;
@@ -3083,7 +3771,7 @@ var Orchestrator = class _Orchestrator {
3083
3771
  this.config = config;
3084
3772
  this.profiler = new ProfilingCollector({
3085
3773
  enabled: config.profilingEnabled,
3086
- storageDir: config.profilingStorageDir || path5.join(config.memoryDir, "profiling"),
3774
+ storageDir: config.profilingStorageDir || path7.join(config.memoryDir, "profiling"),
3087
3775
  maxTraces: config.profilingMaxTraces
3088
3776
  });
3089
3777
  this.storageRouter = new NamespaceStorageRouter(config);
@@ -3110,7 +3798,7 @@ var Orchestrator = class _Orchestrator {
3110
3798
  this.compounding = config.compoundingEnabled ? new CompoundingEngine(config) : void 0;
3111
3799
  this.buffer = new SmartBuffer(config, this.storage);
3112
3800
  this.transcript = new TranscriptManager(config);
3113
- this.conversationIndexDir = path5.join(
3801
+ this.conversationIndexDir = path7.join(
3114
3802
  config.memoryDir,
3115
3803
  "conversation-index",
3116
3804
  "chunks"
@@ -3134,6 +3822,7 @@ var Orchestrator = class _Orchestrator {
3134
3822
  this.transcript
3135
3823
  );
3136
3824
  this.judgeVerdictCache = createVerdictCache();
3825
+ this.judgeDeferCounts = createDeferCountMap();
3137
3826
  this.localLlm = new LocalLlmClient(config, this.modelRegistry);
3138
3827
  this.localLlm.disableThinking = config.localLlmDisableThinking;
3139
3828
  this.fastLlm = config.localLlmFastEnabled ? (() => {
@@ -3149,7 +3838,7 @@ var Orchestrator = class _Orchestrator {
3149
3838
  client.disableThinking = true;
3150
3839
  return client;
3151
3840
  })() : this.localLlm;
3152
- this.fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig) : null;
3841
+ this._fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig) : null;
3153
3842
  if (config.modelSource === "gateway") {
3154
3843
  log.debug(
3155
3844
  `orchestrator: gateway model source active` + (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : "") + (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : "")
@@ -3163,7 +3852,7 @@ var Orchestrator = class _Orchestrator {
3163
3852
  this.modelRegistry
3164
3853
  );
3165
3854
  this.threading = new ThreadingManager(
3166
- path5.join(config.memoryDir, "threads"),
3855
+ path7.join(config.memoryDir, "threads"),
3167
3856
  config.threadingGapMinutes
3168
3857
  );
3169
3858
  this.tmtBuilder = new TmtBuilder(config.memoryDir, {
@@ -3349,9 +4038,9 @@ var Orchestrator = class _Orchestrator {
3349
4038
  * routes through the gateway chain. Otherwise uses the local fast LLM.
3350
4039
  */
3351
4040
  async fastChatCompletion(messages, options) {
3352
- if (this.fastGatewayLlm && this.config.modelSource === "gateway") {
4041
+ if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
3353
4042
  const agentId = this.config.fastGatewayAgentId || this.config.gatewayAgentId || void 0;
3354
- const result2 = await this.fastGatewayLlm.chatCompletion(
4043
+ const result2 = await this._fastGatewayLlm.chatCompletion(
3355
4044
  messages,
3356
4045
  { temperature: options.temperature, maxTokens: options.maxTokens, timeoutMs: options.timeoutMs, agentId }
3357
4046
  );
@@ -3366,7 +4055,7 @@ var Orchestrator = class _Orchestrator {
3366
4055
  * Otherwise returns the local fast LLM directly.
3367
4056
  */
3368
4057
  get fastLlmForRerank() {
3369
- if (this.fastGatewayLlm && this.config.modelSource === "gateway") {
4058
+ if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
3370
4059
  return {
3371
4060
  chatCompletion: (messages, options) => this.fastChatCompletion(messages, options ?? {})
3372
4061
  };
@@ -3408,7 +4097,7 @@ var Orchestrator = class _Orchestrator {
3408
4097
  promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled
3409
4098
  });
3410
4099
  if (this.config.factDeduplicationEnabled) {
3411
- const stateDir = path5.join(this.config.memoryDir, "state");
4100
+ const stateDir = path7.join(this.config.memoryDir, "state");
3412
4101
  this.contentHashIndex = new ContentHashIndex(stateDir);
3413
4102
  await this.contentHashIndex.load();
3414
4103
  log.info(
@@ -3437,7 +4126,7 @@ var Orchestrator = class _Orchestrator {
3437
4126
  const files = await readdir3(wsDir).catch(() => []);
3438
4127
  for (const f of files) {
3439
4128
  if (!f.startsWith(".compaction-reset-signal-")) continue;
3440
- const fp = path5.join(wsDir, f);
4129
+ const fp = path7.join(wsDir, f);
3441
4130
  const s = await stat3(fp).catch(() => null);
3442
4131
  if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
3443
4132
  await unlink2(fp).catch(() => {
@@ -3466,6 +4155,7 @@ var Orchestrator = class _Orchestrator {
3466
4155
  (entry) => entry.namespace === this.config.defaultNamespace
3467
4156
  )?.state ?? "unknown";
3468
4157
  if (defaultState === "missing") {
4158
+ await this.disposeSearchBackendIfNeeded();
3469
4159
  this.qmd = new NoopSearchBackend();
3470
4160
  log.warn(
3471
4161
  "Search collection missing for Remnic memory store; disabling search retrieval for this runtime (fallback retrieval remains enabled)"
@@ -3526,10 +4216,11 @@ var Orchestrator = class _Orchestrator {
3526
4216
  log.info("QMD startup sync: updating index to match current disk state");
3527
4217
  if (this.config.namespacesEnabled) {
3528
4218
  await this.namespaceSearchRouter.updateNamespaces(
3529
- this.configuredNamespaces()
4219
+ this.configuredNamespaces(),
4220
+ { signal }
3530
4221
  );
3531
4222
  } else {
3532
- await this.qmd.update();
4223
+ await this.qmd.update({ signal });
3533
4224
  }
3534
4225
  log.info("QMD startup sync: complete");
3535
4226
  this.deferredSyncSucceeded = true;
@@ -3546,7 +4237,7 @@ var Orchestrator = class _Orchestrator {
3546
4237
  const warmupNs = this.config.defaultNamespace;
3547
4238
  log.info("QMD warmup: pre-loading models with a test search");
3548
4239
  warmupPromises.push(
3549
- this.qmd.search("warmup", warmupNs, 1).then(() => {
4240
+ this.qmd.search("warmup", warmupNs, 1, void 0, { signal }).then(() => {
3550
4241
  log.info("QMD warmup: complete");
3551
4242
  }).catch((err) => {
3552
4243
  log.debug(`QMD warmup search failed (non-fatal): ${err}`);
@@ -3686,6 +4377,7 @@ var Orchestrator = class _Orchestrator {
3686
4377
  if ("available" in this.qmd) {
3687
4378
  this.qmd.available = false;
3688
4379
  }
4380
+ await this.disposeSearchBackendIfNeeded();
3689
4381
  this.qmd = new NoopSearchBackend();
3690
4382
  log.warn("startupSearchSync: search collection missing; disabling search (fallback retrieval remains enabled)");
3691
4383
  return false;
@@ -3700,9 +4392,12 @@ var Orchestrator = class _Orchestrator {
3700
4392
  log.info("startupSearchSync: updating index to match current disk state");
3701
4393
  let namespacesUpdated = 0;
3702
4394
  if (this.config.namespacesEnabled) {
3703
- namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(namespaces);
4395
+ namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(
4396
+ namespaces,
4397
+ { signal }
4398
+ );
3704
4399
  } else {
3705
- await this.qmd.update(signal);
4400
+ await this.qmd.update({ signal });
3706
4401
  }
3707
4402
  if (signal?.aborted) {
3708
4403
  log.debug("startupSearchSync: aborted after update");
@@ -3746,7 +4441,7 @@ var Orchestrator = class _Orchestrator {
3746
4441
  */
3747
4442
  async autoRegisterDaySummaryCron() {
3748
4443
  const home = resolveHomeDir();
3749
- const jobsPath = path5.join(home, ".openclaw", "cron", "jobs.json");
4444
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
3750
4445
  try {
3751
4446
  if (!existsSync2(jobsPath)) {
3752
4447
  log.debug(
@@ -3769,8 +4464,8 @@ var Orchestrator = class _Orchestrator {
3769
4464
  }
3770
4465
  }
3771
4466
  async autoRegisterNightlyGovernanceCron() {
3772
- const home = process.env.HOME || os.homedir();
3773
- const jobsPath = path5.join(home, ".openclaw", "cron", "jobs.json");
4467
+ const home = resolveHomeDir();
4468
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
3774
4469
  try {
3775
4470
  if (!existsSync2(jobsPath)) {
3776
4471
  log.debug("nightly governance cron: jobs.json not found, skipping auto-register");
@@ -3792,7 +4487,7 @@ var Orchestrator = class _Orchestrator {
3792
4487
  }
3793
4488
  async autoRegisterProceduralMiningCron() {
3794
4489
  const home = resolveHomeDir();
3795
- const jobsPath = path5.join(home, ".openclaw", "cron", "jobs.json");
4490
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
3796
4491
  try {
3797
4492
  if (!existsSync2(jobsPath)) {
3798
4493
  log.debug("procedural mining cron: jobs.json not found, skipping auto-register");
@@ -3812,7 +4507,7 @@ var Orchestrator = class _Orchestrator {
3812
4507
  }
3813
4508
  async autoRegisterContradictionScanCron() {
3814
4509
  const home = resolveHomeDir();
3815
- const jobsPath = path5.join(home, ".openclaw", "cron", "jobs.json");
4510
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
3816
4511
  try {
3817
4512
  if (!existsSync2(jobsPath)) {
3818
4513
  log.debug("contradiction scan cron: jobs.json not found, skipping auto-register");
@@ -3848,15 +4543,15 @@ var Orchestrator = class _Orchestrator {
3848
4543
  this.lastFileHygieneRunAtMs = now;
3849
4544
  if (hygiene.rotateEnabled) {
3850
4545
  for (const rel of hygiene.rotatePaths) {
3851
- const abs = path5.isAbsolute(rel) ? rel : path5.join(this.config.workspaceDir, rel);
4546
+ const abs = path7.isAbsolute(rel) ? rel : path7.join(this.config.workspaceDir, rel);
3852
4547
  try {
3853
- const raw = await readFile3(abs, "utf-8");
4548
+ const raw = await readFile4(abs, "utf-8");
3854
4549
  if (raw.length > hygiene.rotateMaxBytes) {
3855
- const archiveDir = path5.join(
4550
+ const archiveDir = path7.join(
3856
4551
  this.config.workspaceDir,
3857
4552
  hygiene.archiveDir
3858
4553
  );
3859
- const base = path5.basename(abs);
4554
+ const base = path7.basename(abs);
3860
4555
  const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
3861
4556
  const { newContent } = await rotateMarkdownFileToArchive({
3862
4557
  filePath: abs,
@@ -3864,7 +4559,7 @@ var Orchestrator = class _Orchestrator {
3864
4559
  archivePrefix: prefix,
3865
4560
  keepTailChars: hygiene.rotateKeepTailChars
3866
4561
  });
3867
- await writeFile3(abs, newContent, "utf-8");
4562
+ await writeFile4(abs, newContent, "utf-8");
3868
4563
  }
3869
4564
  } catch {
3870
4565
  }
@@ -3881,8 +4576,8 @@ var Orchestrator = class _Orchestrator {
3881
4576
  log.warn(w.message);
3882
4577
  }
3883
4578
  if (hygiene.warningsLogEnabled && warnings.length > 0) {
3884
- const fp = path5.join(this.config.memoryDir, hygiene.warningsLogPath);
3885
- await mkdir4(path5.dirname(fp), { recursive: true });
4579
+ const fp = path7.join(this.config.memoryDir, hygiene.warningsLogPath);
4580
+ await mkdir5(path7.dirname(fp), { recursive: true });
3886
4581
  const stamp = (/* @__PURE__ */ new Date()).toISOString();
3887
4582
  const block = `
3888
4583
 
@@ -3891,11 +4586,11 @@ var Orchestrator = class _Orchestrator {
3891
4586
  ` + warnings.map((w) => `- ${w.message}`).join("\n") + "\n";
3892
4587
  let existing = "";
3893
4588
  try {
3894
- existing = await readFile3(fp, "utf-8");
4589
+ existing = await readFile4(fp, "utf-8");
3895
4590
  } catch {
3896
4591
  existing = "# Engram File Hygiene Warnings\n";
3897
4592
  }
3898
- await writeFile3(fp, existing + block, "utf-8");
4593
+ await writeFile4(fp, existing + block, "utf-8");
3899
4594
  }
3900
4595
  }
3901
4596
  }
@@ -3979,14 +4674,15 @@ var Orchestrator = class _Orchestrator {
3979
4674
  }
3980
4675
  for (const cluster of clusters) {
3981
4676
  try {
3982
- let prompt = buildConsolidationPrompt(cluster);
4677
+ const operatorAwareEnabled = this.config.operatorAwareConsolidationEnabled === true;
4678
+ let prompt = operatorAwareEnabled ? buildOperatorAwareConsolidationPrompt(cluster) : buildConsolidationPrompt(cluster);
3983
4679
  if (extensionsBlock.length > 0) {
3984
4680
  prompt += "\n\n" + extensionsBlock;
3985
4681
  }
3986
4682
  const messages = [
3987
4683
  {
3988
4684
  role: "system",
3989
- content: "You are a memory consolidation system. Output only the consolidated memory text."
4685
+ content: operatorAwareEnabled ? 'You are a memory consolidation system. Return ONLY a JSON object with two keys, "operator" and "output". The "operator" value MUST be one of the exact strings "merge", "update", or "split" \u2014 never a pipe-separated placeholder, never prose. The "output" value is the canonical memory text.' : "You are a memory consolidation system. Output only the consolidated memory text."
3990
4686
  },
3991
4687
  { role: "user", content: prompt }
3992
4688
  ];
@@ -4012,13 +4708,31 @@ var Orchestrator = class _Orchestrator {
4012
4708
  result.errors++;
4013
4709
  continue;
4014
4710
  }
4015
- const canonicalContent = parseConsolidationResponse(response.content);
4711
+ let canonicalContent;
4712
+ let operator;
4713
+ if (operatorAwareEnabled) {
4714
+ const parsed = parseOperatorAwareConsolidationResponse(
4715
+ response.content,
4716
+ cluster
4717
+ );
4718
+ canonicalContent = parsed.output;
4719
+ operator = parsed.operator;
4720
+ } else {
4721
+ canonicalContent = parseConsolidationResponse(response.content);
4722
+ operator = chooseConsolidationOperator(cluster);
4723
+ }
4016
4724
  cluster.canonicalContent = canonicalContent;
4017
4725
  const sorted = [...cluster.memories].sort(
4018
4726
  (a, b) => new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime()
4019
4727
  );
4020
4728
  const newest = sorted[0];
4021
4729
  const lineageIds = cluster.memories.map((m) => m.frontmatter.id);
4730
+ const derivedFromEntries = [];
4731
+ for (const m of cluster.memories) {
4732
+ if (!m.path) continue;
4733
+ const entry = await this.storage.snapshotForProvenance(m.path);
4734
+ if (entry) derivedFromEntries.push(entry);
4735
+ }
4022
4736
  const canonicalId = await this.storage.writeMemory(
4023
4737
  newest.frontmatter.category,
4024
4738
  canonicalContent,
@@ -4031,7 +4745,9 @@ var Orchestrator = class _Orchestrator {
4031
4745
  )
4032
4746
  ],
4033
4747
  source: "semantic-consolidation",
4034
- lineage: lineageIds
4748
+ lineage: lineageIds,
4749
+ derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : void 0,
4750
+ derivedVia: operator
4035
4751
  }
4036
4752
  );
4037
4753
  result.memoriesConsolidated++;
@@ -4273,18 +4989,18 @@ ${evidenceText}`
4273
4989
  const datesToScan = [yesterday, utcToday].filter(
4274
4990
  (v, i, a) => a.indexOf(v) === i
4275
4991
  );
4276
- const factsBaseDir = path5.join(storage.dir, "facts");
4992
+ const factsBaseDir = path7.join(storage.dir, "facts");
4277
4993
  const MAX_CHARS = 1e5;
4278
4994
  const facts = [];
4279
4995
  for (const date of datesToScan) {
4280
- const factsDir = path5.join(factsBaseDir, date);
4996
+ const factsDir = path7.join(factsBaseDir, date);
4281
4997
  try {
4282
4998
  const entries = await readdir3(factsDir, { withFileTypes: true });
4283
4999
  for (const entry of entries) {
4284
5000
  if (!entry.name.endsWith(".md")) continue;
4285
- const fullPath = path5.join(factsDir, entry.name);
5001
+ const fullPath = path7.join(factsDir, entry.name);
4286
5002
  try {
4287
- const raw = await readFile3(fullPath, "utf-8");
5003
+ const raw = await readFile4(fullPath, "utf-8");
4288
5004
  const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
4289
5005
  if (!fmMatch) continue;
4290
5006
  const fmBlock = fmMatch[1];
@@ -4298,7 +5014,7 @@ ${evidenceText}`
4298
5014
  facts.push({
4299
5015
  path: fullPath,
4300
5016
  frontmatter: {
4301
- id: fm.id || path5.basename(entry.name, ".md"),
5017
+ id: fm.id || path7.basename(entry.name, ".md"),
4302
5018
  category: fm.category || "fact",
4303
5019
  created: fm.created || "unknown",
4304
5020
  updated: fm.updated || fm.created || "unknown",
@@ -4319,15 +5035,15 @@ ${evidenceText}`
4319
5035
  (a, b) => a.frontmatter.created < b.frontmatter.created ? -1 : 1
4320
5036
  );
4321
5037
  const hourlySummaries = [];
4322
- const hourlyBaseDir = path5.join(storage.dir, "summaries", "hourly");
5038
+ const hourlyBaseDir = path7.join(storage.dir, "summaries", "hourly");
4323
5039
  try {
4324
5040
  const sessionKeys = await readdir3(hourlyBaseDir, { withFileTypes: true });
4325
5041
  for (const sk of sessionKeys) {
4326
5042
  if (!sk.isDirectory()) continue;
4327
5043
  for (const date of datesToScan) {
4328
- const summaryFile = path5.join(hourlyBaseDir, sk.name, `${date}.md`);
5044
+ const summaryFile = path7.join(hourlyBaseDir, sk.name, `${date}.md`);
4329
5045
  try {
4330
- const raw = await readFile3(summaryFile, "utf-8");
5046
+ const raw = await readFile4(summaryFile, "utf-8");
4331
5047
  if (raw.trim().length > 0) {
4332
5048
  hourlySummaries.push(raw.trim());
4333
5049
  }
@@ -4423,13 +5139,13 @@ ${evidenceText}`
4423
5139
  }
4424
5140
  async getLastGraphRecallSnapshot(namespace) {
4425
5141
  const storage = await this.getStorage(namespace);
4426
- const snapshotPath = path5.join(
5142
+ const snapshotPath = path7.join(
4427
5143
  storage.dir,
4428
5144
  "state",
4429
5145
  "last_graph_recall.json"
4430
5146
  );
4431
5147
  try {
4432
- const raw = await readFile3(snapshotPath, "utf-8");
5148
+ const raw = await readFile4(snapshotPath, "utf-8");
4433
5149
  const parsed = JSON.parse(raw);
4434
5150
  if (!parsed || typeof parsed !== "object") return null;
4435
5151
  return {
@@ -4462,9 +5178,9 @@ ${evidenceText}`
4462
5178
  }
4463
5179
  async getLastIntentSnapshot(namespace) {
4464
5180
  const storage = await this.getStorage(namespace);
4465
- const snapshotPath = path5.join(storage.dir, "state", "last_intent.json");
5181
+ const snapshotPath = path7.join(storage.dir, "state", "last_intent.json");
4466
5182
  try {
4467
- const raw = await readFile3(snapshotPath, "utf-8");
5183
+ const raw = await readFile4(snapshotPath, "utf-8");
4468
5184
  const parsed = JSON.parse(raw);
4469
5185
  if (!parsed || typeof parsed !== "object") return null;
4470
5186
  const graphDecision = parsed.graphDecision && typeof parsed.graphDecision === "object" ? parsed.graphDecision : void 0;
@@ -4495,13 +5211,13 @@ ${evidenceText}`
4495
5211
  }
4496
5212
  async getLastQmdRecallSnapshot(namespace) {
4497
5213
  const storage = await this.getStorage(namespace);
4498
- const snapshotPath = path5.join(
5214
+ const snapshotPath = path7.join(
4499
5215
  storage.dir,
4500
5216
  "state",
4501
5217
  "last_qmd_recall.json"
4502
5218
  );
4503
5219
  try {
4504
- const raw = await readFile3(snapshotPath, "utf-8");
5220
+ const raw = await readFile4(snapshotPath, "utf-8");
4505
5221
  const parsed = JSON.parse(raw);
4506
5222
  if (!parsed || typeof parsed !== "object") return null;
4507
5223
  return {
@@ -4647,7 +5363,7 @@ ${r.snippet.trim()}
4647
5363
  const entries = await readdir3(dir, { withFileTypes: true });
4648
5364
  let total = 0;
4649
5365
  for (const entry of entries) {
4650
- const fullPath = path5.join(dir, entry.name);
5366
+ const fullPath = path7.join(dir, entry.name);
4651
5367
  if (entry.isDirectory()) {
4652
5368
  total += await this.countConversationChunkDocs(fullPath);
4653
5369
  continue;
@@ -4918,11 +5634,24 @@ ${r.snippet.trim()}
4918
5634
  reject(new Error("recall timeout"));
4919
5635
  }, RECALL_TIMEOUT_MS);
4920
5636
  });
5637
+ let recallResult;
4921
5638
  try {
4922
- return await Promise.race([recallPromise, timeoutPromise]);
5639
+ recallResult = await Promise.race([recallPromise, timeoutPromise]);
4923
5640
  } finally {
4924
5641
  if (timeoutHandle) clearTimeout(timeoutHandle);
4925
5642
  }
5643
+ if (this.config.recallDirectAnswerEnabled && sessionKey) {
5644
+ try {
5645
+ this.enqueueDirectAnswerObservation(
5646
+ prompt,
5647
+ sessionKey,
5648
+ options.namespace?.trim() || void 0
5649
+ );
5650
+ } catch (err) {
5651
+ log.debug(`direct-answer observation setup failed: ${err}`);
5652
+ }
5653
+ }
5654
+ return recallResult;
4926
5655
  } catch (err) {
4927
5656
  this.logRecallFailure(err);
4928
5657
  this.profiler.endTrace();
@@ -4931,6 +5660,183 @@ ${r.snippet.trim()}
4931
5660
  options.abortSignal?.removeEventListener("abort", onAbort);
4932
5661
  }
4933
5662
  }
5663
+ /**
5664
+ * Return the most recent X-ray snapshot captured during a
5665
+ * `recall()` call that passed `xrayCapture: true` (issue #570 PR 1).
5666
+ * Returns `null` when no such capture has occurred on this
5667
+ * orchestrator instance. Returned snapshot is a deep copy so
5668
+ * caller mutation cannot tear the stored value.
5669
+ */
5670
+ getLastXraySnapshot() {
5671
+ if (!this.lastXraySnapshot) return null;
5672
+ return structuredClone(this.lastXraySnapshot);
5673
+ }
5674
+ /** Clear the captured X-ray snapshot. Exposed for tests / explicit reset. */
5675
+ clearLastXraySnapshot() {
5676
+ this.lastXraySnapshot = null;
5677
+ }
5678
+ /**
5679
+ * Await the in-flight observation-mode direct-answer annotation chain.
5680
+ * Resolves to true when settled, false on timeout.
5681
+ */
5682
+ async waitForDirectAnswerObservationIdle(timeoutMs = 6e4) {
5683
+ let timeoutHandle = null;
5684
+ try {
5685
+ const timeoutPromise = new Promise((resolve) => {
5686
+ timeoutHandle = setTimeout(() => resolve("timeout"), timeoutMs);
5687
+ });
5688
+ const result = await Promise.race([
5689
+ this.directAnswerObservationChain.then(() => "ok"),
5690
+ timeoutPromise
5691
+ ]);
5692
+ if (result === "timeout") {
5693
+ log.warn(
5694
+ `waitForDirectAnswerObservationIdle timed out after ${timeoutMs}ms`
5695
+ );
5696
+ return false;
5697
+ }
5698
+ return true;
5699
+ } finally {
5700
+ if (timeoutHandle) clearTimeout(timeoutHandle);
5701
+ }
5702
+ }
5703
+ enqueueDirectAnswerObservation(prompt, sessionKey, namespaceOverride) {
5704
+ const expectedSnapshot = this.lastRecall.get(sessionKey);
5705
+ if (expectedSnapshot === null) return;
5706
+ if (expectedSnapshot.plannerMode === "no_recall") return;
5707
+ const principal = resolvePrincipal(sessionKey, this.config);
5708
+ const observationCodingOverlay = namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config) ? null : this.applyCodingRecallOverlay(sessionKey);
5709
+ const observationPrincipalSelf = defaultNamespaceForPrincipal(principal, this.config);
5710
+ const observationCodingSelf = observationCodingOverlay ? combineNamespaces(observationPrincipalSelf, observationCodingOverlay.namespace) : null;
5711
+ let observationNamespaces;
5712
+ if (namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)) {
5713
+ observationNamespaces = [namespaceOverride];
5714
+ } else if (observationCodingOverlay && observationCodingSelf) {
5715
+ const base = recallNamespacesForPrincipal(principal, this.config);
5716
+ const mapped = base.map(
5717
+ (ns) => ns === observationPrincipalSelf ? observationCodingSelf : ns
5718
+ );
5719
+ const fallbackNs = observationCodingOverlay.readFallbacks.map(
5720
+ (fallback) => combineNamespaces(observationPrincipalSelf, fallback)
5721
+ );
5722
+ observationNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
5723
+ } else {
5724
+ observationNamespaces = recallNamespacesForPrincipal(principal, this.config);
5725
+ }
5726
+ const observationQueryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {
5727
+ cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,
5728
+ cronRecallNormalizedQueryMaxChars: this.config.cronRecallNormalizedQueryMaxChars,
5729
+ cronRecallInstructionHeavyTokenCap: this.effectiveCronRecallInstructionHeavyTokenCap(),
5730
+ cronConversationRecallMode: this.config.cronConversationRecallMode
5731
+ });
5732
+ const observationQuery = observationQueryPolicy.retrievalQuery || prompt;
5733
+ const expectedIdentity = {
5734
+ writeNonce: expectedSnapshot.writeNonce,
5735
+ traceId: expectedSnapshot.traceId,
5736
+ recordedAt: expectedSnapshot.recordedAt
5737
+ };
5738
+ const previous = this.directAnswerObservationChain;
5739
+ this.directAnswerObservationChain = previous.catch(() => void 0).then(async () => {
5740
+ try {
5741
+ await this.annotateDirectAnswerTier(
5742
+ observationQuery,
5743
+ sessionKey,
5744
+ observationNamespaces,
5745
+ expectedIdentity,
5746
+ void 0
5747
+ );
5748
+ } catch (err) {
5749
+ log.debug(`direct-answer observation chain error: ${err}`);
5750
+ }
5751
+ });
5752
+ }
5753
+ async annotateDirectAnswerTier(prompt, sessionKey, namespaces, expectedIdentity, _parentAbortSignal) {
5754
+ const tierStart = Date.now();
5755
+ try {
5756
+ if (namespaces.length === 0) return;
5757
+ const trustZoneByNsAndRecordId = /* @__PURE__ */ new Map();
5758
+ const trustZoneKey = (ns, recordId) => `${ns}\0${recordId}`;
5759
+ const scopedStorages = /* @__PURE__ */ new Map();
5760
+ for (const ns of namespaces) {
5761
+ const storage = await this.storageRouter.storageFor(ns);
5762
+ scopedStorages.set(ns, storage);
5763
+ const trustZones = await listTrustZoneRecords({
5764
+ memoryDir: storage.dir,
5765
+ trustZoneStoreDir: this.config.trustZoneStoreDir,
5766
+ limit: 200
5767
+ }).catch(() => ({
5768
+ allRecords: []
5769
+ }));
5770
+ for (const record of trustZones.allRecords ?? []) {
5771
+ trustZoneByNsAndRecordId.set(
5772
+ trustZoneKey(ns, record.recordId),
5773
+ record.zone
5774
+ );
5775
+ }
5776
+ }
5777
+ const memoryNamespaceByPath = /* @__PURE__ */ new Map();
5778
+ const memoryNamespaceById = /* @__PURE__ */ new Map();
5779
+ let candidatesConsidered = 0;
5780
+ const sources = {
5781
+ taxonomy: DEFAULT_TAXONOMY,
5782
+ listCandidateMemories: async (options) => {
5783
+ const targetNs = options.namespace;
5784
+ const storage = scopedStorages.get(targetNs) ?? await this.storageRouter.storageFor(targetNs);
5785
+ const all = await storage.readAllMemories();
5786
+ const active = [];
5787
+ for (const m of all) {
5788
+ if ((m.frontmatter.status ?? "active") === "active") {
5789
+ active.push(m);
5790
+ memoryNamespaceByPath.set(m.path, targetNs);
5791
+ if (m.frontmatter.id) {
5792
+ memoryNamespaceById.set(m.frontmatter.id, targetNs);
5793
+ }
5794
+ }
5795
+ }
5796
+ candidatesConsidered += active.length;
5797
+ return active;
5798
+ },
5799
+ trustZoneFor: async (memoryId) => {
5800
+ const ns = memoryNamespaceById.get(memoryId);
5801
+ if (!ns) return null;
5802
+ return trustZoneByNsAndRecordId.get(
5803
+ trustZoneKey(ns, memoryId)
5804
+ ) ?? null;
5805
+ },
5806
+ importanceFor: (memory) => typeof memory.frontmatter.importance?.score === "number" ? memory.frontmatter.importance.score : 0
5807
+ };
5808
+ let result;
5809
+ for (const ns of namespaces) {
5810
+ const r = await tryDirectAnswer({
5811
+ query: prompt,
5812
+ namespace: ns,
5813
+ config: this.config,
5814
+ sources
5815
+ });
5816
+ if (r.eligible && r.winner) {
5817
+ result = r;
5818
+ break;
5819
+ }
5820
+ }
5821
+ if (!result?.eligible || !result?.winner) return;
5822
+ const explain = {
5823
+ tier: "direct-answer",
5824
+ tierReason: result.narrative,
5825
+ filteredBy: result.filteredBy,
5826
+ candidatesConsidered,
5827
+ latencyMs: Date.now() - tierStart,
5828
+ sourceAnchors: [{ path: result.winner.memory.path }]
5829
+ };
5830
+ await this.lastRecall.annotateTierExplain(
5831
+ sessionKey,
5832
+ explain,
5833
+ expectedIdentity
5834
+ );
5835
+ } catch (err) {
5836
+ if (err instanceof Error && err.name === "AbortError") return;
5837
+ log.debug(`direct-answer observation failed: ${err}`);
5838
+ }
5839
+ }
4934
5840
  logRecallFailure(err) {
4935
5841
  const now = Date.now();
4936
5842
  const errorMsg = err instanceof Error ? err.message : String(err);
@@ -5334,7 +6240,7 @@ ${r.snippet.trim()}
5334
6240
  0
5335
6241
  );
5336
6242
  seedPaths.push(
5337
- ...seedRelativePaths.map((rel) => path5.join(storage.dir, rel))
6243
+ ...seedRelativePaths.map((rel) => path7.join(storage.dir, rel))
5338
6244
  );
5339
6245
  const seedSet = new Set(seedRelativePaths);
5340
6246
  const expanded = await this.graphIndexFor(storage).spreadingActivation(
@@ -5344,7 +6250,7 @@ ${r.snippet.trim()}
5344
6250
  if (expanded.length === 0) continue;
5345
6251
  for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
5346
6252
  if (seedSet.has(candidate.path)) continue;
5347
- const memoryPath = path5.resolve(storage.dir, candidate.path);
6253
+ const memoryPath = path7.resolve(storage.dir, candidate.path);
5348
6254
  const memory = await storage.readMemoryByPath(memoryPath);
5349
6255
  if (!memory) continue;
5350
6256
  if (isArtifactMemoryPath(memory.path)) continue;
@@ -5368,7 +6274,7 @@ ${r.snippet.trim()}
5368
6274
  path: memory.path,
5369
6275
  score,
5370
6276
  namespace,
5371
- seed: path5.resolve(storage.dir, candidate.seed),
6277
+ seed: path7.resolve(storage.dir, candidate.seed),
5372
6278
  hopDepth: candidate.hopDepth,
5373
6279
  decayedWeight: candidate.decayedWeight,
5374
6280
  graphType: candidate.graphType
@@ -5384,12 +6290,12 @@ ${r.snippet.trim()}
5384
6290
  }
5385
6291
  async recordLastGraphRecallSnapshot(options) {
5386
6292
  try {
5387
- const snapshotPath = path5.join(
6293
+ const snapshotPath = path7.join(
5388
6294
  options.storage.dir,
5389
6295
  "state",
5390
6296
  "last_graph_recall.json"
5391
6297
  );
5392
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
6298
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
5393
6299
  const now = (/* @__PURE__ */ new Date()).toISOString();
5394
6300
  const totalSeedCount = options.seedPaths.length;
5395
6301
  const totalExpandedCount = options.expandedPaths.length;
@@ -5416,20 +6322,20 @@ ${r.snippet.trim()}
5416
6322
  finalResults: (options.finalResults ?? []).slice(0, 64),
5417
6323
  shadowComparison: options.shadowComparison
5418
6324
  };
5419
- await writeFile3(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
6325
+ await writeFile4(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
5420
6326
  } catch (err) {
5421
6327
  log.debug(`last graph recall write failed: ${err}`);
5422
6328
  }
5423
6329
  }
5424
6330
  async recordLastIntentSnapshot(options) {
5425
6331
  try {
5426
- const snapshotPath = path5.join(
6332
+ const snapshotPath = path7.join(
5427
6333
  options.storage.dir,
5428
6334
  "state",
5429
6335
  "last_intent.json"
5430
6336
  );
5431
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
5432
- await writeFile3(
6337
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
6338
+ await writeFile4(
5433
6339
  snapshotPath,
5434
6340
  JSON.stringify(options.snapshot, null, 2),
5435
6341
  "utf-8"
@@ -5440,13 +6346,13 @@ ${r.snippet.trim()}
5440
6346
  }
5441
6347
  async recordLastQmdRecallSnapshot(options) {
5442
6348
  try {
5443
- const snapshotPath = path5.join(
6349
+ const snapshotPath = path7.join(
5444
6350
  options.storage.dir,
5445
6351
  "state",
5446
6352
  "last_qmd_recall.json"
5447
6353
  );
5448
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
5449
- await writeFile3(
6354
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
6355
+ await writeFile4(
5450
6356
  snapshotPath,
5451
6357
  JSON.stringify(options.snapshot, null, 2),
5452
6358
  "utf-8"
@@ -5460,9 +6366,9 @@ ${r.snippet.trim()}
5460
6366
  const stateDir = await this.resolveStateDirForNamespace(
5461
6367
  options.namespace
5462
6368
  );
5463
- const snapshotPath = path5.join(stateDir, "last_intent.json");
5464
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
5465
- await writeFile3(
6369
+ const snapshotPath = path7.join(stateDir, "last_intent.json");
6370
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
6371
+ await writeFile4(
5466
6372
  snapshotPath,
5467
6373
  JSON.stringify(options.snapshot, null, 2),
5468
6374
  "utf-8"
@@ -5473,12 +6379,12 @@ ${r.snippet.trim()}
5473
6379
  }
5474
6380
  async resolveStateDirForNamespace(namespace) {
5475
6381
  if (!this.config.namespacesEnabled) {
5476
- return path5.join(this.config.memoryDir, "state");
6382
+ return path7.join(this.config.memoryDir, "state");
5477
6383
  }
5478
6384
  if (namespace !== this.config.defaultNamespace) {
5479
- return path5.join(this.config.memoryDir, "namespaces", namespace, "state");
6385
+ return path7.join(this.config.memoryDir, "namespaces", namespace, "state");
5480
6386
  }
5481
- const candidate = path5.join(
6387
+ const candidate = path7.join(
5482
6388
  this.config.memoryDir,
5483
6389
  "namespaces",
5484
6390
  this.config.defaultNamespace
@@ -5486,11 +6392,11 @@ ${r.snippet.trim()}
5486
6392
  try {
5487
6393
  const candidateStat = await stat3(candidate);
5488
6394
  if (candidateStat.isDirectory()) {
5489
- return path5.join(candidate, "state");
6395
+ return path7.join(candidate, "state");
5490
6396
  }
5491
6397
  } catch {
5492
6398
  }
5493
- return path5.join(this.config.memoryDir, "state");
6399
+ return path7.join(this.config.memoryDir, "state");
5494
6400
  }
5495
6401
  buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
5496
6402
  return results.slice(0, limit).map((result) => ({
@@ -5576,7 +6482,10 @@ ${r.snippet.trim()}
5576
6482
  }
5577
6483
  return reserved;
5578
6484
  }
5579
- getRecallBudgetChars() {
6485
+ getRecallBudgetChars(override) {
6486
+ if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
6487
+ return Math.floor(override);
6488
+ }
5580
6489
  const configuredBudget = this.config.recallBudgetChars;
5581
6490
  if (typeof configuredBudget === "number" && Number.isFinite(configuredBudget) && configuredBudget >= 0) {
5582
6491
  return Math.floor(configuredBudget);
@@ -5587,7 +6496,7 @@ ${r.snippet.trim()}
5587
6496
  }
5588
6497
  return 0;
5589
6498
  }
5590
- assembleRecallSections(sectionBuckets) {
6499
+ assembleRecallSections(sectionBuckets, budgetOverride) {
5591
6500
  const orderedEntries = [];
5592
6501
  const pipeline = Array.isArray(this.config.recallPipeline) ? this.config.recallPipeline : [];
5593
6502
  const orderedIds = pipeline.filter((entry) => entry.enabled !== false).map((entry) => entry.id);
@@ -5603,7 +6512,7 @@ ${r.snippet.trim()}
5603
6512
  if (chunks.length === 0) continue;
5604
6513
  orderedEntries.push({ id, content: chunks.join("\n\n") });
5605
6514
  }
5606
- const budget = this.getRecallBudgetChars();
6515
+ const budget = this.getRecallBudgetChars(budgetOverride);
5607
6516
  if (budget === 0) {
5608
6517
  return {
5609
6518
  sections: [],
@@ -5735,6 +6644,13 @@ ${r.snippet.trim()}
5735
6644
  let recalledMemoryCount = 0;
5736
6645
  let recalledMemoryIds = [];
5737
6646
  let recalledMemoryPaths = [];
6647
+ const xrayBranchPoolSize = {
6648
+ hot_qmd: 0,
6649
+ hot_embedding: 0,
6650
+ cold_fallback: 0,
6651
+ recent_scan: 0
6652
+ };
6653
+ const xrayColdPoolSink = { size: 0 };
5738
6654
  let identityInjectionModeUsed = "none";
5739
6655
  let identityInjectedChars = 0;
5740
6656
  let identityInjectionTruncated = false;
@@ -5795,7 +6711,7 @@ ${r.snippet.trim()}
5795
6711
  this.config.verbatimArtifactsMaxRecall
5796
6712
  );
5797
6713
  const embeddingFetchLimit = computedFetchLimit;
5798
- const principal = resolvePrincipal(sessionKey, this.config);
6714
+ const principal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
5799
6715
  const namespaceOverride = options.namespace?.trim() || void 0;
5800
6716
  const readableRecallNamespaces = recallNamespacesForPrincipal(
5801
6717
  principal,
@@ -5806,8 +6722,24 @@ ${r.snippet.trim()}
5806
6722
  `namespace override is not readable: ${namespaceOverride}`
5807
6723
  );
5808
6724
  }
5809
- const selfNamespace = namespaceOverride ?? defaultNamespaceForPrincipal(principal, this.config);
5810
- const recallNamespaces = namespaceOverride ? [namespaceOverride] : readableRecallNamespaces;
6725
+ const codingOverlay = namespaceOverride ? null : this.applyCodingRecallOverlay(sessionKey);
6726
+ const principalSelfNamespace = defaultNamespaceForPrincipal(principal, this.config);
6727
+ const codingSelfNamespace = codingOverlay ? combineNamespaces(principalSelfNamespace, codingOverlay.namespace) : null;
6728
+ const selfNamespace = namespaceOverride ?? codingSelfNamespace ?? principalSelfNamespace;
6729
+ let recallNamespaces;
6730
+ if (namespaceOverride) {
6731
+ recallNamespaces = [namespaceOverride];
6732
+ } else if (codingOverlay && codingSelfNamespace) {
6733
+ const mapped = readableRecallNamespaces.map(
6734
+ (ns) => ns === principalSelfNamespace ? codingSelfNamespace : ns
6735
+ );
6736
+ const fallbackNs = codingOverlay.readFallbacks.map(
6737
+ (fallback) => combineNamespaces(principalSelfNamespace, fallback)
6738
+ );
6739
+ recallNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
6740
+ } else {
6741
+ recallNamespaces = readableRecallNamespaces;
6742
+ }
5811
6743
  const qmdAvailable = this.qmd.isAvailable();
5812
6744
  let graphDecisionStatus = recallDecision.plannedMode === "graph_mode" ? "skipped" : "not_requested";
5813
6745
  let graphDecisionReason = recallDecision.graphReason;
@@ -5824,7 +6756,7 @@ ${r.snippet.trim()}
5824
6756
  const graphExpandedResultPaths = /* @__PURE__ */ new Set();
5825
6757
  const graphSourceLabelsForPath = (resultPath) => {
5826
6758
  const labels = [];
5827
- const normalizedPath = resultPath.split(path5.sep).join("/");
6759
+ const normalizedPath = resultPath.split(path7.sep).join("/");
5828
6760
  const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
5829
6761
  if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
5830
6762
  if (graphExpandedResultPaths.has(resultPath))
@@ -5862,6 +6794,32 @@ ${r.snippet.trim()}
5862
6794
  const earlySessionKey = sessionKey ?? "default";
5863
6795
  this._recallWorkspaceOverrides.delete(earlySessionKey);
5864
6796
  timings.total = `${Date.now() - recallStart}ms`;
6797
+ if (options.xrayCapture === true && !options.abortSignal?.aborted) {
6798
+ try {
6799
+ this.lastXraySnapshot = buildXraySnapshot({
6800
+ query: retrievalQuery,
6801
+ tierExplain: null,
6802
+ results: [],
6803
+ filters: [
6804
+ {
6805
+ name: "planner-mode",
6806
+ considered: 0,
6807
+ admitted: 0,
6808
+ reason: "no_recall"
6809
+ }
6810
+ ],
6811
+ budget: {
6812
+ chars: this.getRecallBudgetChars(options.budgetCharsOverride),
6813
+ used: 0
6814
+ },
6815
+ sessionKey,
6816
+ namespace: selfNamespace,
6817
+ traceId
6818
+ });
6819
+ } catch (err) {
6820
+ log.debug(`x-ray capture (no_recall) failed: ${err}`);
6821
+ }
6822
+ }
5865
6823
  if (sessionKey) {
5866
6824
  this.lastRecall.record({
5867
6825
  sessionKey,
@@ -7011,16 +7969,16 @@ ${formatted}`;
7011
7969
  if (!this.config.compactionResetEnabled) return null;
7012
7970
  const workspaceDir = compactionWorkspaceDir || this.config.workspaceDir || defaultWorkspaceDir();
7013
7971
  const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
7014
- const signalPath = path5.join(
7972
+ const signalPath = path7.join(
7015
7973
  workspaceDir,
7016
7974
  `.compaction-reset-signal-${safeSessionKey}`
7017
7975
  );
7018
- const bootPath = path5.join(workspaceDir, "BOOT.md");
7976
+ const bootPath = path7.join(workspaceDir, "BOOT.md");
7019
7977
  try {
7020
7978
  const signalStat = await stat3(signalPath).catch(() => null);
7021
7979
  if (!signalStat) return null;
7022
7980
  const signalAge = Date.now() - signalStat.mtimeMs;
7023
- const signalData = JSON.parse(await readFile3(signalPath, "utf-8"));
7981
+ const signalData = JSON.parse(await readFile4(signalPath, "utf-8"));
7024
7982
  if (signalData.sessionKey !== effectiveSessionKey) {
7025
7983
  log.debug(
7026
7984
  `recall: compaction signal is for ${signalData.sessionKey}, not ${effectiveSessionKey} \u2014 skipping`
@@ -7040,7 +7998,7 @@ ${formatted}`;
7040
7998
 
7041
7999
  `;
7042
8000
  try {
7043
- const bootContent = await readFile3(bootPath, "utf-8");
8001
+ const bootContent = await readFile4(bootPath, "utf-8");
7044
8002
  section += "### BOOT.md (working state before compaction)\n\n";
7045
8003
  section += bootContent + "\n";
7046
8004
  } catch {
@@ -7747,7 +8705,18 @@ ${tmtNode.summary}`
7747
8705
  "rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
7748
8706
  );
7749
8707
  }
8708
+ if (this.config.recallMemoryWorthFilterEnabled && memoryResults.length > 0) {
8709
+ try {
8710
+ memoryResults = await this.applyMemoryWorthRerank(memoryResults, recallNamespaces);
8711
+ } catch (err) {
8712
+ log.debug("memory-worth filter failed open", { error: err.message });
8713
+ }
8714
+ }
7750
8715
  const effectiveGateScore = preAugmentTopScore > 0 ? Math.max(preAugmentTopScore, maxSpecializedScore) : 0;
8716
+ xrayBranchPoolSize.hot_qmd = Math.max(
8717
+ xrayBranchPoolSize.hot_qmd,
8718
+ memoryResults.length
8719
+ );
7751
8720
  let confidenceGateRejected = false;
7752
8721
  if (this.config.recallConfidenceGateEnabled && effectiveGateScore > 0) {
7753
8722
  if (effectiveGateScore < this.config.recallConfidenceGateThreshold) {
@@ -7761,7 +8730,8 @@ ${tmtNode.summary}`
7761
8730
  memoryResults = this.diversifyAndLimitRecallResults(
7762
8731
  "memories",
7763
8732
  memoryResults,
7764
- recallResultLimit
8733
+ recallResultLimit,
8734
+ retrievalQuery
7765
8735
  );
7766
8736
  if (this.config.memoryReconstructionEnabled && memoryResults.length > 0) {
7767
8737
  try {
@@ -7846,10 +8816,15 @@ ${tmtNode.summary}`
7846
8816
  recallNamespaces,
7847
8817
  retrievalQuery
7848
8818
  );
8819
+ xrayBranchPoolSize.hot_embedding = Math.max(
8820
+ xrayBranchPoolSize.hot_embedding,
8821
+ boostedScoped.length
8822
+ );
7849
8823
  const scoped = this.diversifyAndLimitRecallResults(
7850
8824
  "memories",
7851
8825
  boostedScoped,
7852
- recallResultLimit
8826
+ recallResultLimit,
8827
+ retrievalQuery
7853
8828
  );
7854
8829
  if (scoped.length > 0) {
7855
8830
  if (shouldPersistGraphSnapshot) {
@@ -7882,7 +8857,8 @@ ${tmtNode.summary}`
7882
8857
  recallResultLimit,
7883
8858
  recallMode,
7884
8859
  queryAwarePrefilter,
7885
- abortSignal: options.abortSignal
8860
+ abortSignal: options.abortSignal,
8861
+ xrayPoolSizeSink: xrayColdPoolSink
7886
8862
  });
7887
8863
  if (longTerm.length > 0) {
7888
8864
  if (shouldPersistGraphSnapshot) {
@@ -7966,10 +8942,15 @@ ${tmtNode.summary}`
7966
8942
  recallNamespaces,
7967
8943
  retrievalQuery
7968
8944
  );
8945
+ xrayBranchPoolSize.hot_embedding = Math.max(
8946
+ xrayBranchPoolSize.hot_embedding,
8947
+ boostedScoped.length
8948
+ );
7969
8949
  const scoped = this.diversifyAndLimitRecallResults(
7970
8950
  "memories",
7971
8951
  boostedScoped,
7972
- recallResultLimit
8952
+ recallResultLimit,
8953
+ retrievalQuery
7973
8954
  );
7974
8955
  if (scoped.length > 0) {
7975
8956
  if (shouldPersistGraphSnapshot) {
@@ -8023,7 +9004,8 @@ ${tmtNode.summary}`
8023
9004
  recallResultLimit,
8024
9005
  recallMode,
8025
9006
  queryAwarePrefilter,
8026
- abortSignal: options.abortSignal
9007
+ abortSignal: options.abortSignal,
9008
+ xrayPoolSizeSink: xrayColdPoolSink
8027
9009
  });
8028
9010
  if (longTerm.length > 0) {
8029
9011
  recallSource = "cold_fallback";
@@ -8065,10 +9047,15 @@ ${tmtNode.summary}`
8065
9047
  retrievalQuery,
8066
9048
  preloadedMap
8067
9049
  )).sort((a, b) => b.score - a.score);
9050
+ xrayBranchPoolSize.recent_scan = Math.max(
9051
+ xrayBranchPoolSize.recent_scan,
9052
+ boostedRecent.length
9053
+ );
8068
9054
  const recent = this.diversifyAndLimitRecallResults(
8069
9055
  "memories",
8070
9056
  boostedRecent,
8071
- recallResultLimit
9057
+ recallResultLimit,
9058
+ retrievalQuery
8072
9059
  );
8073
9060
  if (recent.length > 0) {
8074
9061
  if (shouldPersistGraphSnapshot) {
@@ -8101,7 +9088,8 @@ ${tmtNode.summary}`
8101
9088
  recallResultLimit,
8102
9089
  recallMode,
8103
9090
  queryAwarePrefilter,
8104
- abortSignal: options.abortSignal
9091
+ abortSignal: options.abortSignal,
9092
+ xrayPoolSizeSink: xrayColdPoolSink
8105
9093
  });
8106
9094
  if (longTerm.length > 0) {
8107
9095
  if (shouldPersistGraphSnapshot) {
@@ -8137,7 +9125,8 @@ ${tmtNode.summary}`
8137
9125
  recallResultLimit,
8138
9126
  recallMode,
8139
9127
  queryAwarePrefilter,
8140
- abortSignal: options.abortSignal
9128
+ abortSignal: options.abortSignal,
9129
+ xrayPoolSizeSink: xrayColdPoolSink
8141
9130
  });
8142
9131
  if (longTerm.length > 0) {
8143
9132
  if (shouldPersistGraphSnapshot) {
@@ -8296,7 +9285,10 @@ _Context: ${topQuestion.context}_`
8296
9285
  );
8297
9286
  const timingParts = Object.entries(timings).map(([k, v]) => `${k}=${v}`).join(", ");
8298
9287
  log.info(`recall timings: ${timingParts}`);
8299
- const assembledRecall = this.assembleRecallSections(sectionBuckets);
9288
+ const assembledRecall = this.assembleRecallSections(
9289
+ sectionBuckets,
9290
+ options.budgetCharsOverride
9291
+ );
8300
9292
  const context = assembledRecall.sections.length === 0 ? "" : assembledRecall.sections.join("\n\n---\n\n");
8301
9293
  const sourcesUsed = this.collectLastRecallSources(
8302
9294
  sectionBuckets,
@@ -8312,6 +9304,73 @@ _Context: ${topQuestion.context}_`
8312
9304
  includedSections: assembledRecall.includedIds,
8313
9305
  omittedSections: assembledRecall.omittedIds
8314
9306
  });
9307
+ if (options.xrayCapture === true && !options.abortSignal?.aborted) {
9308
+ try {
9309
+ const servedBy = mapRecallSourceToXrayServedBy(recallSource);
9310
+ const idFromPath = (p) => {
9311
+ const match = p.match(/([^/]+)\.md$/);
9312
+ return match ? match[1] ?? null : null;
9313
+ };
9314
+ const results = [];
9315
+ for (const recalledPath of recalledMemoryPaths) {
9316
+ const derivedId = idFromPath(recalledPath);
9317
+ if (!derivedId) continue;
9318
+ results.push({
9319
+ memoryId: derivedId,
9320
+ path: recalledPath,
9321
+ servedBy,
9322
+ scoreDecomposition: { final: 0 },
9323
+ admittedBy: []
9324
+ });
9325
+ }
9326
+ let xrayConsidered;
9327
+ switch (recallSource) {
9328
+ case "hot_qmd":
9329
+ xrayConsidered = xrayBranchPoolSize.hot_qmd;
9330
+ break;
9331
+ case "hot_embedding":
9332
+ xrayConsidered = xrayBranchPoolSize.hot_embedding;
9333
+ break;
9334
+ case "cold_fallback":
9335
+ xrayConsidered = xrayColdPoolSink.size;
9336
+ break;
9337
+ case "recent_scan":
9338
+ xrayConsidered = xrayBranchPoolSize.recent_scan;
9339
+ break;
9340
+ case "none":
9341
+ xrayConsidered = recalledMemoryCount;
9342
+ break;
9343
+ default: {
9344
+ const _exhaustive = recallSource;
9345
+ void _exhaustive;
9346
+ xrayConsidered = recalledMemoryCount;
9347
+ }
9348
+ }
9349
+ xrayConsidered = Math.max(xrayConsidered, recalledMemoryIds.length);
9350
+ const filters = [
9351
+ {
9352
+ name: "recall-result-limit",
9353
+ considered: xrayConsidered,
9354
+ admitted: recalledMemoryIds.length
9355
+ }
9356
+ ];
9357
+ this.lastXraySnapshot = buildXraySnapshot({
9358
+ query: retrievalQuery,
9359
+ tierExplain: null,
9360
+ results,
9361
+ filters,
9362
+ budget: {
9363
+ chars: this.getRecallBudgetChars(options.budgetCharsOverride),
9364
+ used: assembledRecall.finalChars
9365
+ },
9366
+ sessionKey,
9367
+ namespace: selfNamespace,
9368
+ traceId
9369
+ });
9370
+ } catch (err) {
9371
+ log.debug(`x-ray capture failed: ${err}`);
9372
+ }
9373
+ }
8315
9374
  if (sessionKey) {
8316
9375
  throwIfRecallAborted(options.abortSignal);
8317
9376
  this.lastRecall.record({
@@ -8788,7 +9847,10 @@ ${normalized}`).digest("hex");
8788
9847
  return;
8789
9848
  }
8790
9849
  const principal = resolvePrincipal(sessionKey, this.config);
8791
- const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : defaultNamespaceForPrincipal(principal, this.config);
9850
+ const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : this.applyCodingNamespaceOverlay(
9851
+ sessionKey,
9852
+ defaultNamespaceForPrincipal(principal, this.config)
9853
+ );
8792
9854
  const storage = await this.storageRouter.storageFor(selfNamespace);
8793
9855
  const shouldPersistProcessedFingerprint = normalizedTurns.some(
8794
9856
  (turn) => turn.persistProcessedFingerprint === true
@@ -8881,6 +9943,24 @@ ${normalized}`).digest("hex");
8881
9943
  } catch (error) {
8882
9944
  postPersistMetaError = error;
8883
9945
  }
9946
+ try {
9947
+ if (clearBufferAfterExtraction && !this.config.extractionJudgeShadow) {
9948
+ const deferredCount = this.lastPersistExtractionDeferredCount;
9949
+ if (deferredCount > 0 && normalizedTurns.length > 0) {
9950
+ await this.buffer.retainDeferredTurns(
9951
+ bufferKey,
9952
+ normalizedTurns,
9953
+ 10
9954
+ );
9955
+ } else {
9956
+ await this.buffer.retainDeferredTurns(bufferKey, [], 0);
9957
+ }
9958
+ }
9959
+ } catch (err) {
9960
+ log.debug(
9961
+ `extraction-judge: defer retention failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
9962
+ );
9963
+ }
8884
9964
  await clearBuffer({ ignoreAbort: true });
8885
9965
  if (this.config.memoryBoxesEnabled && persistedIds.length > 0) {
8886
9966
  const extractionTopics = deriveTopicsFromExtraction(result);
@@ -9013,7 +10093,7 @@ ${normalized}`).digest("hex");
9013
10093
  );
9014
10094
  this.tierMigrationInFlight = true;
9015
10095
  try {
9016
- const coldStorage = new StorageManager(path5.join(storage.dir, "cold"));
10096
+ const coldStorage = new StorageManager(path7.join(storage.dir, "cold"));
9017
10097
  const [hotMemories, coldMemories] = await Promise.all([
9018
10098
  storage.readAllMemories(),
9019
10099
  coldStorage.readAllMemories()
@@ -9462,6 +10542,7 @@ ${normalized}`).digest("hex");
9462
10542
  }
9463
10543
  let judgeVerdictsByFactIndex = null;
9464
10544
  let judgeGatedCount = 0;
10545
+ this.lastPersistExtractionDeferredCount = 0;
9465
10546
  if (this.config.extractionJudgeEnabled) {
9466
10547
  try {
9467
10548
  const judgeCandidates = [];
@@ -9496,12 +10577,56 @@ ${normalized}`).digest("hex");
9496
10577
  });
9497
10578
  candidateToFactIndex.push(fi);
9498
10579
  }
10580
+ const judgeTelemetryOpts = {
10581
+ enabled: this.config.extractionJudgeTelemetryEnabled === true,
10582
+ memoryDir: this.config.memoryDir
10583
+ };
10584
+ const judgeTrainingOpts = {
10585
+ enabled: this.config.collectJudgeTrainingPairs === true,
10586
+ ...this.config.judgeTrainingDir ? { directory: this.config.judgeTrainingDir } : {}
10587
+ };
10588
+ const judgeTelemetryHandler = judgeTelemetryOpts.enabled || judgeTrainingOpts.enabled ? (obs) => {
10589
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
10590
+ const verdictKind = getVerdictKind(obs.verdict);
10591
+ if (judgeTelemetryOpts.enabled) {
10592
+ const event = {
10593
+ version: 1,
10594
+ category: EXTRACTION_JUDGE_VERDICT_CATEGORY,
10595
+ ts,
10596
+ verdictKind,
10597
+ reason: obs.verdict.reason,
10598
+ deferrals: obs.priorDeferrals,
10599
+ elapsedMs: obs.elapsedMs,
10600
+ candidateCategory: obs.candidate.category,
10601
+ confidence: obs.candidate.confidence,
10602
+ contentHash: obs.contentHash,
10603
+ fromCache: obs.source === "cache",
10604
+ ...obs.source === "llm-cap-rejected" ? { deferCapTriggered: true } : {}
10605
+ };
10606
+ void recordJudgeVerdict(event, judgeTelemetryOpts);
10607
+ }
10608
+ if (judgeTrainingOpts.enabled) {
10609
+ const pair = {
10610
+ version: 1,
10611
+ ts,
10612
+ candidateText: obs.candidate.text,
10613
+ candidateCategory: obs.candidate.category,
10614
+ ...typeof obs.candidate.confidence === "number" ? { candidateConfidence: obs.candidate.confidence } : {},
10615
+ verdictKind,
10616
+ reason: obs.verdict.reason,
10617
+ priorDeferrals: obs.priorDeferrals
10618
+ };
10619
+ void recordJudgeTrainingPair(pair, judgeTrainingOpts);
10620
+ }
10621
+ } : void 0;
9499
10622
  const judgeResult = await judgeFactDurability(
9500
10623
  judgeCandidates,
9501
10624
  this.config,
9502
10625
  this.localLlm,
9503
10626
  new FallbackLlmClient(this.config.gatewayConfig),
9504
- this.judgeVerdictCache
10627
+ this.judgeVerdictCache,
10628
+ this.judgeDeferCounts,
10629
+ judgeTelemetryHandler
9505
10630
  );
9506
10631
  judgeVerdictsByFactIndex = /* @__PURE__ */ new Map();
9507
10632
  for (const [candidateIdx, verdict] of judgeResult.verdicts) {
@@ -9511,8 +10636,9 @@ ${normalized}`).digest("hex");
9511
10636
  }
9512
10637
  }
9513
10638
  log.info(
9514
- `extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.elapsed}ms`
10639
+ `extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.deferred} deferred` + (judgeResult.deferredCappedToReject > 0 ? ` (${judgeResult.deferredCappedToReject} cap-rejected)` : "") + `, ${judgeResult.elapsed}ms`
9515
10640
  );
10641
+ this.lastPersistExtractionDeferredCount = judgeResult.deferred;
9516
10642
  } catch (err) {
9517
10643
  log.warn(
9518
10644
  `extraction-judge: pipeline error, proceeding without filtering (fail-open): ${err instanceof Error ? err.message : String(err)}`
@@ -9587,10 +10713,17 @@ ${normalized}`).digest("hex");
9587
10713
  if (judgeVerdictsByFactIndex) {
9588
10714
  const verdict = judgeVerdictsByFactIndex.get(factLoopIndex);
9589
10715
  if (verdict && !verdict.durable) {
10716
+ const verdictKind = getVerdictKind(verdict);
9590
10717
  if (this.config.extractionJudgeShadow) {
9591
10718
  log.info(
9592
- `extraction-judge[shadow]: would reject "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
10719
+ `extraction-judge[shadow]: would ${verdictKind} "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
10720
+ );
10721
+ } else if (verdictKind === "defer") {
10722
+ judgeGatedCount++;
10723
+ log.debug(
10724
+ `extraction-judge: deferred "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
9593
10725
  );
10726
+ continue;
9594
10727
  } else {
9595
10728
  judgeGatedCount++;
9596
10729
  log.debug(
@@ -10133,7 +11266,7 @@ ${normalized}`).digest("hex");
10133
11266
  const allMems = allMemsForGraph ?? [];
10134
11267
  for (const m of allMems) {
10135
11268
  if (m.frontmatter.entityRef === entityRef) {
10136
- const rel = path5.relative(storage.dir, m.path);
11269
+ const rel = path7.relative(storage.dir, m.path);
10137
11270
  if (rel !== memoryRelPath) entitySiblings.push(rel);
10138
11271
  }
10139
11272
  }
@@ -10404,14 +11537,14 @@ ${normalized}`).digest("hex");
10404
11537
  }
10405
11538
  if (this.config.semanticConsolidationEnabled) {
10406
11539
  try {
10407
- const stateFilePath = path5.join(
11540
+ const stateFilePath = path7.join(
10408
11541
  this.config.memoryDir,
10409
11542
  "state",
10410
11543
  "semantic-consolidation-last-run.json"
10411
11544
  );
10412
11545
  let shouldRun = true;
10413
11546
  try {
10414
- const stateRaw = await readFile3(stateFilePath, "utf-8");
11547
+ const stateRaw = await readFile4(stateFilePath, "utf-8");
10415
11548
  const stateData = JSON.parse(stateRaw);
10416
11549
  if (stateData.lastRunAt) {
10417
11550
  const lastRunMs = new Date(stateData.lastRunAt).getTime();
@@ -10434,9 +11567,9 @@ ${normalized}`).digest("hex");
10434
11567
  allMemories = await this.storage.readAllMemories();
10435
11568
  }
10436
11569
  if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
10437
- const stateDir = path5.join(this.config.memoryDir, "state");
10438
- await mkdir4(stateDir, { recursive: true });
10439
- await writeFile3(
11570
+ const stateDir = path7.join(this.config.memoryDir, "state");
11571
+ await mkdir5(stateDir, { recursive: true });
11572
+ await writeFile4(
10440
11573
  stateFilePath,
10441
11574
  JSON.stringify({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString() }),
10442
11575
  "utf-8"
@@ -10908,13 +12041,13 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
10908
12041
  protectedCategories: this.config.lifecycleProtectedCategories
10909
12042
  }
10910
12043
  };
10911
- const metricsPath = path5.join(
12044
+ const metricsPath = path7.join(
10912
12045
  this.storage.dir,
10913
12046
  "state",
10914
12047
  "lifecycle-metrics.json"
10915
12048
  );
10916
- await mkdir4(path5.dirname(metricsPath), { recursive: true });
10917
- await writeFile3(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
12049
+ await mkdir5(path7.dirname(metricsPath), { recursive: true });
12050
+ await writeFile4(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
10918
12051
  }
10919
12052
  /**
10920
12053
  * Archive old, low-importance, rarely-accessed facts (v6.0).
@@ -11417,11 +12550,97 @@ ${lines.join("\n\n")}`;
11417
12550
  *
11418
12551
  * Callers must pass the full candidate pool (post-rerank, pre-slice).
11419
12552
  */
11420
- diversifyAndLimitRecallResults(sectionId, results, limit) {
12553
+ async applyMemoryWorthRerank(results, namespaces) {
12554
+ const counters = /* @__PURE__ */ new Map();
12555
+ const seenNamespaces = /* @__PURE__ */ new Set();
12556
+ const nowMs = Date.now();
12557
+ for (const [key, entry] of this.memoryWorthCounterCache) {
12558
+ if (nowMs - entry.at >= _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
12559
+ this.memoryWorthCounterCache.delete(key);
12560
+ }
12561
+ }
12562
+ for (const ns of namespaces) {
12563
+ if (seenNamespaces.has(ns)) continue;
12564
+ seenNamespaces.add(ns);
12565
+ try {
12566
+ const cached = this.memoryWorthCounterCache.get(ns);
12567
+ let nsMap;
12568
+ if (cached && nowMs - cached.at < _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
12569
+ nsMap = cached.counters;
12570
+ } else {
12571
+ const storage = await this.getStorage(ns);
12572
+ const memories = await storage.readAllMemories();
12573
+ nsMap = buildMemoryWorthCounterMap(memories);
12574
+ this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });
12575
+ }
12576
+ for (const [path8, c] of nsMap) counters.set(path8, c);
12577
+ } catch (err) {
12578
+ log.debug("memory-worth: failed to read namespace, skipping", {
12579
+ namespace: ns,
12580
+ error: err.message
12581
+ });
12582
+ }
12583
+ }
12584
+ const missing = results.filter((r) => !counters.has(r.path));
12585
+ if (missing.length > 0) {
12586
+ let reader = null;
12587
+ for (const ns of namespaces) {
12588
+ try {
12589
+ reader = await this.getStorage(ns);
12590
+ break;
12591
+ } catch {
12592
+ }
12593
+ }
12594
+ if (reader) {
12595
+ for (const r of missing) {
12596
+ try {
12597
+ const memory = await reader.readMemoryByPath(r.path);
12598
+ if (!memory) continue;
12599
+ const fm = memory.frontmatter;
12600
+ if (fm.mw_success === void 0 && fm.mw_fail === void 0) continue;
12601
+ counters.set(r.path, {
12602
+ mw_success: fm.mw_success,
12603
+ mw_fail: fm.mw_fail,
12604
+ lastAccessed: fm.lastAccessed
12605
+ });
12606
+ } catch (err) {
12607
+ log.debug("memory-worth: direct path lookup failed", {
12608
+ path: r.path,
12609
+ error: err.message
12610
+ });
12611
+ }
12612
+ }
12613
+ }
12614
+ }
12615
+ if (counters.size === 0) return results;
12616
+ const rankedInputs = results.map((r, i) => ({
12617
+ path: r.path,
12618
+ // Large positive rank score so multiplier math stays well-scaled and
12619
+ // we never hit zero; descending so earlier items rank higher.
12620
+ score: results.length - i
12621
+ }));
12622
+ const filtered = applyMemoryWorthFilter(rankedInputs, {
12623
+ counters,
12624
+ now: /* @__PURE__ */ new Date(),
12625
+ halfLifeMs: this.config.recallMemoryWorthHalfLifeMs > 0 ? this.config.recallMemoryWorthHalfLifeMs : void 0
12626
+ });
12627
+ const byPath = new Map(results.map((r) => [r.path, r]));
12628
+ const reordered = [];
12629
+ for (const item of filtered) {
12630
+ const original = byPath.get(item.path);
12631
+ if (original) reordered.push(original);
12632
+ }
12633
+ return reordered;
12634
+ }
12635
+ diversifyAndLimitRecallResults(sectionId, results, limit, retrievalQuery) {
11421
12636
  const safeLimit = typeof limit === "number" && Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 0;
11422
12637
  if (!Array.isArray(results) || results.length === 0) return [];
11423
12638
  if (safeLimit === 0) return [];
11424
- const diversified = this.applyMmrToQmdResults(sectionId, results);
12639
+ const boosted = this.config.recallReasoningTraceBoostEnabled && typeof retrievalQuery === "string" ? applyReasoningTraceBoost(results, {
12640
+ enabled: true,
12641
+ query: retrievalQuery
12642
+ }) : results;
12643
+ const diversified = this.applyMmrToQmdResults(sectionId, boosted);
11425
12644
  return diversified.slice(0, safeLimit);
11426
12645
  }
11427
12646
  /**
@@ -11525,12 +12744,12 @@ ${lines.join("\n\n")}`;
11525
12744
  */
11526
12745
  semanticDedupScopeFor(targetStorage) {
11527
12746
  if (!this.config.namespacesEnabled) return {};
11528
- const memoryDir = path5.resolve(this.config.memoryDir);
11529
- const storageDir = path5.resolve(targetStorage.dir);
12747
+ const memoryDir = path7.resolve(this.config.memoryDir);
12748
+ const storageDir = path7.resolve(targetStorage.dir);
11530
12749
  if (storageDir === memoryDir) {
11531
12750
  return { pathExcludePrefixes: ["namespaces/"] };
11532
12751
  }
11533
- let rel = path5.relative(memoryDir, storageDir);
12752
+ let rel = path7.relative(memoryDir, storageDir);
11534
12753
  if (!rel || rel.startsWith("..")) {
11535
12754
  log.debug(
11536
12755
  `semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
@@ -11549,7 +12768,7 @@ ${lines.join("\n\n")}`;
11549
12768
  if (hits.length === 0) return [];
11550
12769
  const results = [];
11551
12770
  for (const hit of hits) {
11552
- const fullPath = path5.isAbsolute(hit.path) ? hit.path : path5.join(this.config.memoryDir, hit.path);
12771
+ const fullPath = path7.isAbsolute(hit.path) ? hit.path : path7.join(this.config.memoryDir, hit.path);
11553
12772
  const memory = await this.storage.readMemoryByPath(fullPath);
11554
12773
  if (!memory) continue;
11555
12774
  results.push({
@@ -11726,10 +12945,26 @@ ${lines.join("\n\n")}`;
11726
12945
  "rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
11727
12946
  );
11728
12947
  }
12948
+ if (this.config.recallMemoryWorthFilterEnabled && results.length > 0) {
12949
+ try {
12950
+ results = await this.applyMemoryWorthRerank(results, options.recallNamespaces);
12951
+ } catch (err) {
12952
+ log.debug("memory-worth filter (cold) failed open", {
12953
+ error: err.message
12954
+ });
12955
+ }
12956
+ }
12957
+ if (options.xrayPoolSizeSink) {
12958
+ options.xrayPoolSizeSink.size = Math.max(
12959
+ options.xrayPoolSizeSink.size,
12960
+ results.length
12961
+ );
12962
+ }
11729
12963
  return this.diversifyAndLimitRecallResults(
11730
12964
  "memories",
11731
12965
  results,
11732
- options.recallResultLimit
12966
+ options.recallResultLimit,
12967
+ options.prompt
11733
12968
  );
11734
12969
  }
11735
12970
  // ---------------------------------------------------------------------------
@@ -12123,8 +13358,8 @@ ${lines.join("\n\n")}`;
12123
13358
  }
12124
13359
  namespaceFromStorageDir(storageDir) {
12125
13360
  if (!this.config.namespacesEnabled) return this.config.defaultNamespace;
12126
- const resolvedStorageDir = path5.resolve(storageDir);
12127
- const resolvedMemoryDir = path5.resolve(this.config.memoryDir);
13361
+ const resolvedStorageDir = path7.resolve(storageDir);
13362
+ const resolvedMemoryDir = path7.resolve(this.config.memoryDir);
12128
13363
  if (resolvedStorageDir === resolvedMemoryDir)
12129
13364
  return this.config.defaultNamespace;
12130
13365
  const m = resolvedStorageDir.match(/[\\/]namespaces[\\/]([^\\/]+)$/);
@@ -12157,6 +13392,21 @@ export {
12157
13392
  migrateFromEngram,
12158
13393
  buildProcedureRecallSection,
12159
13394
  decideSemanticDedup,
13395
+ DEFAULT_TAXONOMY,
13396
+ generateResolverDocument,
13397
+ validateSlug,
13398
+ validateTaxonomy,
13399
+ loadTaxonomy,
13400
+ saveTaxonomy,
13401
+ getTaxonomyDir,
13402
+ getTaxonomyFilePath,
13403
+ stableHash,
13404
+ normalizeOriginUrl,
13405
+ resolveGitContext,
13406
+ projectNamespaceName,
13407
+ branchNamespaceName,
13408
+ resolveCodingNamespaceOverlay,
13409
+ describeCodingScope,
12160
13410
  dedupeEntitySynthesisEvidenceEntries,
12161
13411
  defaultWorkspaceDir,
12162
13412
  sanitizeSessionKeyForFilename,
@@ -12185,4 +13435,4 @@ export {
12185
13435
  resolvePersistedMemoryRelativePath,
12186
13436
  Orchestrator
12187
13437
  };
12188
- //# sourceMappingURL=chunk-DEPL3635.js.map
13438
+ //# sourceMappingURL=chunk-3YGHKTBF.js.map