@abloatai/ablo 0.36.0 → 0.37.1

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 (597) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +55 -2014
  3. package/NOTICE +2 -2
  4. package/README.md +45 -63
  5. package/assets/banner.png +0 -0
  6. package/dist/auth.d.ts +2 -0
  7. package/dist/auth.d.ts.map +1 -0
  8. package/dist/auth.js +2 -0
  9. package/dist/auth.js.map +1 -0
  10. package/dist/client.d.ts +3 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +3 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/coordination.d.ts +2 -0
  15. package/dist/coordination.d.ts.map +1 -0
  16. package/dist/coordination.js +2 -0
  17. package/dist/coordination.js.map +1 -0
  18. package/dist/index.d.ts +3 -114
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +3 -163
  21. package/dist/index.js.map +1 -0
  22. package/dist/react.d.ts +4 -0
  23. package/dist/react.d.ts.map +1 -0
  24. package/dist/react.js +3 -0
  25. package/dist/react.js.map +1 -0
  26. package/dist/schema.d.ts +2 -0
  27. package/dist/schema.d.ts.map +1 -0
  28. package/dist/schema.js +2 -0
  29. package/dist/schema.js.map +1 -0
  30. package/dist/server.d.ts +2 -0
  31. package/dist/server.d.ts.map +1 -0
  32. package/dist/server.js +2 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/source-conformance.d.ts +2 -0
  35. package/dist/source-conformance.d.ts.map +1 -0
  36. package/dist/source-conformance.js +2 -0
  37. package/dist/source-conformance.js.map +1 -0
  38. package/dist/source-drizzle.d.ts +2 -0
  39. package/dist/source-drizzle.d.ts.map +1 -0
  40. package/dist/source-drizzle.js +2 -0
  41. package/dist/source-drizzle.js.map +1 -0
  42. package/dist/source-kysely.d.ts +2 -0
  43. package/dist/source-kysely.d.ts.map +1 -0
  44. package/dist/source-kysely.js +2 -0
  45. package/dist/source-kysely.js.map +1 -0
  46. package/dist/source-next.d.ts +2 -0
  47. package/dist/source-next.d.ts.map +1 -0
  48. package/dist/source-next.js +2 -0
  49. package/dist/source-next.js.map +1 -0
  50. package/dist/source.d.ts +2 -0
  51. package/dist/source.d.ts.map +1 -0
  52. package/dist/source.js +2 -0
  53. package/dist/source.js.map +1 -0
  54. package/dist/wire.d.ts +2 -0
  55. package/dist/wire.d.ts.map +1 -0
  56. package/dist/wire.js +2 -0
  57. package/dist/wire.js.map +1 -0
  58. package/docs/agents.md +1 -1
  59. package/docs/api-keys.md +7 -6
  60. package/docs/api.md +10 -10
  61. package/docs/client-behavior.md +5 -5
  62. package/docs/coordination.md +52 -62
  63. package/docs/data-sources.md +1 -1
  64. package/docs/examples/agent-human.md +4 -4
  65. package/docs/examples/ai-sdk-tool.md +1 -1
  66. package/docs/examples/existing-python-backend.md +15 -4
  67. package/docs/examples/nextjs.md +27 -6
  68. package/docs/examples/server-agent.md +2 -2
  69. package/docs/how-it-works.md +4 -4
  70. package/docs/identity.md +2 -1
  71. package/docs/integration-guide.md +24 -13
  72. package/docs/internal/README.md +18 -0
  73. package/docs/internal/agent-fleet-coordination-design.md +171 -0
  74. package/docs/internal/agent-orchestration.md +58 -0
  75. package/docs/internal/commit-identifiers.md +91 -0
  76. package/docs/internal/concurrency-open-decisions.md +37 -0
  77. package/docs/internal/data-source-reverse-channel.md +150 -0
  78. package/docs/internal/per-field-conflict-detection.md +165 -0
  79. package/docs/internal/postgres-replication.md +64 -0
  80. package/docs/internal/serializable-schema.md +119 -0
  81. package/docs/internal/structure.md +32 -0
  82. package/docs/mcp.md +2 -2
  83. package/docs/migration.md +3 -3
  84. package/docs/quickstart.md +2 -2
  85. package/docs/react.md +5 -5
  86. package/docs/schema-contract.md +3 -3
  87. package/docs/sessions.md +91 -37
  88. package/examples/README.md +2 -2
  89. package/examples/data-source/README.md +1 -1
  90. package/examples/data-source/ablo-driver.ts +1 -1
  91. package/examples/data-source/customer-server.ts +1 -1
  92. package/examples/data-source/run.ts +1 -1
  93. package/examples/data-source/schema.ts +1 -1
  94. package/examples/quickstart.ts +2 -2
  95. package/llms.txt +8 -8
  96. package/package.json +63 -166
  97. package/bin/ablo.cjs +0 -39
  98. package/dist/BaseSyncedStore.d.ts +0 -843
  99. package/dist/BaseSyncedStore.js +0 -1971
  100. package/dist/Database.d.ts +0 -323
  101. package/dist/Database.js +0 -1502
  102. package/dist/InstanceCache.d.ts +0 -237
  103. package/dist/InstanceCache.js +0 -1166
  104. package/dist/LazyReferenceCollection.d.ts +0 -177
  105. package/dist/LazyReferenceCollection.js +0 -461
  106. package/dist/Model.d.ts +0 -454
  107. package/dist/Model.js +0 -919
  108. package/dist/ModelRegistry.d.ts +0 -225
  109. package/dist/ModelRegistry.js +0 -539
  110. package/dist/NetworkMonitor.d.ts +0 -28
  111. package/dist/NetworkMonitor.js +0 -79
  112. package/dist/RuntimeContext.d.ts +0 -52
  113. package/dist/RuntimeContext.js +0 -80
  114. package/dist/SyncClient.d.ts +0 -541
  115. package/dist/SyncClient.js +0 -2202
  116. package/dist/adapters/alwaysOnline.d.ts +0 -14
  117. package/dist/adapters/alwaysOnline.js +0 -17
  118. package/dist/adapters/inMemoryStorage.d.ts +0 -31
  119. package/dist/adapters/inMemoryStorage.js +0 -110
  120. package/dist/ai-sdk/coordinatedTool.d.ts +0 -120
  121. package/dist/ai-sdk/coordinatedTool.js +0 -134
  122. package/dist/ai-sdk/coordinationContext.d.ts +0 -46
  123. package/dist/ai-sdk/coordinationContext.js +0 -106
  124. package/dist/ai-sdk/index.d.ts +0 -121
  125. package/dist/ai-sdk/index.js +0 -121
  126. package/dist/ai-sdk/wrap.d.ts +0 -65
  127. package/dist/ai-sdk/wrap.js +0 -39
  128. package/dist/auth/index.d.ts +0 -1
  129. package/dist/auth/index.js +0 -8
  130. package/dist/batching/index.d.ts +0 -55
  131. package/dist/batching/index.js +0 -147
  132. package/dist/client/Ablo.d.ts +0 -231
  133. package/dist/client/Ablo.js +0 -160
  134. package/dist/client/abloClient.d.ts +0 -309
  135. package/dist/client/abloClient.js +0 -13
  136. package/dist/client/clientPrelude.d.ts +0 -52
  137. package/dist/client/clientPrelude.js +0 -60
  138. package/dist/client/consoleLogger.d.ts +0 -35
  139. package/dist/client/consoleLogger.js +0 -44
  140. package/dist/client/coreClient.d.ts +0 -60
  141. package/dist/client/coreClient.js +0 -118
  142. package/dist/client/createInternalComponents.d.ts +0 -50
  143. package/dist/client/createInternalComponents.js +0 -98
  144. package/dist/client/createModelProxy.d.ts +0 -248
  145. package/dist/client/createModelProxy.js +0 -884
  146. package/dist/client/humans.d.ts +0 -69
  147. package/dist/client/humans.js +0 -78
  148. package/dist/client/modelRegistration.d.ts +0 -10
  149. package/dist/client/modelRegistration.js +0 -312
  150. package/dist/client/options.d.ts +0 -461
  151. package/dist/client/options.js +0 -7
  152. package/dist/client/reactiveEngine.d.ts +0 -53
  153. package/dist/client/reactiveEngine.js +0 -688
  154. package/dist/client/resourceTypes.d.ts +0 -12
  155. package/dist/client/resourceTypes.js +0 -10
  156. package/dist/client/schemaConfig.d.ts +0 -44
  157. package/dist/client/schemaConfig.js +0 -185
  158. package/dist/client/storeCluster.d.ts +0 -47
  159. package/dist/client/storeCluster.js +0 -118
  160. package/dist/client/storeLifecycle.d.ts +0 -61
  161. package/dist/client/storeLifecycle.js +0 -231
  162. package/dist/client/validateAbloOptions.d.ts +0 -42
  163. package/dist/client/validateAbloOptions.js +0 -43
  164. package/dist/client/wsMutationExecutor.d.ts +0 -27
  165. package/dist/client/wsMutationExecutor.js +0 -72
  166. package/dist/context.d.ts +0 -42
  167. package/dist/context.js +0 -81
  168. package/dist/coordination/ClaimLog.d.ts +0 -26
  169. package/dist/coordination/ClaimLog.js +0 -32
  170. package/dist/coordination/index.d.ts +0 -1
  171. package/dist/coordination/index.js +0 -8
  172. package/dist/core/index.d.ts +0 -33
  173. package/dist/core/index.js +0 -48
  174. package/dist/docs/catalog.d.ts +0 -72
  175. package/dist/docs/catalog.js +0 -230
  176. package/dist/docs/index.d.ts +0 -10
  177. package/dist/docs/index.js +0 -10
  178. package/dist/environment.d.ts +0 -1
  179. package/dist/environment.js +0 -8
  180. package/dist/interfaces/index.d.ts +0 -311
  181. package/dist/interfaces/index.js +0 -9
  182. package/dist/keys/index.d.ts +0 -1
  183. package/dist/keys/index.js +0 -8
  184. package/dist/mutators/RecordingMutation.d.ts +0 -36
  185. package/dist/mutators/RecordingMutation.js +0 -182
  186. package/dist/mutators/Transaction.d.ts +0 -40
  187. package/dist/mutators/Transaction.js +0 -58
  188. package/dist/mutators/UndoManager.d.ts +0 -258
  189. package/dist/mutators/UndoManager.js +0 -658
  190. package/dist/mutators/defineMutators.d.ts +0 -60
  191. package/dist/mutators/defineMutators.js +0 -18
  192. package/dist/mutators/inverseOp.d.ts +0 -126
  193. package/dist/mutators/inverseOp.js +0 -71
  194. package/dist/mutators/mutateActions.d.ts +0 -45
  195. package/dist/mutators/mutateActions.js +0 -105
  196. package/dist/mutators/readerActions.d.ts +0 -33
  197. package/dist/mutators/readerActions.js +0 -57
  198. package/dist/mutators/undoApply.d.ts +0 -51
  199. package/dist/mutators/undoApply.js +0 -117
  200. package/dist/policy/index.d.ts +0 -21
  201. package/dist/policy/index.js +0 -20
  202. package/dist/query/QueryProcessor.d.ts +0 -75
  203. package/dist/query/QueryProcessor.js +0 -255
  204. package/dist/query/client.d.ts +0 -64
  205. package/dist/query/client.js +0 -138
  206. package/dist/query/types.d.ts +0 -85
  207. package/dist/query/types.js +0 -16
  208. package/dist/react/AbloProvider.d.ts +0 -242
  209. package/dist/react/AbloProvider.js +0 -458
  210. package/dist/react/ClientSideSuspense.d.ts +0 -36
  211. package/dist/react/ClientSideSuspense.js +0 -17
  212. package/dist/react/DefaultFallback.d.ts +0 -24
  213. package/dist/react/DefaultFallback.js +0 -43
  214. package/dist/react/context.d.ts +0 -55
  215. package/dist/react/context.js +0 -29
  216. package/dist/react/createAbloReact.d.ts +0 -56
  217. package/dist/react/createAbloReact.js +0 -51
  218. package/dist/react/index.d.ts +0 -62
  219. package/dist/react/index.js +0 -69
  220. package/dist/react/internalContext.d.ts +0 -33
  221. package/dist/react/internalContext.js +0 -3
  222. package/dist/react/useAblo.d.ts +0 -82
  223. package/dist/react/useAblo.js +0 -120
  224. package/dist/react/useCurrentUserId.d.ts +0 -22
  225. package/dist/react/useCurrentUserId.js +0 -34
  226. package/dist/react/useErrorListener.d.ts +0 -20
  227. package/dist/react/useErrorListener.js +0 -38
  228. package/dist/react/useMutationFailureListener.d.ts +0 -26
  229. package/dist/react/useMutationFailureListener.js +0 -38
  230. package/dist/react/useMutators.d.ts +0 -56
  231. package/dist/react/useMutators.js +0 -84
  232. package/dist/react/useReactive.d.ts +0 -35
  233. package/dist/react/useReactive.js +0 -123
  234. package/dist/react/useSyncStatus.d.ts +0 -59
  235. package/dist/react/useSyncStatus.js +0 -76
  236. package/dist/react/useUndoScope.d.ts +0 -34
  237. package/dist/react/useUndoScope.js +0 -81
  238. package/dist/schema/coordination.d.ts +0 -112
  239. package/dist/schema/coordination.js +0 -133
  240. package/dist/schema/ddl.d.ts +0 -97
  241. package/dist/schema/ddl.js +0 -491
  242. package/dist/schema/ddlLock.d.ts +0 -35
  243. package/dist/schema/ddlLock.js +0 -46
  244. package/dist/schema/diff.d.ts +0 -225
  245. package/dist/schema/diff.js +0 -289
  246. package/dist/schema/generate.d.ts +0 -19
  247. package/dist/schema/generate.js +0 -86
  248. package/dist/schema/index.d.ts +0 -42
  249. package/dist/schema/index.js +0 -80
  250. package/dist/schema/queries.d.ts +0 -201
  251. package/dist/schema/queries.js +0 -144
  252. package/dist/schema/select.d.ts +0 -40
  253. package/dist/schema/select.js +0 -90
  254. package/dist/schema/serialize.d.ts +0 -115
  255. package/dist/schema/serialize.js +0 -265
  256. package/dist/schema/sugar.d.ts +0 -109
  257. package/dist/schema/sugar.js +0 -83
  258. package/dist/schema/syncDeltaRow.d.ts +0 -6
  259. package/dist/schema/syncDeltaRow.js +0 -6
  260. package/dist/server/adapter.d.ts +0 -173
  261. package/dist/server/adapter.js +0 -18
  262. package/dist/server/commit.d.ts +0 -107
  263. package/dist/server/commit.js +0 -1
  264. package/dist/server/index.d.ts +0 -14
  265. package/dist/server/index.js +0 -2
  266. package/dist/server/readConfig.d.ts +0 -80
  267. package/dist/server/readConfig.js +0 -8
  268. package/dist/server/storageMode.d.ts +0 -23
  269. package/dist/server/storageMode.js +0 -17
  270. package/dist/source/adapter.d.ts +0 -83
  271. package/dist/source/adapter.js +0 -24
  272. package/dist/source/adapters/drizzle.d.ts +0 -48
  273. package/dist/source/adapters/drizzle.js +0 -219
  274. package/dist/source/adapters/kysely.d.ts +0 -42
  275. package/dist/source/adapters/kysely.js +0 -205
  276. package/dist/source/adapters/kyselyMutationCore.d.ts +0 -76
  277. package/dist/source/adapters/kyselyMutationCore.js +0 -125
  278. package/dist/source/adapters/memory.d.ts +0 -13
  279. package/dist/source/adapters/memory.js +0 -130
  280. package/dist/source/adapters/prisma.d.ts +0 -63
  281. package/dist/source/adapters/prisma.js +0 -202
  282. package/dist/source/conformance.d.ts +0 -37
  283. package/dist/source/conformance.js +0 -215
  284. package/dist/source/connector.d.ts +0 -95
  285. package/dist/source/connector.js +0 -266
  286. package/dist/source/connectorProtocol.d.ts +0 -154
  287. package/dist/source/connectorProtocol.js +0 -163
  288. package/dist/source/contract.d.ts +0 -195
  289. package/dist/source/contract.js +0 -164
  290. package/dist/source/factory.d.ts +0 -92
  291. package/dist/source/factory.js +0 -286
  292. package/dist/source/idempotency.d.ts +0 -61
  293. package/dist/source/idempotency.js +0 -144
  294. package/dist/source/index.d.ts +0 -23
  295. package/dist/source/index.js +0 -30
  296. package/dist/source/migrations.d.ts +0 -21
  297. package/dist/source/migrations.js +0 -103
  298. package/dist/source/next.d.ts +0 -32
  299. package/dist/source/next.js +0 -25
  300. package/dist/source/pushQueue.d.ts +0 -134
  301. package/dist/source/pushQueue.js +0 -256
  302. package/dist/source/signing.d.ts +0 -92
  303. package/dist/source/signing.js +0 -162
  304. package/dist/source/types.d.ts +0 -401
  305. package/dist/source/types.js +0 -59
  306. package/dist/storeContract.d.ts +0 -145
  307. package/dist/storeContract.js +0 -12
  308. package/dist/stores/DatabaseManager.d.ts +0 -107
  309. package/dist/stores/DatabaseManager.js +0 -388
  310. package/dist/stores/ObjectStore.d.ts +0 -115
  311. package/dist/stores/ObjectStore.js +0 -393
  312. package/dist/stores/ObjectStoreContract.d.ts +0 -38
  313. package/dist/stores/ObjectStoreContract.js +0 -1
  314. package/dist/stores/StoreManager.d.ts +0 -114
  315. package/dist/stores/StoreManager.js +0 -304
  316. package/dist/stores/SyncActionStore.d.ts +0 -99
  317. package/dist/stores/SyncActionStore.js +0 -506
  318. package/dist/stores/openIDBWithTimeout.d.ts +0 -65
  319. package/dist/stores/openIDBWithTimeout.js +0 -153
  320. package/dist/stores/syncAction.d.ts +0 -26
  321. package/dist/stores/syncAction.js +0 -16
  322. package/dist/surface.d.ts +0 -36
  323. package/dist/surface.js +0 -75
  324. package/dist/sync/BootstrapFetcher.d.ts +0 -284
  325. package/dist/sync/BootstrapFetcher.js +0 -964
  326. package/dist/sync/ConnectionManager.d.ts +0 -8
  327. package/dist/sync/ConnectionManager.js +0 -8
  328. package/dist/sync/OnDemandLoader.d.ts +0 -231
  329. package/dist/sync/OnDemandLoader.js +0 -743
  330. package/dist/sync/SubscriptionManager.d.ts +0 -159
  331. package/dist/sync/SubscriptionManager.js +0 -243
  332. package/dist/sync/SyncWebSocket.d.ts +0 -173
  333. package/dist/sync/SyncWebSocket.js +0 -438
  334. package/dist/sync/awaitClaimGrant.d.ts +0 -6
  335. package/dist/sync/awaitClaimGrant.js +0 -6
  336. package/dist/sync/bootstrapApply.d.ts +0 -73
  337. package/dist/sync/bootstrapApply.js +0 -73
  338. package/dist/sync/commitFrames.d.ts +0 -8
  339. package/dist/sync/commitFrames.js +0 -8
  340. package/dist/sync/contextPorts.d.ts +0 -18
  341. package/dist/sync/contextPorts.js +0 -31
  342. package/dist/sync/createClaimStream.d.ts +0 -7
  343. package/dist/sync/createClaimStream.js +0 -7
  344. package/dist/sync/createPresenceStream.d.ts +0 -69
  345. package/dist/sync/createPresenceStream.js +0 -200
  346. package/dist/sync/createSnapshot.d.ts +0 -29
  347. package/dist/sync/createSnapshot.js +0 -118
  348. package/dist/sync/credentialLifecycle.d.ts +0 -7
  349. package/dist/sync/credentialLifecycle.js +0 -7
  350. package/dist/sync/deltaPipeline.d.ts +0 -114
  351. package/dist/sync/deltaPipeline.js +0 -278
  352. package/dist/sync/groupChange.d.ts +0 -116
  353. package/dist/sync/groupChange.js +0 -244
  354. package/dist/sync/participants.d.ts +0 -132
  355. package/dist/sync/participants.js +0 -346
  356. package/dist/sync/persistedPrefix.d.ts +0 -12
  357. package/dist/sync/persistedPrefix.js +0 -22
  358. package/dist/sync/schemaDrift.d.ts +0 -55
  359. package/dist/sync/schemaDrift.js +0 -53
  360. package/dist/sync/schemas.d.ts +0 -71
  361. package/dist/sync/schemas.js +0 -94
  362. package/dist/sync/syncCursor.d.ts +0 -40
  363. package/dist/sync/syncCursor.js +0 -55
  364. package/dist/sync/syncPlan.d.ts +0 -54
  365. package/dist/sync/syncPlan.js +0 -50
  366. package/dist/sync/wsFrameHandlers.d.ts +0 -8
  367. package/dist/sync/wsFrameHandlers.js +0 -8
  368. package/dist/syncLog/contract.d.ts +0 -20
  369. package/dist/syncLog/contract.js +0 -19
  370. package/dist/syncLog/index.d.ts +0 -1
  371. package/dist/syncLog/index.js +0 -1
  372. package/dist/transaction/ablo.d.ts +0 -88
  373. package/dist/transaction/ablo.js +0 -33
  374. package/dist/transaction/auth/apiKey.d.ts +0 -152
  375. package/dist/transaction/auth/apiKey.js +0 -419
  376. package/dist/transaction/auth/bootstrapScope.d.ts +0 -15
  377. package/dist/transaction/auth/bootstrapScope.js +0 -1
  378. package/dist/transaction/auth/capability.d.ts +0 -212
  379. package/dist/transaction/auth/capability.js +0 -224
  380. package/dist/transaction/auth/credentialEndpoint.d.ts +0 -61
  381. package/dist/transaction/auth/credentialEndpoint.js +0 -86
  382. package/dist/transaction/auth/credentialPolicy.d.ts +0 -148
  383. package/dist/transaction/auth/credentialPolicy.js +0 -125
  384. package/dist/transaction/auth/credentialSource.d.ts +0 -30
  385. package/dist/transaction/auth/credentialSource.js +0 -55
  386. package/dist/transaction/auth/hostedEndpoints.d.ts +0 -21
  387. package/dist/transaction/auth/hostedEndpoints.js +0 -21
  388. package/dist/transaction/auth/identity.d.ts +0 -55
  389. package/dist/transaction/auth/identity.js +0 -210
  390. package/dist/transaction/auth/index.d.ts +0 -162
  391. package/dist/transaction/auth/index.js +0 -304
  392. package/dist/transaction/auth/schemas.d.ts +0 -59
  393. package/dist/transaction/auth/schemas.js +0 -85
  394. package/dist/transaction/auth/sessionMint.d.ts +0 -28
  395. package/dist/transaction/auth/sessionMint.js +0 -85
  396. package/dist/transaction/coordination/awaitClaimGrant.d.ts +0 -56
  397. package/dist/transaction/coordination/awaitClaimGrant.js +0 -124
  398. package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +0 -84
  399. package/dist/transaction/coordination/claimHeartbeatLoop.js +0 -108
  400. package/dist/transaction/coordination/claimMeta.d.ts +0 -49
  401. package/dist/transaction/coordination/claimMeta.js +0 -52
  402. package/dist/transaction/coordination/createClaimStream.d.ts +0 -64
  403. package/dist/transaction/coordination/createClaimStream.js +0 -475
  404. package/dist/transaction/coordination/events.d.ts +0 -74
  405. package/dist/transaction/coordination/events.js +0 -7
  406. package/dist/transaction/coordination/index.d.ts +0 -19
  407. package/dist/transaction/coordination/index.js +0 -45
  408. package/dist/transaction/coordination/locator.d.ts +0 -104
  409. package/dist/transaction/coordination/locator.js +0 -102
  410. package/dist/transaction/coordination/schema.d.ts +0 -1536
  411. package/dist/transaction/coordination/schema.js +0 -1177
  412. package/dist/transaction/coordination/targetConflict.d.ts +0 -2
  413. package/dist/transaction/coordination/targetConflict.js +0 -107
  414. package/dist/transaction/coordination/trace.d.ts +0 -78
  415. package/dist/transaction/coordination/trace.js +0 -138
  416. package/dist/transaction/durableWrites.d.ts +0 -62
  417. package/dist/transaction/durableWrites.js +0 -71
  418. package/dist/transaction/environment.d.ts +0 -105
  419. package/dist/transaction/environment.js +0 -108
  420. package/dist/transaction/errorCodes.d.ts +0 -403
  421. package/dist/transaction/errorCodes.js +0 -484
  422. package/dist/transaction/errors.d.ts +0 -428
  423. package/dist/transaction/errors.js +0 -686
  424. package/dist/transaction/footprint.d.ts +0 -111
  425. package/dist/transaction/footprint.js +0 -0
  426. package/dist/transaction/index.d.ts +0 -20
  427. package/dist/transaction/index.js +0 -20
  428. package/dist/transaction/keys/index.d.ts +0 -87
  429. package/dist/transaction/keys/index.js +0 -207
  430. package/dist/transaction/log/syncDeltaRow.d.ts +0 -158
  431. package/dist/transaction/log/syncDeltaRow.js +0 -95
  432. package/dist/transaction/logPosition.d.ts +0 -97
  433. package/dist/transaction/logPosition.js +0 -125
  434. package/dist/transaction/logger.d.ts +0 -16
  435. package/dist/transaction/logger.js +0 -7
  436. package/dist/transaction/observability.d.ts +0 -53
  437. package/dist/transaction/observability.js +0 -19
  438. package/dist/transaction/persistence.d.ts +0 -12
  439. package/dist/transaction/persistence.js +0 -11
  440. package/dist/transaction/plugin.d.ts +0 -285
  441. package/dist/transaction/plugin.js +0 -106
  442. package/dist/transaction/policy/types.d.ts +0 -217
  443. package/dist/transaction/policy/types.js +0 -126
  444. package/dist/transaction/resources/functionalUpdate.d.ts +0 -79
  445. package/dist/transaction/resources/functionalUpdate.js +0 -87
  446. package/dist/transaction/resources/httpResources.d.ts +0 -321
  447. package/dist/transaction/resources/httpResources.js +0 -7
  448. package/dist/transaction/resources/modelOperations.d.ts +0 -427
  449. package/dist/transaction/resources/modelOperations.js +0 -12
  450. package/dist/transaction/resources/mutationOptions.d.ts +0 -66
  451. package/dist/transaction/resources/mutationOptions.js +0 -9
  452. package/dist/transaction/resources/where.d.ts +0 -101
  453. package/dist/transaction/resources/where.js +0 -115
  454. package/dist/transaction/resources/writeOptionsSchema.d.ts +0 -47
  455. package/dist/transaction/resources/writeOptionsSchema.js +0 -73
  456. package/dist/transaction/schema/field.d.ts +0 -120
  457. package/dist/transaction/schema/field.js +0 -265
  458. package/dist/transaction/schema/fieldRef.d.ts +0 -38
  459. package/dist/transaction/schema/fieldRef.js +0 -11
  460. package/dist/transaction/schema/loadStrategy.d.ts +0 -45
  461. package/dist/transaction/schema/loadStrategy.js +0 -46
  462. package/dist/transaction/schema/model.d.ts +0 -379
  463. package/dist/transaction/schema/model.js +0 -123
  464. package/dist/transaction/schema/openapi.d.ts +0 -58
  465. package/dist/transaction/schema/openapi.js +0 -501
  466. package/dist/transaction/schema/relation.d.ts +0 -204
  467. package/dist/transaction/schema/relation.js +0 -104
  468. package/dist/transaction/schema/residency.d.ts +0 -29
  469. package/dist/transaction/schema/residency.js +0 -25
  470. package/dist/transaction/schema/roles.d.ts +0 -249
  471. package/dist/transaction/schema/roles.js +0 -230
  472. package/dist/transaction/schema/schema.d.ts +0 -351
  473. package/dist/transaction/schema/schema.js +0 -325
  474. package/dist/transaction/schema/tenancy.d.ts +0 -139
  475. package/dist/transaction/schema/tenancy.js +0 -190
  476. package/dist/transaction/transactionLayer.d.ts +0 -82
  477. package/dist/transaction/transactionLayer.js +0 -24
  478. package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +0 -143
  479. package/dist/transaction/transactions/settlement/commitEnvelope.js +0 -161
  480. package/dist/transaction/transactions/settlement/httpCommitEnvelope.d.ts +0 -53
  481. package/dist/transaction/transactions/settlement/httpCommitEnvelope.js +0 -207
  482. package/dist/transaction/transactions/settlement/idempotencyKey.d.ts +0 -10
  483. package/dist/transaction/transactions/settlement/idempotencyKey.js +0 -9
  484. package/dist/transaction/transactions/settlement/pendingWrite.d.ts +0 -112
  485. package/dist/transaction/transactions/settlement/pendingWrite.js +0 -20
  486. package/dist/transaction/transport/commitFrames.d.ts +0 -90
  487. package/dist/transaction/transport/commitFrames.js +0 -134
  488. package/dist/transaction/transport/connectionManager.d.ts +0 -215
  489. package/dist/transaction/transport/connectionManager.js +0 -673
  490. package/dist/transaction/transport/credentialLifecycle.d.ts +0 -177
  491. package/dist/transaction/transport/credentialLifecycle.js +0 -324
  492. package/dist/transaction/transport/heartbeat.d.ts +0 -65
  493. package/dist/transaction/transport/heartbeat.js +0 -93
  494. package/dist/transaction/transport/httpClient.d.ts +0 -131
  495. package/dist/transaction/transport/httpClient.js +0 -146
  496. package/dist/transaction/transport/httpOptions.d.ts +0 -33
  497. package/dist/transaction/transport/httpOptions.js +0 -12
  498. package/dist/transaction/transport/httpTransport.d.ts +0 -8
  499. package/dist/transaction/transport/httpTransport.js +0 -1388
  500. package/dist/transaction/transport/networkProbe.d.ts +0 -84
  501. package/dist/transaction/transport/networkProbe.js +0 -207
  502. package/dist/transaction/transport/wsFrameHandlers.d.ts +0 -128
  503. package/dist/transaction/transport/wsFrameHandlers.js +0 -429
  504. package/dist/transaction/transport/wsTransport.d.ts +0 -574
  505. package/dist/transaction/transport/wsTransport.js +0 -1023
  506. package/dist/transaction/types/assertExact.d.ts +0 -17
  507. package/dist/transaction/types/assertExact.js +0 -1
  508. package/dist/transaction/types/global.d.ts +0 -107
  509. package/dist/transaction/types/global.js +0 -40
  510. package/dist/transaction/types/index.d.ts +0 -205
  511. package/dist/transaction/types/index.js +0 -56
  512. package/dist/transaction/types/modelData.d.ts +0 -10
  513. package/dist/transaction/types/modelData.js +0 -9
  514. package/dist/transaction/types/participant.d.ts +0 -20
  515. package/dist/transaction/types/participant.js +0 -10
  516. package/dist/transaction/types/streams.d.ts +0 -550
  517. package/dist/transaction/types/streams.js +0 -11
  518. package/dist/transaction/utils/asyncIterator.d.ts +0 -34
  519. package/dist/transaction/utils/asyncIterator.js +0 -135
  520. package/dist/transaction/utils/duration.d.ts +0 -50
  521. package/dist/transaction/utils/duration.js +0 -77
  522. package/dist/transaction/utils/json.d.ts +0 -57
  523. package/dist/transaction/utils/json.js +0 -276
  524. package/dist/transaction/wire/accountResponses.d.ts +0 -420
  525. package/dist/transaction/wire/accountResponses.js +0 -290
  526. package/dist/transaction/wire/auth.d.ts +0 -56
  527. package/dist/transaction/wire/auth.js +0 -63
  528. package/dist/transaction/wire/bootstrapReason.d.ts +0 -9
  529. package/dist/transaction/wire/bootstrapReason.js +0 -8
  530. package/dist/transaction/wire/claimEvent.d.ts +0 -76
  531. package/dist/transaction/wire/claimEvent.js +0 -73
  532. package/dist/transaction/wire/claims.d.ts +0 -530
  533. package/dist/transaction/wire/claims.js +0 -327
  534. package/dist/transaction/wire/commit.d.ts +0 -603
  535. package/dist/transaction/wire/commit.js +0 -321
  536. package/dist/transaction/wire/delta.d.ts +0 -250
  537. package/dist/transaction/wire/delta.js +0 -147
  538. package/dist/transaction/wire/errorEnvelope.d.ts +0 -72
  539. package/dist/transaction/wire/errorEnvelope.js +0 -123
  540. package/dist/transaction/wire/feedCursor.d.ts +0 -60
  541. package/dist/transaction/wire/feedCursor.js +0 -82
  542. package/dist/transaction/wire/feedEvent.d.ts +0 -204
  543. package/dist/transaction/wire/feedEvent.js +0 -65
  544. package/dist/transaction/wire/frames.d.ts +0 -194
  545. package/dist/transaction/wire/frames.js +0 -50
  546. package/dist/transaction/wire/inboundFrames.d.ts +0 -562
  547. package/dist/transaction/wire/inboundFrames.js +0 -116
  548. package/dist/transaction/wire/index.d.ts +0 -54
  549. package/dist/transaction/wire/index.js +0 -83
  550. package/dist/transaction/wire/listEnvelope.d.ts +0 -37
  551. package/dist/transaction/wire/listEnvelope.js +0 -42
  552. package/dist/transaction/wire/modelMutations.d.ts +0 -31
  553. package/dist/transaction/wire/modelMutations.js +0 -52
  554. package/dist/transaction/wire/modelResponses.d.ts +0 -85
  555. package/dist/transaction/wire/modelResponses.js +0 -43
  556. package/dist/transaction/wire/modelShape.d.ts +0 -78
  557. package/dist/transaction/wire/modelShape.js +0 -74
  558. package/dist/transaction/wire/protocol.d.ts +0 -38
  559. package/dist/transaction/wire/protocol.js +0 -38
  560. package/dist/transaction/wire/protocolVersion.d.ts +0 -73
  561. package/dist/transaction/wire/protocolVersion.js +0 -83
  562. package/dist/transactions/mutations/MutationQueue.d.ts +0 -661
  563. package/dist/transactions/mutations/MutationQueue.js +0 -2807
  564. package/dist/transactions/mutations/MutationStore.d.ts +0 -20
  565. package/dist/transactions/mutations/MutationStore.js +0 -53
  566. package/dist/transactions/mutations/UnconfirmedWrites.d.ts +0 -82
  567. package/dist/transactions/mutations/UnconfirmedWrites.js +0 -104
  568. package/dist/transactions/mutations/coalesceRules.d.ts +0 -58
  569. package/dist/transactions/mutations/coalesceRules.js +0 -140
  570. package/dist/transactions/mutations/commitLatency.d.ts +0 -52
  571. package/dist/transactions/mutations/commitLatency.js +0 -130
  572. package/dist/transactions/mutations/commitOutboxStore.d.ts +0 -28
  573. package/dist/transactions/mutations/commitOutboxStore.js +0 -26
  574. package/dist/transactions/mutations/commitPayload.d.ts +0 -165
  575. package/dist/transactions/mutations/commitPayload.js +0 -152
  576. package/dist/transactions/mutations/deltaConfirmation.d.ts +0 -63
  577. package/dist/transactions/mutations/deltaConfirmation.js +0 -235
  578. package/dist/transactions/mutations/durableWriteStore.d.ts +0 -14
  579. package/dist/transactions/mutations/durableWriteStore.js +0 -12
  580. package/dist/transactions/mutations/optimisticApply.d.ts +0 -49
  581. package/dist/transactions/mutations/optimisticApply.js +0 -65
  582. package/dist/transactions/mutations/replayValidation.d.ts +0 -187
  583. package/dist/transactions/mutations/replayValidation.js +0 -164
  584. package/dist/utils/mobxSetup.d.ts +0 -53
  585. package/dist/utils/mobxSetup.js +0 -330
  586. package/dist/views/QueryView.d.ts +0 -79
  587. package/dist/views/QueryView.js +0 -218
  588. package/dist/views/ViewRegistry.d.ts +0 -20
  589. package/dist/views/ViewRegistry.js +0 -55
  590. package/dist/views/incrementalView.d.ts +0 -45
  591. package/dist/views/incrementalView.js +0 -69
  592. package/dist/webhooks/events.d.ts +0 -43
  593. package/dist/webhooks/events.js +0 -42
  594. package/dist/webhooks/index.d.ts +0 -8
  595. package/dist/webhooks/index.js +0 -8
  596. package/dist/wire/index.d.ts +0 -1
  597. package/dist/wire/index.js +0 -8
@@ -30,6 +30,7 @@ The normal integration is one client:
30
30
 
31
31
  ```ts
32
32
  import Ablo from '@abloatai/ablo';
33
+ import { credentialEndpointSuccessSchema } from '@abloatai/ablo/auth';
33
34
  import { defineSchema, model, z } from '@abloatai/ablo/schema';
34
35
  ```
35
36
 
@@ -158,7 +159,7 @@ For rows that don't carry `organization_id` themselves but inherit tenancy via a
158
159
  foreign key, set `policy: { by: 'parent', fk: '<fk>', parent: '<parentTable>' }`.
159
160
  For genuinely global/reference data, `policy: { by: 'none' }`. ⚠ `by: 'none'`
160
161
  exposes the whole table cross-tenant, so it's an explicit, named branch — never a
161
- falsy flag. See `packages/sync-engine/src/schema/model.ts` for the full option set.
162
+ falsy flag. See `packages/transaction/src/schema/model.ts` for the full option set.
162
163
 
163
164
  ## 2. Create The Client
164
165
 
@@ -220,8 +221,18 @@ const sync = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
220
221
 
221
222
  export async function POST() {
222
223
  const session = await auth(); // your own auth — returns the signed-in user
223
- const { token } = await sync.sessions.create({ user: { id: session.userId } });
224
- return Response.json({ token });
224
+ const { token, expiresAt } = await sync.sessions.create({
225
+ user: { id: session.userId },
226
+ can: { tasks: ['read', 'update'] },
227
+ });
228
+ return Response.json(
229
+ credentialEndpointSuccessSchema.parse({
230
+ token,
231
+ expiresAt,
232
+ credentialKind: 'ephemeral',
233
+ }),
234
+ { headers: { 'Cache-Control': 'no-store' } },
235
+ );
225
236
  }
226
237
  ```
227
238
 
@@ -255,8 +266,8 @@ refreshes before expiry.
255
266
  ## 3. Read State
256
267
 
257
268
  Reads come in two flavors, and you pick based on whether you can wait.
258
- `retrieve({ id })` and `list({ where })` hit the server (and hydrate the local
259
- store) — they're async, so you `await` them. `get(id)` (positional),
269
+ `get({ id })` and `list({ where })` hit the server (and hydrate the local
270
+ store) — they're async, so you `await` them. `local.get(id)`,
260
271
  `local.list({ where })`, and `local.count({ where })` read the already-synced local
261
272
  graph synchronously, so they're the ones you call in render — and the ones you
262
273
  use inside a `useAblo` selector, never the async `retrieve`/`list`.
@@ -267,15 +278,15 @@ and waits.
267
278
  ```ts
268
279
  await ablo.ready();
269
280
 
270
- const report = await ablo.weatherReports.retrieve({ id: 'report_stockholm' });
281
+ const report = await ablo.weatherReports.get({ id: 'report_stockholm' });
271
282
  if (!report) throw new Error('report not found');
272
283
  ```
273
284
 
274
- Use `local.retrieve`, `local.list`, and `local.count` for synchronous local-graph reads after
285
+ Use `local.get`, `local.list`, and `local.count` for synchronous local-graph reads after
275
286
  data has synced.
276
287
 
277
288
  ```ts
278
- const report = ablo.weatherReports.local.retrieve('report_stockholm');
289
+ const report = ablo.weatherReports.local.get('report_stockholm');
279
290
  const activeReports = ablo.weatherReports.local.list({
280
291
  where: { projectId: 'proj_123' },
281
292
  filter: (report) => report.status !== 'ready',
@@ -296,7 +307,7 @@ export function ReportRow({
296
307
  }: {
297
308
  report: { id: string; location: string; status: string };
298
309
  }) {
299
- const report = useAblo((ablo) => ablo.weatherReports.local.retrieve(serverReport.id)) ?? serverReport;
310
+ const report = useAblo((ablo) => ablo.weatherReports.local.get(serverReport.id)) ?? serverReport;
300
311
  const active = useAblo((ablo) => ablo.weatherReports.claim.state({ id: serverReport.id }));
301
312
 
302
313
  return <button disabled={Boolean(active) || report.status === 'ready'}>{report.location}</button>;
@@ -387,7 +398,7 @@ The migration can be gradual:
387
398
 
388
399
  1. Declare schema for one model, such as `reports`.
389
400
  2. Keep existing server loads for first paint.
390
- 3. Add `useAblo((ablo) => ablo.weatherReports.local.retrieve(id)) ?? serverReport` for live rows.
401
+ 3. Add `useAblo((ablo) => ablo.weatherReports.local.get(id)) ?? serverReport` for live rows.
391
402
  4. Add one Data Source endpoint that calls the existing service layer.
392
403
  5. Move one mutation button from `fetch('/api/reports/...')` to `ablo.weatherReports.update(...)`.
393
404
  6. Add an outbox/events path for writes that still happen outside Ablo.
@@ -516,9 +527,9 @@ them.
516
527
 
517
528
  | Method | Use it for |
518
529
  | -------------------------------------- | -------------------------------------------------------------------------------- |
519
- | `retrieve({ id })` | Async read of one row from the server (await it). |
530
+ | `get({ id })` | Async read of one row from the server (await it). |
520
531
  | `list({ where })` | Async read of many rows from the server (await it). |
521
- | `get(id)` | Synchronous local read of one synced row (positional id; use in render). |
532
+ | `local.get(id)` | Synchronous local read of one synced row (use in render). |
522
533
  | `local.list({ where })` | Synchronous local read of many synced rows. |
523
534
  | `local.count({ where })` | Synchronous local count of synced rows. |
524
535
  | `create({ data, id? })` | Create through the model client. |
@@ -528,5 +539,5 @@ them.
528
539
  | `claim({ id, description?, ttl? })` | Acquire a disposable handle: wait for your turn, re-read, and hold the row. |
529
540
 
530
541
  Keep first integrations on the model methods above. Every mutation and
531
- server-read verb takes one options object; only the synchronous `get(id)` stays
542
+ server-read verb takes one options object; the synchronous `local.get(id)` stays
532
543
  positional.
@@ -0,0 +1,18 @@
1
+ # Internal Architecture Notes
2
+
3
+ These documents explain implementation and protocol decisions for contributors.
4
+ They are not extra public import paths.
5
+
6
+ The ownership rule is:
7
+
8
+ - transaction owns transport-neutral and HTTP contracts;
9
+ - humans owns reactive state, WebSockets, presence, browser persistence, and React;
10
+ - agent owns agent-specific behavior and perception;
11
+ - the branded `@abloatai/ablo` package maps stable public entrypoints to those
12
+ owners;
13
+ - `apps/sync-server` owns backend execution.
14
+
15
+ Consumer code should import `@abloatai/ablo` and its documented subpaths.
16
+ Contributor code should import the narrow owner package or module it actually
17
+ uses. Do not add forwarding compatibility packages or duplicate contract
18
+ definitions.
@@ -0,0 +1,171 @@
1
+ # Coordination as Eyes and Ears for Agent Fleets
2
+
3
+ The design intent behind claims, presence, and stale-context — stated as one
4
+ picture so it can be argued about and built against, not re-derived each time
5
+ someone asks "how do the coordination agents work?"
6
+
7
+ ## The thesis
8
+
9
+ Humans coordinating in a shared document already have everything they need:
10
+ they *see* each other's cursors, they *hover* to highlight the region they're
11
+ touching, and they *say* what they're doing ("I'm rewriting the intro"). Nobody
12
+ overwrites anybody because everybody has eyes and ears.
13
+
14
+ Agents don't. They work directly and silently, at machine speed, in fleets — say
15
+ 100 agents across 10 groups, each group on its own area of the data. The
16
+ coordination layer's job is to give that fleet the same social awareness a room
17
+ of humans has, expressed as a protocol: **see who is working where, learn what
18
+ they are doing, and take a turn instead of a collision.**
19
+
20
+ At fleet scale the load-bearing property is that this stays *local*. The layer
21
+ does not lock "the fleet." It coordinates per row. 100 agents over 10
22
+ non-overlapping areas are 100 parallel tracks that only ever meet on the
23
+ handful of rows two agents genuinely both want. Cost is paid at the overlap, not
24
+ across the fleet — which is why adding agents on separate areas adds no
25
+ coordination cost.
26
+
27
+ ## The one principle: two channels, never crossed
28
+
29
+ Awareness and safety are different channels, and keeping them apart is what makes
30
+ this safe *and* loop-free at machine speed.
31
+
32
+ - **Safety is pull, at write time.** An agent acts on its best read and its write
33
+ is rejected if the row moved underneath it. The rejection is the signal, and it
34
+ only ever fires when an agent actually chooses to write. A pull channel cannot
35
+ loop — nothing is being pushed.
36
+ - **Awareness is push, and it is the only channel that can storm.** So it is the
37
+ only channel we coalesce and rate-limit. Hot data that changes every
38
+ millisecond lives entirely on the safe *pull* side and therefore generates zero
39
+ awareness traffic — an agent that cares about a fast-ticking value just tries
40
+ its write and re-reads if it lost, rather than being woken on every tick.
41
+
42
+ Collapse the two channels — "notify every reader on every change" — and a
43
+ millisecond-ticking field produces read → notify → re-read → act → notify →
44
+ forever. Keeping them separate is the whole reason that loop can't form.
45
+
46
+ ## The six behaviors
47
+
48
+ ### 1. Eyes: see who is working where
49
+
50
+ Presence broadcasts, live, which agent holds which row. Before an agent commits
51
+ to work, it can see the area is already taken. This is advisory: it informs, it
52
+ forces nothing.
53
+
54
+ ```ts
55
+ const who = ablo.tasks.claim.state({ id: 'task_123' }); // holder or null
56
+ // who.heldBy === 'agent:forecaster'
57
+ // who.description === 'rewriting the risk section to match Q3'
58
+ ```
59
+
60
+ ### 2. Ears: learn *what* they are doing
61
+
62
+ A claim carries a single `description` — the machine version of the
63
+ hover-highlight plus the spoken "what I'm doing," in one field. It is the
64
+ sentence a peer reads to decide whether to wait, work elsewhere, or move on. It
65
+ defaults to `'editing'` when a claim is taken without one.
66
+
67
+ ```ts
68
+ await using claim = await ablo.tasks.claim({
69
+ id: 'task_123',
70
+ description: 'rewriting the risk section to match Q3 numbers',
71
+ });
72
+ ```
73
+
74
+ ### 3. Reject *before* the tokens are spent
75
+
76
+ The claim is a **cheap pre-flight, taken before the generation, not before the
77
+ write.** A human wastes nothing by starting to type into a locked paragraph; an
78
+ agent wastes a whole expensive completion. So the discipline is:
79
+
80
+ ```txt
81
+ claim (cheap) -> if granted: generate the block -> write
82
+ \-> if held: never generate anything
83
+ ```
84
+
85
+ An agent that is told "no" at the claim never produced the write that would have
86
+ lost — the large token spend simply did not happen. This is the single most
87
+ important reason the claim exists before the work, not after it.
88
+
89
+ ### 4. Reject *with* the description, so the blocked agent can decide
90
+
91
+ A bare "taken" forces a blind retry. The rejection carries the holder's
92
+ `description`, and the SDK renders it into the `AbloClaimedError` message:
93
+ *"Claimed by agent:forecaster: rewriting the risk section to match Q3."* So the
94
+ blocked agent reasons on real information: wait for the turn, go work somewhere
95
+ else, or drop the task because the work is already being done. "No, because
96
+ someone is rewriting the risk section" is actionable in a way "no" is not.
97
+
98
+ ### 5. Queue: take a turn, with an opt-out if the line is long
99
+
100
+ Contention is a fair FIFO queue: the blocked agent waits its turn and is
101
+ *notified* the moment it arrives (push, not poll — it does not sit and spin).
102
+ When promoted, it re-reads so it works from the latest, with the previous
103
+ holder's change already in place. And the queue has an opt-out: past a depth
104
+ bound, an agent is told the area is too busy and moves on rather than joining a
105
+ long line.
106
+
107
+ ```ts
108
+ await using claim = await ablo.tasks.claim({
109
+ id: 'task_123',
110
+ description: '...',
111
+ maxQueueDepth: 3, // don't join a line deeper than this
112
+ });
113
+ ```
114
+
115
+ ### 6. Notify on change: without acting on stale data, without looping
116
+
117
+ An agent that read a row and is about to act on it is stopped if the row moved
118
+ since the read; it re-reads instead of acting stale. Where a genuine
119
+ notification is wanted, it is **coalesced** (one settled signal, not a stream)
120
+ and **relevance-gated** (only the fields a decision depends on can wake the
121
+ agent). A fast-ticking value never wakes anyone; a rarely-changing value that
122
+ matters can push one settled signal. Same primitive, two behaviors, chosen by
123
+ whether reacting is worth it — see the two-channel principle above.
124
+
125
+ ## The three layers, as a rising scale
126
+
127
+ The behaviors above compose into three layers of increasing firmness. An agent
128
+ climbs only as high as the situation needs.
129
+
130
+ | Layer | Kind | What it does | Forces anything? |
131
+ | --- | --- | --- | --- |
132
+ | **Presence** | awareness (push) | Shows who holds what, and why, live. | No: informs only. |
133
+ | **Stale-context** | safety (pull) | Rejects a write built on a read the row has moved past. | Yes: at write time. |
134
+ | **Claim + queue** | reservation (push) | Reserves a row across a slow gap; contenders take turns. | Yes: mutual exclusion. |
135
+
136
+ Most work is a quick write and needs only the safety layer. An agent reaches for
137
+ a claim only when it will *hold* a row across a slow gap (read → LLM → write) —
138
+ the case where taking a turn beats colliding.
139
+
140
+ ## What's shipped, and the one open point
141
+
142
+ One piece of the fleet story that once read as future design work is already
143
+ built; one is genuinely still open. Both are called out so neither is misjudged.
144
+
145
+ 1. **Rich work surfaced at reject time — shipped.** A claim carries a single
146
+ `description` (behavior 2) as a first-class field on the wire. It rides the
147
+ presence broadcast, comes back inside the rejection's holder summary
148
+ (`heldByClaim`), and the SDK's `formatClaimedErrorMessage` renders it into the
149
+ `AbloClaimedError`. So "no" already becomes "no, because someone is rewriting
150
+ the risk section" (behavior 4) — the piece that prevents the wasteful blind
151
+ retry works today.
152
+
153
+ 2. **Coalesced, relevance-gated notify — open.** The anti-loop guarantee
154
+ (behavior 6) depends on the awareness channel being coalesced and gated by
155
+ relevance, and on hot data staying on the pull side. This is the sharp one,
156
+ and it is the one not yet built: what exists is the write-time pull guard
157
+ (`onStale`) and operation-level batching, not a coalesced, relevance-gated
158
+ *push* on the presence broadcast. Get it wrong and a millisecond-ticking field
159
+ storms the fleet. The rule to hold: an agent is *rejected at write time* on
160
+ hot data, never *subscribed-and-woken* by it.
161
+
162
+ ## Related
163
+
164
+ - [`coordination.md`](../coordination.md) — the public claim/queue/stale-context
165
+ reference this note motivates.
166
+ - [`agent-orchestration.md`](./agent-orchestration.md) — parent/child agent work
167
+ modeled through claimed job rows; this note is the coordination substrate under
168
+ it.
169
+ - ADR 0009 (`docs/decisions/0009-claim-durability-two-reclaim-clocks.md`) — what a
170
+ claim survives when a holder vanishes, and why liveness can be best-effort while
171
+ correctness is fenced at commit.
@@ -0,0 +1,58 @@
1
+ # Agent Orchestration
2
+
3
+ Do not model parent and child agents as directly talking to each other over WebSocket.
4
+
5
+ Model them as actors coordinating through models:
6
+
7
+ ```txt
8
+ parent creates job -> child claims job -> child commits result -> parent reads result
9
+ ```
10
+
11
+ The WebSocket is delivery infrastructure. The product model is shared state.
12
+
13
+ ## Model Shape
14
+
15
+ A parent creates a job through its typed model client:
16
+
17
+ ```ts
18
+ const jobId = `forecast:${runId}`;
19
+ await ablo.agentJobs.create({
20
+ id: jobId,
21
+ idempotencyKey: `job:${runId}`,
22
+ data: {
23
+ status: 'open',
24
+ kind: 'forecast_report',
25
+ target: { model: 'weatherReports', id: 'report_stockholm', field: 'forecast' },
26
+ },
27
+ wait: 'confirmed',
28
+ });
29
+ ```
30
+
31
+ The child claims the job. If another worker holds it, the claim waits fairly,
32
+ then returns the fresh row:
33
+
34
+ ```ts
35
+ await using claim = await ablo.agentJobs.claim({
36
+ id: jobId,
37
+ description: 'complete',
38
+ ttl: '5m',
39
+ });
40
+ const job = claim.data;
41
+
42
+ await ablo.agentJobs.update({
43
+ id: job.id,
44
+ data: {
45
+ status: 'completed',
46
+ result: { text },
47
+ },
48
+ });
49
+ ```
50
+
51
+ The child commits completion through the normal `update`, which is stale-guarded
52
+ under the held claim. The claim releases when its scope exits.
53
+
54
+ The parent retrieves the job result by model ID. Later, `ablo.events` can make that reactive, but the state model does not change.
55
+
56
+ ## Rule
57
+
58
+ Nested agents should create or complete models. They should not require a separate agent-to-agent protocol for normal work.
@@ -0,0 +1,91 @@
1
+ # Commit identifiers: the two axes
2
+
3
+ Maintainer reference. A commit carries several ids, and they are easy to
4
+ conflate because they travel together and are all "some number attached to a
5
+ write." They are not interchangeable. Each answers a different question, and
6
+ they split cleanly along **one line**: does this id help decide whether the
7
+ write *wins*, or does it only help *identify* the write after the fact?
8
+
9
+ Keeping the two axes separate is what lets each id be reasoned about — and
10
+ audited — on its own. This doc is the single place they sit side by side.
11
+
12
+ ## The line
13
+
14
+ | axis | the question it answers | when it acts | if it's absent |
15
+ |---|---|---|---|
16
+ | **Conflict resolution** | *should this write land, given what else happened?* | at the commit chokepoint, before the row is written | the write is unguarded (last-writer-wins) |
17
+ | **Correlation / audit** | *which write is this, and have I seen it before?* | on receipt (dedup) and after the fact (attribution) | the write still lands; you just can't dedup or trace it as precisely |
18
+
19
+ A conflict-resolution id can **reject** a commit. A correlation id never does —
20
+ at most it makes a retried commit a no-op (idempotency). Never reach for one to
21
+ do the other's job: a correlation id can't fence a stale write, and a fence
22
+ can't dedup a retry.
23
+
24
+ ## Axis 1: conflict resolution (does this write win?)
25
+
26
+ Evaluated inside `executeCommit`'s transaction, atomic with the delta write.
27
+ Three independent fences, each catching what the others can't; the full
28
+ narrative is [ADR 0009 §6](../../../../docs/decisions/0009-claim-durability-two-reclaim-clocks.md)
29
+ and the [coordination reference](../coordination.md).
30
+
31
+ | id | wire field | persisted to | what it asserts | rejects when |
32
+ |---|---|---|---|---|
33
+ | **read basis** | per-op `readAt` | `sync_deltas.read_at_sync_id` | "the state I reasoned **from**": a version watermark | the row moved since `readAt` (version-CAS), under `onStale: 'reject'` |
34
+ | **fencing token** | per-op `fenceToken` | `sync_deltas.fence_token` **and** `claim_fence_watermark.fence_token` | "the lease generation I was authorized **at**": a monotonic per-entity high-water | the token is below the entity's persisted high-water: a lapsed holder writing after its successor already claimed, wrote, and released |
35
+ | **claim / lease** | `claimId`, `heldBy` on the `WireClaim` | the coordination store (Redis), not `sync_deltas` | "I hold this row right now": live mutual exclusion | a non-holder writes a row another participant holds |
36
+
37
+ `onStale` (`notify` / `reject` / `overwrite`) is **not** an id — it's the
38
+ disposition that decides what a stale `readAt` *does*. It rides with the read
39
+ basis but is policy, not evidence, so it isn't persisted.
40
+
41
+ Why the token is a distinct id from `readAt`, and not just reused `sync_id`:
42
+ `readAt` advances on every **write** and asserts *from what data*; the token
43
+ advances on every **grant** and asserts *at what lease generation*. Their events
44
+ differ, so one can't stand in for the other — a lapsed holder that skips
45
+ version-CAS (no `readAt`, a blind write) is invisible to the read basis but
46
+ still carries a stale token. That is precisely fence (c) closing what (a) can't.
47
+ The reasoning in full lives in
48
+ [the fencing-token scope doc](../../../../docs/plans/claim-fencing-token-option-b-scope.md).
49
+
50
+ ## Axis 2: correlation / audit (which write is this?)
51
+
52
+ Never decides a conflict. These are how a write is recognized — as a duplicate,
53
+ as your own echo, or as one row in a signed history.
54
+
55
+ | id | wire field | persisted to | purpose |
56
+ |---|---|---|---|
57
+ | **idempotency key** | batch `clientTxId` (public alias `idempotencyKey`) | dedup ledger keyed by it | a retried batch commits **once**: the second attempt is recognized and folded to a no-op, not re-applied |
58
+ | **per-op transaction id** | per-op `transactionId` | `sync_deltas.transaction_id` | echo detection: the broadcast delta arrives at the originating client carrying the **same** id its queue marked pending, so it reconciles its optimistic write instead of double-applying |
59
+ | **sync id** | assigned server-side (`next_sync_id`) | `sync_deltas.id` | the monotonic total order: the serialization order every reader tails and every `readAt` names. It is *assigned*, never client-supplied |
60
+ | **attribution** | actor / capability / delegation on the frame | `sync_deltas` actor columns + the signed audit chain | who acted, on whose behalf, under which key: the [audit log](../audit.md)'s who/when |
61
+
62
+ The batch key and the per-op id are deliberately separate: a multi-row commit is
63
+ **one** idempotent unit (one `clientTxId`) made of **many** individually-echoable
64
+ ops (each its own `transactionId`). Collapsing them would make echo detection
65
+ batch-coarse and break optimistic reconciliation for multi-op commits.
66
+
67
+ ## The evidence tuple on a `sync_deltas` row
68
+
69
+ Both axes leave their mark on the delta, which is what makes a delta a complete,
70
+ self-describing audit record — you can reconstruct the full justification of a
71
+ write from the row alone, never from a live lease that has since vanished:
72
+
73
+ - **who:** `actor_id` / `capability_id` (+ the signed chain)
74
+ - **what:** `data` / `previous_data`
75
+ - **when:** `id` (`sync_id`) / `created_at`
76
+ - **from what known state:** `read_at_sync_id` (the read basis)
77
+ - **at what lease generation:** `fence_token` (the token the commit fenced)
78
+ - **as which client operation:** `transaction_id` (echo identity)
79
+
80
+ `read_at_sync_id` and `fence_token` are companions: the first records the data
81
+ version the write reasoned against, the second the lease generation it was
82
+ authorized at. Both are `NULL` when the write carried none (an unclaimed write, a
83
+ human `user` committer exempt under Law 7, or a legacy row) — **never fabricated
84
+ server-side**. The evidence derives only from what the write actually presented,
85
+ so the audit row can't drift from what the fence enforced.
86
+
87
+ ## One-line test for "which id is this?"
88
+
89
+ > If removing it could turn an accepted commit into a rejected one, it's
90
+ > **Axis 1**. If removing it only costs you dedup, echo reconciliation, or
91
+ > traceability — while the write still lands — it's **Axis 2**.
@@ -0,0 +1,37 @@
1
+ # Concurrency Convention: Open Decisions
2
+
3
+ Maintainer notes for [`concurrency-convention.md`](../concurrency-convention.md).
4
+ These are decisions the team has deliberately not made yet. They change public
5
+ behaviour, so they are tracked here rather than in the public contract, where an
6
+ unmade decision reads as an unsettled guarantee.
7
+
8
+ ## Default disposition for agents
9
+
10
+ Should an agent-participant guarded write default to `notify` (philosophy
11
+ aligned: surface, do not overwrite) instead of `reject` (back-compat)?
12
+
13
+ The trade-off is alignment against a behaviour change for existing agent
14
+ callers. Today a guarded write with `readAt` but no `onStale` defaults to
15
+ `reject` for every participant kind.
16
+
17
+ ## Batch premises through the policy seam
18
+
19
+ Should premise conflicts also pass through `ConflictPolicy`, or stay on the
20
+ direct `onStale` mapping?
21
+
22
+ Routing them through the seam requires a group-aware conflict shape, because a
23
+ batch premise can name a sync group rather than a row. Custom `ConflictPolicy`
24
+ functions currently see write-target conflicts only (`stale_context` /
25
+ `claim_held`); batch-premise conflicts resolve directly through each entry's
26
+ `onStale`.
27
+
28
+ ## The serializability floor
29
+
30
+ A batch premise is a sound check, not a full precedence-graph guarantee: it
31
+ catches only what the caller declared. A caller that declares nothing gets no
32
+ check at all, because write-target checking needs a `readAt` to check against,
33
+ and a plain write is last-writer-wins.
34
+
35
+ The floor is therefore zero, and closing that gap is the subject of ADR 0018.
36
+ The public page states the resulting behaviour as a limit; the framing of it as
37
+ a gap to be closed belongs here.
@@ -0,0 +1,150 @@
1
+ # Data Source Reverse Channel (local-dev parity)
2
+
3
+ Maintainer scoping doc. Closes the one real day-one DX gap in Data Source
4
+ mode: the `commit`/`load`/`list` legs are inbound webhooks (Ablo → your
5
+ endpoint), so on `localhost` they need a tunnel (ngrok/cloudflared). This
6
+ scopes a built-in reverse channel so Data Source works on localhost the way
7
+ managed mode already does — the Stripe-CLI `stripe listen` pattern.
8
+
9
+ ## The gap, precisely
10
+
11
+ Data Source has two directions today:
12
+
13
+ | Leg | Direction | Transport(s) today | localhost-friendly? |
14
+ |---|---|---|---|
15
+ | `events` (external writes → Ablo) | customer → Ablo | **poll** (`events` handler, Ablo calls you) **+ push** (`createPushQueue` → `POST /api/source/events`, you call Ablo) | ✅ yes, via push |
16
+ | `commit` / `load` / `list` | Ablo → customer | **inbound webhook only** (`dataSource()` route) | ❌ no: needs public URL |
17
+
18
+ The asymmetry is the whole bug. `events` already ships an outbound transport
19
+ (`src/source/pushQueue.ts`), so external writes reach Ablo from localhost
20
+ without a tunnel. The `commit`/`load`/`list` leg never got one, so Ablo Cloud
21
+ has no way to reach a `localhost:3000` dev server.
22
+
23
+ Inbound is exactly what localhost cannot receive. Managed mode has no inbound
24
+ leg (the browser/SDK opens the only connection, outbound to Ablo), which is why
25
+ managed mode "just works" locally and Data Source doesn't.
26
+
27
+ ## Prior art
28
+
29
+ - **Stripe CLI `stripe listen`:** the canonical fix. The CLI opens an
30
+ *outbound* WebSocket to Stripe; Stripe drains webhook events down it and the
31
+ CLI forwards them to `localhost`. No public URL, no tunnel. We want the same
32
+ for the `commit`/`load`/`list` leg.
33
+ - **Our own `createPushQueue`:** already proves the outbound-from-customer
34
+ pattern for the `events` leg. The reverse channel is the symmetric primitive
35
+ for the other direction.
36
+
37
+ ## Design
38
+
39
+ A customer-run **source connector** dials out to Ablo Cloud and serves
40
+ `commit`/`load`/`list` over the open connection, instead of Ablo making inbound
41
+ HTTP calls.
42
+
43
+ ```
44
+ LOCAL DEV (no public URL)
45
+
46
+ ablo client ──ws──▶ Ablo Cloud ──┐
47
+ │ (no inbound HTTP to localhost)
48
+ customer connector ──ws (dial-out)──▶ Ablo Cloud
49
+ │ drains pending commit/load/list for this source
50
+
51
+ dataSource(options) ← UNCHANGED handler, fed a synthesized Request
52
+
53
+ local Postgres
54
+ │ signed response posted back up the same ws
55
+ └──────────────────────────────────────▶ Ablo Cloud ──ws──▶ ablo client
56
+ ```
57
+
58
+ ### Why it's small
59
+
60
+ `dataSource(options)` is already `(request: Request) => Promise<Response>` in
61
+ `src/source/factory.ts`. The connector does not reimplement any handler logic —
62
+ it:
63
+
64
+ 1. Opens a WS to a new Ablo Cloud endpoint (e.g. `/v1/source/listen`),
65
+ authenticating with the project API key.
66
+ 2. Registers which source/org it serves. Ablo Cloud routes that source's
67
+ `commit`/`load`/`list` requests to this socket instead of the configured
68
+ webhook URL (when a live connector is attached).
69
+ 3. For each drained request frame: synthesize a `Request` with the same signed
70
+ headers Ablo would have sent, call the customer's existing `dataSource`
71
+ handler, and post the `Response` back up the socket.
72
+
73
+ Customer-side surface is one wrapper around the handler they already wrote:
74
+
75
+ ```ts
76
+ // dev only — same handler object as the deployed route
77
+ import { dataSource, createSourceConnector } from '@abloatai/ablo';
78
+ import { sourceOptions } from './ablo.source'; // shared with route.ts
79
+
80
+ const connector = createSourceConnector({
81
+ apiKey: process.env.ABLO_API_KEY!, // sk_test_*
82
+ handler: dataSource(sourceOptions), // the unchanged (Request)=>Response
83
+ });
84
+ await connector.run(abortSignal);
85
+ ```
86
+
87
+ `route.ts` (deployed) and the connector (local) share the same
88
+ `sourceOptions` — zero handler drift.
89
+
90
+ ### Server side (sync-server)
91
+
92
+ - New WS endpoint `/v1/source/listen`. Auth: project API key → resolves the
93
+ source. Reject if the key isn't `sk_test_*` unless the source explicitly
94
+ opts into reverse-channel for production (see "Production" below).
95
+ - Per-source request queue. When a `commit`/`load`/`list` needs the customer
96
+ and a connector is attached, enqueue + drain down the socket instead of
97
+ POSTing the webhook URL. Reuse the same signed-envelope shape so the
98
+ customer handler verifies identically (`verifyAbloSourceRequest` unchanged).
99
+ - Fallback: no connector attached → existing inbound webhook path. The
100
+ reverse channel is purely additive; nothing changes for deployed apps.
101
+
102
+ ### Signature / security
103
+
104
+ - The drained frames carry the **same** Standard Webhooks signature
105
+ (`webhook-id`/`webhook-timestamp`/`webhook-signature`) computed with the
106
+ project key, so the connector verifies them through the existing
107
+ `verifyAbloSourceRequest` with no special-casing. The transport changes; the
108
+ trust model does not.
109
+ - Gate to `sk_test_*` by default. The DB still stays canonical in the
110
+ customer's process; nothing here gives Ablo the `DATABASE_URL`.
111
+
112
+ ## Test-mode interplay
113
+
114
+ `SourceRequestContext.mode` (`src/source/types.ts`) already distinguishes
115
+ `test`/`live`. The reverse channel is the natural home for `mode: 'test'`
116
+ traffic: a local connector attached with an `sk_test_*` key receives the
117
+ source's test commits, runs them against the customer's test DB, and the SDK
118
+ sees confirmed rows + fan-out exactly as in production. This is the missing
119
+ piece that makes `sk_test_*` a complete local loop rather than just a data
120
+ namespace.
121
+
122
+ ## Production stance
123
+
124
+ Keep the inbound webhook as the default deployed transport — it's lower
125
+ latency (no long-lived socket to babysit) and stateless. The reverse channel
126
+ is primarily the **dev** affordance. A secondary, opt-in use is a
127
+ "no-public-URL deploy" mode for customers who cannot expose an inbound
128
+ endpoint at all (locked-down VPCs); that's a follow-on, not the initial scope.
129
+
130
+ ## Scope boundary (what this is NOT)
131
+
132
+ - Not a generic tunnel — it forwards only signed Ablo source frames for one
133
+ source, not arbitrary traffic.
134
+ - Not a change to the handler contract — `dataSource` is untouched; the
135
+ connector wraps its handler.
136
+ - Not a managed-mode change — managed mode has no inbound leg and is unaffected.
137
+
138
+ ## Touch list (when built)
139
+
140
+ - `packages/transaction/src/source/connector.ts` — `createSourceConnector`
141
+ (dial-out WS client; synthesize Request → existing handler → post Response).
142
+ - `packages/transaction` export surface — expose `createSourceConnector` next to
143
+ `createPushQueue`.
144
+ - `apps/sync-server` — `/v1/source/listen` WS endpoint + per-source request
145
+ queue + "drain to connector if attached, else webhook" branch in the source
146
+ dispatch path.
147
+ - `docs/data-sources.md` — document the local-dev loop (the current docs only
148
+ describe the public-HTTPS webhook).
149
+ - Tests: connector round-trip (drained commit → handler → response), signature
150
+ parity with the webhook path, fallback-to-webhook when no connector attached.