nlm-memory 0.20.1 → 0.21.12

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 (475) hide show
  1. package/README.md +69 -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 +69 -4
  5. package/dist/cli/digest.js.map +1 -1
  6. package/dist/cli/nlm.d.ts +14 -0
  7. package/dist/cli/nlm.js +556 -71
  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-backfill.d.ts +34 -0
  13. package/dist/cli/scope-backfill.js +237 -0
  14. package/dist/cli/scope-backfill.js.map +1 -0
  15. package/dist/cli/scope-coverage.d.ts +44 -0
  16. package/dist/cli/scope-coverage.js +208 -0
  17. package/dist/cli/scope-coverage.js.map +1 -0
  18. package/dist/cli/supersede.js +8 -7
  19. package/dist/cli/supersede.js.map +1 -1
  20. package/dist/core/actions/actions-log.d.ts +65 -8
  21. package/dist/core/actions/actions-log.js +134 -17
  22. package/dist/core/actions/actions-log.js.map +1 -1
  23. package/dist/core/actions/overlay.d.ts +11 -2
  24. package/dist/core/actions/overlay.js +18 -6
  25. package/dist/core/actions/overlay.js.map +1 -1
  26. package/dist/core/adapters/claude-code.d.ts +14 -0
  27. package/dist/core/adapters/claude-code.js +30 -0
  28. package/dist/core/adapters/claude-code.js.map +1 -1
  29. package/dist/core/adapters/from-source.js +11 -3
  30. package/dist/core/adapters/from-source.js.map +1 -1
  31. package/dist/core/adapters/fs-wiki-writer.d.ts +44 -0
  32. package/dist/core/adapters/fs-wiki-writer.js +132 -0
  33. package/dist/core/adapters/fs-wiki-writer.js.map +1 -0
  34. package/dist/core/adapters/hermes-agent.d.ts +15 -2
  35. package/dist/core/adapters/hermes-agent.js +57 -11
  36. package/dist/core/adapters/hermes-agent.js.map +1 -1
  37. package/dist/core/adapters/memory-wiki-writer.d.ts +8 -0
  38. package/dist/core/adapters/memory-wiki-writer.js +16 -0
  39. package/dist/core/adapters/memory-wiki-writer.js.map +1 -0
  40. package/dist/core/adapters/muse.d.ts +51 -0
  41. package/dist/core/adapters/muse.js +271 -0
  42. package/dist/core/adapters/muse.js.map +1 -0
  43. package/dist/core/adapters/opencode.d.ts +11 -4
  44. package/dist/core/adapters/opencode.js +41 -7
  45. package/dist/core/adapters/opencode.js.map +1 -1
  46. package/dist/core/alerts/alert-state.d.ts +17 -0
  47. package/dist/core/alerts/alert-state.js +45 -0
  48. package/dist/core/alerts/alert-state.js.map +1 -0
  49. package/dist/core/alerts/check-and-alert.d.ts +28 -0
  50. package/dist/core/alerts/check-and-alert.js +53 -0
  51. package/dist/core/alerts/check-and-alert.js.map +1 -0
  52. package/dist/core/alerts/drift-transition.d.ts +27 -0
  53. package/dist/core/alerts/drift-transition.js +56 -0
  54. package/dist/core/alerts/drift-transition.js.map +1 -0
  55. package/dist/core/alerts/embedder-transition.d.ts +23 -0
  56. package/dist/core/alerts/embedder-transition.js +40 -0
  57. package/dist/core/alerts/embedder-transition.js.map +1 -0
  58. package/dist/core/alerts/fire-alert.d.ts +24 -0
  59. package/dist/core/alerts/fire-alert.js +72 -0
  60. package/dist/core/alerts/fire-alert.js.map +1 -0
  61. package/dist/core/alerts/job-alert.d.ts +12 -0
  62. package/dist/core/alerts/job-alert.js +37 -0
  63. package/dist/core/alerts/job-alert.js.map +1 -0
  64. package/dist/core/alerts/types.d.ts +104 -0
  65. package/dist/core/alerts/types.js +11 -0
  66. package/dist/core/alerts/types.js.map +1 -0
  67. package/dist/core/alerts/wiki-alert.d.ts +15 -0
  68. package/dist/core/alerts/wiki-alert.js +31 -0
  69. package/dist/core/alerts/wiki-alert.js.map +1 -0
  70. package/dist/core/classifier/prompt.d.ts +13 -0
  71. package/dist/core/classifier/prompt.js +52 -2
  72. package/dist/core/classifier/prompt.js.map +1 -1
  73. package/dist/core/dataset/build-dataset.d.ts +16 -1
  74. package/dist/core/dataset/build-dataset.js +46 -13
  75. package/dist/core/dataset/build-dataset.js.map +1 -1
  76. package/dist/core/digest/compose.d.ts +11 -3
  77. package/dist/core/digest/compose.js +70 -17
  78. package/dist/core/digest/compose.js.map +1 -1
  79. package/dist/core/digest/hook-injection.d.ts +43 -0
  80. package/dist/core/digest/hook-injection.js +87 -0
  81. package/dist/core/digest/hook-injection.js.map +1 -0
  82. package/dist/core/digest/hook-version-parity.d.ts +31 -0
  83. package/dist/core/digest/hook-version-parity.js +56 -0
  84. package/dist/core/digest/hook-version-parity.js.map +1 -0
  85. package/dist/core/embedding/pg-embed-backfill.js +1 -1
  86. package/dist/core/embedding/pg-embed-backfill.js.map +1 -1
  87. package/dist/core/exemplars/capture-from-session.d.ts +2 -1
  88. package/dist/core/exemplars/capture-from-session.js +4 -4
  89. package/dist/core/exemplars/capture-from-session.js.map +1 -1
  90. package/dist/core/exemplars/embed-backfill.d.ts +9 -0
  91. package/dist/core/exemplars/embed-backfill.js +9 -1
  92. package/dist/core/exemplars/embed-backfill.js.map +1 -1
  93. package/dist/core/exemplars/extract-exemplar.d.ts +2 -0
  94. package/dist/core/exemplars/extract-exemplar.js +7 -1
  95. package/dist/core/exemplars/extract-exemplar.js.map +1 -1
  96. package/dist/core/exemplars/ingest-exemplar.d.ts +1 -0
  97. package/dist/core/exemplars/ingest-exemplar.js +1 -0
  98. package/dist/core/exemplars/ingest-exemplar.js.map +1 -1
  99. package/dist/core/exemplars/recall-code.d.ts +1 -1
  100. package/dist/core/exemplars/recall-code.js +2 -2
  101. package/dist/core/exemplars/recall-code.js.map +1 -1
  102. package/dist/core/facts/backfill-facts.d.ts +1 -1
  103. package/dist/core/facts/backfill-facts.js +4 -4
  104. package/dist/core/facts/backfill-facts.js.map +1 -1
  105. package/dist/core/facts/embed-backfill.d.ts +54 -0
  106. package/dist/core/facts/embed-backfill.js +109 -0
  107. package/dist/core/facts/embed-backfill.js.map +1 -0
  108. package/dist/core/facts/reconcile-facts.d.ts +42 -0
  109. package/dist/core/facts/reconcile-facts.js +133 -0
  110. package/dist/core/facts/reconcile-facts.js.map +1 -0
  111. package/dist/core/health/embed-failure-state.d.ts +4 -0
  112. package/dist/core/health/embed-failure-state.js +12 -0
  113. package/dist/core/health/embed-failure-state.js.map +1 -0
  114. package/dist/core/health/warmup-retry.d.ts +27 -0
  115. package/dist/core/health/warmup-retry.js +53 -0
  116. package/dist/core/health/warmup-retry.js.map +1 -0
  117. package/dist/core/health/warmup-state.d.ts +15 -0
  118. package/dist/core/health/warmup-state.js +15 -1
  119. package/dist/core/health/warmup-state.js.map +1 -1
  120. package/dist/core/hook/cite-memo.d.ts +11 -7
  121. package/dist/core/hook/cite-memo.js +25 -17
  122. package/dist/core/hook/cite-memo.js.map +1 -1
  123. package/dist/core/hook/claude-settings.d.ts +1 -1
  124. package/dist/core/hook/claude-settings.js +0 -1
  125. package/dist/core/hook/claude-settings.js.map +1 -1
  126. package/dist/core/hook/hook-log.d.ts +13 -2
  127. package/dist/core/hook/hook-log.js +16 -8
  128. package/dist/core/hook/hook-log.js.map +1 -1
  129. package/dist/core/hook/memo.d.ts +10 -6
  130. package/dist/core/hook/memo.js +25 -17
  131. package/dist/core/hook/memo.js.map +1 -1
  132. package/dist/core/hook/pointer-block.d.ts +8 -1
  133. package/dist/core/hook/pointer-block.js +17 -4
  134. package/dist/core/hook/pointer-block.js.map +1 -1
  135. package/dist/core/hook/resolve-conversation-by-query.d.ts +6 -5
  136. package/dist/core/hook/resolve-conversation-by-query.js +24 -12
  137. package/dist/core/hook/resolve-conversation-by-query.js.map +1 -1
  138. package/dist/core/ingest/backfill-derivables.d.ts +92 -0
  139. package/dist/core/ingest/backfill-derivables.js +175 -0
  140. package/dist/core/ingest/backfill-derivables.js.map +1 -0
  141. package/dist/core/ingest/ingest-session.d.ts +1 -1
  142. package/dist/core/ingest/ingest-session.js +23 -3
  143. package/dist/core/ingest/ingest-session.js.map +1 -1
  144. package/dist/core/ingest/reclassify-oversized.d.ts +1 -1
  145. package/dist/core/ingest/reclassify-oversized.js +8 -2
  146. package/dist/core/ingest/reclassify-oversized.js.map +1 -1
  147. package/dist/core/ingest/reprocess.d.ts +1 -1
  148. package/dist/core/ingest/reprocess.js +7 -2
  149. package/dist/core/ingest/reprocess.js.map +1 -1
  150. package/dist/core/ingest/transcript-derivables.d.ts +27 -0
  151. package/dist/core/ingest/transcript-derivables.js +138 -0
  152. package/dist/core/ingest/transcript-derivables.js.map +1 -0
  153. package/dist/core/jobs/job-supervisor.d.ts +168 -0
  154. package/dist/core/jobs/job-supervisor.js +335 -0
  155. package/dist/core/jobs/job-supervisor.js.map +1 -0
  156. package/dist/core/learner/model.d.ts +63 -0
  157. package/dist/core/learner/model.js +30 -0
  158. package/dist/core/learner/model.js.map +1 -0
  159. package/dist/core/learner/service.d.ts +42 -0
  160. package/dist/core/learner/service.js +74 -0
  161. package/dist/core/learner/service.js.map +1 -0
  162. package/dist/core/learner/summary.d.ts +28 -0
  163. package/dist/core/learner/summary.js +70 -0
  164. package/dist/core/learner/summary.js.map +1 -0
  165. package/dist/core/learner/validate.d.ts +18 -0
  166. package/dist/core/learner/validate.js +95 -0
  167. package/dist/core/learner/validate.js.map +1 -0
  168. package/dist/core/metrics/re-derivation.d.ts +31 -2
  169. package/dist/core/metrics/re-derivation.js +36 -4
  170. package/dist/core/metrics/re-derivation.js.map +1 -1
  171. package/dist/core/outcome/coverage.d.ts +33 -0
  172. package/dist/core/outcome/coverage.js +46 -0
  173. package/dist/core/outcome/coverage.js.map +1 -0
  174. package/dist/core/outcome/rollup.d.ts +33 -0
  175. package/dist/core/outcome/rollup.js +113 -0
  176. package/dist/core/outcome/rollup.js.map +1 -0
  177. package/dist/core/providers/provider-registry.d.ts +40 -23
  178. package/dist/core/providers/provider-registry.js +99 -81
  179. package/dist/core/providers/provider-registry.js.map +1 -1
  180. package/dist/core/recall/citation-log.d.ts +10 -5
  181. package/dist/core/recall/citation-log.js +21 -10
  182. package/dist/core/recall/citation-log.js.map +1 -1
  183. package/dist/core/recall/hook-recall-log.d.ts +7 -4
  184. package/dist/core/recall/hook-recall-log.js +14 -8
  185. package/dist/core/recall/hook-recall-log.js.map +1 -1
  186. package/dist/core/recall/miss-log.d.ts +7 -4
  187. package/dist/core/recall/miss-log.js +18 -11
  188. package/dist/core/recall/miss-log.js.map +1 -1
  189. package/dist/core/recall/query-log.d.ts +8 -5
  190. package/dist/core/recall/query-log.js +16 -9
  191. package/dist/core/recall/query-log.js.map +1 -1
  192. package/dist/core/recall/recall-service.d.ts +10 -1
  193. package/dist/core/recall/recall-service.js +31 -12
  194. package/dist/core/recall/recall-service.js.map +1 -1
  195. package/dist/core/recall/recent-log.d.ts +6 -1
  196. package/dist/core/recall/recent-log.js +13 -5
  197. package/dist/core/recall/recent-log.js.map +1 -1
  198. package/dist/core/recall/related-concepts.d.ts +29 -0
  199. package/dist/core/recall/related-concepts.js +67 -0
  200. package/dist/core/recall/related-concepts.js.map +1 -0
  201. package/dist/core/recall/related-exemplars.d.ts +1 -1
  202. package/dist/core/recall/related-exemplars.js +2 -2
  203. package/dist/core/recall/related-exemplars.js.map +1 -1
  204. package/dist/core/recall/related-facts.d.ts +1 -1
  205. package/dist/core/recall/related-facts.js +3 -3
  206. package/dist/core/recall/related-facts.js.map +1 -1
  207. package/dist/core/recall-facts/fact-query-log.d.ts +8 -4
  208. package/dist/core/recall-facts/fact-query-log.js +16 -8
  209. package/dist/core/recall-facts/fact-query-log.js.map +1 -1
  210. package/dist/core/recall-facts/fact-recall-service.d.ts +2 -2
  211. package/dist/core/recall-facts/fact-recall-service.js +13 -12
  212. package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
  213. package/dist/core/scheduler/scan-once.js +15 -12
  214. package/dist/core/scheduler/scan-once.js.map +1 -1
  215. package/dist/core/scheduler/scheduler.d.ts +3 -0
  216. package/dist/core/scheduler/scheduler.js +45 -10
  217. package/dist/core/scheduler/scheduler.js.map +1 -1
  218. package/dist/core/scope/alias-map.d.ts +10 -0
  219. package/dist/core/scope/alias-map.js +41 -0
  220. package/dist/core/scope/alias-map.js.map +1 -0
  221. package/dist/core/scope/derive-scope.d.ts +8 -0
  222. package/dist/core/scope/derive-scope.js +54 -0
  223. package/dist/core/scope/derive-scope.js.map +1 -0
  224. package/dist/core/scope/scope-clause.d.ts +16 -0
  225. package/dist/core/scope/scope-clause.js +21 -0
  226. package/dist/core/scope/scope-clause.js.map +1 -0
  227. package/dist/core/scope/stamp-flag.d.ts +1 -0
  228. package/dist/core/scope/stamp-flag.js +4 -0
  229. package/dist/core/scope/stamp-flag.js.map +1 -0
  230. package/dist/core/signals/code-signal.d.ts +1 -0
  231. package/dist/core/signals/code-signal.js +1 -0
  232. package/dist/core/signals/code-signal.js.map +1 -1
  233. package/dist/core/signals/failure-mode-recall.d.ts +1 -1
  234. package/dist/core/signals/failure-mode-recall.js +2 -2
  235. package/dist/core/signals/failure-mode-recall.js.map +1 -1
  236. package/dist/core/signals/ingest-signal.d.ts +1 -1
  237. package/dist/core/signals/ingest-signal.js +3 -1
  238. package/dist/core/signals/ingest-signal.js.map +1 -1
  239. package/dist/core/signals/stamp-scope.d.ts +18 -0
  240. package/dist/core/signals/stamp-scope.js +28 -0
  241. package/dist/core/signals/stamp-scope.js.map +1 -0
  242. package/dist/core/sources/source-registry.d.ts +49 -28
  243. package/dist/core/sources/source-registry.js +113 -70
  244. package/dist/core/sources/source-registry.js.map +1 -1
  245. package/dist/core/storage/pg-code-exemplar-store.d.ts +19 -10
  246. package/dist/core/storage/pg-code-exemplar-store.js +62 -27
  247. package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
  248. package/dist/core/storage/pg-entity-store.d.ts +6 -1
  249. package/dist/core/storage/pg-entity-store.js +33 -18
  250. package/dist/core/storage/pg-entity-store.js.map +1 -1
  251. package/dist/core/storage/pg-fact-ingest.d.ts +1 -1
  252. package/dist/core/storage/pg-fact-ingest.js +10 -7
  253. package/dist/core/storage/pg-fact-ingest.js.map +1 -1
  254. package/dist/core/storage/pg-fact-store.d.ts +29 -17
  255. package/dist/core/storage/pg-fact-store.js +99 -46
  256. package/dist/core/storage/pg-fact-store.js.map +1 -1
  257. package/dist/core/storage/pg-learner-store.d.ts +27 -0
  258. package/dist/core/storage/pg-learner-store.js +174 -0
  259. package/dist/core/storage/pg-learner-store.js.map +1 -0
  260. package/dist/core/storage/pg-session-store.d.ts +25 -21
  261. package/dist/core/storage/pg-session-store.js +186 -114
  262. package/dist/core/storage/pg-session-store.js.map +1 -1
  263. package/dist/core/storage/pg-signal-store.d.ts +10 -5
  264. package/dist/core/storage/pg-signal-store.js +26 -13
  265. package/dist/core/storage/pg-signal-store.js.map +1 -1
  266. package/dist/core/storage/pg-storage.d.ts +4 -0
  267. package/dist/core/storage/pg-storage.js +6 -0
  268. package/dist/core/storage/pg-storage.js.map +1 -1
  269. package/dist/core/storage/pg-workstream-store.d.ts +17 -11
  270. package/dist/core/storage/pg-workstream-store.js +47 -29
  271. package/dist/core/storage/pg-workstream-store.js.map +1 -1
  272. package/dist/core/storage/sqlite-code-exemplar-store.d.ts +24 -10
  273. package/dist/core/storage/sqlite-code-exemplar-store.js +86 -40
  274. package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
  275. package/dist/core/storage/sqlite-entity-store.d.ts +8 -1
  276. package/dist/core/storage/sqlite-entity-store.js +46 -27
  277. package/dist/core/storage/sqlite-entity-store.js.map +1 -1
  278. package/dist/core/storage/sqlite-fact-store.d.ts +45 -19
  279. package/dist/core/storage/sqlite-fact-store.js +175 -64
  280. package/dist/core/storage/sqlite-fact-store.js.map +1 -1
  281. package/dist/core/storage/sqlite-learner-store.d.ts +33 -0
  282. package/dist/core/storage/sqlite-learner-store.js +178 -0
  283. package/dist/core/storage/sqlite-learner-store.js.map +1 -0
  284. package/dist/core/storage/sqlite-outcome-store.d.ts +104 -0
  285. package/dist/core/storage/sqlite-outcome-store.js +211 -0
  286. package/dist/core/storage/sqlite-outcome-store.js.map +1 -0
  287. package/dist/core/storage/sqlite-session-store.d.ts +50 -21
  288. package/dist/core/storage/sqlite-session-store.js +233 -149
  289. package/dist/core/storage/sqlite-session-store.js.map +1 -1
  290. package/dist/core/storage/sqlite-signal-store.d.ts +12 -5
  291. package/dist/core/storage/sqlite-signal-store.js +29 -15
  292. package/dist/core/storage/sqlite-signal-store.js.map +1 -1
  293. package/dist/core/storage/sqlite-storage.d.ts +4 -0
  294. package/dist/core/storage/sqlite-storage.js +10 -2
  295. package/dist/core/storage/sqlite-storage.js.map +1 -1
  296. package/dist/core/storage/sqlite-workstream-store.d.ts +17 -11
  297. package/dist/core/storage/sqlite-workstream-store.js +53 -31
  298. package/dist/core/storage/sqlite-workstream-store.js.map +1 -1
  299. package/dist/core/storage/supersedence-log.d.ts +10 -7
  300. package/dist/core/storage/supersedence-log.js +21 -14
  301. package/dist/core/storage/supersedence-log.js.map +1 -1
  302. package/dist/core/telemetry/probe-filter.d.ts +35 -0
  303. package/dist/core/telemetry/probe-filter.js +56 -0
  304. package/dist/core/telemetry/probe-filter.js.map +1 -0
  305. package/dist/core/tenancy/default-team.d.ts +6 -0
  306. package/dist/core/tenancy/default-team.js +7 -0
  307. package/dist/core/tenancy/default-team.js.map +1 -0
  308. package/dist/core/tenancy/hosted-mode.d.ts +9 -0
  309. package/dist/core/tenancy/hosted-mode.js +12 -0
  310. package/dist/core/tenancy/hosted-mode.js.map +1 -0
  311. package/dist/core/tenancy/team-auth.d.ts +16 -0
  312. package/dist/core/tenancy/team-auth.js +22 -0
  313. package/dist/core/tenancy/team-auth.js.map +1 -0
  314. package/dist/core/tenancy/team-token-store.d.ts +45 -0
  315. package/dist/core/tenancy/team-token-store.js +52 -0
  316. package/dist/core/tenancy/team-token-store.js.map +1 -0
  317. package/dist/core/tenancy/tenant-clause.d.ts +37 -0
  318. package/dist/core/tenancy/tenant-clause.js +11 -0
  319. package/dist/core/tenancy/tenant-clause.js.map +1 -0
  320. package/dist/core/tenancy/tenant-state-path.d.ts +28 -0
  321. package/dist/core/tenancy/tenant-state-path.js +49 -0
  322. package/dist/core/tenancy/tenant-state-path.js.map +1 -0
  323. package/dist/core/update-check/check.d.ts +6 -0
  324. package/dist/core/update-check/check.js +35 -0
  325. package/dist/core/update-check/check.js.map +1 -1
  326. package/dist/core/wiki/project.d.ts +17 -0
  327. package/dist/core/wiki/project.js +37 -0
  328. package/dist/core/wiki/project.js.map +1 -0
  329. package/dist/core/wiki/reconcile.d.ts +15 -0
  330. package/dist/core/wiki/reconcile.js +14 -0
  331. package/dist/core/wiki/reconcile.js.map +1 -0
  332. package/dist/core/wiki/render.d.ts +5 -0
  333. package/dist/core/wiki/render.js +84 -0
  334. package/dist/core/wiki/render.js.map +1 -0
  335. package/dist/core/wiki/rollup.d.ts +28 -0
  336. package/dist/core/wiki/rollup.js +91 -0
  337. package/dist/core/wiki/rollup.js.map +1 -0
  338. package/dist/core/wiki/select.d.ts +8 -0
  339. package/dist/core/wiki/select.js +7 -0
  340. package/dist/core/wiki/select.js.map +1 -0
  341. package/dist/core/wiki/slug.d.ts +36 -0
  342. package/dist/core/wiki/slug.js +71 -0
  343. package/dist/core/wiki/slug.js.map +1 -0
  344. package/dist/core/wiki/types.d.ts +37 -0
  345. package/dist/core/wiki/types.js +2 -0
  346. package/dist/core/wiki/types.js.map +1 -0
  347. package/dist/core/work-digest/build-work-digest.d.ts +1 -1
  348. package/dist/core/work-digest/build-work-digest.js +3 -3
  349. package/dist/core/work-digest/build-work-digest.js.map +1 -1
  350. package/dist/core/workstream/bind.d.ts +3 -2
  351. package/dist/core/workstream/bind.js +29 -10
  352. package/dist/core/workstream/bind.js.map +1 -1
  353. package/dist/core/workstream/model.d.ts +1 -0
  354. package/dist/core/workstream/model.js.map +1 -1
  355. package/dist/core/workstream/rollup.d.ts +1 -1
  356. package/dist/core/workstream/rollup.js +6 -6
  357. package/dist/core/workstream/rollup.js.map +1 -1
  358. package/dist/hook/hook-helpers.d.ts +14 -0
  359. package/dist/hook/hook-helpers.js +29 -2
  360. package/dist/hook/hook-helpers.js.map +1 -1
  361. package/dist/hook/pre-compact-hook.js +8 -5
  362. package/dist/hook/pre-compact-hook.js.map +1 -1
  363. package/dist/hook/prompt-recall-hook.d.ts +7 -3
  364. package/dist/hook/prompt-recall-hook.js +35 -20
  365. package/dist/hook/prompt-recall-hook.js.map +1 -1
  366. package/dist/hook/recall-over-http.d.ts +28 -3
  367. package/dist/hook/recall-over-http.js +58 -12
  368. package/dist/hook/recall-over-http.js.map +1 -1
  369. package/dist/hook/session-end-hook.js +7 -5
  370. package/dist/hook/session-end-hook.js.map +1 -1
  371. package/dist/hook/session-start-hook.d.ts +14 -1
  372. package/dist/hook/session-start-hook.js +57 -16
  373. package/dist/hook/session-start-hook.js.map +1 -1
  374. package/dist/hook/stop-hook.js +11 -8
  375. package/dist/hook/stop-hook.js.map +1 -1
  376. package/dist/http/app.d.ts +47 -3
  377. package/dist/http/app.js +379 -132
  378. package/dist/http/app.js.map +1 -1
  379. package/dist/install/claude-code.d.ts +17 -0
  380. package/dist/install/claude-code.js +44 -5
  381. package/dist/install/claude-code.js.map +1 -1
  382. package/dist/install/codex.d.ts +23 -2
  383. package/dist/install/codex.js +111 -14
  384. package/dist/install/codex.js.map +1 -1
  385. package/dist/install/cursor.d.ts +2 -2
  386. package/dist/install/cursor.js +7 -7
  387. package/dist/install/cursor.js.map +1 -1
  388. package/dist/install/hermes.d.ts +8 -0
  389. package/dist/install/hermes.js +28 -5
  390. package/dist/install/hermes.js.map +1 -1
  391. package/dist/install/local-source.d.ts +20 -0
  392. package/dist/install/local-source.js +28 -0
  393. package/dist/install/local-source.js.map +1 -0
  394. package/dist/install/mcp-block.d.ts +77 -0
  395. package/dist/install/mcp-block.js +99 -0
  396. package/dist/install/mcp-block.js.map +1 -0
  397. package/dist/install/pi.d.ts +26 -0
  398. package/dist/install/pi.js +43 -0
  399. package/dist/install/pi.js.map +1 -1
  400. package/dist/install/setup.js +6 -0
  401. package/dist/install/setup.js.map +1 -1
  402. package/dist/install/windsurf.d.ts +2 -2
  403. package/dist/install/windsurf.js +7 -7
  404. package/dist/install/windsurf.js.map +1 -1
  405. package/dist/llm/classifier-box.d.ts +5 -0
  406. package/dist/llm/classifier-box.js +5 -0
  407. package/dist/llm/classifier-box.js.map +1 -1
  408. package/dist/mcp/server.d.ts +94 -15
  409. package/dist/mcp/server.js +402 -79
  410. package/dist/mcp/server.js.map +1 -1
  411. package/dist/ports/clock.d.ts +12 -0
  412. package/dist/ports/clock.js +10 -0
  413. package/dist/ports/clock.js.map +1 -0
  414. package/dist/ports/code-exemplar-store.d.ts +13 -13
  415. package/dist/ports/entity-store.d.ts +5 -1
  416. package/dist/ports/fact-store.d.ts +0 -0
  417. package/dist/ports/fact-store.js +0 -0
  418. package/dist/ports/fact-store.js.map +1 -1
  419. package/dist/ports/learner-store.d.ts +80 -0
  420. package/dist/ports/learner-store.js +19 -0
  421. package/dist/ports/learner-store.js.map +1 -0
  422. package/dist/ports/outcome.d.ts +85 -0
  423. package/dist/ports/outcome.js +11 -0
  424. package/dist/ports/outcome.js.map +1 -0
  425. package/dist/ports/session-store.d.ts +20 -20
  426. package/dist/ports/session-store.js +5 -0
  427. package/dist/ports/session-store.js.map +1 -1
  428. package/dist/ports/signal-store.d.ts +12 -8
  429. package/dist/ports/spawn-child.d.ts +14 -0
  430. package/dist/ports/spawn-child.js +10 -0
  431. package/dist/ports/spawn-child.js.map +1 -0
  432. package/dist/ports/storage.d.ts +6 -0
  433. package/dist/ports/transcript-adapter.d.ts +11 -0
  434. package/dist/ports/wiki-writer.d.ts +19 -0
  435. package/dist/ports/wiki-writer.js +12 -0
  436. package/dist/ports/wiki-writer.js.map +1 -0
  437. package/dist/ports/workstream-store.d.ts +20 -12
  438. package/dist/shared/net.d.ts +3 -0
  439. package/dist/shared/net.js +4 -0
  440. package/dist/shared/net.js.map +1 -0
  441. package/dist/shared/types.d.ts +55 -0
  442. package/dist/shared/types.js +4 -1
  443. package/dist/shared/types.js.map +1 -1
  444. package/dist/shared/version.d.ts +9 -0
  445. package/dist/shared/version.js +11 -0
  446. package/dist/shared/version.js.map +1 -0
  447. package/dist/ui/assets/index-D6F3xAis.js +11 -0
  448. package/dist/ui/index.html +1 -1
  449. package/migrations/029_project_scope.sql +21 -0
  450. package/migrations/032_session_derivables.sql +11 -0
  451. package/migrations/033_actions_kind_check.sql +58 -0
  452. package/migrations/034_tenancy_teams_and_stamps.sql +40 -0
  453. package/migrations/035_tenancy_entity_rekey.sql +75 -0
  454. package/migrations/036_tenant_name_uniqueness.sql +59 -0
  455. package/migrations/037_sessions_covering_index.sql +25 -0
  456. package/migrations/038_sources_muse.sql +33 -0
  457. package/migrations/039_learner_evidence.sql +51 -0
  458. package/migrations/pg/030_project_scope.sql +23 -0
  459. package/migrations/pg/031_widen_session_edges_kind.sql +11 -0
  460. package/migrations/pg/032_session_derivables.sql +17 -0
  461. package/migrations/pg/033_actions_kind_check.sql +17 -0
  462. package/migrations/pg/034_tenancy.sql +77 -0
  463. package/migrations/pg/035_tenant_name_uniqueness.sql +15 -0
  464. package/migrations/pg/036_sources_muse.sql +12 -0
  465. package/migrations/pg/037_learner_evidence.sql +55 -0
  466. package/nlm/index.js +258 -59
  467. package/package.json +10 -5
  468. package/plugin/.codex-plugin/plugin.json +1 -1
  469. package/plugin/scripts/prompt-recall-hook.mjs +256 -58
  470. package/plugin/scripts/session-start-hook.mjs +283 -55
  471. package/plugin/scripts/stop-hook.mjs +199 -38
  472. package/dist/hook/subagent-start-hook.d.ts +0 -28
  473. package/dist/hook/subagent-start-hook.js +0 -81
  474. package/dist/hook/subagent-start-hook.js.map +0 -1
  475. package/dist/ui/assets/index-CMpQkbQy.js +0 -11
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Reconcile live facts against operator-supplied authorities. Structured
3
+ * sources win: a live fact that contradicts an authority, or that names a
4
+ * deleted file, is retired (never replaced). Deterministic, no LLM calls.
5
+ */
6
+ import { readFileSync } from "node:fs";
7
+ import { appendFactSupersedence } from "../storage/supersedence-log.js";
8
+ import { DEFAULT_TEAM_ID } from "../tenancy/default-team.js";
9
+ export function loadAuthorities(path) {
10
+ const raw = JSON.parse(readFileSync(path, "utf8"));
11
+ const authorities = raw.authorities ?? [];
12
+ const deleted = raw.deleted_files ?? [];
13
+ for (const a of authorities) {
14
+ if (!Array.isArray(a.aliases) || a.aliases.length === 0 || !a.predicate || a.value === undefined) {
15
+ throw new Error("each authority needs non-empty aliases, a predicate and a value");
16
+ }
17
+ }
18
+ for (const d of deleted) {
19
+ if (!d.name)
20
+ throw new Error("each deleted_files entry needs a name");
21
+ }
22
+ return { authorities, deleted_files: deleted };
23
+ }
24
+ export function normalizeSubject(s) {
25
+ return s.toLowerCase().replace(/[\s_-]+/g, " ").trim();
26
+ }
27
+ function ports(value) {
28
+ return (value.match(/\d+/g) ?? []).map(Number);
29
+ }
30
+ /**
31
+ * `host:port` via the WHATWG URL parser only. One parser, so a value can't
32
+ * read one way to this check and another way to whatever consumes it.
33
+ */
34
+ function hostPort(value) {
35
+ try {
36
+ const u = new URL(value.includes("://") ? value : `http://${value}`);
37
+ if (u.username || u.password)
38
+ return null;
39
+ return u.hostname && u.port ? `${u.hostname}:${u.port}`.toLowerCase() : null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ function contradicts(predicate, factValue, authorityValue) {
46
+ if (predicate === "port") {
47
+ const want = Number.parseInt(authorityValue, 10);
48
+ const have = ports(factValue);
49
+ return have.length > 0 && !have.includes(want);
50
+ }
51
+ if (predicate === "host" || predicate === "url" || predicate === "endpoint") {
52
+ // Prose values ("the Pro on :7803") aren't comparable; never retire on a guess.
53
+ const a = hostPort(authorityValue);
54
+ const f = hostPort(factValue.trim());
55
+ return a !== null && f !== null && a !== f;
56
+ }
57
+ return factValue.trim().toLowerCase() !== authorityValue.trim().toLowerCase();
58
+ }
59
+ export function findContradictions(db, file) {
60
+ const rows = db
61
+ .prepare(`SELECT id, subject, predicate, value, created_at, tenant_id FROM facts
62
+ WHERE superseded_by IS NULL AND retired_at IS NULL AND kind != 'decision'
63
+ ORDER BY created_at, id`)
64
+ .all();
65
+ const aliasMap = new Map();
66
+ for (const a of file.authorities) {
67
+ for (const alias of a.aliases) {
68
+ const key = normalizeSubject(alias);
69
+ aliasMap.set(key, [...(aliasMap.get(key) ?? []), a]);
70
+ }
71
+ }
72
+ const dead = file.deleted_files.map((d) => ({ d, key: normalizeSubject(d.name) }));
73
+ const findings = [];
74
+ for (const row of rows) {
75
+ const subject = normalizeSubject(row.subject);
76
+ const base = {
77
+ factId: row.id,
78
+ subject: row.subject,
79
+ predicate: row.predicate,
80
+ value: row.value,
81
+ createdAt: row.created_at,
82
+ tenantId: row.tenant_id ?? DEFAULT_TEAM_ID,
83
+ };
84
+ const predicate = row.predicate.trim().toLowerCase();
85
+ const bad = (aliasMap.get(subject) ?? []).find((a) => a.predicate.trim().toLowerCase() === predicate && contradicts(predicate, row.value, a.value));
86
+ if (bad) {
87
+ findings.push({ ...base, type: "value_mismatch", authorityValue: bad.value, authoritySource: bad.source });
88
+ continue;
89
+ }
90
+ const gone = dead.find(({ key }) => subject === key || subject.startsWith(key));
91
+ if (gone) {
92
+ findings.push({
93
+ ...base,
94
+ type: "dead_reference",
95
+ authorityValue: null,
96
+ authoritySource: gone.d.source ?? `deleted file ${gone.d.name}`,
97
+ });
98
+ }
99
+ }
100
+ return findings;
101
+ }
102
+ export async function applyRetirements(db, dbFilePath, findings, limit, logPath) {
103
+ const batch = findings.slice(0, limit);
104
+ if (batch.length === 0)
105
+ return { retired: [], backupPath: null };
106
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
107
+ const backupPath = `${dbFilePath}.bak-reconcile-${stamp}`;
108
+ await db.backup(backupPath);
109
+ const retire = db.prepare("UPDATE facts SET retired_at = datetime('now') WHERE id = ? AND retired_at IS NULL AND superseded_by IS NULL");
110
+ db.transaction(() => {
111
+ for (const f of batch)
112
+ retire.run(f.factId);
113
+ })();
114
+ for (const f of batch) {
115
+ await appendFactSupersedence(f.tenantId, { factId: f.factId, reason: `${f.type}: contradicted by ${f.authoritySource}`, source: "reconcile" }, logPath);
116
+ }
117
+ return { retired: batch, backupPath };
118
+ }
119
+ export function formatReport(findings, limit) {
120
+ const lines = [];
121
+ for (const type of ["value_mismatch", "dead_reference"]) {
122
+ const group = findings.filter((f) => f.type === type);
123
+ lines.push(`${type} (${group.length})`);
124
+ for (const f of group) {
125
+ const auth = f.authorityValue === null ? "" : `authority=${f.authorityValue} `;
126
+ lines.push(` ${f.factId} subject=${f.subject} predicate=${f.predicate} value=${f.value} ` +
127
+ `${auth}source=${f.authoritySource} created=${f.createdAt}`);
128
+ }
129
+ }
130
+ lines.push(`total: ${findings.length} (--apply would retire ${Math.min(findings.length, limit)})`);
131
+ return lines.join("\n");
132
+ }
133
+ //# sourceMappingURL=reconcile-facts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile-facts.js","sourceRoot":"","sources":["../../../src/core/facts/reconcile-facts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AA2C7D,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA6B,CAAC;IAC/E,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACjG,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAS;IACxC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ,CAAC,KAAa;IAC7B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,SAAiB,EAAE,SAAiB,EAAE,cAAsB;IAC/E,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC5E,gFAAgF;QAChF,MAAM,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QACrC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,EAAqB,EAAE,IAAqB;IAC7E,MAAM,IAAI,GAAG,EAAE;SACZ,OAAO,CACN;;+BAEyB,CAC1B;SACA,GAAG,EAAE,CAAC;IACT,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;YACpC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG;YACX,MAAM,EAAE,GAAG,CAAC,EAAE;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,QAAQ,EAAE,GAAG,CAAC,SAAS,IAAI,eAAe;SAC3C,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAC5C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,SAAS,IAAI,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CACpG,CAAC;QACF,IAAI,GAAG,EAAE,CAAC;YACR,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAE,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAC3G,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,OAAO,KAAK,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAChF,IAAI,IAAI,EAAE,CAAC;YACT,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,IAAI;gBACP,IAAI,EAAE,gBAAgB;gBACtB,cAAc,EAAE,IAAI;gBACpB,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,gBAAgB,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;aAChE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAqB,EACrB,UAAkB,EAClB,QAA4B,EAC5B,KAAa,EACb,OAAgB;IAEhB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IACjE,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,GAAG,UAAU,kBAAkB,KAAK,EAAE,CAAC;IAC1D,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5B,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CACvB,6GAA6G,CAC9G,CAAC;IACF,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;QAClB,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC,CAAC,EAAE,CAAC;IACL,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,sBAAsB,CAC1B,CAAC,CAAC,QAAQ,EACV,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,qBAAqB,CAAC,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EACpG,OAAO,CACR,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAA4B,EAAE,KAAa;IACtE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAU,EAAE,CAAC;QACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,CAAC,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,cAAc,GAAG,CAAC;YAC/E,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,MAAM,aAAa,CAAC,CAAC,OAAO,eAAe,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,KAAK,IAAI;gBACjF,GAAG,IAAI,UAAU,CAAC,CAAC,eAAe,aAAa,CAAC,CAAC,SAAS,EAAE,CAC/D,CAAC;QACJ,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,CAAC,MAAM,0BAA0B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type EmbedFailureKind = "chunk" | "fact";
2
+ export declare function recordEmbedFailure(kind: EmbedFailureKind): void;
3
+ export declare function embedFailureSnapshot(): Readonly<Record<EmbedFailureKind, number>>;
4
+ export declare function resetEmbedFailureForTests(): void;
@@ -0,0 +1,12 @@
1
+ const state = { chunk: 0, fact: 0 };
2
+ export function recordEmbedFailure(kind) {
3
+ state[kind] += 1;
4
+ }
5
+ export function embedFailureSnapshot() {
6
+ return Object.freeze({ ...state });
7
+ }
8
+ export function resetEmbedFailureForTests() {
9
+ state.chunk = 0;
10
+ state.fact = 0;
11
+ }
12
+ //# sourceMappingURL=embed-failure-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed-failure-state.js","sourceRoot":"","sources":["../../../src/core/health/embed-failure-state.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAqC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAEtE,MAAM,UAAU,kBAAkB,CAAC,IAAsB;IACvD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;AACjB,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Retry loop for a warmup probe that must survive a backend being absent.
3
+ *
4
+ * The embedder warmup used to be a single fire-and-forget attempt with an empty
5
+ * catch. If the backend was not servable at that instant the stage latched cold
6
+ * for the daemon's entire uptime, even after the backend returned, and only a
7
+ * restart cleared it. Two costs, both real: a five-day silent outage while the
8
+ * embedder was reachable throughout, and a three-week hunt for a release
9
+ * "regression" that did not exist, because restarting inside the same outage
10
+ * window reproduces the failure every time and reads as determinism.
11
+ *
12
+ * Pure except for the injected `sleep`, so the backoff schedule is testable
13
+ * without timers. Never throws: a warmup probe must not be able to take down
14
+ * the process it is reporting on.
15
+ */
16
+ export interface RetryUntilWarmDeps {
17
+ /** The probe. Resolving means the lane is live. */
18
+ readonly attempt: () => Promise<unknown>;
19
+ readonly onSuccess: () => void;
20
+ /** Called per failed attempt so health can name the cause instead of showing a bare false. */
21
+ readonly onFailure: (reason: string, attempt: number) => void;
22
+ readonly sleep: (ms: number) => Promise<void>;
23
+ readonly maxAttempts?: number;
24
+ readonly baseDelayMs?: number;
25
+ readonly maxDelayMs?: number;
26
+ }
27
+ export declare function retryUntilWarm(deps: RetryUntilWarmDeps): Promise<void>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Retry loop for a warmup probe that must survive a backend being absent.
3
+ *
4
+ * The embedder warmup used to be a single fire-and-forget attempt with an empty
5
+ * catch. If the backend was not servable at that instant the stage latched cold
6
+ * for the daemon's entire uptime, even after the backend returned, and only a
7
+ * restart cleared it. Two costs, both real: a five-day silent outage while the
8
+ * embedder was reachable throughout, and a three-week hunt for a release
9
+ * "regression" that did not exist, because restarting inside the same outage
10
+ * window reproduces the failure every time and reads as determinism.
11
+ *
12
+ * Pure except for the injected `sleep`, so the backoff schedule is testable
13
+ * without timers. Never throws: a warmup probe must not be able to take down
14
+ * the process it is reporting on.
15
+ */
16
+ const DEFAULT_MAX_ATTEMPTS = 60;
17
+ const DEFAULT_BASE_DELAY_MS = 1_000;
18
+ // Caps the tail at a minute: long enough that a backend absent for hours costs
19
+ // ~60 cheap probes, short enough that recovery is noticed within a minute.
20
+ const DEFAULT_MAX_DELAY_MS = 60_000;
21
+ function reasonOf(err) {
22
+ return err instanceof Error ? err.message : String(err);
23
+ }
24
+ export async function retryUntilWarm(deps) {
25
+ const maxAttempts = deps.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
26
+ const baseDelay = deps.baseDelayMs ?? DEFAULT_BASE_DELAY_MS;
27
+ const maxDelay = deps.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
28
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
29
+ try {
30
+ await deps.attempt();
31
+ deps.onSuccess();
32
+ return;
33
+ }
34
+ catch (err) {
35
+ try {
36
+ deps.onFailure(reasonOf(err), attempt);
37
+ }
38
+ catch {
39
+ // A broken reporter must not end the retry loop.
40
+ }
41
+ if (attempt === maxAttempts)
42
+ return;
43
+ const delay = Math.min(baseDelay * 2 ** (attempt - 1), maxDelay);
44
+ try {
45
+ await deps.sleep(delay);
46
+ }
47
+ catch {
48
+ return;
49
+ }
50
+ }
51
+ }
52
+ }
53
+ //# sourceMappingURL=warmup-retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warmup-retry.js","sourceRoot":"","sources":["../../../src/core/health/warmup-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAcH,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AACpC,+EAA+E;AAC/E,2EAA2E;AAC3E,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAEpC,SAAS,QAAQ,CAAC,GAAY;IAC5B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAwB;IAC3D,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,oBAAoB,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,IAAI,qBAAqB,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,IAAI,oBAAoB,CAAC;IAEzD,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YACzC,CAAC;YAAC,MAAM,CAAC;gBACP,iDAAiD;YACnD,CAAC;YACD,IAAI,OAAO,KAAK,WAAW;gBAAE,OAAO;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -2,11 +2,26 @@ interface WarmupState {
2
2
  fts5: boolean;
3
3
  textEmbedder: boolean;
4
4
  }
5
+ /**
6
+ * Why a stage is still cold. A bare `false` is indistinguishable between "the
7
+ * backend was absent at boot" and "this build is broken", and that ambiguity
8
+ * cost three weeks chasing a release regression that did not exist. `since`
9
+ * holds the FIRST failure so health can report how long the lane has been down
10
+ * rather than only the latest retry.
11
+ */
12
+ export interface WarmupFailure {
13
+ readonly reason: string;
14
+ readonly attempts: number;
15
+ readonly since: string;
16
+ }
17
+ type FailureMap = Partial<Record<keyof WarmupState, WarmupFailure>>;
5
18
  export declare function markWarm(stage: keyof WarmupState): void;
19
+ export declare function markWarmFailure(stage: keyof WarmupState, reason: string, attempts: number): void;
6
20
  export declare function warmupSnapshot(): {
7
21
  fts5: boolean;
8
22
  textEmbedder: boolean;
9
23
  ready: boolean;
24
+ lastError?: FailureMap;
10
25
  };
11
26
  export declare function resetWarmupState(): void;
12
27
  export {};
@@ -1,12 +1,26 @@
1
1
  const state = { fts5: false, textEmbedder: false };
2
+ let failures = {};
2
3
  export function markWarm(stage) {
3
4
  state[stage] = true;
5
+ delete failures[stage];
6
+ }
7
+ export function markWarmFailure(stage, reason, attempts) {
8
+ const since = failures[stage]?.since ?? new Date().toISOString();
9
+ failures[stage] = { reason, attempts, since };
4
10
  }
5
11
  export function warmupSnapshot() {
6
- return { fts5: state.fts5, textEmbedder: state.textEmbedder, ready: state.fts5 && state.textEmbedder };
12
+ const ready = state.fts5 && state.textEmbedder;
13
+ const hasFailure = Object.keys(failures).length > 0;
14
+ return {
15
+ fts5: state.fts5,
16
+ textEmbedder: state.textEmbedder,
17
+ ready,
18
+ ...(hasFailure ? { lastError: { ...failures } } : {}),
19
+ };
7
20
  }
8
21
  export function resetWarmupState() {
9
22
  state.fts5 = false;
10
23
  state.textEmbedder = false;
24
+ failures = {};
11
25
  }
12
26
  //# sourceMappingURL=warmup-state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"warmup-state.js","sourceRoot":"","sources":["../../../src/core/health/warmup-state.ts"],"names":[],"mappings":"AAKA,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAEhE,MAAM,UAAU,QAAQ,CAAC,KAAwB;IAC/C,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;AACzG,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;IACnB,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"warmup-state.js","sourceRoot":"","sources":["../../../src/core/health/warmup-state.ts"],"names":[],"mappings":"AAoBA,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAChE,IAAI,QAAQ,GAAe,EAAE,CAAC;AAE9B,MAAM,UAAU,QAAQ,CAAC,KAAwB;IAC/C,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACpB,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAwB,EAAE,MAAc,EAAE,QAAgB;IACxF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjE,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,cAAc;IAM5B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,YAAY,CAAC;IAC/C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACpD,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,KAAK;QACL,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;IACnB,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;IAC3B,QAAQ,GAAG,EAAE,CAAC;AAChB,CAAC"}
@@ -7,14 +7,18 @@
7
7
  * holds the set of (conversationId, citedId) pairs already posted, so each
8
8
  * citation lands exactly once regardless of how many times Stop fires.
9
9
  *
10
- * Storage parallels the surfaced-memo (`memo.ts`): same state directory
11
- * (`~/.nlm/hook-state/`, overridable via NLM_HOOK_STATE_DIR), filename suffix
12
- * `.cited.json` to distinguish from the surfaced memo's `.json`. The existing
13
- * memo-sweep walks the directory by mtime and cleans both files together.
10
+ * Storage parallels the surfaced-memo (`memo.ts`): same tenant-derived state
11
+ * directory (core/tenancy/tenant-state-path.ts) — the default team's dir is
12
+ * `~/.nlm/hook-state/`, overridable via NLM_HOOK_STATE_DIR; every other
13
+ * tenant is isolated under `~/.nlm/tenants/<tenantId>/hook-state/` and
14
+ * ignores the env override. Filename suffix `.cited.json` distinguishes this
15
+ * memo from the surfaced memo's `.json` within the same directory. The
16
+ * existing memo-sweep walks the default team's directory by mtime and cleans
17
+ * both files together.
14
18
  *
15
19
  * Defensive: a missing or corrupt file yields an empty set; a write failure
16
20
  * is swallowed. Telemetry path — must never break the hook.
17
21
  */
18
- export declare function loadCited(conversationId: string): Set<string>;
19
- export declare function recordCited(conversationId: string, ids: ReadonlyArray<string>): void;
20
- export declare function clearCited(conversationId: string): boolean;
22
+ export declare function loadCited(tenantId: string, conversationId: string): Set<string>;
23
+ export declare function recordCited(tenantId: string, conversationId: string, ids: ReadonlyArray<string>): void;
24
+ export declare function clearCited(tenantId: string, conversationId: string): boolean;
@@ -7,27 +7,35 @@
7
7
  * holds the set of (conversationId, citedId) pairs already posted, so each
8
8
  * citation lands exactly once regardless of how many times Stop fires.
9
9
  *
10
- * Storage parallels the surfaced-memo (`memo.ts`): same state directory
11
- * (`~/.nlm/hook-state/`, overridable via NLM_HOOK_STATE_DIR), filename suffix
12
- * `.cited.json` to distinguish from the surfaced memo's `.json`. The existing
13
- * memo-sweep walks the directory by mtime and cleans both files together.
10
+ * Storage parallels the surfaced-memo (`memo.ts`): same tenant-derived state
11
+ * directory (core/tenancy/tenant-state-path.ts) — the default team's dir is
12
+ * `~/.nlm/hook-state/`, overridable via NLM_HOOK_STATE_DIR; every other
13
+ * tenant is isolated under `~/.nlm/tenants/<tenantId>/hook-state/` and
14
+ * ignores the env override. Filename suffix `.cited.json` distinguishes this
15
+ * memo from the surfaced memo's `.json` within the same directory. The
16
+ * existing memo-sweep walks the default team's directory by mtime and cleans
17
+ * both files together.
14
18
  *
15
19
  * Defensive: a missing or corrupt file yields an empty set; a write failure
16
20
  * is swallowed. Telemetry path — must never break the hook.
17
21
  */
18
22
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
19
- import { homedir } from "node:os";
20
23
  import { join } from "node:path";
21
- function stateDir() {
22
- return process.env["NLM_HOOK_STATE_DIR"] ?? join(homedir(), ".nlm", "hook-state");
24
+ import { tenantStatePath } from "../tenancy/tenant-state-path.js";
25
+ import { DEFAULT_TEAM_ID } from "../tenancy/default-team.js";
26
+ function stateDir(tenantId) {
27
+ if (tenantId === DEFAULT_TEAM_ID) {
28
+ return process.env["NLM_HOOK_STATE_DIR"] ?? tenantStatePath(tenantId, "hook-state");
29
+ }
30
+ return tenantStatePath(tenantId, "hook-state");
23
31
  }
24
- function memoPath(conversationId) {
32
+ function memoPath(tenantId, conversationId) {
25
33
  const safe = conversationId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
26
- return join(stateDir(), `${safe}.cited.json`);
34
+ return join(stateDir(tenantId), `${safe}.cited.json`);
27
35
  }
28
- export function loadCited(conversationId) {
36
+ export function loadCited(tenantId, conversationId) {
29
37
  try {
30
- const path = memoPath(conversationId);
38
+ const path = memoPath(tenantId, conversationId);
31
39
  if (!existsSync(path))
32
40
  return new Set();
33
41
  const parsed = JSON.parse(readFileSync(path, "utf8"));
@@ -39,23 +47,23 @@ export function loadCited(conversationId) {
39
47
  return new Set();
40
48
  }
41
49
  }
42
- export function recordCited(conversationId, ids) {
50
+ export function recordCited(tenantId, conversationId, ids) {
43
51
  if (ids.length === 0)
44
52
  return;
45
53
  try {
46
- const merged = loadCited(conversationId);
54
+ const merged = loadCited(tenantId, conversationId);
47
55
  for (const id of ids)
48
56
  merged.add(id);
49
- mkdirSync(stateDir(), { recursive: true });
50
- writeFileSync(memoPath(conversationId), JSON.stringify([...merged]), "utf8");
57
+ mkdirSync(stateDir(tenantId), { recursive: true });
58
+ writeFileSync(memoPath(tenantId, conversationId), JSON.stringify([...merged]), "utf8");
51
59
  }
52
60
  catch {
53
61
  // Memo write failure must never break the hook.
54
62
  }
55
63
  }
56
- export function clearCited(conversationId) {
64
+ export function clearCited(tenantId, conversationId) {
57
65
  try {
58
- const path = memoPath(conversationId);
66
+ const path = memoPath(tenantId, conversationId);
59
67
  if (!existsSync(path))
60
68
  return false;
61
69
  rmSync(path);
@@ -1 +1 @@
1
- {"version":3,"file":"cite-memo.js","sourceRoot":"","sources":["../../../src/core/hook/cite-memo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,SAAS,QAAQ;IACf,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,QAAQ,CAAC,cAAsB;IACtC,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;IACzE,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,cAAsB;IAC9C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QACxC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QAC7C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,cAAsB,EACtB,GAA0B;IAE1B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;QACzC,KAAK,MAAM,EAAE,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,cAAsB;IAC/C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"cite-memo.js","sourceRoot":"","sources":["../../../src/core/hook/cite-memo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,SAAS,QAAQ,CAAC,QAAgB;IAChC,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB,EAAE,cAAsB;IACxD,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;IACzE,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,cAAsB;IAChE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QACxC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QAC7C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,QAAgB,EAChB,cAAsB,EACtB,GAA0B;IAE1B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACnD,KAAK,MAAM,EAAE,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,cAAsB;IACjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -19,7 +19,7 @@ export declare function shellQuote(arg: string): string;
19
19
  */
20
20
  export declare function cmdQuote(arg: string): string;
21
21
  export declare function buildHookCommand(execPath: string, hookJs: string, mode: "shadow" | "live", targetPlatform?: NodeJS.Platform): string;
22
- export type ClaudeHookEvent = "UserPromptSubmit" | "SessionStart" | "SessionEnd" | "Stop" | "PreCompact" | "SubagentStart" | "PostToolUse" | "PreToolUse";
22
+ export type ClaudeHookEvent = "UserPromptSubmit" | "SessionStart" | "SessionEnd" | "Stop" | "PreCompact" | "PostToolUse" | "PreToolUse";
23
23
  export declare function addHook(settingsPath: string, command: string, event?: ClaudeHookEvent): void;
24
24
  /**
25
25
  * Remove the NLM-tagged hook entry from one event (default UserPromptSubmit)
@@ -16,7 +16,6 @@ const HOOK_SCRIPT_MARKERS = [
16
16
  "stop-hook.js",
17
17
  "session-start-hook.js",
18
18
  "pre-compact-hook.js",
19
- "subagent-start-hook.js",
20
19
  ];
21
20
  /**
22
21
  * Single-quote a shell argument so paths with spaces or other shell
@@ -1 +1 @@
1
- {"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../../src/core/hook/claude-settings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../../src/core/hook/claude-settings.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,10 @@
3
3
  * evaluated. This is the dataset the relevance gate (generative patterns +
4
4
  * score threshold) is calibrated against during the shadow window.
5
5
  *
6
- * Path defaults to ~/.nlm/hook-log.jsonl, overridable via NLM_HOOK_LOG.
6
+ * Path is tenant-derived (core/tenancy/tenant-state-path.ts): the default
7
+ * team's log is ~/.nlm/hook-log.jsonl, overridable via NLM_HOOK_LOG; every
8
+ * other tenant is isolated under ~/.nlm/tenants/<tenantId>/hook-log.jsonl
9
+ * and ignores the env override.
7
10
  * appendHookLog swallows its own errors — telemetry must never break the hook.
8
11
  * Uses synchronous I/O: the hook is a short-lived per-prompt process, and an
9
12
  * async write could be lost if the process exits before it flushes.
@@ -21,10 +24,18 @@ export interface HookLogEntry {
21
24
  readonly wouldInject: ReadonlyArray<string>;
22
25
  readonly estTokens: number;
23
26
  readonly mode: "shadow" | "live";
27
+ /**
28
+ * The hook build that wrote this line. Lets the digest assert the hooks
29
+ * actually running match the installed version — liveness alone cannot.
30
+ */
31
+ readonly v?: string;
32
+ /** Why recall returned what it did. Absent on gate-skipped fires (no recall ran).
33
+ * Without it, `hits: []` cannot be told apart from a recall that timed out. */
34
+ readonly recallOutcome?: "ok" | "timeout" | "unreachable" | "http-error" | "skipped";
24
35
  /** Per-candidate relevance-gate decisions, when the recall gate ran. */
25
36
  readonly gateDecisions?: ReadonlyArray<{
26
37
  readonly id: string;
27
38
  readonly gate: "relevant" | "irrelevant";
28
39
  }>;
29
40
  }
30
- export declare function appendHookLog(entry: HookLogEntry): void;
41
+ export declare function appendHookLog(tenantId: string, entry: HookLogEntry): void;
@@ -3,23 +3,31 @@
3
3
  * evaluated. This is the dataset the relevance gate (generative patterns +
4
4
  * score threshold) is calibrated against during the shadow window.
5
5
  *
6
- * Path defaults to ~/.nlm/hook-log.jsonl, overridable via NLM_HOOK_LOG.
6
+ * Path is tenant-derived (core/tenancy/tenant-state-path.ts): the default
7
+ * team's log is ~/.nlm/hook-log.jsonl, overridable via NLM_HOOK_LOG; every
8
+ * other tenant is isolated under ~/.nlm/tenants/<tenantId>/hook-log.jsonl
9
+ * and ignores the env override.
7
10
  * appendHookLog swallows its own errors — telemetry must never break the hook.
8
11
  * Uses synchronous I/O: the hook is a short-lived per-prompt process, and an
9
12
  * async write could be lost if the process exits before it flushes.
10
13
  */
11
14
  import { appendFileSync, mkdirSync } from "node:fs";
12
- import { homedir } from "node:os";
13
- import { dirname, join } from "node:path";
14
- function logPath() {
15
- return process.env["NLM_HOOK_LOG"] ?? join(homedir(), ".nlm", "hook-log.jsonl");
15
+ import { dirname } from "node:path";
16
+ import { tenantStatePath } from "../tenancy/tenant-state-path.js";
17
+ import { DEFAULT_TEAM_ID } from "../tenancy/default-team.js";
18
+ import { NLM_VERSION } from "../../shared/version.js";
19
+ function logPath(tenantId) {
20
+ if (tenantId === DEFAULT_TEAM_ID) {
21
+ return process.env["NLM_HOOK_LOG"] ?? tenantStatePath(tenantId, "hook-log.jsonl");
22
+ }
23
+ return tenantStatePath(tenantId, "hook-log.jsonl");
16
24
  }
17
- export function appendHookLog(entry) {
25
+ export function appendHookLog(tenantId, entry) {
18
26
  try {
19
- const path = logPath();
27
+ const path = logPath(tenantId);
20
28
  mkdirSync(dirname(path), { recursive: true });
21
29
  // Sync I/O: hook is a short-lived process — async write could be lost on exit.
22
- appendFileSync(path, `${JSON.stringify(entry)}\n`, "utf8");
30
+ appendFileSync(path, `${JSON.stringify({ ...entry, v: NLM_VERSION })}\n`, "utf8");
23
31
  }
24
32
  catch {
25
33
  // Telemetry failure must never break the hook.
@@ -1 +1 @@
1
- {"version":3,"file":"hook-log.js","sourceRoot":"","sources":["../../../src/core/hook/hook-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgB1C,SAAS,OAAO;IACd,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAmB;IAC/C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,+EAA+E;QAC/E,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"hook-log.js","sourceRoot":"","sources":["../../../src/core/hook/hook-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAwBjD,SAAS,OAAO,CAAC,QAAgB;IAC/B,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,eAAe,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,KAAmB;IACjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC/B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,+EAA+E;QAC/E,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC"}
@@ -3,15 +3,19 @@
3
3
  * conversation holds the set of session ids already surfaced, so each is
4
4
  * surfaced at most once per conversation.
5
5
  *
6
- * State dir defaults to ~/.nlm/hook-state/, overridable via
7
- * NLM_HOOK_STATE_DIR (testability — mirrors query-log.ts).
6
+ * State dir is tenant-derived (core/tenancy/tenant-state-path.ts): the
7
+ * default team's memo dir is ~/.nlm/hook-state/, overridable via
8
+ * NLM_HOOK_STATE_DIR (testability — mirrors query-log.ts); every other
9
+ * tenant is isolated under ~/.nlm/tenants/<tenantId>/hook-state/ and
10
+ * ignores the env override (see the path contract note in
11
+ * tenant-state-path.ts).
8
12
  *
9
13
  * Every function is defensive: a missing or corrupt file yields an empty
10
14
  * memo, and a write failure is swallowed. The hook must never break on memo
11
15
  * I/O.
12
16
  */
13
- export declare function loadSurfaced(conversationId: string): Set<string>;
14
- export declare function recordSurfaced(conversationId: string, ids: ReadonlyArray<string>): void;
17
+ export declare function loadSurfaced(tenantId: string, conversationId: string): Set<string>;
18
+ export declare function recordSurfaced(tenantId: string, conversationId: string, ids: ReadonlyArray<string>): void;
15
19
  /**
16
20
  * Reverse lookup: which conversation most recently surfaced `sessionId`?
17
21
  *
@@ -23,10 +27,10 @@ export declare function recordSurfaced(conversationId: string, ids: ReadonlyArra
23
27
  *
24
28
  * Defensive: any I/O error yields null so cite_session never breaks.
25
29
  */
26
- export declare function resolveConversationForSession(sessionId: string): string | null;
30
+ export declare function resolveConversationForSession(tenantId: string, sessionId: string): string | null;
27
31
  /**
28
32
  * Delete the memo file for a closed conversation. Called by the SessionEnd
29
33
  * hook so memo files don't accumulate forever. Returns true if a file was
30
34
  * removed, false otherwise — callers may want to log the outcome.
31
35
  */
32
- export declare function clearSurfaced(conversationId: string): boolean;
36
+ export declare function clearSurfaced(tenantId: string, conversationId: string): boolean;