@jungjaehoon/mama-core 2.4.1 → 4.0.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 (371) 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/dist/action-contracts.d.ts +212 -0
  39. package/dist/action-contracts.js +10 -0
  40. package/dist/api/catalog.d.ts +118 -0
  41. package/dist/api/catalog.js +1756 -0
  42. package/dist/api/dispatch.d.ts +76 -0
  43. package/dist/api/dispatch.js +372 -0
  44. package/dist/canonicalize.d.ts +2 -2
  45. package/dist/canonicalize.js +3 -3
  46. package/dist/client/client.d.ts +33 -0
  47. package/dist/client/client.js +123 -0
  48. package/dist/client/ipc.d.ts +81 -0
  49. package/dist/client/ipc.js +314 -0
  50. package/dist/db-adapter/base-adapter.d.ts +6 -66
  51. package/dist/db-adapter/base-adapter.js +6 -6
  52. package/dist/db-adapter/index.d.ts +5 -5
  53. package/dist/db-adapter/index.js +2 -5
  54. package/dist/db-adapter/node-sqlite-adapter.d.ts +85 -15
  55. package/dist/db-adapter/node-sqlite-adapter.js +1968 -570
  56. package/dist/db-manager.d.ts +53 -97
  57. package/dist/db-manager.js +121 -603
  58. package/dist/embedding/embedder.d.ts +132 -0
  59. package/dist/embedding/embedder.js +299 -0
  60. package/dist/identity/principal-repository.d.ts +2 -2
  61. package/dist/index.d.ts +43 -58
  62. package/dist/index.js +97 -145
  63. package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
  64. package/dist/knowledge/access.js +663 -0
  65. package/dist/knowledge/case-errors.d.ts +31 -0
  66. package/dist/knowledge/case-errors.js +40 -0
  67. package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
  68. package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
  69. package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
  70. package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
  71. package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
  72. package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
  73. package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
  74. package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
  75. package/dist/knowledge/commitments.d.ts +188 -0
  76. package/dist/knowledge/commitments.js +370 -0
  77. package/dist/knowledge/decision-edges.d.ts +70 -0
  78. package/dist/knowledge/decision-edges.js +123 -0
  79. package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
  80. package/dist/knowledge/graph-query.js +1585 -0
  81. package/dist/knowledge/identity.d.ts +16 -0
  82. package/dist/knowledge/identity.js +22 -0
  83. package/dist/knowledge/index.d.ts +47 -0
  84. package/dist/knowledge/index.js +90 -0
  85. package/dist/knowledge/judgments.d.ts +118 -0
  86. package/dist/knowledge/judgments.js +808 -0
  87. package/dist/knowledge/observations.d.ts +160 -0
  88. package/dist/knowledge/observations.js +449 -0
  89. package/dist/knowledge/question-type.d.ts +34 -0
  90. package/dist/knowledge/question-type.js +70 -0
  91. package/dist/{search → knowledge}/ranker-features.js +1 -1
  92. package/dist/{search → knowledge}/search-quality.d.ts +0 -1
  93. package/dist/knowledge/search.d.ts +38 -0
  94. package/dist/knowledge/search.js +91 -0
  95. package/dist/knowledge/source-ingest.d.ts +65 -0
  96. package/dist/knowledge/source-ingest.js +174 -0
  97. package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
  98. package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
  99. package/dist/knowledge/work-dates.d.ts +49 -0
  100. package/dist/knowledge/work-dates.js +120 -0
  101. package/dist/mama-api.d.ts +114 -778
  102. package/dist/mama-api.js +313 -2461
  103. package/dist/memory/api.d.ts +264 -24
  104. package/dist/memory/api.js +1633 -843
  105. package/dist/memory/bootstrap-builder.d.ts +2 -1
  106. package/dist/memory/bootstrap-builder.js +5 -5
  107. package/dist/memory/channel-summary-state-store.d.ts +3 -2
  108. package/dist/memory/channel-summary-state-store.js +53 -51
  109. package/dist/memory/channel-summary-store.d.ts +5 -3
  110. package/dist/memory/channel-summary-store.js +3 -8
  111. package/dist/memory/dashboard-read.d.ts +46 -0
  112. package/dist/memory/dashboard-read.js +94 -0
  113. package/dist/memory/event-store.d.ts +3 -3
  114. package/dist/memory/event-store.js +3 -10
  115. package/dist/memory/finding-store.d.ts +3 -2
  116. package/dist/memory/finding-store.js +2 -7
  117. package/dist/memory/graph-read.d.ts +52 -0
  118. package/dist/memory/graph-read.js +130 -0
  119. package/dist/memory/judgment-types.d.ts +394 -0
  120. package/dist/memory/judgment-types.js +16 -0
  121. package/dist/memory/provenance-audit.d.ts +5 -2
  122. package/dist/memory/provenance-audit.js +8 -14
  123. package/dist/memory/provenance-live.d.ts +141 -0
  124. package/dist/memory/provenance-live.js +409 -0
  125. package/dist/memory/provenance-query.d.ts +5 -4
  126. package/dist/memory/provenance-query.js +21 -29
  127. package/dist/memory/provenance-resolver.d.ts +191 -0
  128. package/dist/memory/provenance-resolver.js +155 -0
  129. package/dist/memory/provenance.d.ts +1 -11
  130. package/dist/memory/provenance.js +2 -33
  131. package/dist/memory/recall-sanitize.d.ts +55 -0
  132. package/dist/memory/recall-sanitize.js +144 -0
  133. package/dist/memory/secret-filter.d.ts +32 -0
  134. package/dist/memory/secret-filter.js +126 -0
  135. package/dist/memory/truth-store.d.ts +2 -1
  136. package/dist/memory/truth-store.js +1 -4
  137. package/dist/memory/types.d.ts +74 -24
  138. package/dist/memory/types.js +75 -5
  139. package/dist/memory/write-adapters.d.ts +98 -0
  140. package/dist/memory/write-adapters.js +242 -0
  141. package/dist/operations/owner-action-effects.d.ts +53 -0
  142. package/dist/operations/owner-action-effects.js +96 -0
  143. package/dist/provenance/source-ref.d.ts +1 -1
  144. package/dist/provenance/source-ref.js +0 -2
  145. package/dist/registry/corrections.d.ts +31 -0
  146. package/dist/registry/corrections.js +332 -0
  147. package/dist/registry/record-identity.d.ts +49 -0
  148. package/dist/registry/record-identity.js +133 -0
  149. package/dist/registry/store.d.ts +101 -0
  150. package/dist/registry/store.js +395 -0
  151. package/dist/registry/types.d.ts +28 -0
  152. package/dist/registry/types.js +5 -0
  153. package/dist/relevance-scorer.js +2 -2
  154. package/dist/runtime/agent-event-bus.d.ts +50 -0
  155. package/dist/runtime/agent-event-bus.js +101 -0
  156. package/dist/runtime/drivers/claude-cli-wrapper.d.ts +155 -0
  157. package/dist/runtime/drivers/claude-cli-wrapper.js +392 -0
  158. package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
  159. package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
  160. package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
  161. package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
  162. package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
  163. package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
  164. package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
  165. package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
  166. package/dist/runtime/drivers/codex-home.d.ts +20 -0
  167. package/dist/runtime/drivers/codex-home.js +674 -0
  168. package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
  169. package/dist/runtime/drivers/codex-thread-registry.js +433 -0
  170. package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
  171. package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
  172. package/dist/runtime/drivers/persistent-cli-process.d.ts +424 -0
  173. package/dist/runtime/drivers/persistent-cli-process.js +1543 -0
  174. package/dist/runtime/drivers/types.d.ts +456 -0
  175. package/dist/runtime/drivers/types.js +110 -0
  176. package/dist/runtime/mailbox.d.ts +223 -0
  177. package/dist/runtime/mailbox.js +582 -0
  178. package/dist/runtime/model-run-store.d.ts +28 -0
  179. package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
  180. package/dist/{model-runs/types.d.ts → runtime/model-run-types.d.ts} +33 -4
  181. package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
  182. package/dist/runtime/native-effect-observer.d.ts +22 -0
  183. package/dist/runtime/native-effect-observer.js +103 -0
  184. package/dist/runtime/native-input-journal.d.ts +46 -0
  185. package/dist/runtime/native-input-journal.js +308 -0
  186. package/dist/runtime/native-prompt.d.ts +118 -0
  187. package/dist/runtime/native-prompt.js +496 -0
  188. package/dist/runtime/native-session.d.ts +10 -0
  189. package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
  190. package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
  191. package/dist/runtime/native-tool-trace-observer.js +65 -0
  192. package/dist/runtime/native-turn.d.ts +272 -0
  193. package/dist/runtime/native-turn.js +1041 -0
  194. package/dist/runtime/operations.d.ts +236 -0
  195. package/dist/runtime/operations.js +565 -0
  196. package/dist/runtime/post-tool-handler.d.ts +74 -0
  197. package/dist/runtime/post-tool-handler.js +137 -0
  198. package/dist/runtime/prompt-layers.d.ts +126 -0
  199. package/dist/runtime/prompt-layers.js +239 -0
  200. package/dist/runtime/runtime-process.d.ts +102 -0
  201. package/dist/runtime/runtime-process.js +206 -0
  202. package/dist/runtime/runtime.d.ts +278 -0
  203. package/dist/runtime/runtime.js +563 -0
  204. package/dist/runtime/session-pool.d.ts +176 -0
  205. package/dist/runtime/session-pool.js +369 -0
  206. package/dist/runtime/stimulus-payload.d.ts +5 -0
  207. package/dist/runtime/stimulus-payload.js +50 -0
  208. package/dist/runtime/subagent-bridge.d.ts +24 -0
  209. package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
  210. package/dist/runtime/text-completion.d.ts +22 -0
  211. package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
  212. package/dist/runtime/token-estimator.d.ts +25 -0
  213. package/dist/runtime/token-estimator.js +75 -0
  214. package/dist/runtime/tool-trace-store.d.ts +22 -0
  215. package/dist/{model-runs → runtime}/tool-trace-store.js +46 -27
  216. package/dist/runtime/trace-summary.d.ts +5 -0
  217. package/dist/runtime/trace-summary.js +74 -0
  218. package/dist/runtime/turn-text.d.ts +23 -0
  219. package/dist/runtime/turn-text.js +41 -0
  220. package/dist/storage/database.d.ts +67 -0
  221. package/dist/storage/database.js +158 -0
  222. package/package.json +20 -34
  223. package/dist/agent-graph/alias-write.d.ts +0 -3
  224. package/dist/agent-graph/alias-write.js +0 -234
  225. package/dist/agent-graph/entity-resolve.d.ts +0 -3
  226. package/dist/agent-graph/entity-resolve.js +0 -271
  227. package/dist/agent-graph/errors.d.ts +0 -4
  228. package/dist/agent-graph/errors.js +0 -11
  229. package/dist/agent-graph/graph-query.d.ts +0 -5
  230. package/dist/agent-graph/graph-query.js +0 -360
  231. package/dist/agent-graph/index.d.ts +0 -6
  232. package/dist/agent-situation/builder.d.ts +0 -8
  233. package/dist/agent-situation/builder.js +0 -239
  234. package/dist/agent-situation/cache-key.d.ts +0 -4
  235. package/dist/agent-situation/cache-key.js +0 -64
  236. package/dist/agent-situation/index.d.ts +0 -7
  237. package/dist/agent-situation/index.js +0 -28
  238. package/dist/agent-situation/packet-store.d.ts +0 -27
  239. package/dist/agent-situation/packet-store.js +0 -228
  240. package/dist/agent-situation/ranking-policy.d.ts +0 -18
  241. package/dist/agent-situation/ranking-policy.js +0 -75
  242. package/dist/agent-situation/source-readers.d.ts +0 -52
  243. package/dist/agent-situation/source-readers.js +0 -300
  244. package/dist/agent-situation/types.d.ts +0 -195
  245. package/dist/cases/wiki-page-index.d.ts +0 -37
  246. package/dist/cases/wiki-page-index.js +0 -201
  247. package/dist/config-loader.d.ts +0 -68
  248. package/dist/config-loader.js +0 -239
  249. package/dist/connectors/event-index.d.ts +0 -24
  250. package/dist/connectors/event-index.js +0 -245
  251. package/dist/connectors/raw-query.d.ts +0 -40
  252. package/dist/connectors/raw-query.js +0 -412
  253. package/dist/connectors/types.d.ts +0 -117
  254. package/dist/connectors/types.js +0 -3
  255. package/dist/context-compile/boundary-defaults.d.ts +0 -12
  256. package/dist/context-compile/boundary-defaults.js +0 -105
  257. package/dist/context-compile/channel-grant.js +0 -66
  258. package/dist/context-compile/compiler-policy.d.ts +0 -39
  259. package/dist/context-compile/compiler-policy.js +0 -147
  260. package/dist/context-compile/compiler.d.ts +0 -18
  261. package/dist/context-compile/compiler.js +0 -404
  262. package/dist/context-compile/index.d.ts +0 -10
  263. package/dist/context-compile/index.js +0 -26
  264. package/dist/context-compile/packet-store.d.ts +0 -8
  265. package/dist/context-compile/packet-store.js +0 -239
  266. package/dist/context-compile/ref.d.ts +0 -7
  267. package/dist/context-compile/ref.js +0 -102
  268. package/dist/context-compile/source-readers.d.ts +0 -70
  269. package/dist/context-compile/source-readers.js +0 -840
  270. package/dist/context-compile/types.d.ts +0 -155
  271. package/dist/context-compile/types.js +0 -11
  272. package/dist/context-compile/visibility.d.ts +0 -21
  273. package/dist/context-compile/visibility.js +0 -224
  274. package/dist/decision-tracker.d.ts +0 -206
  275. package/dist/decision-tracker.js +0 -481
  276. package/dist/edges/ref-validation.d.ts +0 -7
  277. package/dist/edges/ref-validation.js +0 -321
  278. package/dist/edges/store.d.ts +0 -8
  279. package/dist/edges/store.js +0 -129
  280. package/dist/embedding-client.d.ts +0 -28
  281. package/dist/embedding-client.js +0 -53
  282. package/dist/embedding-server/index.d.ts +0 -67
  283. package/dist/embedding-server/index.js +0 -405
  284. package/dist/embedding-server/mobile/auth.d.ts +0 -44
  285. package/dist/embedding-server/mobile/auth.js +0 -150
  286. package/dist/embedding-server/mobile/daemon.d.ts +0 -129
  287. package/dist/embedding-server/mobile/daemon.js +0 -313
  288. package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
  289. package/dist/embedding-server/mobile/output-parser.js +0 -241
  290. package/dist/embedding-server/mobile/session-api.d.ts +0 -57
  291. package/dist/embedding-server/mobile/session-api.js +0 -261
  292. package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
  293. package/dist/embedding-server/mobile/session-manager.js +0 -378
  294. package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
  295. package/dist/embedding-server/mobile/websocket-handler.js +0 -486
  296. package/dist/embeddings.d.ts +0 -68
  297. package/dist/embeddings.js +0 -244
  298. package/dist/entities/audit-metrics.d.ts +0 -68
  299. package/dist/entities/audit-metrics.js +0 -124
  300. package/dist/entities/candidate-generator.d.ts +0 -8
  301. package/dist/entities/candidate-generator.js +0 -24
  302. package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
  303. package/dist/entities/entity-linked-decision-counts.js +0 -29
  304. package/dist/entities/entity-list.d.ts +0 -22
  305. package/dist/entities/entity-list.js +0 -3
  306. package/dist/entities/entity-orphan-list.d.ts +0 -17
  307. package/dist/entities/entity-orphan-list.js +0 -3
  308. package/dist/entities/entity-search.d.ts +0 -20
  309. package/dist/entities/entity-search.js +0 -3
  310. package/dist/entities/errors.d.ts +0 -55
  311. package/dist/entities/errors.js +0 -100
  312. package/dist/entities/lineage-store.d.ts +0 -28
  313. package/dist/entities/lineage-store.js +0 -204
  314. package/dist/entities/normalization.d.ts +0 -14
  315. package/dist/entities/normalization.js +0 -63
  316. package/dist/entities/policy-store.d.ts +0 -8
  317. package/dist/entities/policy-store.js +0 -75
  318. package/dist/entities/policy-types.d.ts +0 -72
  319. package/dist/entities/policy-types.js +0 -59
  320. package/dist/entities/projection.d.ts +0 -8
  321. package/dist/entities/projection.js +0 -82
  322. package/dist/entities/provenance-query.d.ts +0 -32
  323. package/dist/entities/provenance-query.js +0 -3
  324. package/dist/entities/read-identity.d.ts +0 -31
  325. package/dist/entities/read-identity.js +0 -264
  326. package/dist/entities/recall-bridge.d.ts +0 -5
  327. package/dist/entities/recall-bridge.js +0 -171
  328. package/dist/entities/resolution-engine.d.ts +0 -8
  329. package/dist/entities/resolution-engine.js +0 -3
  330. package/dist/entities/rollback-preview.d.ts +0 -35
  331. package/dist/entities/rollback-preview.js +0 -3
  332. package/dist/entities/source-locator.d.ts +0 -3
  333. package/dist/entities/source-locator.js +0 -32
  334. package/dist/entities/store.d.ts +0 -69
  335. package/dist/entities/store.js +0 -544
  336. package/dist/entities/types.d.ts +0 -166
  337. package/dist/entities/types.js +0 -30
  338. package/dist/memory/extraction-prompt.d.ts +0 -4
  339. package/dist/memory/extraction-prompt.js +0 -89
  340. package/dist/memory/scope-backfill.d.ts +0 -14
  341. package/dist/memory/scope-backfill.js +0 -3
  342. package/dist/memory/scope-store.d.ts +0 -4
  343. package/dist/memory/scope-store.js +0 -9
  344. package/dist/memory-store.d.ts +0 -87
  345. package/dist/memory-store.js +0 -78
  346. package/dist/model-runs/store.d.ts +0 -13
  347. package/dist/model-runs/tool-trace-store.d.ts +0 -8
  348. package/dist/notification-manager.d.ts +0 -7
  349. package/dist/notification-manager.js +0 -12
  350. package/dist/outcome-tracker.d.ts +0 -151
  351. package/dist/outcome-tracker.js +0 -271
  352. package/dist/query-intent.d.ts +0 -23
  353. package/dist/query-intent.js +0 -114
  354. package/dist/runtime/trusted-provenance.d.ts +0 -3
  355. package/dist/runtime/trusted-provenance.js +0 -6
  356. package/dist/search/question-type.d.ts +0 -5
  357. package/dist/search/question-type.js +0 -41
  358. package/dist/test-utils.d.ts +0 -80
  359. package/dist/test-utils.js +0 -218
  360. package/dist/tier-validator.d.ts +0 -43
  361. package/dist/tier-validator.js +0 -159
  362. package/dist/time-formatter.d.ts +0 -25
  363. package/dist/time-formatter.js +0 -93
  364. /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
  365. /package/dist/{search → knowledge}/feedback-store.js +0 -0
  366. /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
  367. /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
  368. /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
  369. /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
  370. /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
  371. /package/dist/{search → knowledge}/search-quality.js +0 -0
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.detectSourceLocatorKind = detectSourceLocatorKind;
4
- function detectSourceLocatorKind(locator) {
5
- if (typeof locator !== 'string' || locator.trim().length === 0) {
6
- return 'unknown';
7
- }
8
- const trimmed = locator.trim();
9
- const normalized = trimmed.toLowerCase();
10
- if (normalized.startsWith('http://') || normalized.startsWith('https://')) {
11
- return 'url';
12
- }
13
- if (normalized.startsWith('file://')) {
14
- return 'file';
15
- }
16
- if (normalized.startsWith('drive://') ||
17
- normalized.startsWith('gmail://') ||
18
- normalized.startsWith('calendar://') ||
19
- normalized.startsWith('sheets://')) {
20
- return 'connector';
21
- }
22
- if (normalized.endsWith('.db') ||
23
- normalized.includes('/raw.db') ||
24
- normalized.includes('\\raw.db')) {
25
- return 'db';
26
- }
27
- if (trimmed.startsWith('/') || trimmed.startsWith('~/') || /^[A-Za-z]:[\\/]/.test(trimmed)) {
28
- return 'file';
29
- }
30
- return 'unknown';
31
- }
32
- //# sourceMappingURL=source-locator.js.map
@@ -1,69 +0,0 @@
1
- import { type EntityAlias, type EntityNode, type EntityObservation } from './types.js';
2
- export interface EntityStoreAdapter {
3
- prepare(sql: string): {
4
- run(...params: unknown[]): {
5
- changes: number;
6
- lastInsertRowid: number | bigint;
7
- };
8
- get(...params: unknown[]): unknown;
9
- all(...params: unknown[]): unknown[];
10
- };
11
- }
12
- export declare class EntityMergeError extends Error {
13
- readonly code: string;
14
- constructor(code: string, message: string);
15
- }
16
- declare const OBSERVATION_CONTEXT_KEY_COLUMNS: readonly ["workspace_context_key", "channel_context_key", "thread_context_key", "actor_context_key"];
17
- type CreateEntityNodeInput = Omit<EntityNode, 'created_at' | 'updated_at'>;
18
- type AttachEntityAliasInput = Omit<EntityAlias, 'created_at'>;
19
- type ObservationContextKeyColumn = (typeof OBSERVATION_CONTEXT_KEY_COLUMNS)[number];
20
- type UpsertEntityObservationInput = Omit<EntityObservation, 'created_at'> & Partial<Record<ObservationContextKeyColumn, string | null>>;
21
- export interface UpsertEntityObservationResult {
22
- id: string;
23
- created: boolean;
24
- }
25
- export declare function clearEntityTableColumnCache(adapter: EntityStoreAdapter): void;
26
- export declare function parseObservationRow(row: Record<string, unknown>): EntityObservation;
27
- export declare function createEntityNode(input: CreateEntityNodeInput): Promise<EntityNode>;
28
- export declare function getEntityNode(id: string, adapter?: EntityStoreAdapter): EntityNode | null;
29
- export declare function attachEntityAlias(input: AttachEntityAliasInput): Promise<EntityAlias>;
30
- export declare function listEntityAliases(entityId: string, adapter?: EntityStoreAdapter): EntityAlias[];
31
- export declare function upsertEntityObservation(input: UpsertEntityObservationInput): Promise<EntityObservation>;
32
- export declare function upsertEntityObservations(inputs: UpsertEntityObservationInput[]): Promise<UpsertEntityObservationResult[]>;
33
- /**
34
- * Walks the `entity_nodes.merged_into` chain from the given id and returns the
35
- * terminal (unmerged) entity id. Detects cycles and caps depth. Read-only.
36
- *
37
- * Matches the read-time chain-walking approach described in the canonical
38
- * entity ontology implementation plan.
39
- */
40
- export declare function resolveCanonicalEntityId(adapter: EntityStoreAdapter, id: string): string;
41
- export interface MergeEntityNodesInput {
42
- adapter: EntityStoreAdapter;
43
- source_id: string;
44
- target_id: string;
45
- actor_type: 'system' | 'user' | 'agent';
46
- actor_id: string;
47
- reason: string;
48
- candidate_id: string | null;
49
- evidence_json: string;
50
- }
51
- export interface MergeEntityNodesResult {
52
- merge_action_id: string;
53
- timeline_event_id: string;
54
- merged_at: number;
55
- }
56
- /**
57
- * Marks `source_id` as merged into `target_id`, emits a timeline event, and
58
- * inserts the entity_merge_actions audit row with both entity IDs populated.
59
- *
60
- * Intentionally NOT wrapped in its own transaction — the caller is expected
61
- * to wrap the call in `adapter.transaction(...)` so the candidate status
62
- * update and this merge land atomically (Policy B1, hard transaction).
63
- *
64
- * Validates: source != target, both exist, both active/unmerged, same kind,
65
- * same scope. Throws `EntityMergeError` with a stable `code` on any violation.
66
- */
67
- export declare function mergeEntityNodes(input: MergeEntityNodesInput): MergeEntityNodesResult;
68
- export {};
69
- //# sourceMappingURL=store.d.ts.map
@@ -1,544 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EntityMergeError = void 0;
4
- exports.clearEntityTableColumnCache = clearEntityTableColumnCache;
5
- exports.parseObservationRow = parseObservationRow;
6
- exports.createEntityNode = createEntityNode;
7
- exports.getEntityNode = getEntityNode;
8
- exports.attachEntityAlias = attachEntityAlias;
9
- exports.listEntityAliases = listEntityAliases;
10
- exports.upsertEntityObservation = upsertEntityObservation;
11
- exports.upsertEntityObservations = upsertEntityObservations;
12
- exports.resolveCanonicalEntityId = resolveCanonicalEntityId;
13
- exports.mergeEntityNodes = mergeEntityNodes;
14
- const node_crypto_1 = require("node:crypto");
15
- const db_manager_js_1 = require("../db-manager.js");
16
- const types_js_1 = require("./types.js");
17
- class EntityMergeError extends Error {
18
- code;
19
- constructor(code, message) {
20
- super(message);
21
- this.code = code;
22
- this.name = 'EntityMergeError';
23
- }
24
- }
25
- exports.EntityMergeError = EntityMergeError;
26
- const MAX_MERGE_CHAIN_DEPTH = 8;
27
- const OBSERVATION_CONTEXT_KEY_COLUMNS = [
28
- 'workspace_context_key',
29
- 'channel_context_key',
30
- 'thread_context_key',
31
- 'actor_context_key',
32
- ];
33
- const tableColumnCache = new WeakMap();
34
- function now() {
35
- return Date.now();
36
- }
37
- function normalizeSourceLocator(value) {
38
- // Write empty-string as the null sentinel so SQLite UNIQUE can collapse null-like locators; parseObservationRow maps it back to null on read.
39
- return value ?? '';
40
- }
41
- function normalizeContextKey(value) {
42
- return value ?? '';
43
- }
44
- function sourceLocatorForInput(input) {
45
- return normalizeSourceLocator(input.source_locator);
46
- }
47
- function channelContextKey(input) {
48
- if (input.channel_context_key !== undefined) {
49
- return normalizeContextKey(input.channel_context_key);
50
- }
51
- if (input.scope_kind !== 'channel' || !input.scope_id) {
52
- return '';
53
- }
54
- return input.scope_id.startsWith(`${input.source_connector}:`)
55
- ? input.scope_id
56
- : `${input.source_connector}:${input.scope_id}`;
57
- }
58
- function actorContextKey(input) {
59
- if (input.actor_context_key !== undefined) {
60
- return normalizeContextKey(input.actor_context_key);
61
- }
62
- if (input.observation_type === 'author') {
63
- return input.surface_form;
64
- }
65
- return input.related_surface_forms.find((value) => value.trim().length > 0) ?? '';
66
- }
67
- function observationContextKeys(input) {
68
- return {
69
- workspace_context_key: normalizeContextKey(input.workspace_context_key ?? input.source_connector),
70
- channel_context_key: channelContextKey(input),
71
- thread_context_key: normalizeContextKey(input.thread_context_key),
72
- actor_context_key: actorContextKey(input),
73
- };
74
- }
75
- function tableColumnNames(adapter, tableName) {
76
- let adapterCache = tableColumnCache.get(adapter);
77
- if (!adapterCache) {
78
- adapterCache = new Map();
79
- tableColumnCache.set(adapter, adapterCache);
80
- }
81
- const cached = adapterCache.get(tableName);
82
- if (cached) {
83
- return cached;
84
- }
85
- const rows = adapter.prepare(`PRAGMA table_info(${tableName})`).all();
86
- const columns = new Set(rows.map((row) => row.name));
87
- adapterCache.set(tableName, columns);
88
- return columns;
89
- }
90
- function clearEntityTableColumnCache(adapter) {
91
- tableColumnCache.delete(adapter);
92
- }
93
- function requireStringField(row, field) {
94
- if (typeof row[field] !== 'string' || row[field].length === 0) {
95
- throw new Error(`Invalid entity observation row: ${field} must be a non-empty string`);
96
- }
97
- return row[field];
98
- }
99
- function optionalStringField(row, field) {
100
- if (!Object.prototype.hasOwnProperty.call(row, field)) {
101
- throw new Error(`Invalid entity observation row: ${field} must be present`);
102
- }
103
- if (row[field] === null) {
104
- return null;
105
- }
106
- if (typeof row[field] !== 'string') {
107
- throw new Error(`Invalid entity observation row: ${field} must be a string or null`);
108
- }
109
- return row[field];
110
- }
111
- function optionalStringFieldIfPresent(row, field) {
112
- if (!Object.prototype.hasOwnProperty.call(row, field)) {
113
- return undefined;
114
- }
115
- if (row[field] === null) {
116
- return null;
117
- }
118
- if (typeof row[field] !== 'string') {
119
- throw new Error(`Invalid entity observation row: ${field} must be a string or null`);
120
- }
121
- return row[field];
122
- }
123
- function optionalNumberField(row, field) {
124
- if (!Object.prototype.hasOwnProperty.call(row, field)) {
125
- throw new Error(`Invalid entity observation row: ${field} must be present`);
126
- }
127
- if (row[field] === null) {
128
- return null;
129
- }
130
- if (typeof row[field] !== 'number') {
131
- throw new Error(`Invalid entity observation row: ${field} must be a number or null`);
132
- }
133
- return row[field];
134
- }
135
- function parseObservationRow(row) {
136
- const id = requireStringField(row, 'id');
137
- const observationType = requireStringField(row, 'observation_type');
138
- if (!types_js_1.ENTITY_OBSERVATION_TYPES.includes(observationType)) {
139
- throw new Error(`Invalid entity observation row: observation_type=${observationType}`);
140
- }
141
- const entityKindHint = optionalStringField(row, 'entity_kind_hint');
142
- if (entityKindHint !== null &&
143
- !types_js_1.ENTITY_KINDS.includes(entityKindHint)) {
144
- throw new Error(`Invalid entity observation row: entity_kind_hint=${entityKindHint}`);
145
- }
146
- const scopeKind = optionalStringField(row, 'scope_kind');
147
- if (scopeKind === null) {
148
- throw new Error('Invalid entity observation row: scope_kind must not be null');
149
- }
150
- if (!types_js_1.ENTITY_SCOPE_KINDS.includes(scopeKind)) {
151
- throw new Error(`Invalid entity observation row: scope_kind=${scopeKind}`);
152
- }
153
- const createdAt = row.created_at;
154
- if (typeof createdAt !== 'number') {
155
- throw new Error('Invalid entity observation row: created_at must be a number');
156
- }
157
- let relatedSurfaceForms = [];
158
- if (typeof row.related_surface_forms === 'string') {
159
- try {
160
- const parsed = JSON.parse(row.related_surface_forms);
161
- if (!Array.isArray(parsed) || parsed.some((value) => typeof value !== 'string')) {
162
- throw new Error('parsed value is not a string[]');
163
- }
164
- relatedSurfaceForms = parsed;
165
- }
166
- catch (error) {
167
- throw new Error(`Invalid entity observation row: related_surface_forms must be valid JSON string[] (${error instanceof Error ? error.message : String(error)})`);
168
- }
169
- }
170
- else if (row.related_surface_forms !== undefined && row.related_surface_forms !== null) {
171
- throw new Error('Invalid entity observation row: related_surface_forms must be a JSON string or null');
172
- }
173
- const sourceLocator = optionalStringFieldIfPresent(row, 'source_locator');
174
- if (sourceLocator === undefined) {
175
- throw new Error('Invalid entity observation row: source_locator must be present');
176
- }
177
- return {
178
- id,
179
- observation_type: observationType,
180
- entity_kind_hint: entityKindHint,
181
- surface_form: requireStringField(row, 'surface_form'),
182
- normalized_form: requireStringField(row, 'normalized_form'),
183
- lang: optionalStringField(row, 'lang'),
184
- script: optionalStringField(row, 'script'),
185
- context_summary: optionalStringField(row, 'context_summary'),
186
- related_surface_forms: relatedSurfaceForms,
187
- timestamp_observed: optionalNumberField(row, 'timestamp_observed'),
188
- scope_kind: scopeKind,
189
- scope_id: optionalStringField(row, 'scope_id'),
190
- extractor_version: requireStringField(row, 'extractor_version'),
191
- embedding_model_version: optionalStringField(row, 'embedding_model_version'),
192
- source_connector: requireStringField(row, 'source_connector'),
193
- source_locator: sourceLocator && sourceLocator.length > 0 ? sourceLocator : null,
194
- source_raw_record_id: requireStringField(row, 'source_raw_record_id'),
195
- workspace_context_key: optionalStringFieldIfPresent(row, 'workspace_context_key'),
196
- channel_context_key: optionalStringFieldIfPresent(row, 'channel_context_key'),
197
- thread_context_key: optionalStringFieldIfPresent(row, 'thread_context_key'),
198
- actor_context_key: optionalStringFieldIfPresent(row, 'actor_context_key'),
199
- created_at: createdAt,
200
- };
201
- }
202
- async function createEntityNode(input) {
203
- await (0, db_manager_js_1.initDB)();
204
- const adapter = (0, db_manager_js_1.getAdapter)();
205
- const createdAt = now();
206
- adapter
207
- .prepare(`
208
- INSERT INTO entity_nodes (
209
- id, kind, preferred_label, status, scope_kind, scope_id, merged_into, created_at, updated_at
210
- )
211
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
212
- `)
213
- .run(input.id, input.kind, input.preferred_label, input.status, input.scope_kind, input.scope_id, input.merged_into, createdAt, createdAt);
214
- return {
215
- ...input,
216
- created_at: createdAt,
217
- updated_at: createdAt,
218
- };
219
- }
220
- function getEntityNode(id, adapter = (0, db_manager_js_1.getAdapter)()) {
221
- const row = adapter.prepare('SELECT * FROM entity_nodes WHERE id = ?').get(id);
222
- if (!row) {
223
- return null;
224
- }
225
- return {
226
- id: String(row.id),
227
- kind: row.kind,
228
- preferred_label: String(row.preferred_label),
229
- status: row.status,
230
- scope_kind: typeof row.scope_kind === 'string' ? row.scope_kind : null,
231
- scope_id: typeof row.scope_id === 'string' ? row.scope_id : null,
232
- merged_into: typeof row.merged_into === 'string' ? row.merged_into : null,
233
- created_at: Number(row.created_at),
234
- updated_at: Number(row.updated_at),
235
- };
236
- }
237
- async function attachEntityAlias(input) {
238
- await (0, db_manager_js_1.initDB)();
239
- const adapter = (0, db_manager_js_1.getAdapter)();
240
- const createdAt = now();
241
- adapter
242
- .prepare(`
243
- INSERT INTO entity_aliases (
244
- id, entity_id, label, normalized_label, lang, script, label_type,
245
- source_type, source_ref, confidence, status, created_at
246
- )
247
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
248
- `)
249
- .run(input.id, input.entity_id, input.label, input.normalized_label, input.lang, input.script, input.label_type, input.source_type, input.source_ref, input.confidence, input.status, createdAt);
250
- return {
251
- ...input,
252
- created_at: createdAt,
253
- };
254
- }
255
- function listEntityAliases(entityId, adapter = (0, db_manager_js_1.getAdapter)()) {
256
- const rows = adapter
257
- .prepare('SELECT * FROM entity_aliases WHERE entity_id = ? ORDER BY created_at ASC')
258
- .all(entityId);
259
- return rows.map((row) => ({
260
- id: String(row.id),
261
- entity_id: String(row.entity_id),
262
- label: String(row.label),
263
- normalized_label: String(row.normalized_label),
264
- lang: typeof row.lang === 'string' ? row.lang : null,
265
- script: typeof row.script === 'string' ? row.script : null,
266
- label_type: row.label_type,
267
- source_type: String(row.source_type),
268
- source_ref: typeof row.source_ref === 'string' ? row.source_ref : null,
269
- confidence: typeof row.confidence === 'number' ? row.confidence : null,
270
- status: row.status,
271
- created_at: Number(row.created_at),
272
- }));
273
- }
274
- function observationContextColumns(columns) {
275
- return OBSERVATION_CONTEXT_KEY_COLUMNS.filter((column) => columns.has(column));
276
- }
277
- function observationInsertValues(input, normalizedSourceLocator, contextColumns, contextKeys, createdAt) {
278
- const columns = [
279
- 'id',
280
- 'observation_type',
281
- 'entity_kind_hint',
282
- 'surface_form',
283
- 'normalized_form',
284
- 'lang',
285
- 'script',
286
- 'context_summary',
287
- 'related_surface_forms',
288
- 'timestamp_observed',
289
- 'scope_kind',
290
- 'scope_id',
291
- 'extractor_version',
292
- 'embedding_model_version',
293
- 'source_connector',
294
- 'source_locator',
295
- 'source_raw_record_id',
296
- ...contextColumns,
297
- 'created_at',
298
- ];
299
- const values = [
300
- input.id,
301
- input.observation_type,
302
- input.entity_kind_hint,
303
- input.surface_form,
304
- input.normalized_form,
305
- input.lang,
306
- input.script,
307
- input.context_summary,
308
- JSON.stringify(input.related_surface_forms),
309
- input.timestamp_observed,
310
- input.scope_kind,
311
- input.scope_id,
312
- input.extractor_version,
313
- input.embedding_model_version,
314
- input.source_connector,
315
- normalizedSourceLocator,
316
- input.source_raw_record_id,
317
- ...contextColumns.map((column) => contextKeys[column]),
318
- createdAt,
319
- ];
320
- return { columns, values };
321
- }
322
- function findExistingObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys) {
323
- const conditions = [
324
- 'source_connector = ?',
325
- 'source_locator = ?',
326
- 'source_raw_record_id = ?',
327
- 'observation_type = ?',
328
- ...contextColumns.map((column) => `COALESCE(${column}, '') = ?`),
329
- ];
330
- const params = [
331
- input.source_connector,
332
- normalizedSourceLocator,
333
- input.source_raw_record_id,
334
- input.observation_type,
335
- ...contextColumns.map((column) => contextKeys[column]),
336
- ];
337
- return adapter
338
- .prepare(`
339
- SELECT id FROM entity_observations
340
- WHERE ${conditions.join(' AND ')}
341
- ORDER BY created_at ASC, id ASC
342
- LIMIT 1
343
- `)
344
- .get(...params);
345
- }
346
- function insertObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys, createdAt) {
347
- const insert = observationInsertValues(input, normalizedSourceLocator, contextColumns, contextKeys, createdAt);
348
- const placeholders = insert.columns.map(() => '?').join(', ');
349
- adapter
350
- .prepare(`
351
- INSERT INTO entity_observations (${insert.columns.join(', ')})
352
- VALUES (${placeholders})
353
- `)
354
- .run(...insert.values);
355
- }
356
- function updateObservation(adapter, id, input, normalizedSourceLocator, contextColumns, contextKeys) {
357
- const assignments = [
358
- 'entity_kind_hint = ?',
359
- 'surface_form = ?',
360
- 'normalized_form = ?',
361
- 'lang = ?',
362
- 'script = ?',
363
- 'context_summary = ?',
364
- 'related_surface_forms = ?',
365
- 'timestamp_observed = ?',
366
- 'scope_kind = ?',
367
- 'scope_id = ?',
368
- 'extractor_version = ?',
369
- 'embedding_model_version = ?',
370
- 'source_locator = ?',
371
- ...contextColumns.map((column) => `${column} = ?`),
372
- ];
373
- const values = [
374
- input.entity_kind_hint,
375
- input.surface_form,
376
- input.normalized_form,
377
- input.lang,
378
- input.script,
379
- input.context_summary,
380
- JSON.stringify(input.related_surface_forms),
381
- input.timestamp_observed,
382
- input.scope_kind,
383
- input.scope_id,
384
- input.extractor_version,
385
- input.embedding_model_version,
386
- normalizedSourceLocator,
387
- ...contextColumns.map((column) => contextKeys[column]),
388
- id,
389
- ];
390
- adapter
391
- .prepare(`
392
- UPDATE entity_observations
393
- SET ${assignments.join(', ')}
394
- WHERE id = ?
395
- `)
396
- .run(...values);
397
- }
398
- function saveObservation(adapter, input) {
399
- const columns = tableColumnNames(adapter, 'entity_observations');
400
- const contextColumns = observationContextColumns(columns);
401
- const contextKeys = observationContextKeys(input);
402
- const normalizedSourceLocator = sourceLocatorForInput(input);
403
- const existing = findExistingObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys);
404
- if (existing) {
405
- const id = requireStringField(existing, 'id');
406
- updateObservation(adapter, id, input, normalizedSourceLocator, contextColumns, contextKeys);
407
- return { id, created: false };
408
- }
409
- insertObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys, now());
410
- return { id: input.id, created: true };
411
- }
412
- async function upsertEntityObservation(input) {
413
- await (0, db_manager_js_1.initDB)();
414
- const adapter = (0, db_manager_js_1.getAdapter)();
415
- const result = saveObservation(adapter, input);
416
- const saved = adapter.prepare('SELECT * FROM entity_observations WHERE id = ?').get(result.id);
417
- if (!saved) {
418
- throw new Error(`Failed to load saved entity observation ${result.id}`);
419
- }
420
- return parseObservationRow(saved);
421
- }
422
- async function upsertEntityObservations(inputs) {
423
- await (0, db_manager_js_1.initDB)();
424
- const adapter = (0, db_manager_js_1.getAdapter)();
425
- const observations = [];
426
- const upsertOne = (input) => {
427
- observations.push(saveObservation(adapter, input));
428
- };
429
- if ('transaction' in adapter && typeof adapter.transaction === 'function') {
430
- const txResult = adapter.transaction(() => {
431
- for (const input of inputs) {
432
- upsertOne(input);
433
- }
434
- });
435
- if (typeof txResult === 'function') {
436
- txResult();
437
- }
438
- return observations;
439
- }
440
- for (const input of inputs) {
441
- upsertOne(input);
442
- }
443
- return observations;
444
- }
445
- /**
446
- * Walks the `entity_nodes.merged_into` chain from the given id and returns the
447
- * terminal (unmerged) entity id. Detects cycles and caps depth. Read-only.
448
- *
449
- * Matches the read-time chain-walking approach described in the canonical
450
- * entity ontology implementation plan.
451
- */
452
- function resolveCanonicalEntityId(adapter, id) {
453
- const seen = new Set();
454
- let current = id;
455
- for (let depth = 0; depth < MAX_MERGE_CHAIN_DEPTH; depth++) {
456
- if (seen.has(current)) {
457
- throw new EntityMergeError('entity.merge_chain_cycle', `Cycle detected in merged_into chain starting at ${id}`);
458
- }
459
- seen.add(current);
460
- const row = adapter
461
- .prepare('SELECT merged_into FROM entity_nodes WHERE id = ?')
462
- .get(current);
463
- if (!row) {
464
- throw new EntityMergeError('entity.node_not_found', `Entity node ${current} not found while resolving canonical id for ${id}`);
465
- }
466
- if (!row.merged_into) {
467
- return current;
468
- }
469
- current = row.merged_into;
470
- }
471
- throw new EntityMergeError('entity.merge_chain_too_deep', `merged_into chain exceeds depth ${MAX_MERGE_CHAIN_DEPTH} starting at ${id}`);
472
- }
473
- /**
474
- * Marks `source_id` as merged into `target_id`, emits a timeline event, and
475
- * inserts the entity_merge_actions audit row with both entity IDs populated.
476
- *
477
- * Intentionally NOT wrapped in its own transaction — the caller is expected
478
- * to wrap the call in `adapter.transaction(...)` so the candidate status
479
- * update and this merge land atomically (Policy B1, hard transaction).
480
- *
481
- * Validates: source != target, both exist, both active/unmerged, same kind,
482
- * same scope. Throws `EntityMergeError` with a stable `code` on any violation.
483
- */
484
- function mergeEntityNodes(input) {
485
- const { adapter, source_id, target_id, actor_type, actor_id, reason, candidate_id, evidence_json, } = input;
486
- if (!source_id || !target_id) {
487
- throw new EntityMergeError('entity.merge_invalid_args', 'source_id and target_id are required');
488
- }
489
- if (source_id === target_id) {
490
- throw new EntityMergeError('entity.merge_self', 'Cannot merge an entity into itself');
491
- }
492
- const source = adapter.prepare('SELECT * FROM entity_nodes WHERE id = ?').get(source_id);
493
- if (!source) {
494
- throw new EntityMergeError('entity.merge_source_not_found', `Source entity ${source_id} not found`);
495
- }
496
- const target = adapter.prepare('SELECT * FROM entity_nodes WHERE id = ?').get(target_id);
497
- if (!target) {
498
- throw new EntityMergeError('entity.merge_target_not_found', `Target entity ${target_id} not found`);
499
- }
500
- if (source.status === 'merged' || source.merged_into) {
501
- throw new EntityMergeError('entity.merge_source_already_merged', `Source entity ${source_id} is already merged`);
502
- }
503
- if (target.status === 'merged' || target.merged_into) {
504
- throw new EntityMergeError('entity.merge_target_already_merged', `Target entity ${target_id} is already merged`);
505
- }
506
- if (source.status === 'archived' || target.status === 'archived') {
507
- throw new EntityMergeError('entity.merge_archived', 'Cannot merge archived entities');
508
- }
509
- if (source.kind !== target.kind) {
510
- throw new EntityMergeError('entity.merge_kind_mismatch', `Cannot merge ${source.kind} into ${target.kind}`);
511
- }
512
- if (source.scope_kind !== target.scope_kind || source.scope_id !== target.scope_id) {
513
- throw new EntityMergeError('entity.merge_scope_mismatch', `Cannot merge across scopes: ${source.scope_kind}/${source.scope_id ?? 'null'} vs ${target.scope_kind}/${target.scope_id ?? 'null'}`);
514
- }
515
- const mergedAt = now();
516
- const mergeActionId = `mact_${(0, node_crypto_1.randomUUID)()}`;
517
- const timelineEventId = `et_${(0, node_crypto_1.randomUUID)()}`;
518
- adapter
519
- .prepare(`UPDATE entity_nodes SET merged_into = ?, status = 'merged', updated_at = ? WHERE id = ?`)
520
- .run(target_id, mergedAt, source_id);
521
- adapter
522
- .prepare(`
523
- INSERT INTO entity_timeline_events (
524
- id, entity_id, event_type, role, observed_at, source_ref, summary, details, created_at
525
- )
526
- VALUES (?, ?, 'merged', NULL, ?, ?, ?, ?, ?)
527
- `)
528
- .run(timelineEventId, source_id, mergedAt, candidate_id, `Merged into ${target_id}`, JSON.stringify({ target_entity_id: target_id, reason, actor_id, actor_type }), mergedAt);
529
- adapter
530
- .prepare(`
531
- INSERT INTO entity_merge_actions (
532
- id, action_type, source_entity_id, target_entity_id, candidate_id,
533
- actor_type, actor_id, reason, evidence_json, created_at
534
- )
535
- VALUES (?, 'merge', ?, ?, ?, ?, ?, ?, ?, ?)
536
- `)
537
- .run(mergeActionId, source_id, target_id, candidate_id, actor_type, actor_id, reason, evidence_json, mergedAt);
538
- return {
539
- merge_action_id: mergeActionId,
540
- timeline_event_id: timelineEventId,
541
- merged_at: mergedAt,
542
- };
543
- }
544
- //# sourceMappingURL=store.js.map