deepline 0.3.461 → 0.3.462

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 (296) hide show
  1. package/dist/bundling-sources/sdk/src/client-core.ts +7593 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +8 -7366
  3. package/dist/bundling-sources/sdk/src/http-core.ts +1239 -0
  4. package/dist/bundling-sources/sdk/src/http.ts +6 -1231
  5. package/dist/bundling-sources/sdk/src/index.ts +4 -1
  6. package/dist/bundling-sources/sdk/src/play.ts +5 -5
  7. package/dist/bundling-sources/sdk/src/plays/client-core.ts +437 -0
  8. package/dist/bundling-sources/sdk/src/plays/client.ts +4 -421
  9. package/dist/bundling-sources/sdk/src/plays/input-example.ts +3 -4
  10. package/dist/bundling-sources/sdk/src/plays/play-description.ts +1 -1
  11. package/dist/bundling-sources/sdk/src/plays/run-request.ts +1 -1
  12. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  13. package/dist/bundling-sources/sdk/src/server.ts +43 -0
  14. package/dist/bundling-sources/sdk/src/types.ts +15 -5
  15. package/dist/bundling-sources/shared_libs/integration-contracts/billing-entitlements.ts +15 -0
  16. package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +0 -307
  17. package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
  18. package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +3 -2
  19. package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
  20. package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +34 -0
  21. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +59 -0
  22. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +94 -1
  23. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +11 -1
  24. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-failure-codes.ts +24 -0
  25. package/dist/bundling-sources/shared_libs/observability/dlq.ts +32 -0
  26. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +57 -3
  27. package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +1 -0
  28. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +66 -1
  29. package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +36 -7
  30. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +250 -11
  31. package/dist/bundling-sources/shared_libs/play-runtime/array-input-store.ts +319 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +991 -359
  33. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +17 -0
  34. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +13 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +110 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +155 -6
  37. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +110 -6
  38. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -13
  39. package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +14 -1
  40. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +57 -1
  41. package/dist/bundling-sources/shared_libs/play-runtime/free-company-lookup-batching.ts +218 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +42 -5
  43. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-budget-state-backend.ts +6 -1
  44. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +92 -31
  45. package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +69 -14
  46. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +93 -23
  47. package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +15 -4
  48. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +22 -18
  49. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +5 -0
  50. package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +2 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +190 -14
  52. package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +131 -0
  53. package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +77 -2
  54. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +271 -2
  55. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +51 -0
  56. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +2 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +27 -1
  58. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
  59. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
  60. package/dist/bundling-sources/shared_libs/play-runtime/provider-text-for-log.ts +63 -0
  61. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +19 -0
  62. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +112 -16
  63. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +104 -2
  64. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +265 -151
  65. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +17 -0
  66. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +35 -14
  67. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +12 -1
  68. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +4 -0
  69. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-labels.ts +36 -0
  70. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +136 -70
  71. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +237 -36
  72. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +148 -4
  73. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +6 -0
  74. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +285 -32
  75. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +251 -56
  76. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +29 -4
  77. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/sandbox-create-outcome.ts +27 -0
  78. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +22 -1
  79. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1397 -382
  80. package/dist/bundling-sources/shared_libs/play-runtime/runtime-array-input-receipts.ts +920 -0
  81. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +16 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +38 -0
  83. package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +6 -0
  84. package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -1
  85. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +30 -0
  86. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +14 -3
  87. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +31 -4
  88. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -0
  89. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +20 -7
  90. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +12 -0
  91. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/index.ts +9 -0
  92. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +10 -0
  93. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +4 -0
  94. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1496 -320
  95. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +31 -1
  96. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1389 -129
  97. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +36 -0
  98. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
  99. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +162 -23
  100. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +499 -115
  101. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +377 -9
  102. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +117 -8
  103. package/dist/bundling-sources/shared_libs/play-runtime/secret-resolution-retry-policy.ts +25 -0
  104. package/dist/bundling-sources/shared_libs/play-runtime/terminal-runtime-performance.ts +391 -0
  105. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +40 -0
  106. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +6 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/mapped-calls.ts +171 -0
  108. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +16 -1
  109. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +26 -3
  110. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +16 -2
  111. package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +28 -0
  112. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +55 -5
  113. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +41 -1
  114. package/dist/bundling-sources/shared_libs/plays/contracts.ts +4 -0
  115. package/dist/bundling-sources/shared_libs/plays/dataset.ts +9 -3
  116. package/dist/bundling-sources/shared_libs/plays/deploy/manifest-contract.ts +2 -0
  117. package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +3 -2
  118. package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +2 -2
  119. package/dist/bundling-sources/shared_libs/plays/run-output-summary.ts +66 -0
  120. package/dist/bundling-sources/shared_libs/plays/script-entry.ts +1 -1
  121. package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +43 -1
  122. package/dist/bundling-sources/shared_libs/product-notifications/content.ts +9 -0
  123. package/dist/bundling-sources/shared_libs/product-notifications/email.ts +91 -13
  124. package/dist/bundling-sources/shared_libs/product-notifications/events.ts +3 -0
  125. package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +41 -24
  126. package/dist/bundling-sources/shared_libs/security/attested-client-ip.ts +91 -0
  127. package/dist/bundling-sources/shared_libs/security/internal-actor.ts +0 -11
  128. package/dist/cli/{auth-6HJXNWUG.mjs → auth-JDLEY7VU.mjs} +5 -4
  129. package/dist/cli/auth-UXKY6TCC.js +41 -0
  130. package/dist/cli/{billing-6P5HO6QG.js → billing-HXAXB3XZ.js} +152 -78
  131. package/dist/cli/{billing-MJ42N7YF.mjs → billing-SDHLBLMV.mjs} +84 -10
  132. package/dist/cli/{chunk-5MDIZX7M.js → chunk-3ACMRZRV.js} +8 -6
  133. package/dist/cli/{chunk-FGLKOWSC.mjs → chunk-3KZCFOZ6.mjs} +1 -1
  134. package/dist/cli/chunk-4KQ6SIBC.mjs +1038 -0
  135. package/dist/cli/{chunk-Z2GUFYT6.js → chunk-5LEAXRHV.js} +11 -11
  136. package/dist/cli/{chunk-MEAIOXJL.mjs → chunk-6NNVJDVR.mjs} +7 -5
  137. package/dist/cli/{chunk-NMJ4D2WO.js → chunk-6PMCRYDA.js} +216 -91
  138. package/dist/cli/{chunk-RY4IVOU3.mjs → chunk-6RNQGWFD.mjs} +16 -806
  139. package/dist/cli/{chunk-EBU7LQ64.js → chunk-6V7KVRR5.js} +3 -3
  140. package/dist/cli/{chunk-OZBWRICM.js → chunk-7LFIMWMW.js} +2 -2
  141. package/dist/cli/chunk-7MJ6VI2T.mjs +19 -0
  142. package/dist/cli/chunk-7SWNPNML.js +1039 -0
  143. package/dist/cli/{chunk-IHHLTHE7.mjs → chunk-7U3XNPOA.mjs} +267 -38
  144. package/dist/cli/{chunk-5FDKJQZE.js → chunk-7VZHXVOQ.js} +1 -1
  145. package/dist/cli/{chunk-R64BGGRQ.mjs → chunk-AT636LLU.mjs} +2 -2
  146. package/dist/cli/{chunk-MDJPEGVN.js → chunk-BGTPIMSM.js} +392 -261
  147. package/dist/cli/{chunk-KVJ5VHW5.mjs → chunk-CKSOY47X.mjs} +2 -2
  148. package/dist/cli/{chunk-7DH2FD7Y.mjs → chunk-D464JW3N.mjs} +5 -85
  149. package/dist/cli/chunk-D6DXOUTO.mjs +827 -0
  150. package/dist/cli/{describe-2WQY7ZCY.js → chunk-EM4TXCCI.js} +27 -44
  151. package/dist/cli/chunk-F6QV42MC.mjs +91 -0
  152. package/dist/cli/chunk-FKVYR3QA.mjs +1039 -0
  153. package/dist/cli/{chunk-FGMX4HUZ.js → chunk-GEGW5HPZ.js} +29 -27
  154. package/dist/cli/{chunk-TNMBPMMC.js → chunk-HUB3CCM2.js} +13 -4
  155. package/dist/cli/{chunk-ACCR7POB.js → chunk-I6VHOU5O.js} +27 -27
  156. package/dist/cli/{chunk-Z2XUZC34.js → chunk-IAYSWZDJ.js} +188 -76
  157. package/dist/cli/chunk-JF3TLIMQ.js +19 -0
  158. package/dist/cli/{chunk-HDFRJ4IT.mjs → chunk-JVHOS3K3.mjs} +177 -65
  159. package/dist/cli/{chunk-V7REJRDZ.mjs → chunk-LFXLQEZN.mjs} +1 -1
  160. package/dist/cli/{chunk-CRYOUPEB.js → chunk-LROWFPGN.js} +16 -16
  161. package/dist/cli/{chunk-SLEUWLJE.mjs → chunk-MSY22NQW.mjs} +5 -5
  162. package/dist/cli/{chunk-BGY2PLP7.mjs → chunk-MUUQZIOF.mjs} +23 -49
  163. package/dist/cli/{chunk-FCAZQ7WV.js → chunk-NBLSCHKK.js} +52 -50
  164. package/dist/cli/{chunk-QAJAJPKK.mjs → chunk-NHRWZPWZ.mjs} +4 -2
  165. package/dist/cli/{chunk-KXMNM4AQ.js → chunk-NMU3VR5U.js} +4 -5
  166. package/dist/cli/{chunk-QIW7TVV6.mjs → chunk-O2RX5A66.mjs} +14 -12
  167. package/dist/cli/{chunk-SAZFZQRI.js → chunk-OMQ23IXL.js} +2 -2
  168. package/dist/cli/{chunk-5IYOUBFZ.js → chunk-OPJAJBD4.js} +28 -54
  169. package/dist/cli/{chunk-FJZILBL7.mjs → chunk-PHSEINNH.mjs} +5 -5
  170. package/dist/cli/{chunk-3DNKFH2G.mjs → chunk-PKHVSIJG.mjs} +19 -1
  171. package/dist/cli/{chunk-WIYWSYDS.mjs → chunk-Q2EIZKVX.mjs} +3 -3
  172. package/dist/cli/{chunk-5FY72YOV.js → chunk-QJZ6WNWD.js} +8 -8
  173. package/dist/cli/{chunk-EIMG75BT.mjs → chunk-S3A4IXBQ.mjs} +4 -5
  174. package/dist/cli/{chunk-3BMLICF7.mjs → chunk-S42YIQNE.mjs} +13 -8
  175. package/dist/cli/{chunk-RFONC4WJ.mjs → chunk-S6UAJR6V.mjs} +3 -3
  176. package/dist/cli/{chunk-G7L27KZB.mjs → chunk-TKAQR3IB.mjs} +31 -21
  177. package/dist/cli/{chunk-QWRHGGUH.js → chunk-UAJFWWZE.js} +20 -2
  178. package/dist/cli/{chunk-VZBCEA5S.mjs → chunk-UDRPEZ5F.mjs} +223 -92
  179. package/dist/cli/{chunk-KCCOQ5G5.js → chunk-ULK7JGGI.js} +511 -282
  180. package/dist/cli/chunk-V335HGX5.js +1038 -0
  181. package/dist/cli/{chunk-MGXEUZHL.mjs → chunk-V3MEA7NB.mjs} +7 -5
  182. package/dist/cli/{chunk-O6QOMHCH.js → chunk-VFGVXXZP.js} +37 -35
  183. package/dist/cli/chunk-VLEVVDWG.js +91 -0
  184. package/dist/cli/{chunk-R2GLGLDR.mjs → chunk-VPHN2HAL.mjs} +216 -91
  185. package/dist/cli/{chunk-CFUTOWE4.js → chunk-WG3KGAII.js} +8 -88
  186. package/dist/cli/{describe-FRAVCY5F.mjs → chunk-WIY6U6GD.mjs} +19 -36
  187. package/dist/cli/{chunk-PNATXKLP.js → chunk-XANRM3QA.js} +6 -6
  188. package/dist/cli/{chunk-KGQNIA37.js → chunk-XQCTG5OO.js} +44 -34
  189. package/dist/cli/{chunk-T3MVIPHG.mjs → chunk-XZAFIOUQ.mjs} +1 -1
  190. package/dist/cli/chunk-Y4DPU4OM.js +827 -0
  191. package/dist/cli/chunk-YT5EODJO.js +920 -0
  192. package/dist/cli/{chunk-SCIR5JXW.js → chunk-ZGQSFYD2.js} +56 -51
  193. package/dist/cli/{chunk-QEYHTIV4.mjs → chunk-ZUK6LIJB.mjs} +10 -1
  194. package/dist/cli/command-docs.d.mts +5 -0
  195. package/dist/cli/command-docs.d.ts +5 -0
  196. package/dist/cli/command-docs.js +2 -2
  197. package/dist/cli/command-docs.mjs +1 -1
  198. package/dist/cli/{csv-NX7NO3O6.js → csv-C56GSCEU.js} +13 -12
  199. package/dist/cli/{csv-DQ6GW5B5.mjs → csv-L54JS7TF.mjs} +4 -3
  200. package/dist/cli/{db-R72DFMP6.js → db-MOGRMZTA.js} +30 -27
  201. package/dist/cli/{db-2YP33M4K.mjs → db-YVBUW2DX.mjs} +10 -7
  202. package/dist/cli/describe-KYEULWPG.js +48 -0
  203. package/dist/cli/describe-NLZKKT7C.mjs +48 -0
  204. package/dist/cli/describe-core.d.mts +153 -5
  205. package/dist/cli/describe-core.d.ts +153 -5
  206. package/dist/cli/describe-core.js +9 -5
  207. package/dist/cli/describe-core.mjs +10 -6
  208. package/dist/cli/{executions-ZLHD4QIT.js → executions-A7L4ULPP.js} +9 -7
  209. package/dist/cli/{executions-WFBU7L2Q.mjs → executions-ZBGSTT37.mjs} +7 -5
  210. package/dist/cli/{feedback-CN3HJFVF.mjs → feedback-G6GU37FD.mjs} +6 -5
  211. package/dist/cli/{feedback-NDV6TPHG.js → feedback-OHLY7RYD.js} +10 -9
  212. package/dist/cli/getting-started.d.mts +6 -6
  213. package/dist/cli/getting-started.d.ts +6 -6
  214. package/dist/cli/getting-started.js +2 -2
  215. package/dist/cli/getting-started.mjs +1 -1
  216. package/dist/cli/git-P76N4NDQ.js +25 -0
  217. package/dist/cli/{git-QAD6E3HW.mjs → git-PKZW3QD5.mjs} +5 -4
  218. package/dist/cli/index.js +152 -142
  219. package/dist/cli/index.mjs +56 -46
  220. package/dist/cli/{legacy-noops-KVC5QJ74.js → legacy-noops-5LM3D724.js} +8 -7
  221. package/dist/cli/{legacy-noops-TPTKNBI2.mjs → legacy-noops-LJJYG6YA.mjs} +5 -4
  222. package/dist/cli/{monitors-SV57JFLO.mjs → monitors-72QV4ALO.mjs} +19 -6
  223. package/dist/cli/{monitors-KCROV6PJ.js → monitors-UX3H5DC2.js} +103 -90
  224. package/dist/cli/{org-KX6QIR7A.mjs → org-6RRRKOCP.mjs} +9 -6
  225. package/dist/cli/{org-NJYX5743.js → org-IF7ISUVB.js} +70 -67
  226. package/dist/cli/pages-3SU3HKL7.js +252 -0
  227. package/dist/cli/pages-DXDYYKEK.mjs +252 -0
  228. package/dist/cli/{play-IQQ57L7Z.mjs → play-AHASKRLA.mjs} +512 -1508
  229. package/dist/cli/{play-32L7EQN4.js → play-EUIUVLUH.js} +1090 -2086
  230. package/dist/cli/{providers-4WEC2EQN.mjs → providers-GWGE3WY3.mjs} +7 -5
  231. package/dist/cli/{providers-ZQV6QLVQ.js → providers-V5WU4VXJ.js} +10 -8
  232. package/dist/cli/{quickstart-RQ76RIUE.mjs → quickstart-OXKQ5ZST.mjs} +5 -4
  233. package/dist/cli/{quickstart-HKUSFADF.js → quickstart-QP65I5PF.js} +13 -12
  234. package/dist/cli/run-6MM72IGL.mjs +443 -0
  235. package/dist/cli/run-F3FTYS56.js +443 -0
  236. package/dist/cli/search-OYKOOI7A.js +32 -0
  237. package/dist/cli/{search-ZRAVFBZC.mjs → search-ZMEBVJZB.mjs} +8 -6
  238. package/dist/cli/{secrets-J3G5Y43U.js → secrets-ACND5N6A.js} +16 -14
  239. package/dist/cli/{secrets-CMJOVNVH.mjs → secrets-XRCJFF3L.mjs} +7 -5
  240. package/dist/cli/{sessions-MDQYY5CB.mjs → sessions-RTK3CEW6.mjs} +5 -4
  241. package/dist/cli/{sessions-WY7VN4AE.js → sessions-ZGRJPCFF.js} +6 -5
  242. package/dist/cli/{settings-HTNTFKCE.js → settings-PD5KWQQZ.js} +80 -77
  243. package/dist/cli/{settings-4RWZPCT5.mjs → settings-XDRBPRDE.mjs} +14 -11
  244. package/dist/cli/{setup-P3GYYZWG.mjs → setup-3HPYAOCC.mjs} +12 -10
  245. package/dist/cli/{setup-QGCAP62X.js → setup-E2Q6PXHC.js} +53 -51
  246. package/dist/cli/{skills-7NAE4ICL.mjs → skills-OOQFMPOV.mjs} +7 -6
  247. package/dist/cli/skills-XYWV52KB.js +31 -0
  248. package/dist/cli/tools-ASCDZJCK.js +55 -0
  249. package/dist/cli/tools-C5ZT3UIC.mjs +55 -0
  250. package/dist/cli/update-5RQSEIFM.js +33 -0
  251. package/dist/cli/{update-GODLRKNB.mjs → update-ZWJTADIW.mjs} +9 -8
  252. package/dist/cli/{workflow-4BXOUVEO.mjs → workflow-23NMPAJ7.mjs} +10 -8
  253. package/dist/cli/{workflow-AO3A6LXN.js → workflow-TCXU5YJV.js} +20 -18
  254. package/dist/client-DS2IWYZF.d.ts +10 -0
  255. package/dist/client-DTwnz_AW.d.mts +10 -0
  256. package/dist/{client-CYqG23K1.d.ts → client-core-B_6HAIBy.d.ts} +385 -12
  257. package/dist/{client-BbU5_j7n.d.mts → client-core-DzBSlY1U.d.mts} +385 -12
  258. package/dist/{compiler-manifest-CWz_sNOQ.d.ts → compiler-manifest-Dcyd3-Zd.d.mts} +43 -1
  259. package/dist/{compiler-manifest-CWz_sNOQ.d.mts → compiler-manifest-Dcyd3-Zd.d.ts} +43 -1
  260. package/dist/errors-d-sTrZhe.d.mts +142 -0
  261. package/dist/errors-yQwfgrcX.d.ts +142 -0
  262. package/dist/{index-BF2JB_Ug.d.mts → index-C6oXchjN.d.mts} +1 -1
  263. package/dist/{index-4NPXDzlD.d.ts → index-P56zy_z5.d.ts} +1 -1
  264. package/dist/index.d.mts +11 -147
  265. package/dist/index.d.ts +11 -147
  266. package/dist/index.js +15 -11
  267. package/dist/index.mjs +14 -10
  268. package/dist/install-integrity.json +141 -104
  269. package/dist/plays/bundle-play-file.d.mts +3 -3
  270. package/dist/plays/bundle-play-file.d.ts +3 -3
  271. package/dist/plays/bundle-play-file.mjs +2 -1
  272. package/dist/plays/play-description.d.mts +2 -2
  273. package/dist/plays/play-description.d.ts +2 -2
  274. package/dist/plays/play-description.js +2 -2
  275. package/dist/plays/play-description.mjs +1 -1
  276. package/dist/plays/run-request.d.mts +2 -2
  277. package/dist/plays/run-request.d.ts +2 -2
  278. package/dist/release.d.mts +1 -1
  279. package/dist/release.d.ts +1 -1
  280. package/dist/release.js +2 -2
  281. package/dist/release.mjs +1 -1
  282. package/dist/server.d.mts +17 -0
  283. package/dist/server.d.ts +17 -0
  284. package/dist/server.js +76 -0
  285. package/dist/server.mjs +76 -0
  286. package/package.json +6 -1
  287. package/dist/cli/auth-IACERYQH.js +0 -40
  288. package/dist/cli/chunk-PQUUWFXY.js +0 -95
  289. package/dist/cli/chunk-YBWAG72P.mjs +0 -95
  290. package/dist/cli/chunk-YQDUODZW.js +0 -1710
  291. package/dist/cli/git-JVI36ZFV.js +0 -24
  292. package/dist/cli/search-75X5LTDE.js +0 -30
  293. package/dist/cli/skills-BKJ53JOQ.js +0 -30
  294. package/dist/cli/tools-COWMIEJ6.mjs +0 -45
  295. package/dist/cli/tools-TASOCE7I.js +0 -45
  296. package/dist/cli/update-SJIKVME6.js +0 -32
@@ -0,0 +1,920 @@
1
+ import { createHash } from 'node:crypto';
2
+ import {
3
+ stableStringify,
4
+ normalizeTableNamespace,
5
+ } from '../plays/row-identity';
6
+ import { stringifyPostgresJson } from './postgres-json';
7
+ import { buildScopedWorkReceiptKey } from './work-receipts';
8
+ import {
9
+ RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND,
10
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
11
+ RUNTIME_ARRAY_INPUT_RUN_GUARD_RECEIPT_KIND,
12
+ RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND,
13
+ WORK_RECEIPT_STATUS_CODE,
14
+ } from './work-receipt-storage-contract';
15
+ import type {
16
+ RuntimeArrayInputScope,
17
+ RuntimeArrayInputOccurrence,
18
+ RuntimeArrayInputManifest,
19
+ } from './array-input-store';
20
+
21
+ /**
22
+ * Array sources are immutable internal receipts in the existing customer Neon
23
+ * receipt table. A retained run guard fences terminal retirement, while the
24
+ * existing terminal outbox owns bounded removal of page payloads.
25
+ * Every lookup uses the scoped bytea primary key. Replay hydrates one page at
26
+ * a time; seal verification fetches a fixed bounded group per checkout.
27
+ */
28
+
29
+ export type RuntimeArrayInputQueryClient = {
30
+ query<T extends Record<string, unknown> = Record<string, unknown>>(
31
+ sql: string,
32
+ params?: unknown[],
33
+ ): Promise<{ rows: T[] }>;
34
+ };
35
+
36
+ export type RuntimeArrayInputReceiptPort = {
37
+ orgId: string;
38
+ playName: string;
39
+ runId: string;
40
+ table: string;
41
+ /** A customer execution role already opened a transaction around withClient. */
42
+ outerTransaction: boolean;
43
+ /** Internal native-benchmark candidates; never selected by a runtime request. */
44
+ sealPageBatchSize?: 1 | 4 | 8;
45
+ withClient<T>(
46
+ operation: (client: RuntimeArrayInputQueryClient) => Promise<T>,
47
+ ): Promise<T>;
48
+ };
49
+
50
+ /** Trusted tenant connection supplied by the terminal-outbox cleanup owner. */
51
+ export type RuntimeArrayInputRetirementPort = RuntimeArrayInputReceiptPort;
52
+
53
+ function arrayInputKeyHex(key: string): string {
54
+ return Array.from(new TextEncoder().encode(key), (byte) =>
55
+ byte.toString(16).padStart(2, '0'),
56
+ ).join('');
57
+ }
58
+
59
+ const RUNTIME_ARRAY_INPUT_MAX_PAGE_BYTES = 1024 * 1024;
60
+ const RUNTIME_ARRAY_INPUT_MAX_PAGE_ROWS = 1_000;
61
+ const RUNTIME_ARRAY_INPUT_RETIRE_BATCH_ROWS = 128;
62
+
63
+ export type RuntimeArrayInputBegin = RuntimeArrayInputScope & {
64
+ sourceFingerprint: string;
65
+ sourceRows: number;
66
+ hasSourceIdentities: boolean;
67
+ };
68
+ export type RuntimeArrayInputPutPage = RuntimeArrayInputScope & {
69
+ sourceFingerprint: string;
70
+ ordinal: number;
71
+ offset: number;
72
+ rows: RuntimeArrayInputOccurrence[];
73
+ };
74
+ export type RuntimeArrayInputSeal = Omit<
75
+ RuntimeArrayInputBegin,
76
+ 'hasSourceIdentities'
77
+ > & { pageCount: number };
78
+
79
+ function runtimeArrayInputScope(
80
+ port: RuntimeArrayInputReceiptPort,
81
+ input: RuntimeArrayInputScope,
82
+ ): RuntimeArrayInputScope & { orgId: string } {
83
+ const orgId = port.orgId?.trim();
84
+ const playName = input.playName?.trim();
85
+ const runId = input.runId?.trim();
86
+ const tableNamespace = input.tableNamespace?.trim();
87
+ const mapInvocationId = input.mapInvocationId?.trim();
88
+ if (!orgId || !playName || !runId || !tableNamespace || !mapInvocationId) {
89
+ throw new Error(
90
+ 'Runtime array input requires exact org/play/run/map scope.',
91
+ );
92
+ }
93
+ if (
94
+ (port.playName && port.playName !== playName) ||
95
+ (port.runId && port.runId !== runId)
96
+ ) {
97
+ throw new Error('Runtime array input is outside the execution scope.');
98
+ }
99
+ return { orgId, playName, runId, tableNamespace, mapInvocationId };
100
+ }
101
+
102
+ function runtimeArrayInputKey(
103
+ scope: ReturnType<typeof runtimeArrayInputScope>,
104
+ kind: string,
105
+ ordinal?: number,
106
+ ): string {
107
+ return buildScopedWorkReceiptKey({
108
+ orgId: scope.orgId,
109
+ playName: scope.playName,
110
+ key: JSON.stringify([
111
+ kind,
112
+ scope.runId,
113
+ normalizeTableNamespace(scope.tableNamespace),
114
+ scope.mapInvocationId,
115
+ ...(ordinal === undefined ? [] : [ordinal]),
116
+ ]),
117
+ });
118
+ }
119
+
120
+ function validArrayInputCount(
121
+ value: unknown,
122
+ label: string,
123
+ ): asserts value is number {
124
+ if (!Number.isSafeInteger(value) || (value as number) < 0) {
125
+ throw new Error(
126
+ `Runtime array input ${label} must be a nonnegative safe integer.`,
127
+ );
128
+ }
129
+ }
130
+
131
+ function validArrayInputFingerprint(value: unknown): asserts value is string {
132
+ if (typeof value !== 'string' || !/^[0-9a-f]{64}$/.test(value)) {
133
+ throw new Error(
134
+ 'Runtime array input source fingerprint must be a SHA-256 hex digest.',
135
+ );
136
+ }
137
+ }
138
+
139
+ function runtimeArrayInputKeys(
140
+ scope: ReturnType<typeof runtimeArrayInputScope>,
141
+ ) {
142
+ return {
143
+ begin: runtimeArrayInputKey(scope, RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND),
144
+ seal: runtimeArrayInputKey(scope, RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND),
145
+ };
146
+ }
147
+
148
+ type ArrayInputReceiptRow = {
149
+ status: number;
150
+ run_id: string | null;
151
+ output: Record<string, unknown> | null;
152
+ };
153
+
154
+ function arrayInputRowsHaveSourceIdentities(rows: unknown[]): boolean {
155
+ let hasSourceIdentities = false;
156
+ for (const row of rows) {
157
+ if (!row || typeof row !== 'object' || Array.isArray(row))
158
+ throw new Error('Runtime array input page occurrence is corrupt.');
159
+ const occurrence = row as RuntimeArrayInputOccurrence;
160
+ if (
161
+ !occurrence.data ||
162
+ typeof occurrence.data !== 'object' ||
163
+ Array.isArray(occurrence.data)
164
+ )
165
+ throw new Error('Runtime array input page row data must be an object.');
166
+ const identity = occurrence.sourceIdentity;
167
+ if (identity !== undefined) {
168
+ if (
169
+ !identity ||
170
+ typeof identity.datasetId !== 'string' ||
171
+ !identity.datasetId ||
172
+ !Number.isSafeInteger(identity.rowIndex) ||
173
+ identity.rowIndex < 0
174
+ )
175
+ throw new Error('Runtime array input source identity is corrupt.');
176
+ hasSourceIdentities = true;
177
+ }
178
+ }
179
+ return hasSourceIdentities;
180
+ }
181
+
182
+ async function readArrayInputFact(
183
+ client: RuntimeArrayInputQueryClient,
184
+ session: string,
185
+ key: string,
186
+ lock = false,
187
+ ): Promise<ArrayInputReceiptRow | null> {
188
+ const { rows } = await client.query<ArrayInputReceiptRow>(
189
+ `SELECT status, run_id, output FROM ${session} WHERE k = decode($1, 'hex')${lock ? ' FOR UPDATE' : ''}`,
190
+ [arrayInputKeyHex(key)],
191
+ );
192
+ return rows[0] ?? null;
193
+ }
194
+
195
+ function requireArrayInputFact(
196
+ row: ArrayInputReceiptRow | null,
197
+ runId: string,
198
+ kind: string,
199
+ ): Record<string, unknown> {
200
+ if (
201
+ row?.status !== WORK_RECEIPT_STATUS_CODE.completed ||
202
+ row.run_id !== runId ||
203
+ row.output?.kind !== kind
204
+ ) {
205
+ throw new Error(`Runtime array input ${kind} fact is missing or corrupt.`);
206
+ }
207
+ return row.output;
208
+ }
209
+
210
+ async function putArrayInputFact(
211
+ client: RuntimeArrayInputQueryClient,
212
+ session: string,
213
+ key: string,
214
+ runId: string,
215
+ outputJson: string,
216
+ ): Promise<void> {
217
+ await client.query(
218
+ `INSERT INTO ${session} (k, status, output, run_id)
219
+ VALUES (decode($1, 'hex'), $2::smallint, $3::jsonb, $4)
220
+ ON CONFLICT (k) DO NOTHING`,
221
+ [
222
+ arrayInputKeyHex(key),
223
+ WORK_RECEIPT_STATUS_CODE.completed,
224
+ outputJson,
225
+ runId,
226
+ ],
227
+ );
228
+ }
229
+
230
+ async function withArrayInputTransaction<T>(
231
+ client: RuntimeArrayInputQueryClient,
232
+ outerTransaction: boolean,
233
+ work: () => Promise<T>,
234
+ ): Promise<T> {
235
+ const savepoint = 'runtime_array_input_fact';
236
+ await client.query(outerTransaction ? `SAVEPOINT ${savepoint}` : 'BEGIN');
237
+ try {
238
+ const result = await work();
239
+ await client.query(
240
+ outerTransaction ? `RELEASE SAVEPOINT ${savepoint}` : 'COMMIT',
241
+ );
242
+ return result;
243
+ } catch (error) {
244
+ await client.query(
245
+ outerTransaction ? `ROLLBACK TO SAVEPOINT ${savepoint}` : 'ROLLBACK',
246
+ );
247
+ throw error;
248
+ }
249
+ }
250
+
251
+ function arrayInputRunGuardKey(
252
+ port: RuntimeArrayInputReceiptPort,
253
+ runId: string,
254
+ ): string {
255
+ if (
256
+ !port.orgId?.trim() ||
257
+ !port.playName?.trim() ||
258
+ !runId?.trim() ||
259
+ port.runId !== runId
260
+ ) {
261
+ throw new Error(
262
+ 'Runtime array input retirement requires exact org/play/run scope.',
263
+ );
264
+ }
265
+ return buildScopedWorkReceiptKey({
266
+ orgId: port.orgId,
267
+ playName: port.playName,
268
+ key: JSON.stringify([RUNTIME_ARRAY_INPUT_RUN_GUARD_RECEIPT_KIND, runId]),
269
+ });
270
+ }
271
+
272
+ async function lockedArrayInputRunGuard(
273
+ client: RuntimeArrayInputQueryClient,
274
+ port: RuntimeArrayInputReceiptPort,
275
+ runId: string,
276
+ create: boolean,
277
+ ): Promise<{ key: string; retired: boolean }> {
278
+ const key = arrayInputRunGuardKey(port, runId);
279
+ if (create) {
280
+ await putArrayInputFact(
281
+ client,
282
+ port.table,
283
+ key,
284
+ runId,
285
+ stringifyPostgresJson({
286
+ kind: RUNTIME_ARRAY_INPUT_RUN_GUARD_RECEIPT_KIND,
287
+ retired: false,
288
+ })!,
289
+ );
290
+ }
291
+ const guard = requireArrayInputFact(
292
+ await readArrayInputFact(client, port.table, key, true),
293
+ runId,
294
+ RUNTIME_ARRAY_INPUT_RUN_GUARD_RECEIPT_KIND,
295
+ );
296
+ if (typeof guard.retired !== 'boolean') {
297
+ throw new Error('Runtime array input run guard is corrupt.');
298
+ }
299
+ return { key, retired: guard.retired };
300
+ }
301
+
302
+ async function requireActiveArrayInputRun(
303
+ client: RuntimeArrayInputQueryClient,
304
+ port: RuntimeArrayInputReceiptPort,
305
+ runId: string,
306
+ create = false,
307
+ ): Promise<void> {
308
+ const guard = await lockedArrayInputRunGuard(client, port, runId, create);
309
+ if (guard.retired) {
310
+ throw new Error('Runtime array input run is retired.');
311
+ }
312
+ }
313
+
314
+ /** Read-only scans never acquire the writer/retirement row lock. */
315
+ async function requireActiveArrayInputRunForRead(
316
+ client: RuntimeArrayInputQueryClient,
317
+ port: RuntimeArrayInputReceiptPort,
318
+ runId: string,
319
+ ): Promise<void> {
320
+ const guard = requireArrayInputFact(
321
+ await readArrayInputFact(
322
+ client,
323
+ port.table,
324
+ arrayInputRunGuardKey(port, runId),
325
+ ),
326
+ runId,
327
+ RUNTIME_ARRAY_INPUT_RUN_GUARD_RECEIPT_KIND,
328
+ );
329
+ if (guard.retired !== false) {
330
+ throw new Error('Runtime array input run is retired.');
331
+ }
332
+ }
333
+
334
+ function arrayInputRunFactPrefixHex(
335
+ port: RuntimeArrayInputRetirementPort,
336
+ runId: string,
337
+ kind: string,
338
+ ): string {
339
+ const key = buildScopedWorkReceiptKey({
340
+ orgId: port.orgId,
341
+ playName: port.playName,
342
+ key: `${JSON.stringify([kind, runId]).slice(0, -1)},`,
343
+ });
344
+ return arrayInputKeyHex(key);
345
+ }
346
+
347
+ /**
348
+ * The existing terminal outbox retries this bounded batch before ACK. The
349
+ * retained guard serializes with every writer, then refuses all later writes.
350
+ * PK prefix ranges delete only this org/play/run's internal array facts.
351
+ */
352
+ export async function retireRuntimeArrayInputRun(
353
+ port: RuntimeArrayInputRetirementPort,
354
+ input: { runId: string },
355
+ ): Promise<{ done: boolean; deleted: number }> {
356
+ const guardKey = arrayInputRunGuardKey(port, input.runId);
357
+ const factPrefixes = [
358
+ RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND,
359
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
360
+ RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND,
361
+ ].map((kind) => arrayInputRunFactPrefixHex(port, input.runId, kind));
362
+ return await port.withClient((client) =>
363
+ withArrayInputTransaction(client, port.outerTransaction, async () => {
364
+ const guard = await lockedArrayInputRunGuard(
365
+ client,
366
+ port,
367
+ input.runId,
368
+ true,
369
+ );
370
+ if (!guard.retired) {
371
+ await client.query(
372
+ `UPDATE ${port.table} SET output = $2::jsonb WHERE k = decode($1, 'hex') AND run_id = $3`,
373
+ [
374
+ arrayInputKeyHex(guardKey),
375
+ stringifyPostgresJson({
376
+ kind: RUNTIME_ARRAY_INPUT_RUN_GUARD_RECEIPT_KIND,
377
+ retired: true,
378
+ }),
379
+ input.runId,
380
+ ],
381
+ );
382
+ }
383
+ const { rows } = await client.query<{ k: Uint8Array }>(
384
+ `WITH candidates AS (
385
+ (SELECT k FROM ${port.table}
386
+ WHERE k >= decode($2, 'hex') AND k < (decode($2, 'hex') || decode('ff', 'hex'))
387
+ AND run_id = $1
388
+ ORDER BY k LIMIT ${RUNTIME_ARRAY_INPUT_RETIRE_BATCH_ROWS})
389
+ UNION ALL
390
+ (SELECT k FROM ${port.table}
391
+ WHERE k >= decode($3, 'hex') AND k < (decode($3, 'hex') || decode('ff', 'hex'))
392
+ AND run_id = $1
393
+ ORDER BY k LIMIT ${RUNTIME_ARRAY_INPUT_RETIRE_BATCH_ROWS})
394
+ UNION ALL
395
+ (SELECT k FROM ${port.table}
396
+ WHERE k >= decode($4, 'hex') AND k < (decode($4, 'hex') || decode('ff', 'hex'))
397
+ AND run_id = $1
398
+ ORDER BY k LIMIT ${RUNTIME_ARRAY_INPUT_RETIRE_BATCH_ROWS})
399
+ ), doomed AS (
400
+ SELECT k FROM candidates ORDER BY k LIMIT ${RUNTIME_ARRAY_INPUT_RETIRE_BATCH_ROWS}
401
+ )
402
+ DELETE FROM ${port.table} AS receipt USING doomed
403
+ WHERE receipt.k = doomed.k
404
+ RETURNING receipt.k`,
405
+ [input.runId, ...factPrefixes],
406
+ );
407
+ // A full batch may have drained the last page. A false answer is safe:
408
+ // the durable outbox retries and the guard prevents any re-growth.
409
+ return {
410
+ done: rows.length < RUNTIME_ARRAY_INPUT_RETIRE_BATCH_ROWS,
411
+ deleted: rows.length,
412
+ };
413
+ }),
414
+ );
415
+ }
416
+
417
+ export async function getRuntimeArrayInputManifest(
418
+ port: RuntimeArrayInputReceiptPort,
419
+ input: RuntimeArrayInputScope,
420
+ ): Promise<RuntimeArrayInputManifest> {
421
+ const scope = runtimeArrayInputScope(port, input);
422
+ const keys = runtimeArrayInputKeys(scope);
423
+ return await port.withClient(async (client) => {
424
+ const guard = await readArrayInputFact(
425
+ client,
426
+ port.table,
427
+ arrayInputRunGuardKey(port, scope.runId),
428
+ );
429
+ if (guard) {
430
+ const state = requireArrayInputFact(
431
+ guard,
432
+ scope.runId,
433
+ RUNTIME_ARRAY_INPUT_RUN_GUARD_RECEIPT_KIND,
434
+ );
435
+ if (state.retired !== false) {
436
+ throw new Error('Runtime array input run is retired.');
437
+ }
438
+ }
439
+ const begin = await readArrayInputFact(client, port.table, keys.begin);
440
+ if (!begin) return { state: 'absent' };
441
+ const manifest = requireArrayInputFact(
442
+ begin,
443
+ scope.runId,
444
+ RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND,
445
+ );
446
+ validArrayInputFingerprint(manifest.sourceFingerprint);
447
+ validArrayInputCount(manifest.sourceRows, 'sourceRows');
448
+ if (typeof manifest.hasSourceIdentities !== 'boolean') {
449
+ throw new Error('Runtime array input begin identity flag is corrupt.');
450
+ }
451
+ const seal = await readArrayInputFact(client, port.table, keys.seal);
452
+ if (!seal)
453
+ return {
454
+ state: 'staging',
455
+ sourceFingerprint: manifest.sourceFingerprint,
456
+ sourceRows: manifest.sourceRows,
457
+ hasSourceIdentities: manifest.hasSourceIdentities,
458
+ };
459
+ const sealed = requireArrayInputFact(
460
+ seal,
461
+ scope.runId,
462
+ RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND,
463
+ );
464
+ if (
465
+ sealed.sourceFingerprint !== manifest.sourceFingerprint ||
466
+ sealed.sourceRows !== manifest.sourceRows ||
467
+ sealed.hasSourceIdentities !== manifest.hasSourceIdentities
468
+ ) {
469
+ throw new Error('Runtime array input seal disagrees with begin.');
470
+ }
471
+ validArrayInputCount(sealed.pageCount, 'pageCount');
472
+ return {
473
+ state: 'sealed',
474
+ sourceFingerprint: manifest.sourceFingerprint,
475
+ sourceRows: manifest.sourceRows,
476
+ hasSourceIdentities: manifest.hasSourceIdentities,
477
+ pageCount: sealed.pageCount,
478
+ };
479
+ });
480
+ }
481
+
482
+ export async function beginRuntimeArrayInput(
483
+ port: RuntimeArrayInputReceiptPort,
484
+ input: RuntimeArrayInputBegin,
485
+ ): Promise<void> {
486
+ const scope = runtimeArrayInputScope(port, input);
487
+ validArrayInputFingerprint(input.sourceFingerprint);
488
+ validArrayInputCount(input.sourceRows, 'sourceRows');
489
+ if (typeof input.hasSourceIdentities !== 'boolean') {
490
+ throw new Error('Runtime array input identity flag is required.');
491
+ }
492
+ const key = runtimeArrayInputKeys(scope).begin;
493
+ const expected = {
494
+ kind: RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND,
495
+ sourceFingerprint: input.sourceFingerprint,
496
+ sourceRows: input.sourceRows,
497
+ hasSourceIdentities: input.hasSourceIdentities,
498
+ };
499
+ await port.withClient((client) =>
500
+ withArrayInputTransaction(client, port.outerTransaction, async () => {
501
+ await requireActiveArrayInputRun(client, port, scope.runId, true);
502
+ await putArrayInputFact(
503
+ client,
504
+ port.table,
505
+ key,
506
+ scope.runId,
507
+ stringifyPostgresJson(expected)!,
508
+ );
509
+ const stored = requireArrayInputFact(
510
+ await readArrayInputFact(client, port.table, key),
511
+ scope.runId,
512
+ RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND,
513
+ );
514
+ if (
515
+ stored.sourceFingerprint !== expected.sourceFingerprint ||
516
+ stored.sourceRows !== expected.sourceRows ||
517
+ stored.hasSourceIdentities !== expected.hasSourceIdentities
518
+ ) {
519
+ throw new Error(
520
+ 'Runtime array input source changed after staging began.',
521
+ );
522
+ }
523
+ }),
524
+ );
525
+ }
526
+
527
+ export async function putRuntimeArrayInputPage(
528
+ port: RuntimeArrayInputReceiptPort,
529
+ input: RuntimeArrayInputPutPage,
530
+ ): Promise<void> {
531
+ const scope = runtimeArrayInputScope(port, input);
532
+ validArrayInputFingerprint(input.sourceFingerprint);
533
+ validArrayInputCount(input.ordinal, 'ordinal');
534
+ validArrayInputCount(input.offset, 'offset');
535
+ if (
536
+ !Array.isArray(input.rows) ||
537
+ input.rows.length < 1 ||
538
+ input.rows.length > RUNTIME_ARRAY_INPUT_MAX_PAGE_ROWS
539
+ ) {
540
+ throw new Error('Runtime array input page requires 1-1000 rows.');
541
+ }
542
+ arrayInputRowsHaveSourceIdentities(input.rows);
543
+ // JSON normalization matches the value actually persisted in JSONB. Never
544
+ // stringify an entire source: this object is bounded to one page.
545
+ const rows = JSON.parse(
546
+ stringifyPostgresJson(input.rows)!,
547
+ ) as RuntimeArrayInputOccurrence[];
548
+ arrayInputRowsHaveSourceIdentities(rows);
549
+ const digest = createHash('sha256')
550
+ .update(
551
+ stableStringify({
552
+ sourceFingerprint: input.sourceFingerprint,
553
+ ordinal: input.ordinal,
554
+ offset: input.offset,
555
+ rows,
556
+ }),
557
+ )
558
+ .digest('hex');
559
+ const output = {
560
+ kind: RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
561
+ sourceFingerprint: input.sourceFingerprint,
562
+ ordinal: input.ordinal,
563
+ offset: input.offset,
564
+ rowCount: rows.length,
565
+ rows,
566
+ digest,
567
+ };
568
+ const serialized = stringifyPostgresJson(output)!;
569
+ const requestBytes = Buffer.byteLength(
570
+ JSON.stringify({ action: 'runtime_array_input_put_page', input }),
571
+ 'utf8',
572
+ );
573
+ if (
574
+ Buffer.byteLength(serialized, 'utf8') >
575
+ RUNTIME_ARRAY_INPUT_MAX_PAGE_BYTES ||
576
+ requestBytes > RUNTIME_ARRAY_INPUT_MAX_PAGE_BYTES
577
+ ) {
578
+ throw new Error(
579
+ 'Runtime array input page exceeds its 1 MiB JSON envelope limit.',
580
+ );
581
+ }
582
+ const keys = runtimeArrayInputKeys(scope);
583
+ const pageKey = runtimeArrayInputKey(
584
+ scope,
585
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
586
+ input.ordinal,
587
+ );
588
+ await port.withClient((client) =>
589
+ withArrayInputTransaction(client, port.outerTransaction, async () => {
590
+ await requireActiveArrayInputRun(client, port, scope.runId);
591
+ const begin = requireArrayInputFact(
592
+ await readArrayInputFact(client, port.table, keys.begin, true),
593
+ scope.runId,
594
+ RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND,
595
+ );
596
+ if (
597
+ begin.sourceFingerprint !== input.sourceFingerprint ||
598
+ input.offset + rows.length > Number(begin.sourceRows)
599
+ ) {
600
+ throw new Error(
601
+ 'Runtime array input page disagrees with admitted source.',
602
+ );
603
+ }
604
+ if (await readArrayInputFact(client, port.table, keys.seal)) {
605
+ const existing = requireArrayInputFact(
606
+ await readArrayInputFact(client, port.table, pageKey),
607
+ scope.runId,
608
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
609
+ );
610
+ if (existing.digest !== digest)
611
+ throw new Error('Runtime array input sealed page conflict.');
612
+ return;
613
+ }
614
+ await putArrayInputFact(
615
+ client,
616
+ port.table,
617
+ pageKey,
618
+ scope.runId,
619
+ serialized,
620
+ );
621
+ // The put validates only immutable scalar headers. Leave the payload in
622
+ // PostgreSQL here; seal and readPage still fetch and verify every byte.
623
+ const { rows: stored } = await client.query<ArrayInputReceiptRow>(
624
+ `SELECT page.status, page.run_id,
625
+ jsonb_build_object('kind', header.kind,
626
+ 'sourceFingerprint', header."sourceFingerprint", 'ordinal', header.ordinal,
627
+ 'offset', header."offset", 'rowCount', header."rowCount", 'digest', header.digest) AS output
628
+ FROM ${port.table} AS page
629
+ CROSS JOIN LATERAL jsonb_to_record(page.output) AS header(
630
+ kind jsonb, "sourceFingerprint" jsonb, ordinal jsonb,
631
+ "offset" jsonb, "rowCount" jsonb, digest jsonb)
632
+ WHERE page.k = decode($1, 'hex')`,
633
+ [arrayInputKeyHex(pageKey)],
634
+ );
635
+ const existing = requireArrayInputFact(
636
+ stored[0] ?? null,
637
+ scope.runId,
638
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
639
+ );
640
+ if (
641
+ existing.digest !== digest ||
642
+ existing.offset !== input.offset ||
643
+ existing.rowCount !== rows.length ||
644
+ existing.sourceFingerprint !== input.sourceFingerprint ||
645
+ existing.ordinal !== input.ordinal
646
+ ) {
647
+ throw new Error('Runtime array input immutable page conflict.');
648
+ }
649
+ }),
650
+ );
651
+ }
652
+
653
+ export async function sealRuntimeArrayInput(
654
+ port: RuntimeArrayInputReceiptPort,
655
+ input: RuntimeArrayInputSeal,
656
+ ): Promise<void> {
657
+ const scope = runtimeArrayInputScope(port, input);
658
+ validArrayInputFingerprint(input.sourceFingerprint);
659
+ validArrayInputCount(input.sourceRows, 'sourceRows');
660
+ validArrayInputCount(input.pageCount, 'pageCount');
661
+ if (input.pageCount > input.sourceRows) {
662
+ throw new Error('Runtime array input seal has invalid cardinality.');
663
+ }
664
+ const keys = runtimeArrayInputKeys(scope);
665
+ const readBegin = async (client: RuntimeArrayInputQueryClient) => {
666
+ await requireActiveArrayInputRun(client, port, scope.runId);
667
+ const begin = requireArrayInputFact(
668
+ await readArrayInputFact(client, port.table, keys.begin, true),
669
+ scope.runId,
670
+ RUNTIME_ARRAY_INPUT_BEGIN_RECEIPT_KIND,
671
+ );
672
+ if (
673
+ begin.sourceFingerprint !== input.sourceFingerprint ||
674
+ begin.sourceRows !== input.sourceRows ||
675
+ typeof begin.hasSourceIdentities !== 'boolean'
676
+ ) {
677
+ throw new Error(
678
+ 'Runtime array input seal disagrees with admitted source.',
679
+ );
680
+ }
681
+ return begin.hasSourceIdentities;
682
+ };
683
+ const readCompletedSeal = async (
684
+ client: RuntimeArrayInputQueryClient,
685
+ hasSourceIdentities: boolean,
686
+ ): Promise<boolean> => {
687
+ const fact = await readArrayInputFact(client, port.table, keys.seal);
688
+ if (!fact) return false;
689
+ const seal = requireArrayInputFact(
690
+ fact,
691
+ scope.runId,
692
+ RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND,
693
+ );
694
+ if (
695
+ seal.sourceFingerprint !== input.sourceFingerprint ||
696
+ seal.sourceRows !== input.sourceRows ||
697
+ seal.pageCount !== input.pageCount ||
698
+ seal.hasSourceIdentities !== hasSourceIdentities ||
699
+ typeof seal.digestChain !== 'string' ||
700
+ !/^[a-f0-9]{64}$/.test(seal.digestChain)
701
+ )
702
+ throw new Error('Runtime array input immutable seal conflict.');
703
+ return true;
704
+ };
705
+ const initial = await port.withClient((client) =>
706
+ withArrayInputTransaction(client, port.outerTransaction, async () => {
707
+ const hasSourceIdentities = await readBegin(client);
708
+ return {
709
+ hasSourceIdentities,
710
+ sealed: await readCompletedSeal(client, hasSourceIdentities),
711
+ };
712
+ }),
713
+ );
714
+ // A completed seal is the durable proof of the same immutable pages. Reuse
715
+ // that proof on retries rather than repeating a whole-source verification.
716
+ if (initial.sealed) return;
717
+ const expectedHasSourceIdentities = initial.hasSourceIdentities;
718
+ const batchSize = port.sealPageBatchSize ?? 4;
719
+ if (![1, 4, 8].includes(batchSize))
720
+ throw new Error('Invalid array input seal page batch size.');
721
+ const digestChain = createHash('sha256');
722
+ let nextOffset = 0;
723
+ let hasSourceIdentities = false;
724
+ for (
725
+ let batchStart = 0;
726
+ batchStart < input.pageCount;
727
+ batchStart += batchSize
728
+ ) {
729
+ const ordinals = Array.from(
730
+ { length: Math.min(batchSize, input.pageCount - batchStart) },
731
+ (_, index) => batchStart + index,
732
+ );
733
+ // At most eight already-bounded 1 MiB pages cross this checkout. Release
734
+ // both the role transaction and receipt permit before hashing any payload.
735
+ const batch = await port.withClient(async (client) => {
736
+ await requireActiveArrayInputRunForRead(client, port, scope.runId);
737
+ // A peer may have finished while this attempt yielded between batches.
738
+ // Reuse completed proof; never wait for another in-progress attempt.
739
+ if (await readCompletedSeal(client, expectedHasSourceIdentities))
740
+ return null;
741
+ const params = ordinals.map((ordinal) =>
742
+ arrayInputKeyHex(
743
+ runtimeArrayInputKey(
744
+ scope,
745
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
746
+ ordinal,
747
+ ),
748
+ ),
749
+ );
750
+ const { rows } = await client.query<
751
+ ArrayInputReceiptRow & { scan_ordinal: number }
752
+ >(
753
+ ordinals
754
+ .map(
755
+ (ordinal, index) =>
756
+ `SELECT status, run_id, output, ${ordinal} AS scan_ordinal FROM ${port.table} WHERE k = decode($${index + 1}, 'hex')`,
757
+ )
758
+ .join(' UNION ALL '),
759
+ params,
760
+ );
761
+ return rows;
762
+ });
763
+ if (batch === null) return;
764
+ for (const ordinal of ordinals) {
765
+ const fact = batch.find((row) => row.scan_ordinal === ordinal) ?? null;
766
+ const page = requireArrayInputFact(
767
+ fact,
768
+ scope.runId,
769
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
770
+ );
771
+ if (
772
+ page.sourceFingerprint !== input.sourceFingerprint ||
773
+ page.ordinal !== ordinal ||
774
+ page.offset !== nextOffset ||
775
+ !Number.isSafeInteger(page.rowCount) ||
776
+ Number(page.rowCount) < 1 ||
777
+ Number(page.rowCount) > RUNTIME_ARRAY_INPUT_MAX_PAGE_ROWS ||
778
+ !Array.isArray(page.rows) ||
779
+ page.rows.length !== page.rowCount ||
780
+ typeof page.digest !== 'string'
781
+ ) {
782
+ throw new Error(
783
+ 'Runtime array input seal found a missing or misordered page.',
784
+ );
785
+ }
786
+ const verifiedDigest = createHash('sha256')
787
+ .update(
788
+ stableStringify({
789
+ sourceFingerprint: input.sourceFingerprint,
790
+ ordinal,
791
+ offset: nextOffset,
792
+ rows: page.rows,
793
+ }),
794
+ )
795
+ .digest('hex');
796
+ if (verifiedDigest !== page.digest) {
797
+ throw new Error('Runtime array input page digest mismatch.');
798
+ }
799
+ const pageHasSourceIdentities = arrayInputRowsHaveSourceIdentities(
800
+ page.rows,
801
+ );
802
+ hasSourceIdentities ||= pageHasSourceIdentities;
803
+ digestChain.update(page.digest);
804
+ nextOffset += Number(page.rowCount);
805
+ // Keep other requests runnable between bounded canonicalization turns.
806
+ await new Promise<void>((resolve) => setImmediate(resolve));
807
+ }
808
+ }
809
+
810
+ if (nextOffset !== input.sourceRows) {
811
+ throw new Error('Runtime array input seal row count mismatch.');
812
+ }
813
+ if (hasSourceIdentities !== expectedHasSourceIdentities) {
814
+ throw new Error(
815
+ 'Runtime array input seal source identities disagree with begin.',
816
+ );
817
+ }
818
+ const output = {
819
+ kind: RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND,
820
+ sourceFingerprint: input.sourceFingerprint,
821
+ sourceRows: input.sourceRows,
822
+ hasSourceIdentities: expectedHasSourceIdentities,
823
+ pageCount: input.pageCount,
824
+ digestChain: digestChain.digest('hex'),
825
+ };
826
+ // Pages are write-if-absent and immutable. Retirement first marks the run
827
+ // guard, so this final fence rejects any retirement during the released scan.
828
+ await port.withClient((client) =>
829
+ withArrayInputTransaction(client, port.outerTransaction, async () => {
830
+ if ((await readBegin(client)) !== expectedHasSourceIdentities) {
831
+ throw new Error(
832
+ 'Runtime array input seal disagrees with admitted source.',
833
+ );
834
+ }
835
+ await putArrayInputFact(
836
+ client,
837
+ port.table,
838
+ keys.seal,
839
+ scope.runId,
840
+ stringifyPostgresJson(output)!,
841
+ );
842
+ const stored = requireArrayInputFact(
843
+ await readArrayInputFact(client, port.table, keys.seal),
844
+ scope.runId,
845
+ RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND,
846
+ );
847
+ if (
848
+ stored.sourceFingerprint !== output.sourceFingerprint ||
849
+ stored.sourceRows !== output.sourceRows ||
850
+ stored.hasSourceIdentities !== output.hasSourceIdentities ||
851
+ stored.pageCount !== output.pageCount ||
852
+ stored.digestChain !== output.digestChain
853
+ ) {
854
+ throw new Error('Runtime array input immutable seal conflict.');
855
+ }
856
+ }),
857
+ );
858
+ }
859
+
860
+ export async function readRuntimeArrayInputPage(
861
+ port: RuntimeArrayInputReceiptPort,
862
+ input: RuntimeArrayInputScope & { ordinal: number },
863
+ ): Promise<{ offset: number; rows: RuntimeArrayInputOccurrence[] }> {
864
+ const scope = runtimeArrayInputScope(port, input);
865
+ validArrayInputCount(input.ordinal, 'ordinal');
866
+ const keys = runtimeArrayInputKeys(scope);
867
+ return await port.withClient(async (client) => {
868
+ await requireActiveArrayInputRunForRead(client, port, scope.runId);
869
+ const seal = requireArrayInputFact(
870
+ await readArrayInputFact(client, port.table, keys.seal),
871
+ scope.runId,
872
+ RUNTIME_ARRAY_INPUT_SEAL_RECEIPT_KIND,
873
+ );
874
+ validArrayInputFingerprint(seal.sourceFingerprint);
875
+ validArrayInputCount(seal.pageCount, 'pageCount');
876
+ if (input.ordinal >= seal.pageCount) {
877
+ throw new Error(
878
+ 'Runtime array input page ordinal exceeds sealed manifest.',
879
+ );
880
+ }
881
+ const page = requireArrayInputFact(
882
+ await readArrayInputFact(
883
+ client,
884
+ port.table,
885
+ runtimeArrayInputKey(
886
+ scope,
887
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
888
+ input.ordinal,
889
+ ),
890
+ ),
891
+ scope.runId,
892
+ RUNTIME_ARRAY_INPUT_PAGE_RECEIPT_KIND,
893
+ );
894
+ if (
895
+ !Array.isArray(page.rows) ||
896
+ !Number.isSafeInteger(page.offset) ||
897
+ page.ordinal !== input.ordinal ||
898
+ page.sourceFingerprint !== seal.sourceFingerprint ||
899
+ page.rowCount !== page.rows.length
900
+ ) {
901
+ throw new Error('Runtime array input sealed page is corrupt.');
902
+ }
903
+ const digest = createHash('sha256')
904
+ .update(
905
+ stableStringify({
906
+ sourceFingerprint: seal.sourceFingerprint,
907
+ ordinal: input.ordinal,
908
+ offset: page.offset,
909
+ rows: page.rows,
910
+ }),
911
+ )
912
+ .digest('hex');
913
+ if (page.digest !== digest)
914
+ throw new Error('Runtime array input sealed page digest mismatch.');
915
+ return {
916
+ offset: page.offset as number,
917
+ rows: page.rows as RuntimeArrayInputOccurrence[],
918
+ };
919
+ });
920
+ }