@jungjaehoon/mama-core 2.4.1 → 4.1.0

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 (378) hide show
  1. package/README.md +76 -239
  2. package/db/migrations/030-case-first-memory-substrate.sql +13 -98
  3. package/db/migrations/034-add-connector-event-scope-columns.sql +9 -13
  4. package/db/migrations/039-add-connector-event-operator-ingest-seq.sql +9 -95
  5. package/db/migrations/062-refresh-connector-event-sequences.sql +9 -113
  6. package/db/migrations/063-refresh-legacy-connector-event-updates.sql +9 -32
  7. package/db/migrations/067-add-connector-event-source-entity-id.sql +9 -13
  8. package/db/migrations/069-create-registry-nodes.sql +52 -0
  9. package/db/migrations/070-record-identity.sql +35 -0
  10. package/db/migrations/071-service-operation-origins.sql +187 -0
  11. package/db/migrations/072-observation-versions.sql +29 -0
  12. package/db/migrations/073-registry-corrections.sql +45 -0
  13. package/db/migrations/074-work-graph-ref-kinds.sql +39 -0
  14. package/db/migrations/075-agent-judgments.sql +58 -0
  15. package/db/migrations/076-scoped-checkpoint-bindings.sql +15 -0
  16. package/db/migrations/077-legacy-record-kind.sql +6 -0
  17. package/db/migrations/078-source-ingest-commands.sql +18 -0
  18. package/db/migrations/079-twin-edge-relations.sql +43 -0
  19. package/db/migrations/080-restore-duration-days.sql +7 -0
  20. package/db/migrations/081-mailbox.sql +61 -0
  21. package/db/migrations/082-commitments-row-id.sql +12 -0
  22. package/db/migrations/083-observation-is-the-evidence.sql +49 -0
  23. package/db/migrations/084-scope-kind-is-not-the-cores-to-list.sql +34 -0
  24. package/db/migrations/085-a-migration-has-a-source.sql +37 -0
  25. package/db/migrations/086-the-mailbox-is-generic.sql +110 -0
  26. package/db/migrations/087-mailbox-payload.sql +5 -0
  27. package/db/migrations/088-native-input-journal.sql +14 -0
  28. package/db/migrations/089-native-turn-receipt-lookup.sql +3 -0
  29. package/db/migrations/090-model-run-native-inputs.sql +29 -0
  30. package/db/migrations/091-native-turn-results.sql +11 -0
  31. package/db/migrations/092-restore-decision-fts.sql +34 -0
  32. package/db/migrations/093-native-turn-primary-kind.sql +14 -0
  33. package/db/migrations/094-commitment-run-provenance.sql +9 -0
  34. package/db/migrations/095-model-run-native-input-identity.sql +39 -0
  35. package/db/migrations/096-drop-connector-event-index-fts.sql +9 -0
  36. package/db/migrations/097-native-input-json-validity.sql +37 -0
  37. package/db/migrations/098-workflow-memory-kind.sql +105 -0
  38. package/db/migrations/099-commitment-revision-graph.sql +2 -0
  39. package/dist/action-contracts.d.ts +212 -0
  40. package/dist/action-contracts.js +10 -0
  41. package/dist/api/catalog.d.ts +118 -0
  42. package/dist/api/catalog.js +1756 -0
  43. package/dist/api/dispatch.d.ts +76 -0
  44. package/dist/api/dispatch.js +372 -0
  45. package/dist/canonicalize.d.ts +2 -2
  46. package/dist/canonicalize.js +3 -3
  47. package/dist/client/client.d.ts +33 -0
  48. package/dist/client/client.js +123 -0
  49. package/dist/client/ipc.d.ts +81 -0
  50. package/dist/client/ipc.js +314 -0
  51. package/dist/db-adapter/base-adapter.d.ts +6 -66
  52. package/dist/db-adapter/base-adapter.js +6 -6
  53. package/dist/db-adapter/index.d.ts +5 -5
  54. package/dist/db-adapter/index.js +2 -5
  55. package/dist/db-adapter/node-sqlite-adapter.d.ts +85 -15
  56. package/dist/db-adapter/node-sqlite-adapter.js +1985 -570
  57. package/dist/db-manager.d.ts +53 -97
  58. package/dist/db-manager.js +121 -603
  59. package/dist/embedding/embedder.d.ts +132 -0
  60. package/dist/embedding/embedder.js +299 -0
  61. package/dist/identity/principal-repository.d.ts +2 -2
  62. package/dist/index.d.ts +43 -58
  63. package/dist/index.js +97 -145
  64. package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
  65. package/dist/knowledge/access.js +663 -0
  66. package/dist/knowledge/case-errors.d.ts +31 -0
  67. package/dist/knowledge/case-errors.js +40 -0
  68. package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
  69. package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
  70. package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
  71. package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
  72. package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
  73. package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
  74. package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
  75. package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
  76. package/dist/knowledge/commitment-revision-migration.d.ts +4 -0
  77. package/dist/knowledge/commitment-revision-migration.js +50 -0
  78. package/dist/knowledge/commitments.d.ts +192 -0
  79. package/dist/knowledge/commitments.js +386 -0
  80. package/dist/knowledge/decision-edges.d.ts +70 -0
  81. package/dist/knowledge/decision-edges.js +123 -0
  82. package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
  83. package/dist/knowledge/graph-query.js +1585 -0
  84. package/dist/knowledge/identity.d.ts +16 -0
  85. package/dist/knowledge/identity.js +22 -0
  86. package/dist/knowledge/index.d.ts +47 -0
  87. package/dist/knowledge/index.js +90 -0
  88. package/dist/knowledge/judgment-edge.d.ts +6 -0
  89. package/dist/knowledge/judgment-edge.js +22 -0
  90. package/dist/knowledge/judgments.d.ts +118 -0
  91. package/dist/knowledge/judgments.js +802 -0
  92. package/dist/knowledge/observations.d.ts +160 -0
  93. package/dist/knowledge/observations.js +449 -0
  94. package/dist/knowledge/question-type.d.ts +34 -0
  95. package/dist/knowledge/question-type.js +70 -0
  96. package/dist/{search → knowledge}/ranker-features.js +1 -1
  97. package/dist/{search → knowledge}/search-quality.d.ts +0 -1
  98. package/dist/knowledge/search.d.ts +38 -0
  99. package/dist/knowledge/search.js +91 -0
  100. package/dist/knowledge/source-ingest.d.ts +65 -0
  101. package/dist/knowledge/source-ingest.js +174 -0
  102. package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
  103. package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
  104. package/dist/knowledge/work-dates.d.ts +49 -0
  105. package/dist/knowledge/work-dates.js +120 -0
  106. package/dist/mama-api.d.ts +114 -778
  107. package/dist/mama-api.js +313 -2461
  108. package/dist/memory/api.d.ts +264 -24
  109. package/dist/memory/api.js +1633 -843
  110. package/dist/memory/bootstrap-builder.d.ts +2 -1
  111. package/dist/memory/bootstrap-builder.js +5 -5
  112. package/dist/memory/channel-summary-state-store.d.ts +3 -2
  113. package/dist/memory/channel-summary-state-store.js +53 -51
  114. package/dist/memory/channel-summary-store.d.ts +5 -3
  115. package/dist/memory/channel-summary-store.js +3 -8
  116. package/dist/memory/dashboard-read.d.ts +46 -0
  117. package/dist/memory/dashboard-read.js +94 -0
  118. package/dist/memory/event-store.d.ts +3 -3
  119. package/dist/memory/event-store.js +3 -10
  120. package/dist/memory/finding-store.d.ts +3 -2
  121. package/dist/memory/finding-store.js +2 -7
  122. package/dist/memory/graph-read.d.ts +52 -0
  123. package/dist/memory/graph-read.js +130 -0
  124. package/dist/memory/judgment-types.d.ts +394 -0
  125. package/dist/memory/judgment-types.js +16 -0
  126. package/dist/memory/provenance-audit.d.ts +5 -2
  127. package/dist/memory/provenance-audit.js +8 -14
  128. package/dist/memory/provenance-live.d.ts +141 -0
  129. package/dist/memory/provenance-live.js +409 -0
  130. package/dist/memory/provenance-query.d.ts +5 -4
  131. package/dist/memory/provenance-query.js +21 -29
  132. package/dist/memory/provenance-resolver.d.ts +191 -0
  133. package/dist/memory/provenance-resolver.js +155 -0
  134. package/dist/memory/provenance.d.ts +1 -11
  135. package/dist/memory/provenance.js +2 -33
  136. package/dist/memory/recall-sanitize.d.ts +55 -0
  137. package/dist/memory/recall-sanitize.js +144 -0
  138. package/dist/memory/secret-filter.d.ts +32 -0
  139. package/dist/memory/secret-filter.js +126 -0
  140. package/dist/memory/truth-store.d.ts +2 -1
  141. package/dist/memory/truth-store.js +1 -4
  142. package/dist/memory/types.d.ts +74 -24
  143. package/dist/memory/types.js +75 -5
  144. package/dist/memory/write-adapters.d.ts +98 -0
  145. package/dist/memory/write-adapters.js +242 -0
  146. package/dist/operations/owner-action-effects.d.ts +53 -0
  147. package/dist/operations/owner-action-effects.js +96 -0
  148. package/dist/provenance/source-ref.d.ts +1 -1
  149. package/dist/provenance/source-ref.js +0 -2
  150. package/dist/registry/corrections.d.ts +31 -0
  151. package/dist/registry/corrections.js +332 -0
  152. package/dist/registry/record-identity.d.ts +49 -0
  153. package/dist/registry/record-identity.js +133 -0
  154. package/dist/registry/store.d.ts +101 -0
  155. package/dist/registry/store.js +395 -0
  156. package/dist/registry/types.d.ts +28 -0
  157. package/dist/registry/types.js +5 -0
  158. package/dist/relevance-scorer.js +2 -2
  159. package/dist/runtime/agent-event-bus.d.ts +50 -0
  160. package/dist/runtime/agent-event-bus.js +101 -0
  161. package/dist/runtime/drivers/claude-cli-wrapper.d.ts +152 -0
  162. package/dist/runtime/drivers/claude-cli-wrapper.js +375 -0
  163. package/dist/runtime/drivers/claude-effort.d.ts +4 -0
  164. package/dist/runtime/drivers/claude-effort.js +16 -0
  165. package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
  166. package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
  167. package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
  168. package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
  169. package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
  170. package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
  171. package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
  172. package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
  173. package/dist/runtime/drivers/codex-home.d.ts +20 -0
  174. package/dist/runtime/drivers/codex-home.js +674 -0
  175. package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
  176. package/dist/runtime/drivers/codex-thread-registry.js +433 -0
  177. package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
  178. package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
  179. package/dist/runtime/drivers/persistent-cli-process.d.ts +425 -0
  180. package/dist/runtime/drivers/persistent-cli-process.js +1529 -0
  181. package/dist/runtime/drivers/types.d.ts +456 -0
  182. package/dist/runtime/drivers/types.js +110 -0
  183. package/dist/runtime/mailbox.d.ts +223 -0
  184. package/dist/runtime/mailbox.js +582 -0
  185. package/dist/runtime/model-run-store.d.ts +28 -0
  186. package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
  187. package/dist/{model-runs/types.d.ts → runtime/model-run-types.d.ts} +33 -4
  188. package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
  189. package/dist/runtime/native-effect-observer.d.ts +22 -0
  190. package/dist/runtime/native-effect-observer.js +103 -0
  191. package/dist/runtime/native-input-journal.d.ts +46 -0
  192. package/dist/runtime/native-input-journal.js +308 -0
  193. package/dist/runtime/native-prompt.d.ts +118 -0
  194. package/dist/runtime/native-prompt.js +496 -0
  195. package/dist/runtime/native-session.d.ts +10 -0
  196. package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
  197. package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
  198. package/dist/runtime/native-tool-trace-observer.js +65 -0
  199. package/dist/runtime/native-turn.d.ts +272 -0
  200. package/dist/runtime/native-turn.js +1041 -0
  201. package/dist/runtime/operations.d.ts +236 -0
  202. package/dist/runtime/operations.js +565 -0
  203. package/dist/runtime/post-tool-handler.d.ts +74 -0
  204. package/dist/runtime/post-tool-handler.js +137 -0
  205. package/dist/runtime/prompt-layers.d.ts +126 -0
  206. package/dist/runtime/prompt-layers.js +239 -0
  207. package/dist/runtime/runtime-process.d.ts +102 -0
  208. package/dist/runtime/runtime-process.js +206 -0
  209. package/dist/runtime/runtime.d.ts +278 -0
  210. package/dist/runtime/runtime.js +563 -0
  211. package/dist/runtime/session-pool.d.ts +176 -0
  212. package/dist/runtime/session-pool.js +369 -0
  213. package/dist/runtime/stimulus-payload.d.ts +5 -0
  214. package/dist/runtime/stimulus-payload.js +50 -0
  215. package/dist/runtime/subagent-bridge.d.ts +24 -0
  216. package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
  217. package/dist/runtime/text-completion.d.ts +22 -0
  218. package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
  219. package/dist/runtime/token-estimator.d.ts +25 -0
  220. package/dist/runtime/token-estimator.js +75 -0
  221. package/dist/runtime/tool-trace-store.d.ts +22 -0
  222. package/dist/{model-runs → runtime}/tool-trace-store.js +46 -27
  223. package/dist/runtime/trace-summary.d.ts +5 -0
  224. package/dist/runtime/trace-summary.js +74 -0
  225. package/dist/runtime/turn-text.d.ts +23 -0
  226. package/dist/runtime/turn-text.js +41 -0
  227. package/dist/storage/database.d.ts +67 -0
  228. package/dist/storage/database.js +158 -0
  229. package/package.json +20 -34
  230. package/dist/agent-graph/alias-write.d.ts +0 -3
  231. package/dist/agent-graph/alias-write.js +0 -234
  232. package/dist/agent-graph/entity-resolve.d.ts +0 -3
  233. package/dist/agent-graph/entity-resolve.js +0 -271
  234. package/dist/agent-graph/errors.d.ts +0 -4
  235. package/dist/agent-graph/errors.js +0 -11
  236. package/dist/agent-graph/graph-query.d.ts +0 -5
  237. package/dist/agent-graph/graph-query.js +0 -360
  238. package/dist/agent-graph/index.d.ts +0 -6
  239. package/dist/agent-situation/builder.d.ts +0 -8
  240. package/dist/agent-situation/builder.js +0 -239
  241. package/dist/agent-situation/cache-key.d.ts +0 -4
  242. package/dist/agent-situation/cache-key.js +0 -64
  243. package/dist/agent-situation/index.d.ts +0 -7
  244. package/dist/agent-situation/index.js +0 -28
  245. package/dist/agent-situation/packet-store.d.ts +0 -27
  246. package/dist/agent-situation/packet-store.js +0 -228
  247. package/dist/agent-situation/ranking-policy.d.ts +0 -18
  248. package/dist/agent-situation/ranking-policy.js +0 -75
  249. package/dist/agent-situation/source-readers.d.ts +0 -52
  250. package/dist/agent-situation/source-readers.js +0 -300
  251. package/dist/agent-situation/types.d.ts +0 -195
  252. package/dist/cases/wiki-page-index.d.ts +0 -37
  253. package/dist/cases/wiki-page-index.js +0 -201
  254. package/dist/config-loader.d.ts +0 -68
  255. package/dist/config-loader.js +0 -239
  256. package/dist/connectors/event-index.d.ts +0 -24
  257. package/dist/connectors/event-index.js +0 -245
  258. package/dist/connectors/raw-query.d.ts +0 -40
  259. package/dist/connectors/raw-query.js +0 -412
  260. package/dist/connectors/types.d.ts +0 -117
  261. package/dist/connectors/types.js +0 -3
  262. package/dist/context-compile/boundary-defaults.d.ts +0 -12
  263. package/dist/context-compile/boundary-defaults.js +0 -105
  264. package/dist/context-compile/channel-grant.js +0 -66
  265. package/dist/context-compile/compiler-policy.d.ts +0 -39
  266. package/dist/context-compile/compiler-policy.js +0 -147
  267. package/dist/context-compile/compiler.d.ts +0 -18
  268. package/dist/context-compile/compiler.js +0 -404
  269. package/dist/context-compile/index.d.ts +0 -10
  270. package/dist/context-compile/index.js +0 -26
  271. package/dist/context-compile/packet-store.d.ts +0 -8
  272. package/dist/context-compile/packet-store.js +0 -239
  273. package/dist/context-compile/ref.d.ts +0 -7
  274. package/dist/context-compile/ref.js +0 -102
  275. package/dist/context-compile/source-readers.d.ts +0 -70
  276. package/dist/context-compile/source-readers.js +0 -840
  277. package/dist/context-compile/types.d.ts +0 -155
  278. package/dist/context-compile/types.js +0 -11
  279. package/dist/context-compile/visibility.d.ts +0 -21
  280. package/dist/context-compile/visibility.js +0 -224
  281. package/dist/decision-tracker.d.ts +0 -206
  282. package/dist/decision-tracker.js +0 -481
  283. package/dist/edges/ref-validation.d.ts +0 -7
  284. package/dist/edges/ref-validation.js +0 -321
  285. package/dist/edges/store.d.ts +0 -8
  286. package/dist/edges/store.js +0 -129
  287. package/dist/embedding-client.d.ts +0 -28
  288. package/dist/embedding-client.js +0 -53
  289. package/dist/embedding-server/index.d.ts +0 -67
  290. package/dist/embedding-server/index.js +0 -405
  291. package/dist/embedding-server/mobile/auth.d.ts +0 -44
  292. package/dist/embedding-server/mobile/auth.js +0 -150
  293. package/dist/embedding-server/mobile/daemon.d.ts +0 -129
  294. package/dist/embedding-server/mobile/daemon.js +0 -313
  295. package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
  296. package/dist/embedding-server/mobile/output-parser.js +0 -241
  297. package/dist/embedding-server/mobile/session-api.d.ts +0 -57
  298. package/dist/embedding-server/mobile/session-api.js +0 -261
  299. package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
  300. package/dist/embedding-server/mobile/session-manager.js +0 -378
  301. package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
  302. package/dist/embedding-server/mobile/websocket-handler.js +0 -486
  303. package/dist/embeddings.d.ts +0 -68
  304. package/dist/embeddings.js +0 -244
  305. package/dist/entities/audit-metrics.d.ts +0 -68
  306. package/dist/entities/audit-metrics.js +0 -124
  307. package/dist/entities/candidate-generator.d.ts +0 -8
  308. package/dist/entities/candidate-generator.js +0 -24
  309. package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
  310. package/dist/entities/entity-linked-decision-counts.js +0 -29
  311. package/dist/entities/entity-list.d.ts +0 -22
  312. package/dist/entities/entity-list.js +0 -3
  313. package/dist/entities/entity-orphan-list.d.ts +0 -17
  314. package/dist/entities/entity-orphan-list.js +0 -3
  315. package/dist/entities/entity-search.d.ts +0 -20
  316. package/dist/entities/entity-search.js +0 -3
  317. package/dist/entities/errors.d.ts +0 -55
  318. package/dist/entities/errors.js +0 -100
  319. package/dist/entities/lineage-store.d.ts +0 -28
  320. package/dist/entities/lineage-store.js +0 -204
  321. package/dist/entities/normalization.d.ts +0 -14
  322. package/dist/entities/normalization.js +0 -63
  323. package/dist/entities/policy-store.d.ts +0 -8
  324. package/dist/entities/policy-store.js +0 -75
  325. package/dist/entities/policy-types.d.ts +0 -72
  326. package/dist/entities/policy-types.js +0 -59
  327. package/dist/entities/projection.d.ts +0 -8
  328. package/dist/entities/projection.js +0 -82
  329. package/dist/entities/provenance-query.d.ts +0 -32
  330. package/dist/entities/provenance-query.js +0 -3
  331. package/dist/entities/read-identity.d.ts +0 -31
  332. package/dist/entities/read-identity.js +0 -264
  333. package/dist/entities/recall-bridge.d.ts +0 -5
  334. package/dist/entities/recall-bridge.js +0 -171
  335. package/dist/entities/resolution-engine.d.ts +0 -8
  336. package/dist/entities/resolution-engine.js +0 -3
  337. package/dist/entities/rollback-preview.d.ts +0 -35
  338. package/dist/entities/rollback-preview.js +0 -3
  339. package/dist/entities/source-locator.d.ts +0 -3
  340. package/dist/entities/source-locator.js +0 -32
  341. package/dist/entities/store.d.ts +0 -69
  342. package/dist/entities/store.js +0 -544
  343. package/dist/entities/types.d.ts +0 -166
  344. package/dist/entities/types.js +0 -30
  345. package/dist/memory/extraction-prompt.d.ts +0 -4
  346. package/dist/memory/extraction-prompt.js +0 -89
  347. package/dist/memory/scope-backfill.d.ts +0 -14
  348. package/dist/memory/scope-backfill.js +0 -3
  349. package/dist/memory/scope-store.d.ts +0 -4
  350. package/dist/memory/scope-store.js +0 -9
  351. package/dist/memory-store.d.ts +0 -87
  352. package/dist/memory-store.js +0 -78
  353. package/dist/model-runs/store.d.ts +0 -13
  354. package/dist/model-runs/tool-trace-store.d.ts +0 -8
  355. package/dist/notification-manager.d.ts +0 -7
  356. package/dist/notification-manager.js +0 -12
  357. package/dist/outcome-tracker.d.ts +0 -151
  358. package/dist/outcome-tracker.js +0 -271
  359. package/dist/query-intent.d.ts +0 -23
  360. package/dist/query-intent.js +0 -114
  361. package/dist/runtime/trusted-provenance.d.ts +0 -3
  362. package/dist/runtime/trusted-provenance.js +0 -6
  363. package/dist/search/question-type.d.ts +0 -5
  364. package/dist/search/question-type.js +0 -41
  365. package/dist/test-utils.d.ts +0 -80
  366. package/dist/test-utils.js +0 -218
  367. package/dist/tier-validator.d.ts +0 -43
  368. package/dist/tier-validator.js +0 -159
  369. package/dist/time-formatter.d.ts +0 -25
  370. package/dist/time-formatter.js +0 -93
  371. /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
  372. /package/dist/{search → knowledge}/feedback-store.js +0 -0
  373. /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
  374. /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
  375. /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
  376. /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
  377. /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
  378. /package/dist/{search → knowledge}/search-quality.js +0 -0
@@ -1,840 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sourceRefsFromCandidates = sourceRefsFromCandidates;
4
- exports.readMemoryCandidates = readMemoryCandidates;
5
- exports.readRawCandidates = readRawCandidates;
6
- exports.setContextSourceClockForTests = setContextSourceClockForTests;
7
- exports.readGraphCandidates = readGraphCandidates;
8
- const ref_validation_js_1 = require("../edges/ref-validation.js");
9
- const api_js_1 = require("../memory/api.js");
10
- const ref_js_1 = require("./ref.js");
11
- const visibility_js_1 = require("./visibility.js");
12
- const boundary_defaults_js_1 = require("./boundary-defaults.js");
13
- const channel_grant_js_1 = require("./channel-grant.js");
14
- function hiddenAggregate() {
15
- return { total: 0, by_kind: {}, by_reason: {} };
16
- }
17
- function incrementHidden(aggregate, ref, reason) {
18
- aggregate.total += 1;
19
- aggregate.by_kind[ref.kind] = (aggregate.by_kind[ref.kind] ?? 0) + 1;
20
- aggregate.by_reason[reason] = (aggregate.by_reason[reason] ?? 0) + 1;
21
- }
22
- function tableExists(adapter, table) {
23
- const row = adapter
24
- .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?")
25
- .get(table);
26
- return Boolean(row?.name);
27
- }
28
- function placeholders(values) {
29
- return values.map(() => '?').join(', ');
30
- }
31
- function normalizeLimit(limit) {
32
- return Math.max(0, Math.min(100, Math.floor(limit ?? 10)));
33
- }
34
- function parseTimestampMs(value) {
35
- if (typeof value === 'number' && Number.isFinite(value)) {
36
- return Math.floor(value);
37
- }
38
- if (typeof value !== 'string' || value.trim().length === 0) {
39
- return null;
40
- }
41
- const numeric = Number(value);
42
- if (Number.isFinite(numeric)) {
43
- return Math.floor(numeric);
44
- }
45
- const parsed = Date.parse(value);
46
- return Number.isFinite(parsed) ? parsed : null;
47
- }
48
- function asOfMs(input) {
49
- if (input.as_of === null || input.as_of === undefined) {
50
- return null;
51
- }
52
- const parsed = parseTimestampMs(input.as_of);
53
- if (parsed === null) {
54
- throw new Error(`Invalid context source as_of: ${String(input.as_of)}`);
55
- }
56
- return parsed;
57
- }
58
- function timeFilterRequired(input) {
59
- return Boolean(input.range?.start_ms !== undefined ||
60
- input.range?.end_ms !== undefined ||
61
- (input.as_of !== undefined && input.as_of !== null));
62
- }
63
- function rangeBoundaryMs(value, field) {
64
- if (value === undefined) {
65
- return null;
66
- }
67
- if (typeof value === 'number' && Number.isFinite(value)) {
68
- return Math.floor(value);
69
- }
70
- throw new Error(`Invalid context source ${field}: ${String(value)}`);
71
- }
72
- function normalizeContextSourceRange(range) {
73
- if (!range) {
74
- return undefined;
75
- }
76
- const startMs = rangeBoundaryMs(range.start_ms, 'range.start_ms');
77
- const endMs = rangeBoundaryMs(range.end_ms, 'range.end_ms');
78
- if (startMs !== null && endMs !== null && startMs > endMs) {
79
- throw new RangeError(`Invalid context source range: start_ms ${startMs} > end_ms ${endMs}`);
80
- }
81
- if (startMs === null && endMs === null) {
82
- return undefined;
83
- }
84
- return {
85
- ...(startMs !== null ? { start_ms: startMs } : {}),
86
- ...(endMs !== null ? { end_ms: endMs } : {}),
87
- };
88
- }
89
- function normalizeContextSourceAsOf(asOf) {
90
- if (asOf === null || asOf === undefined) {
91
- return asOf;
92
- }
93
- const parsed = parseTimestampMs(asOf);
94
- if (parsed === null) {
95
- throw new Error(`Invalid context source as_of: ${String(asOf)}`);
96
- }
97
- return parsed;
98
- }
99
- function normalizeTimeFilters(input) {
100
- return {
101
- ...input,
102
- range: normalizeContextSourceRange(input.range),
103
- as_of: normalizeContextSourceAsOf(input.as_of),
104
- };
105
- }
106
- function maxVisibleTimeMs(input) {
107
- const ends = [rangeBoundaryMs(input.range?.end_ms, 'range.end_ms'), asOfMs(input)].filter((value) => typeof value === 'number' && Number.isFinite(value));
108
- return ends.length > 0 ? Math.min(...ends) : null;
109
- }
110
- function minVisibleTimeMs(input) {
111
- return rangeBoundaryMs(input.range?.start_ms, 'range.start_ms');
112
- }
113
- function isWithinTimeBoundary(timestampMs, input) {
114
- const min = minVisibleTimeMs(input);
115
- const max = maxVisibleTimeMs(input);
116
- return (min === null || timestampMs >= min) && (max === null || timestampMs <= max);
117
- }
118
- function hasExplicitEmptyProjectWindow(input) {
119
- return (Array.isArray(input.project_refs) &&
120
- input.project_refs.length === 0 &&
121
- (input.boundary?.project_refs?.length ?? 0) > 0);
122
- }
123
- function applyBoundaryDefaults(input) {
124
- return (0, boundary_defaults_js_1.applyContextBoundaryReadDefaults)(input, input.boundary);
125
- }
126
- function memoryTimestampMs(memory) {
127
- return (parseTimestampMs(memory.event_datetime) ??
128
- parseTimestampMs(memory.updated_at) ??
129
- parseTimestampMs(memory.created_at));
130
- }
131
- function diagnosticsFromUnknown(value) {
132
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
133
- return undefined;
134
- }
135
- const record = value;
136
- if (typeof record.retrieval_source !== 'string') {
137
- return undefined;
138
- }
139
- return {
140
- retrieval_source: record.retrieval_source,
141
- vector_similarity: typeof record.vector_similarity === 'number' ? record.vector_similarity : null,
142
- lexical_support: record.lexical_support === true,
143
- entity_support: record.entity_support === true,
144
- scope_support: record.scope_support === true,
145
- graph_source: record.graph_source === 'primary' || record.graph_source === 'expanded'
146
- ? record.graph_source
147
- : null,
148
- is_vector_only: record.is_vector_only === true,
149
- confirmation_signals: Array.isArray(record.confirmation_signals)
150
- ? record.confirmation_signals.filter((signal) => typeof signal === 'string')
151
- : [],
152
- metadata_signals: Array.isArray(record.metadata_signals)
153
- ? record.metadata_signals.filter((signal) => typeof signal === 'string')
154
- : [],
155
- candidate_threshold_used: typeof record.candidate_threshold_used === 'number' ? record.candidate_threshold_used : 0,
156
- };
157
- }
158
- function supportFromDiagnostics(diagnostics) {
159
- return {
160
- retrieval_source: diagnostics?.retrieval_source,
161
- lexical_support: diagnostics?.lexical_support,
162
- entity_support: diagnostics?.entity_support,
163
- scope_support: diagnostics?.scope_support,
164
- graph_source: diagnostics?.graph_source,
165
- graph_expanded: diagnostics?.graph_source === 'expanded',
166
- is_vector_only: diagnostics?.is_vector_only,
167
- vector_similarity: diagnostics?.vector_similarity,
168
- confirmation_signals: diagnostics?.confirmation_signals ?? [],
169
- metadata_signals: diagnostics?.metadata_signals ?? [],
170
- };
171
- }
172
- function emptySupport(retrievalSource) {
173
- return {
174
- retrieval_source: retrievalSource,
175
- confirmation_signals: [],
176
- metadata_signals: [],
177
- };
178
- }
179
- const EXCLUDED_MEMORY_STATUSES = new Set(['superseded', 'quarantined', 'contradicted', 'stale']);
180
- function loadScopesForMemoryIds(adapter, memoryIds) {
181
- const scopeMap = new Map();
182
- if (memoryIds.length === 0 || !tableExists(adapter, 'memory_scope_bindings')) {
183
- return scopeMap;
184
- }
185
- const rows = adapter
186
- .prepare(`
187
- SELECT msb.memory_id, ms.kind, ms.external_id
188
- FROM memory_scope_bindings msb
189
- JOIN memory_scopes ms ON ms.id = msb.scope_id
190
- WHERE msb.memory_id IN (${placeholders(memoryIds)})
191
- ORDER BY msb.is_primary DESC
192
- `)
193
- .all(...memoryIds);
194
- for (const row of rows) {
195
- const existing = scopeMap.get(row.memory_id) ?? [];
196
- existing.push({ kind: row.kind, id: row.external_id });
197
- scopeMap.set(row.memory_id, existing);
198
- }
199
- return scopeMap;
200
- }
201
- function sourceFromTrustContext(value) {
202
- if (typeof value === 'string') {
203
- try {
204
- const parsed = JSON.parse(value);
205
- if (parsed.source) {
206
- return parsed.source;
207
- }
208
- }
209
- catch {
210
- // malformed trust_context falls back to local adapter source
211
- }
212
- }
213
- return { package: 'mama-core', source_type: 'context_compile_adapter' };
214
- }
215
- function memoryRecordFromRow(row, scopes) {
216
- return {
217
- id: String(row.id),
218
- topic: String(row.topic ?? ''),
219
- kind: (row.kind ?? 'decision'),
220
- summary: String(row.summary ?? row.decision ?? ''),
221
- details: String(row.reasoning ?? row.decision ?? ''),
222
- confidence: typeof row.confidence === 'number' ? row.confidence : 0.5,
223
- status: (typeof row.status === 'string' ? row.status : 'active'),
224
- scopes,
225
- source: sourceFromTrustContext(row.trust_context),
226
- created_at: row.created_at ?? 0,
227
- updated_at: row.updated_at ??
228
- row.created_at ??
229
- 0,
230
- event_date: typeof row.event_date === 'string' ? row.event_date : null,
231
- event_datetime: typeof row.event_datetime === 'number' && Number.isFinite(row.event_datetime)
232
- ? row.event_datetime
233
- : null,
234
- };
235
- }
236
- function memoryLexicalScore(memory, query) {
237
- const tokens = (0, api_js_1.getLexicalQueryTokens)(query);
238
- if (tokens.length === 0) {
239
- return 1;
240
- }
241
- const haystack = [memory.topic, memory.summary, memory.details].join(' ').toLowerCase();
242
- const phraseBoost = haystack.includes(query.toLowerCase()) ? 2 : 0;
243
- return tokens.reduce((score, token) => (haystack.includes(token) ? score + 1 : score), phraseBoost);
244
- }
245
- function memoryLexicalWhereClause(tokens) {
246
- if (tokens.length === 0) {
247
- return null;
248
- }
249
- const fields = [
250
- "LOWER(COALESCE(d.topic, ''))",
251
- "LOWER(COALESCE(d.summary, ''))",
252
- "LOWER(COALESCE(d.decision, ''))",
253
- "LOWER(COALESCE(d.reasoning, ''))",
254
- ];
255
- return `(${tokens
256
- .map(() => `(${fields.map((field) => `instr(${field}, ?) > 0`).join(' OR ')})`)
257
- .join(' OR ')})`;
258
- }
259
- function pushMemoryLexicalParams(params, tokens) {
260
- for (const token of tokens) {
261
- const normalized = token.toLowerCase();
262
- params.push(normalized, normalized, normalized, normalized);
263
- }
264
- }
265
- function memoryTimestampSql() {
266
- return 'COALESCE(d.event_datetime, d.updated_at, d.created_at)';
267
- }
268
- const OPERATIONAL_MEMORY_LABELS = [
269
- 'dashboard_briefing',
270
- 'dashboard-briefing',
271
- 'wiki_compilation',
272
- 'wiki-compilation',
273
- 'system-audit',
274
- 'system_audit',
275
- ];
276
- function isOperationalMemoryTopic(topic) {
277
- const normalized = topic.trim().toLowerCase();
278
- return (OPERATIONAL_MEMORY_LABELS.some((label) => normalized === label || normalized.startsWith(`${label}_`)) ||
279
- normalized.startsWith('audit_') ||
280
- normalized.startsWith('audit-'));
281
- }
282
- function taskRequestsOperationalMemory(task) {
283
- const normalized = task.toLowerCase();
284
- return (OPERATIONAL_MEMORY_LABELS.some((label) => normalized.includes(label)) ||
285
- normalized.includes('audit log') ||
286
- normalized.includes('audit-log') ||
287
- normalized.includes('raw audit'));
288
- }
289
- function adapterScopedRecallMemory(adapter, input) {
290
- if (!tableExists(adapter, 'decisions')) {
291
- throw new Error('Context compile memory reader requires a migrated memory database with a decisions table.');
292
- }
293
- const scopes = input.scopes ?? [];
294
- const params = [];
295
- const joins = [];
296
- const where = [
297
- `(d.status IS NULL OR d.status NOT IN (${[...EXCLUDED_MEMORY_STATUSES].map(() => '?').join(', ')}))`,
298
- ];
299
- const lexicalTokens = (0, api_js_1.getLexicalQueryTokens)(input.task);
300
- params.push(...EXCLUDED_MEMORY_STATUSES);
301
- if (scopes.length > 0) {
302
- const includesLegacyGlobalSystem = scopes.some((scope) => scope.kind === 'global' && scope.id === 'system');
303
- joins.push(includesLegacyGlobalSystem
304
- ? 'LEFT JOIN memory_scope_bindings msb ON msb.memory_id = d.id'
305
- : 'JOIN memory_scope_bindings msb ON msb.memory_id = d.id');
306
- joins.push(includesLegacyGlobalSystem
307
- ? 'LEFT JOIN memory_scopes ms ON ms.id = msb.scope_id'
308
- : 'JOIN memory_scopes ms ON ms.id = msb.scope_id');
309
- // Records written before the 'global'/'system' alignment shipped with id
310
- // 'global'. Match both ids when the request includes the global-system
311
- // sentinel so legacy records remain visible.
312
- const scopeClauses = [];
313
- const scopeParams = [];
314
- for (const scope of scopes) {
315
- if (scope.kind === 'global' && scope.id === 'system') {
316
- scopeClauses.push('(ms.kind = ? AND ms.external_id IN (?, ?))');
317
- scopeParams.push('global', 'system', 'global');
318
- }
319
- else {
320
- scopeClauses.push('(ms.kind = ? AND ms.external_id = ?)');
321
- scopeParams.push(scope.kind, scope.id);
322
- }
323
- }
324
- const scopeMatch = scopeClauses.join(' OR ');
325
- where.push(includesLegacyGlobalSystem
326
- ? `((${scopeMatch}) OR NOT EXISTS (SELECT 1 FROM memory_scope_bindings legacy_msb WHERE legacy_msb.memory_id = d.id))`
327
- : `(${scopeMatch})`);
328
- params.push(...scopeParams);
329
- }
330
- const lexicalWhere = memoryLexicalWhereClause(lexicalTokens);
331
- if (lexicalWhere) {
332
- where.push(lexicalWhere);
333
- pushMemoryLexicalParams(params, lexicalTokens);
334
- }
335
- const min = minVisibleTimeMs(input);
336
- const max = maxVisibleTimeMs(input);
337
- const timestampSql = memoryTimestampSql();
338
- if (min !== null) {
339
- where.push(`${timestampSql} >= ?`);
340
- params.push(min);
341
- }
342
- if (max !== null) {
343
- where.push(`${timestampSql} <= ?`);
344
- params.push(max);
345
- }
346
- const rows = adapter
347
- .prepare(`
348
- SELECT DISTINCT d.id, d.topic, d.decision, d.reasoning, d.confidence, d.created_at,
349
- d.updated_at, d.trust_context, d.kind, d.status, d.summary, d.event_date,
350
- d.event_datetime
351
- FROM decisions d
352
- ${joins.join('\n ')}
353
- WHERE ${where.join('\n AND ')}
354
- ORDER BY ${timestampSql} DESC, d.created_at DESC
355
- LIMIT ?
356
- `)
357
- .all(...params, Math.max(normalizeLimit(input.limit) * 5, normalizeLimit(input.limit)));
358
- const scopeMap = loadScopesForMemoryIds(adapter, rows.map((row) => String(row.id)));
359
- const memories = rows
360
- .map((row) => memoryRecordFromRow(row, scopeMap.get(String(row.id)) ?? []))
361
- .map((memory) => ({ memory, score: memoryLexicalScore(memory, input.task) }))
362
- .filter((candidate) => candidate.score > 0)
363
- .sort((left, right) => {
364
- if (right.score !== left.score) {
365
- return right.score - left.score;
366
- }
367
- return (memoryTimestampMs(right.memory) ?? 0) - (memoryTimestampMs(left.memory) ?? 0);
368
- })
369
- .slice(0, normalizeLimit(input.limit))
370
- .map(({ memory, score }) => ({
371
- ...memory,
372
- confidence: Math.max(memory.confidence, Math.min(0.95, 0.45 + score * 0.05)),
373
- retrieval_diagnostics: {
374
- retrieval_source: 'context_compile_adapter',
375
- vector_similarity: null,
376
- lexical_support: true,
377
- entity_support: false,
378
- scope_support: scopes.length > 0,
379
- graph_source: null,
380
- is_vector_only: false,
381
- confirmation_signals: ['lexical'],
382
- metadata_signals: ['adapter_scoped'],
383
- candidate_threshold_used: 0,
384
- },
385
- }));
386
- return {
387
- profile: { static: [], dynamic: [], evidence: [] },
388
- memories,
389
- graph_context: { primary: memories, expanded: [], edges: [] },
390
- search_meta: {
391
- query: input.task,
392
- scope_order: scopes.map((scope) => scope.kind),
393
- retrieval_sources: ['context_compile_adapter'],
394
- },
395
- };
396
- }
397
- function resultFromCandidates(candidates, hidden) {
398
- const visible = candidates.filter((candidate) => candidate.visible);
399
- for (const candidate of candidates) {
400
- if (!candidate.visible) {
401
- incrementHidden(hidden, candidate.ref, candidate.hidden_reason ?? 'hidden');
402
- }
403
- }
404
- return {
405
- candidates: visible,
406
- hidden,
407
- source_refs: sourceRefsFromCandidates(visible),
408
- };
409
- }
410
- function sourceRefsFromCandidates(candidates) {
411
- const refs = new Map();
412
- for (const candidate of candidates) {
413
- if (!candidate.visible) {
414
- continue;
415
- }
416
- refs.set((0, ref_js_1.serializeContextRefForProvenance)(candidate.ref), candidate.ref);
417
- }
418
- return [...refs.values()];
419
- }
420
- async function readMemoryCandidates(input, deps = {}) {
421
- const effectiveInput = normalizeTimeFilters(applyBoundaryDefaults(input));
422
- if (effectiveInput.boundary) {
423
- (0, visibility_js_1.assertContextBoundaryAllowsInput)({
424
- boundary: effectiveInput.boundary,
425
- requestedScopes: effectiveInput.scopes,
426
- requestedConnectors: effectiveInput.connectors,
427
- requestedProjectRefs: effectiveInput.project_refs,
428
- requestedTenantId: effectiveInput.tenant_id,
429
- });
430
- }
431
- if (Array.isArray(effectiveInput.scopes) && effectiveInput.scopes.length === 0) {
432
- return resultFromCandidates([], hiddenAggregate());
433
- }
434
- const recallOptions = {
435
- scopes: effectiveInput.scopes,
436
- limit: normalizeLimit(effectiveInput.limit),
437
- diagnostics: true,
438
- strictness: effectiveInput.strictness,
439
- threshold: effectiveInput.threshold,
440
- ...(effectiveInput.range ? { range: effectiveInput.range } : {}),
441
- ...(effectiveInput.as_of !== undefined ? { as_of: effectiveInput.as_of } : {}),
442
- };
443
- const bundle = deps.recallMemory
444
- ? await deps.recallMemory(effectiveInput.task, recallOptions)
445
- : deps.adapter
446
- ? adapterScopedRecallMemory(deps.adapter, effectiveInput)
447
- : await (0, api_js_1.recallMemory)(effectiveInput.task, recallOptions);
448
- const candidates = [];
449
- const hidden = hiddenAggregate();
450
- const requiresTime = timeFilterRequired(effectiveInput);
451
- const allowOperationalMemory = taskRequestsOperationalMemory(effectiveInput.task);
452
- for (const memory of bundle.memories) {
453
- const ref = { kind: 'memory', id: memory.id };
454
- if (!allowOperationalMemory && isOperationalMemoryTopic(memory.topic)) {
455
- candidates.push(hiddenCandidate(ref, 'memory', 'operational_summary'));
456
- continue;
457
- }
458
- const timestampMs = memoryTimestampMs(memory);
459
- if (timestampMs === null && requiresTime) {
460
- candidates.push(hiddenCandidate(ref, 'memory', 'timestamp_missing'));
461
- continue;
462
- }
463
- if (timestampMs !== null && !isWithinTimeBoundary(timestampMs, effectiveInput)) {
464
- candidates.push(hiddenCandidate(ref, 'memory', 'time_boundary'));
465
- continue;
466
- }
467
- const diagnostics = diagnosticsFromUnknown(memory.retrieval_diagnostics);
468
- candidates.push({
469
- ref,
470
- title: memory.topic || memory.summary || memory.id,
471
- excerpt: memory.summary || memory.details || '',
472
- score: typeof memory.confidence === 'number' ? memory.confidence : 0,
473
- timestamp_ms: timestampMs,
474
- source: 'memory',
475
- visible: true,
476
- support: supportFromDiagnostics(diagnostics),
477
- ...(diagnostics ? { retrieval_diagnostics: diagnostics } : {}),
478
- });
479
- }
480
- return resultFromCandidates(candidates, hidden);
481
- }
482
- function hiddenCandidate(ref, source, hiddenReason) {
483
- return {
484
- ref,
485
- title: '',
486
- excerpt: '',
487
- score: 0,
488
- timestamp_ms: null,
489
- source,
490
- visible: false,
491
- hidden_reason: hiddenReason,
492
- support: emptySupport(),
493
- };
494
- }
495
- function readRawCandidates(adapter, input) {
496
- const effectiveInput = normalizeTimeFilters(applyBoundaryDefaults(input));
497
- if (effectiveInput.boundary) {
498
- (0, visibility_js_1.assertContextBoundaryAllowsInput)({
499
- boundary: effectiveInput.boundary,
500
- requestedScopes: effectiveInput.scopes,
501
- requestedConnectors: effectiveInput.connectors,
502
- requestedProjectRefs: effectiveInput.project_refs,
503
- requestedTenantId: effectiveInput.tenant_id,
504
- });
505
- }
506
- if (!tableExists(adapter, 'connector_event_index')) {
507
- return resultFromCandidates([], hiddenAggregate());
508
- }
509
- // These guards hold on BOTH paths. An explicitly emptied project window and an empty
510
- // scope list are deliberate "read nothing" requests, and the grant branch skipping them
511
- // would have turned two fail-closed states into reads.
512
- if ((effectiveInput.connectors ?? []).length === 0 ||
513
- (effectiveInput.scopes ?? []).length === 0 ||
514
- hasExplicitEmptyProjectWindow(effectiveInput)) {
515
- return resultFromCandidates([], hiddenAggregate());
516
- }
517
- const channelGrant = effectiveInput.boundary?.channels;
518
- if (channelGrant) {
519
- return readRawCandidatesWithinGrant(adapter, effectiveInput, channelGrant);
520
- }
521
- const connectors = effectiveInput.connectors ?? [];
522
- const scopes = effectiveInput.scopes ?? [];
523
- const projectIds = (effectiveInput.project_refs ?? []).map((project) => project.id);
524
- const hasGlobalSystemScope = scopes.some((scope) => scope.kind === 'global' && scope.id === 'system');
525
- const hasScopedVisibility = scopes.some((scope) => !(scope.kind === 'global' && scope.id === 'system')) ||
526
- projectIds.length > 0 ||
527
- Boolean(effectiveInput.tenant_id);
528
- const includesLegacyGlobalSystem = hasGlobalSystemScope && !hasScopedVisibility;
529
- const clauses = [`source_connector IN (${placeholders(connectors)})`];
530
- const params = [...connectors];
531
- if (projectIds.length > 0) {
532
- const projectMatches = [`project_id IN (${placeholders(projectIds)})`];
533
- if (includesLegacyGlobalSystem) {
534
- projectMatches.push('project_id IS NULL');
535
- }
536
- clauses.push(`(${projectMatches.join(' OR ')})`);
537
- params.push(...projectIds);
538
- }
539
- if (effectiveInput.tenant_id) {
540
- clauses.push(includesLegacyGlobalSystem ? '(tenant_id = ? OR tenant_id IS NULL)' : 'tenant_id = ?');
541
- params.push(effectiveInput.tenant_id);
542
- }
543
- // Mirror the legacy global-id handling from readMemoryCandidates: rows
544
- // saved before the alignment used memory_scope_id='global'.
545
- const scopeMatches = [];
546
- const scopeParams = [];
547
- for (const scope of scopes) {
548
- if (scope.kind === 'global' && scope.id === 'system') {
549
- scopeMatches.push('(memory_scope_kind = ? AND memory_scope_id IN (?, ?))');
550
- scopeParams.push('global', 'system', 'global');
551
- }
552
- else {
553
- scopeMatches.push('(memory_scope_kind = ? AND memory_scope_id = ?)');
554
- scopeParams.push(scope.kind, scope.id);
555
- }
556
- }
557
- if (includesLegacyGlobalSystem) {
558
- scopeMatches.push('(memory_scope_kind IS NULL AND memory_scope_id IS NULL)');
559
- }
560
- clauses.push(`(${scopeMatches.join(' OR ')})`);
561
- params.push(...scopeParams);
562
- const min = minVisibleTimeMs(effectiveInput);
563
- const max = maxVisibleTimeMs(effectiveInput);
564
- if (min !== null) {
565
- clauses.push('COALESCE(event_datetime, source_timestamp_ms) >= ?');
566
- params.push(min);
567
- }
568
- if (max !== null) {
569
- clauses.push('COALESCE(event_datetime, source_timestamp_ms) <= ?');
570
- params.push(max);
571
- }
572
- params.push(normalizeLimit(effectiveInput.limit));
573
- const rows = adapter
574
- .prepare(`
575
- SELECT event_index_id, source_connector, source_id, channel, title, content,
576
- event_datetime, source_timestamp_ms
577
- FROM connector_event_index
578
- WHERE ${clauses.join('\n AND ')}
579
- ORDER BY COALESCE(event_datetime, source_timestamp_ms) DESC, event_index_id ASC
580
- LIMIT ?
581
- `)
582
- .all(...params);
583
- return resultFromCandidates(rows.map(rawRowToCandidate), hiddenAggregate());
584
- }
585
- /**
586
- * Raw visibility decided by the caller's (connector, channel) grant.
587
- *
588
- * Two conditions, both necessary: the connector is granted, and the channel is one of the
589
- * channels granted for it. Nothing else gates a row - not project, not tenant, not the
590
- * derived scope columns. See ContextBoundary.channels for why those were removed rather
591
- * than kept alongside: measured on the live index, they hide two thirds of the corpus from
592
- * any caller precise enough to name a scope, and a reader that answers narrow questions
593
- * from nothing is worse than one that answers them from the events.
594
- *
595
- * The grant is enforced in SQL rather than filtered afterwards, so `limit` counts rows the
596
- * caller may actually see. Filtering after the limit silently turns "the 200 most recent
597
- * events" into "however many of the 200 most recent events happened to be readable".
598
- */
599
- function readRawCandidatesWithinGrant(adapter, effectiveInput, grant) {
600
- const requested = effectiveInput.connectors;
601
- if (Array.isArray(requested) && requested.length === 0) {
602
- return resultFromCandidates([], hiddenAggregate());
603
- }
604
- // The rule is compiled to SQL in exactly one place (channel-grant.ts), which is also
605
- // where its boolean form lives. Building the clause here a second time is how the three
606
- // copies this replaces came about.
607
- const granted = (0, channel_grant_js_1.channelGrantClause)(grant, requested, {
608
- connector: 'source_connector',
609
- channel: 'channel',
610
- });
611
- // No overlap between what was asked for and what is granted reads nothing. It must not
612
- // fall through to an unfiltered scan.
613
- if (granted === null) {
614
- return resultFromCandidates([], refusedAggregate(countRefusedByGrant(adapter, effectiveInput)));
615
- }
616
- const clauses = [granted.sql];
617
- const params = [...granted.params];
618
- const min = minVisibleTimeMs(effectiveInput);
619
- if (min !== null) {
620
- clauses.push('COALESCE(event_datetime, source_timestamp_ms) >= ?');
621
- params.push(min);
622
- }
623
- // EVIDENCE IS WHAT HAS ALREADY HAPPENED, so the window ends now unless the caller named
624
- // a later end explicitly.
625
- //
626
- // Found by running this reader against a snapshot of the live index rather than against
627
- // fixtures. `event_datetime` is when the event OCCURS, and a calendar entry occurs in
628
- // the future: 2,762 live rows are future-dated, one of them in 2056. Ordering by that
629
- // column descending gave them the entire top-100 - a report asking what happened in the
630
- // last seven days received one hundred calendar entries and zero messages. Excluding
631
- // them, the same query returns 99 messages and one calendar entry.
632
- //
633
- // Nothing caught this before because the predicate this replaces returned no rows at
634
- // all, so its ordering never mattered. A caller that genuinely wants the future still
635
- // gets it by setting range.end_ms or as_of past now.
636
- const max = maxVisibleTimeMs(effectiveInput) ?? nowMs();
637
- clauses.push('COALESCE(event_datetime, source_timestamp_ms) <= ?');
638
- params.push(max);
639
- params.push(normalizeLimit(effectiveInput.limit));
640
- const rows = adapter
641
- .prepare(`
642
- SELECT event_index_id, source_connector, source_id, channel, title, content,
643
- event_datetime, source_timestamp_ms
644
- FROM connector_event_index
645
- WHERE ${clauses.join('\n AND ')}
646
- ORDER BY COALESCE(event_datetime, source_timestamp_ms) DESC, event_index_id ASC
647
- LIMIT ?
648
- `)
649
- .all(...params);
650
- return resultFromCandidates(rows.map(rawRowToCandidate), refusedAggregate(countRefusedByGrant(adapter, effectiveInput, granted)));
651
- }
652
- /**
653
- * How many events the grant kept out.
654
- *
655
- * Without this the caller cannot tell "this channel was quiet" from "you are not allowed to
656
- * see this channel", because the filtering happens in SQL and leaves no trace. That
657
- * distinction is the entire point: an owner asking about a board whose events are all
658
- * refused would otherwise get a confident empty answer with a clean diagnostics block.
659
- *
660
- * Counted in the requested connectors only - rows of connectors the run never asked about
661
- * are not "refused", they are simply not in question.
662
- */
663
- function countRefusedByGrant(adapter, effectiveInput, granted = null) {
664
- const requested = effectiveInput.connectors ?? [];
665
- if (requested.length === 0)
666
- return 0;
667
- const clauses = [`source_connector IN (${placeholders(requested)})`];
668
- const params = [...requested];
669
- if (granted !== null) {
670
- // `NOT (connector = ? AND channel IN (...))` is NULL when channel is NULL, so a
671
- // NULL-channel row is neither selected nor counted - it vanishes from both sides of
672
- // the answer. A connector that does not populate channel would have every event
673
- // refused and the count would report zero, which is precisely the confident empty
674
- // answer this count exists to prevent.
675
- clauses.push(`(channel IS NULL OR NOT ${granted.sql})`);
676
- params.push(...granted.params);
677
- }
678
- const min = minVisibleTimeMs(effectiveInput);
679
- const max = maxVisibleTimeMs(effectiveInput);
680
- if (min !== null) {
681
- clauses.push('COALESCE(event_datetime, source_timestamp_ms) >= ?');
682
- params.push(min);
683
- }
684
- if (max !== null) {
685
- clauses.push('COALESCE(event_datetime, source_timestamp_ms) <= ?');
686
- params.push(max);
687
- }
688
- const row = adapter
689
- .prepare(`SELECT COUNT(*) AS n FROM connector_event_index WHERE ${clauses.join(' AND ')}`)
690
- .get(...params);
691
- return Number(row?.n ?? 0);
692
- }
693
- /** Injectable only so a test can pin the boundary; production reads the clock. */
694
- let nowMs = () => Date.now();
695
- function setContextSourceClockForTests(clock) {
696
- nowMs = clock;
697
- }
698
- function refusedAggregate(refused) {
699
- const aggregate = hiddenAggregate();
700
- if (refused > 0) {
701
- aggregate.total = refused;
702
- aggregate.by_kind.raw = refused;
703
- aggregate.by_reason.channel_not_granted = refused;
704
- }
705
- return aggregate;
706
- }
707
- function rawRowToCandidate(row) {
708
- const sourceId = typeof row.source_id === 'string' && row.source_id.trim().length > 0
709
- ? row.source_id
710
- : undefined;
711
- return {
712
- ref: {
713
- kind: 'raw',
714
- connector: String(row.source_connector),
715
- raw_id: String(row.event_index_id),
716
- ...(sourceId ? { source_id: sourceId } : {}),
717
- channel_id: typeof row.channel === 'string' ? row.channel : null,
718
- },
719
- title: String(row.title ?? 'Raw event'),
720
- excerpt: String(row.content ?? '').slice(0, 500),
721
- score: 0.7,
722
- timestamp_ms: parseTimestampMs(row.event_datetime ?? row.source_timestamp_ms),
723
- source: 'raw',
724
- visible: true,
725
- support: emptySupport('connector_event_index'),
726
- };
727
- }
728
- function readGraphCandidates(adapter, input, visibleRefs, deps = {}) {
729
- const effectiveInput = normalizeTimeFilters(applyBoundaryDefaults(input));
730
- if (effectiveInput.boundary) {
731
- (0, visibility_js_1.assertContextBoundaryAllowsInput)({
732
- boundary: effectiveInput.boundary,
733
- requestedScopes: effectiveInput.scopes,
734
- requestedConnectors: effectiveInput.connectors,
735
- requestedProjectRefs: effectiveInput.project_refs,
736
- requestedTenantId: effectiveInput.tenant_id,
737
- });
738
- }
739
- if (Array.isArray(effectiveInput.scopes) && effectiveInput.scopes.length === 0) {
740
- return resultFromCandidates([], hiddenAggregate());
741
- }
742
- if (Array.isArray(effectiveInput.connectors) && effectiveInput.connectors.length === 0) {
743
- // Fail closed when caller explicitly narrowed connectors to none, so an
744
- // injectable listEdges cannot leak edges back into the result.
745
- return resultFromCandidates([], hiddenAggregate());
746
- }
747
- if (hasExplicitEmptyProjectWindow(effectiveInput)) {
748
- return resultFromCandidates([], hiddenAggregate());
749
- }
750
- if (visibleRefs.length === 0) {
751
- return resultFromCandidates([], hiddenAggregate());
752
- }
753
- const refs = visibleRefs.map((ref) => (0, ref_js_1.toTwinRef)(ref));
754
- const visibleRefKeys = new Set(visibleRefs.map(ref_js_1.serializeContextRefForProvenance));
755
- const listEdges = deps.listVisibleTwinEdgesForRefs ?? ref_validation_js_1.listVisibleTwinEdgesForRefs;
756
- const min = minVisibleTimeMs(effectiveInput);
757
- const max = maxVisibleTimeMs(effectiveInput);
758
- const edges = listEdges(adapter, refs, {
759
- scopes: effectiveInput.scopes,
760
- connectors: effectiveInput.connectors,
761
- projectRefs: effectiveInput.project_refs,
762
- tenantId: effectiveInput.tenant_id,
763
- startMs: min,
764
- asOfMs: max,
765
- limit: normalizeLimit(effectiveInput.limit),
766
- // Graph neighbours carry an excerpt, so an ungranted raw row reached through an edge
767
- // would disclose content the reader itself refuses.
768
- ...(effectiveInput.boundary?.channels ? { channels: effectiveInput.boundary.channels } : {}),
769
- }).filter((edge) => (min === null || edge.created_at >= min) && (max === null || edge.created_at <= max));
770
- const candidates = [];
771
- const emitted = new Set();
772
- for (const edge of edges) {
773
- for (const ref of edgeNeighborRefs(adapter, edge)) {
774
- const key = (0, ref_js_1.serializeContextRefForProvenance)(ref);
775
- if (visibleRefKeys.has(key) || emitted.has(key)) {
776
- continue;
777
- }
778
- emitted.add(key);
779
- candidates.push({
780
- ref,
781
- title: edge.edge_type,
782
- excerpt: edge.reason_text ?? '',
783
- score: edge.confidence,
784
- timestamp_ms: edge.created_at,
785
- source: 'graph',
786
- visible: true,
787
- edge_id: edge.edge_id,
788
- edge_type: edge.edge_type,
789
- support: {
790
- retrieval_source: 'twin_edges',
791
- graph_source: 'expanded',
792
- graph_expanded: true,
793
- confirmation_signals: [],
794
- metadata_signals: ['graph_edge'],
795
- },
796
- });
797
- }
798
- }
799
- return resultFromCandidates(candidates, hiddenAggregate());
800
- }
801
- function edgeNeighborRefs(adapter, edge) {
802
- return [edge.subject_ref, edge.object_ref].flatMap((ref) => {
803
- const contextRef = contextRefFromTwinRef(adapter, ref);
804
- return contextRef ? [contextRef] : [];
805
- });
806
- }
807
- function contextRefFromTwinRef(adapter, ref) {
808
- switch (ref.kind) {
809
- case 'memory':
810
- case 'entity':
811
- case 'case':
812
- return { kind: ref.kind, id: ref.id };
813
- case 'raw': {
814
- const row = adapter
815
- .prepare(`
816
- SELECT source_connector, source_id, channel
817
- FROM connector_event_index
818
- WHERE event_index_id = ?
819
- LIMIT 1
820
- `)
821
- .get(ref.id);
822
- if (!row || typeof row.source_connector !== 'string') {
823
- return null;
824
- }
825
- const contextRef = {
826
- kind: 'raw',
827
- connector: row.source_connector,
828
- raw_id: ref.id,
829
- };
830
- if (typeof row.source_id === 'string' && row.source_id.trim().length > 0) {
831
- contextRef.source_id = row.source_id;
832
- }
833
- contextRef.channel_id = typeof row.channel === 'string' ? row.channel : null;
834
- return contextRef;
835
- }
836
- default:
837
- return null;
838
- }
839
- }
840
- //# sourceMappingURL=source-readers.js.map