@remnic/core 1.0.3 → 1.1.1

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 (323) hide show
  1. package/dist/abort-error.d.ts +32 -0
  2. package/dist/abort-error.js +11 -0
  3. package/dist/access-audit.d.ts +56 -0
  4. package/dist/access-audit.js +9 -0
  5. package/dist/access-audit.js.map +1 -0
  6. package/dist/access-cli.js +72 -54
  7. package/dist/access-cli.js.map +1 -1
  8. package/dist/access-http.d.ts +16 -8
  9. package/dist/access-http.js +25 -17
  10. package/dist/access-mcp.d.ts +16 -8
  11. package/dist/access-mcp.js +28 -6
  12. package/dist/access-schema.d.ts +130 -39
  13. package/dist/access-schema.js +5 -1
  14. package/dist/access-service-Br8ZydTK.d.ts +827 -0
  15. package/dist/access-service.d.ts +20 -660
  16. package/dist/access-service.js +22 -14
  17. package/dist/bootstrap.d.ts +6 -3
  18. package/dist/briefing.d.ts +1 -0
  19. package/dist/briefing.js +6 -5
  20. package/dist/buffer-surprise-report.d.ts +70 -0
  21. package/dist/buffer-surprise-report.js +7 -0
  22. package/dist/buffer-surprise-report.js.map +1 -0
  23. package/dist/buffer-surprise.d.ts +98 -0
  24. package/dist/buffer-surprise.js +11 -0
  25. package/dist/buffer-surprise.js.map +1 -0
  26. package/dist/buffer.d.ts +100 -2
  27. package/dist/buffer.js +1 -1
  28. package/dist/calibration.js +5 -5
  29. package/dist/causal-behavior.js +4 -4
  30. package/dist/causal-chain.js +2 -2
  31. package/dist/causal-consolidation.js +17 -16
  32. package/dist/causal-consolidation.js.map +1 -1
  33. package/dist/causal-retrieval.js +4 -4
  34. package/dist/causal-trajectory.js +1 -1
  35. package/dist/{chunk-QNJMBKFK.js → chunk-2LGMW3DJ.js} +3 -2
  36. package/dist/chunk-2LGMW3DJ.js.map +1 -0
  37. package/dist/{chunk-QDYXG4CS.js → chunk-3FPTCC3Z.js} +4 -3
  38. package/dist/chunk-3FPTCC3Z.js.map +1 -0
  39. package/dist/chunk-3GPTTA4J.js +57 -0
  40. package/dist/chunk-3GPTTA4J.js.map +1 -0
  41. package/dist/{chunk-QKAH5B6E.js → chunk-3GXCSUXR.js} +94 -6
  42. package/dist/chunk-3GXCSUXR.js.map +1 -0
  43. package/dist/{chunk-POBPGDWI.js → chunk-3OGMS3PE.js} +2 -2
  44. package/dist/chunk-54V4BZWP.js +139 -0
  45. package/dist/chunk-54V4BZWP.js.map +1 -0
  46. package/dist/chunk-5JRF2PZA.js +67 -0
  47. package/dist/chunk-5JRF2PZA.js.map +1 -0
  48. package/dist/chunk-64NJRYU2.js +332 -0
  49. package/dist/chunk-64NJRYU2.js.map +1 -0
  50. package/dist/chunk-6AUUAZEX.js +150 -0
  51. package/dist/chunk-6AUUAZEX.js.map +1 -0
  52. package/dist/{chunk-HITJFT7E.js → chunk-7I7FKFZH.js} +28 -21
  53. package/dist/chunk-7I7FKFZH.js.map +1 -0
  54. package/dist/chunk-AJU4PJGY.js +126 -0
  55. package/dist/chunk-AJU4PJGY.js.map +1 -0
  56. package/dist/chunk-ASAITVLA.js +64 -0
  57. package/dist/chunk-ASAITVLA.js.map +1 -0
  58. package/dist/{chunk-X4WESCKA.js → chunk-B5WXLVDY.js} +187 -6
  59. package/dist/chunk-B5WXLVDY.js.map +1 -0
  60. package/dist/{chunk-RCICHSHL.js → chunk-BGJGXLZ7.js} +111 -2
  61. package/dist/{chunk-RCICHSHL.js.map → chunk-BGJGXLZ7.js.map} +1 -1
  62. package/dist/{chunk-OJFGVJS6.js → chunk-BK2EFTE2.js} +319 -18
  63. package/dist/chunk-BK2EFTE2.js.map +1 -0
  64. package/dist/chunk-C4SQJZAF.js +486 -0
  65. package/dist/chunk-C4SQJZAF.js.map +1 -0
  66. package/dist/{chunk-GJQPH5G3.js → chunk-CUPFXL3J.js} +2 -2
  67. package/dist/chunk-DF3RVK3X.js +119 -0
  68. package/dist/chunk-DF3RVK3X.js.map +1 -0
  69. package/dist/{chunk-PMB3WGDL.js → chunk-DFTTJYSO.js} +167 -7
  70. package/dist/chunk-DFTTJYSO.js.map +1 -0
  71. package/dist/chunk-DGVM5SFL.js +69 -0
  72. package/dist/chunk-DGVM5SFL.js.map +1 -0
  73. package/dist/chunk-EIR5VLIH.js +90 -0
  74. package/dist/chunk-EIR5VLIH.js.map +1 -0
  75. package/dist/{chunk-PAORGQRI.js → chunk-EPQJM2GC.js} +37 -23
  76. package/dist/chunk-EPQJM2GC.js.map +1 -0
  77. package/dist/{chunk-POMSFKTB.js → chunk-F5VP6YCB.js} +368 -10
  78. package/dist/chunk-F5VP6YCB.js.map +1 -0
  79. package/dist/{chunk-6ZH4TU6I.js → chunk-FAAFWE4G.js} +2 -1
  80. package/dist/chunk-FAAFWE4G.js.map +1 -0
  81. package/dist/{chunk-74JR4N5J.js → chunk-FVA6TGI3.js} +2 -2
  82. package/dist/chunk-GDFS42HT.js +206 -0
  83. package/dist/chunk-GDFS42HT.js.map +1 -0
  84. package/dist/{chunk-BKQJBXXX.js → chunk-GGD5W7TB.js} +2 -2
  85. package/dist/chunk-GGD5W7TB.js.map +1 -0
  86. package/dist/{chunk-V7XCAHIB.js → chunk-GKFXUTJ2.js} +508 -26
  87. package/dist/chunk-GKFXUTJ2.js.map +1 -0
  88. package/dist/{chunk-NSB3WSYS.js → chunk-HK3FGIEW.js} +278 -3
  89. package/dist/chunk-HK3FGIEW.js.map +1 -0
  90. package/dist/{chunk-AAI7JARD.js → chunk-HMDCOMYU.js} +8 -11
  91. package/dist/chunk-HMDCOMYU.js.map +1 -0
  92. package/dist/chunk-IISBCCWR.js +52 -0
  93. package/dist/chunk-IISBCCWR.js.map +1 -0
  94. package/dist/{chunk-YFYL2SIJ.js → chunk-INXV5JBT.js} +290 -46
  95. package/dist/chunk-INXV5JBT.js.map +1 -0
  96. package/dist/chunk-JBMSGZEQ.js +441 -0
  97. package/dist/chunk-JBMSGZEQ.js.map +1 -0
  98. package/dist/{chunk-UPMD5XND.js → chunk-JL2PU6AI.js} +16 -5
  99. package/dist/chunk-JL2PU6AI.js.map +1 -0
  100. package/dist/{chunk-J4IYOZZ5.js → chunk-JXS5PDQ7.js} +3 -1
  101. package/dist/chunk-JXS5PDQ7.js.map +1 -0
  102. package/dist/{chunk-AYPYCLR7.js → chunk-KUB6JU6H.js} +4 -4
  103. package/dist/chunk-KVBLZUKV.js +173 -0
  104. package/dist/chunk-KVBLZUKV.js.map +1 -0
  105. package/dist/chunk-LBLXEFWK.js +51 -0
  106. package/dist/chunk-LBLXEFWK.js.map +1 -0
  107. package/dist/{chunk-U2IQTSBY.js → chunk-LTCGGW2D.js} +1 -1
  108. package/dist/chunk-LTCGGW2D.js.map +1 -0
  109. package/dist/{chunk-UEYA6UC7.js → chunk-NZLQTHS5.js} +25 -2
  110. package/dist/chunk-NZLQTHS5.js.map +1 -0
  111. package/dist/chunk-PVGDJXVK.js +21 -0
  112. package/dist/chunk-PVGDJXVK.js.map +1 -0
  113. package/dist/chunk-PVPWZSSI.js +37 -0
  114. package/dist/chunk-PVPWZSSI.js.map +1 -0
  115. package/dist/{chunk-4NRAJUDS.js → chunk-RBBWYEFJ.js} +1 -1
  116. package/dist/chunk-RFYAYKTD.js +146 -0
  117. package/dist/chunk-RFYAYKTD.js.map +1 -0
  118. package/dist/{chunk-JROGC36Y.js → chunk-RGLL5SPU.js} +2 -2
  119. package/dist/{chunk-2VFW5K5U.js → chunk-S3EEFKNY.js} +103 -65
  120. package/dist/chunk-S3EEFKNY.js.map +1 -0
  121. package/dist/chunk-SOBJ6NEY.js +18 -0
  122. package/dist/chunk-SOBJ6NEY.js.map +1 -0
  123. package/dist/{chunk-MYQWXITD.js → chunk-SPI27QT6.js} +2 -2
  124. package/dist/chunk-TVVEYCNW.js +65 -0
  125. package/dist/chunk-TVVEYCNW.js.map +1 -0
  126. package/dist/chunk-ULYOGL6R.js +322 -0
  127. package/dist/chunk-ULYOGL6R.js.map +1 -0
  128. package/dist/{chunk-S4LX5EBI.js → chunk-VBVG2M5G.js} +64 -10
  129. package/dist/chunk-VBVG2M5G.js.map +1 -0
  130. package/dist/{chunk-KWP7T3DP.js → chunk-VDX363PS.js} +2 -2
  131. package/dist/{chunk-XMGSSBFX.js → chunk-VYM3VWOF.js} +1560 -244
  132. package/dist/chunk-VYM3VWOF.js.map +1 -0
  133. package/dist/{chunk-MTLYEMJB.js → chunk-WCLICCGB.js} +18 -3
  134. package/dist/chunk-WCLICCGB.js.map +1 -0
  135. package/dist/{chunk-ECKDIK5F.js → chunk-WVVA7F5A.js} +2 -2
  136. package/dist/chunk-X6GF3FX2.js +26 -0
  137. package/dist/chunk-X6GF3FX2.js.map +1 -0
  138. package/dist/{chunk-3QFQGRHO.js → chunk-XMHBH5H6.js} +4 -4
  139. package/dist/{chunk-KEG4GNGI.js → chunk-XZ2TIKGC.js} +38 -8
  140. package/dist/chunk-XZ2TIKGC.js.map +1 -0
  141. package/dist/chunk-Y4FHOFJ2.js +140 -0
  142. package/dist/chunk-Y4FHOFJ2.js.map +1 -0
  143. package/dist/chunk-YNB73F22.js +137 -0
  144. package/dist/chunk-YNB73F22.js.map +1 -0
  145. package/dist/{chunk-7PA4OZEU.js → chunk-YNQKWQT4.js} +55 -30
  146. package/dist/chunk-YNQKWQT4.js.map +1 -0
  147. package/dist/chunk-ZAIM4TUE.js +488 -0
  148. package/dist/chunk-ZAIM4TUE.js.map +1 -0
  149. package/dist/{chunk-BTY5RRRF.js → chunk-ZEM3OK2K.js} +5 -5
  150. package/dist/chunk-ZZTOURJI.js +91 -0
  151. package/dist/chunk-ZZTOURJI.js.map +1 -0
  152. package/dist/{cli-DwIBnp2g.d.ts → cli-BkeRaYfk.d.ts} +2 -2
  153. package/dist/cli.d.ts +13 -5
  154. package/dist/cli.js +45 -33
  155. package/dist/config.js +1 -1
  156. package/dist/consolidation-operator.d.ts +41 -0
  157. package/dist/consolidation-operator.js +11 -0
  158. package/dist/consolidation-operator.js.map +1 -0
  159. package/dist/consolidation-provenance-check.d.ts +68 -0
  160. package/dist/consolidation-provenance-check.js +9 -0
  161. package/dist/consolidation-provenance-check.js.map +1 -0
  162. package/dist/consolidation-undo.d.ts +123 -0
  163. package/dist/consolidation-undo.js +426 -0
  164. package/dist/consolidation-undo.js.map +1 -0
  165. package/dist/contradiction-review-WIUBAR52.js +21 -0
  166. package/dist/contradiction-review-WIUBAR52.js.map +1 -0
  167. package/dist/contradiction-scan-E3GJTI4F.js +412 -0
  168. package/dist/contradiction-scan-E3GJTI4F.js.map +1 -0
  169. package/dist/cross-namespace-budget.d.ts +133 -0
  170. package/dist/cross-namespace-budget.js +9 -0
  171. package/dist/cross-namespace-budget.js.map +1 -0
  172. package/dist/direct-answer-wiring.d.ts +77 -0
  173. package/dist/direct-answer-wiring.js +10 -0
  174. package/dist/direct-answer-wiring.js.map +1 -0
  175. package/dist/direct-answer.d.ts +106 -0
  176. package/dist/direct-answer.js +10 -0
  177. package/dist/direct-answer.js.map +1 -0
  178. package/dist/{engine-X7X3AAG3.js → engine-F3GOXGE5.js} +7 -6
  179. package/dist/engine-F3GOXGE5.js.map +1 -0
  180. package/dist/entity-retrieval.d.ts +1 -0
  181. package/dist/entity-retrieval.js +6 -5
  182. package/dist/explicit-capture.d.ts +6 -3
  183. package/dist/explicit-capture.js +2 -2
  184. package/dist/extraction-judge-telemetry.d.ts +113 -0
  185. package/dist/extraction-judge-telemetry.js +14 -0
  186. package/dist/extraction-judge-telemetry.js.map +1 -0
  187. package/dist/extraction-judge-training.d.ts +85 -0
  188. package/dist/extraction-judge-training.js +16 -0
  189. package/dist/extraction-judge-training.js.map +1 -0
  190. package/dist/extraction-judge.d.ts +124 -2
  191. package/dist/extraction-judge.js +11 -1
  192. package/dist/extraction.js +7 -6
  193. package/dist/fallback-llm.d.ts +11 -2
  194. package/dist/fallback-llm.js +2 -2
  195. package/dist/graph-recall.d.ts +100 -0
  196. package/dist/graph-recall.js +8 -0
  197. package/dist/graph-recall.js.map +1 -0
  198. package/dist/graph-retrieval.d.ts +271 -0
  199. package/dist/graph-retrieval.js +21 -0
  200. package/dist/graph-retrieval.js.map +1 -0
  201. package/dist/harmonic-retrieval.js +2 -1
  202. package/dist/importance.js +1 -1
  203. package/dist/index.d.ts +589 -138
  204. package/dist/index.js +531 -403
  205. package/dist/index.js.map +1 -1
  206. package/dist/intent.js +1 -1
  207. package/dist/local-llm.d.ts +10 -3
  208. package/dist/local-llm.js +1 -1
  209. package/dist/memory-worth-bench.d.ts +51 -0
  210. package/dist/memory-worth-bench.js +131 -0
  211. package/dist/memory-worth-bench.js.map +1 -0
  212. package/dist/memory-worth-filter.d.ts +128 -0
  213. package/dist/memory-worth-filter.js +10 -0
  214. package/dist/memory-worth-filter.js.map +1 -0
  215. package/dist/memory-worth-outcomes.d.ts +118 -0
  216. package/dist/memory-worth-outcomes.js +9 -0
  217. package/dist/memory-worth-outcomes.js.map +1 -0
  218. package/dist/memory-worth.d.ts +102 -0
  219. package/dist/memory-worth.js +7 -0
  220. package/dist/memory-worth.js.map +1 -0
  221. package/dist/operator-toolkit.d.ts +40 -1
  222. package/dist/operator-toolkit.js +24 -14
  223. package/dist/{orchestrator-B9kwlCep.d.ts → orchestrator-CmJ-NTdJ.d.ts} +254 -10
  224. package/dist/orchestrator.d.ts +6 -3
  225. package/dist/orchestrator.js +59 -48
  226. package/dist/page-versioning.d.ts +12 -1
  227. package/dist/page-versioning.js +5 -3
  228. package/dist/{port-C1GZFv8h.d.ts → port-BADbLZU5.d.ts} +2 -2
  229. package/dist/qmd-recall-cache.d.ts +1 -1
  230. package/dist/qmd.d.ts +5 -3
  231. package/dist/qmd.js +2 -1
  232. package/dist/reasoning-trace-recall.d.ts +90 -0
  233. package/dist/reasoning-trace-recall.js +13 -0
  234. package/dist/reasoning-trace-recall.js.map +1 -0
  235. package/dist/reasoning-trace-types.d.ts +54 -0
  236. package/dist/reasoning-trace-types.js +17 -0
  237. package/dist/reasoning-trace-types.js.map +1 -0
  238. package/dist/recall-audit-anomaly.d.ts +112 -0
  239. package/dist/recall-audit-anomaly.js +11 -0
  240. package/dist/recall-audit-anomaly.js.map +1 -0
  241. package/dist/recall-audit.js +5 -44
  242. package/dist/recall-audit.js.map +1 -1
  243. package/dist/recall-explain-renderer.d.ts +49 -0
  244. package/dist/recall-explain-renderer.js +18 -0
  245. package/dist/recall-explain-renderer.js.map +1 -0
  246. package/dist/recall-state.d.ts +39 -1
  247. package/dist/recall-state.js +1 -1
  248. package/dist/recall-xray-cli.d.ts +40 -0
  249. package/dist/recall-xray-cli.js +11 -0
  250. package/dist/recall-xray-cli.js.map +1 -0
  251. package/dist/recall-xray-renderer.d.ts +44 -0
  252. package/dist/recall-xray-renderer.js +18 -0
  253. package/dist/recall-xray-renderer.js.map +1 -0
  254. package/dist/recall-xray.d.ts +179 -0
  255. package/dist/recall-xray.js +13 -0
  256. package/dist/recall-xray.js.map +1 -0
  257. package/dist/resolution-QBTDHTG7.js +100 -0
  258. package/dist/resolution-QBTDHTG7.js.map +1 -0
  259. package/dist/resolve-provider-secret.d.ts +24 -1
  260. package/dist/resolve-provider-secret.js +3 -1
  261. package/dist/resume-bundles.js +6 -6
  262. package/dist/retrieval-agents.d.ts +1 -1
  263. package/dist/retrieval-tiers.d.ts +17 -0
  264. package/dist/retrieval-tiers.js +9 -0
  265. package/dist/retrieval-tiers.js.map +1 -0
  266. package/dist/schemas.d.ts +301 -45
  267. package/dist/schemas.js +1 -1
  268. package/dist/{semantic-consolidation-DrvSYRdB.d.ts → semantic-consolidation-CxJU6MJk.d.ts} +62 -1
  269. package/dist/semantic-consolidation.d.ts +2 -1
  270. package/dist/semantic-consolidation.js +20 -6
  271. package/dist/semantic-rule-promotion.js +6 -5
  272. package/dist/semantic-rule-verifier.js +6 -5
  273. package/dist/storage.d.ts +82 -1
  274. package/dist/storage.js +5 -4
  275. package/dist/summarizer.js +4 -4
  276. package/dist/temporal-supersession.d.ts +1 -0
  277. package/dist/tier-migration.d.ts +2 -1
  278. package/dist/types-DJhqDJUV.d.ts +50 -0
  279. package/dist/types.d.ts +309 -3
  280. package/dist/types.js +1 -1
  281. package/dist/verified-recall.js +6 -5
  282. package/package.json +1 -1
  283. package/dist/chunk-2VFW5K5U.js.map +0 -1
  284. package/dist/chunk-6ZH4TU6I.js.map +0 -1
  285. package/dist/chunk-7PA4OZEU.js.map +0 -1
  286. package/dist/chunk-AAI7JARD.js.map +0 -1
  287. package/dist/chunk-BKQJBXXX.js.map +0 -1
  288. package/dist/chunk-HITJFT7E.js.map +0 -1
  289. package/dist/chunk-J4IYOZZ5.js.map +0 -1
  290. package/dist/chunk-KEG4GNGI.js.map +0 -1
  291. package/dist/chunk-LAYN4LDC.js +0 -267
  292. package/dist/chunk-LAYN4LDC.js.map +0 -1
  293. package/dist/chunk-MTLYEMJB.js.map +0 -1
  294. package/dist/chunk-NSB3WSYS.js.map +0 -1
  295. package/dist/chunk-OJFGVJS6.js.map +0 -1
  296. package/dist/chunk-PAORGQRI.js.map +0 -1
  297. package/dist/chunk-PMB3WGDL.js.map +0 -1
  298. package/dist/chunk-POMSFKTB.js.map +0 -1
  299. package/dist/chunk-QDYXG4CS.js.map +0 -1
  300. package/dist/chunk-QKAH5B6E.js.map +0 -1
  301. package/dist/chunk-QNJMBKFK.js.map +0 -1
  302. package/dist/chunk-S4LX5EBI.js.map +0 -1
  303. package/dist/chunk-U2IQTSBY.js.map +0 -1
  304. package/dist/chunk-UEYA6UC7.js.map +0 -1
  305. package/dist/chunk-UPMD5XND.js.map +0 -1
  306. package/dist/chunk-UVJFDP7P.js +0 -202
  307. package/dist/chunk-UVJFDP7P.js.map +0 -1
  308. package/dist/chunk-V7XCAHIB.js.map +0 -1
  309. package/dist/chunk-X4WESCKA.js.map +0 -1
  310. package/dist/chunk-XMGSSBFX.js.map +0 -1
  311. package/dist/chunk-YFYL2SIJ.js.map +0 -1
  312. /package/dist/{engine-X7X3AAG3.js.map → abort-error.js.map} +0 -0
  313. /package/dist/{chunk-POBPGDWI.js.map → chunk-3OGMS3PE.js.map} +0 -0
  314. /package/dist/{chunk-GJQPH5G3.js.map → chunk-CUPFXL3J.js.map} +0 -0
  315. /package/dist/{chunk-74JR4N5J.js.map → chunk-FVA6TGI3.js.map} +0 -0
  316. /package/dist/{chunk-AYPYCLR7.js.map → chunk-KUB6JU6H.js.map} +0 -0
  317. /package/dist/{chunk-4NRAJUDS.js.map → chunk-RBBWYEFJ.js.map} +0 -0
  318. /package/dist/{chunk-JROGC36Y.js.map → chunk-RGLL5SPU.js.map} +0 -0
  319. /package/dist/{chunk-MYQWXITD.js.map → chunk-SPI27QT6.js.map} +0 -0
  320. /package/dist/{chunk-KWP7T3DP.js.map → chunk-VDX363PS.js.map} +0 -0
  321. /package/dist/{chunk-ECKDIK5F.js.map → chunk-WVVA7F5A.js.map} +0 -0
  322. /package/dist/{chunk-3QFQGRHO.js.map → chunk-XMHBH5H6.js.map} +0 -0
  323. /package/dist/{chunk-BTY5RRRF.js.map → chunk-ZEM3OK2K.js.map} +0 -0
@@ -2,7 +2,10 @@ import {
2
2
  CompoundingEngine,
3
3
  SharedContextManager,
4
4
  defaultTierMigrationCycleBudget
5
- } from "./chunk-JROGC36Y.js";
5
+ } from "./chunk-RGLL5SPU.js";
6
+ import {
7
+ extractTopics
8
+ } from "./chunk-UHGBNIOS.js";
6
9
  import {
7
10
  applyUtilityPromotionRuntimePolicy,
8
11
  applyUtilityRankingRuntimeDelta,
@@ -23,17 +26,14 @@ import {
23
26
  TmtBuilder
24
27
  } from "./chunk-TPB3I2AC.js";
25
28
  import {
26
- extractTopics
27
- } from "./chunk-UHGBNIOS.js";
29
+ SessionObserverState
30
+ } from "./chunk-JR4ZC3G4.js";
28
31
  import {
29
32
  HourlySummarizer
30
- } from "./chunk-BTY5RRRF.js";
31
- import {
32
- semanticChunkContent
33
- } from "./chunk-KVE7R4CG.js";
33
+ } from "./chunk-ZEM3OK2K.js";
34
34
  import {
35
- SessionObserverState
36
- } from "./chunk-JR4ZC3G4.js";
35
+ RelevanceStore
36
+ } from "./chunk-5NPGSAVB.js";
37
37
  import {
38
38
  RerankCache,
39
39
  rerankLocalOrNoop
@@ -59,23 +59,26 @@ import {
59
59
  import {
60
60
  applyRuntimeRetrievalPolicy
61
61
  } from "./chunk-5IZL4DCV.js";
62
- import {
63
- reorderRecallResultsWithMmr
64
- } from "./chunk-YDBIWGNI.js";
65
- import {
66
- createRecallSectionMetricRecorder
67
- } from "./chunk-7DHTMOND.js";
68
62
  import {
69
63
  LastRecallStore,
70
64
  TierMigrationStatusStore,
71
65
  clampGraphRecallExpandedEntries
72
- } from "./chunk-S4LX5EBI.js";
66
+ } from "./chunk-VBVG2M5G.js";
67
+ import {
68
+ buildXraySnapshot
69
+ } from "./chunk-KVBLZUKV.js";
73
70
  import {
74
71
  findUnresolvedEntityRefs
75
72
  } from "./chunk-X7XN6YU4.js";
76
73
  import {
77
- RelevanceStore
78
- } from "./chunk-5NPGSAVB.js";
74
+ applyReasoningTraceBoost
75
+ } from "./chunk-ZZTOURJI.js";
76
+ import {
77
+ reorderRecallResultsWithMmr
78
+ } from "./chunk-YDBIWGNI.js";
79
+ import {
80
+ createRecallSectionMetricRecorder
81
+ } from "./chunk-7DHTMOND.js";
79
82
  import {
80
83
  buildQmdRecallCacheKey,
81
84
  getCachedQmdRecall,
@@ -87,69 +90,83 @@ import {
87
90
  import {
88
91
  evaluateMemoryActionPolicy
89
92
  } from "./chunk-H63EDPFJ.js";
93
+ import {
94
+ applyMemoryWorthFilter,
95
+ buildMemoryWorthCounterMap
96
+ } from "./chunk-3GPTTA4J.js";
90
97
  import {
91
98
  hasBroadGraphIntent,
92
99
  inferIntentFromText,
93
100
  intentCompatibilityScore,
94
101
  isTaskInitiationIntent,
95
102
  planRecallMode
96
- } from "./chunk-BKQJBXXX.js";
103
+ } from "./chunk-GGD5W7TB.js";
97
104
  import {
98
105
  classifyMemoryKind
99
106
  } from "./chunk-YAZNBMNF.js";
100
107
  import {
101
- EmbeddingFallback
102
- } from "./chunk-ALXMCZEU.js";
108
+ EXTRACTION_JUDGE_VERDICT_CATEGORY,
109
+ recordJudgeVerdict
110
+ } from "./chunk-AJU4PJGY.js";
103
111
  import {
104
- buildEntityRecallSection,
105
- entityRecentTranscriptLookbackHours,
106
- readRecentEntityTranscriptEntries
107
- } from "./chunk-74JR4N5J.js";
112
+ recordJudgeTrainingPair
113
+ } from "./chunk-DF3RVK3X.js";
108
114
  import {
115
+ createDeferCountMap,
109
116
  createVerdictCache,
117
+ getVerdictKind,
110
118
  judgeFactDurability,
111
119
  validateProcedureExtraction
112
- } from "./chunk-LAYN4LDC.js";
120
+ } from "./chunk-C4SQJZAF.js";
113
121
  import {
114
122
  ExtractionEngine
115
- } from "./chunk-2VFW5K5U.js";
123
+ } from "./chunk-S3EEFKNY.js";
116
124
  import {
117
125
  parseMemoryActionEligibilityContext
118
- } from "./chunk-UEYA6UC7.js";
126
+ } from "./chunk-NZLQTHS5.js";
119
127
  import {
120
128
  ProfilingCollector
121
129
  } from "./chunk-NBNN5GOB.js";
122
- import {
123
- LocalLlmClient
124
- } from "./chunk-UPMD5XND.js";
125
130
  import {
126
131
  ModelRegistry
127
132
  } from "./chunk-FEMOX5AD.js";
133
+ import {
134
+ LocalLlmClient
135
+ } from "./chunk-JL2PU6AI.js";
136
+ import {
137
+ tryDirectAnswer
138
+ } from "./chunk-6AUUAZEX.js";
139
+ import {
140
+ EmbeddingFallback
141
+ } from "./chunk-ALXMCZEU.js";
142
+ import {
143
+ buildEntityRecallSection,
144
+ entityRecentTranscriptLookbackHours,
145
+ readRecentEntityTranscriptEntries
146
+ } from "./chunk-FVA6TGI3.js";
147
+ import {
148
+ formatDaySummaryMemories
149
+ } from "./chunk-GZCUW5IC.js";
128
150
  import {
129
151
  RoutingRulesStore,
152
+ expandTildePath,
130
153
  normalizeReplaySessionKey
131
- } from "./chunk-PAORGQRI.js";
154
+ } from "./chunk-EPQJM2GC.js";
132
155
  import {
133
156
  searchVerifiedEpisodes
134
- } from "./chunk-GJQPH5G3.js";
157
+ } from "./chunk-CUPFXL3J.js";
135
158
  import {
136
159
  ThreadingManager
137
160
  } from "./chunk-JRNQ3RNA.js";
138
161
  import {
139
162
  searchVerifiedSemanticRules
140
- } from "./chunk-MYQWXITD.js";
163
+ } from "./chunk-SPI27QT6.js";
141
164
  import {
142
165
  searchWorkProductLedgerEntries
143
166
  } from "./chunk-CULXMQJH.js";
144
167
  import {
145
168
  TranscriptManager
146
169
  } from "./chunk-E6K4NIEU.js";
147
- import {
148
- PolicyRuntimeManager
149
- } from "./chunk-EABGC2TL.js";
150
- import {
151
- searchObjectiveStateSnapshots
152
- } from "./chunk-LOBRX7VD.js";
153
170
  import {
154
171
  NamespaceSearchRouter,
155
172
  NamespaceStorageRouter,
@@ -157,17 +174,26 @@ import {
157
174
  createConversationIndexRuntime,
158
175
  createSearchBackend,
159
176
  writeConversationChunks
160
- } from "./chunk-HITJFT7E.js";
177
+ } from "./chunk-7I7FKFZH.js";
161
178
  import {
162
179
  parseQmdExplain
163
- } from "./chunk-7PA4OZEU.js";
180
+ } from "./chunk-YNQKWQT4.js";
181
+ import {
182
+ PolicyRuntimeManager
183
+ } from "./chunk-EABGC2TL.js";
184
+ import {
185
+ searchObjectiveStateSnapshots
186
+ } from "./chunk-LOBRX7VD.js";
187
+ import {
188
+ searchHarmonicRetrieval
189
+ } from "./chunk-HMDCOMYU.js";
164
190
  import {
165
191
  isAboveImportanceThreshold,
166
192
  scoreImportance
167
- } from "./chunk-J4IYOZZ5.js";
193
+ } from "./chunk-JXS5PDQ7.js";
168
194
  import {
169
- searchHarmonicRetrieval
170
- } from "./chunk-AAI7JARD.js";
195
+ launchProcessSync
196
+ } from "./chunk-LK6SGL53.js";
171
197
  import {
172
198
  collectNativeKnowledgeChunks,
173
199
  formatNativeKnowledgeSection,
@@ -176,6 +202,9 @@ import {
176
202
  import {
177
203
  recordEvalShadowRecall
178
204
  } from "./chunk-K6WK37A6.js";
205
+ import {
206
+ GraphIndex
207
+ } from "./chunk-C2EFFULQ.js";
179
208
  import {
180
209
  CODEX_THREAD_KEY_PREFIX
181
210
  } from "./chunk-3PG3H5TD.js";
@@ -189,21 +218,27 @@ import {
189
218
  renderCompressionGuidelinesMarkdown
190
219
  } from "./chunk-2NMMFZ5T.js";
191
220
  import {
192
- formatDaySummaryMemories
193
- } from "./chunk-GZCUW5IC.js";
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-RCICHSHL.js";
201
- import {
202
- GraphIndex
203
- } from "./chunk-C2EFFULQ.js";
236
+ parseConsolidationResponse,
237
+ parseOperatorAwareConsolidationResponse
238
+ } from "./chunk-BGJGXLZ7.js";
204
239
  import {
205
- chunkContent
206
- } from "./chunk-4WMCPJWX.js";
240
+ FallbackLlmClient
241
+ } from "./chunk-3GXCSUXR.js";
207
242
  import {
208
243
  buildRecallQueryPolicy
209
244
  } from "./chunk-6HZ6AO2P.js";
@@ -214,36 +249,42 @@ import {
214
249
  import {
215
250
  BootstrapEngine
216
251
  } from "./chunk-N53K2EXC.js";
217
- import {
218
- BoxBuilder
219
- } from "./chunk-URB2WSKZ.js";
220
- import {
221
- SmartBuffer
222
- } from "./chunk-UVJFDP7P.js";
223
252
  import {
224
253
  isDisagreementPrompt
225
254
  } from "./chunk-XYIK4LF6.js";
226
255
  import {
227
- FallbackLlmClient
228
- } from "./chunk-QKAH5B6E.js";
256
+ BoxBuilder
257
+ } from "./chunk-URB2WSKZ.js";
258
+ import {
259
+ abortError,
260
+ isAbortError,
261
+ throwIfAborted
262
+ } from "./chunk-PVGDJXVK.js";
229
263
  import {
230
264
  resolveHomeDir
231
265
  } from "./chunk-MARWOCVP.js";
232
266
  import {
267
+ listTrustZoneRecords,
233
268
  searchTrustZoneRecords
234
269
  } from "./chunk-EQINRHYR.js";
270
+ import {
271
+ buildProcedurePersistBody
272
+ } from "./chunk-QDW3E4RD.js";
235
273
  import {
236
274
  shouldSkipImplicitExtraction
237
- } from "./chunk-QDYXG4CS.js";
275
+ } from "./chunk-3FPTCC3Z.js";
238
276
  import {
239
277
  selectRouteRule
240
- } from "./chunk-QNJMBKFK.js";
241
- import {
242
- buildProcedurePersistBody
243
- } from "./chunk-QDW3E4RD.js";
278
+ } from "./chunk-2LGMW3DJ.js";
244
279
  import {
245
280
  searchCausalTrajectories
246
- } from "./chunk-4NRAJUDS.js";
281
+ } from "./chunk-RBBWYEFJ.js";
282
+ import {
283
+ canReadNamespace,
284
+ defaultNamespaceForPrincipal,
285
+ recallNamespacesForPrincipal,
286
+ resolvePrincipal
287
+ } from "./chunk-N5AKDXAI.js";
247
288
  import {
248
289
  decideLifecycleTransition,
249
290
  resolveLifecycleState
@@ -256,10 +297,10 @@ import {
256
297
  normalizeAttributePairs,
257
298
  normalizeEntityName,
258
299
  parseEntityFile
259
- } from "./chunk-POMSFKTB.js";
300
+ } from "./chunk-F5VP6YCB.js";
260
301
  import {
261
302
  confidenceTier
262
- } from "./chunk-U2IQTSBY.js";
303
+ } from "./chunk-LTCGGW2D.js";
263
304
  import {
264
305
  attachCitation,
265
306
  hasCitationForTemplate,
@@ -278,25 +319,19 @@ import {
278
319
  import {
279
320
  log
280
321
  } from "./chunk-2ODBA7MQ.js";
281
- import {
282
- canReadNamespace,
283
- defaultNamespaceForPrincipal,
284
- recallNamespacesForPrincipal,
285
- resolvePrincipal
286
- } from "./chunk-N5AKDXAI.js";
287
322
 
288
323
  // src/orchestrator.ts
289
- import path5 from "path";
324
+ import path7 from "path";
290
325
  import os from "os";
291
326
  import { createHash as createHash2, randomBytes } from "crypto";
292
327
  import { existsSync as existsSync2 } from "fs";
293
328
  import {
294
- mkdir as mkdir4,
329
+ mkdir as mkdir5,
295
330
  readdir as readdir3,
296
- readFile as readFile3,
331
+ readFile as readFile4,
297
332
  stat as stat3,
298
333
  unlink as unlink2,
299
- writeFile as writeFile3
334
+ writeFile as writeFile4
300
335
  } from "fs/promises";
301
336
 
302
337
  // src/migrate/from-engram.ts
@@ -873,7 +908,7 @@ async function buildProcedureRecallSection(storage, prompt, config) {
873
908
  10,
874
909
  Math.max(
875
910
  1,
876
- typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) : 3
911
+ typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) : 2
877
912
  )
878
913
  );
879
914
  const all = await storage.readAllMemories();
@@ -901,6 +936,7 @@ import path2 from "path";
901
936
  var DAY_SUMMARY_CRON_ID = "engram-day-summary";
902
937
  var GOVERNANCE_CRON_ID = "engram-nightly-governance";
903
938
  var PROCEDURAL_MINING_CRON_ID = "engram-procedural-mining";
939
+ var CONTRADICTION_SCAN_CRON_ID = "engram-contradiction-scan";
904
940
  async function acquireCronJobsLock(jobsPath) {
905
941
  const lockPath2 = `${jobsPath}.lock`;
906
942
  const start = Date.now();
@@ -1037,6 +1073,30 @@ async function ensureProceduralMiningCron(jobsPath, options) {
1037
1073
  delivery: { mode: "none" }
1038
1074
  }));
1039
1075
  }
1076
+ async function ensureContradictionScanCron(jobsPath, options) {
1077
+ const scheduleExpr = typeof options.scheduleExpr === "string" && options.scheduleExpr.trim().length > 0 ? options.scheduleExpr.trim() : "37 3 * * *";
1078
+ const agentId = typeof options.agentId === "string" && options.agentId.trim().length > 0 ? options.agentId.trim() : "main";
1079
+ return ensureCronJob(jobsPath, CONTRADICTION_SCAN_CRON_ID, () => ({
1080
+ id: CONTRADICTION_SCAN_CRON_ID,
1081
+ agentId,
1082
+ name: "Remnic Contradiction Scan (nightly)",
1083
+ enabled: true,
1084
+ schedule: {
1085
+ kind: "cron",
1086
+ expr: scheduleExpr,
1087
+ tz: options.timezone
1088
+ },
1089
+ sessionTarget: "isolated",
1090
+ wakeMode: "now",
1091
+ payload: {
1092
+ kind: "agentTurn",
1093
+ timeoutSeconds: 900,
1094
+ thinking: "off",
1095
+ message: "You are OpenClaw automation. Call tool `engram.contradiction_scan_run` with empty params. If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool."
1096
+ },
1097
+ delivery: { mode: "none" }
1098
+ }));
1099
+ }
1040
1100
 
1041
1101
  // src/dedup/semantic.ts
1042
1102
  async function decideSemanticDedup(content, lookup, options) {
@@ -1089,12 +1149,253 @@ async function decideSemanticDedup(content, lookup, options) {
1089
1149
  };
1090
1150
  }
1091
1151
 
1092
- // src/lcm/schema.ts
1152
+ // src/taxonomy/default-taxonomy.ts
1153
+ var DEFAULT_TAXONOMY = {
1154
+ version: 1,
1155
+ categories: [
1156
+ {
1157
+ id: "corrections",
1158
+ name: "Corrections",
1159
+ description: "Corrections to previously stored information",
1160
+ filingRules: ["Any update that supersedes a prior fact"],
1161
+ priority: 10,
1162
+ memoryCategories: ["correction"]
1163
+ },
1164
+ {
1165
+ id: "principles",
1166
+ name: "Principles",
1167
+ description: "Rules, guidelines, and recurring patterns",
1168
+ filingRules: ["A guiding principle, rule, or skill"],
1169
+ priority: 20,
1170
+ memoryCategories: ["principle", "rule", "skill"]
1171
+ },
1172
+ {
1173
+ id: "procedures",
1174
+ name: "Procedures",
1175
+ description: "Ordered multi-step workflows the user repeats",
1176
+ filingRules: ["A repeatable sequence of steps or commands for a task"],
1177
+ priority: 25,
1178
+ memoryCategories: ["procedure"]
1179
+ },
1180
+ {
1181
+ id: "entities",
1182
+ name: "Entities",
1183
+ description: "People, organizations, places, projects",
1184
+ filingRules: ["Named entity with attributes"],
1185
+ priority: 30,
1186
+ memoryCategories: ["entity", "relationship"]
1187
+ },
1188
+ {
1189
+ id: "decisions",
1190
+ name: "Decisions",
1191
+ description: "Choices made and their rationale",
1192
+ filingRules: ["A decision or commitment with reasoning"],
1193
+ priority: 35,
1194
+ memoryCategories: ["decision", "commitment"]
1195
+ },
1196
+ {
1197
+ id: "preferences",
1198
+ name: "Preferences",
1199
+ description: "User likes, dislikes, and style choices",
1200
+ filingRules: ["Anything expressing a preference or taste"],
1201
+ priority: 40,
1202
+ memoryCategories: ["preference"]
1203
+ },
1204
+ {
1205
+ id: "facts",
1206
+ name: "Facts",
1207
+ description: "Objective statements about the world",
1208
+ filingRules: ["Any factual claim or piece of information"],
1209
+ priority: 50,
1210
+ memoryCategories: ["fact"]
1211
+ },
1212
+ {
1213
+ id: "moments",
1214
+ name: "Moments",
1215
+ description: "Significant events or experiences",
1216
+ filingRules: ["A specific event worth remembering"],
1217
+ priority: 60,
1218
+ memoryCategories: ["moment"]
1219
+ },
1220
+ {
1221
+ id: "reasoning-traces",
1222
+ name: "Reasoning Traces",
1223
+ description: "Stored intermediate reasoning / solution chains for a problem the agent previously solved",
1224
+ filingRules: [
1225
+ "A multi-step reasoning chain or solution walkthrough the agent can replay for a similar problem"
1226
+ ],
1227
+ priority: 55,
1228
+ memoryCategories: ["reasoning_trace"]
1229
+ }
1230
+ ]
1231
+ };
1232
+
1233
+ // src/taxonomy/resolver-doc-generator.ts
1234
+ function generateResolverDocument(taxonomy) {
1235
+ const sorted = [...taxonomy.categories].sort((a, b) => {
1236
+ if (a.priority !== b.priority) return a.priority - b.priority;
1237
+ return a.id.localeCompare(b.id);
1238
+ });
1239
+ const lines = [
1240
+ "# Memory Filing Resolver",
1241
+ "",
1242
+ "Given a new piece of knowledge, follow this tree to determine where it belongs.",
1243
+ ""
1244
+ ];
1245
+ let step = 1;
1246
+ for (const cat of sorted) {
1247
+ lines.push(`## Step ${step}: ${cat.description}?`);
1248
+ lines.push("");
1249
+ for (const rule of cat.filingRules) {
1250
+ lines.push(`- ${rule}`);
1251
+ }
1252
+ lines.push("");
1253
+ lines.push(
1254
+ `> YES: File under **${cat.id}/** (priority ${cat.priority})`
1255
+ );
1256
+ lines.push("");
1257
+ step++;
1258
+ }
1259
+ lines.push("## Tie-breaking");
1260
+ lines.push("");
1261
+ lines.push(
1262
+ "If a fact could go in multiple categories, file under the one with the **lowest priority number**."
1263
+ );
1264
+ lines.push("");
1265
+ lines.push(`---`);
1266
+ lines.push(`*Generated from taxonomy v${taxonomy.version}*`);
1267
+ lines.push("");
1268
+ return lines.join("\n");
1269
+ }
1270
+
1271
+ // src/taxonomy/taxonomy-loader.ts
1272
+ import { readFile as readFile3, mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
1093
1273
  import path3 from "path";
1094
- import { mkdir as mkdir3 } from "fs/promises";
1274
+ var TAXONOMY_DIR = ".taxonomy";
1275
+ var TAXONOMY_FILE = "taxonomy.json";
1276
+ var MAX_SLUG_LENGTH = 32;
1277
+ var SLUG_RE = /^[a-z][a-z0-9-]*$/;
1278
+ function validateSlug(slug) {
1279
+ if (slug.length === 0) {
1280
+ throw new Error("Taxonomy category ID must not be empty");
1281
+ }
1282
+ if (slug.length > MAX_SLUG_LENGTH) {
1283
+ throw new Error(
1284
+ `Taxonomy category ID "${slug}" exceeds ${MAX_SLUG_LENGTH} characters`
1285
+ );
1286
+ }
1287
+ if (!SLUG_RE.test(slug)) {
1288
+ throw new Error(
1289
+ `Taxonomy category ID "${slug}" is invalid: must be lowercase letters, digits, and hyphens, starting with a letter`
1290
+ );
1291
+ }
1292
+ }
1293
+ function validateTaxonomy(taxonomy) {
1294
+ if (typeof taxonomy.version !== "number" || taxonomy.version < 1) {
1295
+ throw new Error("Taxonomy version must be a positive integer");
1296
+ }
1297
+ if (!Array.isArray(taxonomy.categories)) {
1298
+ throw new Error("Taxonomy categories must be an array");
1299
+ }
1300
+ const seenIds = /* @__PURE__ */ new Set();
1301
+ for (const cat of taxonomy.categories) {
1302
+ validateSlug(cat.id);
1303
+ if (seenIds.has(cat.id)) {
1304
+ throw new Error(`Duplicate taxonomy category ID: "${cat.id}"`);
1305
+ }
1306
+ seenIds.add(cat.id);
1307
+ if (typeof cat.name !== "string" || cat.name.trim().length === 0) {
1308
+ throw new Error(`Taxonomy category "${cat.id}" must have a non-empty name`);
1309
+ }
1310
+ if (typeof cat.description !== "string" || cat.description.trim().length === 0) {
1311
+ throw new Error(`Taxonomy category "${cat.id}" must have a non-empty description`);
1312
+ }
1313
+ if (!Array.isArray(cat.filingRules)) {
1314
+ throw new Error(`Taxonomy category "${cat.id}" filingRules must be an array`);
1315
+ }
1316
+ if (typeof cat.priority !== "number" || !Number.isFinite(cat.priority)) {
1317
+ throw new Error(`Taxonomy category "${cat.id}" must have a finite numeric priority`);
1318
+ }
1319
+ if (!Array.isArray(cat.memoryCategories)) {
1320
+ throw new Error(`Taxonomy category "${cat.id}" memoryCategories must be an array`);
1321
+ }
1322
+ if (cat.parentId !== void 0) {
1323
+ if (typeof cat.parentId !== "string") {
1324
+ throw new Error(`Taxonomy category "${cat.id}" parentId must be a string if set`);
1325
+ }
1326
+ }
1327
+ }
1328
+ for (const cat of taxonomy.categories) {
1329
+ if (cat.parentId !== void 0 && !seenIds.has(cat.parentId)) {
1330
+ throw new Error(
1331
+ `Taxonomy category "${cat.id}" references unknown parentId "${cat.parentId}"`
1332
+ );
1333
+ }
1334
+ }
1335
+ }
1336
+ async function loadTaxonomy(memoryDir) {
1337
+ const taxonomyPath = path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1338
+ let raw;
1339
+ try {
1340
+ raw = await readFile3(taxonomyPath, "utf-8");
1341
+ } catch (err) {
1342
+ if (err instanceof Error && err.code === "ENOENT") {
1343
+ return structuredClone(DEFAULT_TAXONOMY);
1344
+ }
1345
+ throw err;
1346
+ }
1347
+ const parsed = JSON.parse(raw);
1348
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1349
+ throw new Error("taxonomy.json must be a JSON object");
1350
+ }
1351
+ const obj = parsed;
1352
+ const userVersion = typeof obj.version === "number" ? obj.version : DEFAULT_TAXONOMY.version;
1353
+ const userCategories = Array.isArray(obj.categories) ? obj.categories : [];
1354
+ const userIdCounts = /* @__PURE__ */ new Map();
1355
+ for (const cat of userCategories) {
1356
+ const id = typeof cat.id === "string" ? cat.id : String(cat.id);
1357
+ userIdCounts.set(id, (userIdCounts.get(id) ?? 0) + 1);
1358
+ }
1359
+ const duplicateIds = [...userIdCounts.entries()].filter(([, count]) => count > 1).map(([id]) => id);
1360
+ if (duplicateIds.length > 0) {
1361
+ throw new Error(
1362
+ `Duplicate category IDs in taxonomy.json: ${duplicateIds.map((id) => `"${id}"`).join(", ")}`
1363
+ );
1364
+ }
1365
+ const mergedMap = /* @__PURE__ */ new Map();
1366
+ for (const cat of DEFAULT_TAXONOMY.categories) {
1367
+ mergedMap.set(cat.id, { ...cat });
1368
+ }
1369
+ for (const cat of userCategories) {
1370
+ mergedMap.set(cat.id, cat);
1371
+ }
1372
+ const merged = {
1373
+ version: userVersion,
1374
+ categories: [...mergedMap.values()]
1375
+ };
1376
+ validateTaxonomy(merged);
1377
+ return merged;
1378
+ }
1379
+ async function saveTaxonomy(memoryDir, taxonomy) {
1380
+ validateTaxonomy(taxonomy);
1381
+ const dir = path3.join(memoryDir, TAXONOMY_DIR);
1382
+ await mkdir3(dir, { recursive: true });
1383
+ const filePath = path3.join(dir, TAXONOMY_FILE);
1384
+ await writeFile3(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
1385
+ }
1386
+ function getTaxonomyDir(memoryDir) {
1387
+ return path3.join(memoryDir, TAXONOMY_DIR);
1388
+ }
1389
+ function getTaxonomyFilePath(memoryDir) {
1390
+ return path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1391
+ }
1392
+
1393
+ // src/lcm/schema.ts
1394
+ import path4 from "path";
1395
+ import { mkdir as mkdir4 } from "fs/promises";
1095
1396
  var LCM_SCHEMA_VERSION = 1;
1096
1397
  function openLcmDatabase(memoryDir) {
1097
- const dbPath = path3.join(memoryDir, "state", "lcm.sqlite");
1398
+ const dbPath = path4.join(memoryDir, "state", "lcm.sqlite");
1098
1399
  const db = openBetterSqlite3(dbPath);
1099
1400
  db.pragma("journal_mode = WAL");
1100
1401
  db.pragma("busy_timeout = 5000");
@@ -1103,7 +1404,7 @@ function openLcmDatabase(memoryDir) {
1103
1404
  return db;
1104
1405
  }
1105
1406
  async function ensureLcmStateDir(memoryDir) {
1106
- await mkdir3(path3.join(memoryDir, "state"), { recursive: true });
1407
+ await mkdir4(path4.join(memoryDir, "state"), { recursive: true });
1107
1408
  }
1108
1409
  function applySchema(db) {
1109
1410
  const versionRow = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_meta'").get();
@@ -2367,7 +2668,7 @@ function chunkTranscriptEntries(sessionKey, entries, opts) {
2367
2668
 
2368
2669
  // src/conversation-index/cleanup.ts
2369
2670
  import { readdir as readdir2, rm as rm3 } from "fs/promises";
2370
- import path4 from "path";
2671
+ import path5 from "path";
2371
2672
  async function cleanupConversationChunks(rootDir, retentionDays) {
2372
2673
  if (!Number.isFinite(retentionDays) || retentionDays <= 0) return;
2373
2674
  const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1e3;
@@ -2375,7 +2676,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
2375
2676
  const sessions = await readdir2(rootDir, { withFileTypes: true });
2376
2677
  for (const s of sessions) {
2377
2678
  if (!s.isDirectory()) continue;
2378
- const sessionDir = path4.join(rootDir, s.name);
2679
+ const sessionDir = path5.join(rootDir, s.name);
2379
2680
  const dayDirs = await readdir2(sessionDir, { withFileTypes: true });
2380
2681
  for (const d of dayDirs) {
2381
2682
  if (!d.isDirectory()) continue;
@@ -2383,7 +2684,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
2383
2684
  const dayMs = (/* @__PURE__ */ new Date(d.name + "T00:00:00.000Z")).getTime();
2384
2685
  if (!Number.isFinite(dayMs)) continue;
2385
2686
  if (dayMs < cutoffMs) {
2386
- await rm3(path4.join(sessionDir, d.name), { recursive: true, force: true });
2687
+ await rm3(path5.join(sessionDir, d.name), { recursive: true, force: true });
2387
2688
  }
2388
2689
  }
2389
2690
  try {
@@ -2399,6 +2700,264 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
2399
2700
  }
2400
2701
  }
2401
2702
 
2703
+ // src/coding/git-context.ts
2704
+ import path6 from "path";
2705
+ var DEFAULT_GIT_TIMEOUT_MS = 2e3;
2706
+ function defaultGitInvoker() {
2707
+ return (cwd, args) => {
2708
+ const result = launchProcessSync("git", args, {
2709
+ cwd,
2710
+ encoding: "utf-8",
2711
+ timeout: DEFAULT_GIT_TIMEOUT_MS,
2712
+ shell: false
2713
+ });
2714
+ if (result.error) {
2715
+ return { stdout: "", exitCode: 127 };
2716
+ }
2717
+ return {
2718
+ stdout: typeof result.stdout === "string" ? result.stdout : "",
2719
+ exitCode: typeof result.status === "number" ? result.status : 1
2720
+ };
2721
+ };
2722
+ }
2723
+ function stableHash(input) {
2724
+ let hash = 2166136261;
2725
+ for (let i = 0; i < input.length; i++) {
2726
+ hash ^= input.charCodeAt(i);
2727
+ hash = Math.imul(hash, 16777619) >>> 0;
2728
+ }
2729
+ return hash.toString(16).padStart(8, "0");
2730
+ }
2731
+ function normalizeOriginUrl(rawUrl) {
2732
+ let url = rawUrl.trim();
2733
+ if (!url) return "";
2734
+ if (/\.git$/i.test(url)) url = url.slice(0, -4);
2735
+ if (/^[A-Za-z]:[\\/]/.test(url)) {
2736
+ return url.toLowerCase();
2737
+ }
2738
+ const protoMatch = /^[a-z][a-z0-9+.-]*:\/\/(?:[^@/]+@)?(\[[^\]]+\]|[^/:]*)(?::(\d+))?(\/.*)?$/i.exec(url);
2739
+ if (protoMatch) {
2740
+ let host = protoMatch[1] ?? "";
2741
+ const wasBracketed = host.startsWith("[") && host.endsWith("]");
2742
+ if (wasBracketed) host = host.slice(1, -1);
2743
+ const port = protoMatch[2];
2744
+ const repoPath = (protoMatch[3] ?? "").replace(/^\/+/, "");
2745
+ const hostPort = port ? wasBracketed ? `[${host}]:${port}` : `${host}:${port}` : host;
2746
+ const prefix = hostPort.length > 0 ? hostPort : "localhost";
2747
+ return `${prefix}/${repoPath}`.toLowerCase();
2748
+ }
2749
+ const scpMatch = /^(?:([^@\s/]+)@)?(\[[^\]]+\]|[^:@\s/]+):(.+)$/.exec(url);
2750
+ if (scpMatch) {
2751
+ let host = scpMatch[2] ?? "";
2752
+ if (host.startsWith("[") && host.endsWith("]")) host = host.slice(1, -1);
2753
+ const repoPath = scpMatch[3] ?? "";
2754
+ if (repoPath.startsWith("//")) {
2755
+ return url.toLowerCase();
2756
+ }
2757
+ return `${host}/${repoPath.replace(/^\/+/, "")}`.toLowerCase();
2758
+ }
2759
+ return url.toLowerCase();
2760
+ }
2761
+ async function resolveGitContext(cwd, options = {}) {
2762
+ try {
2763
+ if (typeof cwd !== "string" || cwd.length === 0) return null;
2764
+ const expanded = expandTildePath(cwd);
2765
+ if (!path6.isAbsolute(expanded)) return null;
2766
+ const invoker = options.invoker ?? defaultGitInvoker();
2767
+ const topLevel = invoker(expanded, ["rev-parse", "--show-toplevel"]);
2768
+ if (topLevel.exitCode !== 0) return null;
2769
+ const rootPath = topLevel.stdout.trim();
2770
+ if (!rootPath) return null;
2771
+ const branchResult = invoker(rootPath, ["rev-parse", "--abbrev-ref", "HEAD"]);
2772
+ let branch = null;
2773
+ if (branchResult.exitCode === 0) {
2774
+ const raw = branchResult.stdout.trim();
2775
+ branch = raw && raw !== "HEAD" ? raw : null;
2776
+ } else {
2777
+ const unbornRef = invoker(rootPath, ["symbolic-ref", "--quiet", "HEAD"]);
2778
+ if (unbornRef.exitCode === 0) {
2779
+ const raw = unbornRef.stdout.trim();
2780
+ const prefix = "refs/heads/";
2781
+ if (raw.startsWith(prefix)) {
2782
+ const candidate = raw.slice(prefix.length);
2783
+ if (candidate) branch = candidate;
2784
+ }
2785
+ }
2786
+ }
2787
+ const originResult = invoker(rootPath, ["remote", "get-url", "origin"]);
2788
+ let projectId;
2789
+ if (originResult.exitCode === 0) {
2790
+ const normalized = normalizeOriginUrl(originResult.stdout);
2791
+ projectId = normalized ? `origin:${stableHash(normalized)}` : `root:${stableHash(rootPath)}`;
2792
+ } else {
2793
+ projectId = `root:${stableHash(rootPath)}`;
2794
+ }
2795
+ const headRef = invoker(rootPath, ["symbolic-ref", "--quiet", "refs/remotes/origin/HEAD"]);
2796
+ let defaultBranch = null;
2797
+ if (headRef.exitCode === 0) {
2798
+ const raw = headRef.stdout.trim();
2799
+ const prefix = "refs/remotes/origin/";
2800
+ if (raw.startsWith(prefix)) {
2801
+ const candidate = raw.slice(prefix.length);
2802
+ if (candidate) defaultBranch = candidate;
2803
+ }
2804
+ }
2805
+ return {
2806
+ projectId,
2807
+ branch,
2808
+ rootPath,
2809
+ defaultBranch
2810
+ };
2811
+ } catch {
2812
+ return null;
2813
+ }
2814
+ }
2815
+
2816
+ // src/coding/coding-namespace.ts
2817
+ function sanitizeFragment(input) {
2818
+ if (typeof input !== "string") return "";
2819
+ const trimmed = input.trim().toLowerCase();
2820
+ let out = "";
2821
+ let prevIsDash = true;
2822
+ for (let i = 0; i < trimmed.length; i += 1) {
2823
+ const c = trimmed[i];
2824
+ const cc = trimmed.charCodeAt(i);
2825
+ const isSafe = cc >= 48 && cc <= 57 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
2826
+ if (isSafe) {
2827
+ out += c;
2828
+ prevIsDash = false;
2829
+ } else if (!prevIsDash) {
2830
+ out += "-";
2831
+ prevIsDash = true;
2832
+ }
2833
+ }
2834
+ if (out.endsWith("-")) out = out.slice(0, -1);
2835
+ return out;
2836
+ }
2837
+ var MAX_NAMESPACE_LEN = 64;
2838
+ var HASH_SUFFIX_LEN = 9;
2839
+ function capLength(value) {
2840
+ if (value.length <= MAX_NAMESPACE_LEN) return value;
2841
+ const hash = stableHash(value);
2842
+ let end = MAX_NAMESPACE_LEN - HASH_SUFFIX_LEN;
2843
+ while (end > 0 && value.charCodeAt(end - 1) === 45) end -= 1;
2844
+ return `${value.slice(0, end)}-${hash}`;
2845
+ }
2846
+ function projectNamespaceName(projectId) {
2847
+ const frag = sanitizeFragment(projectId);
2848
+ return capLength(`project-${frag || "unknown"}`);
2849
+ }
2850
+ function sanitizeBaseFragment(input) {
2851
+ if (typeof input !== "string") return "";
2852
+ const trimmed = input.trim();
2853
+ let out = "";
2854
+ let prevIsDash = true;
2855
+ for (let i = 0; i < trimmed.length; i += 1) {
2856
+ const c = trimmed[i];
2857
+ const cc = trimmed.charCodeAt(i);
2858
+ const isSafe = cc >= 48 && cc <= 57 || cc >= 65 && cc <= 90 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
2859
+ if (isSafe) {
2860
+ out += c;
2861
+ prevIsDash = false;
2862
+ } else if (!prevIsDash) {
2863
+ out += "-";
2864
+ prevIsDash = true;
2865
+ }
2866
+ }
2867
+ if (out.endsWith("-")) out = out.slice(0, -1);
2868
+ return out;
2869
+ }
2870
+ function combineNamespaces(base, overlay) {
2871
+ const baseFrag = sanitizeBaseFragment(base);
2872
+ const overlayFrag = sanitizeFragment(overlay);
2873
+ if (!baseFrag) return capLength(overlayFrag || "unknown");
2874
+ if (!overlayFrag) return capLength(baseFrag);
2875
+ return capLength(`${baseFrag}-${overlayFrag}`);
2876
+ }
2877
+ function branchNamespaceName(projectId, branch) {
2878
+ const projectFrag = sanitizeFragment(projectId);
2879
+ const trimmedBranch = branch.trim();
2880
+ const branchFrag = sanitizeFragment(trimmedBranch);
2881
+ const disambig = trimmedBranch.length > 0 && branchFrag !== trimmedBranch;
2882
+ const base = `project-${projectFrag || "unknown"}-branch-${branchFrag || "unknown"}`;
2883
+ const suffixed = disambig ? `${base}-${stableHash(trimmedBranch)}` : base;
2884
+ return capLength(suffixed);
2885
+ }
2886
+ function resolveCodingNamespaceOverlay(codingContext, config) {
2887
+ if (!codingContext) return null;
2888
+ if (!config.projectScope) return null;
2889
+ const projectId = typeof codingContext.projectId === "string" ? codingContext.projectId.trim() : "";
2890
+ if (!projectId) return null;
2891
+ const projectNs = projectNamespaceName(projectId);
2892
+ if (config.branchScope && typeof codingContext.branch === "string" && codingContext.branch.length > 0) {
2893
+ const branchNs = branchNamespaceName(projectId, codingContext.branch);
2894
+ return {
2895
+ namespace: branchNs,
2896
+ readFallbacks: [projectNs],
2897
+ scope: "branch"
2898
+ };
2899
+ }
2900
+ return {
2901
+ namespace: projectNs,
2902
+ readFallbacks: [],
2903
+ scope: "project"
2904
+ };
2905
+ }
2906
+ function describeCodingScope(codingContext, config) {
2907
+ const projectId = codingContext?.projectId ?? null;
2908
+ const branch = codingContext?.branch ?? null;
2909
+ if (!codingContext) {
2910
+ return {
2911
+ scope: "none",
2912
+ projectId: null,
2913
+ branch: null,
2914
+ effectiveNamespace: null,
2915
+ readFallbacks: [],
2916
+ disabledReason: "no-context"
2917
+ };
2918
+ }
2919
+ if (!config.projectScope) {
2920
+ return {
2921
+ scope: "none",
2922
+ projectId,
2923
+ branch,
2924
+ effectiveNamespace: null,
2925
+ readFallbacks: [],
2926
+ disabledReason: "disabled"
2927
+ };
2928
+ }
2929
+ const trimmedId = typeof projectId === "string" ? projectId.trim() : "";
2930
+ if (!trimmedId) {
2931
+ return {
2932
+ scope: "none",
2933
+ projectId,
2934
+ branch,
2935
+ effectiveNamespace: null,
2936
+ readFallbacks: [],
2937
+ disabledReason: "empty-project"
2938
+ };
2939
+ }
2940
+ const overlay = resolveCodingNamespaceOverlay(codingContext, config);
2941
+ if (!overlay) {
2942
+ return {
2943
+ scope: "none",
2944
+ projectId,
2945
+ branch,
2946
+ effectiveNamespace: null,
2947
+ readFallbacks: [],
2948
+ disabledReason: "disabled"
2949
+ };
2950
+ }
2951
+ return {
2952
+ scope: overlay.scope,
2953
+ projectId,
2954
+ branch,
2955
+ effectiveNamespace: overlay.namespace,
2956
+ readFallbacks: overlay.readFallbacks,
2957
+ disabledReason: null
2958
+ };
2959
+ }
2960
+
2402
2961
  // src/orchestrator.ts
2403
2962
  function dedupeEntitySynthesisEvidenceEntries(entries) {
2404
2963
  const dedupedEvidenceEntries = [];
@@ -2463,15 +3022,23 @@ function fingerprintEntitySynthesisEvidence(entity) {
2463
3022
  fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? "");
2464
3023
  return fingerprint.digest("hex");
2465
3024
  }
2466
- function abortRecallError(message) {
2467
- const err = new Error(message);
2468
- Object.defineProperty(err, "name", { value: "AbortError" });
2469
- return err;
3025
+ function mapRecallSourceToXrayServedBy(source) {
3026
+ switch (source) {
3027
+ case "recent_scan":
3028
+ return "recent-scan";
3029
+ case "hot_qmd":
3030
+ case "hot_embedding":
3031
+ case "cold_fallback":
3032
+ case "none":
3033
+ return "hybrid";
3034
+ }
3035
+ const _exhaustive = source;
3036
+ void _exhaustive;
3037
+ return "hybrid";
2470
3038
  }
3039
+ var abortRecallError = abortError;
2471
3040
  function throwIfRecallAborted(signal, message = "recall aborted") {
2472
- if (signal?.aborted) {
2473
- throw abortRecallError(message);
2474
- }
3041
+ throwIfAborted(signal, message);
2475
3042
  }
2476
3043
  async function raceRecallAbort(promise, signal, message = "recall aborted") {
2477
3044
  throwIfRecallAborted(signal, message);
@@ -2491,7 +3058,7 @@ async function raceRecallAbort(promise, signal, message = "recall aborted") {
2491
3058
  }
2492
3059
  var COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1e3;
2493
3060
  function defaultWorkspaceDir() {
2494
- return path5.join(os.homedir(), ".openclaw", "workspace");
3061
+ return path7.join(os.homedir(), ".openclaw", "workspace");
2495
3062
  }
2496
3063
  function sanitizeSessionKeyForFilename(sessionKey) {
2497
3064
  const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
@@ -2659,11 +3226,11 @@ function mergeGraphExpandedResults(primary, expanded) {
2659
3226
  return Array.from(mergedByPath.values());
2660
3227
  }
2661
3228
  function graphPathRelativeToStorage(storageDir, candidatePath) {
2662
- const absolutePath = path5.isAbsolute(candidatePath) ? candidatePath : path5.resolve(storageDir, candidatePath);
2663
- const rel = path5.relative(storageDir, absolutePath);
3229
+ const absolutePath = path7.isAbsolute(candidatePath) ? candidatePath : path7.resolve(storageDir, candidatePath);
3230
+ const rel = path7.relative(storageDir, absolutePath);
2664
3231
  if (!rel || rel === ".") return null;
2665
3232
  if (rel.startsWith("..")) return null;
2666
- return rel.split(path5.sep).join("/");
3233
+ return rel.split(path7.sep).join("/");
2667
3234
  }
2668
3235
  function normalizeGraphActivationScore(score) {
2669
3236
  const bounded = Number.isFinite(score) && score > 0 ? score : 0;
@@ -2805,7 +3372,7 @@ function buildMemoryPathById(allMemsForGraph, storageDir) {
2805
3372
  for (const mem of allMemsForGraph ?? []) {
2806
3373
  const id = mem.frontmatter.id;
2807
3374
  if (!id) continue;
2808
- pathById.set(id, path5.relative(storageDir, mem.path));
3375
+ pathById.set(id, path7.relative(storageDir, mem.path));
2809
3376
  }
2810
3377
  return pathById;
2811
3378
  }
@@ -2813,7 +3380,7 @@ function appendMemoryToGraphContext(options) {
2813
3380
  if (!Array.isArray(options.allMemsForGraph)) return;
2814
3381
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
2815
3382
  options.allMemsForGraph.push({
2816
- path: path5.join(options.storageDir, options.memoryRelPath),
3383
+ path: path7.join(options.storageDir, options.memoryRelPath),
2817
3384
  content: options.content,
2818
3385
  frontmatter: {
2819
3386
  id: options.memoryId,
@@ -2833,15 +3400,16 @@ function resolvePersistedMemoryRelativePath(options) {
2833
3400
  const persisted = options.pathById.get(options.memoryId);
2834
3401
  if (persisted) return persisted;
2835
3402
  if (options.category === "correction") {
2836
- return path5.join("corrections", `${options.memoryId}.md`);
3403
+ return path7.join("corrections", `${options.memoryId}.md`);
2837
3404
  }
3405
+ const subtree = options.category === "procedure" ? "procedures" : options.category === "reasoning_trace" ? "reasoning-traces" : "facts";
2838
3406
  const idParts = options.memoryId.split("-");
2839
3407
  const maybeTimestamp = Number(idParts[1]);
2840
3408
  if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
2841
3409
  const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
2842
- return path5.join("facts", day, `${options.memoryId}.md`);
3410
+ return path7.join(subtree, day, `${options.memoryId}.md`);
2843
3411
  }
2844
- return path5.join("facts", `${options.memoryId}.md`);
3412
+ return path7.join(subtree, `${options.memoryId}.md`);
2845
3413
  }
2846
3414
  var Orchestrator = class _Orchestrator {
2847
3415
  storage;
@@ -2860,12 +3428,39 @@ var Orchestrator = class _Orchestrator {
2860
3428
  localLlm;
2861
3429
  fastLlm;
2862
3430
  judgeVerdictCache;
2863
- fastGatewayLlm;
3431
+ /**
3432
+ * Per-orchestrator defer-counter map (issue #562, PR 2). Tracks how many
3433
+ * times the judge has returned `"defer"` for a given candidate content
3434
+ * hash so the defer cap can be enforced.
3435
+ */
3436
+ judgeDeferCounts;
3437
+ /**
3438
+ * Side-channel: number of facts deferred in the most recent
3439
+ * `persistExtraction` call (issue #562, PR 2). The caller reads this after
3440
+ * `persistExtraction` returns to decide whether to retain buffer turns for
3441
+ * the next extraction pass. Not part of the return signature because many
3442
+ * callers already destructure `persistedIds` by position.
3443
+ */
3444
+ lastPersistExtractionDeferredCount = 0;
3445
+ _fastGatewayLlm;
3446
+ get fastGatewayLlm() {
3447
+ return this._fastGatewayLlm;
3448
+ }
2864
3449
  modelRegistry;
2865
3450
  relevance;
2866
3451
  negatives;
2867
3452
  lastRecall;
2868
3453
  tierMigrationStatus;
3454
+ /**
3455
+ * In-memory X-ray snapshot from the most recent `recall()` call that
3456
+ * was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is
3457
+ * per-process; later slices add CLI/HTTP/MCP surfaces that consume
3458
+ * this via the shared renderer. `null` until the first capture, and
3459
+ * NEVER overwritten by a recall that did not request capture —
3460
+ * requests without the flag leave prior captures intact so the
3461
+ * capturing caller can still read their snapshot back.
3462
+ */
3463
+ lastXraySnapshot = null;
2869
3464
  embeddingFallback;
2870
3465
  conversationIndexDir;
2871
3466
  extraction;
@@ -2881,6 +3476,16 @@ var Orchestrator = class _Orchestrator {
2881
3476
  /** Lossless Context Management engine — proactive session archive + DAG summarization. */
2882
3477
  lcmEngine = null;
2883
3478
  rerankCache = new RerankCache();
3479
+ /**
3480
+ * Short-TTL cache for Memory Worth counter lookups so interactive recall
3481
+ * doesn't trigger a full `readAllMemories` scan per query. Keyed by
3482
+ * namespace; the filter unions across namespaces at query time. The TTL
3483
+ * is intentionally short (seconds, not minutes) because counters are
3484
+ * mutated by `recordMemoryOutcome` asynchronously and we'd rather serve
3485
+ * a 30-second-stale worth score than a stable-but-wrong one.
3486
+ */
3487
+ memoryWorthCounterCache = /* @__PURE__ */ new Map();
3488
+ static MEMORY_WORTH_CACHE_TTL_MS = 3e4;
2884
3489
  /**
2885
3490
  * Per-session workspace overrides keyed by sessionKey.
2886
3491
  * Set by the before_agent_start hook so recall() uses the correct
@@ -2888,6 +3493,14 @@ var Orchestrator = class _Orchestrator {
2888
3493
  * Using a Map prevents concurrent sessions from overwriting each other.
2889
3494
  */
2890
3495
  _recallWorkspaceOverrides = /* @__PURE__ */ new Map();
3496
+ /**
3497
+ * Per-session coding-agent context (issue #569). Populated by connectors at
3498
+ * session-start (PRs 5/6/7) via `setCodingContextForSession`. Used by both
3499
+ * the recall path and the write path so that memory routing respects the
3500
+ * project/branch scope a session is operating in (rule 42 — read + write
3501
+ * through the same namespace layer).
3502
+ */
3503
+ _codingContextBySession = /* @__PURE__ */ new Map();
2891
3504
  routingRulesStore = null;
2892
3505
  contentHashIndex = null;
2893
3506
  artifactSourceStatusCache = /* @__PURE__ */ new WeakMap();
@@ -2921,6 +3534,10 @@ var Orchestrator = class _Orchestrator {
2921
3534
  runtimePolicyValues = null;
2922
3535
  utilityRuntimeValues = null;
2923
3536
  evalShadowWriteChain = Promise.resolve();
3537
+ // Pending background observation-mode direct-answer annotations (#518).
3538
+ // Tracks fire-and-forget `annotateDirectAnswerTier` calls so callers (tests,
3539
+ // waitForDirectAnswerObservationIdle) can await settlement.
3540
+ directAnswerObservationChain = Promise.resolve();
2924
3541
  // Initialization gate: recall() awaits this before proceeding
2925
3542
  initPromise = null;
2926
3543
  resolveInit = null;
@@ -2959,6 +3576,9 @@ var Orchestrator = class _Orchestrator {
2959
3576
  this.deferredInitAbort = null;
2960
3577
  }
2961
3578
  }
3579
+ async disposeSearchBackendIfNeeded() {
3580
+ await this.qmd.dispose?.();
3581
+ }
2962
3582
  /** Set per-session workspace for the next recall() call (compaction reset). @internal */
2963
3583
  setRecallWorkspaceOverride(sessionKey, dir) {
2964
3584
  this._recallWorkspaceOverrides.set(sessionKey, dir);
@@ -2971,10 +3591,96 @@ var Orchestrator = class _Orchestrator {
2971
3591
  return resolvePrincipal(sessionKey, this.config);
2972
3592
  }
2973
3593
  resolveSelfNamespace(sessionKey) {
2974
- return defaultNamespaceForPrincipal(
3594
+ const base = defaultNamespaceForPrincipal(
2975
3595
  this.resolvePrincipal(sessionKey),
2976
3596
  this.config
2977
3597
  );
3598
+ return this.applyCodingNamespaceOverlay(sessionKey, base);
3599
+ }
3600
+ /**
3601
+ * Attach a coding-agent context to a session (issue #569). Called by the
3602
+ * Claude Code / Codex / Cursor connectors at session start after
3603
+ * `resolveGitContext(cwd)`. The context is consulted by the recall path
3604
+ * and the write path so that memories route to a project- (and optionally
3605
+ * branch-) scoped namespace.
3606
+ *
3607
+ * Pass `null` to clear.
3608
+ */
3609
+ setCodingContextForSession(sessionKey, codingContext) {
3610
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
3611
+ if (!this._codingContextBySession) {
3612
+ this._codingContextBySession = /* @__PURE__ */ new Map();
3613
+ }
3614
+ if (codingContext === null) {
3615
+ this._codingContextBySession.delete(sessionKey);
3616
+ return;
3617
+ }
3618
+ this._codingContextBySession.set(sessionKey, codingContext);
3619
+ }
3620
+ /**
3621
+ * Read-only accessor for the coding context attached to a session. Returns
3622
+ * `null` when none is set. Used by `remnic doctor` and by tests.
3623
+ *
3624
+ * Defensive `_codingContextBySession` lookup — legacy orchestrator-flush
3625
+ * tests use `Object.create(Orchestrator.prototype)` which does not run
3626
+ * class-field initializers, so the Map may be undefined on stubs.
3627
+ */
3628
+ getCodingContextForSession(sessionKey) {
3629
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
3630
+ return this._codingContextBySession?.get(sessionKey) ?? null;
3631
+ }
3632
+ /**
3633
+ * Shared helper used by both the recall path and the write path (rule 42).
3634
+ *
3635
+ * Given a base namespace computed from the principal, returns the overlaid
3636
+ * coding namespace when the session has a coding context AND
3637
+ * `codingMode.projectScope` is true AND `namespacesEnabled` is true.
3638
+ * Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.
3639
+ *
3640
+ * Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with
3641
+ * the principal-derived `baseNamespace` rather than replacing it, so two
3642
+ * principals working in the same repository do not share memories through
3643
+ * a common `project-*` namespace.
3644
+ *
3645
+ * Namespaces-disabled gate: when `namespacesEnabled` is false, the
3646
+ * storage router maps every namespace to the same `memoryDir`. Returning
3647
+ * `project-*` in that mode would create apparent route separation with
3648
+ * no actual storage isolation — a false-isolation trap. In that mode we
3649
+ * return `baseNamespace` unchanged so coding mode degrades to the existing
3650
+ * unscoped behavior.
3651
+ *
3652
+ * @internal
3653
+ */
3654
+ applyCodingNamespaceOverlay(sessionKey, baseNamespace) {
3655
+ if (!this.config.namespacesEnabled) return baseNamespace;
3656
+ const codingContext = this.getCodingContextForSession(sessionKey);
3657
+ const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
3658
+ if (!overlay) return baseNamespace;
3659
+ return combineNamespaces(baseNamespace, overlay.namespace);
3660
+ }
3661
+ /**
3662
+ * Read-side overlay: returns the list of namespaces a session should read
3663
+ * from, including any read fallbacks (branch → project asymmetry lands in
3664
+ * PR 3; PR 2 returns an empty fallbacks list).
3665
+ *
3666
+ * Returns `null` when:
3667
+ * - `namespacesEnabled` is false (overlay would create false isolation)
3668
+ * - no context attached to the session
3669
+ * - `codingMode.projectScope` is false (CLAUDE.md #30 escape hatch)
3670
+ *
3671
+ * The returned `namespace` / `readFallbacks` are RAW overlay fragments
3672
+ * (e.g. `project-origin-ab12`). Callers MUST combine them with the
3673
+ * principal-derived base through `combineNamespaces()` before passing to
3674
+ * storage, so principal isolation is preserved (rule 42).
3675
+ *
3676
+ * @internal
3677
+ */
3678
+ applyCodingRecallOverlay(sessionKey) {
3679
+ if (!this.config.namespacesEnabled) return null;
3680
+ const codingContext = this.getCodingContextForSession(sessionKey);
3681
+ const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
3682
+ if (!overlay) return null;
3683
+ return { namespace: overlay.namespace, readFallbacks: overlay.readFallbacks };
2978
3684
  }
2979
3685
  async getStorageForNamespace(namespace) {
2980
3686
  const ns = typeof namespace === "string" && namespace.trim().length > 0 ? namespace.trim() : this.config.defaultNamespace;
@@ -3059,7 +3765,7 @@ var Orchestrator = class _Orchestrator {
3059
3765
  this.config = config;
3060
3766
  this.profiler = new ProfilingCollector({
3061
3767
  enabled: config.profilingEnabled,
3062
- storageDir: config.profilingStorageDir || path5.join(config.memoryDir, "profiling"),
3768
+ storageDir: config.profilingStorageDir || path7.join(config.memoryDir, "profiling"),
3063
3769
  maxTraces: config.profilingMaxTraces
3064
3770
  });
3065
3771
  this.storageRouter = new NamespaceStorageRouter(config);
@@ -3086,7 +3792,7 @@ var Orchestrator = class _Orchestrator {
3086
3792
  this.compounding = config.compoundingEnabled ? new CompoundingEngine(config) : void 0;
3087
3793
  this.buffer = new SmartBuffer(config, this.storage);
3088
3794
  this.transcript = new TranscriptManager(config);
3089
- this.conversationIndexDir = path5.join(
3795
+ this.conversationIndexDir = path7.join(
3090
3796
  config.memoryDir,
3091
3797
  "conversation-index",
3092
3798
  "chunks"
@@ -3110,7 +3816,9 @@ var Orchestrator = class _Orchestrator {
3110
3816
  this.transcript
3111
3817
  );
3112
3818
  this.judgeVerdictCache = createVerdictCache();
3819
+ this.judgeDeferCounts = createDeferCountMap();
3113
3820
  this.localLlm = new LocalLlmClient(config, this.modelRegistry);
3821
+ this.localLlm.disableThinking = config.localLlmDisableThinking;
3114
3822
  this.fastLlm = config.localLlmFastEnabled ? (() => {
3115
3823
  const client = new LocalLlmClient(
3116
3824
  {
@@ -3124,7 +3832,7 @@ var Orchestrator = class _Orchestrator {
3124
3832
  client.disableThinking = true;
3125
3833
  return client;
3126
3834
  })() : this.localLlm;
3127
- this.fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig) : null;
3835
+ this._fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig) : null;
3128
3836
  if (config.modelSource === "gateway") {
3129
3837
  log.debug(
3130
3838
  `orchestrator: gateway model source active` + (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : "") + (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : "")
@@ -3138,7 +3846,7 @@ var Orchestrator = class _Orchestrator {
3138
3846
  this.modelRegistry
3139
3847
  );
3140
3848
  this.threading = new ThreadingManager(
3141
- path5.join(config.memoryDir, "threads"),
3849
+ path7.join(config.memoryDir, "threads"),
3142
3850
  config.threadingGapMinutes
3143
3851
  );
3144
3852
  this.tmtBuilder = new TmtBuilder(config.memoryDir, {
@@ -3324,9 +4032,9 @@ var Orchestrator = class _Orchestrator {
3324
4032
  * routes through the gateway chain. Otherwise uses the local fast LLM.
3325
4033
  */
3326
4034
  async fastChatCompletion(messages, options) {
3327
- if (this.fastGatewayLlm && this.config.modelSource === "gateway") {
4035
+ if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
3328
4036
  const agentId = this.config.fastGatewayAgentId || this.config.gatewayAgentId || void 0;
3329
- const result2 = await this.fastGatewayLlm.chatCompletion(
4037
+ const result2 = await this._fastGatewayLlm.chatCompletion(
3330
4038
  messages,
3331
4039
  { temperature: options.temperature, maxTokens: options.maxTokens, timeoutMs: options.timeoutMs, agentId }
3332
4040
  );
@@ -3341,7 +4049,7 @@ var Orchestrator = class _Orchestrator {
3341
4049
  * Otherwise returns the local fast LLM directly.
3342
4050
  */
3343
4051
  get fastLlmForRerank() {
3344
- if (this.fastGatewayLlm && this.config.modelSource === "gateway") {
4052
+ if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
3345
4053
  return {
3346
4054
  chatCompletion: (messages, options) => this.fastChatCompletion(messages, options ?? {})
3347
4055
  };
@@ -3383,7 +4091,7 @@ var Orchestrator = class _Orchestrator {
3383
4091
  promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled
3384
4092
  });
3385
4093
  if (this.config.factDeduplicationEnabled) {
3386
- const stateDir = path5.join(this.config.memoryDir, "state");
4094
+ const stateDir = path7.join(this.config.memoryDir, "state");
3387
4095
  this.contentHashIndex = new ContentHashIndex(stateDir);
3388
4096
  await this.contentHashIndex.load();
3389
4097
  log.info(
@@ -3412,7 +4120,7 @@ var Orchestrator = class _Orchestrator {
3412
4120
  const files = await readdir3(wsDir).catch(() => []);
3413
4121
  for (const f of files) {
3414
4122
  if (!f.startsWith(".compaction-reset-signal-")) continue;
3415
- const fp = path5.join(wsDir, f);
4123
+ const fp = path7.join(wsDir, f);
3416
4124
  const s = await stat3(fp).catch(() => null);
3417
4125
  if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
3418
4126
  await unlink2(fp).catch(() => {
@@ -3441,6 +4149,7 @@ var Orchestrator = class _Orchestrator {
3441
4149
  (entry) => entry.namespace === this.config.defaultNamespace
3442
4150
  )?.state ?? "unknown";
3443
4151
  if (defaultState === "missing") {
4152
+ await this.disposeSearchBackendIfNeeded();
3444
4153
  this.qmd = new NoopSearchBackend();
3445
4154
  log.warn(
3446
4155
  "Search collection missing for Remnic memory store; disabling search retrieval for this runtime (fallback retrieval remains enabled)"
@@ -3501,10 +4210,11 @@ var Orchestrator = class _Orchestrator {
3501
4210
  log.info("QMD startup sync: updating index to match current disk state");
3502
4211
  if (this.config.namespacesEnabled) {
3503
4212
  await this.namespaceSearchRouter.updateNamespaces(
3504
- this.configuredNamespaces()
4213
+ this.configuredNamespaces(),
4214
+ { signal }
3505
4215
  );
3506
4216
  } else {
3507
- await this.qmd.update();
4217
+ await this.qmd.update({ signal });
3508
4218
  }
3509
4219
  log.info("QMD startup sync: complete");
3510
4220
  this.deferredSyncSucceeded = true;
@@ -3521,7 +4231,7 @@ var Orchestrator = class _Orchestrator {
3521
4231
  const warmupNs = this.config.defaultNamespace;
3522
4232
  log.info("QMD warmup: pre-loading models with a test search");
3523
4233
  warmupPromises.push(
3524
- this.qmd.search("warmup", warmupNs, 1).then(() => {
4234
+ this.qmd.search("warmup", warmupNs, 1, void 0, { signal }).then(() => {
3525
4235
  log.info("QMD warmup: complete");
3526
4236
  }).catch((err) => {
3527
4237
  log.debug(`QMD warmup search failed (non-fatal): ${err}`);
@@ -3611,6 +4321,13 @@ var Orchestrator = class _Orchestrator {
3611
4321
  log.debug(`procedural mining cron auto-register failed (non-fatal): ${err}`);
3612
4322
  }
3613
4323
  }
4324
+ if (this.config.contradictionScan?.enabled) {
4325
+ try {
4326
+ await this.autoRegisterContradictionScanCron();
4327
+ } catch (err) {
4328
+ log.debug(`contradiction scan cron auto-register failed (non-fatal): ${err}`);
4329
+ }
4330
+ }
3614
4331
  log.info("orchestrator initialized (full \u2014 deferred steps complete)");
3615
4332
  }
3616
4333
  /**
@@ -3654,6 +4371,7 @@ var Orchestrator = class _Orchestrator {
3654
4371
  if ("available" in this.qmd) {
3655
4372
  this.qmd.available = false;
3656
4373
  }
4374
+ await this.disposeSearchBackendIfNeeded();
3657
4375
  this.qmd = new NoopSearchBackend();
3658
4376
  log.warn("startupSearchSync: search collection missing; disabling search (fallback retrieval remains enabled)");
3659
4377
  return false;
@@ -3668,9 +4386,12 @@ var Orchestrator = class _Orchestrator {
3668
4386
  log.info("startupSearchSync: updating index to match current disk state");
3669
4387
  let namespacesUpdated = 0;
3670
4388
  if (this.config.namespacesEnabled) {
3671
- namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(namespaces);
4389
+ namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(
4390
+ namespaces,
4391
+ { signal }
4392
+ );
3672
4393
  } else {
3673
- await this.qmd.update(signal);
4394
+ await this.qmd.update({ signal });
3674
4395
  }
3675
4396
  if (signal?.aborted) {
3676
4397
  log.debug("startupSearchSync: aborted after update");
@@ -3714,7 +4435,7 @@ var Orchestrator = class _Orchestrator {
3714
4435
  */
3715
4436
  async autoRegisterDaySummaryCron() {
3716
4437
  const home = resolveHomeDir();
3717
- const jobsPath = path5.join(home, ".openclaw", "cron", "jobs.json");
4438
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
3718
4439
  try {
3719
4440
  if (!existsSync2(jobsPath)) {
3720
4441
  log.debug(
@@ -3738,7 +4459,7 @@ var Orchestrator = class _Orchestrator {
3738
4459
  }
3739
4460
  async autoRegisterNightlyGovernanceCron() {
3740
4461
  const home = process.env.HOME || os.homedir();
3741
- const jobsPath = path5.join(home, ".openclaw", "cron", "jobs.json");
4462
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
3742
4463
  try {
3743
4464
  if (!existsSync2(jobsPath)) {
3744
4465
  log.debug("nightly governance cron: jobs.json not found, skipping auto-register");
@@ -3760,7 +4481,7 @@ var Orchestrator = class _Orchestrator {
3760
4481
  }
3761
4482
  async autoRegisterProceduralMiningCron() {
3762
4483
  const home = resolveHomeDir();
3763
- const jobsPath = path5.join(home, ".openclaw", "cron", "jobs.json");
4484
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
3764
4485
  try {
3765
4486
  if (!existsSync2(jobsPath)) {
3766
4487
  log.debug("procedural mining cron: jobs.json not found, skipping auto-register");
@@ -3778,6 +4499,26 @@ var Orchestrator = class _Orchestrator {
3778
4499
  log.debug(`procedural mining cron auto-register error: ${err}`);
3779
4500
  }
3780
4501
  }
4502
+ async autoRegisterContradictionScanCron() {
4503
+ const home = resolveHomeDir();
4504
+ const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
4505
+ try {
4506
+ if (!existsSync2(jobsPath)) {
4507
+ log.debug("contradiction scan cron: jobs.json not found, skipping auto-register");
4508
+ return;
4509
+ }
4510
+ const created = await ensureContradictionScanCron(jobsPath, {
4511
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
4512
+ });
4513
+ if (created.created) {
4514
+ log.info(`contradiction scan cron auto-registered (${created.jobId})`);
4515
+ } else {
4516
+ log.debug("contradiction scan cron already exists, skipping auto-register");
4517
+ }
4518
+ } catch (err) {
4519
+ log.debug(`contradiction scan cron auto-register error: ${err}`);
4520
+ }
4521
+ }
3781
4522
  async applyBehaviorRuntimePolicy(state) {
3782
4523
  const result = await this.policyRuntime.applyFromBehaviorState(state);
3783
4524
  this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();
@@ -3796,15 +4537,15 @@ var Orchestrator = class _Orchestrator {
3796
4537
  this.lastFileHygieneRunAtMs = now;
3797
4538
  if (hygiene.rotateEnabled) {
3798
4539
  for (const rel of hygiene.rotatePaths) {
3799
- const abs = path5.isAbsolute(rel) ? rel : path5.join(this.config.workspaceDir, rel);
4540
+ const abs = path7.isAbsolute(rel) ? rel : path7.join(this.config.workspaceDir, rel);
3800
4541
  try {
3801
- const raw = await readFile3(abs, "utf-8");
4542
+ const raw = await readFile4(abs, "utf-8");
3802
4543
  if (raw.length > hygiene.rotateMaxBytes) {
3803
- const archiveDir = path5.join(
4544
+ const archiveDir = path7.join(
3804
4545
  this.config.workspaceDir,
3805
4546
  hygiene.archiveDir
3806
4547
  );
3807
- const base = path5.basename(abs);
4548
+ const base = path7.basename(abs);
3808
4549
  const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
3809
4550
  const { newContent } = await rotateMarkdownFileToArchive({
3810
4551
  filePath: abs,
@@ -3812,7 +4553,7 @@ var Orchestrator = class _Orchestrator {
3812
4553
  archivePrefix: prefix,
3813
4554
  keepTailChars: hygiene.rotateKeepTailChars
3814
4555
  });
3815
- await writeFile3(abs, newContent, "utf-8");
4556
+ await writeFile4(abs, newContent, "utf-8");
3816
4557
  }
3817
4558
  } catch {
3818
4559
  }
@@ -3829,8 +4570,8 @@ var Orchestrator = class _Orchestrator {
3829
4570
  log.warn(w.message);
3830
4571
  }
3831
4572
  if (hygiene.warningsLogEnabled && warnings.length > 0) {
3832
- const fp = path5.join(this.config.memoryDir, hygiene.warningsLogPath);
3833
- await mkdir4(path5.dirname(fp), { recursive: true });
4573
+ const fp = path7.join(this.config.memoryDir, hygiene.warningsLogPath);
4574
+ await mkdir5(path7.dirname(fp), { recursive: true });
3834
4575
  const stamp = (/* @__PURE__ */ new Date()).toISOString();
3835
4576
  const block = `
3836
4577
 
@@ -3839,11 +4580,11 @@ var Orchestrator = class _Orchestrator {
3839
4580
  ` + warnings.map((w) => `- ${w.message}`).join("\n") + "\n";
3840
4581
  let existing = "";
3841
4582
  try {
3842
- existing = await readFile3(fp, "utf-8");
4583
+ existing = await readFile4(fp, "utf-8");
3843
4584
  } catch {
3844
4585
  existing = "# Engram File Hygiene Warnings\n";
3845
4586
  }
3846
- await writeFile3(fp, existing + block, "utf-8");
4587
+ await writeFile4(fp, existing + block, "utf-8");
3847
4588
  }
3848
4589
  }
3849
4590
  }
@@ -3927,14 +4668,15 @@ var Orchestrator = class _Orchestrator {
3927
4668
  }
3928
4669
  for (const cluster of clusters) {
3929
4670
  try {
3930
- let prompt = buildConsolidationPrompt(cluster);
4671
+ const operatorAwareEnabled = this.config.operatorAwareConsolidationEnabled === true;
4672
+ let prompt = operatorAwareEnabled ? buildOperatorAwareConsolidationPrompt(cluster) : buildConsolidationPrompt(cluster);
3931
4673
  if (extensionsBlock.length > 0) {
3932
4674
  prompt += "\n\n" + extensionsBlock;
3933
4675
  }
3934
4676
  const messages = [
3935
4677
  {
3936
4678
  role: "system",
3937
- content: "You are a memory consolidation system. Output only the consolidated memory text."
4679
+ 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."
3938
4680
  },
3939
4681
  { role: "user", content: prompt }
3940
4682
  ];
@@ -3960,13 +4702,31 @@ var Orchestrator = class _Orchestrator {
3960
4702
  result.errors++;
3961
4703
  continue;
3962
4704
  }
3963
- const canonicalContent = parseConsolidationResponse(response.content);
4705
+ let canonicalContent;
4706
+ let operator;
4707
+ if (operatorAwareEnabled) {
4708
+ const parsed = parseOperatorAwareConsolidationResponse(
4709
+ response.content,
4710
+ cluster
4711
+ );
4712
+ canonicalContent = parsed.output;
4713
+ operator = parsed.operator;
4714
+ } else {
4715
+ canonicalContent = parseConsolidationResponse(response.content);
4716
+ operator = chooseConsolidationOperator(cluster);
4717
+ }
3964
4718
  cluster.canonicalContent = canonicalContent;
3965
4719
  const sorted = [...cluster.memories].sort(
3966
4720
  (a, b) => new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime()
3967
4721
  );
3968
4722
  const newest = sorted[0];
3969
4723
  const lineageIds = cluster.memories.map((m) => m.frontmatter.id);
4724
+ const derivedFromEntries = [];
4725
+ for (const m of cluster.memories) {
4726
+ if (!m.path) continue;
4727
+ const entry = await this.storage.snapshotForProvenance(m.path);
4728
+ if (entry) derivedFromEntries.push(entry);
4729
+ }
3970
4730
  const canonicalId = await this.storage.writeMemory(
3971
4731
  newest.frontmatter.category,
3972
4732
  canonicalContent,
@@ -3979,7 +4739,9 @@ var Orchestrator = class _Orchestrator {
3979
4739
  )
3980
4740
  ],
3981
4741
  source: "semantic-consolidation",
3982
- lineage: lineageIds
4742
+ lineage: lineageIds,
4743
+ derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : void 0,
4744
+ derivedVia: operator
3983
4745
  }
3984
4746
  );
3985
4747
  result.memoriesConsolidated++;
@@ -4221,18 +4983,18 @@ ${evidenceText}`
4221
4983
  const datesToScan = [yesterday, utcToday].filter(
4222
4984
  (v, i, a) => a.indexOf(v) === i
4223
4985
  );
4224
- const factsBaseDir = path5.join(storage.dir, "facts");
4986
+ const factsBaseDir = path7.join(storage.dir, "facts");
4225
4987
  const MAX_CHARS = 1e5;
4226
4988
  const facts = [];
4227
4989
  for (const date of datesToScan) {
4228
- const factsDir = path5.join(factsBaseDir, date);
4990
+ const factsDir = path7.join(factsBaseDir, date);
4229
4991
  try {
4230
4992
  const entries = await readdir3(factsDir, { withFileTypes: true });
4231
4993
  for (const entry of entries) {
4232
4994
  if (!entry.name.endsWith(".md")) continue;
4233
- const fullPath = path5.join(factsDir, entry.name);
4995
+ const fullPath = path7.join(factsDir, entry.name);
4234
4996
  try {
4235
- const raw = await readFile3(fullPath, "utf-8");
4997
+ const raw = await readFile4(fullPath, "utf-8");
4236
4998
  const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
4237
4999
  if (!fmMatch) continue;
4238
5000
  const fmBlock = fmMatch[1];
@@ -4246,7 +5008,7 @@ ${evidenceText}`
4246
5008
  facts.push({
4247
5009
  path: fullPath,
4248
5010
  frontmatter: {
4249
- id: fm.id || path5.basename(entry.name, ".md"),
5011
+ id: fm.id || path7.basename(entry.name, ".md"),
4250
5012
  category: fm.category || "fact",
4251
5013
  created: fm.created || "unknown",
4252
5014
  updated: fm.updated || fm.created || "unknown",
@@ -4267,15 +5029,15 @@ ${evidenceText}`
4267
5029
  (a, b) => a.frontmatter.created < b.frontmatter.created ? -1 : 1
4268
5030
  );
4269
5031
  const hourlySummaries = [];
4270
- const hourlyBaseDir = path5.join(storage.dir, "summaries", "hourly");
5032
+ const hourlyBaseDir = path7.join(storage.dir, "summaries", "hourly");
4271
5033
  try {
4272
5034
  const sessionKeys = await readdir3(hourlyBaseDir, { withFileTypes: true });
4273
5035
  for (const sk of sessionKeys) {
4274
5036
  if (!sk.isDirectory()) continue;
4275
5037
  for (const date of datesToScan) {
4276
- const summaryFile = path5.join(hourlyBaseDir, sk.name, `${date}.md`);
5038
+ const summaryFile = path7.join(hourlyBaseDir, sk.name, `${date}.md`);
4277
5039
  try {
4278
- const raw = await readFile3(summaryFile, "utf-8");
5040
+ const raw = await readFile4(summaryFile, "utf-8");
4279
5041
  if (raw.trim().length > 0) {
4280
5042
  hourlySummaries.push(raw.trim());
4281
5043
  }
@@ -4371,13 +5133,13 @@ ${evidenceText}`
4371
5133
  }
4372
5134
  async getLastGraphRecallSnapshot(namespace) {
4373
5135
  const storage = await this.getStorage(namespace);
4374
- const snapshotPath = path5.join(
5136
+ const snapshotPath = path7.join(
4375
5137
  storage.dir,
4376
5138
  "state",
4377
5139
  "last_graph_recall.json"
4378
5140
  );
4379
5141
  try {
4380
- const raw = await readFile3(snapshotPath, "utf-8");
5142
+ const raw = await readFile4(snapshotPath, "utf-8");
4381
5143
  const parsed = JSON.parse(raw);
4382
5144
  if (!parsed || typeof parsed !== "object") return null;
4383
5145
  return {
@@ -4410,9 +5172,9 @@ ${evidenceText}`
4410
5172
  }
4411
5173
  async getLastIntentSnapshot(namespace) {
4412
5174
  const storage = await this.getStorage(namespace);
4413
- const snapshotPath = path5.join(storage.dir, "state", "last_intent.json");
5175
+ const snapshotPath = path7.join(storage.dir, "state", "last_intent.json");
4414
5176
  try {
4415
- const raw = await readFile3(snapshotPath, "utf-8");
5177
+ const raw = await readFile4(snapshotPath, "utf-8");
4416
5178
  const parsed = JSON.parse(raw);
4417
5179
  if (!parsed || typeof parsed !== "object") return null;
4418
5180
  const graphDecision = parsed.graphDecision && typeof parsed.graphDecision === "object" ? parsed.graphDecision : void 0;
@@ -4443,13 +5205,13 @@ ${evidenceText}`
4443
5205
  }
4444
5206
  async getLastQmdRecallSnapshot(namespace) {
4445
5207
  const storage = await this.getStorage(namespace);
4446
- const snapshotPath = path5.join(
5208
+ const snapshotPath = path7.join(
4447
5209
  storage.dir,
4448
5210
  "state",
4449
5211
  "last_qmd_recall.json"
4450
5212
  );
4451
5213
  try {
4452
- const raw = await readFile3(snapshotPath, "utf-8");
5214
+ const raw = await readFile4(snapshotPath, "utf-8");
4453
5215
  const parsed = JSON.parse(raw);
4454
5216
  if (!parsed || typeof parsed !== "object") return null;
4455
5217
  return {
@@ -4595,7 +5357,7 @@ ${r.snippet.trim()}
4595
5357
  const entries = await readdir3(dir, { withFileTypes: true });
4596
5358
  let total = 0;
4597
5359
  for (const entry of entries) {
4598
- const fullPath = path5.join(dir, entry.name);
5360
+ const fullPath = path7.join(dir, entry.name);
4599
5361
  if (entry.isDirectory()) {
4600
5362
  total += await this.countConversationChunkDocs(fullPath);
4601
5363
  continue;
@@ -4866,11 +5628,24 @@ ${r.snippet.trim()}
4866
5628
  reject(new Error("recall timeout"));
4867
5629
  }, RECALL_TIMEOUT_MS);
4868
5630
  });
5631
+ let recallResult;
4869
5632
  try {
4870
- return await Promise.race([recallPromise, timeoutPromise]);
5633
+ recallResult = await Promise.race([recallPromise, timeoutPromise]);
4871
5634
  } finally {
4872
5635
  if (timeoutHandle) clearTimeout(timeoutHandle);
4873
5636
  }
5637
+ if (this.config.recallDirectAnswerEnabled && sessionKey) {
5638
+ try {
5639
+ this.enqueueDirectAnswerObservation(
5640
+ prompt,
5641
+ sessionKey,
5642
+ options.namespace?.trim() || void 0
5643
+ );
5644
+ } catch (err) {
5645
+ log.debug(`direct-answer observation setup failed: ${err}`);
5646
+ }
5647
+ }
5648
+ return recallResult;
4874
5649
  } catch (err) {
4875
5650
  this.logRecallFailure(err);
4876
5651
  this.profiler.endTrace();
@@ -4879,6 +5654,183 @@ ${r.snippet.trim()}
4879
5654
  options.abortSignal?.removeEventListener("abort", onAbort);
4880
5655
  }
4881
5656
  }
5657
+ /**
5658
+ * Return the most recent X-ray snapshot captured during a
5659
+ * `recall()` call that passed `xrayCapture: true` (issue #570 PR 1).
5660
+ * Returns `null` when no such capture has occurred on this
5661
+ * orchestrator instance. Returned snapshot is a deep copy so
5662
+ * caller mutation cannot tear the stored value.
5663
+ */
5664
+ getLastXraySnapshot() {
5665
+ if (!this.lastXraySnapshot) return null;
5666
+ return structuredClone(this.lastXraySnapshot);
5667
+ }
5668
+ /** Clear the captured X-ray snapshot. Exposed for tests / explicit reset. */
5669
+ clearLastXraySnapshot() {
5670
+ this.lastXraySnapshot = null;
5671
+ }
5672
+ /**
5673
+ * Await the in-flight observation-mode direct-answer annotation chain.
5674
+ * Resolves to true when settled, false on timeout.
5675
+ */
5676
+ async waitForDirectAnswerObservationIdle(timeoutMs = 6e4) {
5677
+ let timeoutHandle = null;
5678
+ try {
5679
+ const timeoutPromise = new Promise((resolve) => {
5680
+ timeoutHandle = setTimeout(() => resolve("timeout"), timeoutMs);
5681
+ });
5682
+ const result = await Promise.race([
5683
+ this.directAnswerObservationChain.then(() => "ok"),
5684
+ timeoutPromise
5685
+ ]);
5686
+ if (result === "timeout") {
5687
+ log.warn(
5688
+ `waitForDirectAnswerObservationIdle timed out after ${timeoutMs}ms`
5689
+ );
5690
+ return false;
5691
+ }
5692
+ return true;
5693
+ } finally {
5694
+ if (timeoutHandle) clearTimeout(timeoutHandle);
5695
+ }
5696
+ }
5697
+ enqueueDirectAnswerObservation(prompt, sessionKey, namespaceOverride) {
5698
+ const expectedSnapshot = this.lastRecall.get(sessionKey);
5699
+ if (expectedSnapshot === null) return;
5700
+ if (expectedSnapshot.plannerMode === "no_recall") return;
5701
+ const principal = resolvePrincipal(sessionKey, this.config);
5702
+ const observationCodingOverlay = namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config) ? null : this.applyCodingRecallOverlay(sessionKey);
5703
+ const observationPrincipalSelf = defaultNamespaceForPrincipal(principal, this.config);
5704
+ const observationCodingSelf = observationCodingOverlay ? combineNamespaces(observationPrincipalSelf, observationCodingOverlay.namespace) : null;
5705
+ let observationNamespaces;
5706
+ if (namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)) {
5707
+ observationNamespaces = [namespaceOverride];
5708
+ } else if (observationCodingOverlay && observationCodingSelf) {
5709
+ const base = recallNamespacesForPrincipal(principal, this.config);
5710
+ const mapped = base.map(
5711
+ (ns) => ns === observationPrincipalSelf ? observationCodingSelf : ns
5712
+ );
5713
+ const fallbackNs = observationCodingOverlay.readFallbacks.map(
5714
+ (fallback) => combineNamespaces(observationPrincipalSelf, fallback)
5715
+ );
5716
+ observationNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
5717
+ } else {
5718
+ observationNamespaces = recallNamespacesForPrincipal(principal, this.config);
5719
+ }
5720
+ const observationQueryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {
5721
+ cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,
5722
+ cronRecallNormalizedQueryMaxChars: this.config.cronRecallNormalizedQueryMaxChars,
5723
+ cronRecallInstructionHeavyTokenCap: this.effectiveCronRecallInstructionHeavyTokenCap(),
5724
+ cronConversationRecallMode: this.config.cronConversationRecallMode
5725
+ });
5726
+ const observationQuery = observationQueryPolicy.retrievalQuery || prompt;
5727
+ const expectedIdentity = {
5728
+ writeNonce: expectedSnapshot.writeNonce,
5729
+ traceId: expectedSnapshot.traceId,
5730
+ recordedAt: expectedSnapshot.recordedAt
5731
+ };
5732
+ const previous = this.directAnswerObservationChain;
5733
+ this.directAnswerObservationChain = previous.catch(() => void 0).then(async () => {
5734
+ try {
5735
+ await this.annotateDirectAnswerTier(
5736
+ observationQuery,
5737
+ sessionKey,
5738
+ observationNamespaces,
5739
+ expectedIdentity,
5740
+ void 0
5741
+ );
5742
+ } catch (err) {
5743
+ log.debug(`direct-answer observation chain error: ${err}`);
5744
+ }
5745
+ });
5746
+ }
5747
+ async annotateDirectAnswerTier(prompt, sessionKey, namespaces, expectedIdentity, _parentAbortSignal) {
5748
+ const tierStart = Date.now();
5749
+ try {
5750
+ if (namespaces.length === 0) return;
5751
+ const trustZoneByNsAndRecordId = /* @__PURE__ */ new Map();
5752
+ const trustZoneKey = (ns, recordId) => `${ns}\0${recordId}`;
5753
+ const scopedStorages = /* @__PURE__ */ new Map();
5754
+ for (const ns of namespaces) {
5755
+ const storage = await this.storageRouter.storageFor(ns);
5756
+ scopedStorages.set(ns, storage);
5757
+ const trustZones = await listTrustZoneRecords({
5758
+ memoryDir: storage.dir,
5759
+ trustZoneStoreDir: this.config.trustZoneStoreDir,
5760
+ limit: 200
5761
+ }).catch(() => ({
5762
+ allRecords: []
5763
+ }));
5764
+ for (const record of trustZones.allRecords ?? []) {
5765
+ trustZoneByNsAndRecordId.set(
5766
+ trustZoneKey(ns, record.recordId),
5767
+ record.zone
5768
+ );
5769
+ }
5770
+ }
5771
+ const memoryNamespaceByPath = /* @__PURE__ */ new Map();
5772
+ const memoryNamespaceById = /* @__PURE__ */ new Map();
5773
+ let candidatesConsidered = 0;
5774
+ const sources = {
5775
+ taxonomy: DEFAULT_TAXONOMY,
5776
+ listCandidateMemories: async (options) => {
5777
+ const targetNs = options.namespace;
5778
+ const storage = scopedStorages.get(targetNs) ?? await this.storageRouter.storageFor(targetNs);
5779
+ const all = await storage.readAllMemories();
5780
+ const active = [];
5781
+ for (const m of all) {
5782
+ if ((m.frontmatter.status ?? "active") === "active") {
5783
+ active.push(m);
5784
+ memoryNamespaceByPath.set(m.path, targetNs);
5785
+ if (m.frontmatter.id) {
5786
+ memoryNamespaceById.set(m.frontmatter.id, targetNs);
5787
+ }
5788
+ }
5789
+ }
5790
+ candidatesConsidered += active.length;
5791
+ return active;
5792
+ },
5793
+ trustZoneFor: async (memoryId) => {
5794
+ const ns = memoryNamespaceById.get(memoryId);
5795
+ if (!ns) return null;
5796
+ return trustZoneByNsAndRecordId.get(
5797
+ trustZoneKey(ns, memoryId)
5798
+ ) ?? null;
5799
+ },
5800
+ importanceFor: (memory) => typeof memory.frontmatter.importance?.score === "number" ? memory.frontmatter.importance.score : 0
5801
+ };
5802
+ let result;
5803
+ for (const ns of namespaces) {
5804
+ const r = await tryDirectAnswer({
5805
+ query: prompt,
5806
+ namespace: ns,
5807
+ config: this.config,
5808
+ sources
5809
+ });
5810
+ if (r.eligible && r.winner) {
5811
+ result = r;
5812
+ break;
5813
+ }
5814
+ }
5815
+ if (!result?.eligible || !result?.winner) return;
5816
+ const explain = {
5817
+ tier: "direct-answer",
5818
+ tierReason: result.narrative,
5819
+ filteredBy: result.filteredBy,
5820
+ candidatesConsidered,
5821
+ latencyMs: Date.now() - tierStart,
5822
+ sourceAnchors: [{ path: result.winner.memory.path }]
5823
+ };
5824
+ await this.lastRecall.annotateTierExplain(
5825
+ sessionKey,
5826
+ explain,
5827
+ expectedIdentity
5828
+ );
5829
+ } catch (err) {
5830
+ if (err instanceof Error && err.name === "AbortError") return;
5831
+ log.debug(`direct-answer observation failed: ${err}`);
5832
+ }
5833
+ }
4882
5834
  logRecallFailure(err) {
4883
5835
  const now = Date.now();
4884
5836
  const errorMsg = err instanceof Error ? err.message : String(err);
@@ -5282,7 +6234,7 @@ ${r.snippet.trim()}
5282
6234
  0
5283
6235
  );
5284
6236
  seedPaths.push(
5285
- ...seedRelativePaths.map((rel) => path5.join(storage.dir, rel))
6237
+ ...seedRelativePaths.map((rel) => path7.join(storage.dir, rel))
5286
6238
  );
5287
6239
  const seedSet = new Set(seedRelativePaths);
5288
6240
  const expanded = await this.graphIndexFor(storage).spreadingActivation(
@@ -5292,7 +6244,7 @@ ${r.snippet.trim()}
5292
6244
  if (expanded.length === 0) continue;
5293
6245
  for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
5294
6246
  if (seedSet.has(candidate.path)) continue;
5295
- const memoryPath = path5.resolve(storage.dir, candidate.path);
6247
+ const memoryPath = path7.resolve(storage.dir, candidate.path);
5296
6248
  const memory = await storage.readMemoryByPath(memoryPath);
5297
6249
  if (!memory) continue;
5298
6250
  if (isArtifactMemoryPath(memory.path)) continue;
@@ -5316,7 +6268,7 @@ ${r.snippet.trim()}
5316
6268
  path: memory.path,
5317
6269
  score,
5318
6270
  namespace,
5319
- seed: path5.resolve(storage.dir, candidate.seed),
6271
+ seed: path7.resolve(storage.dir, candidate.seed),
5320
6272
  hopDepth: candidate.hopDepth,
5321
6273
  decayedWeight: candidate.decayedWeight,
5322
6274
  graphType: candidate.graphType
@@ -5332,12 +6284,12 @@ ${r.snippet.trim()}
5332
6284
  }
5333
6285
  async recordLastGraphRecallSnapshot(options) {
5334
6286
  try {
5335
- const snapshotPath = path5.join(
6287
+ const snapshotPath = path7.join(
5336
6288
  options.storage.dir,
5337
6289
  "state",
5338
6290
  "last_graph_recall.json"
5339
6291
  );
5340
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
6292
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
5341
6293
  const now = (/* @__PURE__ */ new Date()).toISOString();
5342
6294
  const totalSeedCount = options.seedPaths.length;
5343
6295
  const totalExpandedCount = options.expandedPaths.length;
@@ -5364,20 +6316,20 @@ ${r.snippet.trim()}
5364
6316
  finalResults: (options.finalResults ?? []).slice(0, 64),
5365
6317
  shadowComparison: options.shadowComparison
5366
6318
  };
5367
- await writeFile3(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
6319
+ await writeFile4(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
5368
6320
  } catch (err) {
5369
6321
  log.debug(`last graph recall write failed: ${err}`);
5370
6322
  }
5371
6323
  }
5372
6324
  async recordLastIntentSnapshot(options) {
5373
6325
  try {
5374
- const snapshotPath = path5.join(
6326
+ const snapshotPath = path7.join(
5375
6327
  options.storage.dir,
5376
6328
  "state",
5377
6329
  "last_intent.json"
5378
6330
  );
5379
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
5380
- await writeFile3(
6331
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
6332
+ await writeFile4(
5381
6333
  snapshotPath,
5382
6334
  JSON.stringify(options.snapshot, null, 2),
5383
6335
  "utf-8"
@@ -5388,13 +6340,13 @@ ${r.snippet.trim()}
5388
6340
  }
5389
6341
  async recordLastQmdRecallSnapshot(options) {
5390
6342
  try {
5391
- const snapshotPath = path5.join(
6343
+ const snapshotPath = path7.join(
5392
6344
  options.storage.dir,
5393
6345
  "state",
5394
6346
  "last_qmd_recall.json"
5395
6347
  );
5396
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
5397
- await writeFile3(
6348
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
6349
+ await writeFile4(
5398
6350
  snapshotPath,
5399
6351
  JSON.stringify(options.snapshot, null, 2),
5400
6352
  "utf-8"
@@ -5408,9 +6360,9 @@ ${r.snippet.trim()}
5408
6360
  const stateDir = await this.resolveStateDirForNamespace(
5409
6361
  options.namespace
5410
6362
  );
5411
- const snapshotPath = path5.join(stateDir, "last_intent.json");
5412
- await mkdir4(path5.dirname(snapshotPath), { recursive: true });
5413
- await writeFile3(
6363
+ const snapshotPath = path7.join(stateDir, "last_intent.json");
6364
+ await mkdir5(path7.dirname(snapshotPath), { recursive: true });
6365
+ await writeFile4(
5414
6366
  snapshotPath,
5415
6367
  JSON.stringify(options.snapshot, null, 2),
5416
6368
  "utf-8"
@@ -5421,12 +6373,12 @@ ${r.snippet.trim()}
5421
6373
  }
5422
6374
  async resolveStateDirForNamespace(namespace) {
5423
6375
  if (!this.config.namespacesEnabled) {
5424
- return path5.join(this.config.memoryDir, "state");
6376
+ return path7.join(this.config.memoryDir, "state");
5425
6377
  }
5426
6378
  if (namespace !== this.config.defaultNamespace) {
5427
- return path5.join(this.config.memoryDir, "namespaces", namespace, "state");
6379
+ return path7.join(this.config.memoryDir, "namespaces", namespace, "state");
5428
6380
  }
5429
- const candidate = path5.join(
6381
+ const candidate = path7.join(
5430
6382
  this.config.memoryDir,
5431
6383
  "namespaces",
5432
6384
  this.config.defaultNamespace
@@ -5434,11 +6386,11 @@ ${r.snippet.trim()}
5434
6386
  try {
5435
6387
  const candidateStat = await stat3(candidate);
5436
6388
  if (candidateStat.isDirectory()) {
5437
- return path5.join(candidate, "state");
6389
+ return path7.join(candidate, "state");
5438
6390
  }
5439
6391
  } catch {
5440
6392
  }
5441
- return path5.join(this.config.memoryDir, "state");
6393
+ return path7.join(this.config.memoryDir, "state");
5442
6394
  }
5443
6395
  buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
5444
6396
  return results.slice(0, limit).map((result) => ({
@@ -5524,7 +6476,10 @@ ${r.snippet.trim()}
5524
6476
  }
5525
6477
  return reserved;
5526
6478
  }
5527
- getRecallBudgetChars() {
6479
+ getRecallBudgetChars(override) {
6480
+ if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
6481
+ return Math.floor(override);
6482
+ }
5528
6483
  const configuredBudget = this.config.recallBudgetChars;
5529
6484
  if (typeof configuredBudget === "number" && Number.isFinite(configuredBudget) && configuredBudget >= 0) {
5530
6485
  return Math.floor(configuredBudget);
@@ -5535,7 +6490,7 @@ ${r.snippet.trim()}
5535
6490
  }
5536
6491
  return 0;
5537
6492
  }
5538
- assembleRecallSections(sectionBuckets) {
6493
+ assembleRecallSections(sectionBuckets, budgetOverride) {
5539
6494
  const orderedEntries = [];
5540
6495
  const pipeline = Array.isArray(this.config.recallPipeline) ? this.config.recallPipeline : [];
5541
6496
  const orderedIds = pipeline.filter((entry) => entry.enabled !== false).map((entry) => entry.id);
@@ -5551,7 +6506,7 @@ ${r.snippet.trim()}
5551
6506
  if (chunks.length === 0) continue;
5552
6507
  orderedEntries.push({ id, content: chunks.join("\n\n") });
5553
6508
  }
5554
- const budget = this.getRecallBudgetChars();
6509
+ const budget = this.getRecallBudgetChars(budgetOverride);
5555
6510
  if (budget === 0) {
5556
6511
  return {
5557
6512
  sections: [],
@@ -5683,6 +6638,13 @@ ${r.snippet.trim()}
5683
6638
  let recalledMemoryCount = 0;
5684
6639
  let recalledMemoryIds = [];
5685
6640
  let recalledMemoryPaths = [];
6641
+ const xrayBranchPoolSize = {
6642
+ hot_qmd: 0,
6643
+ hot_embedding: 0,
6644
+ cold_fallback: 0,
6645
+ recent_scan: 0
6646
+ };
6647
+ const xrayColdPoolSink = { size: 0 };
5686
6648
  let identityInjectionModeUsed = "none";
5687
6649
  let identityInjectedChars = 0;
5688
6650
  let identityInjectionTruncated = false;
@@ -5743,7 +6705,7 @@ ${r.snippet.trim()}
5743
6705
  this.config.verbatimArtifactsMaxRecall
5744
6706
  );
5745
6707
  const embeddingFetchLimit = computedFetchLimit;
5746
- const principal = resolvePrincipal(sessionKey, this.config);
6708
+ const principal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
5747
6709
  const namespaceOverride = options.namespace?.trim() || void 0;
5748
6710
  const readableRecallNamespaces = recallNamespacesForPrincipal(
5749
6711
  principal,
@@ -5754,8 +6716,24 @@ ${r.snippet.trim()}
5754
6716
  `namespace override is not readable: ${namespaceOverride}`
5755
6717
  );
5756
6718
  }
5757
- const selfNamespace = namespaceOverride ?? defaultNamespaceForPrincipal(principal, this.config);
5758
- const recallNamespaces = namespaceOverride ? [namespaceOverride] : readableRecallNamespaces;
6719
+ const codingOverlay = namespaceOverride ? null : this.applyCodingRecallOverlay(sessionKey);
6720
+ const principalSelfNamespace = defaultNamespaceForPrincipal(principal, this.config);
6721
+ const codingSelfNamespace = codingOverlay ? combineNamespaces(principalSelfNamespace, codingOverlay.namespace) : null;
6722
+ const selfNamespace = namespaceOverride ?? codingSelfNamespace ?? principalSelfNamespace;
6723
+ let recallNamespaces;
6724
+ if (namespaceOverride) {
6725
+ recallNamespaces = [namespaceOverride];
6726
+ } else if (codingOverlay && codingSelfNamespace) {
6727
+ const mapped = readableRecallNamespaces.map(
6728
+ (ns) => ns === principalSelfNamespace ? codingSelfNamespace : ns
6729
+ );
6730
+ const fallbackNs = codingOverlay.readFallbacks.map(
6731
+ (fallback) => combineNamespaces(principalSelfNamespace, fallback)
6732
+ );
6733
+ recallNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
6734
+ } else {
6735
+ recallNamespaces = readableRecallNamespaces;
6736
+ }
5759
6737
  const qmdAvailable = this.qmd.isAvailable();
5760
6738
  let graphDecisionStatus = recallDecision.plannedMode === "graph_mode" ? "skipped" : "not_requested";
5761
6739
  let graphDecisionReason = recallDecision.graphReason;
@@ -5772,7 +6750,7 @@ ${r.snippet.trim()}
5772
6750
  const graphExpandedResultPaths = /* @__PURE__ */ new Set();
5773
6751
  const graphSourceLabelsForPath = (resultPath) => {
5774
6752
  const labels = [];
5775
- const normalizedPath = resultPath.split(path5.sep).join("/");
6753
+ const normalizedPath = resultPath.split(path7.sep).join("/");
5776
6754
  const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
5777
6755
  if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
5778
6756
  if (graphExpandedResultPaths.has(resultPath))
@@ -5810,6 +6788,32 @@ ${r.snippet.trim()}
5810
6788
  const earlySessionKey = sessionKey ?? "default";
5811
6789
  this._recallWorkspaceOverrides.delete(earlySessionKey);
5812
6790
  timings.total = `${Date.now() - recallStart}ms`;
6791
+ if (options.xrayCapture === true && !options.abortSignal?.aborted) {
6792
+ try {
6793
+ this.lastXraySnapshot = buildXraySnapshot({
6794
+ query: retrievalQuery,
6795
+ tierExplain: null,
6796
+ results: [],
6797
+ filters: [
6798
+ {
6799
+ name: "planner-mode",
6800
+ considered: 0,
6801
+ admitted: 0,
6802
+ reason: "no_recall"
6803
+ }
6804
+ ],
6805
+ budget: {
6806
+ chars: this.getRecallBudgetChars(options.budgetCharsOverride),
6807
+ used: 0
6808
+ },
6809
+ sessionKey,
6810
+ namespace: selfNamespace,
6811
+ traceId
6812
+ });
6813
+ } catch (err) {
6814
+ log.debug(`x-ray capture (no_recall) failed: ${err}`);
6815
+ }
6816
+ }
5813
6817
  if (sessionKey) {
5814
6818
  this.lastRecall.record({
5815
6819
  sessionKey,
@@ -6959,16 +7963,16 @@ ${formatted}`;
6959
7963
  if (!this.config.compactionResetEnabled) return null;
6960
7964
  const workspaceDir = compactionWorkspaceDir || this.config.workspaceDir || defaultWorkspaceDir();
6961
7965
  const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
6962
- const signalPath = path5.join(
7966
+ const signalPath = path7.join(
6963
7967
  workspaceDir,
6964
7968
  `.compaction-reset-signal-${safeSessionKey}`
6965
7969
  );
6966
- const bootPath = path5.join(workspaceDir, "BOOT.md");
7970
+ const bootPath = path7.join(workspaceDir, "BOOT.md");
6967
7971
  try {
6968
7972
  const signalStat = await stat3(signalPath).catch(() => null);
6969
7973
  if (!signalStat) return null;
6970
7974
  const signalAge = Date.now() - signalStat.mtimeMs;
6971
- const signalData = JSON.parse(await readFile3(signalPath, "utf-8"));
7975
+ const signalData = JSON.parse(await readFile4(signalPath, "utf-8"));
6972
7976
  if (signalData.sessionKey !== effectiveSessionKey) {
6973
7977
  log.debug(
6974
7978
  `recall: compaction signal is for ${signalData.sessionKey}, not ${effectiveSessionKey} \u2014 skipping`
@@ -6988,7 +7992,7 @@ ${formatted}`;
6988
7992
 
6989
7993
  `;
6990
7994
  try {
6991
- const bootContent = await readFile3(bootPath, "utf-8");
7995
+ const bootContent = await readFile4(bootPath, "utf-8");
6992
7996
  section += "### BOOT.md (working state before compaction)\n\n";
6993
7997
  section += bootContent + "\n";
6994
7998
  } catch {
@@ -7182,7 +8186,7 @@ ${formatted}`;
7182
8186
  if (!this.isRecallSectionEnabled("procedure-recall", true)) return null;
7183
8187
  try {
7184
8188
  return await buildProcedureRecallSection(
7185
- this.storage,
8189
+ profileStorage,
7186
8190
  retrievalQuery,
7187
8191
  this.config
7188
8192
  );
@@ -7695,7 +8699,18 @@ ${tmtNode.summary}`
7695
8699
  "rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
7696
8700
  );
7697
8701
  }
8702
+ if (this.config.recallMemoryWorthFilterEnabled && memoryResults.length > 0) {
8703
+ try {
8704
+ memoryResults = await this.applyMemoryWorthRerank(memoryResults, recallNamespaces);
8705
+ } catch (err) {
8706
+ log.debug("memory-worth filter failed open", { error: err.message });
8707
+ }
8708
+ }
7698
8709
  const effectiveGateScore = preAugmentTopScore > 0 ? Math.max(preAugmentTopScore, maxSpecializedScore) : 0;
8710
+ xrayBranchPoolSize.hot_qmd = Math.max(
8711
+ xrayBranchPoolSize.hot_qmd,
8712
+ memoryResults.length
8713
+ );
7699
8714
  let confidenceGateRejected = false;
7700
8715
  if (this.config.recallConfidenceGateEnabled && effectiveGateScore > 0) {
7701
8716
  if (effectiveGateScore < this.config.recallConfidenceGateThreshold) {
@@ -7709,7 +8724,8 @@ ${tmtNode.summary}`
7709
8724
  memoryResults = this.diversifyAndLimitRecallResults(
7710
8725
  "memories",
7711
8726
  memoryResults,
7712
- recallResultLimit
8727
+ recallResultLimit,
8728
+ retrievalQuery
7713
8729
  );
7714
8730
  if (this.config.memoryReconstructionEnabled && memoryResults.length > 0) {
7715
8731
  try {
@@ -7794,10 +8810,15 @@ ${tmtNode.summary}`
7794
8810
  recallNamespaces,
7795
8811
  retrievalQuery
7796
8812
  );
8813
+ xrayBranchPoolSize.hot_embedding = Math.max(
8814
+ xrayBranchPoolSize.hot_embedding,
8815
+ boostedScoped.length
8816
+ );
7797
8817
  const scoped = this.diversifyAndLimitRecallResults(
7798
8818
  "memories",
7799
8819
  boostedScoped,
7800
- recallResultLimit
8820
+ recallResultLimit,
8821
+ retrievalQuery
7801
8822
  );
7802
8823
  if (scoped.length > 0) {
7803
8824
  if (shouldPersistGraphSnapshot) {
@@ -7830,7 +8851,8 @@ ${tmtNode.summary}`
7830
8851
  recallResultLimit,
7831
8852
  recallMode,
7832
8853
  queryAwarePrefilter,
7833
- abortSignal: options.abortSignal
8854
+ abortSignal: options.abortSignal,
8855
+ xrayPoolSizeSink: xrayColdPoolSink
7834
8856
  });
7835
8857
  if (longTerm.length > 0) {
7836
8858
  if (shouldPersistGraphSnapshot) {
@@ -7914,10 +8936,15 @@ ${tmtNode.summary}`
7914
8936
  recallNamespaces,
7915
8937
  retrievalQuery
7916
8938
  );
8939
+ xrayBranchPoolSize.hot_embedding = Math.max(
8940
+ xrayBranchPoolSize.hot_embedding,
8941
+ boostedScoped.length
8942
+ );
7917
8943
  const scoped = this.diversifyAndLimitRecallResults(
7918
8944
  "memories",
7919
8945
  boostedScoped,
7920
- recallResultLimit
8946
+ recallResultLimit,
8947
+ retrievalQuery
7921
8948
  );
7922
8949
  if (scoped.length > 0) {
7923
8950
  if (shouldPersistGraphSnapshot) {
@@ -7971,7 +8998,8 @@ ${tmtNode.summary}`
7971
8998
  recallResultLimit,
7972
8999
  recallMode,
7973
9000
  queryAwarePrefilter,
7974
- abortSignal: options.abortSignal
9001
+ abortSignal: options.abortSignal,
9002
+ xrayPoolSizeSink: xrayColdPoolSink
7975
9003
  });
7976
9004
  if (longTerm.length > 0) {
7977
9005
  recallSource = "cold_fallback";
@@ -8013,10 +9041,15 @@ ${tmtNode.summary}`
8013
9041
  retrievalQuery,
8014
9042
  preloadedMap
8015
9043
  )).sort((a, b) => b.score - a.score);
9044
+ xrayBranchPoolSize.recent_scan = Math.max(
9045
+ xrayBranchPoolSize.recent_scan,
9046
+ boostedRecent.length
9047
+ );
8016
9048
  const recent = this.diversifyAndLimitRecallResults(
8017
9049
  "memories",
8018
9050
  boostedRecent,
8019
- recallResultLimit
9051
+ recallResultLimit,
9052
+ retrievalQuery
8020
9053
  );
8021
9054
  if (recent.length > 0) {
8022
9055
  if (shouldPersistGraphSnapshot) {
@@ -8049,7 +9082,8 @@ ${tmtNode.summary}`
8049
9082
  recallResultLimit,
8050
9083
  recallMode,
8051
9084
  queryAwarePrefilter,
8052
- abortSignal: options.abortSignal
9085
+ abortSignal: options.abortSignal,
9086
+ xrayPoolSizeSink: xrayColdPoolSink
8053
9087
  });
8054
9088
  if (longTerm.length > 0) {
8055
9089
  if (shouldPersistGraphSnapshot) {
@@ -8085,7 +9119,8 @@ ${tmtNode.summary}`
8085
9119
  recallResultLimit,
8086
9120
  recallMode,
8087
9121
  queryAwarePrefilter,
8088
- abortSignal: options.abortSignal
9122
+ abortSignal: options.abortSignal,
9123
+ xrayPoolSizeSink: xrayColdPoolSink
8089
9124
  });
8090
9125
  if (longTerm.length > 0) {
8091
9126
  if (shouldPersistGraphSnapshot) {
@@ -8244,7 +9279,10 @@ _Context: ${topQuestion.context}_`
8244
9279
  );
8245
9280
  const timingParts = Object.entries(timings).map(([k, v]) => `${k}=${v}`).join(", ");
8246
9281
  log.info(`recall timings: ${timingParts}`);
8247
- const assembledRecall = this.assembleRecallSections(sectionBuckets);
9282
+ const assembledRecall = this.assembleRecallSections(
9283
+ sectionBuckets,
9284
+ options.budgetCharsOverride
9285
+ );
8248
9286
  const context = assembledRecall.sections.length === 0 ? "" : assembledRecall.sections.join("\n\n---\n\n");
8249
9287
  const sourcesUsed = this.collectLastRecallSources(
8250
9288
  sectionBuckets,
@@ -8260,6 +9298,73 @@ _Context: ${topQuestion.context}_`
8260
9298
  includedSections: assembledRecall.includedIds,
8261
9299
  omittedSections: assembledRecall.omittedIds
8262
9300
  });
9301
+ if (options.xrayCapture === true && !options.abortSignal?.aborted) {
9302
+ try {
9303
+ const servedBy = mapRecallSourceToXrayServedBy(recallSource);
9304
+ const idFromPath = (p) => {
9305
+ const match = p.match(/([^/]+)\.md$/);
9306
+ return match ? match[1] ?? null : null;
9307
+ };
9308
+ const results = [];
9309
+ for (const recalledPath of recalledMemoryPaths) {
9310
+ const derivedId = idFromPath(recalledPath);
9311
+ if (!derivedId) continue;
9312
+ results.push({
9313
+ memoryId: derivedId,
9314
+ path: recalledPath,
9315
+ servedBy,
9316
+ scoreDecomposition: { final: 0 },
9317
+ admittedBy: []
9318
+ });
9319
+ }
9320
+ let xrayConsidered;
9321
+ switch (recallSource) {
9322
+ case "hot_qmd":
9323
+ xrayConsidered = xrayBranchPoolSize.hot_qmd;
9324
+ break;
9325
+ case "hot_embedding":
9326
+ xrayConsidered = xrayBranchPoolSize.hot_embedding;
9327
+ break;
9328
+ case "cold_fallback":
9329
+ xrayConsidered = xrayColdPoolSink.size;
9330
+ break;
9331
+ case "recent_scan":
9332
+ xrayConsidered = xrayBranchPoolSize.recent_scan;
9333
+ break;
9334
+ case "none":
9335
+ xrayConsidered = recalledMemoryCount;
9336
+ break;
9337
+ default: {
9338
+ const _exhaustive = recallSource;
9339
+ void _exhaustive;
9340
+ xrayConsidered = recalledMemoryCount;
9341
+ }
9342
+ }
9343
+ xrayConsidered = Math.max(xrayConsidered, recalledMemoryIds.length);
9344
+ const filters = [
9345
+ {
9346
+ name: "recall-result-limit",
9347
+ considered: xrayConsidered,
9348
+ admitted: recalledMemoryIds.length
9349
+ }
9350
+ ];
9351
+ this.lastXraySnapshot = buildXraySnapshot({
9352
+ query: retrievalQuery,
9353
+ tierExplain: null,
9354
+ results,
9355
+ filters,
9356
+ budget: {
9357
+ chars: this.getRecallBudgetChars(options.budgetCharsOverride),
9358
+ used: assembledRecall.finalChars
9359
+ },
9360
+ sessionKey,
9361
+ namespace: selfNamespace,
9362
+ traceId
9363
+ });
9364
+ } catch (err) {
9365
+ log.debug(`x-ray capture failed: ${err}`);
9366
+ }
9367
+ }
8263
9368
  if (sessionKey) {
8264
9369
  throwIfRecallAborted(options.abortSignal);
8265
9370
  this.lastRecall.record({
@@ -8595,7 +9700,7 @@ _Context: ${topQuestion.context}_`
8595
9700
  if (!this.queueProcessing) {
8596
9701
  this.queueProcessing = true;
8597
9702
  this.processQueue().catch((err) => {
8598
- log.error("background extraction queue processor failed", err);
9703
+ this.logExtractionQueueFailure(err, "processor");
8599
9704
  this.queueProcessing = false;
8600
9705
  });
8601
9706
  }
@@ -8653,12 +9758,38 @@ ${normalized}`).digest("hex");
8653
9758
  try {
8654
9759
  await task();
8655
9760
  } catch (err) {
8656
- log.error("background extraction task failed", err);
9761
+ this.logExtractionQueueFailure(err, "task");
8657
9762
  }
8658
9763
  }
8659
9764
  }
8660
9765
  this.queueProcessing = false;
8661
9766
  }
9767
+ /**
9768
+ * Classify + log a failure from either the per-task catch inside
9769
+ * `processQueue()` or the outer `processQueue().catch(...)` in
9770
+ * `queueBufferedExtraction()`. Issue #549: `throwIfRecallAborted`
9771
+ * (used throughout `runExtraction`) raises an Error whose `name` is
9772
+ * `"AbortError"`. That path fires when `before_reset` aborts a
9773
+ * queued task to avoid duplicate extraction — it is intentional
9774
+ * cancellation, not a failure. Downgrading the log to debug
9775
+ * prevents spurious `error`-level lines that routinely appear
9776
+ * right next to a successful `persisted: N facts, M entities` log
9777
+ * and that confuse operators into thinking extraction is broken.
9778
+ * Genuine extraction failures (network, parse, I/O) still log at
9779
+ * `error`.
9780
+ *
9781
+ * Source differentiates the two call sites so the log message
9782
+ * names the right layer (`task` vs `processor`).
9783
+ */
9784
+ logExtractionQueueFailure(err, source) {
9785
+ const aborted = source === "task" ? "background extraction task aborted (session transition)" : "background extraction queue processor aborted (session transition)";
9786
+ const failed = source === "task" ? "background extraction task failed" : "background extraction queue processor failed";
9787
+ if (isAbortError(err)) {
9788
+ log.debug(aborted);
9789
+ } else {
9790
+ log.error(failed, err);
9791
+ }
9792
+ }
8662
9793
  async runExtraction(turns, options = {}) {
8663
9794
  log.debug(`running extraction on ${turns.length} turns`);
8664
9795
  const clearBufferAfterExtraction = options.clearBufferAfterExtraction ?? true;
@@ -8670,12 +9801,12 @@ ${normalized}`).digest("hex");
8670
9801
  throw new Error(`replay extraction deadline exceeded (${stage})`);
8671
9802
  }
8672
9803
  };
8673
- const throwIfAborted = (stage) => {
9804
+ const throwIfAborted2 = (stage) => {
8674
9805
  throwIfRecallAborted(options.abortSignal, `extraction aborted (${stage})`);
8675
9806
  };
8676
9807
  const clearBuffer = async (options2) => {
8677
9808
  if (options2?.ignoreAbort !== true) {
8678
- throwIfAborted("before_clear_buffer");
9809
+ throwIfAborted2("before_clear_buffer");
8679
9810
  }
8680
9811
  if (clearBufferAfterExtraction) {
8681
9812
  await this.buffer.clearAfterExtraction(bufferKey);
@@ -8694,7 +9825,7 @@ ${normalized}`).digest("hex");
8694
9825
  content: t.content.trim().slice(0, this.config.extractionMaxTurnChars)
8695
9826
  })).filter((t) => t.content.length > 0);
8696
9827
  throwIfDeadlineExceeded("before_extract");
8697
- throwIfAborted("before_extract");
9828
+ throwIfAborted2("before_extract");
8698
9829
  const userTurns = normalizedTurns.filter((t) => t.role === "user");
8699
9830
  const totalChars = normalizedTurns.reduce(
8700
9831
  (sum, t) => sum + t.content.length,
@@ -8710,7 +9841,10 @@ ${normalized}`).digest("hex");
8710
9841
  return;
8711
9842
  }
8712
9843
  const principal = resolvePrincipal(sessionKey, this.config);
8713
- const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : defaultNamespaceForPrincipal(principal, this.config);
9844
+ const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : this.applyCodingNamespaceOverlay(
9845
+ sessionKey,
9846
+ defaultNamespaceForPrincipal(principal, this.config)
9847
+ );
8714
9848
  const storage = await this.storageRouter.storageFor(selfNamespace);
8715
9849
  const shouldPersistProcessedFingerprint = normalizedTurns.some(
8716
9850
  (turn) => turn.persistProcessedFingerprint === true
@@ -8739,7 +9873,7 @@ ${normalized}`).digest("hex");
8739
9873
  "extraction aborted (during_extract)"
8740
9874
  );
8741
9875
  throwIfDeadlineExceeded("before_persist");
8742
- throwIfAborted("before_persist");
9876
+ throwIfAborted2("before_persist");
8743
9877
  if (!result) {
8744
9878
  log.warn("runExtraction: extraction returned null/undefined");
8745
9879
  await clearBuffer();
@@ -8803,6 +9937,24 @@ ${normalized}`).digest("hex");
8803
9937
  } catch (error) {
8804
9938
  postPersistMetaError = error;
8805
9939
  }
9940
+ try {
9941
+ if (clearBufferAfterExtraction && !this.config.extractionJudgeShadow) {
9942
+ const deferredCount = this.lastPersistExtractionDeferredCount;
9943
+ if (deferredCount > 0 && normalizedTurns.length > 0) {
9944
+ await this.buffer.retainDeferredTurns(
9945
+ bufferKey,
9946
+ normalizedTurns,
9947
+ 10
9948
+ );
9949
+ } else {
9950
+ await this.buffer.retainDeferredTurns(bufferKey, [], 0);
9951
+ }
9952
+ }
9953
+ } catch (err) {
9954
+ log.debug(
9955
+ `extraction-judge: defer retention failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
9956
+ );
9957
+ }
8806
9958
  await clearBuffer({ ignoreAbort: true });
8807
9959
  if (this.config.memoryBoxesEnabled && persistedIds.length > 0) {
8808
9960
  const extractionTopics = deriveTopicsFromExtraction(result);
@@ -8935,7 +10087,7 @@ ${normalized}`).digest("hex");
8935
10087
  );
8936
10088
  this.tierMigrationInFlight = true;
8937
10089
  try {
8938
- const coldStorage = new StorageManager(path5.join(storage.dir, "cold"));
10090
+ const coldStorage = new StorageManager(path7.join(storage.dir, "cold"));
8939
10091
  const [hotMemories, coldMemories] = await Promise.all([
8940
10092
  storage.readAllMemories(),
8941
10093
  coldStorage.readAllMemories()
@@ -9384,6 +10536,7 @@ ${normalized}`).digest("hex");
9384
10536
  }
9385
10537
  let judgeVerdictsByFactIndex = null;
9386
10538
  let judgeGatedCount = 0;
10539
+ this.lastPersistExtractionDeferredCount = 0;
9387
10540
  if (this.config.extractionJudgeEnabled) {
9388
10541
  try {
9389
10542
  const judgeCandidates = [];
@@ -9418,12 +10571,56 @@ ${normalized}`).digest("hex");
9418
10571
  });
9419
10572
  candidateToFactIndex.push(fi);
9420
10573
  }
10574
+ const judgeTelemetryOpts = {
10575
+ enabled: this.config.extractionJudgeTelemetryEnabled === true,
10576
+ memoryDir: this.config.memoryDir
10577
+ };
10578
+ const judgeTrainingOpts = {
10579
+ enabled: this.config.collectJudgeTrainingPairs === true,
10580
+ ...this.config.judgeTrainingDir ? { directory: this.config.judgeTrainingDir } : {}
10581
+ };
10582
+ const judgeTelemetryHandler = judgeTelemetryOpts.enabled || judgeTrainingOpts.enabled ? (obs) => {
10583
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
10584
+ const verdictKind = getVerdictKind(obs.verdict);
10585
+ if (judgeTelemetryOpts.enabled) {
10586
+ const event = {
10587
+ version: 1,
10588
+ category: EXTRACTION_JUDGE_VERDICT_CATEGORY,
10589
+ ts,
10590
+ verdictKind,
10591
+ reason: obs.verdict.reason,
10592
+ deferrals: obs.priorDeferrals,
10593
+ elapsedMs: obs.elapsedMs,
10594
+ candidateCategory: obs.candidate.category,
10595
+ confidence: obs.candidate.confidence,
10596
+ contentHash: obs.contentHash,
10597
+ fromCache: obs.source === "cache",
10598
+ ...obs.source === "llm-cap-rejected" ? { deferCapTriggered: true } : {}
10599
+ };
10600
+ void recordJudgeVerdict(event, judgeTelemetryOpts);
10601
+ }
10602
+ if (judgeTrainingOpts.enabled) {
10603
+ const pair = {
10604
+ version: 1,
10605
+ ts,
10606
+ candidateText: obs.candidate.text,
10607
+ candidateCategory: obs.candidate.category,
10608
+ ...typeof obs.candidate.confidence === "number" ? { candidateConfidence: obs.candidate.confidence } : {},
10609
+ verdictKind,
10610
+ reason: obs.verdict.reason,
10611
+ priorDeferrals: obs.priorDeferrals
10612
+ };
10613
+ void recordJudgeTrainingPair(pair, judgeTrainingOpts);
10614
+ }
10615
+ } : void 0;
9421
10616
  const judgeResult = await judgeFactDurability(
9422
10617
  judgeCandidates,
9423
10618
  this.config,
9424
10619
  this.localLlm,
9425
10620
  new FallbackLlmClient(this.config.gatewayConfig),
9426
- this.judgeVerdictCache
10621
+ this.judgeVerdictCache,
10622
+ this.judgeDeferCounts,
10623
+ judgeTelemetryHandler
9427
10624
  );
9428
10625
  judgeVerdictsByFactIndex = /* @__PURE__ */ new Map();
9429
10626
  for (const [candidateIdx, verdict] of judgeResult.verdicts) {
@@ -9433,8 +10630,9 @@ ${normalized}`).digest("hex");
9433
10630
  }
9434
10631
  }
9435
10632
  log.info(
9436
- `extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.elapsed}ms`
10633
+ `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`
9437
10634
  );
10635
+ this.lastPersistExtractionDeferredCount = judgeResult.deferred;
9438
10636
  } catch (err) {
9439
10637
  log.warn(
9440
10638
  `extraction-judge: pipeline error, proceeding without filtering (fail-open): ${err instanceof Error ? err.message : String(err)}`
@@ -9452,16 +10650,6 @@ ${normalized}`).digest("hex");
9452
10650
  }
9453
10651
  fact.tags = Array.isArray(fact.tags) ? fact.tags.filter((t) => typeof t === "string") : [];
9454
10652
  fact.confidence = typeof fact.confidence === "number" ? fact.confidence : 0.7;
9455
- if (this.contentHashIndex) {
9456
- const canonicalContent = citationEnabled && hasCitationForTemplate(fact.content, citationTemplate) ? stripCitationForTemplate(fact.content, citationTemplate) : fact.content;
9457
- if (this.contentHashIndex.has(canonicalContent)) {
9458
- log.debug(
9459
- `dedup: skipping duplicate fact "${fact.content.slice(0, 60)}\u2026"`
9460
- );
9461
- dedupedCount++;
9462
- continue;
9463
- }
9464
- }
9465
10653
  let writeCategory = fact.category;
9466
10654
  let targetStorage = storage;
9467
10655
  let routedRuleId;
@@ -9486,6 +10674,15 @@ ${normalized}`).digest("hex");
9486
10674
  );
9487
10675
  }
9488
10676
  }
10677
+ const canonicalContentForHash = citationEnabled && hasCitationForTemplate(fact.content, citationTemplate) ? stripCitationForTemplate(fact.content, citationTemplate) : fact.content;
10678
+ const contentHashDedupKey = writeCategory === "procedure" ? buildProcedurePersistBody(fact.content, fact.procedureSteps) : canonicalContentForHash;
10679
+ if (this.contentHashIndex && this.contentHashIndex.has(contentHashDedupKey)) {
10680
+ log.debug(
10681
+ `dedup: skipping duplicate fact "${fact.content.slice(0, 60)}\u2026"`
10682
+ );
10683
+ dedupedCount++;
10684
+ continue;
10685
+ }
9489
10686
  const importance = scoreImportance(
9490
10687
  fact.content,
9491
10688
  writeCategory,
@@ -9510,10 +10707,17 @@ ${normalized}`).digest("hex");
9510
10707
  if (judgeVerdictsByFactIndex) {
9511
10708
  const verdict = judgeVerdictsByFactIndex.get(factLoopIndex);
9512
10709
  if (verdict && !verdict.durable) {
10710
+ const verdictKind = getVerdictKind(verdict);
9513
10711
  if (this.config.extractionJudgeShadow) {
9514
10712
  log.info(
9515
- `extraction-judge[shadow]: would reject "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
10713
+ `extraction-judge[shadow]: would ${verdictKind} "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
10714
+ );
10715
+ } else if (verdictKind === "defer") {
10716
+ judgeGatedCount++;
10717
+ log.debug(
10718
+ `extraction-judge: deferred "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
9516
10719
  );
10720
+ continue;
9517
10721
  } else {
9518
10722
  judgeGatedCount++;
9519
10723
  log.debug(
@@ -9529,16 +10733,10 @@ ${normalized}`).digest("hex");
9529
10733
  procedureSteps: fact.procedureSteps
9530
10734
  });
9531
10735
  if (!procGate.durable) {
9532
- if (this.config.extractionJudgeShadow) {
9533
- log.info(
9534
- `extraction-procedure-gate[shadow]: would reject "${fact.content.slice(0, 60)}\u2026" reason="${procGate.reason}"`
9535
- );
9536
- } else {
9537
- log.debug(
9538
- `extraction-procedure-gate: rejected "${fact.content.slice(0, 60)}\u2026" reason="${procGate.reason}"`
9539
- );
9540
- continue;
9541
- }
10736
+ log.debug(
10737
+ `extraction-procedure-gate: rejected "${fact.content.slice(0, 60)}\u2026" reason="${procGate.reason}"`
10738
+ );
10739
+ continue;
9542
10740
  }
9543
10741
  }
9544
10742
  let pendingSemanticSkip = null;
@@ -9935,7 +11133,8 @@ ${normalized}`).digest("hex");
9935
11133
  }
9936
11134
  if (this.contentHashIndex) {
9937
11135
  const canonicalFactContent = citationEnabled && hasCitationForTemplate(fact.content, citationTemplate) ? stripCitationForTemplate(fact.content, citationTemplate) : fact.content;
9938
- this.contentHashIndex.add(canonicalFactContent);
11136
+ const hashRegisterKey = writeCategory === "procedure" ? buildProcedurePersistBody(fact.content, fact.procedureSteps) : canonicalFactContent;
11137
+ this.contentHashIndex.add(hashRegisterKey);
9939
11138
  }
9940
11139
  }
9941
11140
  for (const entity of entities) {
@@ -10061,7 +11260,7 @@ ${normalized}`).digest("hex");
10061
11260
  const allMems = allMemsForGraph ?? [];
10062
11261
  for (const m of allMems) {
10063
11262
  if (m.frontmatter.entityRef === entityRef) {
10064
- const rel = path5.relative(storage.dir, m.path);
11263
+ const rel = path7.relative(storage.dir, m.path);
10065
11264
  if (rel !== memoryRelPath) entitySiblings.push(rel);
10066
11265
  }
10067
11266
  }
@@ -10332,14 +11531,14 @@ ${normalized}`).digest("hex");
10332
11531
  }
10333
11532
  if (this.config.semanticConsolidationEnabled) {
10334
11533
  try {
10335
- const stateFilePath = path5.join(
11534
+ const stateFilePath = path7.join(
10336
11535
  this.config.memoryDir,
10337
11536
  "state",
10338
11537
  "semantic-consolidation-last-run.json"
10339
11538
  );
10340
11539
  let shouldRun = true;
10341
11540
  try {
10342
- const stateRaw = await readFile3(stateFilePath, "utf-8");
11541
+ const stateRaw = await readFile4(stateFilePath, "utf-8");
10343
11542
  const stateData = JSON.parse(stateRaw);
10344
11543
  if (stateData.lastRunAt) {
10345
11544
  const lastRunMs = new Date(stateData.lastRunAt).getTime();
@@ -10362,9 +11561,9 @@ ${normalized}`).digest("hex");
10362
11561
  allMemories = await this.storage.readAllMemories();
10363
11562
  }
10364
11563
  if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
10365
- const stateDir = path5.join(this.config.memoryDir, "state");
10366
- await mkdir4(stateDir, { recursive: true });
10367
- await writeFile3(
11564
+ const stateDir = path7.join(this.config.memoryDir, "state");
11565
+ await mkdir5(stateDir, { recursive: true });
11566
+ await writeFile4(
10368
11567
  stateFilePath,
10369
11568
  JSON.stringify({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString() }),
10370
11569
  "utf-8"
@@ -10836,13 +12035,13 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
10836
12035
  protectedCategories: this.config.lifecycleProtectedCategories
10837
12036
  }
10838
12037
  };
10839
- const metricsPath = path5.join(
12038
+ const metricsPath = path7.join(
10840
12039
  this.storage.dir,
10841
12040
  "state",
10842
12041
  "lifecycle-metrics.json"
10843
12042
  );
10844
- await mkdir4(path5.dirname(metricsPath), { recursive: true });
10845
- await writeFile3(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
12043
+ await mkdir5(path7.dirname(metricsPath), { recursive: true });
12044
+ await writeFile4(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
10846
12045
  }
10847
12046
  /**
10848
12047
  * Archive old, low-importance, rarely-accessed facts (v6.0).
@@ -11345,11 +12544,97 @@ ${lines.join("\n\n")}`;
11345
12544
  *
11346
12545
  * Callers must pass the full candidate pool (post-rerank, pre-slice).
11347
12546
  */
11348
- diversifyAndLimitRecallResults(sectionId, results, limit) {
12547
+ async applyMemoryWorthRerank(results, namespaces) {
12548
+ const counters = /* @__PURE__ */ new Map();
12549
+ const seenNamespaces = /* @__PURE__ */ new Set();
12550
+ const nowMs = Date.now();
12551
+ for (const [key, entry] of this.memoryWorthCounterCache) {
12552
+ if (nowMs - entry.at >= _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
12553
+ this.memoryWorthCounterCache.delete(key);
12554
+ }
12555
+ }
12556
+ for (const ns of namespaces) {
12557
+ if (seenNamespaces.has(ns)) continue;
12558
+ seenNamespaces.add(ns);
12559
+ try {
12560
+ const cached = this.memoryWorthCounterCache.get(ns);
12561
+ let nsMap;
12562
+ if (cached && nowMs - cached.at < _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
12563
+ nsMap = cached.counters;
12564
+ } else {
12565
+ const storage = await this.getStorage(ns);
12566
+ const memories = await storage.readAllMemories();
12567
+ nsMap = buildMemoryWorthCounterMap(memories);
12568
+ this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });
12569
+ }
12570
+ for (const [path8, c] of nsMap) counters.set(path8, c);
12571
+ } catch (err) {
12572
+ log.debug("memory-worth: failed to read namespace, skipping", {
12573
+ namespace: ns,
12574
+ error: err.message
12575
+ });
12576
+ }
12577
+ }
12578
+ const missing = results.filter((r) => !counters.has(r.path));
12579
+ if (missing.length > 0) {
12580
+ let reader = null;
12581
+ for (const ns of namespaces) {
12582
+ try {
12583
+ reader = await this.getStorage(ns);
12584
+ break;
12585
+ } catch {
12586
+ }
12587
+ }
12588
+ if (reader) {
12589
+ for (const r of missing) {
12590
+ try {
12591
+ const memory = await reader.readMemoryByPath(r.path);
12592
+ if (!memory) continue;
12593
+ const fm = memory.frontmatter;
12594
+ if (fm.mw_success === void 0 && fm.mw_fail === void 0) continue;
12595
+ counters.set(r.path, {
12596
+ mw_success: fm.mw_success,
12597
+ mw_fail: fm.mw_fail,
12598
+ lastAccessed: fm.lastAccessed
12599
+ });
12600
+ } catch (err) {
12601
+ log.debug("memory-worth: direct path lookup failed", {
12602
+ path: r.path,
12603
+ error: err.message
12604
+ });
12605
+ }
12606
+ }
12607
+ }
12608
+ }
12609
+ if (counters.size === 0) return results;
12610
+ const rankedInputs = results.map((r, i) => ({
12611
+ path: r.path,
12612
+ // Large positive rank score so multiplier math stays well-scaled and
12613
+ // we never hit zero; descending so earlier items rank higher.
12614
+ score: results.length - i
12615
+ }));
12616
+ const filtered = applyMemoryWorthFilter(rankedInputs, {
12617
+ counters,
12618
+ now: /* @__PURE__ */ new Date(),
12619
+ halfLifeMs: this.config.recallMemoryWorthHalfLifeMs > 0 ? this.config.recallMemoryWorthHalfLifeMs : void 0
12620
+ });
12621
+ const byPath = new Map(results.map((r) => [r.path, r]));
12622
+ const reordered = [];
12623
+ for (const item of filtered) {
12624
+ const original = byPath.get(item.path);
12625
+ if (original) reordered.push(original);
12626
+ }
12627
+ return reordered;
12628
+ }
12629
+ diversifyAndLimitRecallResults(sectionId, results, limit, retrievalQuery) {
11349
12630
  const safeLimit = typeof limit === "number" && Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 0;
11350
12631
  if (!Array.isArray(results) || results.length === 0) return [];
11351
12632
  if (safeLimit === 0) return [];
11352
- const diversified = this.applyMmrToQmdResults(sectionId, results);
12633
+ const boosted = this.config.recallReasoningTraceBoostEnabled && typeof retrievalQuery === "string" ? applyReasoningTraceBoost(results, {
12634
+ enabled: true,
12635
+ query: retrievalQuery
12636
+ }) : results;
12637
+ const diversified = this.applyMmrToQmdResults(sectionId, boosted);
11353
12638
  return diversified.slice(0, safeLimit);
11354
12639
  }
11355
12640
  /**
@@ -11453,12 +12738,12 @@ ${lines.join("\n\n")}`;
11453
12738
  */
11454
12739
  semanticDedupScopeFor(targetStorage) {
11455
12740
  if (!this.config.namespacesEnabled) return {};
11456
- const memoryDir = path5.resolve(this.config.memoryDir);
11457
- const storageDir = path5.resolve(targetStorage.dir);
12741
+ const memoryDir = path7.resolve(this.config.memoryDir);
12742
+ const storageDir = path7.resolve(targetStorage.dir);
11458
12743
  if (storageDir === memoryDir) {
11459
12744
  return { pathExcludePrefixes: ["namespaces/"] };
11460
12745
  }
11461
- let rel = path5.relative(memoryDir, storageDir);
12746
+ let rel = path7.relative(memoryDir, storageDir);
11462
12747
  if (!rel || rel.startsWith("..")) {
11463
12748
  log.debug(
11464
12749
  `semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
@@ -11477,7 +12762,7 @@ ${lines.join("\n\n")}`;
11477
12762
  if (hits.length === 0) return [];
11478
12763
  const results = [];
11479
12764
  for (const hit of hits) {
11480
- const fullPath = path5.isAbsolute(hit.path) ? hit.path : path5.join(this.config.memoryDir, hit.path);
12765
+ const fullPath = path7.isAbsolute(hit.path) ? hit.path : path7.join(this.config.memoryDir, hit.path);
11481
12766
  const memory = await this.storage.readMemoryByPath(fullPath);
11482
12767
  if (!memory) continue;
11483
12768
  results.push({
@@ -11654,10 +12939,26 @@ ${lines.join("\n\n")}`;
11654
12939
  "rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
11655
12940
  );
11656
12941
  }
12942
+ if (this.config.recallMemoryWorthFilterEnabled && results.length > 0) {
12943
+ try {
12944
+ results = await this.applyMemoryWorthRerank(results, options.recallNamespaces);
12945
+ } catch (err) {
12946
+ log.debug("memory-worth filter (cold) failed open", {
12947
+ error: err.message
12948
+ });
12949
+ }
12950
+ }
12951
+ if (options.xrayPoolSizeSink) {
12952
+ options.xrayPoolSizeSink.size = Math.max(
12953
+ options.xrayPoolSizeSink.size,
12954
+ results.length
12955
+ );
12956
+ }
11657
12957
  return this.diversifyAndLimitRecallResults(
11658
12958
  "memories",
11659
12959
  results,
11660
- options.recallResultLimit
12960
+ options.recallResultLimit,
12961
+ options.prompt
11661
12962
  );
11662
12963
  }
11663
12964
  // ---------------------------------------------------------------------------
@@ -12051,8 +13352,8 @@ ${lines.join("\n\n")}`;
12051
13352
  }
12052
13353
  namespaceFromStorageDir(storageDir) {
12053
13354
  if (!this.config.namespacesEnabled) return this.config.defaultNamespace;
12054
- const resolvedStorageDir = path5.resolve(storageDir);
12055
- const resolvedMemoryDir = path5.resolve(this.config.memoryDir);
13355
+ const resolvedStorageDir = path7.resolve(storageDir);
13356
+ const resolvedMemoryDir = path7.resolve(this.config.memoryDir);
12056
13357
  if (resolvedStorageDir === resolvedMemoryDir)
12057
13358
  return this.config.defaultNamespace;
12058
13359
  const m = resolvedStorageDir.match(/[\\/]namespaces[\\/]([^\\/]+)$/);
@@ -12085,6 +13386,21 @@ export {
12085
13386
  migrateFromEngram,
12086
13387
  buildProcedureRecallSection,
12087
13388
  decideSemanticDedup,
13389
+ DEFAULT_TAXONOMY,
13390
+ generateResolverDocument,
13391
+ validateSlug,
13392
+ validateTaxonomy,
13393
+ loadTaxonomy,
13394
+ saveTaxonomy,
13395
+ getTaxonomyDir,
13396
+ getTaxonomyFilePath,
13397
+ stableHash,
13398
+ normalizeOriginUrl,
13399
+ resolveGitContext,
13400
+ projectNamespaceName,
13401
+ branchNamespaceName,
13402
+ resolveCodingNamespaceOverlay,
13403
+ describeCodingScope,
12088
13404
  dedupeEntitySynthesisEvidenceEntries,
12089
13405
  defaultWorkspaceDir,
12090
13406
  sanitizeSessionKeyForFilename,
@@ -12113,4 +13429,4 @@ export {
12113
13429
  resolvePersistedMemoryRelativePath,
12114
13430
  Orchestrator
12115
13431
  };
12116
- //# sourceMappingURL=chunk-XMGSSBFX.js.map
13432
+ //# sourceMappingURL=chunk-VYM3VWOF.js.map