@remnic/core 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. package/dist/access-audit.d.ts +56 -0
  2. package/dist/access-audit.js +9 -0
  3. package/dist/access-cli.js +70 -53
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +16 -9
  6. package/dist/access-http.js +26 -18
  7. package/dist/access-mcp.d.ts +16 -9
  8. package/dist/access-mcp.js +30 -8
  9. package/dist/access-schema.d.ts +124 -33
  10. package/dist/access-schema.js +5 -1
  11. package/dist/{access-service-HmO1Trrx.d.ts → access-service-Br8ZydTK.d.ts} +158 -63
  12. package/dist/access-service.d.ts +13 -6
  13. package/dist/access-service.js +23 -14
  14. package/dist/bootstrap.d.ts +6 -3
  15. package/dist/briefing.d.ts +1 -0
  16. package/dist/briefing.js +8 -6
  17. package/dist/buffer-surprise-report.d.ts +70 -0
  18. package/dist/buffer-surprise-report.js +7 -0
  19. package/dist/buffer-surprise-report.js.map +1 -0
  20. package/dist/buffer-surprise.d.ts +98 -0
  21. package/dist/buffer-surprise.js +11 -0
  22. package/dist/buffer-surprise.js.map +1 -0
  23. package/dist/buffer.d.ts +100 -2
  24. package/dist/buffer.js +1 -1
  25. package/dist/calibration.js +6 -6
  26. package/dist/causal-behavior.js +4 -4
  27. package/dist/causal-chain.js +2 -2
  28. package/dist/causal-consolidation.js +19 -18
  29. package/dist/causal-consolidation.js.map +1 -1
  30. package/dist/causal-retrieval.js +4 -4
  31. package/dist/causal-trajectory.js +1 -1
  32. package/dist/{chunk-QNJMBKFK.js → chunk-2LGMW3DJ.js} +3 -2
  33. package/dist/chunk-2LGMW3DJ.js.map +1 -0
  34. package/dist/{chunk-QDYXG4CS.js → chunk-3FPTCC3Z.js} +4 -3
  35. package/dist/chunk-3FPTCC3Z.js.map +1 -0
  36. package/dist/chunk-3GPTTA4J.js +57 -0
  37. package/dist/chunk-3GPTTA4J.js.map +1 -0
  38. package/dist/{chunk-ITRLGI2T.js → chunk-3OGMS3PE.js} +2 -2
  39. package/dist/{chunk-DEPL3635.js → chunk-3YGHKTBF.js} +1446 -196
  40. package/dist/chunk-3YGHKTBF.js.map +1 -0
  41. package/dist/{chunk-BLKTA7MM.js → chunk-4HQS2HPX.js} +54 -21
  42. package/dist/chunk-4HQS2HPX.js.map +1 -0
  43. package/dist/chunk-54V4BZWP.js +139 -0
  44. package/dist/chunk-54V4BZWP.js.map +1 -0
  45. package/dist/chunk-5JRF2PZA.js +67 -0
  46. package/dist/chunk-5JRF2PZA.js.map +1 -0
  47. package/dist/chunk-64NJRYU2.js +332 -0
  48. package/dist/chunk-64NJRYU2.js.map +1 -0
  49. package/dist/{chunk-OIT5QGG4.js → chunk-6AUUAZEX.js} +72 -2
  50. package/dist/chunk-6AUUAZEX.js.map +1 -0
  51. package/dist/{chunk-3QHL5ABG.js → chunk-6YJHX2DL.js} +191 -10
  52. package/dist/chunk-6YJHX2DL.js.map +1 -0
  53. package/dist/chunk-AJU4PJGY.js +126 -0
  54. package/dist/chunk-AJU4PJGY.js.map +1 -0
  55. package/dist/chunk-ASAITVLA.js +64 -0
  56. package/dist/chunk-ASAITVLA.js.map +1 -0
  57. package/dist/{chunk-44ICJRF3.js → chunk-AYXIPSZO.js} +5 -5
  58. package/dist/{chunk-MBJHSA7F.js → chunk-BECYBZLX.js} +265 -20
  59. package/dist/chunk-BECYBZLX.js.map +1 -0
  60. package/dist/chunk-C4SQJZAF.js +486 -0
  61. package/dist/chunk-C4SQJZAF.js.map +1 -0
  62. package/dist/{chunk-6UJ47TVX.js → chunk-CUPFXL3J.js} +2 -2
  63. package/dist/chunk-DF3RVK3X.js +119 -0
  64. package/dist/chunk-DF3RVK3X.js.map +1 -0
  65. package/dist/{chunk-N42IWANG.js → chunk-DG6YMRDC.js} +3 -3
  66. package/dist/chunk-DGVM5SFL.js +69 -0
  67. package/dist/chunk-DGVM5SFL.js.map +1 -0
  68. package/dist/{chunk-3SV6CQHO.js → chunk-DIXB44VE.js} +102 -66
  69. package/dist/chunk-DIXB44VE.js.map +1 -0
  70. package/dist/chunk-EIR5VLIH.js +90 -0
  71. package/dist/chunk-EIR5VLIH.js.map +1 -0
  72. package/dist/{chunk-GV6NLQ4X.js → chunk-F5VP6YCB.js} +374 -16
  73. package/dist/chunk-F5VP6YCB.js.map +1 -0
  74. package/dist/{chunk-6ZH4TU6I.js → chunk-FAAFWE4G.js} +2 -1
  75. package/dist/chunk-FAAFWE4G.js.map +1 -0
  76. package/dist/{chunk-7WQ6SLIE.js → chunk-FVA6TGI3.js} +2 -2
  77. package/dist/{chunk-PAORGQRI.js → chunk-GA5P7RST.js} +37 -23
  78. package/dist/chunk-GA5P7RST.js.map +1 -0
  79. package/dist/chunk-GDFS42HT.js +206 -0
  80. package/dist/chunk-GDFS42HT.js.map +1 -0
  81. package/dist/chunk-IISBCCWR.js +52 -0
  82. package/dist/chunk-IISBCCWR.js.map +1 -0
  83. package/dist/chunk-JBMSGZEQ.js +441 -0
  84. package/dist/chunk-JBMSGZEQ.js.map +1 -0
  85. package/dist/{chunk-J4IYOZZ5.js → chunk-JXS5PDQ7.js} +3 -1
  86. package/dist/chunk-JXS5PDQ7.js.map +1 -0
  87. package/dist/chunk-KVBLZUKV.js +173 -0
  88. package/dist/chunk-KVBLZUKV.js.map +1 -0
  89. package/dist/{chunk-4LACOVZX.js → chunk-L7IXWRYE.js} +10 -5
  90. package/dist/chunk-L7IXWRYE.js.map +1 -0
  91. package/dist/chunk-LBLXEFWK.js +51 -0
  92. package/dist/chunk-LBLXEFWK.js.map +1 -0
  93. package/dist/{chunk-WBSAYXVI.js → chunk-LOIMBRDE.js} +201 -45
  94. package/dist/chunk-LOIMBRDE.js.map +1 -0
  95. package/dist/{chunk-3WHVNEN7.js → chunk-LTCGGW2D.js} +1 -1
  96. package/dist/chunk-LTCGGW2D.js.map +1 -0
  97. package/dist/{chunk-ZVBB3T7V.js → chunk-NBVAS5MT.js} +25 -23
  98. package/dist/chunk-NBVAS5MT.js.map +1 -0
  99. package/dist/{chunk-UEYA6UC7.js → chunk-NZLQTHS5.js} +25 -2
  100. package/dist/chunk-NZLQTHS5.js.map +1 -0
  101. package/dist/{chunk-NQEVYWX6.js → chunk-OC5OXUQ4.js} +211 -7
  102. package/dist/chunk-OC5OXUQ4.js.map +1 -0
  103. package/dist/{chunk-LK6SGL53.js → chunk-OR64ZGRZ.js} +3 -2
  104. package/dist/chunk-OR64ZGRZ.js.map +1 -0
  105. package/dist/{chunk-SYUK3VLY.js → chunk-PVICZTKG.js} +117 -5
  106. package/dist/chunk-PVICZTKG.js.map +1 -0
  107. package/dist/chunk-PVPWZSSI.js +37 -0
  108. package/dist/chunk-PVPWZSSI.js.map +1 -0
  109. package/dist/{chunk-JL2PU6AI.js → chunk-R2XRID2N.js} +2 -2
  110. package/dist/{chunk-4NRAJUDS.js → chunk-RBBWYEFJ.js} +1 -1
  111. package/dist/chunk-RFYAYKTD.js +146 -0
  112. package/dist/chunk-RFYAYKTD.js.map +1 -0
  113. package/dist/chunk-SOBJ6NEY.js +18 -0
  114. package/dist/chunk-SOBJ6NEY.js.map +1 -0
  115. package/dist/{chunk-JIU55F3X.js → chunk-SPI27QT6.js} +2 -2
  116. package/dist/{chunk-MVTHXUBX.js → chunk-STGWEHYR.js} +479 -20
  117. package/dist/chunk-STGWEHYR.js.map +1 -0
  118. package/dist/{chunk-6LX5ORAS.js → chunk-TMYO7B5P.js} +4 -4
  119. package/dist/chunk-TVVEYCNW.js +65 -0
  120. package/dist/chunk-TVVEYCNW.js.map +1 -0
  121. package/dist/chunk-ULYOGL6R.js +322 -0
  122. package/dist/chunk-ULYOGL6R.js.map +1 -0
  123. package/dist/{chunk-37UIFYWO.js → chunk-UWB5LMWY.js} +108 -9
  124. package/dist/chunk-UWB5LMWY.js.map +1 -0
  125. package/dist/{chunk-47UU5PU2.js → chunk-VBVG2M5G.js} +18 -3
  126. package/dist/chunk-VBVG2M5G.js.map +1 -0
  127. package/dist/{chunk-7ECD5ATE.js → chunk-VDX363PS.js} +2 -2
  128. package/dist/{chunk-O5ETUNBT.js → chunk-VTU2B4VF.js} +7 -3
  129. package/dist/chunk-VTU2B4VF.js.map +1 -0
  130. package/dist/{chunk-MTLYEMJB.js → chunk-WCLICCGB.js} +18 -3
  131. package/dist/chunk-WCLICCGB.js.map +1 -0
  132. package/dist/chunk-X6GF3FX2.js +26 -0
  133. package/dist/chunk-X6GF3FX2.js.map +1 -0
  134. package/dist/{chunk-3QFQGRHO.js → chunk-XMHBH5H6.js} +4 -4
  135. package/dist/{chunk-DHHP2Z4X.js → chunk-XXVWLXSG.js} +2 -2
  136. package/dist/{chunk-XZ2TIKGC.js → chunk-Y7R2XJ5Q.js} +25 -9
  137. package/dist/chunk-Y7R2XJ5Q.js.map +1 -0
  138. package/dist/{chunk-ALXMCZEU.js → chunk-Z2E7VW55.js} +6 -3
  139. package/dist/chunk-Z2E7VW55.js.map +1 -0
  140. package/dist/chunk-ZAIM4TUE.js +488 -0
  141. package/dist/chunk-ZAIM4TUE.js.map +1 -0
  142. package/dist/chunk-ZZTOURJI.js +91 -0
  143. package/dist/chunk-ZZTOURJI.js.map +1 -0
  144. package/dist/{cli-BneVIEvh.d.ts → cli-BkeRaYfk.d.ts} +2 -2
  145. package/dist/cli.d.ts +13 -6
  146. package/dist/cli.js +42 -31
  147. package/dist/config.js +2 -2
  148. package/dist/consolidation-operator.d.ts +41 -0
  149. package/dist/consolidation-operator.js +11 -0
  150. package/dist/consolidation-operator.js.map +1 -0
  151. package/dist/consolidation-provenance-check.d.ts +68 -0
  152. package/dist/consolidation-provenance-check.js +9 -0
  153. package/dist/consolidation-provenance-check.js.map +1 -0
  154. package/dist/consolidation-undo.d.ts +123 -0
  155. package/dist/consolidation-undo.js +426 -0
  156. package/dist/consolidation-undo.js.map +1 -0
  157. package/dist/{contradiction-scan-GR33PONM.js → contradiction-scan-E3GJTI4F.js} +43 -7
  158. package/dist/contradiction-scan-E3GJTI4F.js.map +1 -0
  159. package/dist/cross-namespace-budget.d.ts +133 -0
  160. package/dist/cross-namespace-budget.js +9 -0
  161. package/dist/cross-namespace-budget.js.map +1 -0
  162. package/dist/direct-answer-wiring.js +5 -70
  163. package/dist/direct-answer-wiring.js.map +1 -1
  164. package/dist/embedding-fallback.js +2 -1
  165. package/dist/{engine-5TIQBYZR.js → engine-72LSIWQP.js} +8 -7
  166. package/dist/engine-72LSIWQP.js.map +1 -0
  167. package/dist/entity-retrieval.d.ts +1 -0
  168. package/dist/entity-retrieval.js +7 -6
  169. package/dist/explicit-capture.d.ts +6 -3
  170. package/dist/explicit-capture.js +2 -2
  171. package/dist/extraction-judge-telemetry.d.ts +113 -0
  172. package/dist/extraction-judge-telemetry.js +14 -0
  173. package/dist/extraction-judge-telemetry.js.map +1 -0
  174. package/dist/extraction-judge-training.d.ts +85 -0
  175. package/dist/extraction-judge-training.js +16 -0
  176. package/dist/extraction-judge-training.js.map +1 -0
  177. package/dist/extraction-judge.d.ts +124 -2
  178. package/dist/extraction-judge.js +11 -1
  179. package/dist/extraction.js +10 -9
  180. package/dist/fallback-llm.js +3 -3
  181. package/dist/graph-recall.d.ts +100 -0
  182. package/dist/graph-recall.js +8 -0
  183. package/dist/graph-recall.js.map +1 -0
  184. package/dist/graph-retrieval.d.ts +271 -0
  185. package/dist/graph-retrieval.js +21 -0
  186. package/dist/graph-retrieval.js.map +1 -0
  187. package/dist/importance.js +1 -1
  188. package/dist/index.d.ts +585 -20
  189. package/dist/index.js +542 -344
  190. package/dist/index.js.map +1 -1
  191. package/dist/local-llm.js +2 -2
  192. package/dist/memory-worth-bench.d.ts +51 -0
  193. package/dist/memory-worth-bench.js +131 -0
  194. package/dist/memory-worth-bench.js.map +1 -0
  195. package/dist/memory-worth-filter.d.ts +128 -0
  196. package/dist/memory-worth-filter.js +10 -0
  197. package/dist/memory-worth-filter.js.map +1 -0
  198. package/dist/memory-worth-outcomes.d.ts +118 -0
  199. package/dist/memory-worth-outcomes.js +9 -0
  200. package/dist/memory-worth-outcomes.js.map +1 -0
  201. package/dist/memory-worth.d.ts +102 -0
  202. package/dist/memory-worth.js +7 -0
  203. package/dist/memory-worth.js.map +1 -0
  204. package/dist/operator-toolkit.d.ts +40 -1
  205. package/dist/operator-toolkit.js +25 -16
  206. package/dist/{orchestrator-DRYA6_lW.d.ts → orchestrator-CmJ-NTdJ.d.ts} +233 -8
  207. package/dist/orchestrator.d.ts +6 -3
  208. package/dist/orchestrator.js +54 -44
  209. package/dist/page-versioning.d.ts +12 -1
  210. package/dist/page-versioning.js +5 -3
  211. package/dist/{port-C1GZFv8h.d.ts → port-BADbLZU5.d.ts} +2 -2
  212. package/dist/qmd-recall-cache.d.ts +1 -1
  213. package/dist/qmd.d.ts +5 -3
  214. package/dist/qmd.js +3 -3
  215. package/dist/reasoning-trace-recall.d.ts +90 -0
  216. package/dist/reasoning-trace-recall.js +13 -0
  217. package/dist/reasoning-trace-recall.js.map +1 -0
  218. package/dist/reasoning-trace-types.d.ts +54 -0
  219. package/dist/reasoning-trace-types.js +17 -0
  220. package/dist/reasoning-trace-types.js.map +1 -0
  221. package/dist/recall-audit-anomaly.d.ts +112 -0
  222. package/dist/recall-audit-anomaly.js +11 -0
  223. package/dist/recall-audit-anomaly.js.map +1 -0
  224. package/dist/recall-audit.js +5 -44
  225. package/dist/recall-audit.js.map +1 -1
  226. package/dist/recall-explain-renderer.d.ts +49 -0
  227. package/dist/recall-explain-renderer.js +18 -0
  228. package/dist/recall-explain-renderer.js.map +1 -0
  229. package/dist/recall-state.d.ts +12 -1
  230. package/dist/recall-state.js +1 -1
  231. package/dist/recall-xray-cli.d.ts +40 -0
  232. package/dist/recall-xray-cli.js +11 -0
  233. package/dist/recall-xray-cli.js.map +1 -0
  234. package/dist/recall-xray-renderer.d.ts +44 -0
  235. package/dist/recall-xray-renderer.js +18 -0
  236. package/dist/recall-xray-renderer.js.map +1 -0
  237. package/dist/recall-xray.d.ts +179 -0
  238. package/dist/recall-xray.js +13 -0
  239. package/dist/recall-xray.js.map +1 -0
  240. package/dist/resolve-provider-secret.d.ts +5 -1
  241. package/dist/resolve-provider-secret.js +3 -1
  242. package/dist/resume-bundles.js +6 -6
  243. package/dist/retrieval-agents.d.ts +1 -1
  244. package/dist/retrieval-tiers.d.ts +17 -0
  245. package/dist/retrieval-tiers.js +9 -0
  246. package/dist/retrieval-tiers.js.map +1 -0
  247. package/dist/schemas.d.ts +309 -53
  248. package/dist/schemas.js +1 -1
  249. package/dist/{semantic-consolidation-DrvSYRdB.d.ts → semantic-consolidation-CxJU6MJk.d.ts} +62 -1
  250. package/dist/semantic-consolidation.d.ts +2 -1
  251. package/dist/semantic-consolidation.js +22 -7
  252. package/dist/semantic-rule-promotion.js +7 -6
  253. package/dist/semantic-rule-verifier.js +7 -6
  254. package/dist/storage.d.ts +82 -1
  255. package/dist/storage.js +6 -5
  256. package/dist/summarizer.js +6 -6
  257. package/dist/temporal-supersession.d.ts +1 -0
  258. package/dist/tier-migration.d.ts +2 -1
  259. package/dist/tokens.js +2 -1
  260. package/dist/types.d.ts +276 -2
  261. package/dist/types.js +1 -1
  262. package/dist/verified-recall.js +7 -6
  263. package/package.json +1 -1
  264. package/dist/chunk-37UIFYWO.js.map +0 -1
  265. package/dist/chunk-3QHL5ABG.js.map +0 -1
  266. package/dist/chunk-3SV6CQHO.js.map +0 -1
  267. package/dist/chunk-3WHVNEN7.js.map +0 -1
  268. package/dist/chunk-47UU5PU2.js.map +0 -1
  269. package/dist/chunk-4LACOVZX.js.map +0 -1
  270. package/dist/chunk-6ZH4TU6I.js.map +0 -1
  271. package/dist/chunk-ALXMCZEU.js.map +0 -1
  272. package/dist/chunk-BLKTA7MM.js.map +0 -1
  273. package/dist/chunk-DEPL3635.js.map +0 -1
  274. package/dist/chunk-GV6NLQ4X.js.map +0 -1
  275. package/dist/chunk-J4IYOZZ5.js.map +0 -1
  276. package/dist/chunk-LAYN4LDC.js +0 -267
  277. package/dist/chunk-LAYN4LDC.js.map +0 -1
  278. package/dist/chunk-LK6SGL53.js.map +0 -1
  279. package/dist/chunk-MBJHSA7F.js.map +0 -1
  280. package/dist/chunk-MTLYEMJB.js.map +0 -1
  281. package/dist/chunk-MVTHXUBX.js.map +0 -1
  282. package/dist/chunk-NQEVYWX6.js.map +0 -1
  283. package/dist/chunk-O5ETUNBT.js.map +0 -1
  284. package/dist/chunk-OIT5QGG4.js.map +0 -1
  285. package/dist/chunk-PAORGQRI.js.map +0 -1
  286. package/dist/chunk-QDYXG4CS.js.map +0 -1
  287. package/dist/chunk-QNJMBKFK.js.map +0 -1
  288. package/dist/chunk-SYUK3VLY.js.map +0 -1
  289. package/dist/chunk-UEYA6UC7.js.map +0 -1
  290. package/dist/chunk-UVJFDP7P.js +0 -202
  291. package/dist/chunk-UVJFDP7P.js.map +0 -1
  292. package/dist/chunk-WBSAYXVI.js.map +0 -1
  293. package/dist/chunk-XZ2TIKGC.js.map +0 -1
  294. package/dist/chunk-ZVBB3T7V.js.map +0 -1
  295. package/dist/contradiction-scan-GR33PONM.js.map +0 -1
  296. /package/dist/{engine-5TIQBYZR.js.map → access-audit.js.map} +0 -0
  297. /package/dist/{chunk-ITRLGI2T.js.map → chunk-3OGMS3PE.js.map} +0 -0
  298. /package/dist/{chunk-44ICJRF3.js.map → chunk-AYXIPSZO.js.map} +0 -0
  299. /package/dist/{chunk-6UJ47TVX.js.map → chunk-CUPFXL3J.js.map} +0 -0
  300. /package/dist/{chunk-N42IWANG.js.map → chunk-DG6YMRDC.js.map} +0 -0
  301. /package/dist/{chunk-7WQ6SLIE.js.map → chunk-FVA6TGI3.js.map} +0 -0
  302. /package/dist/{chunk-JL2PU6AI.js.map → chunk-R2XRID2N.js.map} +0 -0
  303. /package/dist/{chunk-4NRAJUDS.js.map → chunk-RBBWYEFJ.js.map} +0 -0
  304. /package/dist/{chunk-JIU55F3X.js.map → chunk-SPI27QT6.js.map} +0 -0
  305. /package/dist/{chunk-6LX5ORAS.js.map → chunk-TMYO7B5P.js.map} +0 -0
  306. /package/dist/{chunk-7ECD5ATE.js.map → chunk-VDX363PS.js.map} +0 -0
  307. /package/dist/{chunk-3QFQGRHO.js.map → chunk-XMHBH5H6.js.map} +0 -0
  308. /package/dist/{chunk-DHHP2Z4X.js.map → chunk-XXVWLXSG.js.map} +0 -0
@@ -0,0 +1,64 @@
1
+ // src/buffer-surprise-report.ts
2
+ async function reportBufferSurpriseDistribution(readEvents, options = {}) {
3
+ const limit = typeof options.limit === "number" && options.limit > 0 ? Math.floor(options.limit) : 200;
4
+ const raw = await readEvents({ limit, since: options.since });
5
+ const sinceMs = typeof options.since === "string" && options.since.length > 0 ? Date.parse(options.since) : Number.NaN;
6
+ const rows = raw.filter((row) => {
7
+ if (!row || row.event !== "BUFFER_SURPRISE") return false;
8
+ if (typeof row.surpriseScore !== "number") return false;
9
+ if (!Number.isFinite(row.surpriseScore)) return false;
10
+ if (row.surpriseScore < 0 || row.surpriseScore > 1) return false;
11
+ if (typeof row.triggeredFlush !== "boolean") return false;
12
+ if (Number.isFinite(sinceMs)) {
13
+ const ts = Date.parse(row.timestamp);
14
+ if (!Number.isFinite(ts) || ts <= sinceMs) return false;
15
+ }
16
+ return true;
17
+ });
18
+ if (rows.length === 0) {
19
+ return {
20
+ count: 0,
21
+ triggeredCount: 0,
22
+ triggeredRate: 0,
23
+ mean: 0,
24
+ median: 0,
25
+ p90: 0,
26
+ min: 0,
27
+ max: 0,
28
+ currentThreshold: null
29
+ };
30
+ }
31
+ const scores = rows.map((r) => r.surpriseScore).sort((a, b) => a - b);
32
+ const triggeredCount = rows.reduce(
33
+ (acc, r) => acc + (r.triggeredFlush ? 1 : 0),
34
+ 0
35
+ );
36
+ const sum = scores.reduce((acc, v) => acc + v, 0);
37
+ const mean = sum / scores.length;
38
+ const median = percentile(scores, 0.5);
39
+ const p90 = percentile(scores, 0.9);
40
+ const mostRecent = rows[rows.length - 1];
41
+ const currentThreshold = mostRecent && typeof mostRecent.threshold === "number" ? mostRecent.threshold : null;
42
+ return {
43
+ count: scores.length,
44
+ triggeredCount,
45
+ triggeredRate: triggeredCount / scores.length,
46
+ mean,
47
+ median,
48
+ p90,
49
+ min: scores[0],
50
+ max: scores[scores.length - 1],
51
+ currentThreshold
52
+ };
53
+ }
54
+ function percentile(sorted, p) {
55
+ if (sorted.length === 0) return 0;
56
+ const clamped = Math.max(0, Math.min(1, p));
57
+ const rank = Math.max(1, Math.ceil(clamped * sorted.length));
58
+ return sorted[rank - 1];
59
+ }
60
+
61
+ export {
62
+ reportBufferSurpriseDistribution
63
+ };
64
+ //# sourceMappingURL=chunk-ASAITVLA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/buffer-surprise-report.ts"],"sourcesContent":["/**\n * Buffer-surprise telemetry report (issue #563 PR 3).\n *\n * Reads the append-only `state/buffer-surprise-ledger.jsonl` file written\n * by `SmartBuffer` and summarizes the recent distribution of surprise\n * scores for the Doctor surface. This module is intentionally standalone\n * and pure — the only I/O is reading the ledger via the injected\n * `readEvents` callback, so it can be exercised directly in tests\n * without touching the filesystem.\n *\n * # Output shape\n *\n * `BufferSurpriseDistribution` has fields sized for a one-screen Doctor\n * display:\n *\n * - `count` — rows considered in the summary window.\n * - `triggeredCount` — rows whose `triggeredFlush === true`.\n * - `triggeredRate` — `triggeredCount / count`, or `0` when empty.\n * - `mean` — arithmetic mean of `surpriseScore`.\n * - `median` — middle value (50th percentile).\n * - `p90` — 90th percentile (tail of novelty).\n * - `min`, `max` — window extremes.\n * - `currentThreshold` — threshold from the MOST RECENT row, or `null`.\n *\n * All percentile math uses the nearest-rank method (no interpolation) so\n * the report is stable across small windows.\n *\n * # Why a pure function + injected reader?\n *\n * The Doctor surface is exercised both at runtime (through the CLI and\n * gateway tools) and in tests. A pure distribution helper fed from an\n * arbitrary `readEvents` callback keeps the report logic trivially\n * testable without spinning up a real `StorageManager`.\n */\n\nimport type { BufferSurpriseEvent } from \"./types.js\";\n\nexport interface BufferSurpriseDistribution {\n count: number;\n triggeredCount: number;\n triggeredRate: number;\n mean: number;\n median: number;\n p90: number;\n min: number;\n max: number;\n currentThreshold: number | null;\n}\n\nexport interface BufferSurpriseReportOptions {\n /**\n * Maximum number of recent rows to include. Defaults to `200` — large\n * enough to see a distribution, small enough to read in one sitting.\n */\n limit?: number;\n /** Lower-bound ISO timestamp; rows at or before this are excluded. */\n since?: string;\n}\n\n/**\n * Reader callback shape. The helper does not want to know whether the\n * rows come from a file, a queue, or an in-memory buffer.\n */\nexport type BufferSurpriseReader = (\n options: BufferSurpriseReportOptions,\n) => Promise<readonly BufferSurpriseEvent[]>;\n\n/**\n * Summarize the recent buffer-surprise distribution. Returns the empty\n * distribution shape when the ledger has no applicable rows — callers can\n * detect this via `count === 0` and render \"no data yet\".\n */\nexport async function reportBufferSurpriseDistribution(\n readEvents: BufferSurpriseReader,\n options: BufferSurpriseReportOptions = {},\n): Promise<BufferSurpriseDistribution> {\n const limit =\n typeof options.limit === \"number\" && options.limit > 0\n ? Math.floor(options.limit)\n : 200;\n const raw = await readEvents({ limit, since: options.since });\n\n // Filter for sanity: finite numeric scores in [0, 1], event tag match,\n // and the optional `since` lower bound. Malformed rows are skipped.\n const sinceMs =\n typeof options.since === \"string\" && options.since.length > 0\n ? Date.parse(options.since)\n : Number.NaN;\n const rows = raw.filter((row): row is BufferSurpriseEvent => {\n if (!row || row.event !== \"BUFFER_SURPRISE\") return false;\n if (typeof row.surpriseScore !== \"number\") return false;\n if (!Number.isFinite(row.surpriseScore)) return false;\n if (row.surpriseScore < 0 || row.surpriseScore > 1) return false;\n // `triggeredFlush` must be a real boolean — not a string or other\n // truthy value. A row with `triggeredFlush: \"false\"` (string from a\n // JSON-parsing bug upstream) would otherwise be counted as\n // triggered, inflating the rate and misleading operators tuning the\n // threshold from real traffic.\n if (typeof row.triggeredFlush !== \"boolean\") return false;\n if (Number.isFinite(sinceMs)) {\n const ts = Date.parse(row.timestamp);\n if (!Number.isFinite(ts) || ts <= sinceMs) return false;\n }\n return true;\n });\n\n if (rows.length === 0) {\n return {\n count: 0,\n triggeredCount: 0,\n triggeredRate: 0,\n mean: 0,\n median: 0,\n p90: 0,\n min: 0,\n max: 0,\n currentThreshold: null,\n };\n }\n\n const scores = rows.map((r) => r.surpriseScore).sort((a, b) => a - b);\n const triggeredCount = rows.reduce(\n (acc, r) => acc + (r.triggeredFlush ? 1 : 0),\n 0,\n );\n const sum = scores.reduce((acc, v) => acc + v, 0);\n const mean = sum / scores.length;\n\n // Nearest-rank percentiles keep the output stable for small windows.\n const median = percentile(scores, 0.5);\n const p90 = percentile(scores, 0.9);\n\n // \"Current\" threshold is whichever was in force for the most recent row\n // — not necessarily the one configured right now, but the value the\n // ledger rows were judged against. That's what operators need to reason\n // about the distribution.\n const mostRecent = rows[rows.length - 1];\n const currentThreshold =\n mostRecent && typeof mostRecent.threshold === \"number\"\n ? mostRecent.threshold\n : null;\n\n return {\n count: scores.length,\n triggeredCount,\n triggeredRate: triggeredCount / scores.length,\n mean,\n median,\n p90,\n min: scores[0]!,\n max: scores[scores.length - 1]!,\n currentThreshold,\n };\n}\n\n/**\n * Nearest-rank percentile of a pre-sorted ascending array.\n *\n * Returns `sorted[ceil(p * n) - 1]`, with `p` clamped to `[0, 1]`.\n * This avoids the interpolation ambiguity of R-7/R-8 percentiles and is\n * stable when the window is small (e.g. 3-5 rows).\n */\nfunction percentile(sorted: readonly number[], p: number): number {\n if (sorted.length === 0) return 0;\n const clamped = Math.max(0, Math.min(1, p));\n const rank = Math.max(1, Math.ceil(clamped * sorted.length));\n return sorted[rank - 1]!;\n}\n"],"mappings":";AAwEA,eAAsB,iCACpB,YACA,UAAuC,CAAC,GACH;AACrC,QAAM,QACJ,OAAO,QAAQ,UAAU,YAAY,QAAQ,QAAQ,IACjD,KAAK,MAAM,QAAQ,KAAK,IACxB;AACN,QAAM,MAAM,MAAM,WAAW,EAAE,OAAO,OAAO,QAAQ,MAAM,CAAC;AAI5D,QAAM,UACJ,OAAO,QAAQ,UAAU,YAAY,QAAQ,MAAM,SAAS,IACxD,KAAK,MAAM,QAAQ,KAAK,IACxB,OAAO;AACb,QAAM,OAAO,IAAI,OAAO,CAAC,QAAoC;AAC3D,QAAI,CAAC,OAAO,IAAI,UAAU,kBAAmB,QAAO;AACpD,QAAI,OAAO,IAAI,kBAAkB,SAAU,QAAO;AAClD,QAAI,CAAC,OAAO,SAAS,IAAI,aAAa,EAAG,QAAO;AAChD,QAAI,IAAI,gBAAgB,KAAK,IAAI,gBAAgB,EAAG,QAAO;AAM3D,QAAI,OAAO,IAAI,mBAAmB,UAAW,QAAO;AACpD,QAAI,OAAO,SAAS,OAAO,GAAG;AAC5B,YAAM,KAAK,KAAK,MAAM,IAAI,SAAS;AACnC,UAAI,CAAC,OAAO,SAAS,EAAE,KAAK,MAAM,QAAS,QAAO;AAAA,IACpD;AACA,WAAO;AAAA,EACT,CAAC;AAED,MAAI,KAAK,WAAW,GAAG;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,kBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACpE,QAAM,iBAAiB,KAAK;AAAA,IAC1B,CAAC,KAAK,MAAM,OAAO,EAAE,iBAAiB,IAAI;AAAA,IAC1C;AAAA,EACF;AACA,QAAM,MAAM,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAChD,QAAM,OAAO,MAAM,OAAO;AAG1B,QAAM,SAAS,WAAW,QAAQ,GAAG;AACrC,QAAM,MAAM,WAAW,QAAQ,GAAG;AAMlC,QAAM,aAAa,KAAK,KAAK,SAAS,CAAC;AACvC,QAAM,mBACJ,cAAc,OAAO,WAAW,cAAc,WAC1C,WAAW,YACX;AAEN,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,eAAe,iBAAiB,OAAO;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,OAAO,CAAC;AAAA,IACb,KAAK,OAAO,OAAO,SAAS,CAAC;AAAA,IAC7B;AAAA,EACF;AACF;AASA,SAAS,WAAW,QAA2B,GAAmB;AAChE,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAC1C,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,OAAO,MAAM,CAAC;AAC3D,SAAO,OAAO,OAAO,CAAC;AACxB;","names":[]}
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  getGatewayRuntimeAuthForModel,
3
3
  resolveProviderApiKey
4
- } from "./chunk-XZ2TIKGC.js";
4
+ } from "./chunk-Y7R2XJ5Q.js";
5
+ import {
6
+ loadModelsJsonProviders
7
+ } from "./chunk-ODWDQNRE.js";
5
8
  import {
6
9
  buildChatCompletionTokenLimit,
7
10
  shouldAssumeOpenAiChatCompletions
8
11
  } from "./chunk-Y27UJK6V.js";
9
- import {
10
- loadModelsJsonProviders
11
- } from "./chunk-ODWDQNRE.js";
12
12
  import {
13
13
  extractJsonCandidates
14
14
  } from "./chunk-UZB5KHKX.js";
@@ -458,4 +458,4 @@ function extractResponsesOutputText(data) {
458
458
  export {
459
459
  FallbackLlmClient
460
460
  };
461
- //# sourceMappingURL=chunk-44ICJRF3.js.map
461
+ //# sourceMappingURL=chunk-AYXIPSZO.js.map
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  cloneDefaultSessionObserverBands
3
3
  } from "./chunk-Z5LAYHGJ.js";
4
+ import {
5
+ normalizeEntitySchemas
6
+ } from "./chunk-4DJQYKMN.js";
4
7
  import {
5
8
  readEnvVar,
6
9
  resolveHomeDir
7
10
  } from "./chunk-MARWOCVP.js";
8
- import {
9
- normalizeEntitySchemas
10
- } from "./chunk-4DJQYKMN.js";
11
11
  import {
12
12
  log
13
13
  } from "./chunk-2ODBA7MQ.js";
@@ -160,7 +160,8 @@ var VALID_MEMORY_CATEGORIES = /* @__PURE__ */ new Set([
160
160
  "moment",
161
161
  "skill",
162
162
  "rule",
163
- "procedure"
163
+ "procedure",
164
+ "reasoning_trace"
164
165
  ]);
165
166
  var DEFAULT_BEHAVIOR_LOOP_PROTECTED_PARAMS = [
166
167
  "maxMemoryTokens",
@@ -192,7 +193,14 @@ var MEMORY_OS_PRESETS = {
192
193
  compressionGuidelineSemanticRefinementEnabled: false,
193
194
  maxProactiveQuestionsPerExtraction: 0,
194
195
  maxCompressionTokensPerHour: 0,
195
- behaviorLoopAutoTuneEnabled: false
196
+ behaviorLoopAutoTuneEnabled: false,
197
+ // Issue #567 PR 4/5 flipped `procedural.enabled` default to `true`.
198
+ // The conservative preset intentionally keeps the feature OFF to
199
+ // match its restrictive intent (no proactive extraction, no
200
+ // compression guideline learning, etc.). Users who want procedural
201
+ // memory on a conservative preset must set `procedural.enabled: true`
202
+ // explicitly.
203
+ procedural: { enabled: false }
196
204
  },
197
205
  balanced: {
198
206
  maxMemoryTokens: 2e3,
@@ -274,16 +282,28 @@ function resolveMemoryOsPreset(value) {
274
282
  function parseConfig(raw) {
275
283
  const baseCfg = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
276
284
  const memoryOsPreset = resolveMemoryOsPreset(baseCfg.memoryOsPreset);
277
- const cfg = memoryOsPreset ? {
278
- ...MEMORY_OS_PRESETS[memoryOsPreset],
279
- ...baseCfg,
280
- memoryOsPreset
281
- } : baseCfg;
285
+ let cfg;
286
+ if (memoryOsPreset) {
287
+ const preset = MEMORY_OS_PRESETS[memoryOsPreset];
288
+ const presetProcedural = preset.procedural && typeof preset.procedural === "object" && !Array.isArray(preset.procedural) ? preset.procedural : void 0;
289
+ const baseProcedural = baseCfg.procedural && typeof baseCfg.procedural === "object" && !Array.isArray(baseCfg.procedural) ? baseCfg.procedural : void 0;
290
+ const mergedProcedural = presetProcedural && baseProcedural ? { ...presetProcedural, ...baseProcedural } : baseProcedural ?? presetProcedural;
291
+ cfg = {
292
+ ...preset,
293
+ ...baseCfg,
294
+ memoryOsPreset
295
+ };
296
+ if (mergedProcedural !== void 0) {
297
+ cfg.procedural = mergedProcedural;
298
+ }
299
+ } else {
300
+ cfg = baseCfg;
301
+ }
282
302
  let apiKey;
283
303
  if (typeof cfg.openaiApiKey === "string" && cfg.openaiApiKey.length > 0) {
284
304
  apiKey = resolveEnvVars(cfg.openaiApiKey);
285
305
  } else {
286
- apiKey = process.env.OPENAI_API_KEY;
306
+ apiKey = readEnvVar("OPENAI_API_KEY");
287
307
  }
288
308
  const model = typeof cfg.model === "string" && cfg.model.length > 0 ? cfg.model : "gpt-5.2";
289
309
  const captureMode = cfg.captureMode === "explicit" || cfg.captureMode === "hybrid" ? cfg.captureMode : "implicit";
@@ -327,19 +347,37 @@ function parseConfig(raw) {
327
347
  ) ? rawCodexCompat.compactionFlushMode : "auto",
328
348
  fingerprintDedup: rawCodexCompat.fingerprintDedup !== false
329
349
  };
350
+ if (cfg.procedural !== void 0 && (cfg.procedural === null || typeof cfg.procedural !== "object" || Array.isArray(cfg.procedural))) {
351
+ throw new Error(
352
+ `procedural must be an object (got ${JSON.stringify(cfg.procedural)}). Use procedural: { enabled: false } to opt out; omit the key to use the default-on behavior (issue #567 PR 4).`
353
+ );
354
+ }
330
355
  const rawProcedural = cfg.procedural && typeof cfg.procedural === "object" && !Array.isArray(cfg.procedural) ? cfg.procedural : {};
331
356
  const proceduralMinCoerced = coerceNumber(rawProcedural.minOccurrences);
332
357
  const proceduralMinRaw = proceduralMinCoerced !== void 0 ? Math.floor(proceduralMinCoerced) : 3;
333
358
  const successFloorRaw = coerceNumber(rawProcedural.successFloor);
334
- const successFloor = successFloorRaw !== void 0 && successFloorRaw >= 0 && successFloorRaw <= 1 ? successFloorRaw : 0.7;
359
+ const successFloor = successFloorRaw !== void 0 && successFloorRaw >= 0 && successFloorRaw <= 1 ? successFloorRaw : 0.75;
335
360
  const autoPromoteOccRaw = coerceNumber(rawProcedural.autoPromoteOccurrences);
336
361
  const autoPromoteOccurrences = autoPromoteOccRaw !== void 0 && Number.isFinite(autoPromoteOccRaw) ? autoPromoteOccRaw <= 0 ? 0 : Math.min(1e4, Math.max(1, Math.floor(autoPromoteOccRaw))) : 8;
337
362
  const lookbackCoerced = coerceNumber(rawProcedural.lookbackDays);
338
- const lookbackDays = lookbackCoerced !== void 0 && Number.isFinite(lookbackCoerced) ? Math.min(3650, Math.max(1, Math.floor(lookbackCoerced))) : 30;
363
+ const lookbackDays = lookbackCoerced !== void 0 && Number.isFinite(lookbackCoerced) ? Math.min(3650, Math.max(1, Math.floor(lookbackCoerced))) : 14;
339
364
  const recallMaxCoerced = coerceNumber(rawProcedural.recallMaxProcedures);
340
- const recallMaxProcedures = recallMaxCoerced !== void 0 && Number.isFinite(recallMaxCoerced) ? Math.min(10, Math.max(1, Math.floor(recallMaxCoerced))) : 3;
365
+ const recallMaxProcedures = recallMaxCoerced !== void 0 && Number.isFinite(recallMaxCoerced) ? Math.min(10, Math.max(1, Math.floor(recallMaxCoerced))) : 2;
366
+ const rawEnabledValue = rawProcedural.enabled;
367
+ let proceduralEnabled;
368
+ if (rawEnabledValue === void 0) {
369
+ proceduralEnabled = true;
370
+ } else {
371
+ const enabledCoerced = coerceBool(rawEnabledValue);
372
+ if (enabledCoerced === void 0) {
373
+ throw new Error(
374
+ `procedural.enabled must be a boolean or one of "true"/"false"/"1"/"0"/"yes"/"no"/"on"/"off" (got ${JSON.stringify(rawEnabledValue)}). Omit the key to use the default-on behavior (issue #567 PR 4).`
375
+ );
376
+ }
377
+ proceduralEnabled = enabledCoerced;
378
+ }
341
379
  const procedural = {
342
- enabled: coerceBool(rawProcedural.enabled) === true,
380
+ enabled: proceduralEnabled,
343
381
  /** `0` skips all mining (`minOccurrences_zero`); otherwise clusters need at least this many members. */
344
382
  minOccurrences: Math.min(1e3, Math.max(0, proceduralMinRaw)),
345
383
  successFloor,
@@ -349,6 +387,13 @@ function parseConfig(raw) {
349
387
  proceduralMiningCronAutoRegister: coerceBool(rawProcedural.proceduralMiningCronAutoRegister) === true,
350
388
  recallMaxProcedures
351
389
  };
390
+ const rawCodingMode = cfg.codingMode && typeof cfg.codingMode === "object" && !Array.isArray(cfg.codingMode) ? cfg.codingMode : {};
391
+ const codingProjectScopeRaw = coerceBool(rawCodingMode.projectScope);
392
+ const codingBranchScopeRaw = coerceBool(rawCodingMode.branchScope);
393
+ const codingMode = {
394
+ projectScope: codingProjectScopeRaw === void 0 ? true : codingProjectScopeRaw,
395
+ branchScope: codingBranchScopeRaw === true
396
+ };
352
397
  const memoryDir = typeof cfg.memoryDir === "string" && cfg.memoryDir.length > 0 ? cfg.memoryDir : DEFAULT_MEMORY_DIR;
353
398
  const rawIdentityInjectionMode = cfg.identityInjectionMode;
354
399
  const identityInjectionMode = rawIdentityInjectionMode && VALID_IDENTITY_INJECTION_MODES.includes(rawIdentityInjectionMode) ? rawIdentityInjectionMode : "recovery_only";
@@ -435,15 +480,15 @@ function parseConfig(raw) {
435
480
  enabled: rawAgentAccessHttp?.enabled === true,
436
481
  host: typeof rawAgentAccessHttp?.host === "string" && rawAgentAccessHttp.host.trim().length > 0 ? rawAgentAccessHttp.host.trim() : "127.0.0.1",
437
482
  port: typeof rawAgentAccessHttp?.port === "number" ? Math.max(0, Math.floor(rawAgentAccessHttp.port)) : 4318,
438
- authToken: typeof rawAgentAccessHttp?.authToken === "string" && rawAgentAccessHttp.authToken.trim().length > 0 ? resolveEnvVars(rawAgentAccessHttp.authToken) : process.env.OPENCLAW_REMNIC_ACCESS_TOKEN ?? process.env.OPENCLAW_ENGRAM_ACCESS_TOKEN,
439
- principal: typeof rawAgentAccessHttp?.principal === "string" && rawAgentAccessHttp.principal.trim().length > 0 ? resolveEnvVars(rawAgentAccessHttp.principal) : process.env.OPENCLAW_ENGRAM_ACCESS_PRINCIPAL?.trim() || void 0,
483
+ authToken: typeof rawAgentAccessHttp?.authToken === "string" && rawAgentAccessHttp.authToken.trim().length > 0 ? resolveEnvVars(rawAgentAccessHttp.authToken) : readEnvVar("OPENCLAW_REMNIC_ACCESS_TOKEN") ?? readEnvVar("OPENCLAW_ENGRAM_ACCESS_TOKEN"),
484
+ principal: typeof rawAgentAccessHttp?.principal === "string" && rawAgentAccessHttp.principal.trim().length > 0 ? resolveEnvVars(rawAgentAccessHttp.principal) : readEnvVar("OPENCLAW_ENGRAM_ACCESS_PRINCIPAL")?.trim() || void 0,
440
485
  maxBodyBytes: typeof rawAgentAccessHttp?.maxBodyBytes === "number" ? Math.max(1, Math.floor(rawAgentAccessHttp.maxBodyBytes)) : 131072
441
486
  };
442
487
  let baseUrl;
443
488
  if (typeof cfg.openaiBaseUrl === "string" && cfg.openaiBaseUrl.length > 0) {
444
489
  baseUrl = normalizeOpenaiBaseUrl(resolveEnvVars(cfg.openaiBaseUrl), "config");
445
490
  } else {
446
- baseUrl = normalizeOpenaiBaseUrl(process.env.OPENAI_BASE_URL, "env");
491
+ baseUrl = normalizeOpenaiBaseUrl(readEnvVar("OPENAI_BASE_URL"), "env");
447
492
  }
448
493
  const sharedCrossSignalSemanticEnabled = cfg.sharedCrossSignalSemanticEnabled === true || cfg.crossSignalsSemanticEnabled === true;
449
494
  const sharedCrossSignalSemanticTimeoutMs = typeof cfg.sharedCrossSignalSemanticTimeoutMs === "number" ? Math.max(1, Math.floor(cfg.sharedCrossSignalSemanticTimeoutMs)) : typeof cfg.crossSignalsSemanticTimeoutMs === "number" ? Math.max(1, Math.floor(cfg.crossSignalsSemanticTimeoutMs)) : 4e3;
@@ -456,6 +501,36 @@ function parseConfig(raw) {
456
501
  triggerMode,
457
502
  bufferMaxTurns: typeof cfg.bufferMaxTurns === "number" ? cfg.bufferMaxTurns : 5,
458
503
  bufferMaxMinutes: typeof cfg.bufferMaxMinutes === "number" ? cfg.bufferMaxMinutes : 15,
504
+ // Surprise-gated buffer flush (issue #563, D-MEM). See types.ts for
505
+ // semantics. Default off so PR 2 ships as a pure no-op until an operator
506
+ // opts in. PR 4 benchmarks the flag and may flip the default.
507
+ //
508
+ // Use `coerceBool` rather than a strict `=== true` check: CLI operators
509
+ // set booleans via `--config bufferSurpriseTriggerEnabled=true` which
510
+ // arrives as the string `"true"` — the strict form would silently
511
+ // leave the flag off. Matches the coercion contract established for
512
+ // other boolean config keys (CLAUDE.md rule #36).
513
+ bufferSurpriseTriggerEnabled: coerceBool(cfg.bufferSurpriseTriggerEnabled) === true,
514
+ // Numeric surprise knobs go through `coerceNumber` so CLI operators
515
+ // can pass `--config bufferSurpriseThreshold=0.5` without the string
516
+ // silently dropping to the default. Matches the coercion contract
517
+ // applied to other numeric config keys (CLAUDE.md rule #28).
518
+ bufferSurpriseThreshold: clampSurpriseThreshold(
519
+ coerceNumber(cfg.bufferSurpriseThreshold),
520
+ 0.35
521
+ ),
522
+ bufferSurpriseK: clampSurpriseK(
523
+ coerceNumber(cfg.bufferSurpriseK),
524
+ 5
525
+ ),
526
+ bufferSurpriseRecentMemoryCount: clampSurpriseRecentMemoryCount(
527
+ coerceNumber(cfg.bufferSurpriseRecentMemoryCount),
528
+ 20
529
+ ),
530
+ bufferSurpriseProbeTimeoutMs: clampSurpriseProbeTimeoutMs(
531
+ coerceNumber(cfg.bufferSurpriseProbeTimeoutMs),
532
+ 2e3
533
+ ),
459
534
  consolidateEveryN: typeof cfg.consolidateEveryN === "number" ? cfg.consolidateEveryN : 3,
460
535
  highSignalPatterns: Array.isArray(cfg.highSignalPatterns) ? cfg.highSignalPatterns : [],
461
536
  maxMemoryTokens: typeof cfg.maxMemoryTokens === "number" ? cfg.maxMemoryTokens : 2e3,
@@ -544,6 +619,49 @@ function parseConfig(raw) {
544
619
  // QMD path. Operators can opt out with
545
620
  // recallDirectAnswerEnabled=false.
546
621
  recallDirectAnswerEnabled: coerceBool(cfg.recallDirectAnswerEnabled) ?? true,
622
+ // Graph-based retrieval tier (issue #559 PR 4). Default `false` —
623
+ // the tier ships off pending the `retrieval-graph` bench in PR 5.
624
+ recallGraphEnabled: coerceBool(cfg.recallGraphEnabled) ?? false,
625
+ recallGraphDamping: (() => {
626
+ const n = coerceNumber(cfg.recallGraphDamping);
627
+ return n !== void 0 && n >= 0 && n < 1 ? n : 0.85;
628
+ })(),
629
+ // Fractional integer values (e.g. `0.5`) are REJECTED rather than
630
+ // silently floored to zero — CLAUDE.md rule 51 ("Reject invalid
631
+ // user input instead of silently defaulting"). Users who set a
632
+ // fractional iteration cap almost certainly meant an integer and
633
+ // quietly flooring their value to 0 turns off the tier without
634
+ // warning.
635
+ recallGraphIterations: (() => {
636
+ if (cfg.recallGraphIterations === void 0) return 20;
637
+ const n = coerceNumber(cfg.recallGraphIterations);
638
+ if (n === void 0 || !Number.isFinite(n) || n < 0 || n > 500) {
639
+ throw new Error(
640
+ `recallGraphIterations must be an integer in [0, 500] (got ${JSON.stringify(cfg.recallGraphIterations)}).`
641
+ );
642
+ }
643
+ if (!Number.isInteger(n)) {
644
+ throw new Error(
645
+ `recallGraphIterations must be an integer (got fractional value ${n}).`
646
+ );
647
+ }
648
+ return n;
649
+ })(),
650
+ recallGraphTopK: (() => {
651
+ if (cfg.recallGraphTopK === void 0) return 50;
652
+ const n = coerceNumber(cfg.recallGraphTopK);
653
+ if (n === void 0 || !Number.isFinite(n) || n < 0 || n > 1e4) {
654
+ throw new Error(
655
+ `recallGraphTopK must be an integer in [0, 10000] (got ${JSON.stringify(cfg.recallGraphTopK)}).`
656
+ );
657
+ }
658
+ if (!Number.isInteger(n)) {
659
+ throw new Error(
660
+ `recallGraphTopK must be an integer (got fractional value ${n}).`
661
+ );
662
+ }
663
+ return n;
664
+ })(),
547
665
  recallDirectAnswerTokenOverlapFloor: (() => {
548
666
  const n = coerceNumber(cfg.recallDirectAnswerTokenOverlapFloor);
549
667
  return n !== void 0 && n >= 0 && n <= 1 ? n : 0.55;
@@ -561,6 +679,71 @@ function parseConfig(raw) {
561
679
  ) ? cfg.recallDirectAnswerEligibleTaxonomyBuckets.filter(
562
680
  (v) => typeof v === "string" && v.length > 0
563
681
  ) : ["decisions", "principles", "conventions", "runbooks", "entities"],
682
+ // Cross-namespace query-budget limiter (issue #565 PR 4/5).
683
+ // Defaults to false — ships disabled so existing deployments are
684
+ // unaffected. When enabled, the read path throttles a principal that
685
+ // issues a burst of recalls against namespaces other than their own.
686
+ recallCrossNamespaceBudgetEnabled: coerceBool(cfg.recallCrossNamespaceBudgetEnabled) ?? false,
687
+ recallCrossNamespaceBudgetWindowMs: (() => {
688
+ const n = coerceNumber(cfg.recallCrossNamespaceBudgetWindowMs);
689
+ return n !== void 0 && n > 0 ? Math.floor(n) : 6e4;
690
+ })(),
691
+ recallCrossNamespaceBudgetSoftLimit: (() => {
692
+ const n = coerceNumber(cfg.recallCrossNamespaceBudgetSoftLimit);
693
+ return n !== void 0 && n >= 0 ? Math.floor(n) : 10;
694
+ })(),
695
+ recallCrossNamespaceBudgetHardLimit: (() => {
696
+ const n = coerceNumber(cfg.recallCrossNamespaceBudgetHardLimit);
697
+ return n !== void 0 && n > 0 ? Math.floor(n) : 30;
698
+ })(),
699
+ // Recall-audit anomaly detector (issue #565 PR 5/5). Defaults off so
700
+ // existing deployments are unaffected; enable explicitly to let the
701
+ // access surfaces flag suspicious query patterns derived from the
702
+ // audit trail. Thresholds floor AFTER validating the floored value
703
+ // is still >= 1 — a `0.5` input that floors to 0 would turn every
704
+ // detector into a flood-on-anything, flipping the default to
705
+ // max-noise instead of max-silence.
706
+ recallAuditAnomalyDetectionEnabled: coerceBool(cfg.recallAuditAnomalyDetectionEnabled) ?? false,
707
+ recallAuditAnomalyWindowMs: (() => {
708
+ const n = coerceNumber(cfg.recallAuditAnomalyWindowMs);
709
+ if (n === void 0) return 5 * 6e4;
710
+ const floored = Math.floor(n);
711
+ return floored >= 1 ? floored : 5 * 6e4;
712
+ })(),
713
+ recallAuditAnomalyRepeatQueryLimit: (() => {
714
+ const n = coerceNumber(cfg.recallAuditAnomalyRepeatQueryLimit);
715
+ if (n === void 0) return 5;
716
+ const floored = Math.floor(n);
717
+ return floored >= 1 ? floored : 5;
718
+ })(),
719
+ recallAuditAnomalyNamespaceWalkLimit: (() => {
720
+ const n = coerceNumber(cfg.recallAuditAnomalyNamespaceWalkLimit);
721
+ if (n === void 0) return 3;
722
+ const floored = Math.floor(n);
723
+ return floored >= 1 ? floored : 3;
724
+ })(),
725
+ recallAuditAnomalyHighCardinalityLimit: (() => {
726
+ const n = coerceNumber(cfg.recallAuditAnomalyHighCardinalityLimit);
727
+ if (n === void 0) return 50;
728
+ const floored = Math.floor(n);
729
+ return floored >= 1 ? floored : 50;
730
+ })(),
731
+ recallAuditAnomalyRapidFireLimit: (() => {
732
+ const n = coerceNumber(cfg.recallAuditAnomalyRapidFireLimit);
733
+ if (n === void 0) return 30;
734
+ const floored = Math.floor(n);
735
+ return floored >= 1 ? floored : 30;
736
+ })(),
737
+ // Memory Worth recall filter (issue #560 PR 4, default flipped in PR 5).
738
+ // Bench result on the seeded fixture: precision@5 lifts from 0.00 to
739
+ // 0.60 across all 50 cases with zero regressions. See
740
+ // `runMemoryWorthBench` in memory-worth-bench.ts. Operators can still
741
+ // opt out with recallMemoryWorthFilterEnabled=false.
742
+ recallMemoryWorthFilterEnabled: coerceBool(cfg.recallMemoryWorthFilterEnabled) ?? true,
743
+ recallMemoryWorthHalfLifeMs: (() => {
744
+ const n = coerceNumber(cfg.recallMemoryWorthHalfLifeMs);
745
+ return n !== void 0 && n >= 0 ? n : 0;
746
+ })(),
564
747
  // Memory Linking (Phase 3A)
565
748
  memoryLinkingEnabled: cfg.memoryLinkingEnabled === true,
566
749
  // Off by default initially
@@ -637,6 +820,7 @@ function parseConfig(raw) {
637
820
  activeRecallAllowChainedActiveMemory: cfg.activeRecallAllowChainedActiveMemory === true,
638
821
  dreaming,
639
822
  procedural,
823
+ codingMode,
640
824
  heartbeat,
641
825
  slotBehavior,
642
826
  codexCompat,
@@ -709,6 +893,17 @@ function parseConfig(raw) {
709
893
  ) : ["correction", "commitment", "procedure"],
710
894
  semanticConsolidationIntervalHours: typeof cfg.semanticConsolidationIntervalHours === "number" ? Math.max(1, Math.floor(cfg.semanticConsolidationIntervalHours)) : 168,
711
895
  semanticConsolidationMaxPerRun: typeof cfg.semanticConsolidationMaxPerRun === "number" ? Math.max(0, Math.floor(cfg.semanticConsolidationMaxPerRun)) : 100,
896
+ // Operator-aware consolidation prompt (issue #561 PR 3). Defaults
897
+ // to `false` to match sibling `*Enabled` flags' least-privileged
898
+ // convention. Operators opt in by setting `true` (or truthy
899
+ // coercions like "true", "1", "yes", "on") when they want the
900
+ // consolidation LLM to emit SPLIT/MERGE/UPDATE operator selection
901
+ // on the `derived_via` frontmatter field. Uses `coerceBool` per
902
+ // Gotcha #36 so CLI / env-string inputs coerce correctly. When
903
+ // disabled, `derived_via` is still populated via the cluster-shape
904
+ // heuristic (chooseConsolidationOperator) so PR 2's provenance
905
+ // wiring keeps working without operator-aware prompts.
906
+ operatorAwareConsolidationEnabled: coerceBool(cfg.operatorAwareConsolidationEnabled) ?? false,
712
907
  creationMemoryEnabled: cfg.creationMemoryEnabled === true,
713
908
  memoryUtilityLearningEnabled: cfg.memoryUtilityLearningEnabled === true,
714
909
  promotionByOutcomeEnabled: cfg.promotionByOutcomeEnabled === true,
@@ -782,6 +977,21 @@ function parseConfig(raw) {
782
977
  extractionJudgeModel: typeof cfg.extractionJudgeModel === "string" ? cfg.extractionJudgeModel : "",
783
978
  extractionJudgeBatchSize: typeof cfg.extractionJudgeBatchSize === "number" && Number.isFinite(cfg.extractionJudgeBatchSize) ? Math.max(1, Math.round(cfg.extractionJudgeBatchSize)) : 20,
784
979
  extractionJudgeShadow: cfg.extractionJudgeShadow === true,
980
+ // Defer cap (issue #562 PR 2): max re-deferrals for the same candidate
981
+ // text before the verdict is forcibly converted to reject.
982
+ extractionJudgeMaxDeferrals: typeof cfg.extractionJudgeMaxDeferrals === "number" && Number.isFinite(cfg.extractionJudgeMaxDeferrals) && cfg.extractionJudgeMaxDeferrals >= 1 ? Math.floor(cfg.extractionJudgeMaxDeferrals) : 2,
983
+ // Judge telemetry (issue #562 PR 3): opt-in structured emit to the
984
+ // observation ledger for defer-rate / latency metrics.
985
+ // Uses `coerceBool` so CLI-style string inputs (`"true"`, `"false"`,
986
+ // `"1"`, `"0"`) are accepted consistently with the rest of the
987
+ // codebase (CLAUDE.md gotcha 36).
988
+ extractionJudgeTelemetryEnabled: coerceBool(cfg.extractionJudgeTelemetryEnabled) === true,
989
+ // Judge training-pair collection (issue #562 PR 4): opt-in shim for a
990
+ // future GRPO training pipeline. Rows land under ~/.remnic/judge-
991
+ // training/<date>.jsonl — NOT in the shared memory directory.
992
+ // Uses `coerceBool` per CLAUDE.md gotcha 36 for CLI-string parity.
993
+ collectJudgeTrainingPairs: coerceBool(cfg.collectJudgeTrainingPairs) === true,
994
+ judgeTrainingDir: typeof cfg.judgeTrainingDir === "string" ? cfg.judgeTrainingDir : "",
785
995
  // Inline source attribution (issue #369). Opt-in to preserve
786
996
  // backwards compatibility with existing downstream consumers.
787
997
  inlineSourceAttributionEnabled: cfg.inlineSourceAttributionEnabled === true,
@@ -913,6 +1123,8 @@ function parseConfig(raw) {
913
1123
  recallMmrEnabled: cfg.recallMmrEnabled !== false,
914
1124
  recallMmrLambda: typeof cfg.recallMmrLambda === "number" && Number.isFinite(cfg.recallMmrLambda) ? Math.min(1, Math.max(0, cfg.recallMmrLambda)) : 0.7,
915
1125
  recallMmrTopN: typeof cfg.recallMmrTopN === "number" && Number.isFinite(cfg.recallMmrTopN) ? Math.max(0, Math.floor(cfg.recallMmrTopN)) : 40,
1126
+ // Issue #564 PR 3: off by default; enable explicitly after bench validation.
1127
+ recallReasoningTraceBoostEnabled: coerceBool(cfg.recallReasoningTraceBoostEnabled) ?? false,
916
1128
  qmdRecallCacheTtlMs: typeof cfg.qmdRecallCacheTtlMs === "number" ? Math.max(0, Math.floor(cfg.qmdRecallCacheTtlMs)) : 6e4,
917
1129
  qmdRecallCacheStaleTtlMs: typeof cfg.qmdRecallCacheStaleTtlMs === "number" ? Math.max(0, Math.floor(cfg.qmdRecallCacheStaleTtlMs)) : 10 * 6e4,
918
1130
  qmdRecallCacheMaxEntries: typeof cfg.qmdRecallCacheMaxEntries === "number" ? Math.max(0, Math.floor(cfg.qmdRecallCacheMaxEntries)) : 128,
@@ -1196,6 +1408,22 @@ function clampNonNegativeNumber(value) {
1196
1408
  if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
1197
1409
  return Math.max(0, Math.floor(value));
1198
1410
  }
1411
+ function clampSurpriseThreshold(value, fallback) {
1412
+ if (value === void 0) return fallback;
1413
+ return Math.min(1, Math.max(0, value));
1414
+ }
1415
+ function clampSurpriseK(value, fallback) {
1416
+ if (value === void 0) return fallback;
1417
+ return Math.max(1, Math.floor(value));
1418
+ }
1419
+ function clampSurpriseRecentMemoryCount(value, fallback) {
1420
+ if (value === void 0) return fallback;
1421
+ return Math.max(0, Math.floor(value));
1422
+ }
1423
+ function clampSurpriseProbeTimeoutMs(value, fallback) {
1424
+ if (value === void 0) return fallback;
1425
+ return Math.max(1, Math.floor(value));
1426
+ }
1199
1427
  function parseRecallSectionEntry(raw) {
1200
1428
  const entry = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
1201
1429
  return {
@@ -1255,7 +1483,24 @@ function buildDefaultRecallPipeline(cfg) {
1255
1483
  { id: "verbatim-artifacts", enabled: cfg.verbatimArtifactsEnabled === true },
1256
1484
  {
1257
1485
  id: "procedure-recall",
1258
- enabled: typeof cfg.procedural === "object" && cfg.procedural !== null && !Array.isArray(cfg.procedural) && cfg.procedural.enabled === true,
1486
+ // Default-on since issue #567 PR 4/5: the master `procedural.enabled`
1487
+ // gate now defaults to `true` when the key is omitted, so the recall
1488
+ // pipeline must stay in sync. Explicit `false` (or any coerceBool
1489
+ // falsy variant) still disables recall injection.
1490
+ //
1491
+ // CLAUDE.md rule 48 (least-privileged defaults) + Cursor review on #609:
1492
+ // never fail open on unrecognized values. Only `coerced === true` or
1493
+ // the "key omitted" path enables the section. `parseConfig` throws
1494
+ // on invalid values upstream, so this branch only ever sees boolean
1495
+ // results — `coerced === undefined` should never happen in practice,
1496
+ // but defense-in-depth keeps the section disabled if it ever does.
1497
+ enabled: (() => {
1498
+ const proceduralRaw = typeof cfg.procedural === "object" && cfg.procedural !== null && !Array.isArray(cfg.procedural) ? cfg.procedural : void 0;
1499
+ if (proceduralRaw === void 0) return true;
1500
+ const rawEnabled = proceduralRaw.enabled;
1501
+ if (rawEnabled === void 0) return true;
1502
+ return coerceBool(rawEnabled) === true;
1503
+ })(),
1259
1504
  maxChars: 2400
1260
1505
  },
1261
1506
  { id: "memory-boxes", enabled: cfg.memoryBoxesEnabled === true },
@@ -1361,4 +1606,4 @@ export {
1361
1606
  VALID_MEMORY_CATEGORIES,
1362
1607
  parseConfig
1363
1608
  };
1364
- //# sourceMappingURL=chunk-MBJHSA7F.js.map
1609
+ //# sourceMappingURL=chunk-BECYBZLX.js.map