nlm-memory 0.21.0 → 0.21.13

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 (413) hide show
  1. package/README.md +67 -12
  2. package/assets/replay-eval-dark.svg +26 -0
  3. package/assets/replay-eval-light.svg +26 -0
  4. package/dist/cli/digest.js +34 -7
  5. package/dist/cli/digest.js.map +1 -1
  6. package/dist/cli/nlm.d.ts +14 -0
  7. package/dist/cli/nlm.js +450 -65
  8. package/dist/cli/nlm.js.map +1 -1
  9. package/dist/cli/reprocess-job-adapters.d.ts +35 -0
  10. package/dist/cli/reprocess-job-adapters.js +80 -0
  11. package/dist/cli/reprocess-job-adapters.js.map +1 -0
  12. package/dist/cli/scope-coverage.js +4 -1
  13. package/dist/cli/scope-coverage.js.map +1 -1
  14. package/dist/cli/supersede.js +8 -7
  15. package/dist/cli/supersede.js.map +1 -1
  16. package/dist/core/actions/actions-log.d.ts +65 -8
  17. package/dist/core/actions/actions-log.js +134 -17
  18. package/dist/core/actions/actions-log.js.map +1 -1
  19. package/dist/core/actions/overlay.d.ts +11 -2
  20. package/dist/core/actions/overlay.js +18 -6
  21. package/dist/core/actions/overlay.js.map +1 -1
  22. package/dist/core/adapters/from-source.js +11 -3
  23. package/dist/core/adapters/from-source.js.map +1 -1
  24. package/dist/core/adapters/fs-wiki-writer.d.ts +44 -0
  25. package/dist/core/adapters/fs-wiki-writer.js +132 -0
  26. package/dist/core/adapters/fs-wiki-writer.js.map +1 -0
  27. package/dist/core/adapters/hermes-agent.d.ts +15 -2
  28. package/dist/core/adapters/hermes-agent.js +57 -11
  29. package/dist/core/adapters/hermes-agent.js.map +1 -1
  30. package/dist/core/adapters/memory-wiki-writer.d.ts +8 -0
  31. package/dist/core/adapters/memory-wiki-writer.js +16 -0
  32. package/dist/core/adapters/memory-wiki-writer.js.map +1 -0
  33. package/dist/core/adapters/muse.d.ts +51 -0
  34. package/dist/core/adapters/muse.js +271 -0
  35. package/dist/core/adapters/muse.js.map +1 -0
  36. package/dist/core/adapters/opencode.d.ts +11 -4
  37. package/dist/core/adapters/opencode.js +41 -7
  38. package/dist/core/adapters/opencode.js.map +1 -1
  39. package/dist/core/alerts/alert-state.d.ts +17 -0
  40. package/dist/core/alerts/alert-state.js +45 -0
  41. package/dist/core/alerts/alert-state.js.map +1 -0
  42. package/dist/core/alerts/check-and-alert.d.ts +28 -0
  43. package/dist/core/alerts/check-and-alert.js +53 -0
  44. package/dist/core/alerts/check-and-alert.js.map +1 -0
  45. package/dist/core/alerts/drift-transition.d.ts +27 -0
  46. package/dist/core/alerts/drift-transition.js +56 -0
  47. package/dist/core/alerts/drift-transition.js.map +1 -0
  48. package/dist/core/alerts/embedder-transition.d.ts +23 -0
  49. package/dist/core/alerts/embedder-transition.js +40 -0
  50. package/dist/core/alerts/embedder-transition.js.map +1 -0
  51. package/dist/core/alerts/fire-alert.d.ts +24 -0
  52. package/dist/core/alerts/fire-alert.js +72 -0
  53. package/dist/core/alerts/fire-alert.js.map +1 -0
  54. package/dist/core/alerts/job-alert.d.ts +12 -0
  55. package/dist/core/alerts/job-alert.js +37 -0
  56. package/dist/core/alerts/job-alert.js.map +1 -0
  57. package/dist/core/alerts/types.d.ts +104 -0
  58. package/dist/core/alerts/types.js +11 -0
  59. package/dist/core/alerts/types.js.map +1 -0
  60. package/dist/core/alerts/wiki-alert.d.ts +15 -0
  61. package/dist/core/alerts/wiki-alert.js +31 -0
  62. package/dist/core/alerts/wiki-alert.js.map +1 -0
  63. package/dist/core/classifier/prompt.d.ts +13 -0
  64. package/dist/core/classifier/prompt.js +52 -2
  65. package/dist/core/classifier/prompt.js.map +1 -1
  66. package/dist/core/dataset/build-dataset.d.ts +16 -1
  67. package/dist/core/dataset/build-dataset.js +105 -45
  68. package/dist/core/dataset/build-dataset.js.map +1 -1
  69. package/dist/core/digest/compose.d.ts +8 -0
  70. package/dist/core/digest/compose.js +54 -0
  71. package/dist/core/digest/compose.js.map +1 -1
  72. package/dist/core/digest/hook-injection.d.ts +1 -1
  73. package/dist/core/digest/hook-injection.js +9 -1
  74. package/dist/core/digest/hook-injection.js.map +1 -1
  75. package/dist/core/digest/hook-version-parity.d.ts +31 -0
  76. package/dist/core/digest/hook-version-parity.js +56 -0
  77. package/dist/core/digest/hook-version-parity.js.map +1 -0
  78. package/dist/core/embedding/pg-embed-backfill.js +1 -1
  79. package/dist/core/embedding/pg-embed-backfill.js.map +1 -1
  80. package/dist/core/exemplars/capture-from-session.d.ts +1 -1
  81. package/dist/core/exemplars/capture-from-session.js +3 -3
  82. package/dist/core/exemplars/capture-from-session.js.map +1 -1
  83. package/dist/core/exemplars/embed-backfill.d.ts +9 -0
  84. package/dist/core/exemplars/embed-backfill.js +9 -1
  85. package/dist/core/exemplars/embed-backfill.js.map +1 -1
  86. package/dist/core/exemplars/recall-code.d.ts +1 -1
  87. package/dist/core/exemplars/recall-code.js +2 -2
  88. package/dist/core/exemplars/recall-code.js.map +1 -1
  89. package/dist/core/facts/backfill-facts.d.ts +1 -1
  90. package/dist/core/facts/backfill-facts.js +4 -4
  91. package/dist/core/facts/backfill-facts.js.map +1 -1
  92. package/dist/core/facts/embed-backfill.d.ts +54 -0
  93. package/dist/core/facts/embed-backfill.js +109 -0
  94. package/dist/core/facts/embed-backfill.js.map +1 -0
  95. package/dist/core/facts/reconcile-facts.d.ts +42 -0
  96. package/dist/core/facts/reconcile-facts.js +133 -0
  97. package/dist/core/facts/reconcile-facts.js.map +1 -0
  98. package/dist/core/health/embed-failure-state.d.ts +4 -0
  99. package/dist/core/health/embed-failure-state.js +12 -0
  100. package/dist/core/health/embed-failure-state.js.map +1 -0
  101. package/dist/core/health/warmup-retry.d.ts +27 -0
  102. package/dist/core/health/warmup-retry.js +53 -0
  103. package/dist/core/health/warmup-retry.js.map +1 -0
  104. package/dist/core/health/warmup-state.d.ts +15 -0
  105. package/dist/core/health/warmup-state.js +15 -1
  106. package/dist/core/health/warmup-state.js.map +1 -1
  107. package/dist/core/hook/cite-memo.d.ts +11 -7
  108. package/dist/core/hook/cite-memo.js +25 -17
  109. package/dist/core/hook/cite-memo.js.map +1 -1
  110. package/dist/core/hook/hook-log.d.ts +13 -2
  111. package/dist/core/hook/hook-log.js +16 -8
  112. package/dist/core/hook/hook-log.js.map +1 -1
  113. package/dist/core/hook/memo.d.ts +10 -6
  114. package/dist/core/hook/memo.js +25 -17
  115. package/dist/core/hook/memo.js.map +1 -1
  116. package/dist/core/hook/pointer-block.d.ts +8 -1
  117. package/dist/core/hook/pointer-block.js +17 -4
  118. package/dist/core/hook/pointer-block.js.map +1 -1
  119. package/dist/core/hook/resolve-conversation-by-query.d.ts +6 -5
  120. package/dist/core/hook/resolve-conversation-by-query.js +24 -12
  121. package/dist/core/hook/resolve-conversation-by-query.js.map +1 -1
  122. package/dist/core/ingest/ingest-session.d.ts +1 -1
  123. package/dist/core/ingest/ingest-session.js +3 -3
  124. package/dist/core/ingest/ingest-session.js.map +1 -1
  125. package/dist/core/ingest/reclassify-oversized.d.ts +1 -1
  126. package/dist/core/ingest/reclassify-oversized.js +2 -2
  127. package/dist/core/ingest/reclassify-oversized.js.map +1 -1
  128. package/dist/core/ingest/reprocess.d.ts +1 -1
  129. package/dist/core/ingest/reprocess.js +2 -2
  130. package/dist/core/ingest/reprocess.js.map +1 -1
  131. package/dist/core/jobs/job-supervisor.d.ts +168 -0
  132. package/dist/core/jobs/job-supervisor.js +335 -0
  133. package/dist/core/jobs/job-supervisor.js.map +1 -0
  134. package/dist/core/learner/model.d.ts +63 -0
  135. package/dist/core/learner/model.js +30 -0
  136. package/dist/core/learner/model.js.map +1 -0
  137. package/dist/core/learner/service.d.ts +42 -0
  138. package/dist/core/learner/service.js +74 -0
  139. package/dist/core/learner/service.js.map +1 -0
  140. package/dist/core/learner/summary.d.ts +28 -0
  141. package/dist/core/learner/summary.js +70 -0
  142. package/dist/core/learner/summary.js.map +1 -0
  143. package/dist/core/learner/validate.d.ts +18 -0
  144. package/dist/core/learner/validate.js +95 -0
  145. package/dist/core/learner/validate.js.map +1 -0
  146. package/dist/core/metrics/re-derivation.d.ts +31 -2
  147. package/dist/core/metrics/re-derivation.js +36 -4
  148. package/dist/core/metrics/re-derivation.js.map +1 -1
  149. package/dist/core/outcome/coverage.d.ts +1 -1
  150. package/dist/core/outcome/coverage.js +2 -2
  151. package/dist/core/outcome/coverage.js.map +1 -1
  152. package/dist/core/outcome/rollup.d.ts +1 -1
  153. package/dist/core/outcome/rollup.js +4 -4
  154. package/dist/core/outcome/rollup.js.map +1 -1
  155. package/dist/core/providers/provider-registry.d.ts +40 -23
  156. package/dist/core/providers/provider-registry.js +99 -81
  157. package/dist/core/providers/provider-registry.js.map +1 -1
  158. package/dist/core/recall/citation-log.d.ts +10 -5
  159. package/dist/core/recall/citation-log.js +21 -10
  160. package/dist/core/recall/citation-log.js.map +1 -1
  161. package/dist/core/recall/hook-recall-log.d.ts +5 -2
  162. package/dist/core/recall/hook-recall-log.js +12 -6
  163. package/dist/core/recall/hook-recall-log.js.map +1 -1
  164. package/dist/core/recall/miss-log.d.ts +7 -4
  165. package/dist/core/recall/miss-log.js +18 -11
  166. package/dist/core/recall/miss-log.js.map +1 -1
  167. package/dist/core/recall/query-log.d.ts +8 -5
  168. package/dist/core/recall/query-log.js +16 -9
  169. package/dist/core/recall/query-log.js.map +1 -1
  170. package/dist/core/recall/recall-service.d.ts +10 -1
  171. package/dist/core/recall/recall-service.js +31 -12
  172. package/dist/core/recall/recall-service.js.map +1 -1
  173. package/dist/core/recall/recent-log.d.ts +6 -1
  174. package/dist/core/recall/recent-log.js +13 -5
  175. package/dist/core/recall/recent-log.js.map +1 -1
  176. package/dist/core/recall/related-concepts.d.ts +29 -0
  177. package/dist/core/recall/related-concepts.js +67 -0
  178. package/dist/core/recall/related-concepts.js.map +1 -0
  179. package/dist/core/recall/related-exemplars.d.ts +1 -1
  180. package/dist/core/recall/related-exemplars.js +2 -2
  181. package/dist/core/recall/related-exemplars.js.map +1 -1
  182. package/dist/core/recall/related-facts.d.ts +1 -1
  183. package/dist/core/recall/related-facts.js +3 -3
  184. package/dist/core/recall/related-facts.js.map +1 -1
  185. package/dist/core/recall-facts/fact-query-log.d.ts +8 -4
  186. package/dist/core/recall-facts/fact-query-log.js +16 -8
  187. package/dist/core/recall-facts/fact-query-log.js.map +1 -1
  188. package/dist/core/recall-facts/fact-recall-service.d.ts +2 -2
  189. package/dist/core/recall-facts/fact-recall-service.js +12 -12
  190. package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
  191. package/dist/core/scheduler/scan-once.js +15 -14
  192. package/dist/core/scheduler/scan-once.js.map +1 -1
  193. package/dist/core/scheduler/scheduler.d.ts +3 -0
  194. package/dist/core/scheduler/scheduler.js +15 -11
  195. package/dist/core/scheduler/scheduler.js.map +1 -1
  196. package/dist/core/signals/failure-mode-recall.d.ts +1 -1
  197. package/dist/core/signals/failure-mode-recall.js +2 -2
  198. package/dist/core/signals/failure-mode-recall.js.map +1 -1
  199. package/dist/core/signals/stamp-scope.d.ts +2 -2
  200. package/dist/core/signals/stamp-scope.js +2 -2
  201. package/dist/core/signals/stamp-scope.js.map +1 -1
  202. package/dist/core/sources/source-registry.d.ts +49 -28
  203. package/dist/core/sources/source-registry.js +113 -70
  204. package/dist/core/sources/source-registry.js.map +1 -1
  205. package/dist/core/storage/pg-code-exemplar-store.d.ts +19 -10
  206. package/dist/core/storage/pg-code-exemplar-store.js +58 -27
  207. package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
  208. package/dist/core/storage/pg-entity-store.d.ts +6 -1
  209. package/dist/core/storage/pg-entity-store.js +33 -18
  210. package/dist/core/storage/pg-entity-store.js.map +1 -1
  211. package/dist/core/storage/pg-fact-ingest.d.ts +1 -1
  212. package/dist/core/storage/pg-fact-ingest.js +10 -7
  213. package/dist/core/storage/pg-fact-ingest.js.map +1 -1
  214. package/dist/core/storage/pg-fact-store.d.ts +29 -17
  215. package/dist/core/storage/pg-fact-store.js +99 -46
  216. package/dist/core/storage/pg-fact-store.js.map +1 -1
  217. package/dist/core/storage/pg-learner-store.d.ts +27 -0
  218. package/dist/core/storage/pg-learner-store.js +174 -0
  219. package/dist/core/storage/pg-learner-store.js.map +1 -0
  220. package/dist/core/storage/pg-session-store.d.ts +24 -20
  221. package/dist/core/storage/pg-session-store.js +162 -90
  222. package/dist/core/storage/pg-session-store.js.map +1 -1
  223. package/dist/core/storage/pg-signal-store.d.ts +10 -5
  224. package/dist/core/storage/pg-signal-store.js +24 -12
  225. package/dist/core/storage/pg-signal-store.js.map +1 -1
  226. package/dist/core/storage/pg-storage.d.ts +4 -0
  227. package/dist/core/storage/pg-storage.js +6 -0
  228. package/dist/core/storage/pg-storage.js.map +1 -1
  229. package/dist/core/storage/pg-workstream-store.d.ts +16 -11
  230. package/dist/core/storage/pg-workstream-store.js +46 -29
  231. package/dist/core/storage/pg-workstream-store.js.map +1 -1
  232. package/dist/core/storage/sqlite-code-exemplar-store.d.ts +24 -10
  233. package/dist/core/storage/sqlite-code-exemplar-store.js +84 -40
  234. package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
  235. package/dist/core/storage/sqlite-entity-store.d.ts +8 -1
  236. package/dist/core/storage/sqlite-entity-store.js +46 -27
  237. package/dist/core/storage/sqlite-entity-store.js.map +1 -1
  238. package/dist/core/storage/sqlite-fact-store.d.ts +45 -19
  239. package/dist/core/storage/sqlite-fact-store.js +172 -64
  240. package/dist/core/storage/sqlite-fact-store.js.map +1 -1
  241. package/dist/core/storage/sqlite-learner-store.d.ts +33 -0
  242. package/dist/core/storage/sqlite-learner-store.js +178 -0
  243. package/dist/core/storage/sqlite-learner-store.js.map +1 -0
  244. package/dist/core/storage/sqlite-outcome-store.d.ts +37 -22
  245. package/dist/core/storage/sqlite-outcome-store.js +90 -37
  246. package/dist/core/storage/sqlite-outcome-store.js.map +1 -1
  247. package/dist/core/storage/sqlite-session-store.d.ts +29 -20
  248. package/dist/core/storage/sqlite-session-store.js +207 -121
  249. package/dist/core/storage/sqlite-session-store.js.map +1 -1
  250. package/dist/core/storage/sqlite-signal-store.d.ts +12 -5
  251. package/dist/core/storage/sqlite-signal-store.js +27 -15
  252. package/dist/core/storage/sqlite-signal-store.js.map +1 -1
  253. package/dist/core/storage/sqlite-storage.d.ts +4 -0
  254. package/dist/core/storage/sqlite-storage.js +10 -2
  255. package/dist/core/storage/sqlite-storage.js.map +1 -1
  256. package/dist/core/storage/sqlite-workstream-store.d.ts +16 -11
  257. package/dist/core/storage/sqlite-workstream-store.js +52 -31
  258. package/dist/core/storage/sqlite-workstream-store.js.map +1 -1
  259. package/dist/core/storage/supersedence-log.d.ts +10 -7
  260. package/dist/core/storage/supersedence-log.js +19 -14
  261. package/dist/core/storage/supersedence-log.js.map +1 -1
  262. package/dist/core/tenancy/default-team.d.ts +6 -0
  263. package/dist/core/tenancy/default-team.js +7 -0
  264. package/dist/core/tenancy/default-team.js.map +1 -0
  265. package/dist/core/tenancy/hosted-mode.d.ts +9 -0
  266. package/dist/core/tenancy/hosted-mode.js +12 -0
  267. package/dist/core/tenancy/hosted-mode.js.map +1 -0
  268. package/dist/core/tenancy/team-auth.d.ts +16 -0
  269. package/dist/core/tenancy/team-auth.js +22 -0
  270. package/dist/core/tenancy/team-auth.js.map +1 -0
  271. package/dist/core/tenancy/team-token-store.d.ts +45 -0
  272. package/dist/core/tenancy/team-token-store.js +52 -0
  273. package/dist/core/tenancy/team-token-store.js.map +1 -0
  274. package/dist/core/tenancy/tenant-clause.d.ts +37 -0
  275. package/dist/core/tenancy/tenant-clause.js +11 -0
  276. package/dist/core/tenancy/tenant-clause.js.map +1 -0
  277. package/dist/core/tenancy/tenant-state-path.d.ts +28 -0
  278. package/dist/core/tenancy/tenant-state-path.js +49 -0
  279. package/dist/core/tenancy/tenant-state-path.js.map +1 -0
  280. package/dist/core/wiki/project.d.ts +17 -0
  281. package/dist/core/wiki/project.js +37 -0
  282. package/dist/core/wiki/project.js.map +1 -0
  283. package/dist/core/wiki/reconcile.d.ts +15 -0
  284. package/dist/core/wiki/reconcile.js +14 -0
  285. package/dist/core/wiki/reconcile.js.map +1 -0
  286. package/dist/core/wiki/render.d.ts +5 -0
  287. package/dist/core/wiki/render.js +84 -0
  288. package/dist/core/wiki/render.js.map +1 -0
  289. package/dist/core/wiki/rollup.d.ts +28 -0
  290. package/dist/core/wiki/rollup.js +91 -0
  291. package/dist/core/wiki/rollup.js.map +1 -0
  292. package/dist/core/wiki/select.d.ts +8 -0
  293. package/dist/core/wiki/select.js +7 -0
  294. package/dist/core/wiki/select.js.map +1 -0
  295. package/dist/core/wiki/slug.d.ts +36 -0
  296. package/dist/core/wiki/slug.js +71 -0
  297. package/dist/core/wiki/slug.js.map +1 -0
  298. package/dist/core/wiki/types.d.ts +37 -0
  299. package/dist/core/wiki/types.js +2 -0
  300. package/dist/core/wiki/types.js.map +1 -0
  301. package/dist/core/work-digest/build-work-digest.d.ts +1 -1
  302. package/dist/core/work-digest/build-work-digest.js +3 -3
  303. package/dist/core/work-digest/build-work-digest.js.map +1 -1
  304. package/dist/core/workstream/bind.d.ts +1 -1
  305. package/dist/core/workstream/bind.js +10 -10
  306. package/dist/core/workstream/bind.js.map +1 -1
  307. package/dist/core/workstream/rollup.d.ts +1 -1
  308. package/dist/core/workstream/rollup.js +6 -6
  309. package/dist/core/workstream/rollup.js.map +1 -1
  310. package/dist/hook/hook-helpers.d.ts +14 -0
  311. package/dist/hook/hook-helpers.js +29 -2
  312. package/dist/hook/hook-helpers.js.map +1 -1
  313. package/dist/hook/pre-compact-hook.js +6 -4
  314. package/dist/hook/pre-compact-hook.js.map +1 -1
  315. package/dist/hook/prompt-recall-hook.d.ts +5 -2
  316. package/dist/hook/prompt-recall-hook.js +28 -17
  317. package/dist/hook/prompt-recall-hook.js.map +1 -1
  318. package/dist/hook/recall-over-http.d.ts +27 -3
  319. package/dist/hook/recall-over-http.js +44 -11
  320. package/dist/hook/recall-over-http.js.map +1 -1
  321. package/dist/hook/session-end-hook.js +7 -5
  322. package/dist/hook/session-end-hook.js.map +1 -1
  323. package/dist/hook/session-start-hook.d.ts +14 -1
  324. package/dist/hook/session-start-hook.js +55 -15
  325. package/dist/hook/session-start-hook.js.map +1 -1
  326. package/dist/hook/stop-hook.js +9 -7
  327. package/dist/hook/stop-hook.js.map +1 -1
  328. package/dist/http/app.d.ts +41 -3
  329. package/dist/http/app.js +355 -96
  330. package/dist/http/app.js.map +1 -1
  331. package/dist/install/claude-code.d.ts +17 -0
  332. package/dist/install/claude-code.js +44 -5
  333. package/dist/install/claude-code.js.map +1 -1
  334. package/dist/install/codex.d.ts +23 -2
  335. package/dist/install/codex.js +111 -14
  336. package/dist/install/codex.js.map +1 -1
  337. package/dist/install/cursor.d.ts +2 -2
  338. package/dist/install/cursor.js +7 -7
  339. package/dist/install/cursor.js.map +1 -1
  340. package/dist/install/hermes.d.ts +8 -0
  341. package/dist/install/hermes.js +28 -5
  342. package/dist/install/hermes.js.map +1 -1
  343. package/dist/install/local-source.d.ts +20 -0
  344. package/dist/install/local-source.js +28 -0
  345. package/dist/install/local-source.js.map +1 -0
  346. package/dist/install/mcp-block.d.ts +77 -0
  347. package/dist/install/mcp-block.js +99 -0
  348. package/dist/install/mcp-block.js.map +1 -0
  349. package/dist/install/pi.d.ts +26 -0
  350. package/dist/install/pi.js +43 -0
  351. package/dist/install/pi.js.map +1 -1
  352. package/dist/install/setup.js +6 -0
  353. package/dist/install/setup.js.map +1 -1
  354. package/dist/install/windsurf.d.ts +2 -2
  355. package/dist/install/windsurf.js +7 -7
  356. package/dist/install/windsurf.js.map +1 -1
  357. package/dist/llm/classifier-box.d.ts +5 -0
  358. package/dist/llm/classifier-box.js +5 -0
  359. package/dist/llm/classifier-box.js.map +1 -1
  360. package/dist/mcp/server.d.ts +73 -16
  361. package/dist/mcp/server.js +306 -83
  362. package/dist/mcp/server.js.map +1 -1
  363. package/dist/ports/clock.d.ts +12 -0
  364. package/dist/ports/clock.js +10 -0
  365. package/dist/ports/clock.js.map +1 -0
  366. package/dist/ports/code-exemplar-store.d.ts +13 -13
  367. package/dist/ports/entity-store.d.ts +5 -1
  368. package/dist/ports/fact-store.d.ts +0 -0
  369. package/dist/ports/fact-store.js +0 -0
  370. package/dist/ports/fact-store.js.map +1 -1
  371. package/dist/ports/learner-store.d.ts +80 -0
  372. package/dist/ports/learner-store.js +19 -0
  373. package/dist/ports/learner-store.js.map +1 -0
  374. package/dist/ports/outcome.d.ts +3 -3
  375. package/dist/ports/session-store.d.ts +20 -14
  376. package/dist/ports/session-store.js +5 -0
  377. package/dist/ports/session-store.js.map +1 -1
  378. package/dist/ports/signal-store.d.ts +12 -8
  379. package/dist/ports/spawn-child.d.ts +14 -0
  380. package/dist/ports/spawn-child.js +10 -0
  381. package/dist/ports/spawn-child.js.map +1 -0
  382. package/dist/ports/storage.d.ts +6 -0
  383. package/dist/ports/transcript-adapter.d.ts +11 -0
  384. package/dist/ports/wiki-writer.d.ts +19 -0
  385. package/dist/ports/wiki-writer.js +12 -0
  386. package/dist/ports/wiki-writer.js.map +1 -0
  387. package/dist/ports/workstream-store.d.ts +19 -12
  388. package/dist/shared/types.d.ts +22 -0
  389. package/dist/shared/types.js.map +1 -1
  390. package/dist/shared/version.d.ts +9 -0
  391. package/dist/shared/version.js +11 -0
  392. package/dist/shared/version.js.map +1 -0
  393. package/dist/ui/assets/index-D6F3xAis.js +11 -0
  394. package/dist/ui/index.html +1 -1
  395. package/migrations/033_actions_kind_check.sql +58 -0
  396. package/migrations/034_tenancy_teams_and_stamps.sql +40 -0
  397. package/migrations/035_tenancy_entity_rekey.sql +75 -0
  398. package/migrations/036_tenant_name_uniqueness.sql +59 -0
  399. package/migrations/037_sessions_covering_index.sql +25 -0
  400. package/migrations/038_sources_muse.sql +33 -0
  401. package/migrations/039_learner_evidence.sql +51 -0
  402. package/migrations/pg/033_actions_kind_check.sql +17 -0
  403. package/migrations/pg/034_tenancy.sql +77 -0
  404. package/migrations/pg/035_tenant_name_uniqueness.sql +15 -0
  405. package/migrations/pg/036_sources_muse.sql +12 -0
  406. package/migrations/pg/037_learner_evidence.sql +55 -0
  407. package/nlm/index.js +246 -55
  408. package/package.json +10 -5
  409. package/plugin/.codex-plugin/plugin.json +2 -2
  410. package/plugin/scripts/prompt-recall-hook.mjs +244 -55
  411. package/plugin/scripts/session-start-hook.mjs +273 -53
  412. package/plugin/scripts/stop-hook.mjs +195 -37
  413. package/dist/ui/assets/index-CSaBtgXD.js +0 -11
package/nlm/index.js CHANGED
@@ -191,6 +191,133 @@ function extractRecallQuery(prompt) {
191
191
  }
192
192
 
193
193
  // src/hook/hook-helpers.ts
194
+ import { appendFileSync, mkdirSync, realpathSync } from "node:fs";
195
+ import { pathToFileURL } from "node:url";
196
+
197
+ // package.json
198
+ var package_default = {
199
+ name: "nlm-memory",
200
+ version: "0.21.13",
201
+ description: "Local-first non-linear memory operating system for AI operators.",
202
+ type: "module",
203
+ license: "Apache-2.0",
204
+ engines: {
205
+ node: ">=22.0.0"
206
+ },
207
+ repository: {
208
+ type: "git",
209
+ url: "git+https://github.com/pbmagnet4/nlm-memory.git"
210
+ },
211
+ homepage: "https://github.com/pbmagnet4/nlm-memory#readme",
212
+ bugs: {
213
+ url: "https://github.com/pbmagnet4/nlm-memory/issues"
214
+ },
215
+ keywords: [
216
+ "ai",
217
+ "memory",
218
+ "mcp",
219
+ "claude-code",
220
+ "codex",
221
+ "hermes",
222
+ "local-first",
223
+ "recall",
224
+ "session-memory"
225
+ ],
226
+ files: [
227
+ "dist",
228
+ "migrations",
229
+ "fixtures",
230
+ "templates",
231
+ "plugin",
232
+ "plugin-hermes-agent",
233
+ "nlm",
234
+ "assets",
235
+ "LICENSE",
236
+ "README.md"
237
+ ],
238
+ bin: {
239
+ nlm: "dist/cli/nlm.js"
240
+ },
241
+ scripts: {
242
+ dev: "tsx watch src/cli/nlm.ts start",
243
+ start: "node dist/cli/nlm.js start",
244
+ "build:server": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
245
+ "build:ui": "vite build --config src/ui/vite.config.ts",
246
+ "build:codex-plugin": "node scripts/build-codex-plugin.mjs",
247
+ "verify:codex-release": "node scripts/verify-codex-release.mjs",
248
+ build: "npm run build:server && npm run build:ui && npm run build:codex-plugin",
249
+ prepare: "[ -d src ] && npm run build || true",
250
+ "ui:dev": "vite --config src/ui/vite.config.ts",
251
+ test: "vitest run",
252
+ "test:watch": "vitest",
253
+ "test:unit": "vitest run tests/unit",
254
+ "test:integration": "vitest run tests/integration",
255
+ "test:pg": "vitest run .pg.test.ts --test-timeout=20000",
256
+ typecheck: "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json",
257
+ "bench:longmemeval": "tsx scripts/longmemeval/run-harness.ts",
258
+ "bench:classifier": "tsx scripts/longmemeval/run-harness.ts --classifier",
259
+ "bench:compare": "tsx scripts/longmemeval/compare-classifiers.ts",
260
+ "eval:signals": "tsx scripts/eval/signals-eval.ts",
261
+ "eval:classifier": "tsx scripts/eval/classifier-eval.ts",
262
+ "eval:fact-recall": "tsx scripts/eval/fact-recall-eval.ts",
263
+ "eval:recall-impact-replay": "tsx scripts/eval/recall-impact-replay.ts",
264
+ "eval:code-exemplar": "tsx scripts/eval/code-exemplar-eval.ts",
265
+ "eval:reranker": "tsx scripts/eval/reranker-ablation.ts",
266
+ "eval:floor": "tsx scripts/eval/floor-calibration.ts",
267
+ "eval:matcher": "tsx scripts/eval/tune-matcher.ts",
268
+ "eval:naming": "tsx scripts/eval/tune-naming.ts",
269
+ "eval:rederiv-sample": "tsx scripts/eval/re-derivation-sample.ts",
270
+ "eval:rederiv-label": "tsx scripts/eval/re-derivation-label.ts",
271
+ "eval:rederiv-calibrate": "tsx scripts/eval/re-derivation-calibrate.ts"
272
+ },
273
+ dependencies: {
274
+ "@clack/prompts": "^1.4.0",
275
+ "@hono/node-server": "^2.0.3",
276
+ "@huggingface/transformers": "4.2.0",
277
+ "@modelcontextprotocol/sdk": "^1.29.0",
278
+ "@toon-format/toon": "^2.3.0",
279
+ "better-sqlite3": "^13.0.1",
280
+ commander: "^15.0.0",
281
+ hono: "^4.6.0",
282
+ pg: "^8.21.0",
283
+ pgvector: "^0.3.0",
284
+ "sqlite-vec": "^0.1.6",
285
+ yaml: "^2.9.0",
286
+ zod: "^4.4.3"
287
+ },
288
+ devDependencies: {
289
+ "@types/better-sqlite3": "^7.6.13",
290
+ "@types/node": "^22.10.0",
291
+ "@types/pg": "^8.20.0",
292
+ "@types/react": "^19.2.17",
293
+ "@types/react-dom": "^19.2.3",
294
+ "@vitejs/plugin-react": "^6.0.2",
295
+ esbuild: "^0.28.0",
296
+ react: "^19.2.7",
297
+ "react-dom": "^19.2.7",
298
+ "react-router-dom": "^6.30.3",
299
+ "tsc-alias": "^1.8.17",
300
+ tsx: "^4.19.0",
301
+ typescript: "^6.0.3",
302
+ vite: "^8.0.16",
303
+ vitest: "^4.1.8"
304
+ }
305
+ };
306
+
307
+ // src/shared/version.ts
308
+ var NLM_VERSION = package_default.version;
309
+
310
+ // src/hook/hook-helpers.ts
311
+ function isMainModule(metaUrl, argv1) {
312
+ if (!argv1) return false;
313
+ let resolved;
314
+ try {
315
+ resolved = realpathSync(argv1);
316
+ } catch {
317
+ return false;
318
+ }
319
+ return metaUrl === pathToFileURL(resolved).href;
320
+ }
194
321
  function readStdin() {
195
322
  return new Promise((resolve2) => {
196
323
  let data = "";
@@ -223,27 +350,36 @@ function parseRecallTimeout(raw) {
223
350
  const n = Number(raw);
224
351
  return Number.isFinite(n) && n > 0 ? n : 4e3;
225
352
  }
226
- var RECALL_TIMEOUT_MS = parseRecallTimeout(process.env["NLM_HOOK_RECALL_TIMEOUT_MS"]);
227
- async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword") {
353
+ function recallTimeoutMs() {
354
+ return parseRecallTimeout(process.env["NLM_HOOK_RECALL_TIMEOUT_MS"]);
355
+ }
356
+ var emptyResult = (outcome) => ({
357
+ hits: [],
358
+ facts: [],
359
+ exemplars: [],
360
+ concepts: [],
361
+ outcome
362
+ });
363
+ async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword", source = "hook") {
228
364
  const query = extractRecallQuery(prompt);
229
- if (query === null) return { hits: [], facts: [], exemplars: [] };
365
+ if (query === null) return emptyResult("skipped");
230
366
  const portValue = process.env["NLM_PORT"] ?? DEFAULT_NLM_PORT;
231
367
  const url = (
232
368
  // 127.0.0.1, not localhost: each hook is a fresh process with no connection
233
369
  // reuse, and Node resolves localhost to IPv6 ::1 first — a measured ~50-300ms
234
370
  // per-fire connect penalty vs ~3ms on the explicit IPv4 loopback.
235
- `http://127.0.0.1:${portValue}/api/recall?q=${encodeURIComponent(query)}&mode=${mode}&limit=${RECALL_LIMIT}&withFacts=true&withExemplars=true` + (conversationId ? `&conversation_id=${encodeURIComponent(conversationId)}` : "")
371
+ `http://127.0.0.1:${portValue}/api/recall?q=${encodeURIComponent(query)}&mode=${mode}&limit=${RECALL_LIMIT}&withFacts=true&withExemplars=true&withConcepts=true` + (conversationId ? `&conversation_id=${encodeURIComponent(conversationId)}` : "")
236
372
  );
237
373
  try {
238
- const extra = { "x-recall-source": "hook" };
374
+ const extra = { "x-recall-source": source };
239
375
  if (runtime) extra["x-recall-runtime"] = runtime;
240
- const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) }, RECALL_TIMEOUT_MS);
241
- if (!res.ok) return { hits: [], facts: [], exemplars: [] };
376
+ const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) }, recallTimeoutMs());
377
+ if (!res.ok) return emptyResult("http-error");
242
378
  let body;
243
379
  try {
244
380
  body = await res.json();
245
381
  } catch {
246
- return { hits: [], facts: [], exemplars: [] };
382
+ return emptyResult("http-error");
247
383
  }
248
384
  const hits = (body.results ?? []).map((r) => ({
249
385
  id: r.id,
@@ -264,15 +400,19 @@ async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword")
264
400
  repo: e.repo,
265
401
  taskContext: e.taskContext
266
402
  }));
267
- return { hits, facts, exemplars };
268
- } catch {
269
- return { hits: [], facts: [], exemplars: [] };
403
+ const concepts = (body.relatedConcepts ?? []).map((c) => ({
404
+ concept: c.concept,
405
+ status: c.status,
406
+ attemptCount: c.attemptCount,
407
+ nextStep: c.nextStep
408
+ }));
409
+ return { hits, facts, exemplars, concepts, outcome: "ok" };
410
+ } catch (err) {
411
+ const aborted = err instanceof Error && err.name === "AbortError";
412
+ return emptyResult(aborted ? "timeout" : "unreachable");
270
413
  }
271
414
  }
272
415
 
273
- // src/hook/prompt-recall-hook.ts
274
- import { pathToFileURL } from "node:url";
275
-
276
416
  // src/core/hook/gate.ts
277
417
  var LEADING_FILLER = /^(please|can you|could you|would you|will you|i need you to|i'd like you to|i want you to|i would like you to|help me|let's|lets|hey|ok|okay)\b[\s,]*/i;
278
418
  var GENERATIVE_OPENER = /^(write|draft|create|compose|generate|brainstorm|design|outline|sketch|invent|rename|come up with)\b/i;
@@ -463,17 +603,47 @@ function recentConversationContext(transcriptPath, opts = {}) {
463
603
  }
464
604
 
465
605
  // src/core/hook/hook-log.ts
466
- import { appendFileSync, mkdirSync } from "node:fs";
606
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
607
+ import { dirname } from "node:path";
608
+
609
+ // src/core/tenancy/tenant-state-path.ts
610
+ import { createHash } from "node:crypto";
467
611
  import { homedir as homedir2 } from "node:os";
468
- import { dirname, join } from "node:path";
469
- function logPath() {
470
- return process.env["NLM_HOOK_LOG"] ?? join(homedir2(), ".nlm", "hook-log.jsonl");
612
+ import { join } from "node:path";
613
+
614
+ // src/core/tenancy/default-team.ts
615
+ var DEFAULT_TEAM_ID = "team_local";
616
+
617
+ // src/core/tenancy/tenant-state-path.ts
618
+ var TENANTS_DIRNAME = "tenants";
619
+ var SAFE_TENANT_ID = /^[A-Za-z0-9_-]+$/;
620
+ function sanitizeTenantId(tenantId) {
621
+ if (SAFE_TENANT_ID.test(tenantId)) return tenantId;
622
+ const sanitized = tenantId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
623
+ const hash = createHash("sha256").update(tenantId).digest("hex").slice(0, 8);
624
+ return `${sanitized}_${hash}`;
625
+ }
626
+ function stateRoot() {
627
+ return process.env["NLM_STATE_ROOT"] || join(homedir2(), ".nlm");
628
+ }
629
+ function tenantStatePath(tenantId, ...segments) {
630
+ const base = stateRoot();
631
+ if (tenantId === DEFAULT_TEAM_ID) return join(base, ...segments);
632
+ return join(base, TENANTS_DIRNAME, sanitizeTenantId(tenantId), ...segments);
633
+ }
634
+
635
+ // src/core/hook/hook-log.ts
636
+ function logPath(tenantId) {
637
+ if (tenantId === DEFAULT_TEAM_ID) {
638
+ return process.env["NLM_HOOK_LOG"] ?? tenantStatePath(tenantId, "hook-log.jsonl");
639
+ }
640
+ return tenantStatePath(tenantId, "hook-log.jsonl");
471
641
  }
472
- function appendHookLog(entry) {
642
+ function appendHookLog(tenantId, entry) {
473
643
  try {
474
- const path = logPath();
475
- mkdirSync(dirname(path), { recursive: true });
476
- appendFileSync(path, `${JSON.stringify(entry)}
644
+ const path = logPath(tenantId);
645
+ mkdirSync2(dirname(path), { recursive: true });
646
+ appendFileSync2(path, `${JSON.stringify({ ...entry, v: NLM_VERSION })}
477
647
  `, "utf8");
478
648
  } catch {
479
649
  }
@@ -482,25 +652,27 @@ function appendHookLog(entry) {
482
652
  // src/core/hook/memo.ts
483
653
  import {
484
654
  existsSync as existsSync3,
485
- mkdirSync as mkdirSync2,
655
+ mkdirSync as mkdirSync3,
486
656
  readdirSync,
487
657
  readFileSync as readFileSync2,
488
658
  rmSync,
489
659
  statSync,
490
660
  writeFileSync
491
661
  } from "node:fs";
492
- import { homedir as homedir3 } from "node:os";
493
662
  import { join as join2 } from "node:path";
494
- function stateDir() {
495
- return process.env["NLM_HOOK_STATE_DIR"] ?? join2(homedir3(), ".nlm", "hook-state");
663
+ function stateDir(tenantId) {
664
+ if (tenantId === DEFAULT_TEAM_ID) {
665
+ return process.env["NLM_HOOK_STATE_DIR"] ?? tenantStatePath(tenantId, "hook-state");
666
+ }
667
+ return tenantStatePath(tenantId, "hook-state");
496
668
  }
497
- function memoPath(conversationId) {
669
+ function memoPath(tenantId, conversationId) {
498
670
  const safe = conversationId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
499
- return join2(stateDir(), `${safe}.json`);
671
+ return join2(stateDir(tenantId), `${safe}.json`);
500
672
  }
501
- function loadSurfaced(conversationId) {
673
+ function loadSurfaced(tenantId, conversationId) {
502
674
  try {
503
- const path = memoPath(conversationId);
675
+ const path = memoPath(tenantId, conversationId);
504
676
  if (!existsSync3(path)) return /* @__PURE__ */ new Set();
505
677
  const parsed = JSON.parse(readFileSync2(path, "utf8"));
506
678
  if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
@@ -509,12 +681,12 @@ function loadSurfaced(conversationId) {
509
681
  return /* @__PURE__ */ new Set();
510
682
  }
511
683
  }
512
- function recordSurfaced(conversationId, ids) {
684
+ function recordSurfaced(tenantId, conversationId, ids) {
513
685
  try {
514
- const merged = loadSurfaced(conversationId);
686
+ const merged = loadSurfaced(tenantId, conversationId);
515
687
  for (const id of ids) merged.add(id);
516
- mkdirSync2(stateDir(), { recursive: true });
517
- writeFileSync(memoPath(conversationId), JSON.stringify([...merged]), "utf8");
688
+ mkdirSync3(stateDir(tenantId), { recursive: true });
689
+ writeFileSync(memoPath(tenantId, conversationId), JSON.stringify([...merged]), "utf8");
518
690
  } catch {
519
691
  }
520
692
  }
@@ -540,8 +712,8 @@ function truncateSummary(s, max = 200) {
540
712
  }
541
713
  return window + " ...";
542
714
  }
543
- function formatPointerBlock(hits, facts = [], exemplars = []) {
544
- if (hits.length === 0 && facts.length === 0 && exemplars.length === 0) return "";
715
+ function formatPointerBlock(hits, facts = [], exemplars = [], concepts = []) {
716
+ if (hits.length === 0 && facts.length === 0 && exemplars.length === 0 && concepts.length === 0) return "";
545
717
  const out = [];
546
718
  if (hits.length > 0) {
547
719
  out.push("## Possibly-relevant prior sessions (nlm-memory)");
@@ -570,7 +742,19 @@ function formatPointerBlock(hits, facts = [], exemplars = []) {
570
742
  out.push(`- [${e.outcome}] ${langPart}${e.repo} - ${truncateSummary(e.taskContext)}`);
571
743
  }
572
744
  }
573
- const tools = exemplars.length > 0 ? "NLM tools: recall_sessions (search), get_session (full transcript), recall_facts (prior decisions), get_fact_history (how a decision evolved), recall_code (pull the full code for a related exemplar)." : "NLM tools: recall_sessions (search), get_session (full transcript), recall_facts (prior decisions), get_fact_history (how a decision evolved).";
745
+ if (concepts.length > 0) {
746
+ if (out.length > 0) out.push("");
747
+ out.push("## Learning state (nlm-memory)");
748
+ for (const c of concepts) {
749
+ const n = c.attemptCount === 1 ? "1 attempt" : `${c.attemptCount} attempts`;
750
+ out.push(`- [${c.status}] ${c.concept} (${n})`);
751
+ }
752
+ const nextSteps = [...new Set(concepts.map((c) => c.nextStep).filter((s) => !!s))].slice(0, 2);
753
+ for (const next of nextSteps) {
754
+ out.push(`Next: ${truncateSummary(next, 120)}`);
755
+ }
756
+ }
757
+ const tools = exemplars.length > 0 ? "NLM tools: recall_sessions (search), get_session (full transcript), recall_facts (prior decisions), get_fact_history (how a decision evolved), recall_code (pull the full code for a related exemplar), learner_summary (concept mastery + next step)." : "NLM tools: recall_sessions (search), get_session (full transcript), recall_facts (prior decisions), get_fact_history (how a decision evolved), learner_summary (concept mastery + next step).";
574
758
  out.push(tools);
575
759
  return out.join("\n");
576
760
  }
@@ -582,10 +766,10 @@ function medianScore(hits) {
582
766
  return sorted[Math.floor(sorted.length / 2)] ?? 0;
583
767
  }
584
768
  function selectHits(params) {
585
- const { hits, surfaced, scoreThreshold, perFireCap, perConversationCap, relativeFloor = 0 } = params;
586
- const relCut = relativeFloor > 0 ? relativeFloor * medianScore(hits) : 0;
769
+ const { hits, surfaced, scoreThreshold: scoreThreshold2, perFireCap, perConversationCap, relativeFloor: relativeFloor2 = 0 } = params;
770
+ const relCut = relativeFloor2 > 0 ? relativeFloor2 * medianScore(hits) : 0;
587
771
  const eligible = hits.filter(
588
- (h) => h.matchScore >= scoreThreshold && h.matchScore >= relCut && !surfaced.has(h.id)
772
+ (h) => h.matchScore >= scoreThreshold2 && h.matchScore >= relCut && !surfaced.has(h.id)
589
773
  );
590
774
  const budget = Math.max(0, perConversationCap - surfaced.size);
591
775
  const limit = Math.min(perFireCap, budget);
@@ -655,8 +839,8 @@ ${candidate}` }
655
839
  }
656
840
 
657
841
  // src/hook/prompt-recall-hook.ts
658
- var SCORE_THRESHOLD = parseScoreFloor(process.env["NLM_RECALL_SCORE_FLOOR"]);
659
- var RELATIVE_FLOOR = parseRelativeFloor(process.env["NLM_RECALL_REL_FLOOR"], 0.9);
842
+ var scoreThreshold = () => parseScoreFloor(process.env["NLM_RECALL_SCORE_FLOOR"]);
843
+ var relativeFloor = () => parseRelativeFloor(process.env["NLM_RECALL_REL_FLOOR"], 0.9);
660
844
  var PER_FIRE_CAP = 3;
661
845
  var PER_CONVERSATION_CAP = 10;
662
846
  var PROMPT_PREVIEW_CHARS = 200;
@@ -665,7 +849,9 @@ function parseHookDeadline(raw, defaultMs = 4e3) {
665
849
  const n = Number(raw);
666
850
  return Number.isFinite(n) && n > 0 ? n : defaultMs;
667
851
  }
668
- var HOOK_DEADLINE_MS = parseHookDeadline(process.env["NLM_HOOK_DEADLINE_MS"], 6e3);
852
+ function hookDeadlineMs() {
853
+ return parseHookDeadline(process.env["NLM_HOOK_DEADLINE_MS"], 6e3);
854
+ }
669
855
  async function withDeadline(p, ms, fallback) {
670
856
  if (ms <= 0) return fallback;
671
857
  let timer;
@@ -703,7 +889,7 @@ async function runHook(input, deps) {
703
889
  const gate = classifyPrompt(input.prompt);
704
890
  const preview = input.prompt.slice(0, PROMPT_PREVIEW_CHARS);
705
891
  if (gate === "generative" || gate === "skip") {
706
- appendHookLog({
892
+ appendHookLog(DEFAULT_TEAM_ID, {
707
893
  ts: (/* @__PURE__ */ new Date()).toISOString(),
708
894
  conversationId: input.conversationId,
709
895
  promptPreview: preview,
@@ -715,22 +901,26 @@ async function runHook(input, deps) {
715
901
  });
716
902
  return "";
717
903
  }
718
- const deadline = Date.now() + (deps.deadlineMs ?? HOOK_DEADLINE_MS);
719
- let fetched = { hits: [], facts: [] };
904
+ const deadline = Date.now() + (deps.deadlineMs ?? hookDeadlineMs());
905
+ let fetched = { hits: [], facts: [], outcome: "timeout" };
720
906
  try {
721
907
  fetched = normalizeRecall(
722
- await withDeadline(deps.recall(buildRecallQuery(input)), deadline - Date.now(), { hits: [], facts: [] })
908
+ await withDeadline(
909
+ deps.recall(buildRecallQuery(input)),
910
+ deadline - Date.now(),
911
+ { hits: [], facts: [], outcome: "timeout" }
912
+ )
723
913
  );
724
914
  } catch {
725
- fetched = { hits: [], facts: [] };
915
+ fetched = { hits: [], facts: [], outcome: "unreachable" };
726
916
  }
727
917
  const hits = fetched.hits;
728
- const surfaced = loadSurfaced(input.conversationId);
918
+ const surfaced = loadSurfaced(DEFAULT_TEAM_ID, input.conversationId);
729
919
  const selected = selectHits({
730
920
  hits,
731
921
  surfaced,
732
- scoreThreshold: SCORE_THRESHOLD,
733
- relativeFloor: RELATIVE_FLOOR,
922
+ scoreThreshold: scoreThreshold(),
923
+ relativeFloor: relativeFloor(),
734
924
  perFireCap: PER_FIRE_CAP,
735
925
  perConversationCap: PER_CONVERSATION_CAP
736
926
  });
@@ -756,9 +946,9 @@ ${h.summary ?? ""}`) }))),
756
946
  injected = selected.filter((h) => !drop.has(h.id));
757
947
  }
758
948
  }
759
- const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars);
949
+ const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars, fetched.concepts ?? []);
760
950
  const estTokens = Math.ceil(block.length / 4);
761
- appendHookLog({
951
+ appendHookLog(DEFAULT_TEAM_ID, {
762
952
  ts: (/* @__PURE__ */ new Date()).toISOString(),
763
953
  conversationId: input.conversationId,
764
954
  promptPreview: preview,
@@ -767,10 +957,11 @@ ${h.summary ?? ""}`) }))),
767
957
  wouldInject: injected.map((h) => h.id),
768
958
  estTokens,
769
959
  mode: deps.mode,
960
+ ...fetched.outcome ? { recallOutcome: fetched.outcome } : {},
770
961
  ...gateDecisions ? { gateDecisions } : {}
771
962
  });
772
963
  if (deps.mode === "live" && injected.length > 0) {
773
- recordSurfaced(input.conversationId, injected.map((h) => h.id));
964
+ recordSurfaced(DEFAULT_TEAM_ID, input.conversationId, injected.map((h) => h.id));
774
965
  return block;
775
966
  }
776
967
  return "";
@@ -802,7 +993,7 @@ async function main() {
802
993
  } catch {
803
994
  }
804
995
  }
805
- if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
996
+ if (isMainModule(import.meta.url, process.argv[1])) {
806
997
  void main();
807
998
  }
808
999
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nlm-memory",
3
- "version": "0.21.0",
3
+ "version": "0.21.13",
4
4
  "description": "Local-first non-linear memory operating system for AI operators.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -47,6 +47,7 @@
47
47
  "build:server": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
48
48
  "build:ui": "vite build --config src/ui/vite.config.ts",
49
49
  "build:codex-plugin": "node scripts/build-codex-plugin.mjs",
50
+ "verify:codex-release": "node scripts/verify-codex-release.mjs",
50
51
  "build": "npm run build:server && npm run build:ui && npm run build:codex-plugin",
51
52
  "prepare": "[ -d src ] && npm run build || true",
52
53
  "ui:dev": "vite --config src/ui/vite.config.ts",
@@ -54,19 +55,23 @@
54
55
  "test:watch": "vitest",
55
56
  "test:unit": "vitest run tests/unit",
56
57
  "test:integration": "vitest run tests/integration",
57
- "test:pg": "vitest run --no-file-parallelism .pg.test.ts",
58
- "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
58
+ "test:pg": "vitest run .pg.test.ts --test-timeout=20000",
59
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json",
59
60
  "bench:longmemeval": "tsx scripts/longmemeval/run-harness.ts",
60
61
  "bench:classifier": "tsx scripts/longmemeval/run-harness.ts --classifier",
61
62
  "bench:compare": "tsx scripts/longmemeval/compare-classifiers.ts",
62
63
  "eval:signals": "tsx scripts/eval/signals-eval.ts",
63
64
  "eval:classifier": "tsx scripts/eval/classifier-eval.ts",
64
65
  "eval:fact-recall": "tsx scripts/eval/fact-recall-eval.ts",
66
+ "eval:recall-impact-replay": "tsx scripts/eval/recall-impact-replay.ts",
65
67
  "eval:code-exemplar": "tsx scripts/eval/code-exemplar-eval.ts",
66
68
  "eval:reranker": "tsx scripts/eval/reranker-ablation.ts",
67
69
  "eval:floor": "tsx scripts/eval/floor-calibration.ts",
68
70
  "eval:matcher": "tsx scripts/eval/tune-matcher.ts",
69
- "eval:naming": "tsx scripts/eval/tune-naming.ts"
71
+ "eval:naming": "tsx scripts/eval/tune-naming.ts",
72
+ "eval:rederiv-sample": "tsx scripts/eval/re-derivation-sample.ts",
73
+ "eval:rederiv-label": "tsx scripts/eval/re-derivation-label.ts",
74
+ "eval:rederiv-calibrate": "tsx scripts/eval/re-derivation-calibrate.ts"
70
75
  },
71
76
  "dependencies": {
72
77
  "@clack/prompts": "^1.4.0",
@@ -74,7 +79,7 @@
74
79
  "@huggingface/transformers": "4.2.0",
75
80
  "@modelcontextprotocol/sdk": "^1.29.0",
76
81
  "@toon-format/toon": "^2.3.0",
77
- "better-sqlite3": "^12.10.0",
82
+ "better-sqlite3": "^13.0.1",
78
83
  "commander": "^15.0.0",
79
84
  "hono": "^4.6.0",
80
85
  "pg": "^8.21.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nlm-memory",
3
- "version": "0.21.0",
3
+ "version": "0.21.13",
4
4
  "description": "Local-first persistent memory for AI coding agents. Recalls relevant prior sessions on every prompt; learns which sessions actually get cited. Owner-edited timeline beats append-only memory layers.",
5
5
  "author": {
6
6
  "name": "Edward Chalupa",
@@ -19,4 +19,4 @@
19
19
  ],
20
20
  "mcpServers": "./.mcp.json",
21
21
  "hooks": "./hooks/hooks.json"
22
- }
22
+ }