@jungjaehoon/mama-core 2.4.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +76 -239
  2. package/db/migrations/030-case-first-memory-substrate.sql +13 -98
  3. package/db/migrations/034-add-connector-event-scope-columns.sql +9 -13
  4. package/db/migrations/039-add-connector-event-operator-ingest-seq.sql +9 -95
  5. package/db/migrations/062-refresh-connector-event-sequences.sql +9 -113
  6. package/db/migrations/063-refresh-legacy-connector-event-updates.sql +9 -32
  7. package/db/migrations/067-add-connector-event-source-entity-id.sql +9 -13
  8. package/db/migrations/069-create-registry-nodes.sql +52 -0
  9. package/db/migrations/070-record-identity.sql +35 -0
  10. package/db/migrations/071-service-operation-origins.sql +187 -0
  11. package/db/migrations/072-observation-versions.sql +29 -0
  12. package/db/migrations/073-registry-corrections.sql +45 -0
  13. package/db/migrations/074-work-graph-ref-kinds.sql +39 -0
  14. package/db/migrations/075-agent-judgments.sql +58 -0
  15. package/db/migrations/076-scoped-checkpoint-bindings.sql +15 -0
  16. package/db/migrations/077-legacy-record-kind.sql +6 -0
  17. package/db/migrations/078-source-ingest-commands.sql +18 -0
  18. package/db/migrations/079-twin-edge-relations.sql +43 -0
  19. package/db/migrations/080-restore-duration-days.sql +7 -0
  20. package/db/migrations/081-mailbox.sql +61 -0
  21. package/db/migrations/082-commitments-row-id.sql +12 -0
  22. package/db/migrations/083-observation-is-the-evidence.sql +49 -0
  23. package/db/migrations/084-scope-kind-is-not-the-cores-to-list.sql +34 -0
  24. package/db/migrations/085-a-migration-has-a-source.sql +37 -0
  25. package/db/migrations/086-the-mailbox-is-generic.sql +110 -0
  26. package/db/migrations/087-mailbox-payload.sql +5 -0
  27. package/db/migrations/088-native-input-journal.sql +14 -0
  28. package/db/migrations/089-native-turn-receipt-lookup.sql +3 -0
  29. package/db/migrations/090-model-run-native-inputs.sql +29 -0
  30. package/db/migrations/091-native-turn-results.sql +11 -0
  31. package/db/migrations/092-restore-decision-fts.sql +34 -0
  32. package/db/migrations/093-native-turn-primary-kind.sql +14 -0
  33. package/db/migrations/094-commitment-run-provenance.sql +9 -0
  34. package/db/migrations/095-model-run-native-input-identity.sql +39 -0
  35. package/db/migrations/096-drop-connector-event-index-fts.sql +9 -0
  36. package/db/migrations/097-native-input-json-validity.sql +37 -0
  37. package/db/migrations/098-workflow-memory-kind.sql +105 -0
  38. package/db/migrations/099-commitment-revision-graph.sql +2 -0
  39. package/dist/action-contracts.d.ts +212 -0
  40. package/dist/action-contracts.js +10 -0
  41. package/dist/api/catalog.d.ts +118 -0
  42. package/dist/api/catalog.js +1756 -0
  43. package/dist/api/dispatch.d.ts +76 -0
  44. package/dist/api/dispatch.js +372 -0
  45. package/dist/canonicalize.d.ts +2 -2
  46. package/dist/canonicalize.js +3 -3
  47. package/dist/client/client.d.ts +33 -0
  48. package/dist/client/client.js +123 -0
  49. package/dist/client/ipc.d.ts +81 -0
  50. package/dist/client/ipc.js +314 -0
  51. package/dist/db-adapter/base-adapter.d.ts +6 -66
  52. package/dist/db-adapter/base-adapter.js +6 -6
  53. package/dist/db-adapter/index.d.ts +5 -5
  54. package/dist/db-adapter/index.js +2 -5
  55. package/dist/db-adapter/node-sqlite-adapter.d.ts +85 -15
  56. package/dist/db-adapter/node-sqlite-adapter.js +1985 -570
  57. package/dist/db-manager.d.ts +53 -97
  58. package/dist/db-manager.js +121 -603
  59. package/dist/embedding/embedder.d.ts +132 -0
  60. package/dist/embedding/embedder.js +299 -0
  61. package/dist/identity/principal-repository.d.ts +2 -2
  62. package/dist/index.d.ts +43 -58
  63. package/dist/index.js +97 -145
  64. package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
  65. package/dist/knowledge/access.js +663 -0
  66. package/dist/knowledge/case-errors.d.ts +31 -0
  67. package/dist/knowledge/case-errors.js +40 -0
  68. package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
  69. package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
  70. package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
  71. package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
  72. package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
  73. package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
  74. package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
  75. package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
  76. package/dist/knowledge/commitment-revision-migration.d.ts +4 -0
  77. package/dist/knowledge/commitment-revision-migration.js +50 -0
  78. package/dist/knowledge/commitments.d.ts +192 -0
  79. package/dist/knowledge/commitments.js +386 -0
  80. package/dist/knowledge/decision-edges.d.ts +70 -0
  81. package/dist/knowledge/decision-edges.js +123 -0
  82. package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
  83. package/dist/knowledge/graph-query.js +1585 -0
  84. package/dist/knowledge/identity.d.ts +16 -0
  85. package/dist/knowledge/identity.js +22 -0
  86. package/dist/knowledge/index.d.ts +47 -0
  87. package/dist/knowledge/index.js +90 -0
  88. package/dist/knowledge/judgment-edge.d.ts +6 -0
  89. package/dist/knowledge/judgment-edge.js +22 -0
  90. package/dist/knowledge/judgments.d.ts +118 -0
  91. package/dist/knowledge/judgments.js +802 -0
  92. package/dist/knowledge/observations.d.ts +160 -0
  93. package/dist/knowledge/observations.js +449 -0
  94. package/dist/knowledge/question-type.d.ts +34 -0
  95. package/dist/knowledge/question-type.js +70 -0
  96. package/dist/{search → knowledge}/ranker-features.js +1 -1
  97. package/dist/{search → knowledge}/search-quality.d.ts +0 -1
  98. package/dist/knowledge/search.d.ts +38 -0
  99. package/dist/knowledge/search.js +91 -0
  100. package/dist/knowledge/source-ingest.d.ts +65 -0
  101. package/dist/knowledge/source-ingest.js +174 -0
  102. package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
  103. package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
  104. package/dist/knowledge/work-dates.d.ts +49 -0
  105. package/dist/knowledge/work-dates.js +120 -0
  106. package/dist/mama-api.d.ts +114 -778
  107. package/dist/mama-api.js +313 -2461
  108. package/dist/memory/api.d.ts +264 -24
  109. package/dist/memory/api.js +1633 -843
  110. package/dist/memory/bootstrap-builder.d.ts +2 -1
  111. package/dist/memory/bootstrap-builder.js +5 -5
  112. package/dist/memory/channel-summary-state-store.d.ts +3 -2
  113. package/dist/memory/channel-summary-state-store.js +53 -51
  114. package/dist/memory/channel-summary-store.d.ts +5 -3
  115. package/dist/memory/channel-summary-store.js +3 -8
  116. package/dist/memory/dashboard-read.d.ts +46 -0
  117. package/dist/memory/dashboard-read.js +94 -0
  118. package/dist/memory/event-store.d.ts +3 -3
  119. package/dist/memory/event-store.js +3 -10
  120. package/dist/memory/finding-store.d.ts +3 -2
  121. package/dist/memory/finding-store.js +2 -7
  122. package/dist/memory/graph-read.d.ts +52 -0
  123. package/dist/memory/graph-read.js +130 -0
  124. package/dist/memory/judgment-types.d.ts +394 -0
  125. package/dist/memory/judgment-types.js +16 -0
  126. package/dist/memory/provenance-audit.d.ts +5 -2
  127. package/dist/memory/provenance-audit.js +8 -14
  128. package/dist/memory/provenance-live.d.ts +141 -0
  129. package/dist/memory/provenance-live.js +409 -0
  130. package/dist/memory/provenance-query.d.ts +5 -4
  131. package/dist/memory/provenance-query.js +21 -29
  132. package/dist/memory/provenance-resolver.d.ts +191 -0
  133. package/dist/memory/provenance-resolver.js +155 -0
  134. package/dist/memory/provenance.d.ts +1 -11
  135. package/dist/memory/provenance.js +2 -33
  136. package/dist/memory/recall-sanitize.d.ts +55 -0
  137. package/dist/memory/recall-sanitize.js +144 -0
  138. package/dist/memory/secret-filter.d.ts +32 -0
  139. package/dist/memory/secret-filter.js +126 -0
  140. package/dist/memory/truth-store.d.ts +2 -1
  141. package/dist/memory/truth-store.js +1 -4
  142. package/dist/memory/types.d.ts +74 -24
  143. package/dist/memory/types.js +75 -5
  144. package/dist/memory/write-adapters.d.ts +98 -0
  145. package/dist/memory/write-adapters.js +242 -0
  146. package/dist/operations/owner-action-effects.d.ts +53 -0
  147. package/dist/operations/owner-action-effects.js +96 -0
  148. package/dist/provenance/source-ref.d.ts +1 -1
  149. package/dist/provenance/source-ref.js +0 -2
  150. package/dist/registry/corrections.d.ts +31 -0
  151. package/dist/registry/corrections.js +332 -0
  152. package/dist/registry/record-identity.d.ts +49 -0
  153. package/dist/registry/record-identity.js +133 -0
  154. package/dist/registry/store.d.ts +101 -0
  155. package/dist/registry/store.js +395 -0
  156. package/dist/registry/types.d.ts +28 -0
  157. package/dist/registry/types.js +5 -0
  158. package/dist/relevance-scorer.js +2 -2
  159. package/dist/runtime/agent-event-bus.d.ts +50 -0
  160. package/dist/runtime/agent-event-bus.js +101 -0
  161. package/dist/runtime/drivers/claude-cli-wrapper.d.ts +152 -0
  162. package/dist/runtime/drivers/claude-cli-wrapper.js +375 -0
  163. package/dist/runtime/drivers/claude-effort.d.ts +4 -0
  164. package/dist/runtime/drivers/claude-effort.js +16 -0
  165. package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
  166. package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
  167. package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
  168. package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
  169. package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
  170. package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
  171. package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
  172. package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
  173. package/dist/runtime/drivers/codex-home.d.ts +20 -0
  174. package/dist/runtime/drivers/codex-home.js +674 -0
  175. package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
  176. package/dist/runtime/drivers/codex-thread-registry.js +433 -0
  177. package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
  178. package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
  179. package/dist/runtime/drivers/persistent-cli-process.d.ts +425 -0
  180. package/dist/runtime/drivers/persistent-cli-process.js +1529 -0
  181. package/dist/runtime/drivers/types.d.ts +456 -0
  182. package/dist/runtime/drivers/types.js +110 -0
  183. package/dist/runtime/mailbox.d.ts +223 -0
  184. package/dist/runtime/mailbox.js +582 -0
  185. package/dist/runtime/model-run-store.d.ts +28 -0
  186. package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
  187. package/dist/{model-runs/types.d.ts → runtime/model-run-types.d.ts} +33 -4
  188. package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
  189. package/dist/runtime/native-effect-observer.d.ts +22 -0
  190. package/dist/runtime/native-effect-observer.js +103 -0
  191. package/dist/runtime/native-input-journal.d.ts +46 -0
  192. package/dist/runtime/native-input-journal.js +308 -0
  193. package/dist/runtime/native-prompt.d.ts +118 -0
  194. package/dist/runtime/native-prompt.js +496 -0
  195. package/dist/runtime/native-session.d.ts +10 -0
  196. package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
  197. package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
  198. package/dist/runtime/native-tool-trace-observer.js +65 -0
  199. package/dist/runtime/native-turn.d.ts +272 -0
  200. package/dist/runtime/native-turn.js +1041 -0
  201. package/dist/runtime/operations.d.ts +236 -0
  202. package/dist/runtime/operations.js +565 -0
  203. package/dist/runtime/post-tool-handler.d.ts +74 -0
  204. package/dist/runtime/post-tool-handler.js +137 -0
  205. package/dist/runtime/prompt-layers.d.ts +126 -0
  206. package/dist/runtime/prompt-layers.js +239 -0
  207. package/dist/runtime/runtime-process.d.ts +102 -0
  208. package/dist/runtime/runtime-process.js +206 -0
  209. package/dist/runtime/runtime.d.ts +278 -0
  210. package/dist/runtime/runtime.js +563 -0
  211. package/dist/runtime/session-pool.d.ts +176 -0
  212. package/dist/runtime/session-pool.js +369 -0
  213. package/dist/runtime/stimulus-payload.d.ts +5 -0
  214. package/dist/runtime/stimulus-payload.js +50 -0
  215. package/dist/runtime/subagent-bridge.d.ts +24 -0
  216. package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
  217. package/dist/runtime/text-completion.d.ts +22 -0
  218. package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
  219. package/dist/runtime/token-estimator.d.ts +25 -0
  220. package/dist/runtime/token-estimator.js +75 -0
  221. package/dist/runtime/tool-trace-store.d.ts +22 -0
  222. package/dist/{model-runs → runtime}/tool-trace-store.js +46 -27
  223. package/dist/runtime/trace-summary.d.ts +5 -0
  224. package/dist/runtime/trace-summary.js +74 -0
  225. package/dist/runtime/turn-text.d.ts +23 -0
  226. package/dist/runtime/turn-text.js +41 -0
  227. package/dist/storage/database.d.ts +67 -0
  228. package/dist/storage/database.js +158 -0
  229. package/package.json +20 -34
  230. package/dist/agent-graph/alias-write.d.ts +0 -3
  231. package/dist/agent-graph/alias-write.js +0 -234
  232. package/dist/agent-graph/entity-resolve.d.ts +0 -3
  233. package/dist/agent-graph/entity-resolve.js +0 -271
  234. package/dist/agent-graph/errors.d.ts +0 -4
  235. package/dist/agent-graph/errors.js +0 -11
  236. package/dist/agent-graph/graph-query.d.ts +0 -5
  237. package/dist/agent-graph/graph-query.js +0 -360
  238. package/dist/agent-graph/index.d.ts +0 -6
  239. package/dist/agent-situation/builder.d.ts +0 -8
  240. package/dist/agent-situation/builder.js +0 -239
  241. package/dist/agent-situation/cache-key.d.ts +0 -4
  242. package/dist/agent-situation/cache-key.js +0 -64
  243. package/dist/agent-situation/index.d.ts +0 -7
  244. package/dist/agent-situation/index.js +0 -28
  245. package/dist/agent-situation/packet-store.d.ts +0 -27
  246. package/dist/agent-situation/packet-store.js +0 -228
  247. package/dist/agent-situation/ranking-policy.d.ts +0 -18
  248. package/dist/agent-situation/ranking-policy.js +0 -75
  249. package/dist/agent-situation/source-readers.d.ts +0 -52
  250. package/dist/agent-situation/source-readers.js +0 -300
  251. package/dist/agent-situation/types.d.ts +0 -195
  252. package/dist/cases/wiki-page-index.d.ts +0 -37
  253. package/dist/cases/wiki-page-index.js +0 -201
  254. package/dist/config-loader.d.ts +0 -68
  255. package/dist/config-loader.js +0 -239
  256. package/dist/connectors/event-index.d.ts +0 -24
  257. package/dist/connectors/event-index.js +0 -245
  258. package/dist/connectors/raw-query.d.ts +0 -40
  259. package/dist/connectors/raw-query.js +0 -412
  260. package/dist/connectors/types.d.ts +0 -117
  261. package/dist/connectors/types.js +0 -3
  262. package/dist/context-compile/boundary-defaults.d.ts +0 -12
  263. package/dist/context-compile/boundary-defaults.js +0 -105
  264. package/dist/context-compile/channel-grant.js +0 -66
  265. package/dist/context-compile/compiler-policy.d.ts +0 -39
  266. package/dist/context-compile/compiler-policy.js +0 -147
  267. package/dist/context-compile/compiler.d.ts +0 -18
  268. package/dist/context-compile/compiler.js +0 -404
  269. package/dist/context-compile/index.d.ts +0 -10
  270. package/dist/context-compile/index.js +0 -26
  271. package/dist/context-compile/packet-store.d.ts +0 -8
  272. package/dist/context-compile/packet-store.js +0 -239
  273. package/dist/context-compile/ref.d.ts +0 -7
  274. package/dist/context-compile/ref.js +0 -102
  275. package/dist/context-compile/source-readers.d.ts +0 -70
  276. package/dist/context-compile/source-readers.js +0 -840
  277. package/dist/context-compile/types.d.ts +0 -155
  278. package/dist/context-compile/types.js +0 -11
  279. package/dist/context-compile/visibility.d.ts +0 -21
  280. package/dist/context-compile/visibility.js +0 -224
  281. package/dist/decision-tracker.d.ts +0 -206
  282. package/dist/decision-tracker.js +0 -481
  283. package/dist/edges/ref-validation.d.ts +0 -7
  284. package/dist/edges/ref-validation.js +0 -321
  285. package/dist/edges/store.d.ts +0 -8
  286. package/dist/edges/store.js +0 -129
  287. package/dist/embedding-client.d.ts +0 -28
  288. package/dist/embedding-client.js +0 -53
  289. package/dist/embedding-server/index.d.ts +0 -67
  290. package/dist/embedding-server/index.js +0 -405
  291. package/dist/embedding-server/mobile/auth.d.ts +0 -44
  292. package/dist/embedding-server/mobile/auth.js +0 -150
  293. package/dist/embedding-server/mobile/daemon.d.ts +0 -129
  294. package/dist/embedding-server/mobile/daemon.js +0 -313
  295. package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
  296. package/dist/embedding-server/mobile/output-parser.js +0 -241
  297. package/dist/embedding-server/mobile/session-api.d.ts +0 -57
  298. package/dist/embedding-server/mobile/session-api.js +0 -261
  299. package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
  300. package/dist/embedding-server/mobile/session-manager.js +0 -378
  301. package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
  302. package/dist/embedding-server/mobile/websocket-handler.js +0 -486
  303. package/dist/embeddings.d.ts +0 -68
  304. package/dist/embeddings.js +0 -244
  305. package/dist/entities/audit-metrics.d.ts +0 -68
  306. package/dist/entities/audit-metrics.js +0 -124
  307. package/dist/entities/candidate-generator.d.ts +0 -8
  308. package/dist/entities/candidate-generator.js +0 -24
  309. package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
  310. package/dist/entities/entity-linked-decision-counts.js +0 -29
  311. package/dist/entities/entity-list.d.ts +0 -22
  312. package/dist/entities/entity-list.js +0 -3
  313. package/dist/entities/entity-orphan-list.d.ts +0 -17
  314. package/dist/entities/entity-orphan-list.js +0 -3
  315. package/dist/entities/entity-search.d.ts +0 -20
  316. package/dist/entities/entity-search.js +0 -3
  317. package/dist/entities/errors.d.ts +0 -55
  318. package/dist/entities/errors.js +0 -100
  319. package/dist/entities/lineage-store.d.ts +0 -28
  320. package/dist/entities/lineage-store.js +0 -204
  321. package/dist/entities/normalization.d.ts +0 -14
  322. package/dist/entities/normalization.js +0 -63
  323. package/dist/entities/policy-store.d.ts +0 -8
  324. package/dist/entities/policy-store.js +0 -75
  325. package/dist/entities/policy-types.d.ts +0 -72
  326. package/dist/entities/policy-types.js +0 -59
  327. package/dist/entities/projection.d.ts +0 -8
  328. package/dist/entities/projection.js +0 -82
  329. package/dist/entities/provenance-query.d.ts +0 -32
  330. package/dist/entities/provenance-query.js +0 -3
  331. package/dist/entities/read-identity.d.ts +0 -31
  332. package/dist/entities/read-identity.js +0 -264
  333. package/dist/entities/recall-bridge.d.ts +0 -5
  334. package/dist/entities/recall-bridge.js +0 -171
  335. package/dist/entities/resolution-engine.d.ts +0 -8
  336. package/dist/entities/resolution-engine.js +0 -3
  337. package/dist/entities/rollback-preview.d.ts +0 -35
  338. package/dist/entities/rollback-preview.js +0 -3
  339. package/dist/entities/source-locator.d.ts +0 -3
  340. package/dist/entities/source-locator.js +0 -32
  341. package/dist/entities/store.d.ts +0 -69
  342. package/dist/entities/store.js +0 -544
  343. package/dist/entities/types.d.ts +0 -166
  344. package/dist/entities/types.js +0 -30
  345. package/dist/memory/extraction-prompt.d.ts +0 -4
  346. package/dist/memory/extraction-prompt.js +0 -89
  347. package/dist/memory/scope-backfill.d.ts +0 -14
  348. package/dist/memory/scope-backfill.js +0 -3
  349. package/dist/memory/scope-store.d.ts +0 -4
  350. package/dist/memory/scope-store.js +0 -9
  351. package/dist/memory-store.d.ts +0 -87
  352. package/dist/memory-store.js +0 -78
  353. package/dist/model-runs/store.d.ts +0 -13
  354. package/dist/model-runs/tool-trace-store.d.ts +0 -8
  355. package/dist/notification-manager.d.ts +0 -7
  356. package/dist/notification-manager.js +0 -12
  357. package/dist/outcome-tracker.d.ts +0 -151
  358. package/dist/outcome-tracker.js +0 -271
  359. package/dist/query-intent.d.ts +0 -23
  360. package/dist/query-intent.js +0 -114
  361. package/dist/runtime/trusted-provenance.d.ts +0 -3
  362. package/dist/runtime/trusted-provenance.js +0 -6
  363. package/dist/search/question-type.d.ts +0 -5
  364. package/dist/search/question-type.js +0 -41
  365. package/dist/test-utils.d.ts +0 -80
  366. package/dist/test-utils.js +0 -218
  367. package/dist/tier-validator.d.ts +0 -43
  368. package/dist/tier-validator.js +0 -159
  369. package/dist/time-formatter.d.ts +0 -25
  370. package/dist/time-formatter.js +0 -93
  371. /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
  372. /package/dist/{search → knowledge}/feedback-store.js +0 -0
  373. /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
  374. /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
  375. /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
  376. /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
  377. /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
  378. /package/dist/{search → knowledge}/search-quality.js +0 -0
@@ -0,0 +1,1756 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.recordLinkSchema = exports.scopeRefSchema = exports.UnknownActionError = void 0;
4
+ exports.createCatalog = createCatalog;
5
+ exports.coreActionRegistrations = coreActionRegistrations;
6
+ const judgments_js_1 = require("../knowledge/judgments.js");
7
+ const api_js_1 = require("../memory/api.js");
8
+ const provenance_live_js_1 = require("../memory/provenance-live.js");
9
+ const dashboard_read_js_1 = require("../memory/dashboard-read.js");
10
+ const graph_read_js_1 = require("../memory/graph-read.js");
11
+ const recall_sanitize_js_1 = require("../memory/recall-sanitize.js");
12
+ const source_ingest_js_1 = require("../knowledge/source-ingest.js");
13
+ const store_js_1 = require("../registry/store.js");
14
+ const api_js_2 = require("../memory/api.js");
15
+ const types_js_1 = require("../memory/types.js");
16
+ const twin_edge_types_js_1 = require("../knowledge/twin-edge-types.js");
17
+ const operations_js_1 = require("../runtime/operations.js");
18
+ const tool_trace_store_js_1 = require("../runtime/tool-trace-store.js");
19
+ class UnknownActionError extends Error {
20
+ code = 'unknown_action';
21
+ constructor(name) {
22
+ super(`Unknown action: ${name}`);
23
+ this.name = 'UnknownActionError';
24
+ }
25
+ }
26
+ exports.UnknownActionError = UnknownActionError;
27
+ function createCatalog(registrations, aliases = {}) {
28
+ const entries = new Map();
29
+ for (const registration of registrations) {
30
+ const name = registration.contract.name;
31
+ if (entries.has(name)) {
32
+ throw new Error(`Duplicate action registration: ${name}`);
33
+ }
34
+ entries.set(name, registration);
35
+ }
36
+ const canonicalName = (name) => aliases[name] ?? name;
37
+ const entry = (name) => {
38
+ const found = entries.get(canonicalName(name));
39
+ if (!found) {
40
+ throw new UnknownActionError(name);
41
+ }
42
+ return found;
43
+ };
44
+ return {
45
+ list: () => [...entries.values()].map((registration) => registration.contract),
46
+ describe: (name) => entry(name).contract,
47
+ entry,
48
+ };
49
+ }
50
+ const refSchema = {
51
+ type: 'object',
52
+ required: ['kind', 'id'],
53
+ additionalProperties: false,
54
+ properties: {
55
+ kind: {
56
+ type: 'string',
57
+ enum: twin_edge_types_js_1.TWIN_REF_KINDS,
58
+ description: 'Referenced graph kind, e.g. "memory" (a work item\'s revision record) or "registry".',
59
+ },
60
+ id: {
61
+ type: 'string',
62
+ minLength: 1,
63
+ description: 'Stable id within the kind, e.g. "work_123".',
64
+ },
65
+ },
66
+ };
67
+ const msRangeSchema = {
68
+ type: 'object',
69
+ additionalProperties: false,
70
+ properties: {
71
+ start: {
72
+ type: 'number',
73
+ description: 'Inclusive epoch-millisecond start, e.g. 1760000000000.',
74
+ },
75
+ end: {
76
+ type: 'number',
77
+ description: 'Inclusive epoch-millisecond end, e.g. 1760086400000.',
78
+ },
79
+ },
80
+ };
81
+ exports.scopeRefSchema = {
82
+ type: 'object',
83
+ required: ['kind', 'id'],
84
+ additionalProperties: false,
85
+ properties: {
86
+ kind: {
87
+ type: 'string',
88
+ enum: types_js_1.MEMORY_SCOPE_KINDS,
89
+ description: 'Scope kind, e.g. "project".',
90
+ },
91
+ id: { type: 'string', minLength: 1, description: 'Scope identifier, e.g. "project_123".' },
92
+ },
93
+ };
94
+ exports.recordLinkSchema = {
95
+ type: 'object',
96
+ required: ['relation', 'target'],
97
+ additionalProperties: false,
98
+ properties: {
99
+ relation: {
100
+ type: 'string',
101
+ description: 'Relationship to the target, e.g. "derived_from".',
102
+ enum: [
103
+ 'supersedes',
104
+ 'refines',
105
+ 'contradicts',
106
+ 'mentions',
107
+ 'derived_from',
108
+ 'builds_on',
109
+ 'debates',
110
+ 'synthesizes',
111
+ 'blocks',
112
+ 'next_action_for',
113
+ 'case_member',
114
+ 'amends',
115
+ ],
116
+ },
117
+ target: {
118
+ ...refSchema,
119
+ description: 'Target graph reference, e.g. {"kind":"observation","id":"obs_123"}.',
120
+ },
121
+ attrs: {
122
+ type: 'object',
123
+ description: 'Optional relationship metadata, e.g. {"confidence":0.8}.',
124
+ },
125
+ },
126
+ };
127
+ /** Fields every work command shares; required-ness lives on each action. */
128
+ /** The lifecycle fields a reclassification states; callers may not repeat them. */
129
+ function requiredOperationId(context, action) {
130
+ if (typeof context.operationId !== 'string' || context.operationId.trim().length === 0) {
131
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', `${action} requires operationId: it becomes the command id, and a retry reuses it.`);
132
+ }
133
+ return context.operationId;
134
+ }
135
+ /** Topic/summary a revision needs when the caller did not restate them. */
136
+ const workGraphQuerySchema = {
137
+ type: 'object',
138
+ required: ['view'],
139
+ additionalProperties: false,
140
+ properties: {
141
+ view: {
142
+ type: 'string',
143
+ enum: ['overview', 'browse', 'neighbors', 'timeline', 'paths', 'detail'],
144
+ description: 'Graph view to execute, e.g. "neighbors".',
145
+ },
146
+ seeds: {
147
+ type: 'array',
148
+ description: 'Starting graph references, e.g. [{"kind":"memory","id":"judgment_123"}].',
149
+ items: refSchema,
150
+ },
151
+ search: {
152
+ type: 'object',
153
+ required: ['text'],
154
+ additionalProperties: false,
155
+ description: 'Optional registered-name search, e.g. {"text":"release"}.',
156
+ properties: {
157
+ text: {
158
+ type: 'string',
159
+ minLength: 1,
160
+ description: 'Name text to resolve, e.g. "release".',
161
+ },
162
+ kinds: {
163
+ type: 'array',
164
+ description: 'Kinds to restrict the search, e.g. ["registry"].',
165
+ items: { type: 'string', enum: twin_edge_types_js_1.TWIN_REF_KINDS },
166
+ },
167
+ },
168
+ },
169
+ section: {
170
+ type: 'string',
171
+ enum: ['summary', 'reasoning', 'payload'],
172
+ description: 'Detail section to expand, e.g. "summary".',
173
+ },
174
+ textOffset: {
175
+ type: 'integer',
176
+ minimum: 0,
177
+ description: 'Character offset for detail text, e.g. 0.',
178
+ },
179
+ textLimit: {
180
+ type: 'integer',
181
+ minimum: 1,
182
+ description: 'Maximum detail characters, e.g. 4000.',
183
+ },
184
+ from: {
185
+ ...refSchema,
186
+ description: 'Path/timeline start reference, e.g. {"kind":"memory","id":"judgment_123"}.',
187
+ },
188
+ to: {
189
+ ...refSchema,
190
+ description: 'Path/timeline end reference, e.g. {"kind":"memory","id":"mem_123"}.',
191
+ },
192
+ maxDepth: {
193
+ type: 'integer',
194
+ minimum: 0,
195
+ description: 'Maximum graph traversal depth, e.g. 2.',
196
+ },
197
+ direction: {
198
+ type: 'string',
199
+ enum: ['in', 'out', 'both'],
200
+ description: 'Edge direction, e.g. "both".',
201
+ },
202
+ relations: {
203
+ type: 'array',
204
+ description: 'Relationship names to include, e.g. ["derived_from"].',
205
+ items: { type: 'string', minLength: 1 },
206
+ },
207
+ history: {
208
+ type: 'string',
209
+ enum: ['current', 'all'],
210
+ description: 'History mode, e.g. "current".',
211
+ },
212
+ eventRange: {
213
+ ...msRangeSchema,
214
+ description: 'Occurrence-time window, e.g. {"start":1760000000000}.',
215
+ },
216
+ recordedRange: {
217
+ ...msRangeSchema,
218
+ description: 'Recorded-time window, e.g. {"end":1760086400000}.',
219
+ },
220
+ asOf: {
221
+ type: 'number',
222
+ description: 'Read state at epoch milliseconds, e.g. 1760000000000.',
223
+ },
224
+ limit: { type: 'integer', minimum: 1, description: 'Maximum returned graph rows, e.g. 25.' },
225
+ cursor: {
226
+ type: 'string',
227
+ minLength: 1,
228
+ description: 'Opaque page cursor, e.g. "cursor_25".',
229
+ },
230
+ },
231
+ };
232
+ /** Read knobs every work read shares; show adds the identity filters. */
233
+ const workReadFields = {
234
+ asOf: {
235
+ type: 'integer',
236
+ minimum: 0,
237
+ description: 'Read work as of epoch milliseconds, e.g. 1760000000000.',
238
+ },
239
+ history: {
240
+ type: 'string',
241
+ enum: ['current', 'all'],
242
+ description: 'Revision view, e.g. "all".',
243
+ },
244
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Maximum work rows, e.g. 25.' },
245
+ cursor: {
246
+ type: 'string',
247
+ minLength: 1,
248
+ description: 'Opaque work page cursor, e.g. "cursor_25".',
249
+ },
250
+ };
251
+ const workListSchema = {
252
+ type: 'object',
253
+ additionalProperties: false,
254
+ properties: workReadFields,
255
+ };
256
+ const workShowSchema = {
257
+ type: 'object',
258
+ additionalProperties: false,
259
+ properties: {
260
+ ...workReadFields,
261
+ commitmentId: {
262
+ type: 'string',
263
+ minLength: 1,
264
+ description: 'Stable commitmentId citation handle, e.g. "commitment_123".',
265
+ },
266
+ rowId: {
267
+ type: 'integer',
268
+ minimum: 0,
269
+ description: 'Legacy numeric commitment row id, e.g. 123.',
270
+ },
271
+ },
272
+ };
273
+ const observationEvidenceSchema = {
274
+ type: 'object',
275
+ required: ['kind', 'id'],
276
+ additionalProperties: false,
277
+ properties: {
278
+ kind: { const: 'observation', description: 'Evidence kind; use "observation".' },
279
+ id: {
280
+ type: 'string',
281
+ minLength: 1,
282
+ description: 'Stable observationRef citation handle, e.g. "obs_123".',
283
+ },
284
+ },
285
+ };
286
+ /** One endpoint reassignment — by existing node id (or null to release) or by a new child's clientKey. */
287
+ const identityAssignmentSchema = {
288
+ oneOf: [
289
+ {
290
+ type: 'object',
291
+ required: ['edgeId', 'endpoint', 'targetNodeId'],
292
+ additionalProperties: false,
293
+ properties: {
294
+ edgeId: { type: 'string', minLength: 1 },
295
+ endpoint: { type: 'string', enum: ['from', 'to'] },
296
+ targetNodeId: { oneOf: [{ type: 'string', minLength: 1 }, { type: 'null' }] },
297
+ },
298
+ },
299
+ {
300
+ type: 'object',
301
+ required: ['edgeId', 'endpoint', 'targetClientKey'],
302
+ additionalProperties: false,
303
+ properties: {
304
+ edgeId: { type: 'string', minLength: 1 },
305
+ endpoint: { type: 'string', enum: ['from', 'to'] },
306
+ targetClientKey: { type: 'string', minLength: 1 },
307
+ },
308
+ },
309
+ ],
310
+ };
311
+ const splitChildSchema = {
312
+ type: 'object',
313
+ required: ['name'],
314
+ additionalProperties: false,
315
+ properties: {
316
+ clientKey: { type: 'string', minLength: 1 },
317
+ name: { type: 'string', minLength: 1 },
318
+ aliases: { type: 'array', items: { type: 'string', minLength: 1 } },
319
+ },
320
+ };
321
+ function correctionVariant(operation, extra, extraRequired) {
322
+ return {
323
+ type: 'object',
324
+ required: ['expectedRevision', 'reason', 'operation', ...extraRequired],
325
+ additionalProperties: false,
326
+ properties: {
327
+ operation: { const: operation },
328
+ expectedRevision: { type: 'integer', minimum: 0 },
329
+ reason: { type: 'string', minLength: 1 },
330
+ // An explicitly empty scopes array is not "use the authority's" - that
331
+ // is what omitting the field means. The store refuses it too, one layer
332
+ // in; saying it here refuses it before the transaction opens, which is
333
+ // what the deleted tool schema did.
334
+ scopes: { type: 'array', minItems: 1, items: exports.scopeRefSchema },
335
+ evidence: { type: 'array', items: observationEvidenceSchema },
336
+ ...extra,
337
+ },
338
+ };
339
+ }
340
+ const identityCorrectSchema = {
341
+ type: 'object',
342
+ oneOf: [
343
+ correctionVariant('add_alias', {
344
+ nodeId: { type: 'string', minLength: 1 },
345
+ alias: { type: 'string', minLength: 1 },
346
+ }, ['nodeId', 'alias']),
347
+ correctionVariant('merge', {
348
+ survivorId: { type: 'string', minLength: 1 },
349
+ memberIds: { type: 'array', items: { type: 'string', minLength: 1 } },
350
+ }, ['survivorId', 'memberIds']),
351
+ correctionVariant('split', {
352
+ parentId: { type: 'string', minLength: 1 },
353
+ children: { type: 'array', items: splitChildSchema },
354
+ assignments: { type: 'array', items: identityAssignmentSchema },
355
+ }, ['parentId', 'children', 'assignments']),
356
+ correctionVariant('assign_refs', {
357
+ parentId: { type: 'string', minLength: 1 },
358
+ assignments: { type: 'array', items: identityAssignmentSchema },
359
+ }, ['parentId', 'assignments']),
360
+ ],
361
+ };
362
+ const memorySearchSchema = {
363
+ type: 'object',
364
+ additionalProperties: false,
365
+ properties: {
366
+ query: {
367
+ type: 'string',
368
+ minLength: 1,
369
+ description: 'Memory text to recall, e.g. "release decision".',
370
+ },
371
+ limit: { type: 'integer', minimum: 1, description: 'Maximum memory results, e.g. 5.' },
372
+ kind: {
373
+ type: 'string',
374
+ enum: types_js_1.MEMORY_KINDS,
375
+ description: 'Optional memory record kind filter, e.g. "lesson".',
376
+ },
377
+ scopes: {
378
+ type: 'array',
379
+ description: 'Optional admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
380
+ items: exports.scopeRefSchema,
381
+ },
382
+ threshold: {
383
+ type: 'number',
384
+ minimum: 0,
385
+ maximum: 1,
386
+ description: 'Minimum relevance score, e.g. 0.7.',
387
+ },
388
+ strict: { type: 'boolean', description: 'Use strict legacy filtering, e.g. true.' },
389
+ strictness: {
390
+ type: 'string',
391
+ enum: ['recall', 'balanced', 'strict'],
392
+ description: 'Recall strictness mode, e.g. "balanced".',
393
+ },
394
+ disableRecency: { type: 'boolean', description: 'Disable recency weighting, e.g. true.' },
395
+ includeRelated: { type: 'boolean', description: 'Include related graph records, e.g. true.' },
396
+ topicPrefix: {
397
+ type: 'string',
398
+ minLength: 1,
399
+ description: 'Exact topic prefix for ledger listing, e.g. "work/".',
400
+ },
401
+ minLexicalSupport: {
402
+ type: 'boolean',
403
+ description: 'Require lexical query support, e.g. true.',
404
+ },
405
+ diagnostics: { type: 'boolean', description: 'Include search diagnostics, e.g. true.' },
406
+ rerankWithLearned: { type: 'boolean', description: 'Apply the learned ranker, e.g. true.' },
407
+ useReranking: { type: 'boolean', description: 'Allow host-provided reranking, e.g. true.' },
408
+ },
409
+ };
410
+ const memoryCheckpointLoadSchema = {
411
+ type: 'object',
412
+ additionalProperties: false,
413
+ properties: {},
414
+ };
415
+ const operationGetSchema = {
416
+ type: 'object',
417
+ required: ['operationId'],
418
+ additionalProperties: false,
419
+ properties: {
420
+ operationId: { type: 'string', minLength: 1 },
421
+ },
422
+ };
423
+ const memorySourceSchema = {
424
+ type: 'object',
425
+ required: ['package', 'source_type'],
426
+ additionalProperties: false,
427
+ properties: {
428
+ // No enum. The core does not hold a list of who may use it.
429
+ package: {
430
+ type: 'string',
431
+ minLength: 1,
432
+ description: 'Producer package name, e.g. "owner-agent".',
433
+ },
434
+ source_type: {
435
+ type: 'string',
436
+ minLength: 1,
437
+ description: 'Producer action/source type, e.g. "memory.save".',
438
+ },
439
+ user_id: {
440
+ type: 'string',
441
+ minLength: 1,
442
+ description: 'User scope identifier, e.g. "user_123".',
443
+ },
444
+ channel_id: {
445
+ type: 'string',
446
+ minLength: 1,
447
+ description: 'Channel scope identifier, e.g. "channel_123".',
448
+ },
449
+ project_id: {
450
+ type: 'string',
451
+ minLength: 1,
452
+ description: 'Project scope identifier, e.g. "project_123".',
453
+ },
454
+ },
455
+ };
456
+ const memorySaveSchema = {
457
+ type: 'object',
458
+ required: ['topic', 'kind', 'summary', 'details', 'source'],
459
+ additionalProperties: false,
460
+ properties: {
461
+ topic: {
462
+ type: 'string',
463
+ minLength: 1,
464
+ description: 'Memory topic key, e.g. "release_window".',
465
+ },
466
+ kind: {
467
+ type: 'string',
468
+ enum: types_js_1.MEMORY_KINDS,
469
+ description: 'Memory record kind, e.g. "decision".',
470
+ },
471
+ summary: {
472
+ type: 'string',
473
+ minLength: 1,
474
+ description: 'Short durable statement, e.g. "Release is Tuesday".',
475
+ },
476
+ details: {
477
+ type: 'string',
478
+ minLength: 1,
479
+ description: 'Supporting explanation, e.g. "Owner confirmed after review".',
480
+ },
481
+ appliesWhen: {
482
+ type: 'string',
483
+ minLength: 1,
484
+ description: 'One line saying when this lesson, preference, constraint, or workflow applies.',
485
+ },
486
+ steps: {
487
+ type: 'array',
488
+ minItems: 1,
489
+ description: 'Ordered steps for a workflow memory, e.g. ["Read the checklist", "Confirm the result"].',
490
+ items: { type: 'string', minLength: 1 },
491
+ },
492
+ evidenceChecks: {
493
+ type: 'array',
494
+ description: 'Optional evidence a workflow must check, e.g. ["Read the current checklist"].',
495
+ items: { type: 'string', minLength: 1 },
496
+ },
497
+ confidence: {
498
+ type: 'number',
499
+ minimum: 0,
500
+ maximum: 1,
501
+ description: 'Confidence from 0 to 1, e.g. 0.9.',
502
+ },
503
+ status: {
504
+ type: 'string',
505
+ enum: types_js_1.MEMORY_STATUSES,
506
+ description: 'Lifecycle status, e.g. "active".',
507
+ },
508
+ scopes: {
509
+ type: 'array',
510
+ description: "Visibility scopes are global, user, channel, or project; omit to use the caller's admitted scopes.",
511
+ items: exports.scopeRefSchema,
512
+ },
513
+ source: {
514
+ ...memorySourceSchema,
515
+ description: 'Origin metadata, e.g. {"package":"owner-agent","source_type":"memory.save"}.',
516
+ },
517
+ eventDate: { type: 'string', minLength: 1, description: 'Event date text, e.g. "2026-09-25".' },
518
+ eventDateTime: {
519
+ type: 'number',
520
+ description: 'Event time as epoch milliseconds, e.g. 1760000000000.',
521
+ },
522
+ itemId: {
523
+ description: 'Optional related item id, e.g. "work_123" or null.',
524
+ oneOf: [{ type: 'string', minLength: 1 }, { type: 'null' }],
525
+ },
526
+ actors: {
527
+ type: 'array',
528
+ description: 'People and roles evidenced by the memory, e.g. [{"personId":"person_123","role":"reviewer"}].',
529
+ items: {
530
+ type: 'object',
531
+ required: ['personId', 'role'],
532
+ additionalProperties: false,
533
+ properties: {
534
+ personId: {
535
+ type: 'string',
536
+ minLength: 1,
537
+ description: 'Actor person handle, e.g. "person_123".',
538
+ },
539
+ role: {
540
+ type: 'string',
541
+ minLength: 1,
542
+ description: 'Role in the memory event, e.g. "reviewer".',
543
+ },
544
+ },
545
+ },
546
+ },
547
+ links: {
548
+ type: 'array',
549
+ description: 'Evidence or graph links, e.g. [{"relation":"derived_from","target":{"kind":"observation","id":"obs_123"}}].',
550
+ items: exports.recordLinkSchema,
551
+ },
552
+ replaces: {
553
+ type: 'array',
554
+ description: 'Earlier records this one supersedes, e.g. [{"id":"mem_old","reason":"corrected"}].',
555
+ items: {
556
+ type: 'object',
557
+ additionalProperties: false,
558
+ required: ['id', 'reason'],
559
+ properties: {
560
+ id: {
561
+ type: 'string',
562
+ minLength: 1,
563
+ description: 'Existing memory id to replace, e.g. "mem_old".',
564
+ },
565
+ reason: {
566
+ type: 'string',
567
+ minLength: 1,
568
+ description: 'Why the old record is replaced, e.g. "owner corrected it".',
569
+ },
570
+ },
571
+ },
572
+ },
573
+ },
574
+ };
575
+ /**
576
+ * The actions this build actually implements. `graph.query` reads the twin-edge
577
+ * graph and `graph.identity.correct` is the registry_corrections transaction —
578
+ * the action behind `registry_correct`; the `work.*` commands are the
579
+ * commitment log's public write/read surface — the actions behind `task_create`
580
+ * / `task_update` / `task_reclassify` / `task_list`; `operation.get` is how a
581
+ * caller settles a call whose reply was lost.
582
+ */
583
+ function coreActionRegistrations(knowledge, adapter, deps) {
584
+ const effects = deps?.effects;
585
+ const effectLedger = deps?.effectLedger;
586
+ const runner = deps?.runner;
587
+ /** One receipt for a write recall can return. */
588
+ const recordWriteReceipt = (context, action, ref) => {
589
+ const ledger = effectLedger?.();
590
+ if (ledger === undefined || ref === null) {
591
+ return;
592
+ }
593
+ const session = context.session;
594
+ const change = {
595
+ runId: session?.modelRunId ?? null,
596
+ channelId: session?.channelId ?? null,
597
+ kind: 'memory_write',
598
+ targetType: 'memory',
599
+ targetId: `${action}:${ref}`,
600
+ payload: { action, ref },
601
+ atMs: Date.now(),
602
+ };
603
+ const causes = (session?.causeEventIds ?? []).filter(operations_js_1.isUsableCause);
604
+ if (causes.length > 0) {
605
+ (0, operations_js_1.recordEffect)(ledger, { ...change, sourceEventIds: [...causes] });
606
+ }
607
+ else {
608
+ // A run with no batch honestly records an unattributed change rather
609
+ // than inventing a cause for it.
610
+ (0, operations_js_1.recordUnattributedChange)(ledger, change, 'owner_message');
611
+ }
612
+ };
613
+ return [
614
+ {
615
+ contract: {
616
+ name: 'graph.query',
617
+ summary: 'Read the work graph: overview roots, neighbors, paths, timelines, and hydrated details under the caller authority. Each view takes its own inputs: browse pages every visible edge and accepts only history, relations, asOf, limit and cursor; paths requires from and to; neighbors, timeline and detail need seeds or a search. search resolves a name spelling to its registered node or alias; an empty page with coverage.search_no_match means nothing is registered under that spelling. Ref kinds are memory, case, report, edge, raw, registry and observation; a work item is reached through its memory (revision) records.',
618
+ inputSchema: workGraphQuerySchema,
619
+ examples: [
620
+ {
621
+ title: 'Current neighbors of an item',
622
+ input: { view: 'neighbors', seeds: [{ kind: 'registry', id: 'item_1' }] },
623
+ },
624
+ {
625
+ title: 'Everything ever known about a memory, including what replaced it',
626
+ input: {
627
+ view: 'timeline',
628
+ seeds: [{ kind: 'memory', id: 'judgment_…' }],
629
+ history: 'all',
630
+ },
631
+ },
632
+ ],
633
+ },
634
+ exec: (input, context) => {
635
+ const maxSourceMs = context.readAllowance?.maxSourceMs;
636
+ const access = maxSourceMs === undefined ? context.access : { ...context.access, maxSourceMs };
637
+ return knowledge.queryGraph(input, access);
638
+ },
639
+ },
640
+ {
641
+ contract: {
642
+ name: 'graph.node.put',
643
+ summary: 'Upsert one registry node: resolve by (kind, name, scopes) or create, then attach aliases and scope bindings. Alias resolution makes a retried put land on the same node — a store write bound to the caller authority, not a judgment command.',
644
+ inputSchema: {
645
+ type: 'object',
646
+ additionalProperties: false,
647
+ properties: {
648
+ kind: { type: 'string' },
649
+ name: { type: 'string' },
650
+ // A blank alias is not a spelling, and neither is whitespace. The
651
+ // deleted host tool trimmed and refused it ('invalid_alias'); the
652
+ // contract says it now, so a caller reaching the action directly
653
+ // meets the same rule instead of finding out from the store.
654
+ aliases: { type: 'array', items: { type: 'string', pattern: '\\S' } },
655
+ note: { oneOf: [{ type: 'string' }, { type: 'null' }] },
656
+ parent_of: {
657
+ type: 'array',
658
+ items: {
659
+ type: 'object',
660
+ properties: {
661
+ name: { type: 'string' },
662
+ aliases: { type: 'array', items: { type: 'string', pattern: '\\S' } },
663
+ },
664
+ required: ['name'],
665
+ },
666
+ },
667
+ },
668
+ required: ['kind', 'name'],
669
+ },
670
+ examples: [
671
+ {
672
+ title: 'Register an item the agent named',
673
+ input: { kind: 'item', name: 'ops channel', aliases: ['ops'] },
674
+ },
675
+ ],
676
+ },
677
+ exec: (input, context) => {
678
+ const body = input;
679
+ const kind = typeof body.kind === 'string' ? body.kind.trim() : '';
680
+ const name = typeof body.name === 'string' ? body.name.trim() : '';
681
+ if (!kind || !name) {
682
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'graph.node.put requires kind and name');
683
+ }
684
+ // Scope bindings come from the caller authority alone — the payload
685
+ // carries no scopes, so a put can never self-grant visibility. Which
686
+ // makes an authority stating NO scope the one case a put must refuse:
687
+ // the node would be bound to nothing, and whether that reads as
688
+ // invisible or as unfiltered is the reader's accident, not a decision
689
+ // anyone made. graph.identity.correct already refuses it
690
+ // (registry/corrections.ts, 'At least one signed scope is required');
691
+ // this said the same thing one layer out, in the host tool case that
692
+ // called this action, where a caller reaching the action directly
693
+ // never met it.
694
+ if (context.access.scopes.length === 0) {
695
+ throw new judgments_js_1.JudgmentError('INVALID_SCOPE', 'graph.node.put requires at least one scope on the caller authority');
696
+ }
697
+ return (0, store_js_1.upsertNode)(adapter, {
698
+ kind,
699
+ name,
700
+ aliases: body.aliases ?? [],
701
+ note: body.note ?? null,
702
+ scopes: context.access.scopes,
703
+ children: body.parent_of,
704
+ });
705
+ },
706
+ },
707
+ {
708
+ contract: {
709
+ name: 'graph.identity.correct',
710
+ summary: 'Append one identity correction — alias, merge, split, or edge-endpoint reassignment — inside the registry_corrections transaction. operationId is the command id; the caller authority scopes the result, input never grants it.',
711
+ inputSchema: identityCorrectSchema,
712
+ examples: [
713
+ {
714
+ title: 'Attach the name the owner actually uses',
715
+ input: {
716
+ expectedRevision: 3,
717
+ reason: 'owner calls it the ops channel',
718
+ operation: 'add_alias',
719
+ nodeId: 'item_1',
720
+ alias: 'ops channel',
721
+ },
722
+ },
723
+ {
724
+ title: 'Fold a duplicate into its survivor',
725
+ input: {
726
+ expectedRevision: 4,
727
+ reason: 'two rows name the same vendor',
728
+ operation: 'merge',
729
+ survivorId: 'item_1',
730
+ memberIds: ['item_2'],
731
+ },
732
+ },
733
+ ],
734
+ },
735
+ exec: (input, context) => knowledge.correctIdentity({
736
+ ...input,
737
+ commandId: requiredOperationId(context, 'graph.identity.correct'),
738
+ }, context.access),
739
+ },
740
+ {
741
+ contract: {
742
+ name: 'memory.save',
743
+ // What this writes, recall can return.
744
+ recallableWrite: true,
745
+ summary: "Append one judgment record. Explicit links attach visible evidence; replaces supersedes named visible records while preserving history. Matching topic alone never replaces. Access is the only authority — scopes in input are checked against it, and provenance comes from call authority and host-stated session facts. Scopes are global, user, channel, or project; omitted scopes use the caller's admitted scopes. operationId is the command id; a retry replays the original receipt.",
746
+ inputSchema: memorySaveSchema,
747
+ examples: [
748
+ {
749
+ title: 'Record a decision the owner made',
750
+ input: {
751
+ topic: 'deploy_window',
752
+ kind: 'decision',
753
+ summary: 'Deploys happen Tuesday 10:00 KST',
754
+ details: 'Owner confirmed the fixed window after the June freeze.',
755
+ source: { package: 'my-app', source_type: 'mama_save' },
756
+ },
757
+ },
758
+ {
759
+ title: 'Correct an earlier memory after reading preserved evidence',
760
+ input: {
761
+ topic: 'source_access',
762
+ kind: 'fact',
763
+ summary: 'The preserved source is readable',
764
+ details: 'A source.read call returned the original observation.',
765
+ source: { package: 'my-app', source_type: 'mama_save' },
766
+ links: [{ relation: 'derived_from', target: { kind: 'observation', id: 'obs_123' } }],
767
+ replaces: [{ id: 'judgment_old', reason: 'the original was read successfully' }],
768
+ },
769
+ },
770
+ {
771
+ title: 'Record an approved workflow',
772
+ input: {
773
+ topic: 'release_review',
774
+ kind: 'workflow',
775
+ summary: 'Review a release before sending it',
776
+ details: 'A short procedure the owner approved.',
777
+ appliesWhen: 'When preparing a release for review',
778
+ steps: ['Read the checklist', 'Confirm the build', 'Send the summary'],
779
+ evidenceChecks: ['Read the current checklist'],
780
+ source: { package: 'my-app', source_type: 'mama_save' },
781
+ },
782
+ },
783
+ ],
784
+ },
785
+ exec: async (input, context) => {
786
+ const saved = await (0, api_js_1.saveJudgmentRecord)(adapter, input, context.access, requiredOperationId(context, 'memory.save'), context.session);
787
+ recordWriteReceipt(context, 'memory.save', saved.id ?? null);
788
+ return saved;
789
+ },
790
+ },
791
+ {
792
+ contract: {
793
+ name: 'memory.update',
794
+ // What this writes, recall can return.
795
+ recallableWrite: true,
796
+ summary: 'Append one outcome amendment to a memory record — the append-only judgment row and the maintained decisions projection move in one transaction. Outcome is SUCCESS, FAILED, or PARTIAL (case-insensitive).',
797
+ inputSchema: {
798
+ type: 'object',
799
+ additionalProperties: false,
800
+ properties: {
801
+ id: { type: 'string', description: 'Memory id to amend, e.g. "mem_123".' },
802
+ outcome: { type: 'string', description: 'Outcome label, e.g. "SUCCESS".' },
803
+ failure_reason: {
804
+ type: 'string',
805
+ description: 'Why the outcome failed, e.g. "missing review".',
806
+ },
807
+ limitation: {
808
+ type: 'string',
809
+ description: 'Known limitation, e.g. "only one channel checked".',
810
+ },
811
+ },
812
+ required: ['id', 'outcome'],
813
+ },
814
+ examples: [
815
+ {
816
+ title: 'Mark a decision as having failed in the field',
817
+ input: {
818
+ id: 'decision_deploy_window_1',
819
+ outcome: 'failed',
820
+ failure_reason: 'the Tuesday window collided with the provider maintenance',
821
+ },
822
+ },
823
+ ],
824
+ },
825
+ exec: async (input, context) => {
826
+ const body = input;
827
+ const id = typeof body.id === 'string' ? body.id.trim() : '';
828
+ const outcome = typeof body.outcome === 'string' ? body.outcome.trim().toUpperCase() : '';
829
+ if (!id) {
830
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.update requires id');
831
+ }
832
+ if (!['SUCCESS', 'FAILED', 'PARTIAL'].includes(outcome)) {
833
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.update outcome must be SUCCESS, FAILED, or PARTIAL');
834
+ }
835
+ const bindings = adapter
836
+ .prepare(`SELECT s.kind, s.external_id AS id FROM memory_scope_bindings b
837
+ JOIN memory_scopes s ON s.id = b.scope_id WHERE b.memory_id = ?`)
838
+ .all(id);
839
+ if (bindings.length > 0 &&
840
+ !bindings.some((binding) => context.access.scopes.some((scope) => scope.kind === binding.kind && scope.id === binding.id))) {
841
+ throw new judgments_js_1.JudgmentError('SCOPE_DENIED', 'Memory record is outside the admitted write scopes');
842
+ }
843
+ await (0, api_js_2.updateOutcomeInAdapter)(adapter, id, {
844
+ outcome,
845
+ failure_reason: body.failure_reason ?? null,
846
+ limitation: body.limitation ?? null,
847
+ });
848
+ recordWriteReceipt(context, 'memory.update', id);
849
+ return { id, outcome };
850
+ },
851
+ },
852
+ {
853
+ contract: {
854
+ name: 'memory.checkpoint.save',
855
+ summary: 'Write one session checkpoint — the durable hand-off record a later turn restores work from. Not a judgment and not scope-bound; the row is what it says.',
856
+ inputSchema: {
857
+ type: 'object',
858
+ additionalProperties: false,
859
+ properties: {
860
+ summary: {
861
+ type: 'string',
862
+ description: 'Checkpoint summary, e.g. "Projection handle is wired".',
863
+ },
864
+ open_files: {
865
+ type: 'array',
866
+ description: 'Files to reopen, e.g. ["src/runtime.ts"].',
867
+ items: { type: 'string' },
868
+ },
869
+ next_steps: {
870
+ type: 'string',
871
+ description: 'Next work to resume, e.g. "run the integration test".',
872
+ },
873
+ },
874
+ required: ['summary'],
875
+ },
876
+ examples: [
877
+ {
878
+ title: 'Save the session state before stopping',
879
+ input: {
880
+ summary: 'Goal: migrate the socket owner. Evidence: runtime.ts mounted.',
881
+ next_steps: 'convert the last direct caller to the client path',
882
+ },
883
+ },
884
+ ],
885
+ },
886
+ exec: async (input, context) => {
887
+ const body = input;
888
+ const summary = typeof body.summary === 'string' ? body.summary.trim() : '';
889
+ if (!summary) {
890
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.checkpoint.save requires summary');
891
+ }
892
+ const id = await (0, api_js_2.saveCheckpointInAdapter)(adapter, summary, body.open_files ?? [], body.next_steps ?? '',
893
+ // The transcript is the host's to state; a caller that has none saves a
894
+ // checkpoint without one rather than inventing it.
895
+ [...(context.session?.recentConversation ?? [])]);
896
+ return { id: String(id) };
897
+ },
898
+ },
899
+ {
900
+ contract: {
901
+ name: 'memory.search',
902
+ summary: 'Search or list memory records under the caller authority. Omitted scopes read the admitted corpus; explicit scopes must be a subset of it. With a query this is the semantic recall path (vector + lexical fusion, learned ranker when enabled); without one it is the exact topic-prefix ledger read.',
903
+ inputSchema: memorySearchSchema,
904
+ examples: [
905
+ {
906
+ title: 'Recall what was decided about deploys',
907
+ input: { query: 'deploy window decision', limit: 5 },
908
+ },
909
+ {
910
+ title: 'Every record filed under one item key',
911
+ input: { topicPrefix: 'item_0001', limit: 30 },
912
+ },
913
+ ],
914
+ },
915
+ exec: async (input, context) => {
916
+ const query = input;
917
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, query.scopes);
918
+ if (scopes.length === 0) {
919
+ // No admitted scopes means no visible corpus — an honest empty page,
920
+ // not the legacy unbounded scan.
921
+ return { success: true, results: [], count: 0 };
922
+ }
923
+ if (typeof query.query !== 'string' || query.query.trim().length === 0) {
924
+ const rows = await (0, api_js_2.listDecisionsInAdapter)(adapter, {
925
+ limit: query.limit,
926
+ kind: query.kind,
927
+ topicPrefix: query.topicPrefix,
928
+ scopes,
929
+ });
930
+ const items = Array.isArray(rows) ? rows : [];
931
+ return { success: true, results: items, count: items.length };
932
+ }
933
+ const result = (await (0, api_js_2.suggestInAdapter)(adapter, query.query, {
934
+ limit: query.limit,
935
+ kind: query.kind,
936
+ threshold: query.threshold,
937
+ strict: query.strict,
938
+ strictness: query.strictness,
939
+ disableRecency: query.disableRecency,
940
+ includeRelated: query.includeRelated,
941
+ topicPrefix: query.topicPrefix,
942
+ minLexicalSupport: query.minLexicalSupport,
943
+ diagnostics: query.diagnostics,
944
+ rerankWithLearned: query.rerankWithLearned,
945
+ useReranking: query.useReranking,
946
+ ...(runner?.() ? { runner: runner() } : {}),
947
+ scopes,
948
+ }));
949
+ if (!result || typeof result !== 'object') {
950
+ return {
951
+ success: false,
952
+ code: 'suggest_returned_null',
953
+ error: 'Search failed: suggest() returned no result for query',
954
+ results: [],
955
+ count: 0,
956
+ };
957
+ }
958
+ return result;
959
+ },
960
+ },
961
+ {
962
+ contract: {
963
+ name: 'memory.checkpoint.load',
964
+ summary: 'Load the latest active session checkpoint — the durable hand-off record a later turn restores work from. Returns null when none exists.',
965
+ inputSchema: memoryCheckpointLoadSchema,
966
+ examples: [{ title: 'Restore the last checkpoint', input: {} }],
967
+ },
968
+ exec: (_input, _context) => (0, api_js_2.loadCheckpointInAdapter)(adapter),
969
+ },
970
+ {
971
+ contract: {
972
+ name: 'memory.checkpoint.list',
973
+ summary: 'List recent session checkpoints, newest first — the hand-off records this workspace kept, including superseded ones. `limit` defaults to 20 and is capped at 50.',
974
+ inputSchema: {
975
+ type: 'object',
976
+ additionalProperties: false,
977
+ properties: {
978
+ limit: { type: 'number', description: 'Maximum checkpoints, e.g. 10.' },
979
+ },
980
+ },
981
+ examples: [{ title: 'What was handed off recently', input: { limit: 10 } }],
982
+ },
983
+ exec: async (input) => {
984
+ const raw = Number(input.limit);
985
+ const limit = Number.isFinite(raw) ? Math.min(Math.max(Math.floor(raw), 1), 50) : 20;
986
+ const checkpoints = await (0, api_js_2.listCheckpointsInAdapter)(adapter, limit);
987
+ return { checkpoints, count: checkpoints.length };
988
+ },
989
+ },
990
+ {
991
+ contract: {
992
+ name: 'memory.read:listing',
993
+ summary: 'Decisions under the admitted scopes as a list: `order: recent` is what changed last, `order: stale` is what has gone longest untouched, and `status` narrows to one lifecycle state. The default compact view keeps the complete decision and a short reasoning preview; use memory.search(topicPrefix) for one topic or `detail: full` for complete batch reasoning. `limit` defaults to 50 and is capped at 200.',
994
+ inputSchema: {
995
+ type: 'object',
996
+ additionalProperties: false,
997
+ properties: {
998
+ status: { type: 'string', description: 'Memory lifecycle filter, e.g. "active".' },
999
+ order: {
1000
+ type: 'string',
1001
+ enum: ['recent', 'stale'],
1002
+ description: 'List order, e.g. "recent".',
1003
+ },
1004
+ limit: { type: 'number', description: 'Maximum listed memories, e.g. 20.' },
1005
+ detail: {
1006
+ type: 'string',
1007
+ enum: ['compact', 'full'],
1008
+ description: 'Reasoning detail, e.g. "compact".',
1009
+ },
1010
+ scopes: {
1011
+ type: 'array',
1012
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1013
+ items: exports.scopeRefSchema,
1014
+ },
1015
+ },
1016
+ },
1017
+ examples: [
1018
+ { title: 'Active decisions going stale', input: { status: 'active', order: 'stale' } },
1019
+ { title: 'What changed lately', input: { order: 'recent', limit: 20 } },
1020
+ { title: 'Read complete reasoning for the scoped list', input: { detail: 'full' } },
1021
+ ],
1022
+ },
1023
+ exec: async (input, context) => {
1024
+ const query = input;
1025
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, query.scopes);
1026
+ const decisions = await (0, dashboard_read_js_1.readDecisionListing)(adapter, scopes, {
1027
+ ...(typeof query.status === 'string' ? { status: query.status } : {}),
1028
+ ...(query.order === 'stale' ? { order: 'stale' } : { order: 'recent' }),
1029
+ ...(Number.isFinite(Number(query.limit)) ? { limit: Number(query.limit) } : {}),
1030
+ });
1031
+ if (query.detail === 'full')
1032
+ return { decisions, count: decisions.length };
1033
+ const compact = decisions.map(({ reasoning, ...row }) => {
1034
+ const points = Array.from(reasoning ?? '');
1035
+ return {
1036
+ ...row,
1037
+ reasoningPreview: points.slice(0, 160).join(''),
1038
+ reasoningTruncated: points.length > 160,
1039
+ };
1040
+ });
1041
+ return { decisions: compact, count: compact.length };
1042
+ },
1043
+ },
1044
+ {
1045
+ contract: {
1046
+ name: 'memory.read:projects',
1047
+ summary: 'Project rollups over the admitted scopes: how many active decisions each project holds and when it last moved. Name a `project` to get that project\u2019s decisions instead, still bounded by what the caller admits.',
1048
+ inputSchema: {
1049
+ type: 'object',
1050
+ additionalProperties: false,
1051
+ properties: {
1052
+ project: { type: 'string', description: 'Project label to inspect, e.g. "release".' },
1053
+ limit: { type: 'number', description: 'Maximum project decisions, e.g. 20.' },
1054
+ scopes: {
1055
+ type: 'array',
1056
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1057
+ items: exports.scopeRefSchema,
1058
+ },
1059
+ },
1060
+ },
1061
+ examples: [
1062
+ { title: 'Which projects are busy', input: {} },
1063
+ { title: 'What one project holds', input: { project: 'mama', limit: 20 } },
1064
+ ],
1065
+ },
1066
+ exec: async (input, context) => {
1067
+ const query = input;
1068
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, query.scopes);
1069
+ const project = typeof query.project === 'string' ? query.project.trim() : '';
1070
+ if (project) {
1071
+ const decisions = await (0, dashboard_read_js_1.readProjectDecisions)(adapter, scopes, project, Number.isFinite(Number(query.limit)) ? Number(query.limit) : 50);
1072
+ return { project, decisions, count: decisions.length };
1073
+ }
1074
+ const projects = await (0, dashboard_read_js_1.readProjectRollups)(adapter, scopes);
1075
+ return { projects, count: projects.length };
1076
+ },
1077
+ },
1078
+ {
1079
+ contract: {
1080
+ name: 'memory.read:graph',
1081
+ summary: 'The decision graph this caller may see: `view: graph` returns a bounded page of nodes with the edges joining admitted nodes and the admitted total; `nodes` returns the named ids; `detail` returns one record in full; `similarity` returns what the vector index says is near, over the admitted window. Every view is bounded by the admitted scopes.',
1082
+ inputSchema: {
1083
+ type: 'object',
1084
+ additionalProperties: false,
1085
+ properties: {
1086
+ view: {
1087
+ type: 'string',
1088
+ enum: ['graph', 'nodes', 'detail', 'similarity'],
1089
+ description: 'Memory graph view, e.g. "detail".',
1090
+ },
1091
+ id: { type: 'string', description: 'One memory id for detail, e.g. "mem_123".' },
1092
+ ids: {
1093
+ type: 'array',
1094
+ description: 'Memory ids for node lookup, e.g. ["mem_123"].',
1095
+ items: { type: 'string' },
1096
+ },
1097
+ limit: { type: 'number', description: 'Maximum graph rows, e.g. 100.' },
1098
+ scopes: {
1099
+ type: 'array',
1100
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1101
+ items: exports.scopeRefSchema,
1102
+ },
1103
+ },
1104
+ },
1105
+ examples: [
1106
+ { title: 'The graph a viewer draws', input: { view: 'graph', limit: 100 } },
1107
+ { title: 'One decision in full', input: { view: 'detail', id: 'judgment_…' } },
1108
+ ],
1109
+ },
1110
+ exec: async (input, context) => {
1111
+ const query = input;
1112
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, query.scopes);
1113
+ const view = typeof query.view === 'string' ? query.view : 'graph';
1114
+ const rawLimit = Number(query.limit);
1115
+ const limit = Number.isFinite(rawLimit)
1116
+ ? Math.min(Math.max(Math.floor(rawLimit), 1), 1000)
1117
+ : null;
1118
+ if (view === 'detail') {
1119
+ const id = typeof query.id === 'string' ? query.id.trim() : '';
1120
+ if (!id) {
1121
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.read:graph detail requires an id');
1122
+ }
1123
+ const [node] = await (0, graph_read_js_1.readGraphNodes)(adapter, scopes, { ids: [id], limit: 1 });
1124
+ return { node: node ?? null };
1125
+ }
1126
+ if (view === 'nodes') {
1127
+ const ids = Array.isArray(query.ids)
1128
+ ? query.ids.filter((id) => typeof id === 'string' && id.trim() !== '')
1129
+ : [];
1130
+ if (ids.length === 0) {
1131
+ return { nodes: [] };
1132
+ }
1133
+ return { nodes: await (0, graph_read_js_1.readGraphNodes)(adapter, scopes, { ids, limit: null }) };
1134
+ }
1135
+ if (view === 'similarity') {
1136
+ return { edges: await (0, graph_read_js_1.readGraphSimilarityEdges)(adapter, scopes) };
1137
+ }
1138
+ const [nodes, edges, total] = await Promise.all([
1139
+ (0, graph_read_js_1.readGraphNodes)(adapter, scopes, { limit }),
1140
+ (0, graph_read_js_1.readGraphEdges)(adapter, scopes),
1141
+ (0, graph_read_js_1.countGraphNodes)(adapter, scopes),
1142
+ ]);
1143
+ return { nodes, edges, total };
1144
+ },
1145
+ },
1146
+ {
1147
+ contract: {
1148
+ name: 'memory.read:stats',
1149
+ summary: 'Counts over the memory this caller may see: decisions in total and over the last week and month, the outcome breakdown, the five busiest topics, and how many checkpoints exist. Bounded by the admitted scopes — a principal that admits nothing counts nothing.',
1150
+ inputSchema: {
1151
+ type: 'object',
1152
+ additionalProperties: false,
1153
+ properties: {
1154
+ scopes: {
1155
+ type: 'array',
1156
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1157
+ items: exports.scopeRefSchema,
1158
+ },
1159
+ },
1160
+ },
1161
+ examples: [{ title: 'What this workspace holds', input: {} }],
1162
+ },
1163
+ exec: async (input, context) => {
1164
+ const query = input;
1165
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, query.scopes);
1166
+ return (0, api_js_2.readMemoryStatsInAdapter)(adapter, scopes);
1167
+ },
1168
+ },
1169
+ {
1170
+ contract: {
1171
+ name: 'memory.read:topic',
1172
+ summary: 'Read the topic recall bundle — the profile, ranked memories, and graph context a question rests on. Omitted scopes read the admitted corpus; explicit scopes must be a subset of it. An admitted-empty caller gets an empty bundle, never an unbounded scan.',
1173
+ inputSchema: {
1174
+ type: 'object',
1175
+ additionalProperties: false,
1176
+ properties: {
1177
+ query: {
1178
+ type: 'string',
1179
+ description: 'Topic text to recall, e.g. "release decision".',
1180
+ },
1181
+ scopes: {
1182
+ type: 'array',
1183
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1184
+ items: exports.scopeRefSchema,
1185
+ },
1186
+ },
1187
+ required: ['query'],
1188
+ },
1189
+ examples: [
1190
+ {
1191
+ title: 'Recall everything relevant to a topic',
1192
+ input: { query: 'deploy freeze decision' },
1193
+ },
1194
+ ],
1195
+ },
1196
+ exec: async (input, context) => {
1197
+ const query = input;
1198
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, query.scopes);
1199
+ if (typeof query.query !== 'string' || query.query.trim().length === 0) {
1200
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.read:topic requires a non-empty query');
1201
+ }
1202
+ // Scrubbed and narrowed to the fields a read may answer with. This
1203
+ // lived in a host tool case that wrapped the action, so a caller naming
1204
+ // memory.read:topic got unredacted full records while
1205
+ // memory.read:provenance below scrubbed its excerpts.
1206
+ return (0, recall_sanitize_js_1.sanitizeRecallBundle)(await (0, api_js_1.recallMemory)(adapter, query.query, { scopes, includeProfile: true }));
1207
+ },
1208
+ },
1209
+ {
1210
+ contract: {
1211
+ name: 'memory.read:provenance',
1212
+ summary: "Resolve a stored memory's recorded cause and derived_from observation links. Every supporting observation is checked against the current caller's source-read authority; a memory id grants no access. Omit scopes to use the admitted read scope. Excerpts are scrubbed with the recall redaction.",
1213
+ inputSchema: {
1214
+ type: 'object',
1215
+ additionalProperties: false,
1216
+ properties: {
1217
+ // Nonblank at the contract, not only in exec: the deleted host tool
1218
+ // trimmed and refused a blank handle before dispatching, and a
1219
+ // whitespace id is not a handle.
1220
+ memory_id: {
1221
+ type: 'string',
1222
+ pattern: '\\S',
1223
+ description: 'Memory id whose provenance to resolve, e.g. "mem_123".',
1224
+ },
1225
+ scopes: {
1226
+ type: 'array',
1227
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1228
+ items: exports.scopeRefSchema,
1229
+ },
1230
+ },
1231
+ required: ['memory_id'],
1232
+ },
1233
+ examples: [
1234
+ {
1235
+ title: 'What does this decision rest on',
1236
+ input: { memory_id: 'mem_7f3a' },
1237
+ },
1238
+ ],
1239
+ },
1240
+ exec: async (input, context) => {
1241
+ const body = input;
1242
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, body.scopes);
1243
+ if (typeof body.memory_id !== 'string' || body.memory_id.trim().length === 0) {
1244
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.read:provenance requires a non-empty memory_id');
1245
+ }
1246
+ const allowance = context.readAllowance;
1247
+ return (0, provenance_live_js_1.resolveMemoryProvenanceLive)(adapter, body.memory_id, {
1248
+ scopes,
1249
+ connectors: allowance?.connectors ?? [],
1250
+ wideConnectors: allowance?.wideConnectors ?? [],
1251
+ ...(allowance?.channels ? { channels: allowance.channels } : {}),
1252
+ ...(allowance?.projectIds === undefined ? {} : { projectIds: allowance.projectIds }),
1253
+ tenantId: allowance?.tenantId ?? null,
1254
+ minObservedMs: allowance?.minObservedMs ?? null,
1255
+ maxObservedMs: allowance?.maxObservedMs ?? null,
1256
+ maxSourceMs: allowance?.maxSourceMs ?? null,
1257
+ principalId: context.access.principalId,
1258
+ redact: (text) => (0, recall_sanitize_js_1.sanitizeRecallText)(text) ?? '',
1259
+ });
1260
+ },
1261
+ },
1262
+ {
1263
+ contract: {
1264
+ name: 'memory.read:record',
1265
+ summary: 'Read one complete memory record by id within the admitted memory scopes. Returns the stored record content and structured workflow steps, without source excerpts or provenance material. An id is not a capability.',
1266
+ inputSchema: {
1267
+ type: 'object',
1268
+ additionalProperties: false,
1269
+ properties: {
1270
+ memory_id: {
1271
+ type: 'string',
1272
+ pattern: '\\S',
1273
+ description: 'Memory id to read, e.g. "mem_123".',
1274
+ },
1275
+ scopes: {
1276
+ type: 'array',
1277
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1278
+ items: exports.scopeRefSchema,
1279
+ },
1280
+ },
1281
+ required: ['memory_id'],
1282
+ },
1283
+ examples: [
1284
+ { title: 'Read a guidance record from its index id', input: { memory_id: 'mem_123' } },
1285
+ ],
1286
+ },
1287
+ exec: async (input, context) => {
1288
+ const body = input;
1289
+ const memoryId = typeof body.memory_id === 'string' ? body.memory_id.trim() : '';
1290
+ if (!memoryId) {
1291
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.read:record requires a non-empty memory_id');
1292
+ }
1293
+ const scopes = (0, api_js_1.boundReadScopesFor)(context.access, body.scopes);
1294
+ const record = await (0, api_js_1.readMemoryRecordById)(adapter, memoryId, scopes);
1295
+ return {
1296
+ record: record
1297
+ ? {
1298
+ id: record.id,
1299
+ kind: record.kind,
1300
+ topic: record.topic,
1301
+ summary: record.summary,
1302
+ details: record.details,
1303
+ ...(record.applies_when === undefined ? {} : { appliesWhen: record.applies_when }),
1304
+ ...(record.steps === undefined ? {} : { steps: record.steps }),
1305
+ ...(record.evidence_checks === undefined
1306
+ ? {}
1307
+ : { evidenceChecks: record.evidence_checks }),
1308
+ confidence: record.confidence,
1309
+ status: record.status,
1310
+ createdAt: record.created_at,
1311
+ updatedAt: record.updated_at,
1312
+ }
1313
+ : null,
1314
+ };
1315
+ },
1316
+ },
1317
+ {
1318
+ contract: {
1319
+ name: 'memory.retire',
1320
+ recallableWrite: true,
1321
+ summary: 'Retire one visible memory record by appending a stale or superseded status amendment with its reason. The original record remains readable and the action returns the amendment receipt id.',
1322
+ inputSchema: {
1323
+ type: 'object',
1324
+ additionalProperties: false,
1325
+ properties: {
1326
+ memory_id: {
1327
+ type: 'string',
1328
+ pattern: '\\S',
1329
+ description: 'Memory id to retire, e.g. "mem_123".',
1330
+ },
1331
+ status: {
1332
+ type: 'string',
1333
+ enum: ['stale', 'superseded'],
1334
+ description: 'Why the record no longer applies, e.g. "stale".',
1335
+ },
1336
+ reason: {
1337
+ type: 'string',
1338
+ minLength: 1,
1339
+ description: 'Why this guidance was withdrawn or replaced, e.g. "The process changed".',
1340
+ },
1341
+ scopes: {
1342
+ type: 'array',
1343
+ description: 'Admitted scope filter, e.g. [{"kind":"project","id":"project_123"}].',
1344
+ items: exports.scopeRefSchema,
1345
+ },
1346
+ },
1347
+ required: ['memory_id', 'status', 'reason'],
1348
+ },
1349
+ examples: [
1350
+ {
1351
+ title: 'Retire a withdrawn preference',
1352
+ input: {
1353
+ memory_id: 'mem_123',
1354
+ status: 'stale',
1355
+ reason: 'The owner withdrew this preference.',
1356
+ },
1357
+ },
1358
+ ],
1359
+ },
1360
+ exec: async (input, context) => {
1361
+ const body = input;
1362
+ // A read grant may expose a memory record, but it cannot authorize changing its status.
1363
+ const writeAccess = { ...context.access, readScopes: [] };
1364
+ const scopes = (0, api_js_1.boundReadScopesFor)(writeAccess, body.scopes);
1365
+ const status = body.status;
1366
+ if (status !== 'stale' && status !== 'superseded') {
1367
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.retire status must be stale or superseded');
1368
+ }
1369
+ const retired = await (0, api_js_1.retireMemoryRecord)(adapter, {
1370
+ memoryId: typeof body.memory_id === 'string' ? body.memory_id : '',
1371
+ status,
1372
+ reason: typeof body.reason === 'string' ? body.reason : '',
1373
+ }, { ...writeAccess, scopes }, requiredOperationId(context, 'memory.retire'));
1374
+ recordWriteReceipt(context, 'memory.retire', retired.id);
1375
+ return retired;
1376
+ },
1377
+ },
1378
+ {
1379
+ contract: {
1380
+ name: 'memory.read:experience',
1381
+ summary: 'Read execution evidence — the tool-trace ledger. One trace by trace_id, or a bounded page filtered by run_id/tool_name/cursor. The caller authority scopes the read: principalId becomes owner_scope, the single admitted project scope becomes project_id, and a non-owner caller must carry a channel scope that becomes channel_id. A trace id is never a capability — input cannot widen the scope.',
1382
+ inputSchema: {
1383
+ type: 'object',
1384
+ additionalProperties: false,
1385
+ properties: {
1386
+ trace_id: {
1387
+ type: 'string',
1388
+ minLength: 1,
1389
+ description: 'One tool trace handle, e.g. "trace_123".',
1390
+ },
1391
+ run_id: {
1392
+ type: 'string',
1393
+ minLength: 1,
1394
+ description: 'Model run filter, e.g. "run_123".',
1395
+ },
1396
+ tool_name: {
1397
+ type: 'string',
1398
+ minLength: 1,
1399
+ description: 'Tool name filter, e.g. "source.read".',
1400
+ },
1401
+ cursor: {
1402
+ type: 'string',
1403
+ minLength: 1,
1404
+ description: 'Opaque trace page cursor, e.g. "cursor_25".',
1405
+ },
1406
+ limit: { type: 'number', description: 'Maximum traces, e.g. 25.' },
1407
+ evidence_only: {
1408
+ type: 'boolean',
1409
+ description: 'Return only evidence-bearing traces, e.g. true.',
1410
+ },
1411
+ offset: { type: 'number', description: 'Character offset inside one trace, e.g. 0.' },
1412
+ chars: { type: 'number', description: 'Maximum trace characters, e.g. 4000.' },
1413
+ },
1414
+ },
1415
+ examples: [
1416
+ { title: 'Read one execution trace', input: { trace_id: 'trace_abc' } },
1417
+ { title: 'List recent tool evidence for a run', input: { run_id: 'run_1', limit: 10 } },
1418
+ ],
1419
+ },
1420
+ exec: async (input, context) => {
1421
+ const body = input;
1422
+ // Execution evidence answers to the RUN, not to the caller's memory
1423
+ // scopes: exactly one project, the owner lane or the principal, and a
1424
+ // channel for a member. The host states that as a session fact, which
1425
+ // is why this reads it rather than re-deriving it from `access` --
1426
+ // a host used to rewrite the principal's scopes for this one tool name,
1427
+ // and an access object with two authorities on it is what that cost.
1428
+ const evidence = context.session?.runEvidenceScope;
1429
+ if (!evidence) {
1430
+ throw new judgments_js_1.JudgmentError('SCOPE_DENIED', 'memory.read:experience requires the run evidence authority');
1431
+ }
1432
+ const isOwnerRuntime = evidence.ownerScope === 'owner:runtime';
1433
+ if (!isOwnerRuntime && !evidence.channelId) {
1434
+ throw new judgments_js_1.JudgmentError('SCOPE_DENIED', 'memory.read:experience member reads require an admitted channel scope');
1435
+ }
1436
+ const scope = {
1437
+ owner_scope: evidence.ownerScope,
1438
+ project_id: evidence.projectId,
1439
+ ...(isOwnerRuntime ? {} : { channel_id: evidence.channelId }),
1440
+ };
1441
+ if (body.trace_id !== undefined) {
1442
+ if (body.run_id !== undefined ||
1443
+ body.tool_name !== undefined ||
1444
+ body.cursor !== undefined ||
1445
+ body.limit !== undefined ||
1446
+ body.evidence_only !== undefined) {
1447
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.read:experience trace reads accept only offset and chars beside trace_id');
1448
+ }
1449
+ const offset = body.offset ?? 0;
1450
+ const chars = body.chars ?? 4000;
1451
+ if (!Number.isSafeInteger(offset) ||
1452
+ offset < 0 ||
1453
+ !Number.isSafeInteger(chars) ||
1454
+ chars < 1 ||
1455
+ chars > 8000) {
1456
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.read:experience offset/chars invalid');
1457
+ }
1458
+ const trace = await (0, tool_trace_store_js_1.readToolTrace)(adapter, body.trace_id, scope);
1459
+ if (!trace) {
1460
+ throw new judgments_js_1.JudgmentError('NOT_FOUND', `Execution evidence unavailable: ${body.trace_id}`);
1461
+ }
1462
+ const text = Array.from(trace.evidence_json ?? '');
1463
+ if (offset > text.length) {
1464
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'memory.read:experience offset out of range');
1465
+ }
1466
+ const end = Math.min(offset + chars, text.length);
1467
+ return {
1468
+ trace: { ...trace, evidence_json: null },
1469
+ content: text.slice(offset, end).join(''),
1470
+ offset,
1471
+ total_chars: text.length,
1472
+ next_offset: end < text.length ? end : null,
1473
+ };
1474
+ }
1475
+ return (0, tool_trace_store_js_1.listToolTraces)(adapter, {
1476
+ ...scope,
1477
+ ...(body.run_id !== undefined ? { model_run_id: body.run_id } : {}),
1478
+ ...(body.tool_name !== undefined ? { tool_name: body.tool_name } : {}),
1479
+ ...(body.cursor !== undefined ? { cursor: body.cursor } : {}),
1480
+ ...(body.limit !== undefined ? { limit: body.limit } : {}),
1481
+ ...(body.evidence_only !== undefined ? { evidence_only: body.evidence_only } : {}),
1482
+ });
1483
+ },
1484
+ },
1485
+ {
1486
+ contract: {
1487
+ name: 'source.ingest',
1488
+ summary: 'Store one explicitly provided raw observation — a content body or one whole conversation — under the caller authority. One call is one observation: no extraction, no judgment rows, no per-message split. The operationId is the command id, so retransmitting the same call replays the stored receipt instead of writing a second observation.',
1489
+ inputSchema: {
1490
+ type: 'object',
1491
+ additionalProperties: false,
1492
+ properties: {
1493
+ content: { type: 'string' },
1494
+ messages: {
1495
+ type: 'array',
1496
+ items: {
1497
+ type: 'object',
1498
+ required: ['role', 'content'],
1499
+ additionalProperties: false,
1500
+ properties: {
1501
+ role: { type: 'string' },
1502
+ content: { type: 'string' },
1503
+ },
1504
+ },
1505
+ },
1506
+ source: {
1507
+ type: 'object',
1508
+ additionalProperties: false,
1509
+ properties: {
1510
+ connector: { type: 'string' },
1511
+ id: { type: 'string' },
1512
+ package: { type: 'string' },
1513
+ source_type: { type: 'string' },
1514
+ },
1515
+ },
1516
+ session_date: { type: 'string' },
1517
+ scopes: { type: 'array', items: exports.scopeRefSchema },
1518
+ metadata: { type: 'object' },
1519
+ },
1520
+ },
1521
+ examples: [
1522
+ {
1523
+ title: 'Import a conversation as one raw observation',
1524
+ input: {
1525
+ messages: [
1526
+ { role: 'user', content: 'ship on Friday?' },
1527
+ { role: 'assistant', content: 'yes, after the freeze lifts' },
1528
+ ],
1529
+ source: { connector: 'conversation:mcp_ingest_conversation' },
1530
+ },
1531
+ },
1532
+ ],
1533
+ },
1534
+ exec: async (input, context) => {
1535
+ const body = input;
1536
+ const hasContent = typeof body.content === 'string' && body.content.trim().length > 0;
1537
+ const messages = Array.isArray(body.messages)
1538
+ ? body.messages.filter((m) => typeof m?.role === 'string' && typeof m?.content === 'string')
1539
+ : [];
1540
+ const hasMessages = messages.length > 0;
1541
+ if (hasContent === hasMessages) {
1542
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'source.ingest requires exactly one of content or a non-empty messages array');
1543
+ }
1544
+ const commandId = requiredOperationId(context, 'source.ingest');
1545
+ const sessionMs = body.session_date === undefined ? null : Date.parse(body.session_date);
1546
+ if (body.session_date !== undefined && !Number.isFinite(sessionMs)) {
1547
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', `source.ingest session_date is not a parseable date: ${body.session_date}`);
1548
+ }
1549
+ const connector = body.source?.connector ??
1550
+ (body.source?.source_type ? `conversation:${body.source.source_type}` : 'explicit');
1551
+ if (connector.startsWith('owner-message:') || connector.startsWith('owner-result:')) {
1552
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'source.ingest cannot use a reserved source prefix');
1553
+ }
1554
+ const receipt = await (0, source_ingest_js_1.ingestSource)({
1555
+ commandId,
1556
+ source: { connector, id: body.source?.id ?? commandId },
1557
+ body: hasContent
1558
+ ? body.content
1559
+ : messages.map((m) => `${m.role}: ${m.content}`).join('\n'),
1560
+ sourceAt: sessionMs,
1561
+ metadata: {
1562
+ ...(body.metadata ?? {}),
1563
+ ...(body.source ? { source: body.source } : {}),
1564
+ ...(hasMessages
1565
+ ? {
1566
+ message_count: messages.length,
1567
+ roles: messages.map((m) => m.role),
1568
+ session_date: body.session_date ?? null,
1569
+ }
1570
+ : {}),
1571
+ },
1572
+ ...(body.scopes ? { scopes: body.scopes } : {}),
1573
+ event: { reason: 'source ingest command' },
1574
+ }, context.access, { adapter });
1575
+ // The observation id is the ref later reads (source.read) name.
1576
+ return { ...receipt, observationRef: receipt.observationId };
1577
+ },
1578
+ },
1579
+ {
1580
+ contract: {
1581
+ name: 'work.list',
1582
+ summary: 'Page the owner-work commitment log under the caller authority — coverage reasons name rows outside the caller scopes rather than shortening the page silently.',
1583
+ inputSchema: workListSchema,
1584
+ examples: [
1585
+ { title: 'The current board, one page', input: { limit: 25 } },
1586
+ {
1587
+ title: 'What the board looked like then',
1588
+ input: { asOf: 1760000000000, history: 'all' },
1589
+ },
1590
+ ],
1591
+ },
1592
+ exec: (input, context) => knowledge.readWork(input, context.access),
1593
+ },
1594
+ {
1595
+ contract: {
1596
+ name: 'work.show',
1597
+ summary: 'One commitment by commitmentId (or rowId): the revision chain by default, or every revision with full values when history: all.',
1598
+ inputSchema: workShowSchema,
1599
+ examples: [
1600
+ { title: 'One task as it stands', input: { commitmentId: 'commitment_…' } },
1601
+ {
1602
+ title: 'Every revision it ever took',
1603
+ input: { commitmentId: 'commitment_…', history: 'all' },
1604
+ },
1605
+ ],
1606
+ },
1607
+ exec: (input, context) => {
1608
+ const body = input;
1609
+ if (body.commitmentId === undefined && body.rowId === undefined) {
1610
+ throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'work.show requires commitmentId or rowId: name the commitment');
1611
+ }
1612
+ return knowledge.readWork(body.history === undefined ? { ...body, history: 'chain' } : body, context.access);
1613
+ },
1614
+ },
1615
+ ...(effects !== undefined
1616
+ ? [
1617
+ {
1618
+ contract: {
1619
+ name: 'work.changes',
1620
+ summary: 'What this system durably changed in a window, with coverage. Use view=turn_inputs and an effect_id to page the accepted inputs in its native model turn; that relation is turn context, not an assertion that every input directly caused the effect.',
1621
+ inputSchema: {
1622
+ type: 'object',
1623
+ additionalProperties: false,
1624
+ properties: {
1625
+ view: {
1626
+ type: 'string',
1627
+ enum: ['changes', 'turn_inputs'],
1628
+ description: 'Changes view, e.g. "changes".',
1629
+ },
1630
+ effect_id: {
1631
+ type: 'integer',
1632
+ minimum: 1,
1633
+ description: 'Effect id for native-turn inputs, e.g. 1.',
1634
+ },
1635
+ cursor: {
1636
+ type: 'integer',
1637
+ minimum: 0,
1638
+ description: 'Numeric effect cursor, e.g. 0.',
1639
+ },
1640
+ since: { type: 'string', description: 'Window start, e.g. "7d" or an ISO time.' },
1641
+ target_type: {
1642
+ type: 'string',
1643
+ enum: [...operations_js_1.CHANGES_READ_TARGET_TYPES],
1644
+ description: 'Changed target type, e.g. "memory".',
1645
+ },
1646
+ cause_state: {
1647
+ type: 'string',
1648
+ enum: [...operations_js_1.CHANGES_READ_CAUSE_STATES],
1649
+ description: 'Cause attribution state, e.g. "unattributed".',
1650
+ },
1651
+ limit: {
1652
+ description: 'Maximum changes or inputs, e.g. 25.',
1653
+ oneOf: [
1654
+ { type: 'integer', minimum: 1 },
1655
+ { type: 'string', minLength: 1 },
1656
+ ],
1657
+ },
1658
+ },
1659
+ },
1660
+ examples: [
1661
+ { title: 'What changed today', input: {} },
1662
+ {
1663
+ title: 'Unexplained task changes this week',
1664
+ input: { since: '7d', target_type: 'task', cause_state: 'unattributed' },
1665
+ },
1666
+ {
1667
+ title: 'Inputs in one effect’s native turn',
1668
+ input: { view: 'turn_inputs', effect_id: 1, limit: 25 },
1669
+ },
1670
+ ],
1671
+ },
1672
+ exec: (input, context) => {
1673
+ const body = input;
1674
+ if (body.view === 'turn_inputs') {
1675
+ if (body.since !== undefined ||
1676
+ body.target_type !== undefined ||
1677
+ body.cause_state !== undefined) {
1678
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'turn_inputs reads one effect; window filters do not apply');
1679
+ }
1680
+ const effectId = body.effect_id;
1681
+ const limit = body.limit === undefined ? 25 : Number(body.limit);
1682
+ const afterId = body.cursor === undefined ? 0 : body.cursor;
1683
+ if (typeof effectId !== 'number' ||
1684
+ !Number.isSafeInteger(effectId) ||
1685
+ effectId < 1 ||
1686
+ !Number.isSafeInteger(limit) ||
1687
+ limit < 1 ||
1688
+ limit > 100 ||
1689
+ typeof afterId !== 'number' ||
1690
+ !Number.isSafeInteger(afterId) ||
1691
+ afterId < 0) {
1692
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'turn_inputs requires a valid effect_id, limit and cursor');
1693
+ }
1694
+ if (!effects.listTurnInputs) {
1695
+ throw new judgments_js_1.JudgmentError('TOOL_ERROR', 'Native turn input reader is not configured');
1696
+ }
1697
+ const change = effects.listChanges({ id: effectId, limit: 1 })[0];
1698
+ if (!change?.runId) {
1699
+ throw new judgments_js_1.JudgmentError('NOT_FOUND', 'Native turn context is not visible');
1700
+ }
1701
+ let page;
1702
+ try {
1703
+ page = effects.listTurnInputs(change.runId, context.access.principalId, {
1704
+ afterId,
1705
+ limit,
1706
+ });
1707
+ }
1708
+ catch (error) {
1709
+ const message = error instanceof Error ? error.message : String(error);
1710
+ if (/Model run not found|matching principal-bound|no accepted native turn receipt/.test(message)) {
1711
+ throw new judgments_js_1.JudgmentError('NOT_FOUND', 'Native turn context is not visible');
1712
+ }
1713
+ throw error;
1714
+ }
1715
+ return {
1716
+ success: true,
1717
+ view: 'turn_inputs',
1718
+ effect_id: effectId,
1719
+ run_id: change.runId,
1720
+ relation: 'shared_native_turn_context',
1721
+ direct_cause_event_ids: change.sourceEventIds,
1722
+ run_status: page.runStatus,
1723
+ returned: page.items.length,
1724
+ next_cursor: page.nextCursor,
1725
+ items: page.items,
1726
+ };
1727
+ }
1728
+ if (body.effect_id !== undefined || body.cursor !== undefined) {
1729
+ throw new judgments_js_1.JudgmentError('INVALID_INPUT', 'effect_id and cursor require view=turn_inputs');
1730
+ }
1731
+ const result = (0, operations_js_1.readChanges)(effects, input, Date.now());
1732
+ if (!result.success) {
1733
+ throw new judgments_js_1.JudgmentError(result.code, result.error);
1734
+ }
1735
+ return result;
1736
+ },
1737
+ },
1738
+ ]
1739
+ : []),
1740
+ {
1741
+ contract: {
1742
+ name: 'operation.get',
1743
+ summary: 'Settle a call whose reply was lost: which command the operationId bound to, under whose authority, and the receipt it committed. An operationId that is absent — or belongs to another principal — answers unavailable, never existence.',
1744
+ inputSchema: operationGetSchema,
1745
+ examples: [
1746
+ {
1747
+ title: 'A reply lost after commit',
1748
+ input: { operationId: 'op_…' },
1749
+ },
1750
+ ],
1751
+ },
1752
+ exec: (input, context) => (0, operations_js_1.readOperation)(adapter, input.operationId, context.access),
1753
+ },
1754
+ ];
1755
+ }
1756
+ //# sourceMappingURL=catalog.js.map