@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
@@ -0,0 +1,370 @@
1
+ "use strict";
2
+ /**
3
+ * Reading owner work back out of the commitment log.
4
+ *
5
+ * `appendJudgment` has written `commitments` and `commitment_assignments` since
6
+ * migration 075: a commitment row carries identity, the current revision and the
7
+ * head record, and one assignment row per revision carries the patch that
8
+ * revision applied. Nothing read them back. The only SELECT against either table
9
+ * was the writer's own CAS check, so the substrate could be written and never
10
+ * answered from - the shape this refactor exists to close.
11
+ *
12
+ * Current values are a fold, not a column. Each assignment states `set` and
13
+ * `clear` for that revision only, and the view is those applied in revision
14
+ * order. That is what keeps a correction from erasing what it corrected: the
15
+ * revision that changed a title is still readable next to the one that set it,
16
+ * and `history: 'all'` returns them.
17
+ *
18
+ * @module knowledge/commitments
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.readWork = readWork;
22
+ exports.createWork = createWork;
23
+ exports.reviseWork = reviseWork;
24
+ exports.withdrawWork = withdrawWork;
25
+ const judgments_js_1 = require("./judgments.js");
26
+ const work_dates_js_1 = require("./work-dates.js");
27
+ const DEFAULT_LIMIT = 25;
28
+ const MAX_LIMIT = 100;
29
+ function parseLimit(value) {
30
+ if (value === undefined)
31
+ return DEFAULT_LIMIT;
32
+ if (!Number.isSafeInteger(value) || value < 1 || value > MAX_LIMIT) {
33
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', `limit must be an integer from 1 to ${MAX_LIMIT}`);
34
+ }
35
+ return value;
36
+ }
37
+ function parseCursor(value) {
38
+ if (value === undefined)
39
+ return 0;
40
+ const afterTaskId = Number(value);
41
+ if (!Number.isSafeInteger(afterTaskId) || afterTaskId < 0) {
42
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'cursor is not a commitment page cursor');
43
+ }
44
+ return afterTaskId;
45
+ }
46
+ function parseAsOf(value) {
47
+ if (value === undefined)
48
+ return null;
49
+ if (!Number.isSafeInteger(value) || value < 0) {
50
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'asOf must be an epoch millisecond integer');
51
+ }
52
+ return value;
53
+ }
54
+ function parsePatch(json, field) {
55
+ const parsed = JSON.parse(json);
56
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
57
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', `${field} is not a work patch object`);
58
+ }
59
+ return parsed;
60
+ }
61
+ function parseClear(json) {
62
+ const parsed = JSON.parse(json);
63
+ if (!Array.isArray(parsed)) {
64
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'clear_json is not a field list');
65
+ }
66
+ return parsed;
67
+ }
68
+ function applyRevision(values, revision) {
69
+ for (const [field, value] of Object.entries(revision.set)) {
70
+ values[field] = value;
71
+ }
72
+ for (const field of revision.clear) {
73
+ delete values[field];
74
+ }
75
+ }
76
+ /**
77
+ * Fold the assignments into the values they leave behind.
78
+ *
79
+ * `clear` is applied after `set` within one revision: a revision that sets and
80
+ * clears the same field is stating that the field ends the revision absent,
81
+ * which is what the writer's own ordering already means.
82
+ */
83
+ function foldAssignments(revisions) {
84
+ const values = {};
85
+ for (const revision of revisions) {
86
+ applyRevision(values, revision);
87
+ }
88
+ return values;
89
+ }
90
+ function stringField(values, field) {
91
+ const value = values[field];
92
+ return typeof value === 'string' ? value : null;
93
+ }
94
+ /** A revision's summary, only when its record is visible to the caller. */
95
+ function readJudgmentSummary(adapter, recordId, admitted) {
96
+ if (!recordVisible(adapter, recordId, admitted))
97
+ return null;
98
+ const row = adapter.prepare('SELECT summary FROM decisions WHERE id = ?').get(recordId);
99
+ return row && typeof row.summary === 'string' ? row.summary : null;
100
+ }
101
+ function buildChain(adapter, revisions, admitted) {
102
+ const values = {};
103
+ return revisions.map((revision) => {
104
+ applyRevision(values, revision);
105
+ return {
106
+ revision: revision.revision,
107
+ operation: revision.operation,
108
+ eventDatetime: revision.eventDatetime,
109
+ status: revision.operation === 'withdraw' ? 'cancelled' : stringField(values, 'status'),
110
+ stage: stringField(values, 'stage'),
111
+ summary: readJudgmentSummary(adapter, revision.recordRef.id, admitted),
112
+ };
113
+ });
114
+ }
115
+ /**
116
+ * Whether the caller may read this commitment.
117
+ *
118
+ * A commitment carries no scope of its own; its head record does, through the
119
+ * same `memory_scope_bindings` every judgment read uses. An unbound record has
120
+ * no partition boundary to violate and stays readable, exactly as
121
+ * `referenceExists` decides it for a memory ref.
122
+ */
123
+ function recordVisible(adapter, recordId, admitted) {
124
+ const row = adapter
125
+ .prepare('SELECT COUNT(*) AS bindings FROM memory_scope_bindings WHERE memory_id = ?')
126
+ .get(recordId);
127
+ if (!row)
128
+ return false;
129
+ if (row.bindings === 0)
130
+ return true;
131
+ if (admitted.length === 0)
132
+ return false;
133
+ const placeholders = admitted.map(() => '?').join(', ');
134
+ return (adapter
135
+ .prepare(`SELECT 1 FROM memory_scope_bindings
136
+ WHERE memory_id = ? AND scope_id IN (${placeholders}) LIMIT 1`)
137
+ .get(recordId, ...admitted) !== undefined);
138
+ }
139
+ /**
140
+ * Read owner work: one commitment, or a bounded page of them.
141
+ *
142
+ * `asOf` folds revisions by their source event time when recorded, or by the
143
+ * commit clock for judgments without an event time. A backfill committed today
144
+ * can therefore answer what was current at a historical instant. A commitment
145
+ * whose first revision is later than `asOf` is absent, not empty.
146
+ */
147
+ function readWork(adapter, query, access) {
148
+ const admitted = (0, judgments_js_1.admittedScopeIds)(access);
149
+ const limit = parseLimit(query.limit);
150
+ const afterTaskId = parseCursor(query.cursor);
151
+ const asOf = parseAsOf(query.asOf);
152
+ const wantsHistory = query.history === 'all';
153
+ const wantsChain = query.history === 'chain';
154
+ if (query.history !== undefined &&
155
+ query.history !== 'all' &&
156
+ query.history !== 'current' &&
157
+ query.history !== 'chain') {
158
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', "history must be 'current', 'chain', or 'all'");
159
+ }
160
+ if (query.commitmentId !== undefined && query.rowId !== undefined) {
161
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'Ask by commitmentId or rowId, not both');
162
+ }
163
+ const reasons = [];
164
+ let rows;
165
+ let total = null;
166
+ if (query.commitmentId !== undefined) {
167
+ rows = adapter
168
+ .prepare('SELECT * FROM commitments WHERE commitment_id = ?')
169
+ .all(query.commitmentId);
170
+ }
171
+ else if (query.rowId !== undefined) {
172
+ rows = adapter
173
+ .prepare('SELECT * FROM commitments WHERE row_id = ?')
174
+ .all(query.rowId);
175
+ }
176
+ else {
177
+ // One extra row decides whether another page exists without a second count.
178
+ rows = adapter
179
+ .prepare('SELECT * FROM commitments WHERE row_id > ? ORDER BY row_id ASC LIMIT ?')
180
+ .all(afterTaskId, limit + 1);
181
+ total = adapter.prepare('SELECT COUNT(*) AS n FROM commitments').get().n;
182
+ }
183
+ const hasMore = query.commitmentId === undefined && query.rowId === undefined ? rows.length > limit : false;
184
+ const pageRows = hasMore ? rows.slice(0, limit) : rows;
185
+ const items = [];
186
+ let scopeHidden = 0;
187
+ for (const row of pageRows) {
188
+ if (!recordVisible(adapter, row.head_record_id, admitted)) {
189
+ scopeHidden += 1;
190
+ continue;
191
+ }
192
+ const assignments = adapter
193
+ .prepare(asOf === null
194
+ ? `SELECT assignment.*, judgment.event_datetime AS judgment_event_datetime
195
+ FROM commitment_assignments assignment
196
+ JOIN decisions judgment ON judgment.id = assignment.record_id
197
+ WHERE assignment.commitment_id = ? ORDER BY assignment.revision ASC`
198
+ : `SELECT assignment.*, judgment.event_datetime AS judgment_event_datetime FROM commitment_assignments assignment
199
+ JOIN decisions judgment ON judgment.id = assignment.record_id
200
+ WHERE assignment.commitment_id = ?
201
+ AND COALESCE(assignment.applies_from, judgment.event_datetime, assignment.created_at) <= ?
202
+ ORDER BY assignment.revision ASC`)
203
+ .all(...(asOf === null ? [row.commitment_id] : [row.commitment_id, asOf]));
204
+ if (assignments.length === 0) {
205
+ // Bounded away entirely: the commitment had not been created at `asOf`.
206
+ continue;
207
+ }
208
+ const revisions = assignments.map((assignment) => ({
209
+ revision: assignment.revision,
210
+ operation: assignment.operation,
211
+ recordRef: { kind: 'memory', id: assignment.record_id },
212
+ set: parsePatch(assignment.set_json, 'set_json'),
213
+ clear: parseClear(assignment.clear_json),
214
+ eventDatetime: assignment.applies_from ?? assignment.judgment_event_datetime ?? null,
215
+ createdAt: assignment.created_at,
216
+ }));
217
+ const head = revisions[revisions.length - 1];
218
+ items.push({
219
+ commitmentId: row.commitment_id,
220
+ rowId: row.row_id,
221
+ revision: head.revision,
222
+ latestJudgmentRef: head.recordRef,
223
+ values: foldAssignments(revisions),
224
+ withdrawn: revisions.some((revision) => revision.operation === 'withdraw'),
225
+ basis: revisions.map((revision) => revision.recordRef),
226
+ createdAt: row.created_at,
227
+ updatedAt: asOf === null ? row.updated_at : (head.eventDatetime ?? head.createdAt),
228
+ ...(wantsHistory ? { history: revisions } : {}),
229
+ ...(wantsChain ? { chain: buildChain(adapter, revisions, admitted) } : {}),
230
+ });
231
+ }
232
+ if (hasMore) {
233
+ reasons.push('more commitments follow this page');
234
+ }
235
+ if (scopeHidden > 0) {
236
+ // Named, never silent: a page short by rows the caller cannot read is a
237
+ // different answer from a page that is short because there is no more work.
238
+ reasons.push(`${scopeHidden} commitment(s) outside the caller's scopes`);
239
+ }
240
+ if (asOf !== null) {
241
+ reasons.push(`bounded to revisions effective at or before ${asOf}`);
242
+ }
243
+ return {
244
+ items,
245
+ nextCursor: hasMore ? String(pageRows[pageRows.length - 1].row_id) : null,
246
+ coverage: {
247
+ returned: items.length,
248
+ total,
249
+ complete: !hasMore && scopeHidden === 0,
250
+ reasons,
251
+ },
252
+ };
253
+ }
254
+ /**
255
+ * The record half of a work command, with absent fields omitted rather than set
256
+ * to `undefined`.
257
+ *
258
+ * The command payload is canonicalized and hashed into `command_bindings`, and
259
+ * the canonicalizer rejects an explicit `undefined` - correctly, since a key
260
+ * present with no value and a key absent are different payloads and must not
261
+ * hash alike.
262
+ */
263
+ function recordFields(command) {
264
+ return {
265
+ commandId: command.commandId,
266
+ ...(command.modelRunId === undefined ? {} : { modelRunId: command.modelRunId }),
267
+ topic: command.topic,
268
+ summary: command.summary,
269
+ recordKind: 'commitment',
270
+ ...(command.reasoning === undefined ? {} : { reasoning: command.reasoning }),
271
+ ...(command.scopes === undefined ? {} : { scopes: command.scopes }),
272
+ ...(command.sourceRefs === undefined ? {} : { sourceRefs: command.sourceRefs }),
273
+ ...(command.links === undefined ? {} : { links: command.links }),
274
+ ...(command.eventDatetime === undefined ? {} : { eventDatetime: command.eventDatetime }),
275
+ ...(command.recordedAt === undefined ? {} : { recordedAt: command.recordedAt }),
276
+ ...(command.event === undefined ? {} : { event: command.event }),
277
+ };
278
+ }
279
+ function requireWorkReceipt(receipt) {
280
+ if (!receipt.work) {
281
+ // appendJudgment writes the commitment inside the same transaction as the
282
+ // record, so a receipt without one means the command was not a commitment.
283
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'The judgment carried no commitment receipt');
284
+ }
285
+ return {
286
+ commitmentId: receipt.work.commitmentId,
287
+ revision: receipt.work.revision,
288
+ recordRef: { kind: 'memory', id: receipt.recordId },
289
+ receipt,
290
+ };
291
+ }
292
+ /**
293
+ * Commit new owner work.
294
+ *
295
+ * The work and the record that states it commit together: `appendJudgment` owns
296
+ * the transaction, and this is the vocabulary in front of it. A caller that
297
+ * wrote a task row here and a record there is the split this replaces.
298
+ */
299
+ async function createWork(command, access, options) {
300
+ (0, work_dates_js_1.assertWorkPatchValues)(command.set);
301
+ const receipt = await (0, judgments_js_1.appendJudgment)({
302
+ ...recordFields(command),
303
+ work: {
304
+ operation: 'create',
305
+ set: command.set,
306
+ ...(command.imported === undefined ? {} : { imported: command.imported }),
307
+ },
308
+ }, access, options);
309
+ return requireWorkReceipt(receipt);
310
+ }
311
+ /**
312
+ * Revise owner work at an expected revision.
313
+ *
314
+ * The revision is the caller's claim about what it read. A concurrent write
315
+ * moves it and this fails loudly rather than overwriting what the caller never
316
+ * saw - the same compare-and-set the ledger it replaces performed.
317
+ */
318
+ async function reviseWork(command, access, options) {
319
+ const statesNothing = command.set === undefined &&
320
+ (command.clear === undefined || command.clear.length === 0) &&
321
+ (command.links === undefined || command.links.length === 0);
322
+ if (statesNothing) {
323
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'A revision must set, clear, or link at least one field');
324
+ }
325
+ if (command.set !== undefined) {
326
+ (0, work_dates_js_1.assertWorkPatchValues)(command.set);
327
+ }
328
+ // A revision is the caller's claim about what it read; a commitment it cannot
329
+ // see is one it cannot name. The read gate answers 'unavailable' rather than
330
+ // 'denied' so an outside-scope id probes the same silence as a wrong one.
331
+ if (readWork(options.adapter, { commitmentId: command.commitmentId }, access).items.length === 0) {
332
+ throw new judgments_js_1.JudgmentError('REFERENCE_NOT_FOUND', `Commitment is unavailable: ${command.commitmentId}`);
333
+ }
334
+ const receipt = await (0, judgments_js_1.appendJudgment)({
335
+ ...recordFields(command),
336
+ work: {
337
+ operation: 'revise',
338
+ commitmentId: command.commitmentId,
339
+ ...(command.expectedRevision === undefined
340
+ ? {}
341
+ : { expectedRevision: command.expectedRevision }),
342
+ ...(command.set === undefined ? {} : { set: command.set }),
343
+ ...(command.clear === undefined ? {} : { clear: command.clear }),
344
+ },
345
+ }, access, options);
346
+ return requireWorkReceipt(receipt);
347
+ }
348
+ /**
349
+ * Withdraw owner work.
350
+ *
351
+ * Withdrawal is a revision like any other: the values stay readable and the
352
+ * commitment is marked. Nothing is deleted, so a withdrawn commitment can still
353
+ * answer what it held and who withdrew it.
354
+ */
355
+ async function withdrawWork(command, access, options) {
356
+ // Same gate as a revision: withdrawal is a claim about what the caller read.
357
+ if (readWork(options.adapter, { commitmentId: command.commitmentId }, access).items.length === 0) {
358
+ throw new judgments_js_1.JudgmentError('REFERENCE_NOT_FOUND', `Commitment is unavailable: ${command.commitmentId}`);
359
+ }
360
+ const receipt = await (0, judgments_js_1.appendJudgment)({
361
+ ...recordFields(command),
362
+ work: {
363
+ operation: 'withdraw',
364
+ commitmentId: command.commitmentId,
365
+ expectedRevision: command.expectedRevision,
366
+ },
367
+ }, access, options);
368
+ return requireWorkReceipt(receipt);
369
+ }
370
+ //# sourceMappingURL=commitments.js.map
@@ -0,0 +1,70 @@
1
+ import type { DatabaseAdapter } from '../db-manager.js';
2
+ /**
3
+ * decision_edges + link_audit_log write boundary.
4
+ *
5
+ * Every mutation of the decision-edge graph goes through this module, so
6
+ * `decision_edges` and `link_audit_log` each have exactly one writing module
7
+ * inside `knowledge/` (the sibling judgments.ts owns the judgment-command
8
+ * edge insert). Each function performs the edge change and its audit row
9
+ * inside ONE adapter transaction - a link write and its audit row commit or
10
+ * fail together.
11
+ */
12
+ type EdgeWriter = Pick<DatabaseAdapter, 'prepare' | 'transaction'>;
13
+ export interface DecisionEdgeKey {
14
+ fromId: string;
15
+ toId: string;
16
+ relationship: string;
17
+ }
18
+ export interface DecisionEdgeRow extends DecisionEdgeKey {
19
+ reason: string | null;
20
+ createdBy: string | null;
21
+ approvedByUser: number | null;
22
+ decisionId: string | null;
23
+ evidence: string | null;
24
+ createdAt: number | null;
25
+ }
26
+ export interface ProposedDecisionEdge extends DecisionEdgeKey {
27
+ reason: string;
28
+ decisionId: string | null;
29
+ evidence: string | null;
30
+ }
31
+ export interface DecisionEdgeDeleteFailure {
32
+ link: string;
33
+ error: string;
34
+ }
35
+ /**
36
+ * Insert-or-replace one decision edge row with explicit governance columns.
37
+ * Used by the public createEdge API (createdBy 'llm', approvedByUser 1) and by
38
+ * the backup-restore path (columns replayed from the backup file).
39
+ */
40
+ export declare function upsertDecisionEdge(adapter: EdgeWriter, edge: DecisionEdgeRow): void;
41
+ /**
42
+ * Record a proposed edge pending user approval, plus its 'proposed' audit row.
43
+ */
44
+ export declare function proposeDecisionEdge(adapter: EdgeWriter, edge: ProposedDecisionEdge): void;
45
+ /**
46
+ * Approve a pending edge, plus its 'approved' audit row.
47
+ */
48
+ export declare function approveDecisionEdge(adapter: EdgeWriter, key: DecisionEdgeKey): void;
49
+ /**
50
+ * Reject a proposed edge: the 'rejected' audit row is written before the edge
51
+ * is deleted, in the same transaction.
52
+ */
53
+ export declare function rejectDecisionEdge(adapter: EdgeWriter, key: DecisionEdgeKey, reason: string): void;
54
+ /**
55
+ * Remove the auto-generated edge population (created_by='user' with no
56
+ * proposal context) and record one 'deprecated' audit row per removed link.
57
+ * `links` is the already-scanned target set; it only feeds the audit rows.
58
+ */
59
+ export declare function deprecateAutoDecisionEdges(adapter: EdgeWriter, links: readonly DecisionEdgeKey[], reason: string): void;
60
+ /**
61
+ * Delete one batch of edges, writing a 'deprecated' audit row for each. A
62
+ * per-link failure is collected and the batch continues, matching the cleanup
63
+ * tool's accounting; a failure of the batch itself throws to the caller.
64
+ */
65
+ export declare function deleteDecisionEdgesWithAudit(adapter: EdgeWriter, links: readonly DecisionEdgeKey[], reason: string): {
66
+ deleted: number;
67
+ failures: DecisionEdgeDeleteFailure[];
68
+ };
69
+ export {};
70
+ //# sourceMappingURL=decision-edges.d.ts.map
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.upsertDecisionEdge = upsertDecisionEdge;
4
+ exports.proposeDecisionEdge = proposeDecisionEdge;
5
+ exports.approveDecisionEdge = approveDecisionEdge;
6
+ exports.rejectDecisionEdge = rejectDecisionEdge;
7
+ exports.deprecateAutoDecisionEdges = deprecateAutoDecisionEdges;
8
+ exports.deleteDecisionEdgesWithAudit = deleteDecisionEdgesWithAudit;
9
+ /**
10
+ * Insert-or-replace one decision edge row with explicit governance columns.
11
+ * Used by the public createEdge API (createdBy 'llm', approvedByUser 1) and by
12
+ * the backup-restore path (columns replayed from the backup file).
13
+ */
14
+ function upsertDecisionEdge(adapter, edge) {
15
+ adapter
16
+ .prepare(`INSERT OR REPLACE INTO decision_edges
17
+ (from_id, to_id, relationship, reason, created_by, approved_by_user, decision_id, evidence, created_at)
18
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
19
+ .run(edge.fromId, edge.toId, edge.relationship, edge.reason, edge.createdBy, edge.approvedByUser, edge.decisionId, edge.evidence, edge.createdAt);
20
+ }
21
+ /**
22
+ * Record a proposed edge pending user approval, plus its 'proposed' audit row.
23
+ */
24
+ function proposeDecisionEdge(adapter, edge) {
25
+ adapter.transaction(() => {
26
+ adapter
27
+ .prepare(`INSERT INTO decision_edges
28
+ (from_id, to_id, relationship, reason, created_by, approved_by_user, decision_id, evidence, created_at)
29
+ VALUES (?, ?, ?, ?, 'llm', 0, ?, ?, ?)`)
30
+ .run(edge.fromId, edge.toId, edge.relationship, edge.reason, edge.decisionId, edge.evidence, Date.now());
31
+ adapter
32
+ .prepare(`INSERT INTO link_audit_log (from_id, to_id, relationship, action, actor, reason, created_at)
33
+ VALUES (?, ?, ?, 'proposed', 'llm', ?, ?)`)
34
+ .run(edge.fromId, edge.toId, edge.relationship, edge.reason, Date.now());
35
+ });
36
+ }
37
+ /**
38
+ * Approve a pending edge, plus its 'approved' audit row.
39
+ */
40
+ function approveDecisionEdge(adapter, key) {
41
+ adapter.transaction(() => {
42
+ adapter
43
+ .prepare(`UPDATE decision_edges
44
+ SET approved_by_user = 1, approved_at = ?
45
+ WHERE from_id = ? AND to_id = ? AND relationship = ?`)
46
+ .run(Date.now(), key.fromId, key.toId, key.relationship);
47
+ adapter
48
+ .prepare(`INSERT INTO link_audit_log (from_id, to_id, relationship, action, actor, created_at)
49
+ VALUES (?, ?, ?, 'approved', 'user', ?)`)
50
+ .run(key.fromId, key.toId, key.relationship, Date.now());
51
+ });
52
+ }
53
+ /**
54
+ * Reject a proposed edge: the 'rejected' audit row is written before the edge
55
+ * is deleted, in the same transaction.
56
+ */
57
+ function rejectDecisionEdge(adapter, key, reason) {
58
+ adapter.transaction(() => {
59
+ adapter
60
+ .prepare(`INSERT INTO link_audit_log (from_id, to_id, relationship, action, actor, reason, created_at)
61
+ VALUES (?, ?, ?, 'rejected', 'user', ?, ?)`)
62
+ .run(key.fromId, key.toId, key.relationship, reason, Date.now());
63
+ adapter
64
+ .prepare(`DELETE FROM decision_edges
65
+ WHERE from_id = ? AND to_id = ? AND relationship = ?`)
66
+ .run(key.fromId, key.toId, key.relationship);
67
+ });
68
+ }
69
+ /**
70
+ * Remove the auto-generated edge population (created_by='user' with no
71
+ * proposal context) and record one 'deprecated' audit row per removed link.
72
+ * `links` is the already-scanned target set; it only feeds the audit rows.
73
+ */
74
+ function deprecateAutoDecisionEdges(adapter, links, reason) {
75
+ adapter.transaction(() => {
76
+ adapter
77
+ .prepare(`DELETE FROM decision_edges WHERE created_by = 'user' AND decision_id IS NULL`)
78
+ .run();
79
+ const auditStmt = adapter.prepare(`INSERT INTO link_audit_log (from_id, to_id, relationship, action, actor, reason, created_at)
80
+ VALUES (?, ?, ?, 'deprecated', 'system', ?, ?)`);
81
+ const timestamp = Date.now();
82
+ for (const link of links) {
83
+ auditStmt.run(link.fromId, link.toId, link.relationship, reason, timestamp);
84
+ }
85
+ });
86
+ }
87
+ /**
88
+ * Delete one batch of edges, writing a 'deprecated' audit row for each. A
89
+ * per-link failure is collected and the batch continues, matching the cleanup
90
+ * tool's accounting; a failure of the batch itself throws to the caller.
91
+ */
92
+ function deleteDecisionEdgesWithAudit(adapter, links, reason) {
93
+ const deleteStmt = adapter.prepare(`DELETE FROM decision_edges
94
+ WHERE from_id = ? AND to_id = ? AND relationship = ?`);
95
+ const auditStmt = adapter.prepare(`INSERT INTO link_audit_log (from_id, to_id, relationship, action, actor, reason, created_at)
96
+ VALUES (?, ?, ?, 'deprecated', 'system', ?, ?)`);
97
+ let deleted = 0;
98
+ const failures = [];
99
+ const processLinks = () => {
100
+ for (const link of links) {
101
+ try {
102
+ deleteStmt.run(link.fromId, link.toId, link.relationship);
103
+ auditStmt.run(link.fromId, link.toId, link.relationship, reason, Date.now());
104
+ deleted++;
105
+ }
106
+ catch (error) {
107
+ failures.push({
108
+ link: `${link.fromId}->${link.toId}`,
109
+ error: error instanceof Error ? error.message : String(error),
110
+ });
111
+ }
112
+ }
113
+ };
114
+ // Use transaction if available, otherwise run directly
115
+ if (adapter.transaction) {
116
+ adapter.transaction(processLinks);
117
+ }
118
+ else {
119
+ processLinks();
120
+ }
121
+ return { deleted, failures };
122
+ }
123
+ //# sourceMappingURL=decision-edges.js.map