@sixb/core 0.1.9 → 0.1.11

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 (328) hide show
  1. package/dist/actions/index.js +9 -9
  2. package/dist/agents/index.js +17 -16
  3. package/dist/agents/index.js.map +1 -1
  4. package/dist/blob-storage/types.d.ts +4 -1
  5. package/dist/blob-storage/types.d.ts.map +1 -1
  6. package/dist/bootstrap/index.js +21 -20
  7. package/dist/bootstrap/index.js.map +1 -1
  8. package/dist/broker/in-memory.d.ts +8 -2
  9. package/dist/broker/in-memory.d.ts.map +1 -1
  10. package/dist/broker/index.d.ts +4 -2
  11. package/dist/broker/index.d.ts.map +1 -1
  12. package/dist/broker/index.js +7 -3
  13. package/dist/broker/index.js.map +1 -1
  14. package/dist/broker/retention.d.ts +4 -0
  15. package/dist/broker/retention.d.ts.map +1 -0
  16. package/dist/broker/subscriber.d.ts +10 -0
  17. package/dist/broker/subscriber.d.ts.map +1 -0
  18. package/dist/broker/types.d.ts +14 -1
  19. package/dist/broker/types.d.ts.map +1 -1
  20. package/dist/{chunk-ypbtykv6.js → chunk-01kj2pbh.js} +1 -1
  21. package/dist/{chunk-k3cqkkn2.js → chunk-1824gssz.js} +30 -65
  22. package/dist/chunk-1824gssz.js.map +12 -0
  23. package/dist/{chunk-xyr8kppc.js → chunk-1yefycb1.js} +1 -1
  24. package/dist/chunk-2c4j899j.js.map +1 -1
  25. package/dist/{chunk-ppytyr6w.js → chunk-358caqf5.js} +4 -4
  26. package/dist/chunk-358caqf5.js.map +12 -0
  27. package/dist/{chunk-m3z3x9v0.js → chunk-3ckk0xfj.js} +2 -2
  28. package/dist/{chunk-kxwa347f.js → chunk-3qms4nax.js} +2 -2
  29. package/dist/{chunk-kxwa347f.js.map → chunk-3qms4nax.js.map} +3 -3
  30. package/dist/{chunk-52hbv0ak.js → chunk-4zhmdsx6.js} +141 -55
  31. package/dist/chunk-4zhmdsx6.js.map +36 -0
  32. package/dist/{chunk-zcnq6105.js → chunk-85cd7e8c.js} +2 -1
  33. package/dist/chunk-85cd7e8c.js.map +10 -0
  34. package/dist/{chunk-3f7veca0.js → chunk-9x8dybsb.js} +3 -3
  35. package/dist/chunk-9x8dybsb.js.map +10 -0
  36. package/dist/{chunk-0w35wavj.js → chunk-a0e6x5hd.js} +1 -1
  37. package/dist/{chunk-r29fxdhn.js → chunk-aa6z4a19.js} +160 -44
  38. package/dist/chunk-aa6z4a19.js.map +12 -0
  39. package/dist/{chunk-emyyk7dx.js → chunk-cfvakeax.js} +22 -145
  40. package/dist/chunk-cfvakeax.js.map +12 -0
  41. package/dist/chunk-d62kjtbg.js.map +1 -1
  42. package/dist/{chunk-h1gfhhbh.js → chunk-d63nnr5b.js} +2 -2
  43. package/dist/{chunk-r4tfx1sf.js → chunk-fh8kgex1.js} +5 -5
  44. package/dist/{chunk-an5tt9y0.js → chunk-ftv470j8.js} +42 -4
  45. package/dist/{chunk-an5tt9y0.js.map → chunk-ftv470j8.js.map} +7 -7
  46. package/dist/{chunk-jjy0fhrn.js → chunk-g91qxjj0.js} +20 -3
  47. package/dist/chunk-g91qxjj0.js.map +12 -0
  48. package/dist/{chunk-hpr1r6av.js → chunk-gq8vhakp.js} +51 -40
  49. package/dist/{chunk-hpr1r6av.js.map → chunk-gq8vhakp.js.map} +6 -6
  50. package/dist/{chunk-x57ycxq0.js → chunk-gqh45d2n.js} +42 -3
  51. package/dist/{chunk-x57ycxq0.js.map → chunk-gqh45d2n.js.map} +3 -3
  52. package/dist/{chunk-mjbk2djy.js → chunk-gqm76kse.js} +231 -125
  53. package/dist/{chunk-mjbk2djy.js.map → chunk-gqm76kse.js.map} +9 -8
  54. package/dist/{chunk-e0d1rzef.js → chunk-jsy70480.js} +16 -3
  55. package/dist/chunk-jsy70480.js.map +15 -0
  56. package/dist/{chunk-0rdrecsb.js → chunk-kfee1h52.js} +116 -32
  57. package/dist/chunk-kfee1h52.js.map +13 -0
  58. package/dist/{chunk-3frsnm7x.js → chunk-qma80ych.js} +4 -6
  59. package/dist/chunk-qma80ych.js.map +11 -0
  60. package/dist/{chunk-vf691g1r.js → chunk-sepyxgpc.js} +3 -3
  61. package/dist/chunk-v2vcg0w6.js +151 -0
  62. package/dist/chunk-v2vcg0w6.js.map +11 -0
  63. package/dist/{chunk-3tgwrcyh.js → chunk-wf88w4kp.js} +17 -23
  64. package/dist/chunk-wf88w4kp.js.map +14 -0
  65. package/dist/{chunk-xfbydgzy.js → chunk-x9m9x2eq.js} +7 -8
  66. package/dist/{chunk-xfbydgzy.js.map → chunk-x9m9x2eq.js.map} +3 -3
  67. package/dist/{chunk-qhcpj9wc.js → chunk-z0271qkp.js} +98 -2
  68. package/dist/chunk-z0271qkp.js.map +15 -0
  69. package/dist/{chunk-1enhpacz.js → chunk-z0s4axeh.js} +6 -6
  70. package/dist/connectors/connections/authorizations.d.ts.map +1 -1
  71. package/dist/connectors/connections/command-context.d.ts +2 -0
  72. package/dist/connectors/connections/command-context.d.ts.map +1 -1
  73. package/dist/connectors/connections/contracts.d.ts +4 -1
  74. package/dist/connectors/connections/contracts.d.ts.map +1 -1
  75. package/dist/connectors/connections/execution.d.ts +1 -0
  76. package/dist/connectors/connections/execution.d.ts.map +1 -1
  77. package/dist/connectors/connections/internal.js +1 -1
  78. package/dist/connectors/connections/request.d.ts +3 -1
  79. package/dist/connectors/connections/request.d.ts.map +1 -1
  80. package/dist/connectors/connections/runs.d.ts +1 -0
  81. package/dist/connectors/connections/runs.d.ts.map +1 -1
  82. package/dist/connectors/connections/service.d.ts +2 -0
  83. package/dist/connectors/connections/service.d.ts.map +1 -1
  84. package/dist/connectors/connections/tokens.d.ts.map +1 -1
  85. package/dist/connectors/connections/validation.d.ts +5 -1
  86. package/dist/connectors/connections/validation.d.ts.map +1 -1
  87. package/dist/connectors/types.d.ts +19 -4
  88. package/dist/connectors/types.d.ts.map +1 -1
  89. package/dist/events/execution.d.ts +1 -1
  90. package/dist/events/execution.d.ts.map +1 -1
  91. package/dist/events/index.js +1 -1
  92. package/dist/events/outbox-dispatcher.d.ts +2 -2
  93. package/dist/events/outbox-dispatcher.d.ts.map +1 -1
  94. package/dist/events/service.d.ts +2 -2
  95. package/dist/events/service.d.ts.map +1 -1
  96. package/dist/execution/agent.js +17 -16
  97. package/dist/execution/agent.js.map +1 -1
  98. package/dist/execution/primitive.js +17 -16
  99. package/dist/execution/primitive.js.map +2 -2
  100. package/dist/execution/request.js +17 -16
  101. package/dist/execution/request.js.map +2 -2
  102. package/dist/index.d.ts +3 -3
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +31 -29
  105. package/dist/index.js.map +1 -1
  106. package/dist/lake-storage/changes.d.ts +5 -0
  107. package/dist/lake-storage/changes.d.ts.map +1 -0
  108. package/dist/lake-storage/in-memory.d.ts +2 -1
  109. package/dist/lake-storage/in-memory.d.ts.map +1 -1
  110. package/dist/lake-storage/index.d.ts +2 -1
  111. package/dist/lake-storage/index.d.ts.map +1 -1
  112. package/dist/lake-storage/index.js +4 -2
  113. package/dist/lake-storage/index.js.map +1 -1
  114. package/dist/lake-storage/types.d.ts +38 -0
  115. package/dist/lake-storage/types.d.ts.map +1 -1
  116. package/dist/logging/internal.js +1 -1
  117. package/dist/maintenance/ontology-maintenance.d.ts.map +1 -1
  118. package/dist/maintenance/types.d.ts +1 -1
  119. package/dist/maintenance/types.d.ts.map +1 -1
  120. package/dist/materialization/index.d.ts +1 -1
  121. package/dist/materialization/index.d.ts.map +1 -1
  122. package/dist/materialization/model.d.ts +12 -1
  123. package/dist/materialization/model.d.ts.map +1 -1
  124. package/dist/materializer/index.d.ts +1 -1
  125. package/dist/materializer/index.d.ts.map +1 -1
  126. package/dist/materializer/index.js +6 -6
  127. package/dist/materializer/materializer.d.ts +5 -1
  128. package/dist/materializer/materializer.d.ts.map +1 -1
  129. package/dist/materializer/projections/entry-validator.d.ts +2 -1
  130. package/dist/materializer/projections/entry-validator.d.ts.map +1 -1
  131. package/dist/materializer/projections/replace.d.ts.map +1 -1
  132. package/dist/materializer/projections/source-materialization.d.ts +4 -3
  133. package/dist/materializer/projections/source-materialization.d.ts.map +1 -1
  134. package/dist/materializer/shared/normalize.d.ts +2 -1
  135. package/dist/materializer/shared/normalize.d.ts.map +1 -1
  136. package/dist/models/definitions.d.ts +7 -0
  137. package/dist/models/definitions.d.ts.map +1 -1
  138. package/dist/models/execution/index.js +6 -6
  139. package/dist/models/index.js +1 -1
  140. package/dist/objects/index.js +10 -10
  141. package/dist/objects/query/index.js +6 -6
  142. package/dist/pipelines/index.js +7 -7
  143. package/dist/pipelines/run-dispatch.d.ts.map +1 -1
  144. package/dist/projections/internal.js +7 -9
  145. package/dist/projections/internal.js.map +1 -1
  146. package/dist/projections/run-dispatch.d.ts.map +1 -1
  147. package/dist/queues/in-memory.d.ts +7 -3
  148. package/dist/queues/in-memory.d.ts.map +1 -1
  149. package/dist/queues/index.js +1 -1
  150. package/dist/queues/indexed-heap.d.ts +15 -0
  151. package/dist/queues/indexed-heap.d.ts.map +1 -0
  152. package/dist/runtime/host.d.ts.map +1 -1
  153. package/dist/runtime/internal.js +1 -1
  154. package/dist/runtime/ontology-mutations.d.ts +3 -1
  155. package/dist/runtime/ontology-mutations.d.ts.map +1 -1
  156. package/dist/shares/internal.js +5 -5
  157. package/dist/storage/agents/provider.js +1 -1
  158. package/dist/storage/connector-connections/in-memory.d.ts +1 -0
  159. package/dist/storage/connector-connections/in-memory.d.ts.map +1 -1
  160. package/dist/storage/connector-connections/provider/connections.d.ts.map +1 -1
  161. package/dist/storage/connector-connections/provider/runs.d.ts +1 -0
  162. package/dist/storage/connector-connections/provider/runs.d.ts.map +1 -1
  163. package/dist/storage/connector-connections/provider/shared.d.ts +1 -0
  164. package/dist/storage/connector-connections/provider/shared.d.ts.map +1 -1
  165. package/dist/storage/connector-connections/provider.d.ts +1 -0
  166. package/dist/storage/connector-connections/provider.d.ts.map +1 -1
  167. package/dist/storage/connector-connections/provider.js +11 -17
  168. package/dist/storage/connector-connections/provider.js.map +6 -6
  169. package/dist/storage/connector-connections/types.d.ts +6 -3
  170. package/dist/storage/connector-connections/types.d.ts.map +1 -1
  171. package/dist/storage/index.d.ts +1 -1
  172. package/dist/storage/index.d.ts.map +1 -1
  173. package/dist/storage/index.js +5 -5
  174. package/dist/storage/internal.js +1 -1
  175. package/dist/storage/ontology/in-memory/materializations-state.d.ts.map +1 -1
  176. package/dist/storage/ontology/in-memory/materializations.d.ts +1 -1
  177. package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
  178. package/dist/storage/ontology/in-memory/shared-state.d.ts +15 -2
  179. package/dist/storage/ontology/in-memory/shared-state.d.ts.map +1 -1
  180. package/dist/storage/ontology/in-memory/source-roots.d.ts +6 -0
  181. package/dist/storage/ontology/in-memory/source-roots.d.ts.map +1 -0
  182. package/dist/storage/ontology/in-memory/sources.d.ts.map +1 -1
  183. package/dist/storage/ontology/index.d.ts +1 -1
  184. package/dist/storage/ontology/index.d.ts.map +1 -1
  185. package/dist/storage/ontology/outbox.d.ts +1 -0
  186. package/dist/storage/ontology/outbox.d.ts.map +1 -1
  187. package/dist/storage/ontology/provider.d.ts +16 -0
  188. package/dist/storage/ontology/provider.d.ts.map +1 -1
  189. package/dist/storage/ontology/provider.js +4 -2
  190. package/dist/storage/ontology/provider.js.map +1 -1
  191. package/dist/storage/ontology/sources.d.ts +13 -4
  192. package/dist/storage/ontology/sources.d.ts.map +1 -1
  193. package/dist/storage/projection-runs/lifecycle.d.ts.map +1 -1
  194. package/dist/storage/projection-runs/provider.js +2 -2
  195. package/dist/storage/projection-runs/types.d.ts +2 -0
  196. package/dist/storage/projection-runs/types.d.ts.map +1 -1
  197. package/dist/syncs/index.js +9 -8
  198. package/dist/syncs/index.js.map +1 -1
  199. package/dist/syncs/run-dispatch.d.ts.map +1 -1
  200. package/dist/testing/broker-contract.d.ts.map +1 -1
  201. package/dist/testing/connector-connection-storage-contract.d.ts.map +1 -1
  202. package/dist/testing/index.d.ts +1 -0
  203. package/dist/testing/index.d.ts.map +1 -1
  204. package/dist/testing/index.js +1499 -963
  205. package/dist/testing/index.js.map +10 -9
  206. package/dist/testing/lake-changes-contract.d.ts +6 -0
  207. package/dist/testing/lake-changes-contract.d.ts.map +1 -0
  208. package/dist/testing/lake-storage-contract.d.ts.map +1 -1
  209. package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
  210. package/dist/testing/ontology-storage-contract.d.ts.map +1 -1
  211. package/dist/testing/projection-run-storage-contract.d.ts.map +1 -1
  212. package/dist/webhooks/connections.d.ts +6 -0
  213. package/dist/webhooks/connections.d.ts.map +1 -0
  214. package/dist/webhooks/index.d.ts +1 -1
  215. package/dist/webhooks/index.d.ts.map +1 -1
  216. package/dist/webhooks/internal.d.ts +2 -0
  217. package/dist/webhooks/internal.d.ts.map +1 -1
  218. package/dist/webhooks/internal.js +55 -10
  219. package/dist/webhooks/internal.js.map +4 -3
  220. package/dist/webhooks/registry.d.ts +1 -1
  221. package/dist/webhooks/registry.d.ts.map +1 -1
  222. package/dist/webhooks/types.d.ts +15 -4
  223. package/dist/webhooks/types.d.ts.map +1 -1
  224. package/dist/workflows/index.js +18 -17
  225. package/dist/workflows/index.js.map +1 -1
  226. package/dist/workflows/run-dispatch.d.ts +3 -1
  227. package/dist/workflows/run-dispatch.d.ts.map +1 -1
  228. package/package.json +1 -1
  229. package/src/agents/model-loop.ts +7 -0
  230. package/src/blob-storage/types.ts +4 -1
  231. package/src/broker/in-memory.ts +104 -39
  232. package/src/broker/index.ts +4 -1
  233. package/src/broker/retention.ts +28 -0
  234. package/src/broker/subscriber.ts +21 -0
  235. package/src/broker/types.ts +15 -1
  236. package/src/connectors/builders.ts +0 -6
  237. package/src/connectors/connections/authorizations.ts +11 -5
  238. package/src/connectors/connections/command-context.ts +21 -4
  239. package/src/connectors/connections/contracts.ts +7 -1
  240. package/src/connectors/connections/execution.ts +3 -0
  241. package/src/connectors/connections/request.ts +56 -22
  242. package/src/connectors/connections/runs.ts +39 -1
  243. package/src/connectors/connections/service.ts +6 -0
  244. package/src/connectors/connections/tokens.ts +4 -0
  245. package/src/connectors/connections/validation.ts +91 -5
  246. package/src/connectors/types.ts +19 -4
  247. package/src/events/execution.ts +2 -2
  248. package/src/events/outbox-dispatcher.ts +20 -26
  249. package/src/events/service.ts +3 -3
  250. package/src/index.ts +10 -2
  251. package/src/lake-storage/changes.ts +43 -0
  252. package/src/lake-storage/in-memory.ts +75 -0
  253. package/src/lake-storage/index.ts +4 -0
  254. package/src/lake-storage/types.ts +42 -0
  255. package/src/logging/service.ts +1 -1
  256. package/src/maintenance/ontology-maintenance.ts +6 -2
  257. package/src/maintenance/types.ts +1 -1
  258. package/src/materialization/index.ts +2 -0
  259. package/src/materialization/model.ts +14 -1
  260. package/src/materializer/README.md +1 -1
  261. package/src/materializer/index.ts +2 -0
  262. package/src/materializer/materializer.ts +10 -0
  263. package/src/materializer/projections/entry-validator.ts +19 -1
  264. package/src/materializer/projections/replace.ts +36 -1
  265. package/src/materializer/projections/source-materialization.ts +26 -6
  266. package/src/materializer/shared/normalize.ts +1 -1
  267. package/src/models/definitions.ts +19 -0
  268. package/src/models/pricing.ts +6 -2
  269. package/src/pipelines/run-dispatch.ts +21 -1
  270. package/src/projections/run-dispatch.ts +30 -68
  271. package/src/queues/in-memory.ts +105 -62
  272. package/src/queues/indexed-heap.ts +74 -0
  273. package/src/runtime/host.ts +0 -14
  274. package/src/runtime/ontology-mutations.ts +4 -0
  275. package/src/storage/connector-connections/in-memory.ts +19 -19
  276. package/src/storage/connector-connections/provider/connections.ts +1 -15
  277. package/src/storage/connector-connections/provider/runs.ts +9 -1
  278. package/src/storage/connector-connections/provider/shared.ts +2 -3
  279. package/src/storage/connector-connections/provider.ts +6 -0
  280. package/src/storage/connector-connections/types.ts +8 -3
  281. package/src/storage/index.ts +1 -0
  282. package/src/storage/ontology/in-memory/materializations-state.ts +5 -18
  283. package/src/storage/ontology/in-memory/materializations.ts +73 -92
  284. package/src/storage/ontology/in-memory/shared-state.ts +36 -4
  285. package/src/storage/ontology/in-memory/source-roots.ts +123 -0
  286. package/src/storage/ontology/in-memory/sources.ts +78 -23
  287. package/src/storage/ontology/index.ts +1 -0
  288. package/src/storage/ontology/outbox.ts +1 -0
  289. package/src/storage/ontology/provider.ts +70 -0
  290. package/src/storage/ontology/sources.ts +14 -3
  291. package/src/storage/projection-runs/lifecycle.ts +5 -2
  292. package/src/storage/projection-runs/types.ts +4 -3
  293. package/src/syncs/run-dispatch.ts +19 -1
  294. package/src/testing/broker-contract.ts +95 -0
  295. package/src/testing/connector-connection-storage-contract.ts +29 -12
  296. package/src/testing/index.ts +1 -0
  297. package/src/testing/lake-changes-contract.ts +240 -0
  298. package/src/testing/lake-storage-contract.ts +29 -0
  299. package/src/testing/materializer-storage-contract.ts +172 -1
  300. package/src/testing/ontology-storage-contract.ts +15 -3
  301. package/src/testing/projection-run-storage-contract.ts +34 -0
  302. package/src/webhooks/connections.ts +56 -0
  303. package/src/webhooks/index.ts +2 -0
  304. package/src/webhooks/internal.ts +2 -0
  305. package/src/webhooks/registry.ts +3 -4
  306. package/src/webhooks/types.ts +17 -4
  307. package/src/workflows/run-dispatch.ts +42 -29
  308. package/dist/chunk-0rdrecsb.js.map +0 -11
  309. package/dist/chunk-3f7veca0.js.map +0 -10
  310. package/dist/chunk-3frsnm7x.js.map +0 -11
  311. package/dist/chunk-3tgwrcyh.js.map +0 -14
  312. package/dist/chunk-52hbv0ak.js.map +0 -36
  313. package/dist/chunk-e0d1rzef.js.map +0 -15
  314. package/dist/chunk-emyyk7dx.js.map +0 -14
  315. package/dist/chunk-jjy0fhrn.js.map +0 -12
  316. package/dist/chunk-k3cqkkn2.js.map +0 -12
  317. package/dist/chunk-ppytyr6w.js.map +0 -12
  318. package/dist/chunk-qhcpj9wc.js.map +0 -14
  319. package/dist/chunk-r29fxdhn.js.map +0 -11
  320. package/dist/chunk-zcnq6105.js.map +0 -10
  321. /package/dist/{chunk-ypbtykv6.js.map → chunk-01kj2pbh.js.map} +0 -0
  322. /package/dist/{chunk-xyr8kppc.js.map → chunk-1yefycb1.js.map} +0 -0
  323. /package/dist/{chunk-m3z3x9v0.js.map → chunk-3ckk0xfj.js.map} +0 -0
  324. /package/dist/{chunk-0w35wavj.js.map → chunk-a0e6x5hd.js.map} +0 -0
  325. /package/dist/{chunk-h1gfhhbh.js.map → chunk-d63nnr5b.js.map} +0 -0
  326. /package/dist/{chunk-r4tfx1sf.js.map → chunk-fh8kgex1.js.map} +0 -0
  327. /package/dist/{chunk-vf691g1r.js.map → chunk-sepyxgpc.js.map} +0 -0
  328. /package/dist/{chunk-1enhpacz.js.map → chunk-z0s4axeh.js.map} +0 -0
@@ -8,6 +8,7 @@ export type {
8
8
  } from "../datasets"
9
9
  export { assertDatasetDefinition } from "../datasets/validation"
10
10
  export type { JsonValue } from "../json"
11
+ export { resolveDatasetChangeColumns } from "./changes"
11
12
  export type {
12
13
  DatasetDefinitionUpdatePlan,
13
14
  DatasetMetadataUpdatePlan,
@@ -54,9 +55,11 @@ export type {
54
55
  BeginDatasetWriteInput,
55
56
  CommitDatasetWriteInput,
56
57
  DatasetCatalogState,
58
+ DatasetChanges,
57
59
  DatasetLatestVersionSummary,
58
60
  DatasetProducer,
59
61
  DatasetRow,
62
+ DatasetRowChange,
60
63
  DatasetVersion,
61
64
  DatasetVersionMode,
62
65
  DatasetVersionRef,
@@ -66,6 +69,7 @@ export type {
66
69
  LakeStandardId,
67
70
  LakeStorage,
68
71
  LakeWriteSession,
72
+ ReadDatasetChangesInput,
69
73
  ReadDatasetRowsInput,
70
74
  } from "./types"
71
75
  export { hasDatasetInputChanges } from "./version-inputs"
@@ -71,6 +71,41 @@ export interface ReadDatasetRowsInput {
71
71
  readonly columns?: readonly string[]
72
72
  readonly limit?: number
73
73
  readonly offset?: number
74
+ /** Cancel an active read or a read waiting for provider capacity. */
75
+ readonly signal?: AbortSignal
76
+ }
77
+
78
+ export interface ReadDatasetChangesInput {
79
+ readonly datasetId: string
80
+ readonly fromVersionId: string
81
+ readonly toVersionId: string
82
+ /** Stable, unique row identity in both versions; it need not be the dataset primary key. */
83
+ readonly keyColumns: readonly string[]
84
+ /** Complete inputs of the consumer's calculation, including key columns and timestamps. */
85
+ readonly columns: readonly string[]
86
+ readonly signal?: AbortSignal
87
+ }
88
+
89
+ export interface DatasetRowChange {
90
+ /** Null for an insertion. Otherwise includes every requested column. */
91
+ readonly before: DatasetRow | null
92
+ /** Null for a deletion. Otherwise includes every requested column. */
93
+ readonly after: DatasetRow | null
94
+ }
95
+
96
+ /** A complete, pinned change set. Call close in finally, including when iteration never starts. */
97
+ export interface DatasetChanges {
98
+ readonly fromRowCount: number
99
+ readonly toRowCount: number
100
+ /** Exact number of records the iterator must deliver before EOF. */
101
+ readonly changeCount: number
102
+ /**
103
+ * At most one record per key, with at least one non-null image. Includes every changed key;
104
+ * providers may conservatively include equal images (for example, reordered JSON fields).
105
+ * Order is unspecified. Consumers must exhaust the stream before publishing its result.
106
+ */
107
+ readonly changes: AsyncIterable<DatasetRowChange>
108
+ close(): Promise<void>
74
109
  }
75
110
 
76
111
  export interface CommitDatasetWriteInput {
@@ -138,6 +173,13 @@ export interface LakeStorage {
138
173
  /** Explicit immutable-version reads have stable physical order and stable offset semantics. */
139
174
  readRows(input: ReadDatasetRowsInput): AsyncIterable<DatasetRow>
140
175
 
176
+ /**
177
+ * Optional comparison of two immutable versions. Null means the snapshots, schemas or unique
178
+ * keys cannot support a complete delta: use a full read. Operational errors must propagate.
179
+ * Iteration releases the provider connection between bounded pages, allowing other lake work.
180
+ */
181
+ readChanges?(input: ReadDatasetChangesInput): Promise<DatasetChanges | null>
182
+
141
183
  /** Release external resources. Optional: a provider that owns none omits it. */
142
184
  close?(): void | Promise<void>
143
185
  }
@@ -213,7 +213,7 @@ export class LoggingService {
213
213
  const lines = records.map(hydrateLogRecord)
214
214
  if (lines.length === 0) return
215
215
  try {
216
- handler(lines)
216
+ return handler(lines)
217
217
  } catch {
218
218
  // Subscriber failures never break broker delivery.
219
219
  }
@@ -93,6 +93,7 @@ export class OntologyMaintenance {
93
93
 
94
94
  /** Runs one coalesced pass. Exposed for deterministic hosting and tests. */
95
95
  runNow(): Promise<void> {
96
+ if (this.stopping) return this.stopping
96
97
  this.pass ??= this.runPass().finally(() => {
97
98
  this.pass = null
98
99
  })
@@ -244,12 +245,15 @@ export class OntologyMaintenance {
244
245
  this.timer = null
245
246
  }
246
247
  const activePass = this.pass ?? Promise.resolve()
247
- const stopping = settlesWithin(activePass, this.shutdownTimeoutMs).then((settled) => {
248
+ const stopping = settlesWithin(activePass, this.shutdownTimeoutMs).then(async (settled) => {
248
249
  if (!settled) {
249
250
  this.reportError(
250
- new Error(`[Sixb] Ontology maintenance did not stop within ${this.shutdownTimeoutMs}ms.`)
251
+ new Error(
252
+ `[Sixb] Ontology maintenance is still stopping after ${this.shutdownTimeoutMs}ms; waiting for active storage operations.`
253
+ )
251
254
  )
252
255
  }
256
+ await activePass
253
257
  })
254
258
  this.stopping = stopping.finally(() => {
255
259
  this.stopping = null
@@ -7,7 +7,7 @@ export interface OntologyMaintenanceOptions {
7
7
  readonly terminalSourceRetentionMs?: number
8
8
  /** Maximum deletions attempted per cleanup domain and pass. Defaults to 1,000. */
9
9
  readonly cleanupLimit?: number
10
- /** Maximum time to wait for an active pass during shutdown. Defaults to 30 seconds. */
10
+ /** Warn after this shutdown grace period, then wait for active operations. Defaults to 30 seconds. */
11
11
  readonly shutdownTimeoutMs?: number
12
12
  }
13
13
 
@@ -51,6 +51,8 @@ export type {
51
51
  ProjectionRunFinishInput,
52
52
  ProjectionRunTerminalDecision,
53
53
  ProjectionSourceAssertion,
54
+ ProjectionSourceBase,
55
+ ProjectionSourceDeletion,
54
56
  ProjectionSourceEntry,
55
57
  ProjectionSourceRef,
56
58
  ProjectionSourceReplacement,
@@ -169,11 +169,24 @@ export interface ProjectionSourceEntry {
169
169
  readonly assertions: readonly ProjectionSourceAssertion[]
170
170
  }
171
171
 
172
+ export interface ProjectionSourceDeletion {
173
+ readonly root: ProjectionEntityRef
174
+ readonly deleted: true
175
+ }
176
+
177
+ /** Exact committed source state against which a complete delta was calculated. */
178
+ export interface ProjectionSourceBase {
179
+ readonly materializationId: string
180
+ readonly lastCommitId: string
181
+ }
182
+
172
183
  export interface ProjectionSourceReplacement {
173
184
  readonly source: ProjectionSourceRef
174
185
  readonly datasetVersion: PinnedDatasetVersion
175
186
  readonly execution: ProjectionExecution
176
- readonly entries: AsyncIterable<ProjectionSourceEntry>
187
+ /** Without a base, entries replace the whole source. With a base, unchanged roots are retained. */
188
+ readonly entries: AsyncIterable<ProjectionSourceEntry | ProjectionSourceDeletion>
189
+ readonly base?: ProjectionSourceBase
177
190
  readonly signal?: AbortSignal
178
191
  }
179
192
 
@@ -17,7 +17,7 @@ runtime telemetry -> telemetry.append (origin: telemetry/runtime)
17
17
 
18
18
  Committed facts are published from the transactional outbox after the commit resolves.
19
19
  `OntologyOutboxDispatcher` owns that protocol: ingresses call `notify()` for prompt, non-blocking
20
- in-process delivery, and a process may call `start()` to host the durable poll loop. Publication is
20
+ in-process delivery; `OntologyMaintenance` hosts recovery catch-up. Publication is
21
21
  best effort — delivery may lag, but a committed fact is never lost.
22
22
 
23
23
  ## Common commit pipeline
@@ -42,6 +42,8 @@ export type {
42
42
  ProjectionProtocolIdentity,
43
43
  ProjectionRunFinishInput,
44
44
  ProjectionSourceAssertion,
45
+ ProjectionSourceBase,
46
+ ProjectionSourceDeletion,
45
47
  ProjectionSourceEntry,
46
48
  ProjectionSourceRef,
47
49
  ProjectionSourceReplacement,
@@ -4,12 +4,14 @@ import type {
4
4
  OntologyEditCommit,
5
5
  ProjectionCommitResult,
6
6
  ProjectionRunFinishInput,
7
+ ProjectionSourceRef,
7
8
  ProjectionSourceReplacement,
8
9
  TelemetryAppend,
9
10
  TelemetryCommitResult,
10
11
  } from "../materialization/model"
11
12
  import type { OntologyRegistry } from "../ontology"
12
13
  import type { ProjectionRegistry } from "../projections/registry"
14
+ import type { OntologySourceRecord } from "../storage/ontology"
13
15
  import {
14
16
  createMaterializerContext,
15
17
  type MaterializerContext,
@@ -34,6 +36,7 @@ export interface OntologyMaterializerContract {
34
36
  commit(input: MaterializerCommand<OntologyEditCommit>): Promise<EditCommitResult>
35
37
  }
36
38
  readonly projections: {
39
+ getActive(source: ProjectionSourceRef): Promise<OntologySourceRecord | null>
37
40
  replace(
38
41
  input: MaterializerCommand<ProjectionSourceReplacement>
39
42
  ): Promise<ProjectionCommitResult>
@@ -50,6 +53,7 @@ export interface BoundOntologyMaterializer {
50
53
  commit(input: OntologyEditCommit): Promise<EditCommitResult>
51
54
  }
52
55
  readonly projections: {
56
+ getActive(source: ProjectionSourceRef): Promise<OntologySourceRecord | null>
53
57
  replace(input: ProjectionSourceReplacement): Promise<ProjectionCommitResult>
54
58
  finishRun(input: ProjectionRunFinishInput): Promise<void>
55
59
  }
@@ -64,6 +68,11 @@ export class OntologyMaterializer implements OntologyMaterializerContract {
64
68
  commitEdits(this.context, command),
65
69
  }
66
70
  readonly projections = {
71
+ getActive: (source: ProjectionSourceRef) =>
72
+ this.context.storage.ontology.sources.getActive({
73
+ projectId: this.context.projectId,
74
+ source,
75
+ }),
67
76
  replace: (command: MaterializerCommand<ProjectionSourceReplacement>) =>
68
77
  replaceProjection(this.context, command),
69
78
  finishRun: (command: MaterializerCommand<ProjectionRunFinishInput>) =>
@@ -80,6 +89,7 @@ export class OntologyMaterializer implements OntologyMaterializerContract {
80
89
  commit: (input: OntologyEditCommit) => this.edits.commit({ scope, input }),
81
90
  }),
82
91
  projections: Object.freeze({
92
+ getActive: (source: ProjectionSourceRef) => this.projections.getActive(source),
83
93
  replace: (input: ProjectionSourceReplacement) => this.projections.replace({ scope, input }),
84
94
  finishRun: (input: ProjectionRunFinishInput) =>
85
95
  this.projections.finishRun({ scope, input }),
@@ -1,5 +1,5 @@
1
1
  import { MaterializationValidationError } from "../../materialization/errors"
2
- import type { ProjectionSourceEntry } from "../../materialization/model"
2
+ import type { ProjectionEntityRef, ProjectionSourceEntry } from "../../materialization/model"
3
3
  import { linkOwnershipKey } from "../../materialization/refs"
4
4
  import type { OntologyRegistry } from "../../ontology"
5
5
  import type { ProjectionRegistry } from "../../projections/registry"
@@ -30,6 +30,24 @@ export function createProjectionEntryValidator(
30
30
  return (entry) => validateProjectionEntry(ontology, resolved, policy, entry)
31
31
  }
32
32
 
33
+ export function validateProjectionRootRef(
34
+ resolved: ResolvedSourceProjection,
35
+ root: ProjectionEntityRef
36
+ ): void {
37
+ const definition = resolved.definition
38
+ const owned =
39
+ definition._tag === "ObjectProjectionDefinition"
40
+ ? root.kind === "object" && root.ref.objectTypeId === definition.objectTypeId
41
+ : root.kind === "link" &&
42
+ root.ref.source.objectTypeId === definition.sourceObjectTypeId &&
43
+ root.ref.target.objectTypeId === definition.targetObjectTypeId &&
44
+ root.ref.linkId === definition.linkId
45
+ if (!owned)
46
+ throw new MaterializationValidationError(
47
+ "Projection root is outside its owned type or link scope."
48
+ )
49
+ }
50
+
33
51
  function createValidationPolicy(resolved: ResolvedSourceProjection): ProjectionValidationPolicy {
34
52
  const ownedProperties = new Map(
35
53
  resolved.ownership.objects.map((object) => [object.objectTypeId, new Set(object.propertyIds)])
@@ -10,6 +10,8 @@ import type {
10
10
  ProjectionCommitResult,
11
11
  ProjectionExecution,
12
12
  ProjectionMaterializationIdentity,
13
+ ProjectionSourceBase,
14
+ ProjectionSourceDeletion,
13
15
  ProjectionSourceEntry,
14
16
  ProjectionSourceRef,
15
17
  ProjectionSourceReplacement,
@@ -19,6 +21,7 @@ import type {
19
21
  OntologyCommitRecord,
20
22
  OntologyCommitWrite,
21
23
  OntologyMaterializationStorage,
24
+ OntologySourceRecord,
22
25
  OntologyStorage,
23
26
  } from "../../storage/ontology"
24
27
  import type { MaterializerContext, MaterializerStorage } from "../context"
@@ -60,7 +63,8 @@ interface PreparedProjectionReplacement {
60
63
  readonly source: ProjectionSourceRef
61
64
  readonly datasetVersion: PinnedDatasetVersion
62
65
  readonly execution: ProjectionExecution
63
- readonly entries: AsyncIterable<ProjectionSourceEntry>
66
+ readonly entries: AsyncIterable<ProjectionSourceEntry | ProjectionSourceDeletion>
67
+ readonly base?: ProjectionSourceBase
64
68
  readonly signal?: AbortSignal
65
69
  readonly resolved: ResolvedSourceProjection
66
70
  readonly projectionKind: "object" | "link"
@@ -128,6 +132,7 @@ function prepareProjectionReplacement(
128
132
  datasetVersion,
129
133
  execution,
130
134
  entries: raw.input.entries,
135
+ ...(raw.input.base ? { base: Object.freeze({ ...raw.input.base }) } : {}),
131
136
  resolved,
132
137
  projectionKind,
133
138
  runIdentity,
@@ -237,6 +242,7 @@ async function prepareProjectionCandidate(
237
242
  source: command.source,
238
243
  })
239
244
  validateProjectionWatermark(active, command.datasetVersion)
245
+ assertDeltaBase(active, command)
240
246
  return {
241
247
  materializationId: context.materializationId(),
242
248
  createdAt: context.clock().toISOString(),
@@ -263,6 +269,7 @@ async function stageProjectionCandidate(
263
269
  ownershipHash: command.resolved.ownershipHash,
264
270
  createdAt: candidate.createdAt,
265
271
  entries: command.entries,
272
+ ...(command.base ? { base: command.base } : {}),
266
273
  validateEntry: createProjectionEntryValidator(context.ontology, command.resolved),
267
274
  }
268
275
  const staged = await stageCandidateEntries(context, input, command.signal)
@@ -312,6 +319,14 @@ async function executeProjectionTransaction(
312
319
  )
313
320
  if (replay) return projectionReplayResult(replay, command)
314
321
 
322
+ if (command.base) {
323
+ const active = await storage.ontology.sources.getActive({
324
+ projectId: context.projectId,
325
+ source: command.source,
326
+ })
327
+ validateProjectionWatermark(active, command.datasetVersion)
328
+ assertDeltaBase(active, command)
329
+ }
315
330
  const origin = projectionOrigin(command)
316
331
  throwIfAborted(command.signal)
317
332
  const session = await storage.ontology.materializations.begin({
@@ -478,3 +493,23 @@ function validateProjectionWatermark(
478
493
  if (!active) return
479
494
  assertPinnedDatasetWatermark(active.datasetVersion, next, "Projection replacement")
480
495
  }
496
+
497
+ function assertDeltaBase(
498
+ active: OntologySourceRecord | null,
499
+ command: PreparedProjectionReplacement
500
+ ): void {
501
+ if (
502
+ command.base &&
503
+ (!active ||
504
+ active.materializationId !== command.base.materializationId ||
505
+ active.lastCommitId !== command.base.lastCommitId ||
506
+ active.projectionRevision !== command.runIdentity.projectionRevision ||
507
+ active.ontologyRevision !== command.runIdentity.ontologyRevision ||
508
+ active.ownershipHash !== command.runIdentity.ownershipHash)
509
+ ) {
510
+ throw new MaterializationConflictError(
511
+ "source-materialization",
512
+ "Projection delta no longer matches the active source or its definition."
513
+ )
514
+ }
515
+ }
@@ -1,16 +1,19 @@
1
+ import { MaterializationValidationError } from "../../materialization/errors"
1
2
  import type {
2
3
  PinnedDatasetVersion,
3
4
  ProjectionExecution,
5
+ ProjectionSourceBase,
6
+ ProjectionSourceDeletion,
4
7
  ProjectionSourceEntry,
5
8
  ProjectionSourceRef,
6
9
  } from "../../materialization/model"
7
10
  import { utf8JsonByteLength } from "../../materialization/refs"
8
- import type { StageSourceAssertion } from "../../storage/ontology"
11
+ import type { StageSourceAssertion, StageSourceRoot } from "../../storage/ontology"
9
12
  import type { MaterializerContext } from "../context"
10
13
  import { throwIfAborted } from "../shared/abort"
11
14
  import { chunkBySize } from "../shared/chunking"
12
- import { normalizeProjectionSourceEntry } from "../shared/normalize"
13
- import type { ProjectionEntryValidator } from "./entry-validator"
15
+ import { normalizeProjectionEntity, normalizeProjectionSourceEntry } from "../shared/normalize"
16
+ import { type ProjectionEntryValidator, validateProjectionRootRef } from "./entry-validator"
14
17
 
15
18
  export interface StagedProjectionMaterialization {
16
19
  readonly rootCount: number
@@ -37,7 +40,8 @@ export async function stageProjectionMaterialization(
37
40
  readonly projectionRevision: string
38
41
  readonly ownershipHash: string
39
42
  readonly createdAt: string
40
- readonly entries: AsyncIterable<ProjectionSourceEntry>
43
+ readonly entries: AsyncIterable<ProjectionSourceEntry | ProjectionSourceDeletion>
44
+ readonly base?: ProjectionSourceBase
41
45
  readonly validateEntry: ProjectionEntryValidator
42
46
  readonly signal?: AbortSignal
43
47
  }
@@ -54,13 +58,28 @@ export async function stageProjectionMaterialization(
54
58
  ownershipHash: input.ownershipHash,
55
59
  ontologyRevision: context.projectionRegistry.ontologyRevision,
56
60
  createdAt: input.createdAt,
61
+ ...(input.base ? { base: input.base } : {}),
57
62
  })
58
63
 
59
64
  let rootCount = 0
60
65
  let assertionCount = 0
61
- async function* assertions(): AsyncIterable<StageSourceAssertion> {
66
+ async function* assertions(): AsyncIterable<StageSourceAssertion | StageSourceRoot> {
62
67
  for await (const rawEntry of input.entries) {
63
68
  throwIfAborted(input.signal)
69
+ if ("deleted" in rawEntry) {
70
+ if (!input.base || rawEntry.deleted !== true) {
71
+ throw new MaterializationValidationError(
72
+ "Explicit root deletions require a pinned source base."
73
+ )
74
+ }
75
+ const root = normalizeProjectionEntity(rawEntry.root)
76
+ validateProjectionRootRef(
77
+ context.projectionRegistry.resolveSource(input.source.projectionId),
78
+ root
79
+ )
80
+ yield { root, stagingOrdinal: rootCount++ }
81
+ continue
82
+ }
64
83
  const entry = input.validateEntry(normalizeProjectionSourceEntry(rawEntry))
65
84
  const stagingOrdinal = rootCount
66
85
  for (const assertion of entry.assertions) {
@@ -82,7 +101,8 @@ export async function stageProjectionMaterialization(
82
101
  source: input.source,
83
102
  materializationId: input.materializationId,
84
103
  execution: input.execution,
85
- rows,
104
+ rows: rows.filter((row): row is StageSourceAssertion => "assertion" in row),
105
+ deletions: rows.filter((row) => !("assertion" in row)),
86
106
  })
87
107
  }
88
108
 
@@ -344,7 +344,7 @@ export function normalizeProjectionExecution(input: ProjectionExecution): Projec
344
344
  })
345
345
  }
346
346
 
347
- function normalizeProjectionEntity(entity: ProjectionEntityRef): ProjectionEntityRef {
347
+ export function normalizeProjectionEntity(entity: ProjectionEntityRef): ProjectionEntityRef {
348
348
  return entity.kind === "object"
349
349
  ? Object.freeze({ kind: "object", ref: normalizeObjectRef(entity.ref) })
350
350
  : Object.freeze({ kind: "link", ref: normalizeLinkRef(entity.ref) })
@@ -14,6 +14,10 @@ export interface ModelDefinition {
14
14
  readonly modelId: string
15
15
  readonly name?: string
16
16
  readonly description?: string
17
+ /** Model author for display; does not change the provider/model routing identity. */
18
+ readonly publisher?: { readonly id: string; readonly name: string }
19
+ /** Hosting service label, when the model is offered through an intermediary. */
20
+ readonly via?: string
17
21
  readonly family?: string
18
22
  readonly tags?: readonly string[]
19
23
  readonly releaseDate?: string
@@ -38,6 +42,17 @@ export function defineLanguageModel(definition: LanguageModelDefinition): Langua
38
42
  assertModelId(definition.modelId, "modelId")
39
43
  assertOptionalString(definition.name, "name")
40
44
  assertOptionalString(definition.description, "description")
45
+ assertOptionalString(definition.via, "via")
46
+ if (definition.via !== undefined && !definition.via.trim())
47
+ throw new TypeError("[Sixb] Model via must not be empty.")
48
+ const publisher = definition.publisher
49
+ if (publisher !== undefined) {
50
+ assertRecord(publisher, "publisher")
51
+ for (const [field, value] of Object.entries({ id: publisher.id, name: publisher.name })) {
52
+ if (typeof value !== "string" || !value.trim() || value !== value.trim())
53
+ throw new TypeError(`[Sixb] Model publisher.${field} must be a nonempty trimmed string.`)
54
+ }
55
+ }
41
56
  assertOptionalString(definition.family, "family")
42
57
  assertOptionalString(definition.releaseDate, "releaseDate")
43
58
  assertOptionalString(definition.knowledgeCutoff, "knowledgeCutoff")
@@ -52,6 +67,10 @@ export function defineLanguageModel(definition: LanguageModelDefinition): Langua
52
67
  modelId: definition.modelId,
53
68
  ...(definition.name === undefined ? {} : { name: definition.name }),
54
69
  ...(definition.description === undefined ? {} : { description: definition.description }),
70
+ ...(publisher === undefined
71
+ ? {}
72
+ : { publisher: Object.freeze({ id: publisher.id, name: publisher.name }) }),
73
+ ...(definition.via === undefined ? {} : { via: definition.via }),
55
74
  ...(definition.family === undefined ? {} : { family: definition.family }),
56
75
  ...(tags === undefined ? {} : { tags }),
57
76
  ...(definition.releaseDate === undefined ? {} : { releaseDate: definition.releaseDate }),
@@ -335,8 +335,12 @@ function partitionInputUsage(usage: ModelUsage, rateCard: LanguageModelRateCard)
335
335
  ...(rateCard.cacheReadInput === undefined ? {} : { cacheRead }),
336
336
  ...(hasSpecificWrites
337
337
  ? {
338
- cacheWrite5m: usage.cacheWrite5mInputTokens ?? 0,
339
- cacheWrite1h: usage.cacheWrite1hInputTokens ?? 0,
338
+ ...(rateCard.cacheWriteInput5m !== undefined || rateCard.cacheWriteInput !== undefined
339
+ ? { cacheWrite5m: usage.cacheWrite5mInputTokens ?? 0 }
340
+ : {}),
341
+ ...(rateCard.cacheWriteInput1h !== undefined || rateCard.cacheWriteInput !== undefined
342
+ ? { cacheWrite1h: usage.cacheWrite1hInputTokens ?? 0 }
343
+ : {}),
340
344
  }
341
345
  : rateCard.cacheWriteInput === undefined
342
346
  ? {}
@@ -101,7 +101,10 @@ export async function dispatchPipelineRun(
101
101
  input: DispatchPipelineRunInput
102
102
  ): Promise<PipelineRunRequestResult> {
103
103
  const runId = createPipelineRunId(input.runId)
104
- const persisted = await persistPipelineRun(input, runId)
104
+ let persisted = await persistPipelineRun(input, runId)
105
+ if (!persisted.publish && input.validateExistingRun && persisted.run.status === "queued") {
106
+ persisted = await reusePipelineRun(input, persisted.run)
107
+ }
105
108
  if (!persisted.publish) return existingPipelineRunResult(persisted.run)
106
109
  return publishPipelineRun(input, persisted)
107
110
  }
@@ -155,6 +158,15 @@ async function reusePipelineRun(
155
158
  ): Promise<PersistedPipelineRun> {
156
159
  assertExistingRunMatchesRequest(existing, input)
157
160
  await input.validateExistingRun?.(existing, input.storage)
161
+ if (input.validateExistingRun && existing.status === "queued") {
162
+ const execution = await input.storage.executions.getById({
163
+ projectId: input.projectId,
164
+ id: existing.executionId,
165
+ })
166
+ if (!execution)
167
+ throw new PipelineRunError(`[Sixb] Execution '${existing.executionId}' was not found.`)
168
+ return { publish: true, run: existing, execution, queuedAt: existing.queuedAt, created: false }
169
+ }
158
170
  if (
159
171
  existing.status !== "failed" ||
160
172
  existing.error?.code !== "queue.enqueue_failed" ||
@@ -200,6 +212,11 @@ async function publishPipelineRun(
200
212
  },
201
213
  ],
202
214
  })
215
+ if (!job || job.id !== persisted.run.id) {
216
+ throw new PipelineRunError(
217
+ `[Sixb] Queue did not acknowledge Pipeline run '${persisted.run.id}'.`
218
+ )
219
+ }
203
220
  return {
204
221
  pipelineId: persisted.run.pipelineId,
205
222
  runId: persisted.run.id,
@@ -208,6 +225,9 @@ async function publishPipelineRun(
208
225
  created: persisted.created,
209
226
  }
210
227
  } catch (error) {
228
+ // Automatic consumers retain the batch and retry. Keep uncertain delivery queued:
229
+ // a lost reply does not prove that the queue rejected the job.
230
+ if (input.validateExistingRun) throw error
211
231
  const failedAt = new Date()
212
232
  const failure = toEnqueueFailure(error, persisted.run, failedAt)
213
233
  const failed = await requirePipelineRunStorage(input.storage).finish({