@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,6 +2,9 @@ import {
2
2
  resolveCueAnchorStoreDir,
3
3
  validateCueAnchor
4
4
  } from "./chunk-C6QPK5GG.js";
5
+ import {
6
+ throwIfAborted
7
+ } from "./chunk-PVGDJXVK.js";
5
8
  import {
6
9
  resolveAbstractionNodeStoreDir,
7
10
  validateAbstractionNode
@@ -96,13 +99,13 @@ async function readCueAnchors(options) {
96
99
  return anchors;
97
100
  }
98
101
  async function searchHarmonicRetrieval(options) {
99
- throwIfAborted(options.abortSignal);
102
+ throwIfAborted(options.abortSignal, "harmonic retrieval aborted");
100
103
  const queryTokens = new Set(normalizeRecallTokens(options.query, ["what", "which"]));
101
104
  if (queryTokens.size === 0 || options.maxResults <= 0) return [];
102
105
  const nodes = await readAbstractionNodes(options);
103
106
  const candidates = /* @__PURE__ */ new Map();
104
107
  for (const node of nodes) {
105
- throwIfAborted(options.abortSignal);
108
+ throwIfAborted(options.abortSignal, "harmonic retrieval aborted");
106
109
  const { score, matchedFields } = scoreNode(node, queryTokens);
107
110
  if (score <= 0) continue;
108
111
  candidates.set(node.nodeId, {
@@ -114,11 +117,11 @@ async function searchHarmonicRetrieval(options) {
114
117
  });
115
118
  }
116
119
  if (options.anchorsEnabled) {
117
- throwIfAborted(options.abortSignal);
120
+ throwIfAborted(options.abortSignal, "harmonic retrieval aborted");
118
121
  const anchors = await readCueAnchors(options);
119
122
  const nodeIndex = new Map(nodes.map((node) => [node.nodeId, node]));
120
123
  for (const anchor of anchors) {
121
- throwIfAborted(options.abortSignal);
124
+ throwIfAborted(options.abortSignal, "harmonic retrieval aborted");
122
125
  const { score, matchedFields } = scoreAnchor(anchor, queryTokens);
123
126
  if (score <= 0) continue;
124
127
  for (const nodeRef of anchor.nodeRefs) {
@@ -160,14 +163,8 @@ async function searchHarmonicRetrieval(options) {
160
163
  (left, right) => right.score - left.score || right.anchorScore - left.anchorScore || right.node.recordedAt.localeCompare(left.node.recordedAt)
161
164
  ).slice(0, options.maxResults);
162
165
  }
163
- function throwIfAborted(signal) {
164
- if (!signal?.aborted) return;
165
- const err = new Error("harmonic retrieval aborted");
166
- Object.defineProperty(err, "name", { value: "AbortError" });
167
- throw err;
168
- }
169
166
 
170
167
  export {
171
168
  searchHarmonicRetrieval
172
169
  };
173
- //# sourceMappingURL=chunk-AAI7JARD.js.map
170
+ //# sourceMappingURL=chunk-HMDCOMYU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/harmonic-retrieval.ts"],"sourcesContent":["import path from \"node:path\";\nimport { listJsonFiles, readJsonFile } from \"./json-store.js\";\nimport { throwIfAborted } from \"./abort-error.js\";\nimport {\n resolveAbstractionNodeStoreDir,\n validateAbstractionNode,\n type AbstractionNode,\n} from \"./abstraction-nodes.js\";\nimport {\n resolveCueAnchorStoreDir,\n validateCueAnchor,\n type CueAnchor,\n type CueAnchorType,\n} from \"./cue-anchors.js\";\nimport { countRecallTokenOverlap, normalizeRecallTokens } from \"./recall-tokenization.js\";\n\nexport interface HarmonicMatchedAnchor {\n anchorId: string;\n anchorType: CueAnchorType;\n anchorValue: string;\n}\n\nexport interface HarmonicRetrievalResult {\n node: AbstractionNode;\n score: number;\n nodeScore: number;\n anchorScore: number;\n matchedFields: string[];\n matchedAnchors: HarmonicMatchedAnchor[];\n}\n\ninterface HarmonicCandidate {\n node: AbstractionNode;\n nodeScore: number;\n anchorScore: number;\n matchedFields: Set<string>;\n matchedAnchors: Map<string, HarmonicMatchedAnchor>;\n}\n\nfunction scoreNode(node: AbstractionNode, queryTokens: Set<string>): { score: number; matchedFields: string[] } {\n const matchedFields: string[] = [];\n let score = 0;\n\n const titleMatches = countRecallTokenOverlap(queryTokens, node.title);\n if (titleMatches > 0) {\n score += titleMatches * 3;\n matchedFields.push(\"title\");\n }\n\n const summaryMatches = countRecallTokenOverlap(queryTokens, node.summary);\n if (summaryMatches > 0) {\n score += summaryMatches * 3;\n matchedFields.push(\"summary\");\n }\n\n const tagMatches = countRecallTokenOverlap(queryTokens, node.tags?.join(\" \"));\n if (tagMatches > 0) {\n score += tagMatches * 2;\n matchedFields.push(\"tags\");\n }\n\n const entityMatches = countRecallTokenOverlap(queryTokens, node.entityRefs?.join(\" \"));\n if (entityMatches > 0) {\n score += entityMatches * 2;\n matchedFields.push(\"entityRefs\");\n }\n\n const kindMatches = countRecallTokenOverlap(queryTokens, `${node.kind} ${node.abstractionLevel}`);\n if (kindMatches > 0) {\n score += kindMatches;\n matchedFields.push(\"kind\");\n }\n\n return { score, matchedFields };\n}\n\nfunction scoreAnchor(anchor: CueAnchor, queryTokens: Set<string>): { score: number; matchedFields: string[] } {\n const matchedFields: string[] = [];\n let score = 0;\n\n const valueMatches = countRecallTokenOverlap(queryTokens, anchor.anchorValue);\n const normalizedMatches = countRecallTokenOverlap(queryTokens, anchor.normalizedCue);\n const cueMatches = Math.max(valueMatches, normalizedMatches);\n if (cueMatches > 0) {\n score += cueMatches * 4;\n if (valueMatches > 0) matchedFields.push(\"anchorValue\");\n if (normalizedMatches > 0) matchedFields.push(\"anchor\");\n }\n\n const typeMatches = countRecallTokenOverlap(queryTokens, anchor.anchorType);\n if (typeMatches > 0) {\n score += typeMatches;\n matchedFields.push(\"anchorType\");\n }\n\n const tagMatches = countRecallTokenOverlap(queryTokens, anchor.tags?.join(\" \"));\n if (tagMatches > 0) {\n score += tagMatches * 2;\n matchedFields.push(\"anchorTags\");\n }\n\n return { score, matchedFields };\n}\n\nasync function readAbstractionNodes(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n}): Promise<AbstractionNode[]> {\n const rootDir = resolveAbstractionNodeStoreDir(options.memoryDir, options.abstractionNodeStoreDir);\n const files = await listJsonFiles(path.join(rootDir, \"nodes\"));\n const nodes: AbstractionNode[] = [];\n for (const filePath of files) {\n try {\n nodes.push(validateAbstractionNode(await readJsonFile(filePath)));\n } catch {\n // fail-open: invalid artifacts stay visible via status tooling instead of recall\n }\n }\n return nodes;\n}\n\nasync function readCueAnchors(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n}): Promise<CueAnchor[]> {\n const abstractionRoot = resolveAbstractionNodeStoreDir(options.memoryDir, options.abstractionNodeStoreDir);\n const rootDir = resolveCueAnchorStoreDir(abstractionRoot);\n const files = await listJsonFiles(rootDir);\n const anchors: CueAnchor[] = [];\n for (const filePath of files) {\n try {\n anchors.push(validateCueAnchor(await readJsonFile(filePath)));\n } catch {\n // fail-open: invalid artifacts stay visible via status tooling instead of recall\n }\n }\n return anchors;\n}\n\nexport async function searchHarmonicRetrieval(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n query: string;\n maxResults: number;\n sessionKey?: string;\n anchorsEnabled: boolean;\n abortSignal?: AbortSignal;\n}): Promise<HarmonicRetrievalResult[]> {\n throwIfAborted(options.abortSignal, \"harmonic retrieval aborted\");\n const queryTokens = new Set(normalizeRecallTokens(options.query, [\"what\", \"which\"]));\n if (queryTokens.size === 0 || options.maxResults <= 0) return [];\n\n const nodes = await readAbstractionNodes(options);\n const candidates = new Map<string, HarmonicCandidate>();\n\n for (const node of nodes) {\n throwIfAborted(options.abortSignal, \"harmonic retrieval aborted\");\n const { score, matchedFields } = scoreNode(node, queryTokens);\n if (score <= 0) continue;\n candidates.set(node.nodeId, {\n node,\n nodeScore: score,\n anchorScore: 0,\n matchedFields: new Set(matchedFields),\n matchedAnchors: new Map(),\n });\n }\n\n if (options.anchorsEnabled) {\n throwIfAborted(options.abortSignal, \"harmonic retrieval aborted\");\n const anchors = await readCueAnchors(options);\n const nodeIndex = new Map(nodes.map((node) => [node.nodeId, node]));\n for (const anchor of anchors) {\n throwIfAborted(options.abortSignal, \"harmonic retrieval aborted\");\n const { score, matchedFields } = scoreAnchor(anchor, queryTokens);\n if (score <= 0) continue;\n for (const nodeRef of anchor.nodeRefs) {\n const node = nodeIndex.get(nodeRef);\n if (!node) continue;\n const existing = candidates.get(nodeRef) ?? {\n node,\n nodeScore: 0,\n anchorScore: 0,\n matchedFields: new Set<string>(),\n matchedAnchors: new Map<string, HarmonicMatchedAnchor>(),\n };\n existing.anchorScore += score;\n existing.matchedFields.add(\"anchor\");\n for (const field of matchedFields) existing.matchedFields.add(field);\n existing.matchedAnchors.set(anchor.anchorId, {\n anchorId: anchor.anchorId,\n anchorType: anchor.anchorType,\n anchorValue: anchor.anchorValue,\n });\n candidates.set(nodeRef, existing);\n }\n }\n }\n\n return [...candidates.values()]\n .map((candidate) => {\n let score = candidate.nodeScore + candidate.anchorScore;\n if (options.sessionKey && candidate.node.sessionKey === options.sessionKey) score += 0.5;\n return {\n node: candidate.node,\n score,\n nodeScore: candidate.nodeScore,\n anchorScore: candidate.anchorScore,\n matchedFields: [...candidate.matchedFields].sort(),\n matchedAnchors: [...candidate.matchedAnchors.values()].sort((left, right) =>\n left.anchorType.localeCompare(right.anchorType) || left.anchorValue.localeCompare(right.anchorValue)\n ),\n };\n })\n .filter((result) => result.nodeScore > 0 || result.anchorScore > 0)\n .sort(\n (left, right) =>\n right.score - left.score\n || right.anchorScore - left.anchorScore\n || right.node.recordedAt.localeCompare(left.node.recordedAt),\n )\n .slice(0, options.maxResults);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,52 @@
1
+ // src/memory-worth.ts
2
+ var MAX_COUNTER = 1e12;
3
+ function classifyCounter(value) {
4
+ if (value === void 0) return { ok: true, value: 0 };
5
+ if (typeof value !== "number") return { ok: false };
6
+ if (!Number.isFinite(value)) return { ok: false };
7
+ if (value < 0) return { ok: false };
8
+ if (!Number.isInteger(value)) return { ok: false };
9
+ if (value > MAX_COUNTER) return { ok: false };
10
+ return { ok: true, value };
11
+ }
12
+ function parseLastAccessedMs(lastAccessed) {
13
+ if (!lastAccessed) return null;
14
+ const parsed = Date.parse(lastAccessed);
15
+ if (!Number.isFinite(parsed)) return null;
16
+ return parsed;
17
+ }
18
+ function decayFactor(ageMs, halfLifeMs) {
19
+ if (typeof halfLifeMs !== "number") return 1;
20
+ if (!Number.isFinite(halfLifeMs)) return 1;
21
+ if (halfLifeMs <= 0) return 1;
22
+ if (ageMs <= 0) return 1;
23
+ return Math.pow(2, -ageMs / halfLifeMs);
24
+ }
25
+ function computeMemoryWorth(input) {
26
+ const sClass = classifyCounter(input.mw_success);
27
+ const fClass = classifyCounter(input.mw_fail);
28
+ if (!sClass.ok || !fClass.ok) {
29
+ return { score: 0.5, p_success: 0.5, confidence: 0 };
30
+ }
31
+ const rawS = sClass.value;
32
+ const rawF = fClass.value;
33
+ const lastAccessedMs = parseLastAccessedMs(input.lastAccessed);
34
+ const nowMs = input.now.getTime();
35
+ const nowUsable = Number.isFinite(nowMs);
36
+ const ageMs = !nowUsable || lastAccessedMs === null ? 0 : Math.max(0, nowMs - lastAccessedMs);
37
+ const factor = nowUsable ? decayFactor(ageMs, input.halfLifeMs) : 1;
38
+ const sEff = rawS * factor;
39
+ const fEff = rawF * factor;
40
+ const pSuccess = (sEff + 1) / (sEff + fEff + 2);
41
+ const clamped = Math.max(0, Math.min(1, pSuccess));
42
+ return {
43
+ score: clamped,
44
+ p_success: clamped,
45
+ confidence: sEff + fEff
46
+ };
47
+ }
48
+
49
+ export {
50
+ computeMemoryWorth
51
+ };
52
+ //# sourceMappingURL=chunk-IISBCCWR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory-worth.ts"],"sourcesContent":["/**\n * Issue #560 PR 2 — Memory Worth scoring (pure helper).\n *\n * Given per-memory outcome counters (`mw_success`, `mw_fail` — added to\n * frontmatter in PR 1), compute a scalar worth score plus interpretable\n * metadata. The score is a Laplace-smoothed success probability with an\n * optional recency decay, and is meant to be used as a multiplier on existing\n * recall scores (PR 4) to sink memories that consistently lead to failed\n * sessions and keep uninstrumented memories at a neutral baseline.\n *\n * Intentional properties:\n * - Pure function. No I/O, no time-of-import side effects. Testable in\n * isolation; callers pass `now` so tests don't depend on the wall clock.\n * - Laplace-smoothed ratio `(s + 1) / (s + f + 2)` ensures a memory with\n * zero observations scores exactly 0.5 — neither boosted nor penalized.\n * A single failure on a new memory lands at 1/3, not 0, so one bad\n * session doesn't permanently exile a fact.\n * - Recency decay is optional. When a memory hasn't been touched in a long\n * time, its `p_success` is pulled back toward 0.5 (the prior). Decay is\n * exponential with an operator-configured half-life so old verdicts\n * aren't treated as equally informative as fresh ones.\n * - Corrupt / missing inputs fail safely to the prior. Callers upstream of\n * this helper (see `storage.parseMemoryWorthCounterField` in PR 1) already\n * strip negatives and non-integers, but the helper re-validates so it\n * survives being called directly from tests / ad-hoc tooling.\n * - Confidence is the effective number of observations (post-decay). PR 4\n * and PR 5 use it to decide whether the Memory Worth multiplier should\n * actually be applied vs. left at 1.0 (i.e., \"not enough signal yet\").\n *\n * Out of scope here:\n * - Mutating frontmatter (PR 3).\n * - Recall integration / feature flag (PR 4).\n * - Benchmark & default-flip (PR 5).\n */\n\n/**\n * Input to `computeMemoryWorth`.\n *\n * All fields are optional so a legacy (pre-PR-1) memory can be passed through\n * without upstream guards — it will simply score to the neutral prior.\n */\nexport interface ComputeMemoryWorthInput {\n /** Count of sessions where this memory was recalled and the outcome was success. */\n mw_success?: number;\n /** Count of sessions where this memory was recalled and the outcome was failure. */\n mw_fail?: number;\n /**\n * ISO timestamp of the most recent outcome observation for this memory.\n * When provided together with `halfLifeMs`, observations decay exponentially\n * toward the uniform prior as they age. Absent / unparseable timestamp →\n * decay is skipped and raw counters are used directly.\n */\n lastAccessed?: string | null;\n /**\n * Current wall-clock reference. Required in the signature (not defaulted to\n * `Date.now()`) so the function stays pure and tests are deterministic.\n */\n now: Date;\n /**\n * Half-life for outcome decay, in milliseconds. When `undefined` or `<= 0`,\n * no decay is applied (raw counts are used). When positive, counter weights\n * are multiplied by `2^(-age / halfLifeMs)`.\n */\n halfLifeMs?: number;\n}\n\n/**\n * Output of `computeMemoryWorth`.\n *\n * `score` is the value recall callers multiply into their base score.\n * `p_success` is the same number pre-clamped — exposed separately so\n * observability surfaces can log the probability distinctly from the\n * multiplier. `confidence` is the effective observation count after decay,\n * useful for UIs that want to render \"strong signal\" vs. \"tentative\".\n */\nexport interface MemoryWorthResult {\n /**\n * The Laplace-smoothed success probability, post-decay, clamped to\n * `[0, 1]`. This is the multiplier PR 4 applies to the base recall score.\n */\n score: number;\n /**\n * Same as `score` conceptually, surfaced separately so telemetry /\n * xray surfaces can report probability independently of whatever final\n * multiplier PR 4 chooses to apply.\n */\n p_success: number;\n /**\n * Effective observation count (`s_eff + f_eff`). With decay enabled this is\n * fractional; without decay it equals `mw_success + mw_fail` exactly.\n * Zero indicates no signal — callers should treat the score as a prior.\n */\n confidence: number;\n}\n\n/**\n * Treat fractional or negative counter inputs as zero. Upstream writers in\n * PR 1 already reject these, but this helper is also called from tests and\n * benchmark seeders that build inputs by hand, so we defend here too.\n */\n/**\n * Upper bound for a plausible counter. `Number.MAX_SAFE_INTEGER` would\n * be technically correct but still overflows the sum `sEff + fEff + 2`\n * when both counters are near the max. A more conservative cap also\n * doubles as a sanity check against clearly-corrupt frontmatter (no\n * single memory should have 10B recorded outcomes), and leaves plenty\n * of headroom for the sum.\n */\nconst MAX_COUNTER = 1e12;\n\n/**\n * Classify a counter into `{ok, value}` for the scorer:\n * - `{ok: true, value}` means the input was absent or a valid non-negative\n * integer within range. Treated as a normal signal.\n * - `{ok: false}` means the caller supplied a value but it was corrupt\n * (negative, NaN, Infinity, non-integer, or absurdly large). The scorer\n * treats the record as corrupted and collapses BOTH counters to the\n * prior — a partial-corruption record (e.g. `mw_success: 10` with\n * `mw_fail: NaN`) must not be read as strong evidence.\n */\nfunction classifyCounter(value: number | undefined): { ok: true; value: number } | { ok: false } {\n // Absent counter is a legitimate \"no data yet\" signal, not corruption.\n if (value === undefined) return { ok: true, value: 0 };\n if (typeof value !== \"number\") return { ok: false };\n if (!Number.isFinite(value)) return { ok: false };\n if (value < 0) return { ok: false };\n // Non-integer counters are refused outright (not floored). Fractional\n // counters can only arise from hand-edited frontmatter or a mis-seeded\n // bench fixture — the PR 1 serializer rejects them on write. Treating\n // `1.9` as `1` would give obviously-corrupt data non-zero confidence and\n // shift the score away from the neutral prior.\n if (!Number.isInteger(value)) return { ok: false };\n // Overflow guard. `mw_success: 1e308` (or anything past `MAX_COUNTER`)\n // would let `sEff + fEff + 2` overflow to `Infinity` and drive the\n // computed score to 0 for symmetric counts — exactly the opposite of\n // the neutral-prior fail-safe contract.\n if (value > MAX_COUNTER) return { ok: false };\n return { ok: true, value };\n}\n\n/**\n * Parse `lastAccessed` into a millisecond timestamp. Any parse failure\n * collapses to `null`, which disables decay rather than throwing.\n */\nfunction parseLastAccessedMs(lastAccessed: string | null | undefined): number | null {\n if (!lastAccessed) return null;\n const parsed = Date.parse(lastAccessed);\n if (!Number.isFinite(parsed)) return null;\n return parsed;\n}\n\n/**\n * Compute the decay multiplier for an observation of age `ageMs` given a\n * `halfLifeMs`. Returns `1` when decay is disabled or age is non-positive\n * (can happen if a test seeds `lastAccessed` slightly in the future).\n */\nfunction decayFactor(ageMs: number, halfLifeMs: number | undefined): number {\n if (typeof halfLifeMs !== \"number\") return 1;\n if (!Number.isFinite(halfLifeMs)) return 1;\n if (halfLifeMs <= 0) return 1;\n if (ageMs <= 0) return 1;\n return Math.pow(2, -ageMs / halfLifeMs);\n}\n\n/**\n * Score a single memory's worth based on outcome history.\n *\n * Returns the neutral prior (`0.5`, `confidence=0`) for uninstrumented\n * memories so the caller can treat \"no data\" and \"data says 50/50\"\n * identically — neither should be penalized.\n */\nexport function computeMemoryWorth(input: ComputeMemoryWorthInput): MemoryWorthResult {\n const sClass = classifyCounter(input.mw_success);\n const fClass = classifyCounter(input.mw_fail);\n // If EITHER counter is corrupt, fail the whole record to the prior. A\n // partially-corrupt record (e.g. `mw_success: 10` with `mw_fail: NaN`)\n // would otherwise read as strong positive evidence — the exact opposite\n // of the documented \"corrupt inputs fail safely\" contract.\n if (!sClass.ok || !fClass.ok) {\n return { score: 0.5, p_success: 0.5, confidence: 0 };\n }\n const rawS = sClass.value;\n const rawF = fClass.value;\n\n const lastAccessedMs = parseLastAccessedMs(input.lastAccessed);\n const nowMs = input.now.getTime();\n // An invalid `now` Date (`new Date(\"bad\")`) would otherwise propagate\n // NaN through `ageMs` → `decayFactor` → score and poison any downstream\n // sort that treats NaN as \"less than everything\". Skip decay in that\n // case — the raw counters are still well-defined.\n const nowUsable = Number.isFinite(nowMs);\n const ageMs =\n !nowUsable || lastAccessedMs === null ? 0 : Math.max(0, nowMs - lastAccessedMs);\n const factor = nowUsable ? decayFactor(ageMs, input.halfLifeMs) : 1;\n\n const sEff = rawS * factor;\n const fEff = rawF * factor;\n\n // Laplace smoothing: Beta(1,1) prior ⇒ (s+1) / (s+f+2).\n // This is equivalent to adding one imaginary success + one imaginary\n // failure before computing the ratio, and guarantees a finite non-zero\n // result even when both counters are 0.\n const pSuccess = (sEff + 1) / (sEff + fEff + 2);\n\n // Clamp defensively — floating-point noise can push (s+1)/(s+f+2) a hair\n // outside [0, 1] when `factor` is very small, and the callers (recall\n // score multiplication) expect a well-formed probability.\n const clamped = Math.max(0, Math.min(1, pSuccess));\n\n return {\n score: clamped,\n p_success: clamped,\n confidence: sEff + fEff,\n };\n}\n"],"mappings":";AA4GA,IAAM,cAAc;AAYpB,SAAS,gBAAgB,OAAwE;AAE/F,MAAI,UAAU,OAAW,QAAO,EAAE,IAAI,MAAM,OAAO,EAAE;AACrD,MAAI,OAAO,UAAU,SAAU,QAAO,EAAE,IAAI,MAAM;AAClD,MAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO,EAAE,IAAI,MAAM;AAChD,MAAI,QAAQ,EAAG,QAAO,EAAE,IAAI,MAAM;AAMlC,MAAI,CAAC,OAAO,UAAU,KAAK,EAAG,QAAO,EAAE,IAAI,MAAM;AAKjD,MAAI,QAAQ,YAAa,QAAO,EAAE,IAAI,MAAM;AAC5C,SAAO,EAAE,IAAI,MAAM,MAAM;AAC3B;AAMA,SAAS,oBAAoB,cAAwD;AACnF,MAAI,CAAC,aAAc,QAAO;AAC1B,QAAM,SAAS,KAAK,MAAM,YAAY;AACtC,MAAI,CAAC,OAAO,SAAS,MAAM,EAAG,QAAO;AACrC,SAAO;AACT;AAOA,SAAS,YAAY,OAAe,YAAwC;AAC1E,MAAI,OAAO,eAAe,SAAU,QAAO;AAC3C,MAAI,CAAC,OAAO,SAAS,UAAU,EAAG,QAAO;AACzC,MAAI,cAAc,EAAG,QAAO;AAC5B,MAAI,SAAS,EAAG,QAAO;AACvB,SAAO,KAAK,IAAI,GAAG,CAAC,QAAQ,UAAU;AACxC;AASO,SAAS,mBAAmB,OAAmD;AACpF,QAAM,SAAS,gBAAgB,MAAM,UAAU;AAC/C,QAAM,SAAS,gBAAgB,MAAM,OAAO;AAK5C,MAAI,CAAC,OAAO,MAAM,CAAC,OAAO,IAAI;AAC5B,WAAO,EAAE,OAAO,KAAK,WAAW,KAAK,YAAY,EAAE;AAAA,EACrD;AACA,QAAM,OAAO,OAAO;AACpB,QAAM,OAAO,OAAO;AAEpB,QAAM,iBAAiB,oBAAoB,MAAM,YAAY;AAC7D,QAAM,QAAQ,MAAM,IAAI,QAAQ;AAKhC,QAAM,YAAY,OAAO,SAAS,KAAK;AACvC,QAAM,QACJ,CAAC,aAAa,mBAAmB,OAAO,IAAI,KAAK,IAAI,GAAG,QAAQ,cAAc;AAChF,QAAM,SAAS,YAAY,YAAY,OAAO,MAAM,UAAU,IAAI;AAElE,QAAM,OAAO,OAAO;AACpB,QAAM,OAAO,OAAO;AAMpB,QAAM,YAAY,OAAO,MAAM,OAAO,OAAO;AAK7C,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC;AAEjD,SAAO;AAAA,IACL,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY,OAAO;AAAA,EACrB;AACF;","names":[]}
@@ -1,11 +1,14 @@
1
1
  import {
2
2
  promoteSemanticRuleFromMemory
3
- } from "./chunk-KWP7T3DP.js";
3
+ } from "./chunk-VDX363PS.js";
4
4
  import {
5
5
  buildResumeBundleFromState,
6
6
  getResumeBundleStatus,
7
7
  recordResumeBundle
8
- } from "./chunk-AYPYCLR7.js";
8
+ } from "./chunk-KUB6JU6H.js";
9
+ import {
10
+ parseXrayCliOptions
11
+ } from "./chunk-PVPWZSSI.js";
9
12
  import {
10
13
  listNamespaces,
11
14
  runBenchmarkRecall,
@@ -16,7 +19,7 @@ import {
16
19
  runOperatorRepair,
17
20
  runOperatorSetup,
18
21
  verifyNamespaces
19
- } from "./chunk-X4WESCKA.js";
22
+ } from "./chunk-B5WXLVDY.js";
20
23
  import {
21
24
  compareVersions
22
25
  } from "./chunk-HL4DB7TO.js";
@@ -25,13 +28,14 @@ import {
25
28
  } from "./chunk-ZPKBYX2F.js";
26
29
  import {
27
30
  RoutingRulesStore,
31
+ expandTildePath,
28
32
  isReplayRole,
29
33
  isReplaySource,
30
34
  normalizeReplaySessionKey,
31
35
  parseIsoOffsetTimestamp,
32
36
  parseIsoTimestamp,
33
37
  validateReplayTurn
34
- } from "./chunk-PAORGQRI.js";
38
+ } from "./chunk-EPQJM2GC.js";
35
39
  import {
36
40
  getUtilityLearningStatus,
37
41
  learnUtilityPromotionWeights
@@ -42,25 +46,18 @@ import {
42
46
  } from "./chunk-3QKK7QOS.js";
43
47
  import {
44
48
  searchVerifiedEpisodes
45
- } from "./chunk-GJQPH5G3.js";
49
+ } from "./chunk-CUPFXL3J.js";
46
50
  import {
47
51
  ThreadingManager
48
52
  } from "./chunk-JRNQ3RNA.js";
49
53
  import {
50
54
  searchVerifiedSemanticRules
51
- } from "./chunk-MYQWXITD.js";
55
+ } from "./chunk-SPI27QT6.js";
52
56
  import {
53
57
  getWorkProductLedgerStatus,
54
58
  recordWorkProductLedgerEntry,
55
59
  searchWorkProductLedgerEntries
56
60
  } from "./chunk-CULXMQJH.js";
57
- import {
58
- readRuntimePolicySnapshot,
59
- sanitizeRuntimePolicyValues
60
- } from "./chunk-EABGC2TL.js";
61
- import {
62
- getObjectiveStateStoreStatus
63
- } from "./chunk-LOBRX7VD.js";
64
61
  import {
65
62
  analyzeSessionIntegrity,
66
63
  applySessionRepair,
@@ -71,11 +68,21 @@ import {
71
68
  PLUGIN_ID
72
69
  } from "./chunk-U66YHYC7.js";
73
70
  import {
74
- rescoreMemoryImportance
75
- } from "./chunk-J4IYOZZ5.js";
71
+ readRuntimePolicySnapshot,
72
+ sanitizeRuntimePolicyValues
73
+ } from "./chunk-EABGC2TL.js";
74
+ import {
75
+ getObjectiveStateStoreStatus
76
+ } from "./chunk-LOBRX7VD.js";
76
77
  import {
77
78
  searchHarmonicRetrieval
78
- } from "./chunk-AAI7JARD.js";
79
+ } from "./chunk-HMDCOMYU.js";
80
+ import {
81
+ rescoreMemoryImportance
82
+ } from "./chunk-JXS5PDQ7.js";
83
+ import {
84
+ launchProcess
85
+ } from "./chunk-LK6SGL53.js";
79
86
  import {
80
87
  loadPersistedNativeKnowledgeChunks
81
88
  } from "./chunk-7SEAZFFB.js";
@@ -88,24 +95,21 @@ import {
88
95
  runEvalStoredBaselineCiGate,
89
96
  validateEvalBenchmarkPack
90
97
  } from "./chunk-K6WK37A6.js";
91
- import {
92
- launchProcess
93
- } from "./chunk-LK6SGL53.js";
94
- import {
95
- applyCommitmentLedgerLifecycle,
96
- getCommitmentLedgerStatus,
97
- recordCommitmentLedgerEntry,
98
- transitionCommitmentLedgerEntryState
99
- } from "./chunk-FYIYMQ5N.js";
100
98
  import {
101
99
  parseConfig
102
- } from "./chunk-OJFGVJS6.js";
100
+ } from "./chunk-BK2EFTE2.js";
103
101
  import {
104
102
  getCueAnchorStoreStatus
105
103
  } from "./chunk-C6QPK5GG.js";
106
104
  import {
107
105
  analyzeGraphHealth
108
106
  } from "./chunk-C2EFFULQ.js";
107
+ import {
108
+ applyCommitmentLedgerLifecycle,
109
+ getCommitmentLedgerStatus,
110
+ recordCommitmentLedgerEntry,
111
+ transitionCommitmentLedgerEntryState
112
+ } from "./chunk-FYIYMQ5N.js";
109
113
  import {
110
114
  chunkContent
111
115
  } from "./chunk-4WMCPJWX.js";
@@ -114,38 +118,43 @@ import {
114
118
  } from "./chunk-NGAVDO7E.js";
115
119
  import {
116
120
  EngramAccessHttpServer
117
- } from "./chunk-PMB3WGDL.js";
121
+ } from "./chunk-DFTTJYSO.js";
118
122
  import {
119
123
  EngramMcpServer
120
- } from "./chunk-NSB3WSYS.js";
124
+ } from "./chunk-HK3FGIEW.js";
121
125
  import {
122
126
  resolveHomeDir
123
127
  } from "./chunk-MARWOCVP.js";
124
128
  import {
125
129
  EngramAccessService,
126
130
  WorkStorage
127
- } from "./chunk-V7XCAHIB.js";
131
+ } from "./chunk-GKFXUTJ2.js";
128
132
  import {
129
- getTrustZoneStoreStatus,
130
- promoteTrustZoneRecord,
131
- seedTrustZoneDemoDataset
132
- } from "./chunk-EQINRHYR.js";
133
+ parseRecallExplainFormat,
134
+ renderRecallExplain,
135
+ renderXray
136
+ } from "./chunk-ZAIM4TUE.js";
133
137
  import {
134
138
  listMemoryGovernanceRuns,
135
139
  readMemoryGovernanceRunArtifact,
136
140
  restoreMemoryGovernanceRun,
137
141
  runMemoryGovernance
138
- } from "./chunk-POBPGDWI.js";
142
+ } from "./chunk-3OGMS3PE.js";
143
+ import {
144
+ getTrustZoneStoreStatus,
145
+ promoteTrustZoneRecord,
146
+ seedTrustZoneDemoDataset
147
+ } from "./chunk-EQINRHYR.js";
139
148
  import {
140
149
  selectRouteRule,
141
150
  validateRouteTarget
142
- } from "./chunk-QNJMBKFK.js";
151
+ } from "./chunk-2LGMW3DJ.js";
143
152
  import {
144
153
  getCausalTrajectoryStoreStatus
145
- } from "./chunk-4NRAJUDS.js";
154
+ } from "./chunk-RBBWYEFJ.js";
146
155
  import {
147
156
  StorageManager
148
- } from "./chunk-POMSFKTB.js";
157
+ } from "./chunk-F5VP6YCB.js";
149
158
  import {
150
159
  MEMORY_LIFECYCLE_EVENT_SORT_ORDER,
151
160
  buildLifecycleEventsForMemory,
@@ -3785,13 +3794,6 @@ function isWorkTaskPriority(value) {
3785
3794
  function isWorkProjectStatus(value) {
3786
3795
  return value === "active" || value === "on_hold" || value === "completed" || value === "archived";
3787
3796
  }
3788
- function expandTildePath(p) {
3789
- if (p === "~") return resolveHomeDir();
3790
- if (p.startsWith("~/") || p.startsWith("~\\")) {
3791
- return path19.join(resolveHomeDir(), p.slice(2));
3792
- }
3793
- return p;
3794
- }
3795
3797
  async function runTrainingExportCliCommand(opts) {
3796
3798
  const expandedMemoryDir = expandTildePath(opts.memoryDir);
3797
3799
  const expandedOutput = expandTildePath(opts.output);
@@ -4121,7 +4123,7 @@ async function runSemanticRulePromoteCliCommand(options) {
4121
4123
  });
4122
4124
  }
4123
4125
  async function runCompoundingPromoteCliCommand(options) {
4124
- const { CompoundingEngine } = await import("./engine-X7X3AAG3.js");
4126
+ const { CompoundingEngine } = await import("./engine-F3GOXGE5.js");
4125
4127
  const config = parseConfig({
4126
4128
  memoryDir: options.memoryDir,
4127
4129
  qmdEnabled: false,
@@ -5531,6 +5533,68 @@ function registerCli(api, orchestrator) {
5531
5533
  }
5532
5534
  }
5533
5535
  });
5536
+ cmd.command("judge-stats").description(
5537
+ "Show extraction-judge verdict stats from the observation ledger"
5538
+ ).option("--since <iso>", "Start timestamp (inclusive, ISO-8601)").option("--until <iso>", "End timestamp (exclusive, ISO-8601)").option("--json", "Emit machine-readable JSON only").action(async (...args) => {
5539
+ const options = args[0] ?? {};
5540
+ const sinceRaw = typeof options.since === "string" ? options.since : void 0;
5541
+ const untilRaw = typeof options.until === "string" ? options.until : void 0;
5542
+ const sinceMs = sinceRaw ? Date.parse(sinceRaw) : void 0;
5543
+ const untilMs = untilRaw ? Date.parse(untilRaw) : void 0;
5544
+ if (sinceRaw && !Number.isFinite(sinceMs)) {
5545
+ throw new Error(
5546
+ `Invalid --since value: ${sinceRaw}. Use ISO-8601, e.g. 2026-04-01T00:00:00Z`
5547
+ );
5548
+ }
5549
+ if (untilRaw && !Number.isFinite(untilMs)) {
5550
+ throw new Error(
5551
+ `Invalid --until value: ${untilRaw}. Use ISO-8601, e.g. 2026-04-15T00:00:00Z`
5552
+ );
5553
+ }
5554
+ const { readJudgeVerdictStats } = await import("./extraction-judge-telemetry.js");
5555
+ const stats = await readJudgeVerdictStats(
5556
+ orchestrator.config.memoryDir,
5557
+ {
5558
+ ...typeof sinceMs === "number" && Number.isFinite(sinceMs) ? { sinceMs } : {},
5559
+ ...typeof untilMs === "number" && Number.isFinite(untilMs) ? { untilMs } : {}
5560
+ }
5561
+ );
5562
+ if (options.json === true) {
5563
+ console.log(JSON.stringify(stats, null, 2));
5564
+ return;
5565
+ }
5566
+ console.log("=== Extraction Judge Verdict Stats ===\n");
5567
+ console.log(`Total verdicts: ${stats.total}`);
5568
+ if (stats.total === 0) {
5569
+ if (!orchestrator.config.extractionJudgeTelemetryEnabled) {
5570
+ console.log(
5571
+ "\nNote: extractionJudgeTelemetryEnabled is OFF. Enable it in plugin config to collect verdict telemetry."
5572
+ );
5573
+ }
5574
+ return;
5575
+ }
5576
+ console.log(
5577
+ ` accept: ${stats.accept} (${(stats.accept / stats.total * 100).toFixed(1)}%)`
5578
+ );
5579
+ console.log(
5580
+ ` reject: ${stats.reject} (${(stats.reject / stats.total * 100).toFixed(1)}%)`
5581
+ );
5582
+ console.log(
5583
+ ` defer: ${stats.defer} (${(stats.deferRate * 100).toFixed(1)}%)`
5584
+ );
5585
+ if (stats.deferCapTriggered > 0) {
5586
+ console.log(
5587
+ ` of which ${stats.deferCapTriggered} cap-rejected (defer \u2192 reject)`
5588
+ );
5589
+ }
5590
+ console.log(` mean elapsed: ${stats.meanElapsedMs.toFixed(1)} ms`);
5591
+ if (stats.firstTs && stats.lastTs) {
5592
+ console.log(` window: ${stats.firstTs} \u2026 ${stats.lastTs}`);
5593
+ }
5594
+ if (stats.malformed > 0) {
5595
+ console.log(` malformed rows skipped: ${stats.malformed}`);
5596
+ }
5597
+ });
5534
5598
  cmd.command("setup").description("Validate config, scaffold directories, and print first-run next steps").option("--install-capture-instructions", "Create workspace MEMORY.md when explicit capture is enabled and missing").option("--preview-capture-instructions", "Print the managed explicit-capture instruction snippet without writing files").option("--remove-capture-instructions", "Remove the managed explicit-capture instruction snippet from MEMORY.md").option("--json", "Emit machine-readable JSON only").action(async (...args) => {
5535
5599
  const options = args[0] ?? {};
5536
5600
  const captureInstructionsMode = options.removeCaptureInstructions === true ? "remove" : options.previewCaptureInstructions === true ? "preview" : options.installCaptureInstructions === true ? "install" : void 0;
@@ -5950,6 +6014,59 @@ function registerCli(api, orchestrator) {
5950
6014
  }
5951
6015
  if (!reportHasMachineReadableOutput(options)) console.log("OK");
5952
6016
  });
6017
+ cmd.command("recall-explain").description(
6018
+ "Show tier explain for the most recent recall (or a specific session)"
6019
+ ).option(
6020
+ "--session <key>",
6021
+ "Session key to look up; omit to use the most recent snapshot"
6022
+ ).option("--format <fmt>", "Output format: text (default) or json", "text").action(async (...args) => {
6023
+ const options = args[0] ?? {};
6024
+ const format = parseRecallExplainFormat(options.format);
6025
+ await orchestrator.lastRecall.load();
6026
+ const sessionKey = typeof options.session === "string" && options.session.length > 0 ? options.session : void 0;
6027
+ let snapshot = null;
6028
+ try {
6029
+ snapshot = sessionKey ? orchestrator.lastRecall.get(sessionKey) : orchestrator.lastRecall.getMostRecent();
6030
+ } catch {
6031
+ snapshot = null;
6032
+ }
6033
+ console.log(renderRecallExplain(snapshot, format));
6034
+ });
6035
+ cmd.command("xray").description(
6036
+ "Run a recall with X-ray capture and print the unified snapshot (tier + audit + MMR + filters). Part of #570."
6037
+ ).argument("<query>", "Query to recall against").option(
6038
+ "--format <fmt>",
6039
+ "Output format: text (default), markdown, or json",
6040
+ "text"
6041
+ ).option(
6042
+ "--budget <chars>",
6043
+ "Override recall character budget for this call (positive integer)"
6044
+ ).option(
6045
+ "--namespace <ns>",
6046
+ "Namespace to scope the recall to (defaults to configured namespace)"
6047
+ ).option(
6048
+ "--out <path>",
6049
+ "Write the rendered snapshot to a file instead of stdout"
6050
+ ).action(async (...args) => {
6051
+ const parsed = parseXrayCliOptions(
6052
+ args[0],
6053
+ args[1] ?? {}
6054
+ );
6055
+ const xrayService = new EngramAccessService(orchestrator);
6056
+ const response = await xrayService.recallXray({
6057
+ query: parsed.query,
6058
+ ...parsed.namespace ? { namespace: parsed.namespace } : {},
6059
+ ...parsed.budget !== void 0 ? { budget: parsed.budget } : {}
6060
+ });
6061
+ const snapshot = response.snapshotFound ? response.snapshot ?? null : null;
6062
+ const rendered = renderXray(snapshot, parsed.format);
6063
+ if (parsed.outPath) {
6064
+ const { writeFile: fsWriteFile } = await import("fs/promises");
6065
+ await fsWriteFile(expandTildePath(parsed.outPath), rendered, "utf8");
6066
+ } else {
6067
+ console.log(rendered);
6068
+ }
6069
+ });
5953
6070
  cmd.command("benchmark-validate").description("Validate a benchmark manifest file or pack directory without importing it").argument("<path>", "Path to a benchmark manifest JSON file or a directory with manifest.json").action(async (...args) => {
5954
6071
  const inputPath = args[0];
5955
6072
  const summary = await runBenchmarkValidateCliCommand({
@@ -7336,6 +7453,36 @@ Clusters found: ${result.clustersFound}`);
7336
7453
  Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=${result.memoriesConsolidated}, archived=${result.memoriesArchived}, errors=${result.errors}`
7337
7454
  );
7338
7455
  });
7456
+ cmd.command("consolidate-undo <target>").description(
7457
+ "Undo a consolidation: restore source memories from their derived_from snapshots and archive the target"
7458
+ ).option("--dry-run", "Show the restore plan without modifying files").action(async (...args) => {
7459
+ const rawTarget = typeof args[0] === "string" ? args[0] : "";
7460
+ const options = args[1] ?? {};
7461
+ const dryRun = options.dryRun === true;
7462
+ if (!rawTarget) {
7463
+ console.error("consolidate-undo: missing <target> argument");
7464
+ process.exitCode = 1;
7465
+ return;
7466
+ }
7467
+ const expandedTarget = expandTildePath(rawTarget);
7468
+ const targetPath = path19.isAbsolute(expandedTarget) ? expandedTarget : path19.join(orchestrator.config.memoryDir, expandedTarget);
7469
+ const { runConsolidationUndo, formatConsolidationUndoResult } = await import("./consolidation-undo.js");
7470
+ const result = await runConsolidationUndo({
7471
+ storage: orchestrator.storage,
7472
+ memoryDir: orchestrator.config.memoryDir,
7473
+ targetPath,
7474
+ versioning: {
7475
+ enabled: orchestrator.config.versioningEnabled,
7476
+ maxVersionsPerPage: orchestrator.config.versioningMaxPerPage,
7477
+ sidecarDir: orchestrator.config.versioningSidecarDir
7478
+ },
7479
+ dryRun
7480
+ });
7481
+ console.log(formatConsolidationUndoResult(result));
7482
+ if (result.error) {
7483
+ process.exitCode = 1;
7484
+ }
7485
+ });
7339
7486
  cmd.command("questions").description("List open questions from memory extraction").option("-a, --all", "Show all questions including resolved").action(async (...args) => {
7340
7487
  const options = args[0] ?? {};
7341
7488
  const showAll = options.all === true;
@@ -7732,6 +7879,103 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
7732
7879
  }
7733
7880
  console.log(orchestrator.summarizer.formatForRecall(summaries, summaries.length));
7734
7881
  });
7882
+ const reviewCmd = cmd.command("review").description("Manage contradiction review queue");
7883
+ reviewCmd.command("list").description("List contradiction review items").option("--filter <type>", "Filter: all, unresolved, contradicts, independent, duplicates, needs-user", "unresolved").option("--namespace <ns>", "Filter by namespace").option("--limit <n>", "Max items (default 50)", "50").action(async (...args) => {
7884
+ const options = args[0] ?? {};
7885
+ const filter = options.filter ?? "unresolved";
7886
+ const validFilters = ["all", "unresolved", "contradicts", "independent", "duplicates", "needs-user"];
7887
+ if (!validFilters.includes(filter)) {
7888
+ console.error(`Invalid filter: ${filter}. Must be one of: ${validFilters.join(", ")}`);
7889
+ process.exit(1);
7890
+ }
7891
+ const limit = parseInt(options.limit ?? "50", 10);
7892
+ const { listPairs } = await import("./contradiction-review-WIUBAR52.js");
7893
+ const result = listPairs(orchestrator.config.memoryDir, {
7894
+ filter,
7895
+ namespace: options.namespace,
7896
+ limit: Number.isFinite(limit) ? limit : 50
7897
+ });
7898
+ if (result.pairs.length === 0) {
7899
+ console.log("No review items found.");
7900
+ return;
7901
+ }
7902
+ console.log(`Found ${result.total} item(s) (${result.durationMs}ms):
7903
+ `);
7904
+ for (const pair of result.pairs) {
7905
+ console.log(` [${pair.verdict}] ${pair.pairId}`);
7906
+ console.log(` Memories: ${pair.memoryIds.join(", ")}`);
7907
+ console.log(` Rationale: ${pair.rationale}`);
7908
+ console.log(` Confidence: ${pair.confidence.toFixed(2)}`);
7909
+ if (pair.resolution) console.log(` Resolution: ${pair.resolution}`);
7910
+ console.log();
7911
+ }
7912
+ });
7913
+ reviewCmd.command("show <pairId>").description("Show details of a contradiction pair").action(async (...args) => {
7914
+ const pairId = typeof args[0] === "string" ? args[0] : "";
7915
+ if (!pairId) {
7916
+ console.error("pairId is required");
7917
+ process.exit(1);
7918
+ }
7919
+ const { readPair } = await import("./contradiction-review-WIUBAR52.js");
7920
+ const pair = readPair(orchestrator.config.memoryDir, pairId);
7921
+ if (!pair) {
7922
+ console.error(`Pair ${pairId} not found.`);
7923
+ process.exit(1);
7924
+ }
7925
+ console.log(JSON.stringify(pair, null, 2));
7926
+ });
7927
+ reviewCmd.command("resolve <pairId>").description("Resolve a contradiction pair").requiredOption("--verb <verb>", "Resolution verb: keep-a, keep-b, merge, both-valid, needs-more-context").action(async (...args) => {
7928
+ const pairId = typeof args[0] === "string" ? args[0] : "";
7929
+ const cmdOpts = args[1] ?? {};
7930
+ if (!pairId) {
7931
+ console.error("pairId is required");
7932
+ process.exit(1);
7933
+ }
7934
+ const verb = cmdOpts.verb;
7935
+ if (!verb) {
7936
+ console.error("--verb is required. Must be one of: keep-a, keep-b, merge, both-valid, needs-more-context");
7937
+ process.exit(1);
7938
+ }
7939
+ const { isValidResolutionVerb, executeResolution } = await import("./resolution-QBTDHTG7.js");
7940
+ if (!isValidResolutionVerb(verb)) {
7941
+ console.error(`Invalid verb: ${verb}. Must be one of: keep-a, keep-b, merge, both-valid, needs-more-context`);
7942
+ process.exit(1);
7943
+ }
7944
+ const result = await executeResolution(orchestrator.config.memoryDir, orchestrator.storage, pairId, verb);
7945
+ console.log(result.message);
7946
+ if (result.affectedIds.length > 0) {
7947
+ console.log(`Affected: ${result.affectedIds.join(", ")}`);
7948
+ }
7949
+ });
7950
+ reviewCmd.command("scan").description("Run an on-demand contradiction scan").option("--namespace <ns>", "Namespace to scan").action(async (...args) => {
7951
+ const options = args[0] ?? {};
7952
+ const { runContradictionScan } = await import("./contradiction-scan-E3GJTI4F.js");
7953
+ console.log("Running contradiction scan...");
7954
+ const result = await runContradictionScan({
7955
+ storage: orchestrator.storage,
7956
+ config: orchestrator.config,
7957
+ memoryDir: orchestrator.config.memoryDir,
7958
+ embeddingLookupFactory: (storage) => {
7959
+ if (!orchestrator.config.embeddingFallbackEnabled) return void 0;
7960
+ return async (content, limit) => {
7961
+ try {
7962
+ return await orchestrator.semanticDedupLookup(content, limit, storage);
7963
+ } catch {
7964
+ return [];
7965
+ }
7966
+ };
7967
+ },
7968
+ localLlm: orchestrator.localLlm ?? null,
7969
+ fallbackLlm: orchestrator.fastGatewayLlm ?? null,
7970
+ namespace: options.namespace
7971
+ });
7972
+ console.log(`Scan complete in ${result.elapsedMs}ms:`);
7973
+ console.log(` Scanned: ${result.scanned} memories`);
7974
+ console.log(` Candidates: ${result.candidates} pairs`);
7975
+ console.log(` Judged: ${result.judged}`);
7976
+ console.log(` Queued: ${result.queued}`);
7977
+ console.log(` Cooled down: ${result.cooledDown}`);
7978
+ });
7735
7979
  },
7736
7980
  { commands: ["engram"] }
7737
7981
  );
@@ -7854,4 +8098,4 @@ export {
7854
8098
  resolveMemoryDirForNamespace,
7855
8099
  registerCli
7856
8100
  };
7857
- //# sourceMappingURL=chunk-YFYL2SIJ.js.map
8101
+ //# sourceMappingURL=chunk-INXV5JBT.js.map