nlm-memory 0.20.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/README.md +17 -10
  2. package/dist/cli/digest.js +21 -0
  3. package/dist/cli/digest.js.map +1 -1
  4. package/dist/cli/init.d.ts +12 -0
  5. package/dist/cli/init.js +49 -0
  6. package/dist/cli/init.js.map +1 -0
  7. package/dist/cli/nlm.d.ts +13 -1
  8. package/dist/cli/nlm.js +766 -55
  9. package/dist/cli/nlm.js.map +1 -1
  10. package/dist/core/actions/overlay.d.ts +20 -6
  11. package/dist/core/actions/overlay.js +32 -18
  12. package/dist/core/actions/overlay.js.map +1 -1
  13. package/dist/core/adapters/claude-code.js +6 -0
  14. package/dist/core/adapters/claude-code.js.map +1 -1
  15. package/dist/core/classifier/prompt.js +3 -3
  16. package/dist/core/digest/compose.d.ts +10 -0
  17. package/dist/core/digest/compose.js +7 -1
  18. package/dist/core/digest/compose.js.map +1 -1
  19. package/dist/core/embedding/embed-backfill.d.ts +13 -2
  20. package/dist/core/embedding/embed-backfill.js +181 -43
  21. package/dist/core/embedding/embed-backfill.js.map +1 -1
  22. package/dist/core/embedding/embedding-config.d.ts +17 -0
  23. package/dist/core/embedding/embedding-config.js +12 -0
  24. package/dist/core/embedding/embedding-config.js.map +1 -0
  25. package/dist/core/embedding/pg-embed-backfill.d.ts +31 -0
  26. package/dist/core/embedding/pg-embed-backfill.js +264 -0
  27. package/dist/core/embedding/pg-embed-backfill.js.map +1 -0
  28. package/dist/core/entities/dedup-suggest.d.ts +25 -0
  29. package/dist/core/entities/dedup-suggest.js +107 -0
  30. package/dist/core/entities/dedup-suggest.js.map +1 -0
  31. package/dist/core/eval/classifier-fixture-eval.d.ts +29 -0
  32. package/dist/core/eval/classifier-fixture-eval.js +217 -0
  33. package/dist/core/eval/classifier-fixture-eval.js.map +1 -0
  34. package/dist/core/eval/extraction-scoring.d.ts +63 -0
  35. package/dist/core/eval/extraction-scoring.js +79 -0
  36. package/dist/core/eval/extraction-scoring.js.map +1 -0
  37. package/dist/core/eval/run-eval.d.ts +40 -0
  38. package/dist/core/eval/run-eval.js +34 -0
  39. package/dist/core/eval/run-eval.js.map +1 -0
  40. package/dist/core/exemplars/capture-from-session.d.ts +1 -0
  41. package/dist/core/exemplars/capture-from-session.js +6 -2
  42. package/dist/core/exemplars/capture-from-session.js.map +1 -1
  43. package/dist/core/exemplars/diff-parse.d.ts +23 -0
  44. package/dist/core/exemplars/diff-parse.js +73 -0
  45. package/dist/core/exemplars/diff-parse.js.map +1 -0
  46. package/dist/core/exemplars/embed-backfill.d.ts +36 -0
  47. package/dist/core/exemplars/embed-backfill.js +85 -0
  48. package/dist/core/exemplars/embed-backfill.js.map +1 -0
  49. package/dist/core/exemplars/embed-text.d.ts +15 -0
  50. package/dist/core/exemplars/embed-text.js +18 -0
  51. package/dist/core/exemplars/embed-text.js.map +1 -0
  52. package/dist/core/exemplars/extract-exemplar.js +2 -65
  53. package/dist/core/exemplars/extract-exemplar.js.map +1 -1
  54. package/dist/core/exemplars/recall-code.js +4 -0
  55. package/dist/core/exemplars/recall-code.js.map +1 -1
  56. package/dist/core/exemplars/warm-embedder.d.ts +14 -0
  57. package/dist/core/exemplars/warm-embedder.js +18 -0
  58. package/dist/core/exemplars/warm-embedder.js.map +1 -0
  59. package/dist/core/health/corpus-state.d.ts +8 -0
  60. package/dist/core/health/corpus-state.js +11 -0
  61. package/dist/core/health/corpus-state.js.map +1 -0
  62. package/dist/core/health/embed-inflight.d.ts +9 -0
  63. package/dist/core/health/embed-inflight.js +30 -0
  64. package/dist/core/health/embed-inflight.js.map +1 -0
  65. package/dist/core/health/embedding-lane-state.d.ts +6 -0
  66. package/dist/core/health/embedding-lane-state.js +18 -0
  67. package/dist/core/health/embedding-lane-state.js.map +1 -0
  68. package/dist/core/health/warmup-state.d.ts +12 -0
  69. package/dist/core/health/warmup-state.js +12 -0
  70. package/dist/core/health/warmup-state.js.map +1 -0
  71. package/dist/core/hook/gate.d.ts +13 -6
  72. package/dist/core/hook/gate.js +47 -6
  73. package/dist/core/hook/gate.js.map +1 -1
  74. package/dist/core/hook/hook-log.d.ts +5 -0
  75. package/dist/core/hook/hook-log.js.map +1 -1
  76. package/dist/core/hook/memo.d.ts +12 -0
  77. package/dist/core/hook/memo.js +41 -1
  78. package/dist/core/hook/memo.js.map +1 -1
  79. package/dist/core/hook/pointer-block.d.ts +1 -0
  80. package/dist/core/hook/pointer-block.js +23 -2
  81. package/dist/core/hook/pointer-block.js.map +1 -1
  82. package/dist/core/hook/query-extract.d.ts +2 -1
  83. package/dist/core/hook/query-extract.js +10 -1
  84. package/dist/core/hook/query-extract.js.map +1 -1
  85. package/dist/core/hook/resolve-conversation-by-query.d.ts +28 -0
  86. package/dist/core/hook/resolve-conversation-by-query.js +98 -0
  87. package/dist/core/hook/resolve-conversation-by-query.js.map +1 -0
  88. package/dist/core/hook/select.d.ts +8 -0
  89. package/dist/core/hook/select.js +9 -2
  90. package/dist/core/hook/select.js.map +1 -1
  91. package/dist/core/hook/transcript.js +16 -2
  92. package/dist/core/hook/transcript.js.map +1 -1
  93. package/dist/core/ingest/ingest-session.d.ts +5 -0
  94. package/dist/core/ingest/ingest-session.js +3 -0
  95. package/dist/core/ingest/ingest-session.js.map +1 -1
  96. package/dist/core/ingest/reclassify-oversized.d.ts +5 -0
  97. package/dist/core/ingest/reclassify-oversized.js +3 -0
  98. package/dist/core/ingest/reclassify-oversized.js.map +1 -1
  99. package/dist/core/ingest/reprocess.d.ts +96 -0
  100. package/dist/core/ingest/reprocess.js +275 -0
  101. package/dist/core/ingest/reprocess.js.map +1 -0
  102. package/dist/core/integrity/check-invariants.d.ts +6 -1
  103. package/dist/core/integrity/check-invariants.js +209 -3
  104. package/dist/core/integrity/check-invariants.js.map +1 -1
  105. package/dist/core/metrics/corpus-stats.d.ts +49 -0
  106. package/dist/core/metrics/corpus-stats.js +111 -0
  107. package/dist/core/metrics/corpus-stats.js.map +1 -0
  108. package/dist/core/metrics/re-derivation.d.ts +48 -0
  109. package/dist/core/metrics/re-derivation.js +87 -0
  110. package/dist/core/metrics/re-derivation.js.map +1 -0
  111. package/dist/core/recall/citation-log.d.ts +8 -0
  112. package/dist/core/recall/citation-log.js +17 -0
  113. package/dist/core/recall/citation-log.js.map +1 -1
  114. package/dist/core/recall/query-intent.d.ts +7 -0
  115. package/dist/core/recall/query-intent.js +25 -0
  116. package/dist/core/recall/query-intent.js.map +1 -0
  117. package/dist/core/recall/query-log.d.ts +4 -0
  118. package/dist/core/recall/query-log.js +4 -0
  119. package/dist/core/recall/query-log.js.map +1 -1
  120. package/dist/core/recall/recall-service.d.ts +37 -1
  121. package/dist/core/recall/recall-service.js +106 -63
  122. package/dist/core/recall/recall-service.js.map +1 -1
  123. package/dist/core/recall/related-exemplars.d.ts +1 -0
  124. package/dist/core/recall/related-exemplars.js +4 -1
  125. package/dist/core/recall/related-exemplars.js.map +1 -1
  126. package/dist/core/recall/related-facts.js +2 -2
  127. package/dist/core/recall/related-facts.js.map +1 -1
  128. package/dist/core/recall/reranker.d.ts +2 -1
  129. package/dist/core/recall/reranker.js +3 -3
  130. package/dist/core/recall/reranker.js.map +1 -1
  131. package/dist/core/recall-facts/fact-query-log.d.ts +7 -0
  132. package/dist/core/recall-facts/fact-query-log.js +2 -0
  133. package/dist/core/recall-facts/fact-query-log.js.map +1 -1
  134. package/dist/core/recall-facts/fact-recall-service.d.ts +9 -1
  135. package/dist/core/recall-facts/fact-recall-service.js +21 -8
  136. package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
  137. package/dist/core/scheduler/scan-once.d.ts +6 -6
  138. package/dist/core/scheduler/scan-once.js +13 -49
  139. package/dist/core/scheduler/scan-once.js.map +1 -1
  140. package/dist/core/scheduler/scheduler.d.ts +10 -0
  141. package/dist/core/scheduler/scheduler.js +75 -10
  142. package/dist/core/scheduler/scheduler.js.map +1 -1
  143. package/dist/core/signals/code-signal.d.ts +49 -0
  144. package/dist/core/signals/code-signal.js +53 -0
  145. package/dist/core/signals/code-signal.js.map +1 -0
  146. package/dist/core/storage/db-restore.js +3 -1
  147. package/dist/core/storage/db-restore.js.map +1 -1
  148. package/dist/core/storage/fact-batch.d.ts +9 -0
  149. package/dist/core/storage/fact-batch.js +14 -0
  150. package/dist/core/storage/fact-batch.js.map +1 -0
  151. package/dist/core/storage/pg-code-exemplar-store.d.ts +1 -0
  152. package/dist/core/storage/pg-code-exemplar-store.js +7 -0
  153. package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
  154. package/dist/core/storage/pg-embedding-config.d.ts +29 -0
  155. package/dist/core/storage/pg-embedding-config.js +53 -0
  156. package/dist/core/storage/pg-embedding-config.js.map +1 -0
  157. package/dist/core/storage/pg-entity-store.d.ts +12 -0
  158. package/dist/core/storage/pg-entity-store.js +79 -0
  159. package/dist/core/storage/pg-entity-store.js.map +1 -0
  160. package/dist/core/storage/pg-fact-ingest.d.ts +15 -0
  161. package/dist/core/storage/pg-fact-ingest.js +34 -0
  162. package/dist/core/storage/pg-fact-ingest.js.map +1 -0
  163. package/dist/core/storage/pg-fact-store.d.ts +3 -0
  164. package/dist/core/storage/pg-fact-store.js +26 -30
  165. package/dist/core/storage/pg-fact-store.js.map +1 -1
  166. package/dist/core/storage/pg-migrate.d.ts +18 -0
  167. package/dist/core/storage/pg-migrate.js +73 -0
  168. package/dist/core/storage/pg-migrate.js.map +1 -0
  169. package/dist/core/storage/pg-session-store.d.ts +9 -0
  170. package/dist/core/storage/pg-session-store.js +204 -76
  171. package/dist/core/storage/pg-session-store.js.map +1 -1
  172. package/dist/core/storage/pg-storage.d.ts +9 -7
  173. package/dist/core/storage/pg-storage.js +20 -50
  174. package/dist/core/storage/pg-storage.js.map +1 -1
  175. package/dist/core/storage/pg-workstream-store.d.ts +24 -0
  176. package/dist/core/storage/pg-workstream-store.js +96 -0
  177. package/dist/core/storage/pg-workstream-store.js.map +1 -0
  178. package/dist/core/storage/sqlite-code-exemplar-store.d.ts +1 -0
  179. package/dist/core/storage/sqlite-code-exemplar-store.js +11 -0
  180. package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
  181. package/dist/core/storage/sqlite-embedding-config.d.ts +10 -0
  182. package/dist/core/storage/sqlite-embedding-config.js +27 -0
  183. package/dist/core/storage/sqlite-embedding-config.js.map +1 -0
  184. package/dist/core/storage/sqlite-entity-store.d.ts +13 -0
  185. package/dist/core/storage/sqlite-entity-store.js +96 -0
  186. package/dist/core/storage/sqlite-entity-store.js.map +1 -0
  187. package/dist/core/storage/sqlite-fact-store.d.ts +15 -7
  188. package/dist/core/storage/sqlite-fact-store.js +76 -25
  189. package/dist/core/storage/sqlite-fact-store.js.map +1 -1
  190. package/dist/core/storage/sqlite-session-store.d.ts +20 -5
  191. package/dist/core/storage/sqlite-session-store.js +183 -68
  192. package/dist/core/storage/sqlite-session-store.js.map +1 -1
  193. package/dist/core/storage/sqlite-storage.d.ts +8 -8
  194. package/dist/core/storage/sqlite-storage.js +21 -32
  195. package/dist/core/storage/sqlite-storage.js.map +1 -1
  196. package/dist/core/storage/sqlite-workstream-store.d.ts +24 -0
  197. package/dist/core/storage/sqlite-workstream-store.js +98 -0
  198. package/dist/core/storage/sqlite-workstream-store.js.map +1 -0
  199. package/dist/core/work-digest/active-spans.d.ts +8 -0
  200. package/dist/core/work-digest/active-spans.js +29 -0
  201. package/dist/core/work-digest/active-spans.js.map +1 -0
  202. package/dist/core/work-digest/attribute.d.ts +15 -0
  203. package/dist/core/work-digest/attribute.js +76 -0
  204. package/dist/core/work-digest/attribute.js.map +1 -0
  205. package/dist/core/work-digest/build-work-digest.d.ts +12 -0
  206. package/dist/core/work-digest/build-work-digest.js +69 -0
  207. package/dist/core/work-digest/build-work-digest.js.map +1 -0
  208. package/dist/core/work-digest/compose-work-digest.d.ts +3 -0
  209. package/dist/core/work-digest/compose-work-digest.js +52 -0
  210. package/dist/core/work-digest/compose-work-digest.js.map +1 -0
  211. package/dist/core/work-digest/merge-active.d.ts +10 -0
  212. package/dist/core/work-digest/merge-active.js +22 -0
  213. package/dist/core/work-digest/merge-active.js.map +1 -0
  214. package/dist/core/work-digest/read-transcript-timestamps.d.ts +7 -0
  215. package/dist/core/work-digest/read-transcript-timestamps.js +40 -0
  216. package/dist/core/work-digest/read-transcript-timestamps.js.map +1 -0
  217. package/dist/core/work-digest/topics.d.ts +18 -0
  218. package/dist/core/work-digest/topics.js +26 -0
  219. package/dist/core/work-digest/topics.js.map +1 -0
  220. package/dist/core/work-digest/types.d.ts +45 -0
  221. package/dist/core/work-digest/types.js +2 -0
  222. package/dist/core/work-digest/types.js.map +1 -0
  223. package/dist/core/workstream/bind.d.ts +25 -0
  224. package/dist/core/workstream/bind.js +23 -0
  225. package/dist/core/workstream/bind.js.map +1 -0
  226. package/dist/core/workstream/compose-recall.d.ts +2 -0
  227. package/dist/core/workstream/compose-recall.js +39 -0
  228. package/dist/core/workstream/compose-recall.js.map +1 -0
  229. package/dist/core/workstream/merge-suggest.d.ts +19 -0
  230. package/dist/core/workstream/merge-suggest.js +61 -0
  231. package/dist/core/workstream/merge-suggest.js.map +1 -0
  232. package/dist/core/workstream/model.d.ts +20 -0
  233. package/dist/core/workstream/model.js +9 -0
  234. package/dist/core/workstream/model.js.map +1 -0
  235. package/dist/core/workstream/name-match.d.ts +8 -0
  236. package/dist/core/workstream/name-match.js +18 -0
  237. package/dist/core/workstream/name-match.js.map +1 -0
  238. package/dist/core/workstream/resolve.d.ts +10 -0
  239. package/dist/core/workstream/resolve.js +21 -0
  240. package/dist/core/workstream/resolve.js.map +1 -0
  241. package/dist/core/workstream/rollup.d.ts +12 -0
  242. package/dist/core/workstream/rollup.js +17 -0
  243. package/dist/core/workstream/rollup.js.map +1 -0
  244. package/dist/core/workstream/work-topics.d.ts +10 -0
  245. package/dist/core/workstream/work-topics.js +55 -0
  246. package/dist/core/workstream/work-topics.js.map +1 -0
  247. package/dist/hook/hook-helpers.d.ts +4 -0
  248. package/dist/hook/hook-helpers.js +36 -0
  249. package/dist/hook/hook-helpers.js.map +1 -0
  250. package/dist/hook/pre-compact-hook.d.ts +23 -0
  251. package/dist/hook/pre-compact-hook.js +66 -0
  252. package/dist/hook/pre-compact-hook.js.map +1 -0
  253. package/dist/hook/prompt-recall-hook.d.ts +37 -0
  254. package/dist/hook/prompt-recall-hook.js +120 -20
  255. package/dist/hook/prompt-recall-hook.js.map +1 -1
  256. package/dist/hook/recall-gate.d.ts +29 -0
  257. package/dist/hook/recall-gate.js +50 -0
  258. package/dist/hook/recall-gate.js.map +1 -0
  259. package/dist/hook/recall-over-http.d.ts +1 -1
  260. package/dist/hook/recall-over-http.js +11 -11
  261. package/dist/hook/recall-over-http.js.map +1 -1
  262. package/dist/hook/recent-context.d.ts +25 -0
  263. package/dist/hook/recent-context.js +104 -0
  264. package/dist/hook/recent-context.js.map +1 -0
  265. package/dist/hook/score-floor.d.ts +27 -0
  266. package/dist/hook/score-floor.js +42 -0
  267. package/dist/hook/score-floor.js.map +1 -0
  268. package/dist/hook/session-end-hook.js +8 -29
  269. package/dist/hook/session-end-hook.js.map +1 -1
  270. package/dist/hook/session-start-hook.js +24 -59
  271. package/dist/hook/session-start-hook.js.map +1 -1
  272. package/dist/hook/stop-hook.js +22 -59
  273. package/dist/hook/stop-hook.js.map +1 -1
  274. package/dist/hook/subagent-start-hook.d.ts +28 -0
  275. package/dist/hook/subagent-start-hook.js +81 -0
  276. package/dist/hook/subagent-start-hook.js.map +1 -0
  277. package/dist/http/app.js +28 -8
  278. package/dist/http/app.js.map +1 -1
  279. package/dist/install/setup.js +2 -0
  280. package/dist/install/setup.js.map +1 -1
  281. package/dist/llm/build-classifier.d.ts +22 -0
  282. package/dist/llm/build-classifier.js +42 -0
  283. package/dist/llm/build-classifier.js.map +1 -0
  284. package/dist/llm/build-embedder.d.ts +11 -0
  285. package/dist/llm/build-embedder.js +42 -0
  286. package/dist/llm/build-embedder.js.map +1 -0
  287. package/dist/llm/bundled-embedder-client.d.ts +37 -0
  288. package/dist/llm/bundled-embedder-client.js +90 -0
  289. package/dist/llm/bundled-embedder-client.js.map +1 -0
  290. package/dist/llm/classifier-box.d.ts +13 -5
  291. package/dist/llm/classifier-box.js +28 -6
  292. package/dist/llm/classifier-box.js.map +1 -1
  293. package/dist/llm/classifier-egress.d.ts +18 -0
  294. package/dist/llm/classifier-egress.js +59 -0
  295. package/dist/llm/classifier-egress.js.map +1 -0
  296. package/dist/llm/client-shared.d.ts +4 -0
  297. package/dist/llm/client-shared.js +39 -0
  298. package/dist/llm/client-shared.js.map +1 -0
  299. package/dist/llm/deepseek-client.d.ts +20 -0
  300. package/dist/llm/deepseek-client.js +59 -45
  301. package/dist/llm/deepseek-client.js.map +1 -1
  302. package/dist/llm/embedder-info.d.ts +15 -0
  303. package/dist/llm/embedder-info.js +27 -0
  304. package/dist/llm/embedder-info.js.map +1 -0
  305. package/dist/llm/model-quirks.d.ts +4 -0
  306. package/dist/llm/model-quirks.js +7 -0
  307. package/dist/llm/model-quirks.js.map +1 -0
  308. package/dist/llm/naming.d.ts +5 -0
  309. package/dist/llm/naming.js +20 -0
  310. package/dist/llm/naming.js.map +1 -0
  311. package/dist/llm/ollama-client.d.ts +7 -8
  312. package/dist/llm/ollama-client.js +59 -51
  313. package/dist/llm/ollama-client.js.map +1 -1
  314. package/dist/llm/ollama-code-embedder.d.ts +8 -3
  315. package/dist/llm/ollama-code-embedder.js +14 -24
  316. package/dist/llm/ollama-code-embedder.js.map +1 -1
  317. package/dist/llm/openai-code-embedder-client.d.ts +25 -0
  318. package/dist/llm/openai-code-embedder-client.js +52 -0
  319. package/dist/llm/openai-code-embedder-client.js.map +1 -0
  320. package/dist/llm/openai-embedder-client.d.ts +41 -0
  321. package/dist/llm/openai-embedder-client.js +83 -0
  322. package/dist/llm/openai-embedder-client.js.map +1 -0
  323. package/dist/mcp/server.d.ts +47 -2
  324. package/dist/mcp/server.js +303 -18
  325. package/dist/mcp/server.js.map +1 -1
  326. package/dist/ports/code-embedder.d.ts +6 -1
  327. package/dist/ports/code-exemplar-store.d.ts +5 -0
  328. package/dist/ports/entity-store.d.ts +35 -0
  329. package/dist/ports/entity-store.js +7 -0
  330. package/dist/ports/entity-store.js.map +1 -0
  331. package/dist/ports/fact-store.d.ts +0 -0
  332. package/dist/ports/fact-store.js.map +1 -1
  333. package/dist/ports/llm-client.d.ts +9 -1
  334. package/dist/ports/session-store.d.ts +12 -0
  335. package/dist/ports/storage.d.ts +7 -30
  336. package/dist/ports/storage.js +3 -7
  337. package/dist/ports/storage.js.map +1 -1
  338. package/dist/ports/transcript-adapter.d.ts +2 -0
  339. package/dist/ports/workstream-store.d.ts +21 -0
  340. package/dist/ports/workstream-store.js +2 -0
  341. package/dist/ports/workstream-store.js.map +1 -0
  342. package/dist/shared/types.d.ts +23 -2
  343. package/fixtures/classifier-gold/README.md +94 -0
  344. package/fixtures/classifier-gold/reference.json +318 -0
  345. package/fixtures/classifier-gold/transcripts/01-bug-fix-null-pointer-api.txt +75 -0
  346. package/fixtures/classifier-gold/transcripts/02-bug-fix-race-condition-queue.txt +77 -0
  347. package/fixtures/classifier-gold/transcripts/03-bug-fix-jwt-clock-skew.txt +86 -0
  348. package/fixtures/classifier-gold/transcripts/04-feature-webhook-retry.txt +95 -0
  349. package/fixtures/classifier-gold/transcripts/05-feature-csv-export.txt +86 -0
  350. package/fixtures/classifier-gold/transcripts/06-feature-rate-limiting.txt +61 -0
  351. package/fixtures/classifier-gold/transcripts/07-refactor-db-abstraction.txt +72 -0
  352. package/fixtures/classifier-gold/transcripts/08-refactor-config-loading.txt +89 -0
  353. package/fixtures/classifier-gold/transcripts/09-ops-docker-staging.txt +94 -0
  354. package/fixtures/classifier-gold/transcripts/10-ops-nginx-ssl.txt +121 -0
  355. package/fixtures/classifier-gold/transcripts/11-ops-postgres-migration.txt +74 -0
  356. package/fixtures/classifier-gold/transcripts/12-ops-cron-debugging.txt +73 -0
  357. package/fixtures/classifier-gold/transcripts/13-research-vector-db-comparison.txt +59 -0
  358. package/fixtures/classifier-gold/transcripts/14-research-oauth-provider.txt +74 -0
  359. package/fixtures/classifier-gold/transcripts/15-writing-api-docs.txt +154 -0
  360. package/fixtures/classifier-gold/transcripts/16-meeting-sprint-planning.txt +69 -0
  361. package/fixtures/classifier-gold/transcripts/17-trivial-list-files.txt +14 -0
  362. package/fixtures/classifier-gold/transcripts/18-trivial-version-check.txt +21 -0
  363. package/fixtures/classifier-gold/transcripts/19-trivial-syntax-help.txt +29 -0
  364. package/fixtures/classifier-gold/transcripts/20-trivial-read-package-json.txt +41 -0
  365. package/migrations/000_initial_schema.sql +1 -1
  366. package/migrations/024_backfill_exemplar_repo_basename.sql +32 -0
  367. package/migrations/025_workstreams.sql +30 -0
  368. package/migrations/026_embedding_config.sql +12 -0
  369. package/migrations/027_drop_legacy_session_embeddings.sql +7 -0
  370. package/migrations/028_classifier_provenance.sql +5 -0
  371. package/migrations/pg/001_initial.sql +34 -0
  372. package/migrations/pg/019_split_replaces.sql +16 -7
  373. package/migrations/pg/025_workstreams.sql +34 -0
  374. package/migrations/pg/026_embedding_config.sql +12 -0
  375. package/migrations/pg/028_classifier_provenance.sql +5 -0
  376. package/migrations/pg/029_entity_variants.sql +9 -0
  377. package/nlm/index.js +395 -37
  378. package/package.json +12 -2
  379. package/plugin/.codex-plugin/plugin.json +1 -1
  380. package/plugin/scripts/prompt-recall-hook.mjs +402 -41
  381. package/plugin/scripts/session-start-hook.mjs +286 -60
  382. package/plugin/scripts/stop-hook.mjs +85 -65
  383. package/plugin-hermes-agent/__init__.py +2 -1
  384. package/templates/agent-contract/README.md +24 -0
  385. package/templates/agent-contract/claude-code.md +40 -0
  386. package/templates/agent-contract/generic.md +38 -0
  387. package/dist/core/embedding/embed-normalize.d.ts +0 -28
  388. package/dist/core/embedding/embed-normalize.js +0 -98
  389. package/dist/core/embedding/embed-normalize.js.map +0 -1
  390. package/dist/core/storage/pg-tx-context.d.ts +0 -52
  391. package/dist/core/storage/pg-tx-context.js +0 -149
  392. package/dist/core/storage/pg-tx-context.js.map +0 -1
@@ -0,0 +1,35 @@
1
+ /**
2
+ * EntityStore -- read/write surface for the entities + entity_variants tables.
3
+ *
4
+ * Lives on Storage.entities. Both SQLite and PG adapters implement this port.
5
+ */
6
+ export interface EntityRow {
7
+ readonly canonical: string;
8
+ readonly type: string;
9
+ readonly status: string;
10
+ readonly sessionCount: number;
11
+ readonly firstSeenSession: string | null;
12
+ readonly lastSeenSession: string | null;
13
+ }
14
+ export interface EntityStore {
15
+ /**
16
+ * Merge source entity into target entity.
17
+ *
18
+ * Semantics (both adapters, inside one transaction):
19
+ * 1. INSERT OR IGNORE (pg: ON CONFLICT DO NOTHING) session_entities rows
20
+ * from source onto target to preserve all session links.
21
+ * 2. DELETE the source's session_entities rows.
22
+ * 3. Recompute target.session_count exactly from session_entities.
23
+ * 4. Widen target first_seen_session / last_seen_session to the
24
+ * chronologically earliest / latest session across both entities.
25
+ * 5. INSERT INTO entity_variants (variant=source, canonical=target,
26
+ * source_session_id=NULL) so future ingest of the old surface form
27
+ * binds to the canonical.
28
+ * 6. Re-point any existing entity_variants rows where canonical=source
29
+ * to canonical=target.
30
+ * 7. Keep the source entities row with status='retired', session_count=0.
31
+ *
32
+ * Errors loudly when target is missing or already retired.
33
+ */
34
+ merge(source: string, target: string): Promise<void>;
35
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * EntityStore -- read/write surface for the entities + entity_variants tables.
3
+ *
4
+ * Lives on Storage.entities. Both SQLite and PG adapters implement this port.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=entity-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-store.js","sourceRoot":"","sources":["../../src/ports/entity-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
Binary file
@@ -1 +1 @@
1
- {"version":3,"file":"fact-store.js","sourceRoot":"","sources":["../../src/ports/fact-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA4JH,uDAAuD;AACvD,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,SAAiB,EAAE,KAAa;IAChF,OAAO,GAAG,OAAO,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"fact-store.js","sourceRoot":"","sources":["../../src/ports/fact-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoKH,uDAAuD;AACvD,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,SAAiB,EAAE,KAAa;IAChF,OAAO,GAAG,OAAO,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;AAC5C,CAAC"}
@@ -54,9 +54,17 @@ export interface RewriteResult {
54
54
  /** Free-text rationale for debugging; not used by the retrieval path. */
55
55
  readonly rationale?: string;
56
56
  }
57
+ export interface WorkstreamCandidateHint {
58
+ readonly label: string;
59
+ }
57
60
  export interface LLMClient {
58
- embed(text: string, kind: EmbeddingKind): Promise<EmbedResult>;
61
+ embed(text: string, kind: EmbeddingKind, opts?: {
62
+ signal?: AbortSignal;
63
+ }): Promise<EmbedResult>;
59
64
  classify(transcript: string): Promise<ClassifyResult>;
65
+ /** Name which candidate workstream this session belongs to, or null for "none".
66
+ * Returns the chosen candidate.label verbatim. Content is label+summary or a transcript. */
67
+ nameWorkstream(content: string, candidates: ReadonlyArray<WorkstreamCandidateHint>): Promise<string | null>;
60
68
  /**
61
69
  * Rewrite a recall query for better retrieval. Cheap-ish call (one-shot
62
70
  * chat completion, ~hundreds of ms locally). Implementations MUST throw
@@ -5,6 +5,7 @@
5
5
  * interface, never on better-sqlite3 directly. Swapping SQLite for Postgres
6
6
  * tomorrow means writing a new implementation; core/ does not change.
7
7
  */
8
+ import type { BindingSource } from "../core/workstream/model.js";
8
9
  import type { Session, SessionStatus } from "../shared/types.js";
9
10
  export interface SessionFilter {
10
11
  readonly entity?: string;
@@ -27,11 +28,18 @@ export interface KeywordNeighbor {
27
28
  */
28
29
  export interface SearchOptions {
29
30
  readonly includeSuperseded?: boolean;
31
+ readonly workstreamIds?: ReadonlyArray<string>;
30
32
  }
31
33
  export interface SessionStore {
32
34
  list(filter?: SessionFilter): Promise<ReadonlyArray<Session>>;
33
35
  getById(sessionId: string): Promise<Session | null>;
34
36
  getByIds(ids: ReadonlyArray<string>): Promise<ReadonlyArray<Session>>;
37
+ /**
38
+ * Sessions whose lifespan [started_at, ended_at or open] overlaps the
39
+ * half-open window [fromIso, toIso). Body is omitted (callers that need it
40
+ * fetch by id). Ordered by started_at ascending. Used by the work-digest.
41
+ */
42
+ listByDateRange(fromIso: string, toIso: string): Promise<ReadonlyArray<Session>>;
35
43
  semanticSearch(queryVector: Float32Array, limit: number, opts?: SearchOptions): Promise<ReadonlyArray<SemanticNeighbor>>;
36
44
  keywordSearch(query: string, limit: number, opts?: SearchOptions): Promise<ReadonlyArray<KeywordNeighbor>>;
37
45
  /**
@@ -53,4 +61,8 @@ export interface SessionStore {
53
61
  * action that lets an operator retroactively retire a stale session.
54
62
  */
55
63
  markSuperseded(predecessorId: string, successorId: string): Promise<void>;
64
+ setWorkstreamBinding(sessionId: string, workstreamId: string | null, source: BindingSource | null, confidence: number | null): Promise<void>;
65
+ listSessionIdsByWorkstreams(workstreamIds: ReadonlyArray<string>): Promise<ReadonlyArray<string>>;
66
+ getEntities(sessionId: string): Promise<ReadonlyArray<string>>;
67
+ getWorkstreamIds(sessionIds: ReadonlyArray<string>): Promise<Map<string, string | null>>;
56
68
  }
@@ -1,53 +1,30 @@
1
1
  /**
2
2
  * Storage — top-level handle for NLM's fact + session corpus. Owns lifecycle
3
- * (init/close) and the atomic unit-of-work primitive (withTransaction).
4
- *
5
- * Read paths use the bare .facts / .sessions handles. Writes that must
6
- * commit together — session+facts+embeddings on ingest, supersedence chain
7
- * edits — go through withTransaction so the adapter chooses its own
8
- * atomicity mechanism (single SQLite connection, PG transaction, etc.)
9
- * without core/ knowing which backend it's talking to.
3
+ * (init/close). Read and write paths use the bare .facts / .sessions handles;
4
+ * adapters manage atomicity internally via explicit BEGIN/COMMIT on a PoolClient
5
+ * (PG) or a single WAL writer (SQLite).
10
6
  *
11
7
  * See docs/plans/2026-05-30-factstore-storage-port.md.
12
8
  */
13
9
  import type { CodeExemplarStore } from "./code-exemplar-store.js";
10
+ import type { EntityStore } from "./entity-store.js";
14
11
  import type { FactStore } from "./fact-store.js";
15
12
  import type { SessionStore } from "./session-store.js";
16
13
  import type { SignalStore } from "./signal-store.js";
14
+ import type { WorkstreamStore } from "./workstream-store.js";
17
15
  import type { SourceRegistryPort } from "../core/sources/source-registry.js";
18
16
  import type { ProviderRegistryPort } from "../core/providers/provider-registry.js";
19
- export interface StorageContext {
20
- readonly facts: FactStore;
21
- readonly sessions: SessionStore;
22
- }
23
17
  export interface Storage {
24
18
  readonly facts: FactStore;
25
19
  readonly sessions: SessionStore;
26
20
  readonly signals: SignalStore;
27
21
  readonly exemplars: CodeExemplarStore;
22
+ readonly workstreams: WorkstreamStore;
23
+ readonly entities: EntityStore;
28
24
  /** Transcript-source registry (claude-code/hermes/webhook/…). */
29
25
  readonly sources: SourceRegistryPort;
30
26
  /** LLM-provider registry (ollama/deepseek/openai/…). */
31
27
  readonly providers: ProviderRegistryPort;
32
- /**
33
- * Run `fn` inside an adapter-defined transaction. The handles on the
34
- * provided StorageContext are bound to that transaction; reads and writes
35
- * through them see one another, and either all commit or all roll back.
36
- * Outer handles (storage.facts, storage.sessions) MUST NOT be used inside
37
- * `fn`; adapters may enforce this with a runtime check.
38
- *
39
- * Callbacks MUST be synchronous. Async work (embedder calls, network I/O)
40
- * runs BEFORE or AFTER withTransaction, not inside. The SQLite adapter
41
- * enforces this constraint structurally (better-sqlite3 transactions are
42
- * synchronous); the Postgres adapter will honor the same shape by
43
- * batching sync operations into a single async txn. This keeps the
44
- * port honest across backends and matches the established pattern in
45
- * SqliteSessionStore.insertSession where embedding work lives outside
46
- * the transaction.
47
- *
48
- * Nested calls are not supported. Adapters throw on nested invocation.
49
- */
50
- withTransaction<T>(fn: (ctx: StorageContext) => T): Promise<T>;
51
28
  /** Apply migrations / install extensions. Idempotent. */
52
29
  init(): Promise<void>;
53
30
  /** Release the underlying connection or pool. */
@@ -1,12 +1,8 @@
1
1
  /**
2
2
  * Storage — top-level handle for NLM's fact + session corpus. Owns lifecycle
3
- * (init/close) and the atomic unit-of-work primitive (withTransaction).
4
- *
5
- * Read paths use the bare .facts / .sessions handles. Writes that must
6
- * commit together — session+facts+embeddings on ingest, supersedence chain
7
- * edits — go through withTransaction so the adapter chooses its own
8
- * atomicity mechanism (single SQLite connection, PG transaction, etc.)
9
- * without core/ knowing which backend it's talking to.
3
+ * (init/close). Read and write paths use the bare .facts / .sessions handles;
4
+ * adapters manage atomicity internally via explicit BEGIN/COMMIT on a PoolClient
5
+ * (PG) or a single WAL writer (SQLite).
10
6
  *
11
7
  * See docs/plans/2026-05-30-factstore-storage-port.md.
12
8
  */
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/ports/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/ports/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -31,6 +31,8 @@ export interface SessionChunk {
31
31
  readonly gitBranch: string;
32
32
  readonly text: string;
33
33
  readonly label: string;
34
+ /** Last assistant-turn model string seen in this chunk. Omitted when the transcript carries no model field. */
35
+ readonly model?: string;
34
36
  /**
35
37
  * Raw `nlm.signal` payloads found in the transcript (Pi custom_message
36
38
  * entries). Normalized + persisted by the scheduler, decoupled from session
@@ -0,0 +1,21 @@
1
+ import type { Workstream } from "../core/workstream/model.js";
2
+ export interface WorkstreamStore {
3
+ create(input: {
4
+ id: string;
5
+ label: string;
6
+ }): Promise<Workstream>;
7
+ getById(id: string): Promise<Workstream | null>;
8
+ findByNormalizedLabel(normalizedLabel: string): Promise<Workstream | null>;
9
+ listAll(): Promise<ReadonlyArray<Workstream>>;
10
+ touchLastSession(id: string, atIso: string): Promise<void>;
11
+ setLabel(id: string, label: string): Promise<void>;
12
+ setStatus(id: string, status: import("../core/workstream/model.js").WorkstreamStatus): Promise<void>;
13
+ /** Supersede fromId into intoId: set merged_into + status="merged", union entities, clear from's entity rows. */
14
+ merge(fromId: string, intoId: string): Promise<void>;
15
+ upsertEntities(workstreamId: string, entities: ReadonlyArray<string>): Promise<void>;
16
+ entitiesFor(workstreamIds: ReadonlyArray<string>): Promise<Map<string, string[]>>;
17
+ candidatesByEntityOverlap(entities: ReadonlyArray<string>, limit: number): Promise<ReadonlyArray<{
18
+ workstreamId: string;
19
+ entities: string[];
20
+ }>>;
21
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=workstream-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workstream-store.js","sourceRoot":"","sources":["../../src/ports/workstream-store.ts"],"names":[],"mappings":""}
@@ -36,6 +36,12 @@ export interface Session {
36
36
  readonly supersedes?: ReadonlyArray<string>;
37
37
  /** ID of the session that superseded this one, if any. Populated by getById; absent on bulk reads. */
38
38
  readonly supersededBy?: string | null;
39
+ /** Live binding to a workstream, if any. Populated by projections that select it (e.g. listByDateRange); absent elsewhere. */
40
+ readonly workstreamId?: string | null;
41
+ /** Classifier that produced this session's classification. NULL = classified before provenance tracking. */
42
+ readonly classifierProvider?: string | null;
43
+ readonly classifierModel?: string | null;
44
+ readonly classifierConfidence?: number | null;
39
45
  }
40
46
  /**
41
47
  * Supersedence-relation edge kinds in `session_edges.kind`.
@@ -95,6 +101,14 @@ export interface RecallQuery {
95
101
  * Task #303.
96
102
  */
97
103
  readonly includeSuperseded?: boolean;
104
+ /**
105
+ * Optional workstream id or label to filter recall results. When set, only
106
+ * sessions bound to the resolved workstream (or any member of its merge
107
+ * chain) are returned. Merge chains resolve to the live survivor. No-op
108
+ * when omitted or when `resolveWorkstreamMembers` is not wired into
109
+ * RecallServiceDeps.
110
+ */
111
+ readonly workstream?: string;
98
112
  }
99
113
  export interface RecallHit {
100
114
  readonly id: string;
@@ -150,7 +164,7 @@ export interface RecallResult {
150
164
  * docs/plans/factstore-design.md for the full design rationale.
151
165
  *
152
166
  * `kind` mirrors the marker taxonomy plus a third category for entity
153
- * attributes ("mac-pro-llm-host" + "endpoint" + "http://macpro:8080/v1").
167
+ * attributes ("local-llm-host" + "endpoint" + "http://macpro:8080/v1").
154
168
  *
155
169
  * `subject` and `predicate` are normalized (lowercased, trimmed) at extraction
156
170
  * time so the deterministic supersedence path can do exact-match collision
@@ -171,6 +185,13 @@ export interface Fact {
171
185
  readonly createdAt: string;
172
186
  readonly supersededBy: string | null;
173
187
  readonly confidence: number;
188
+ /**
189
+ * When set, the fact was retired (hard-removed from active recall). Populated
190
+ * by store reads; absent on bulk constructions. Recall's in-memory filter
191
+ * excludes any fact carrying this so retired facts can never leak through the
192
+ * semantic-neighbour path (where the SQL pre-filter does not apply).
193
+ */
194
+ readonly retiredAt?: string | null;
174
195
  }
175
196
  export type FactMatchField = "value" | "subject" | "predicate" | "semantic";
176
197
  export interface FactRecallQuery {
@@ -209,7 +230,7 @@ export interface FactRecallResult {
209
230
  }
210
231
  /**
211
232
  * A current high-confidence fact attached to a recall result — the hook
212
- * uses these to inject structured context ("polysignal uses: duckdb")
233
+ * uses these to inject structured context ("beacon uses: duckdb")
213
234
  * alongside the session pointer list. Selected by `pickRelatedFacts`
214
235
  * server-side using the entities of the top recall hits, the fact-store
215
236
  * confidence filter, and the spec G.1 corroborationCount.
@@ -0,0 +1,94 @@
1
+ # Classifier Gold Fixtures
2
+
3
+ A hand-authored evaluation set for the NLM session classifier. These fixtures
4
+ are part of the shipped product; they run as part of the deterministic fixture
5
+ eval in CI and are public.
6
+
7
+ ## What is in this set
8
+
9
+ 20 synthetic agent-session transcripts covering the range of sessions the
10
+ classifier encounters in practice:
11
+
12
+ | Category | IDs | Count |
13
+ |---|---|---|
14
+ | Coding: bug fix | 01, 02, 03 | 3 |
15
+ | Coding: feature | 04, 05, 06 | 3 |
16
+ | Coding: refactor | 07, 08 | 2 |
17
+ | Ops / infra | 09, 10, 11, 12 | 4 |
18
+ | Research / writing | 13, 14, 15 | 3 |
19
+ | Meeting notes | 16 | 1 |
20
+ | Low-signal / trivial | 17, 18, 19, 20 | 4 |
21
+
22
+ Low-signal sessions (17-20) contain no project context, no decisions, and no
23
+ meaningful entities. The classifier prompt instructs models to use confidence
24
+ <= 0.4 for routine/trivial sessions. The fixture eval asserts this calibration
25
+ in both directions (low-signal sessions must score <= 0.4; substantive sessions
26
+ must score > 0.4).
27
+
28
+ ## Authorship rules
29
+
30
+ All content is fully synthetic. No real projects, people, companies, or
31
+ infrastructure appear anywhere in the transcripts or references. Invented
32
+ names follow the pattern: single lowercase word (corvid-api, taskvine, lumens,
33
+ pulsearch, irongate, gridhost, droneflow, bridgeauth, flarepath, vaultdb,
34
+ axiom-worker, crestapi, orbitflow, cobalt-api). Domains are example.com.
35
+ Paths are /opt/... or /home/dev/... style.
36
+
37
+ No em dashes appear in any file in this directory. This is a hard rule for
38
+ all text in this repository, fixtures included.
39
+
40
+ ## reference.json schema
41
+
42
+ ```json
43
+ [
44
+ {
45
+ "id": "<transcript filename without .txt>",
46
+ "label": "Expected label string (4-10 words)",
47
+ "labelAlternates": ["alternate phrasings that also count as correct"],
48
+ "entities": ["exact named things the classifier must surface"],
49
+ "decisions": ["key phrase that must appear in a matched extracted decision"],
50
+ "expectLowConfidence": false
51
+ }
52
+ ]
53
+ ```
54
+
55
+ Field notes:
56
+
57
+ - `entities`: only unambiguous named things (project names, specific
58
+ technologies, specific error types). Do not include generic nouns. An entity
59
+ is matched if the reference string appears (case-insensitive) as a substring
60
+ in any extracted entity, or vice versa.
61
+ - `decisions`: concrete enough to match by key-phrase overlap. The scorer
62
+ checks whether a reference decision's key tokens appear in at least one
63
+ extracted decision. Author reference decisions around the unique commitment
64
+ (e.g. "SELECT FOR UPDATE SKIP LOCKED") rather than generic phrasing.
65
+ - `expectLowConfidence`: true for sessions 17-20. The classifier must return
66
+ confidence <= 0.4 for these or the calibration check fails.
67
+
68
+ ## Frozen prompt dependency
69
+
70
+ The reference values are authored against the classifier prompt in:
71
+
72
+ src/core/classifier/prompt.ts (CLASSIFIER_SYSTEM_PROMPT)
73
+
74
+ Specifically:
75
+ - The label style guidance ("4-10 word string title")
76
+ - The closed PREDICATE_VOCABULARY (for any expected facts, though facts are
77
+ not included in this fixture set's reference shape)
78
+ - The confidence instruction ("Use 0.4 or below for routine/trivial sessions")
79
+
80
+ If CLASSIFIER_SYSTEM_PROMPT changes materially, review all reference.json
81
+ entries and update expectLowConfidence thresholds if the confidence instruction
82
+ changes.
83
+
84
+ ## How to add a fixture
85
+
86
+ 1. Write a .txt transcript in transcripts/. File name: NN-category-short-slug.txt.
87
+ Keep it 1-6K characters. Use only invented names. No em dashes.
88
+ 2. Add an entry to reference.json. Choose entities and decisions that are
89
+ unambiguous: a competent extraction must find them; borderline cases must
90
+ not be included.
91
+ 3. Run the fixture eval to confirm your reference scores as expected:
92
+ `npx tsx scripts/eval/classifier-eval.ts --fixtures tests/fixtures/classifier-gold`
93
+ 4. Increment the fixture count comment at the top of
94
+ src/core/eval/classifier-fixture-eval.ts if it exists.