@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
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Knowledge observations: immutable observation versions and the visibility
3
+ * rule that decides which of them a caller may read. A cited observation must
4
+ * satisfy the same rule as a row the reader would have returned.
5
+ *
6
+ * @module knowledge/observations
7
+ */
8
+ import type { DatabaseAdapter } from '../db-manager.js';
9
+ import type { MemoryScopeRef } from '../memory/types.js';
10
+ type ObservationAdapter = Pick<DatabaseAdapter, 'prepare'>;
11
+ type ObservationVisibilityAdapter = Pick<DatabaseAdapter, 'prepare'>;
12
+ export interface ObservationBodyLocation {
13
+ kind: 'raw';
14
+ connectorName: string;
15
+ revisionSourceId: string;
16
+ }
17
+ export interface ObservationVersionInput {
18
+ /**
19
+ * Where this came from -- a namespace, paired with `sourceId` inside it. It was
20
+ * `sourceConnector`; a deployment with no connectors still observes things.
21
+ */
22
+ source: string;
23
+ sourceId: string;
24
+ producerVersionId?: string | null;
25
+ body?: string;
26
+ bodyLocation?: ObservationBodyLocation;
27
+ author?: string | null;
28
+ sourceAt?: number | null;
29
+ observedAt: number;
30
+ contentHash: string;
31
+ metadata?: Record<string, unknown> | null;
32
+ /**
33
+ * What was observed, beyond its body. These lived only on the connector index,
34
+ * which is why a core read had to go there to answer what a memory rests on.
35
+ */
36
+ sourceType?: string | null;
37
+ sourceLocator?: string | null;
38
+ title?: string | null;
39
+ artifactLocator?: string | null;
40
+ artifactTitle?: string | null;
41
+ eventDate?: string | null;
42
+ sourceEntityId?: string | null;
43
+ /**
44
+ * Who may see it. Columns rather than a JSON blob because raw visibility is a
45
+ * WHERE clause as well as a predicate, and the two are pinned against each other.
46
+ */
47
+ channel?: string | null;
48
+ projectId?: string | null;
49
+ tenantId?: string | null;
50
+ memoryScopeKind?: string | null;
51
+ memoryScopeId?: string | null;
52
+ scope?: Record<string, unknown> | null;
53
+ }
54
+ export interface ObservationVersionRecord {
55
+ observationId: string;
56
+ source: string;
57
+ sourceId: string;
58
+ producerVersionId: string | null;
59
+ body: string | null;
60
+ bodyLocation: ObservationBodyLocation | null;
61
+ author: string | null;
62
+ sourceAt: number | null;
63
+ observedAt: number;
64
+ contentHash: string;
65
+ metadata: Record<string, unknown>;
66
+ sourceType: string | null;
67
+ sourceLocator: string | null;
68
+ title: string | null;
69
+ artifactLocator: string | null;
70
+ artifactTitle: string | null;
71
+ eventDate: string | null;
72
+ sourceEntityId: string | null;
73
+ channel: string | null;
74
+ projectId: string | null;
75
+ tenantId: string | null;
76
+ memoryScopeKind: string | null;
77
+ memoryScopeId: string | null;
78
+ scope: Record<string, unknown>;
79
+ }
80
+ export interface OwnerObservationSearchItem {
81
+ observationRef: string;
82
+ source: string;
83
+ sourceId: string;
84
+ author: string | null;
85
+ sourceAt: number | null;
86
+ observedAt: number;
87
+ contentPreview: string;
88
+ metadataPreview: string;
89
+ }
90
+ export interface ObservationBodyReader {
91
+ readVersion(input: ObservationBodyLocation & {
92
+ expectedContentHash: string;
93
+ }): {
94
+ status: 'available';
95
+ body: string;
96
+ contentHash: string;
97
+ } | {
98
+ status: 'version_unavailable';
99
+ reason: 'VERSION_NOT_FOUND' | 'HASH_MISMATCH';
100
+ };
101
+ }
102
+ export type ObservationReadResult = {
103
+ status: 'available';
104
+ observation: ObservationVersionRecord;
105
+ body: string;
106
+ } | {
107
+ status: 'version_unavailable';
108
+ observation: ObservationVersionRecord;
109
+ reason: 'BODY_READER_UNAVAILABLE' | 'VERSION_NOT_FOUND' | 'HASH_MISMATCH';
110
+ } | {
111
+ status: 'not_found';
112
+ };
113
+ export declare function observationVersionId(input: ObservationVersionInput): string;
114
+ export declare function appendObservationVersion(adapter: ObservationAdapter, input: ObservationVersionInput): ObservationVersionRecord;
115
+ /**
116
+ * The observation's source, without reading the rest of it.
117
+ *
118
+ * A caller deciding whether a row is an owner observation needs one column. It
119
+ * asks for one: mapping the whole record would parse a body and a metadata
120
+ * blob it does not use, and a row whose metadata is malformed would then fail
121
+ * loudly where the answer is simply "not yours" — the disclosure the visibility
122
+ * check exists to avoid.
123
+ */
124
+ export declare function getObservationVersionSource(adapter: ObservationAdapter, observationId: string): string | null;
125
+ export declare function getObservationVersion(adapter: ObservationAdapter, observationId: string): ObservationVersionRecord | null;
126
+ export declare function searchOwnerObservationVersions(adapter: ObservationAdapter, input: {
127
+ query: string;
128
+ principalId: string;
129
+ agentId: string;
130
+ connectors?: string[];
131
+ connectorChannels?: Readonly<Record<string, readonly string[]>>;
132
+ fromMs?: number;
133
+ toMs?: number;
134
+ cursor?: string;
135
+ limit?: number;
136
+ }): {
137
+ items: OwnerObservationSearchItem[];
138
+ nextCursor: string | null;
139
+ };
140
+ export declare function readObservationVersion(adapter: ObservationAdapter, observationId: string, reader?: ObservationBodyReader, options?: {
141
+ maxSourceMs?: number | null;
142
+ }): ObservationReadResult;
143
+ export interface ObservationVisibilityAuthority {
144
+ principalId?: string;
145
+ agentId?: string;
146
+ scopes?: readonly MemoryScopeRef[];
147
+ connectors?: readonly string[];
148
+ connectorWideRead?: readonly string[];
149
+ channels?: Readonly<Record<string, readonly string[]>>;
150
+ maxSourceMs?: number | null;
151
+ }
152
+ export interface ObservationVisibilityRow {
153
+ source: unknown;
154
+ scope_json: unknown;
155
+ source_at?: unknown;
156
+ }
157
+ export declare function isObservationVersionVisible(adapter: ObservationVisibilityAdapter, observationId: string, authority: ObservationVisibilityAuthority): boolean;
158
+ export declare function isObservationVisibilityRowVisible(row: ObservationVisibilityRow, authority: ObservationVisibilityAuthority): boolean;
159
+ export {};
160
+ //# sourceMappingURL=observations.d.ts.map
@@ -0,0 +1,449 @@
1
+ "use strict";
2
+ /**
3
+ * Knowledge observations: immutable observation versions and the visibility
4
+ * rule that decides which of them a caller may read. A cited observation must
5
+ * satisfy the same rule as a row the reader would have returned.
6
+ *
7
+ * @module knowledge/observations
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.observationVersionId = observationVersionId;
11
+ exports.appendObservationVersion = appendObservationVersion;
12
+ exports.getObservationVersionSource = getObservationVersionSource;
13
+ exports.getObservationVersion = getObservationVersion;
14
+ exports.searchOwnerObservationVersions = searchOwnerObservationVersions;
15
+ exports.readObservationVersion = readObservationVersion;
16
+ exports.isObservationVersionVisible = isObservationVersionVisible;
17
+ exports.isObservationVisibilityRowVisible = isObservationVisibilityRowVisible;
18
+ const node_crypto_1 = require("node:crypto");
19
+ const canonicalize_js_1 = require("../canonicalize.js");
20
+ function parseObject(value, field) {
21
+ if (typeof value !== 'string') {
22
+ throw new Error(`observation_versions.${field} must be JSON text`);
23
+ }
24
+ let parsed;
25
+ try {
26
+ parsed = JSON.parse(value);
27
+ }
28
+ catch (error) {
29
+ const message = error instanceof Error ? error.message : String(error);
30
+ throw new Error(`observation_versions.${field} is malformed JSON: ${message}`);
31
+ }
32
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
33
+ throw new Error(`observation_versions.${field} must contain a JSON object`);
34
+ }
35
+ return parsed;
36
+ }
37
+ function nullableString(value, field) {
38
+ if (value === null) {
39
+ return null;
40
+ }
41
+ if (typeof value !== 'string') {
42
+ throw new Error(`observation_versions.${field} must be text or null`);
43
+ }
44
+ return value;
45
+ }
46
+ function finiteNumber(value, field, nullable = false) {
47
+ if (nullable && value === null) {
48
+ return null;
49
+ }
50
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
51
+ throw new Error(`observation_versions.${field} must be a finite number${nullable ? ' or null' : ''}`);
52
+ }
53
+ return value;
54
+ }
55
+ function mapRow(row) {
56
+ if (typeof row.observation_id !== 'string' || row.observation_id.trim() === '') {
57
+ throw new Error('observation_versions.observation_id must be nonblank text');
58
+ }
59
+ if (typeof row.source !== 'string' || row.source.trim() === '') {
60
+ throw new Error('observation_versions.source must be nonblank text');
61
+ }
62
+ if (typeof row.source_id !== 'string' || row.source_id.trim() === '') {
63
+ throw new Error('observation_versions.source_id must be nonblank text');
64
+ }
65
+ if (typeof row.content_hash !== 'string' || row.content_hash.trim() === '') {
66
+ throw new Error('observation_versions.content_hash must be nonblank text');
67
+ }
68
+ const body = nullableString(row.body, 'body');
69
+ const bodyLocationJson = nullableString(row.body_location_json, 'body_location_json');
70
+ if ((body === null) === (bodyLocationJson === null)) {
71
+ throw new Error('observation_versions row requires exactly one body source');
72
+ }
73
+ const bodyLocation = bodyLocationJson
74
+ ? parseObject(bodyLocationJson, 'body_location_json')
75
+ : null;
76
+ if (bodyLocation &&
77
+ (bodyLocation.kind !== 'raw' ||
78
+ typeof bodyLocation.connectorName !== 'string' ||
79
+ typeof bodyLocation.revisionSourceId !== 'string' ||
80
+ bodyLocation.connectorName.trim() === '' ||
81
+ bodyLocation.revisionSourceId.trim() === '')) {
82
+ throw new Error('observation_versions.body_location_json has an invalid raw locator');
83
+ }
84
+ return {
85
+ observationId: row.observation_id,
86
+ source: row.source,
87
+ sourceId: row.source_id,
88
+ producerVersionId: nullableString(row.producer_version_id, 'producer_version_id'),
89
+ body,
90
+ bodyLocation: bodyLocation,
91
+ author: nullableString(row.author, 'author'),
92
+ sourceAt: finiteNumber(row.source_at, 'source_at', true),
93
+ observedAt: finiteNumber(row.observed_at, 'observed_at'),
94
+ contentHash: row.content_hash,
95
+ metadata: parseObject(row.metadata_json, 'metadata_json'),
96
+ sourceType: nullableString(row.source_type, 'source_type'),
97
+ sourceLocator: nullableString(row.source_locator, 'source_locator'),
98
+ title: nullableString(row.title, 'title'),
99
+ artifactLocator: nullableString(row.artifact_locator, 'artifact_locator'),
100
+ artifactTitle: nullableString(row.artifact_title, 'artifact_title'),
101
+ eventDate: nullableString(row.event_date, 'event_date'),
102
+ sourceEntityId: nullableString(row.source_entity_id, 'source_entity_id'),
103
+ channel: nullableString(row.channel, 'channel'),
104
+ projectId: nullableString(row.project_id, 'project_id'),
105
+ tenantId: nullableString(row.tenant_id, 'tenant_id'),
106
+ memoryScopeKind: nullableString(row.memory_scope_kind, 'memory_scope_kind'),
107
+ memoryScopeId: nullableString(row.memory_scope_id, 'memory_scope_id'),
108
+ scope: parseObject(row.scope_json, 'scope_json'),
109
+ };
110
+ }
111
+ function sameObservation(actual, input, scope) {
112
+ return (actual.source === input.source &&
113
+ actual.sourceId === input.sourceId &&
114
+ actual.producerVersionId === (input.producerVersionId ?? null) &&
115
+ actual.body === (input.body ?? null) &&
116
+ (0, canonicalize_js_1.canonicalizeJSON)(actual.bodyLocation) === (0, canonicalize_js_1.canonicalizeJSON)(input.bodyLocation ?? null) &&
117
+ actual.author === (input.author ?? null) &&
118
+ actual.sourceAt === (input.sourceAt ?? null) &&
119
+ actual.observedAt === Math.floor(input.observedAt) &&
120
+ actual.contentHash === input.contentHash &&
121
+ (0, canonicalize_js_1.canonicalizeJSON)(actual.metadata) === (0, canonicalize_js_1.canonicalizeJSON)(input.metadata ?? {}) &&
122
+ (0, canonicalize_js_1.canonicalizeJSON)(actual.scope) === (0, canonicalize_js_1.canonicalizeJSON)(scope));
123
+ }
124
+ function observationVersionId(input) {
125
+ const identity = (0, canonicalize_js_1.canonicalizeJSON)({
126
+ source: input.source,
127
+ sourceId: input.sourceId,
128
+ producerVersionId: input.producerVersionId ?? null,
129
+ ...(input.producerVersionId === null || input.producerVersionId === undefined
130
+ ? { contentHash: input.contentHash }
131
+ : {}),
132
+ });
133
+ return `obs_${(0, node_crypto_1.createHash)('sha256').update(identity).digest('hex').slice(0, 24)}`;
134
+ }
135
+ function appendObservationVersion(adapter, input) {
136
+ if ((input.body === undefined) === (input.bodyLocation === undefined)) {
137
+ throw new Error('Observation requires exactly one of body or bodyLocation.');
138
+ }
139
+ if (!Number.isFinite(input.observedAt)) {
140
+ throw new Error('Observation observedAt must be finite.');
141
+ }
142
+ for (const [field, value] of [
143
+ ['source', input.source],
144
+ ['sourceId', input.sourceId],
145
+ ['contentHash', input.contentHash],
146
+ ]) {
147
+ if (!value.trim()) {
148
+ throw new Error(`Observation ${field} must be nonblank.`);
149
+ }
150
+ }
151
+ // The scope bag and the scope columns are one fact in two shapes: the bag is what
152
+ // was stated, the columns are what a WHERE clause can reach. Deriving the columns
153
+ // here, once, is what keeps them from disagreeing -- a caller that fills only one
154
+ // of the two is how they drift apart.
155
+ const scope = input.scope ?? {};
156
+ const fromScope = (key, explicit) => {
157
+ if (explicit !== undefined) {
158
+ return explicit;
159
+ }
160
+ const value = scope[key];
161
+ return typeof value === 'string' && value !== '' ? value : null;
162
+ };
163
+ const channel = fromScope('channel', input.channel);
164
+ const projectId = fromScope('projectId', input.projectId);
165
+ const tenantId = fromScope('tenantId', input.tenantId);
166
+ const memoryScopeKind = fromScope('memoryScopeKind', input.memoryScopeKind);
167
+ const memoryScopeId = fromScope('memoryScopeId', input.memoryScopeId);
168
+ // And the other direction. A caller that named the scope as columns has said the
169
+ // same thing as one that named it in the bag, and the two readers -- a WHERE
170
+ // clause over the columns, a predicate over the bag -- must not disagree about it.
171
+ const scopeBag = { ...scope };
172
+ for (const [key, value] of [
173
+ ['channel', channel],
174
+ ['projectId', projectId],
175
+ ['tenantId', tenantId],
176
+ ['memoryScopeKind', memoryScopeKind],
177
+ ['memoryScopeId', memoryScopeId],
178
+ ]) {
179
+ if (value !== null && scopeBag[key] === undefined) {
180
+ scopeBag[key] = value;
181
+ }
182
+ }
183
+ const id = observationVersionId(input);
184
+ adapter
185
+ .prepare(`INSERT OR IGNORE INTO observation_versions (
186
+ observation_id, source, source_id, producer_version_id, body,
187
+ body_location_json, author, source_at, observed_at, content_hash, metadata_json, scope_json,
188
+ source_type, source_locator, title, artifact_locator, artifact_title, event_date,
189
+ source_entity_id, channel, project_id, tenant_id, memory_scope_kind, memory_scope_id
190
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
191
+ .run(id, input.source, input.sourceId, input.producerVersionId ?? null, input.body ?? null, input.bodyLocation ? (0, canonicalize_js_1.canonicalizeJSON)(input.bodyLocation) : null, input.author ?? null, input.sourceAt ?? null, Math.floor(input.observedAt), input.contentHash, (0, canonicalize_js_1.canonicalizeJSON)(input.metadata ?? {}), (0, canonicalize_js_1.canonicalizeJSON)(scopeBag), input.sourceType ?? null, input.sourceLocator ?? null, input.title ?? null, input.artifactLocator ?? null, input.artifactTitle ?? null, input.eventDate ?? null, input.sourceEntityId ?? null, channel, projectId, tenantId, memoryScopeKind, memoryScopeId);
192
+ const record = getObservationVersion(adapter, id);
193
+ if (!record) {
194
+ throw new Error(`Failed to persist observation ${id}`);
195
+ }
196
+ if (!sameObservation(record, input, scopeBag)) {
197
+ throw new Error(`Observation replay conflict for ${id}`);
198
+ }
199
+ return record;
200
+ }
201
+ /**
202
+ * The observation's source, without reading the rest of it.
203
+ *
204
+ * A caller deciding whether a row is an owner observation needs one column. It
205
+ * asks for one: mapping the whole record would parse a body and a metadata
206
+ * blob it does not use, and a row whose metadata is malformed would then fail
207
+ * loudly where the answer is simply "not yours" — the disclosure the visibility
208
+ * check exists to avoid.
209
+ */
210
+ function getObservationVersionSource(adapter, observationId) {
211
+ const row = adapter
212
+ .prepare('SELECT source FROM observation_versions WHERE observation_id = ? LIMIT 1')
213
+ .get(observationId);
214
+ if (!row) {
215
+ return null;
216
+ }
217
+ if (typeof row.source !== 'string' || row.source.trim() === '') {
218
+ throw new Error('observation_versions.source must be nonblank text');
219
+ }
220
+ return row.source;
221
+ }
222
+ function getObservationVersion(adapter, observationId) {
223
+ const row = adapter
224
+ .prepare('SELECT * FROM observation_versions WHERE observation_id = ? LIMIT 1')
225
+ .get(observationId);
226
+ return row ? mapRow(row) : null;
227
+ }
228
+ function searchOwnerObservationVersions(adapter, input) {
229
+ const query = input.query.trim();
230
+ const limit = Math.min(100, Math.max(1, Math.floor(input.limit ?? 25)));
231
+ const clauses = [
232
+ "(source LIKE 'owner-message:%' OR source LIKE 'owner-result:%')",
233
+ "json_extract(scope_json, '$.visibility') = 'owner'",
234
+ "json_extract(scope_json, '$.principalId') = ?",
235
+ "json_extract(scope_json, '$.agentId') = ?",
236
+ ];
237
+ const params = [input.principalId, input.agentId];
238
+ const connectors = [...new Set((input.connectors ?? []).map((value) => value.trim()))].filter(Boolean);
239
+ if (input.connectors !== undefined && connectors.length === 0) {
240
+ return { items: [], nextCursor: null };
241
+ }
242
+ if (connectors.length > 0) {
243
+ clauses.push(`source IN (${connectors.map(() => '?').join(', ')})`);
244
+ params.push(...connectors);
245
+ }
246
+ if (input.connectorChannels !== undefined) {
247
+ const pairs = Object.entries(input.connectorChannels)
248
+ .map(([connector, values]) => [
249
+ connector.trim(),
250
+ [...new Set(values.map((value) => value.trim()).filter(Boolean))],
251
+ ])
252
+ .filter(([connector, values]) => connector.length > 0 && values.length > 0);
253
+ if (pairs.length === 0) {
254
+ return { items: [], nextCursor: null };
255
+ }
256
+ clauses.push(`(${pairs
257
+ .map(([, values]) => `(source IN (?, ?) AND channel IN (${values.map(() => '?').join(', ')}))`)
258
+ .join(' OR ')})`);
259
+ for (const [connector, values] of pairs) {
260
+ params.push(`owner-message:${connector}`, `owner-result:${connector}`, ...values);
261
+ }
262
+ }
263
+ if (input.fromMs !== undefined) {
264
+ clauses.push('observed_at >= ?');
265
+ params.push(input.fromMs);
266
+ }
267
+ if (input.toMs !== undefined) {
268
+ clauses.push('observed_at <= ?');
269
+ params.push(input.toMs);
270
+ }
271
+ if (query) {
272
+ clauses.push('(instr(body, ?) > 0 OR instr(metadata_json, ?) > 0)');
273
+ params.push(query, query);
274
+ }
275
+ if (input.cursor) {
276
+ let cursor;
277
+ try {
278
+ cursor = JSON.parse(Buffer.from(input.cursor, 'base64url').toString('utf8'));
279
+ }
280
+ catch {
281
+ throw new Error('Invalid owner observation cursor.');
282
+ }
283
+ if (!cursor ||
284
+ typeof cursor !== 'object' ||
285
+ Array.isArray(cursor) ||
286
+ !Number.isFinite(cursor.observedAt) ||
287
+ typeof cursor.observationId !== 'string' ||
288
+ !cursor.observationId) {
289
+ throw new Error('Invalid owner observation cursor.');
290
+ }
291
+ clauses.push('(observed_at < ? OR (observed_at = ? AND observation_id > ?))');
292
+ params.push(cursor.observedAt, cursor.observedAt, cursor.observationId);
293
+ }
294
+ const rows = adapter
295
+ .prepare(`SELECT * FROM observation_versions
296
+ WHERE ${clauses.join(' AND ')}
297
+ ORDER BY observed_at DESC, observation_id ASC
298
+ LIMIT ?`)
299
+ .all(...params, limit + 1);
300
+ const pageRows = rows.slice(0, limit);
301
+ const last = rows.length > limit ? pageRows[pageRows.length - 1] : undefined;
302
+ return {
303
+ items: pageRows.map((row) => {
304
+ const record = mapRow(row);
305
+ const compact = (record.body ?? '').replace(/\s+/g, ' ').trim();
306
+ return {
307
+ observationRef: record.observationId,
308
+ source: record.source,
309
+ sourceId: record.sourceId,
310
+ author: record.author,
311
+ sourceAt: record.sourceAt,
312
+ observedAt: record.observedAt,
313
+ contentPreview: compact.length > 500 ? `${compact.slice(0, 497)}...` : compact,
314
+ metadataPreview: (0, canonicalize_js_1.canonicalizeJSON)(record.metadata).slice(0, 500),
315
+ };
316
+ }),
317
+ nextCursor: last
318
+ ? Buffer.from(JSON.stringify({
319
+ observedAt: Number(last.observed_at),
320
+ observationId: String(last.observation_id),
321
+ })).toString('base64url')
322
+ : null,
323
+ };
324
+ }
325
+ function readObservationVersion(adapter, observationId, reader, options) {
326
+ const observation = getObservationVersion(adapter, observationId);
327
+ if (!observation) {
328
+ return { status: 'not_found' };
329
+ }
330
+ const maxSourceMs = options?.maxSourceMs ?? null;
331
+ if (maxSourceMs !== null) {
332
+ if (!Number.isSafeInteger(maxSourceMs) || maxSourceMs < 0) {
333
+ throw new Error('Observation source ceiling must be a nonnegative epoch millisecond integer');
334
+ }
335
+ if (observation.sourceAt === null || observation.sourceAt > maxSourceMs) {
336
+ return { status: 'not_found' };
337
+ }
338
+ }
339
+ if (observation.body !== null) {
340
+ return { status: 'available', observation, body: observation.body };
341
+ }
342
+ if (!reader || !observation.bodyLocation) {
343
+ return { status: 'version_unavailable', observation, reason: 'BODY_READER_UNAVAILABLE' };
344
+ }
345
+ const result = reader.readVersion({
346
+ ...observation.bodyLocation,
347
+ expectedContentHash: observation.contentHash,
348
+ });
349
+ if (result.status === 'available') {
350
+ return result.contentHash === observation.contentHash
351
+ ? { status: 'available', observation, body: result.body }
352
+ : { status: 'version_unavailable', observation, reason: 'HASH_MISMATCH' };
353
+ }
354
+ return { status: 'version_unavailable', observation, reason: result.reason };
355
+ }
356
+ function parseScopeJson(value) {
357
+ if (typeof value !== 'string') {
358
+ throw new Error('observation_versions.scope_json must be JSON text');
359
+ }
360
+ let parsed;
361
+ try {
362
+ parsed = JSON.parse(value);
363
+ }
364
+ catch (error) {
365
+ const message = error instanceof Error ? error.message : String(error);
366
+ throw new Error(`observation_versions.scope_json is malformed JSON: ${message}`);
367
+ }
368
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
369
+ throw new Error('observation_versions.scope_json must contain a JSON object');
370
+ }
371
+ return parsed;
372
+ }
373
+ function matchesScope(scope, visible) {
374
+ if (visible.kind === 'project') {
375
+ return (scope.projectId === visible.id ||
376
+ (scope.memoryScopeKind === 'project' && scope.memoryScopeId === visible.id));
377
+ }
378
+ if (visible.kind === 'channel') {
379
+ return (scope.channel === visible.id ||
380
+ (scope.memoryScopeKind === 'channel' && scope.memoryScopeId === visible.id));
381
+ }
382
+ return scope.memoryScopeKind === visible.kind && scope.memoryScopeId === visible.id;
383
+ }
384
+ function isObservationVersionVisible(adapter, observationId, authority) {
385
+ const row = adapter
386
+ .prepare(`SELECT scope_json, source, source_at
387
+ FROM observation_versions WHERE observation_id = ?`)
388
+ .get(observationId);
389
+ if (!row) {
390
+ return false;
391
+ }
392
+ return isObservationVisibilityRowVisible(row, authority);
393
+ }
394
+ function isObservationVisibilityRowVisible(row, authority) {
395
+ const principalId = authority.principalId?.trim();
396
+ const agentId = authority.agentId?.trim();
397
+ if (!principalId || !agentId) {
398
+ return false;
399
+ }
400
+ const maxSourceMs = authority.maxSourceMs ?? null;
401
+ if (maxSourceMs !== null) {
402
+ if (!Number.isSafeInteger(maxSourceMs) || maxSourceMs < 0) {
403
+ throw new Error('Observation source ceiling must be a nonnegative epoch millisecond integer');
404
+ }
405
+ const sourceAt = typeof row.source_at === 'number' ? row.source_at : null;
406
+ if (sourceAt === null || sourceAt > maxSourceMs)
407
+ return false;
408
+ }
409
+ if (typeof row.source !== 'string' || !row.source.trim()) {
410
+ throw new Error('observation_versions.source must be nonblank text');
411
+ }
412
+ const ownerConnector = /^owner-(?:message|result):(.+)$/.exec(row.source)?.[1];
413
+ const connector = ownerConnector ?? row.source;
414
+ if (!authority.connectors?.includes(connector)) {
415
+ return false;
416
+ }
417
+ const scope = parseScopeJson(row.scope_json);
418
+ const connectorWideRead = authority.connectorWideRead?.includes(connector) === true;
419
+ if (authority.channels && !connectorWideRead) {
420
+ const visibleChannels = authority.channels[connector];
421
+ const channel = typeof scope.channel === 'string' ? scope.channel : null;
422
+ const normalizedChannel = channel?.startsWith(`${connector}:`)
423
+ ? channel.slice(connector.length + 1)
424
+ : channel;
425
+ if (!visibleChannels ||
426
+ channel === null ||
427
+ (!visibleChannels.includes(channel) &&
428
+ (normalizedChannel === null || !visibleChannels.includes(normalizedChannel)))) {
429
+ return false;
430
+ }
431
+ }
432
+ if (ownerConnector !== undefined || scope.visibility === 'owner') {
433
+ if (ownerConnector === undefined || scope.visibility !== 'owner') {
434
+ throw new Error('owner observation connector and scope visibility are inconsistent');
435
+ }
436
+ return scope.principalId === principalId && scope.agentId === agentId;
437
+ }
438
+ // A current connector/channel grant is the same read authority source.read
439
+ // applies. Imported originals can have no project or memory-scope tag; that
440
+ // absence does not revoke an explicitly granted source read in the graph.
441
+ if (connectorWideRead || authority.channels) {
442
+ return true;
443
+ }
444
+ if (!authority.scopes || authority.scopes.length === 0) {
445
+ return false;
446
+ }
447
+ return authority.scopes.some((visible) => matchesScope(scope, visible));
448
+ }
449
+ //# sourceMappingURL=observations.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * What a search query is asking for.
3
+ *
4
+ * The classifier is a mechanism: an ordered list of patterns, first match wins. The
5
+ * WORDS are not. Two of them named connectors that one deployment happens to run,
6
+ * which told every other product installing this core that asking about that
7
+ * connector is asking about an artifact, whether or not it has one.
8
+ *
9
+ * So the words are injectable. The default below carries only words that name no
10
+ * product: what a file is, what a date is, what asking "why" looks like. A caller
11
+ * with its own domain adds to it.
12
+ */
13
+ export type QuestionType = 'correction' | 'artifact' | 'timeline' | 'status' | 'decision_reason' | 'how_to' | 'unknown';
14
+ export declare const QUESTION_TYPES: readonly QuestionType[];
15
+ /** One question type and the pattern that names it. Order is the precedence. */
16
+ export interface QuestionPattern {
17
+ readonly type: Exclude<QuestionType, 'unknown'>;
18
+ readonly pattern: RegExp;
19
+ }
20
+ export type QuestionVocabulary = readonly QuestionPattern[];
21
+ export declare const DEFAULT_QUESTION_VOCABULARY: QuestionVocabulary;
22
+ /**
23
+ * Declare the words this deployment asks questions with. Call once, at boot.
24
+ *
25
+ * Replaces the default outright rather than merging: a caller that wants the general
26
+ * words plus its own spreads DEFAULT_QUESTION_VOCABULARY itself, and can see in one
27
+ * place what its classifier actually knows.
28
+ */
29
+ export declare function declareQuestionVocabulary(next: QuestionVocabulary): void;
30
+ /** Restore the default. For tests that declared their own. */
31
+ export declare function resetQuestionVocabulary(): void;
32
+ export declare function classifyQuestionType(query: string): QuestionType;
33
+ export declare function isQuestionType(value: string): value is QuestionType;
34
+ //# sourceMappingURL=question-type.d.ts.map