deepline 0.3.461 → 0.3.463

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 (297) 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/billing/tamradar.ts +17 -17
  17. package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +0 -307
  18. package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
  19. package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +3 -2
  20. package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
  21. package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +34 -0
  22. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +61 -0
  23. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +122 -2
  24. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +11 -1
  25. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-failure-codes.ts +24 -0
  26. package/dist/bundling-sources/shared_libs/observability/dlq.ts +32 -0
  27. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +57 -3
  28. package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +1 -0
  29. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +66 -1
  30. package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +36 -7
  31. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +250 -11
  32. package/dist/bundling-sources/shared_libs/play-runtime/array-input-store.ts +319 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +991 -359
  34. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +17 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +13 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +110 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +155 -6
  38. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +110 -6
  39. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -13
  40. package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +14 -1
  41. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +57 -1
  42. package/dist/bundling-sources/shared_libs/play-runtime/free-company-lookup-batching.ts +218 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +42 -5
  44. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-budget-state-backend.ts +6 -1
  45. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +92 -31
  46. package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +69 -14
  47. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +93 -23
  48. package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +15 -4
  49. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +22 -18
  50. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +5 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +2 -0
  52. package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +190 -14
  53. package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +131 -0
  54. package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +77 -2
  55. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +271 -2
  56. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +51 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +2 -0
  58. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +27 -1
  59. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
  60. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
  61. package/dist/bundling-sources/shared_libs/play-runtime/provider-text-for-log.ts +63 -0
  62. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +19 -0
  63. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +112 -16
  64. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +104 -2
  65. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +265 -151
  66. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +17 -0
  67. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +35 -14
  68. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +12 -1
  69. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +4 -0
  70. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-labels.ts +36 -0
  71. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +136 -70
  72. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +237 -36
  73. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +148 -4
  74. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +6 -0
  75. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +285 -32
  76. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +251 -56
  77. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +29 -4
  78. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/sandbox-create-outcome.ts +27 -0
  79. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +22 -1
  80. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1397 -382
  81. package/dist/bundling-sources/shared_libs/play-runtime/runtime-array-input-receipts.ts +920 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +16 -0
  83. package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +38 -0
  84. package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +6 -0
  85. package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -1
  86. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +30 -0
  87. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +14 -3
  88. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +31 -4
  89. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -0
  90. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +20 -7
  91. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +12 -0
  92. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/index.ts +9 -0
  93. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +10 -0
  94. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +4 -0
  95. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1496 -320
  96. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +31 -1
  97. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1389 -129
  98. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +36 -0
  99. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
  100. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +162 -23
  101. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +499 -115
  102. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +377 -9
  103. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +117 -8
  104. package/dist/bundling-sources/shared_libs/play-runtime/secret-resolution-retry-policy.ts +25 -0
  105. package/dist/bundling-sources/shared_libs/play-runtime/terminal-runtime-performance.ts +391 -0
  106. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +40 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +6 -0
  108. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/mapped-calls.ts +171 -0
  109. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +16 -1
  110. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +38 -12
  111. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +33 -9
  112. package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +28 -0
  113. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +55 -5
  114. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +41 -1
  115. package/dist/bundling-sources/shared_libs/plays/contracts.ts +4 -0
  116. package/dist/bundling-sources/shared_libs/plays/dataset.ts +9 -3
  117. package/dist/bundling-sources/shared_libs/plays/deploy/manifest-contract.ts +2 -0
  118. package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +3 -2
  119. package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +2 -2
  120. package/dist/bundling-sources/shared_libs/plays/run-output-summary.ts +66 -0
  121. package/dist/bundling-sources/shared_libs/plays/script-entry.ts +1 -1
  122. package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +43 -1
  123. package/dist/bundling-sources/shared_libs/product-notifications/content.ts +9 -0
  124. package/dist/bundling-sources/shared_libs/product-notifications/email.ts +91 -13
  125. package/dist/bundling-sources/shared_libs/product-notifications/events.ts +3 -0
  126. package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +41 -24
  127. package/dist/bundling-sources/shared_libs/security/attested-client-ip.ts +91 -0
  128. package/dist/bundling-sources/shared_libs/security/internal-actor.ts +0 -11
  129. package/dist/cli/{auth-6HJXNWUG.mjs → auth-LZLBR4C3.mjs} +5 -4
  130. package/dist/cli/auth-XPGKBJKB.js +41 -0
  131. package/dist/cli/{billing-6P5HO6QG.js → billing-6TJPNJQD.js} +152 -78
  132. package/dist/cli/{billing-MJ42N7YF.mjs → billing-OTOP5RE4.mjs} +84 -10
  133. package/dist/cli/{chunk-FCAZQ7WV.js → chunk-2NISBXMN.js} +52 -50
  134. package/dist/cli/{chunk-PNATXKLP.js → chunk-2ZIRCBYG.js} +6 -6
  135. package/dist/cli/{chunk-5FDKJQZE.js → chunk-3BOIOCNX.js} +1 -1
  136. package/dist/cli/chunk-3BVLLJ3H.mjs +1038 -0
  137. package/dist/cli/{chunk-FJZILBL7.mjs → chunk-3U5EAP6E.mjs} +5 -5
  138. package/dist/cli/{describe-FRAVCY5F.mjs → chunk-4YZKBBLZ.mjs} +19 -36
  139. package/dist/cli/{chunk-QWRHGGUH.js → chunk-5DRNNC72.js} +20 -2
  140. package/dist/cli/{chunk-Z2GUFYT6.js → chunk-5LEAXRHV.js} +11 -11
  141. package/dist/cli/{chunk-5MDIZX7M.js → chunk-5LHXOIPT.js} +8 -6
  142. package/dist/cli/{chunk-NMJ4D2WO.js → chunk-6PMCRYDA.js} +216 -91
  143. package/dist/cli/{chunk-EBU7LQ64.js → chunk-6V7KVRR5.js} +3 -3
  144. package/dist/cli/{chunk-MGXEUZHL.mjs → chunk-7D6X7IXW.mjs} +7 -5
  145. package/dist/cli/{chunk-SAZFZQRI.js → chunk-7FCYPAPP.js} +2 -2
  146. package/dist/cli/{chunk-ACCR7POB.js → chunk-7XYDDCQ2.js} +27 -27
  147. package/dist/cli/{chunk-5IYOUBFZ.js → chunk-ALZBANZI.js} +28 -54
  148. package/dist/cli/{chunk-3DNKFH2G.mjs → chunk-BAPTQDLF.mjs} +19 -1
  149. package/dist/cli/chunk-BGNWI3KH.js +827 -0
  150. package/dist/cli/{chunk-V7REJRDZ.mjs → chunk-C25QE4CH.mjs} +1 -1
  151. package/dist/cli/{chunk-FGMX4HUZ.js → chunk-CBZP6J3V.js} +29 -27
  152. package/dist/cli/{chunk-QEYHTIV4.mjs → chunk-CTQ56DXP.mjs} +10 -1
  153. package/dist/cli/{chunk-IHHLTHE7.mjs → chunk-CVQ7N5CV.mjs} +267 -38
  154. package/dist/cli/{chunk-7DH2FD7Y.mjs → chunk-D464JW3N.mjs} +5 -85
  155. package/dist/cli/{chunk-MEAIOXJL.mjs → chunk-DHXCBITQ.mjs} +7 -5
  156. package/dist/cli/chunk-F2RHUPVH.mjs +827 -0
  157. package/dist/cli/chunk-F6QV42MC.mjs +91 -0
  158. package/dist/cli/{chunk-OZBWRICM.js → chunk-FK2HNDCN.js} +2 -2
  159. package/dist/cli/{chunk-BGY2PLP7.mjs → chunk-GUT7CLOL.mjs} +23 -49
  160. package/dist/cli/{chunk-RY4IVOU3.mjs → chunk-I624J4H5.mjs} +16 -806
  161. package/dist/cli/{chunk-Z2XUZC34.js → chunk-IAYSWZDJ.js} +188 -76
  162. package/dist/cli/{chunk-FGLKOWSC.mjs → chunk-IKWRUNAP.mjs} +1 -1
  163. package/dist/cli/{chunk-KCCOQ5G5.js → chunk-JVDKZJUH.js} +511 -282
  164. package/dist/cli/{chunk-HDFRJ4IT.mjs → chunk-JVHOS3K3.mjs} +177 -65
  165. package/dist/cli/chunk-LYFKBLJI.mjs +1039 -0
  166. package/dist/cli/{chunk-SLEUWLJE.mjs → chunk-MSY22NQW.mjs} +5 -5
  167. package/dist/cli/{chunk-5FY72YOV.js → chunk-NAPTMYTY.js} +8 -8
  168. package/dist/cli/{chunk-O6QOMHCH.js → chunk-NDHJR2WZ.js} +37 -35
  169. package/dist/cli/{chunk-KXMNM4AQ.js → chunk-NMU3VR5U.js} +4 -5
  170. package/dist/cli/chunk-NTLI6P6Y.mjs +19 -0
  171. package/dist/cli/{chunk-RFONC4WJ.mjs → chunk-O3BJYD6D.mjs} +3 -3
  172. package/dist/cli/{describe-2WQY7ZCY.js → chunk-PVY4DPPF.js} +27 -44
  173. package/dist/cli/{chunk-WIYWSYDS.mjs → chunk-Q2EIZKVX.mjs} +3 -3
  174. package/dist/cli/{chunk-VZBCEA5S.mjs → chunk-RD6IQ2JY.mjs} +223 -92
  175. package/dist/cli/chunk-RGOUCIIZ.js +1039 -0
  176. package/dist/cli/{chunk-EIMG75BT.mjs → chunk-S3A4IXBQ.mjs} +4 -5
  177. package/dist/cli/{chunk-QIW7TVV6.mjs → chunk-S4XQCFES.mjs} +14 -12
  178. package/dist/cli/chunk-SKU6ECIY.js +19 -0
  179. package/dist/cli/{chunk-CRYOUPEB.js → chunk-TIRBDQ3W.js} +16 -16
  180. package/dist/cli/{chunk-G7L27KZB.mjs → chunk-TKAQR3IB.mjs} +31 -21
  181. package/dist/cli/{chunk-MDJPEGVN.js → chunk-UC4SFYNU.js} +392 -261
  182. package/dist/cli/{chunk-3BMLICF7.mjs → chunk-UIURR26V.mjs} +13 -8
  183. package/dist/cli/{chunk-TNMBPMMC.js → chunk-UROQDCVW.js} +13 -4
  184. package/dist/cli/{chunk-R64BGGRQ.mjs → chunk-VDGTTH7K.mjs} +2 -2
  185. package/dist/cli/chunk-VLEVVDWG.js +91 -0
  186. package/dist/cli/{chunk-R2GLGLDR.mjs → chunk-VPHN2HAL.mjs} +216 -91
  187. package/dist/cli/chunk-VY2GBNTX.js +1038 -0
  188. package/dist/cli/{chunk-CFUTOWE4.js → chunk-WG3KGAII.js} +8 -88
  189. package/dist/cli/{chunk-QAJAJPKK.mjs → chunk-WUMIYOXQ.mjs} +4 -2
  190. package/dist/cli/{chunk-SCIR5JXW.js → chunk-WUZS2HK6.js} +56 -51
  191. package/dist/cli/{chunk-T3MVIPHG.mjs → chunk-XDWS2JJT.mjs} +1 -1
  192. package/dist/cli/{chunk-KGQNIA37.js → chunk-XQCTG5OO.js} +44 -34
  193. package/dist/cli/{chunk-KVJ5VHW5.mjs → chunk-XW2JIYG7.mjs} +2 -2
  194. package/dist/cli/chunk-YGGIZ3VT.js +920 -0
  195. package/dist/cli/command-docs.d.mts +5 -0
  196. package/dist/cli/command-docs.d.ts +5 -0
  197. package/dist/cli/command-docs.js +2 -2
  198. package/dist/cli/command-docs.mjs +1 -1
  199. package/dist/cli/{csv-NX7NO3O6.js → csv-EH5QWR4O.js} +13 -12
  200. package/dist/cli/{csv-DQ6GW5B5.mjs → csv-OK45Z5XQ.mjs} +4 -3
  201. package/dist/cli/{db-R72DFMP6.js → db-3ESJKETS.js} +30 -27
  202. package/dist/cli/{db-2YP33M4K.mjs → db-6Z5E4HKN.mjs} +10 -7
  203. package/dist/cli/describe-PNDQB7YS.mjs +48 -0
  204. package/dist/cli/describe-QUF7VTTR.js +48 -0
  205. package/dist/cli/describe-core.d.mts +153 -5
  206. package/dist/cli/describe-core.d.ts +153 -5
  207. package/dist/cli/describe-core.js +9 -5
  208. package/dist/cli/describe-core.mjs +10 -6
  209. package/dist/cli/{executions-WFBU7L2Q.mjs → executions-2NTWQFEG.mjs} +7 -5
  210. package/dist/cli/{executions-ZLHD4QIT.js → executions-KUOBRX5V.js} +9 -7
  211. package/dist/cli/{feedback-CN3HJFVF.mjs → feedback-7RPRMSGY.mjs} +6 -5
  212. package/dist/cli/{feedback-NDV6TPHG.js → feedback-UPHAZJ4C.js} +10 -9
  213. package/dist/cli/getting-started.d.mts +6 -6
  214. package/dist/cli/getting-started.d.ts +6 -6
  215. package/dist/cli/getting-started.js +2 -2
  216. package/dist/cli/getting-started.mjs +1 -1
  217. package/dist/cli/{git-QAD6E3HW.mjs → git-SCYP6WSZ.mjs} +5 -4
  218. package/dist/cli/git-UH653WHV.js +25 -0
  219. package/dist/cli/index.js +152 -142
  220. package/dist/cli/index.mjs +56 -46
  221. package/dist/cli/{legacy-noops-KVC5QJ74.js → legacy-noops-7XMFCVRG.js} +8 -7
  222. package/dist/cli/{legacy-noops-TPTKNBI2.mjs → legacy-noops-A4KYAGI6.mjs} +5 -4
  223. package/dist/cli/{monitors-SV57JFLO.mjs → monitors-FLC5J7RI.mjs} +19 -6
  224. package/dist/cli/{monitors-KCROV6PJ.js → monitors-NZV6IX5H.js} +103 -90
  225. package/dist/cli/{org-NJYX5743.js → org-IZ7UP3XF.js} +70 -67
  226. package/dist/cli/{org-KX6QIR7A.mjs → org-LUETJ7Z5.mjs} +9 -6
  227. package/dist/cli/pages-22ML3O7O.js +252 -0
  228. package/dist/cli/pages-EUX5EAGF.mjs +252 -0
  229. package/dist/cli/{play-IQQ57L7Z.mjs → play-CDHPAKKM.mjs} +512 -1508
  230. package/dist/cli/{play-32L7EQN4.js → play-USJBQADG.js} +1090 -2086
  231. package/dist/cli/{providers-4WEC2EQN.mjs → providers-CCXZ3SQF.mjs} +7 -5
  232. package/dist/cli/{providers-ZQV6QLVQ.js → providers-WFEUNPGC.js} +10 -8
  233. package/dist/cli/{quickstart-HKUSFADF.js → quickstart-O4JSUORZ.js} +13 -12
  234. package/dist/cli/{quickstart-RQ76RIUE.mjs → quickstart-ZUULI635.mjs} +5 -4
  235. package/dist/cli/run-ISDJYJMU.js +443 -0
  236. package/dist/cli/run-QJ4NX5F5.mjs +443 -0
  237. package/dist/cli/{search-ZRAVFBZC.mjs → search-IX3XKZJ3.mjs} +8 -6
  238. package/dist/cli/search-TIFNLRPM.js +32 -0
  239. package/dist/cli/{secrets-CMJOVNVH.mjs → secrets-7VUDXTUZ.mjs} +7 -5
  240. package/dist/cli/{secrets-J3G5Y43U.js → secrets-ELQSNCTR.js} +16 -14
  241. package/dist/cli/{sessions-WY7VN4AE.js → sessions-A3FG3AZX.js} +6 -5
  242. package/dist/cli/{sessions-MDQYY5CB.mjs → sessions-VOIQ62GB.mjs} +5 -4
  243. package/dist/cli/{settings-4RWZPCT5.mjs → settings-S6N6EFBG.mjs} +14 -11
  244. package/dist/cli/{settings-HTNTFKCE.js → settings-ZTXQEMZI.js} +80 -77
  245. package/dist/cli/{setup-P3GYYZWG.mjs → setup-AYPIK4JE.mjs} +12 -10
  246. package/dist/cli/{setup-QGCAP62X.js → setup-Y3WOIFLS.js} +53 -51
  247. package/dist/cli/{skills-7NAE4ICL.mjs → skills-5SF5QWNI.mjs} +7 -6
  248. package/dist/cli/skills-MWFRMG3H.js +31 -0
  249. package/dist/cli/tools-3XNZ4J64.mjs +55 -0
  250. package/dist/cli/tools-XEC4OD3R.js +55 -0
  251. package/dist/cli/{update-GODLRKNB.mjs → update-3U4OVX5R.mjs} +9 -8
  252. package/dist/cli/update-DWYEYTZE.js +33 -0
  253. package/dist/cli/{workflow-4BXOUVEO.mjs → workflow-2M5JP7SA.mjs} +10 -8
  254. package/dist/cli/{workflow-AO3A6LXN.js → workflow-RM7H7555.js} +20 -18
  255. package/dist/client-DS2IWYZF.d.ts +10 -0
  256. package/dist/client-DTwnz_AW.d.mts +10 -0
  257. package/dist/{client-CYqG23K1.d.ts → client-core-B_6HAIBy.d.ts} +385 -12
  258. package/dist/{client-BbU5_j7n.d.mts → client-core-DzBSlY1U.d.mts} +385 -12
  259. package/dist/{compiler-manifest-CWz_sNOQ.d.ts → compiler-manifest-Dcyd3-Zd.d.mts} +43 -1
  260. package/dist/{compiler-manifest-CWz_sNOQ.d.mts → compiler-manifest-Dcyd3-Zd.d.ts} +43 -1
  261. package/dist/errors-d-sTrZhe.d.mts +142 -0
  262. package/dist/errors-yQwfgrcX.d.ts +142 -0
  263. package/dist/{index-BF2JB_Ug.d.mts → index-C6oXchjN.d.mts} +1 -1
  264. package/dist/{index-4NPXDzlD.d.ts → index-P56zy_z5.d.ts} +1 -1
  265. package/dist/index.d.mts +11 -147
  266. package/dist/index.d.ts +11 -147
  267. package/dist/index.js +16 -12
  268. package/dist/index.mjs +15 -11
  269. package/dist/install-integrity.json +141 -104
  270. package/dist/plays/bundle-play-file.d.mts +3 -3
  271. package/dist/plays/bundle-play-file.d.ts +3 -3
  272. package/dist/plays/bundle-play-file.mjs +2 -1
  273. package/dist/plays/play-description.d.mts +2 -2
  274. package/dist/plays/play-description.d.ts +2 -2
  275. package/dist/plays/play-description.js +2 -2
  276. package/dist/plays/play-description.mjs +1 -1
  277. package/dist/plays/run-request.d.mts +2 -2
  278. package/dist/plays/run-request.d.ts +2 -2
  279. package/dist/release.d.mts +1 -1
  280. package/dist/release.d.ts +1 -1
  281. package/dist/release.js +2 -2
  282. package/dist/release.mjs +1 -1
  283. package/dist/server.d.mts +17 -0
  284. package/dist/server.d.ts +17 -0
  285. package/dist/server.js +76 -0
  286. package/dist/server.mjs +76 -0
  287. package/package.json +6 -1
  288. package/dist/cli/auth-IACERYQH.js +0 -40
  289. package/dist/cli/chunk-PQUUWFXY.js +0 -95
  290. package/dist/cli/chunk-YBWAG72P.mjs +0 -95
  291. package/dist/cli/chunk-YQDUODZW.js +0 -1710
  292. package/dist/cli/git-JVI36ZFV.js +0 -24
  293. package/dist/cli/search-75X5LTDE.js +0 -30
  294. package/dist/cli/skills-BKJ53JOQ.js +0 -30
  295. package/dist/cli/tools-COWMIEJ6.mjs +0 -45
  296. package/dist/cli/tools-TASOCE7I.js +0 -45
  297. package/dist/cli/update-SJIKVME6.js +0 -32
@@ -91,7 +91,7 @@ const RUNTIME_EVENT_LOG_POSITION_EXPRESSION = `jsonb_set(
91
91
  // Migration readiness tracks this projection body independently of scheduler
92
92
  // wire and schema versions. Bump when a changed trigger must be reinstalled.
93
93
  export const RUNTIME_EVENT_SEARCH_OUTBOX_PROJECTION_MARKER =
94
- 'runtime-event-search-direct-receipts-bounded-terminal-log-facts';
94
+ 'runtime-event-search-legacy-position-resolver-pools';
95
95
  /** Trusted trigger-authored state; absent on already-projected legacy rows. */
96
96
  export const RUNTIME_EVENT_DEFERRED_PROJECTION_FIELD =
97
97
  '_runtimeSearchProjectionPending';
@@ -1516,6 +1516,12 @@ export async function hasRuntimeEventReaderGrant(
1516
1516
  );
1517
1517
  }
1518
1518
  const scope = requiredScope(runtimeScope);
1519
+ // Reject explicit role edges in both directions, including NOINHERIT,
1520
+ // without repeatedly traversing every unrelated role's membership graph.
1521
+ // Keep membership-aware checks for the three exact owners: implicit
1522
+ // pg_database_owner membership has no pg_auth_members edge.
1523
+ // User-created namespaces have indexed pg_depend references; enumerate
1524
+ // their relations without scanning every other Preview namespace's catalog.
1519
1525
  const result = await client.query<{ ready: boolean }>(
1520
1526
  `SELECT coalesce(roles.rolcanlogin AND NOT roles.rolsuper AND NOT roles.rolbypassrls
1521
1527
  AND has_schema_privilege(roles.oid, 'runtime_observability', 'USAGE')
@@ -1544,36 +1550,35 @@ export async function hasRuntimeEventReaderGrant(
1544
1550
  AND NOT has_table_privilege(roles.oid, 'runtime_observability.run_log_cursors', 'TRUNCATE')
1545
1551
  AND NOT has_table_privilege(roles.oid, 'runtime_observability.run_log_cursors', 'REFERENCES')
1546
1552
  AND NOT has_table_privilege(roles.oid, 'runtime_observability.run_log_cursors', 'TRIGGER')
1547
- AND NOT has_schema_privilege(roles.oid, $2, 'USAGE')
1548
- AND NOT has_schema_privilege(roles.oid, $2, 'CREATE')
1553
+ AND NOT has_schema_privilege(roles.oid, runtime_schema.oid, 'USAGE')
1554
+ AND NOT has_schema_privilege(roles.oid, runtime_schema.oid, 'CREATE')
1549
1555
  AND NOT EXISTS (SELECT 1 FROM pg_auth_members AS membership
1550
- WHERE pg_has_role(roles.oid, membership.roleid, 'MEMBER'))
1551
- AND NOT EXISTS (SELECT 1 FROM pg_class AS events
1552
- JOIN pg_namespace AS event_schema ON event_schema.oid = events.relnamespace
1553
- WHERE event_schema.nspname = 'runtime_observability'
1554
- AND events.relname = 'events'
1555
- AND pg_has_role(roles.oid, events.relowner, 'USAGE'))
1556
- AND NOT EXISTS (SELECT 1 FROM pg_class AS log_cursors
1557
- JOIN pg_namespace AS event_schema ON event_schema.oid = log_cursors.relnamespace
1558
- WHERE event_schema.nspname = 'runtime_observability'
1559
- AND log_cursors.relname = 'run_log_cursors'
1560
- AND pg_has_role(roles.oid, log_cursors.relowner, 'USAGE'))
1561
- AND (SELECT relrowsecurity FROM pg_class
1562
- WHERE oid = 'runtime_observability.events'::regclass)
1563
- AND (SELECT relrowsecurity FROM pg_class
1564
- WHERE oid = 'runtime_observability.run_log_cursors'::regclass)
1565
- AND NOT EXISTS (SELECT 1 FROM pg_class AS scoped_relation
1566
- JOIN pg_namespace AS scoped_schema ON scoped_schema.oid = scoped_relation.relnamespace
1567
- WHERE scoped_schema.nspname = $2
1556
+ WHERE membership.member = roles.oid OR membership.roleid = roles.oid)
1557
+ AND NOT pg_has_role(roles.oid, events.relowner, 'USAGE')
1558
+ AND NOT pg_has_role(roles.oid, log_cursors.relowner, 'USAGE')
1559
+ AND events.relrowsecurity
1560
+ AND log_cursors.relrowsecurity
1561
+ AND NOT EXISTS (SELECT 1 FROM pg_depend AS namespace_dependency
1562
+ JOIN pg_class AS scoped_relation ON scoped_relation.oid = namespace_dependency.objid
1563
+ WHERE namespace_dependency.refclassid = 'pg_namespace'::regclass
1564
+ AND namespace_dependency.refobjid = runtime_schema.oid
1565
+ AND namespace_dependency.classid = 'pg_class'::regclass
1566
+ AND namespace_dependency.objsubid = 0
1567
+ AND namespace_dependency.refobjsubid = 0
1568
+ AND namespace_dependency.deptype = 'n'
1569
+ AND scoped_relation.relnamespace = runtime_schema.oid
1568
1570
  AND scoped_relation.relkind IN ('r', 'p', 'v', 'm', 'f')
1569
1571
  AND (has_table_privilege(roles.oid, scoped_relation.oid, 'SELECT')
1570
1572
  OR has_any_column_privilege(roles.oid, scoped_relation.oid, 'SELECT')))
1571
- AND NOT pg_has_role(roles.oid,
1572
- (SELECT receipt_function.proowner FROM pg_proc AS receipt_function
1573
- WHERE receipt_function.oid = 'runtime_observability.fetch_receipt(text,text,text,uuid)'::regprocedure),
1574
- 'USAGE')
1573
+ AND NOT pg_has_role(roles.oid, receipt_function.proowner, 'USAGE')
1575
1574
  AND has_function_privilege(roles.oid, 'runtime_observability.fetch_receipt(text,text,text,uuid)', 'EXECUTE'), false) AS ready
1576
- FROM pg_roles AS roles WHERE roles.rolname = $1`,
1575
+ FROM pg_roles AS roles
1576
+ JOIN pg_namespace AS runtime_schema ON runtime_schema.nspname = $2
1577
+ AND runtime_schema.oid >= 16384::oid
1578
+ JOIN pg_class AS events ON events.oid = 'runtime_observability.events'::regclass
1579
+ JOIN pg_class AS log_cursors ON log_cursors.oid = 'runtime_observability.run_log_cursors'::regclass
1580
+ JOIN pg_proc AS receipt_function ON receipt_function.oid = 'runtime_observability.fetch_receipt(text,text,text,uuid)'::regprocedure
1581
+ WHERE roles.rolname = $1`,
1577
1582
  [readerRole, scope],
1578
1583
  );
1579
1584
  return result.rows[0]?.ready === true;
@@ -2372,6 +2377,369 @@ export async function attachRuntimeEventSearchTriggers(
2372
2377
  ${schema}.project_origin_log_batch_with_targets(${schema}.outbox,jsonb,text,text,boolean,boolean,timestamptz,jsonb,boolean)
2373
2378
  FROM PUBLIC;
2374
2379
  END; $install_fresh_log_sequences$`);
2380
+ // The positional path is used before origin identities are enabled. Keep
2381
+ // its physical lookup contract local, like fresh sequence assignment: a
2382
+ // generic plan warmed on an empty journal must not scan unrelated runs.
2383
+ // VOLATILE preserves visibility of aliases written earlier in this batch.
2384
+ await client.query(`DO $install_legacy_log_access$ BEGIN
2385
+ CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_identity(probe_org text, probe_id text)
2386
+ RETURNS TABLE(runtime_scope text, org_id text, event_id text, run_id text, kind text, source_digest text, search_doc jsonb)
2387
+ LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
2388
+ SET enable_seqscan = off SET enable_indexscan = on AS $function$
2389
+ BEGIN RETURN QUERY
2390
+ SELECT candidate.* FROM (
2391
+ SELECT event.runtime_scope, event.org_id, event.event_id, event.run_id,
2392
+ event.kind, event.source_digest, event.search_doc
2393
+ FROM runtime_observability.events AS event
2394
+ WHERE (event.runtime_scope, event.org_id, event.event_id)
2395
+ >= (${quoteLiteral(scope)}, probe_org, probe_id)
2396
+ ORDER BY event.runtime_scope, event.org_id, event.event_id
2397
+ LIMIT 1
2398
+ ) AS candidate
2399
+ WHERE candidate.runtime_scope = ${quoteLiteral(scope)}
2400
+ AND candidate.org_id = probe_org AND candidate.event_id = probe_id;
2401
+ END
2402
+ $function$;
2403
+ REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_identity(text,text) FROM PUBLIC;
2404
+ CREATE OR REPLACE FUNCTION ${schema}.update_legacy_log_alias(probe_org text, probe_id text, probe_doc jsonb, probe_run text)
2405
+ RETURNS TABLE(updated_tid tid)
2406
+ LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
2407
+ SET enable_seqscan = off SET enable_indexscan = on SET enable_tidscan = on AS $function$
2408
+ DECLARE alias_identity record;
2409
+ alias_target NO SCROLL CURSOR FOR
2410
+ WITH alias_candidate AS MATERIALIZED (
2411
+ SELECT event.ctid AS target_tid
2412
+ FROM runtime_observability.events AS event
2413
+ WHERE (event.runtime_scope, event.org_id, event.event_id)
2414
+ >= (${quoteLiteral(scope)}, probe_org, probe_id)
2415
+ ORDER BY event.runtime_scope, event.org_id, event.event_id
2416
+ LIMIT 1
2417
+ )
2418
+ SELECT event.runtime_scope, event.org_id, event.run_id, event.event_id
2419
+ FROM alias_candidate AS candidate
2420
+ JOIN runtime_observability.events AS event ON event.ctid = candidate.target_tid
2421
+ WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = probe_org
2422
+ AND event.run_id = probe_run AND event.event_id = probe_id
2423
+ FOR UPDATE OF event;
2424
+ BEGIN
2425
+ -- Resolve and lock one exact identity in the same cursor statement.
2426
+ -- Filtering before FOR UPDATE must never lock a neighboring run on EOF.
2427
+ OPEN alias_target;
2428
+ BEGIN
2429
+ FETCH alias_target INTO alias_identity;
2430
+ IF NOT FOUND THEN
2431
+ RAISE EXCEPTION 'Legacy log alias target changed before update' USING ERRCODE = '40001';
2432
+ END IF;
2433
+ IF alias_identity.runtime_scope IS DISTINCT FROM ${quoteLiteral(scope)}
2434
+ OR alias_identity.org_id IS DISTINCT FROM probe_org
2435
+ OR alias_identity.run_id IS DISTINCT FROM probe_run
2436
+ OR alias_identity.event_id IS DISTINCT FROM probe_id THEN
2437
+ RAISE EXCEPTION 'Legacy log alias target changed before update' USING ERRCODE = '40001';
2438
+ END IF;
2439
+ RETURN QUERY
2440
+ UPDATE runtime_observability.events SET search_doc = probe_doc
2441
+ WHERE CURRENT OF alias_target RETURNING ctid;
2442
+ IF NOT FOUND THEN
2443
+ RAISE EXCEPTION 'Legacy log alias target changed before update' USING ERRCODE = '40001';
2444
+ END IF;
2445
+ EXCEPTION WHEN OTHERS THEN
2446
+ -- The cursor predates this exception block, so it remains open after
2447
+ -- rollback of a failed update. Preserve the original SQL error.
2448
+ CLOSE alias_target;
2449
+ RAISE;
2450
+ END;
2451
+ CLOSE alias_target;
2452
+ END
2453
+ $function$;
2454
+ REVOKE ALL ON FUNCTION ${schema}.update_legacy_log_alias(text,text,jsonb,text) FROM PUBLIC;
2455
+ -- These cursors keep a cached, index-ordered lower-bound plan. Stop at the
2456
+ -- first different complete prefix, retaining all equal-prefix occurrences
2457
+ -- before applying the original sequence and identity ordering.
2458
+ CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_position(probe_org text, probe_run text, probe_channel text, probe_alias jsonb)
2459
+ RETURNS TABLE(event_id text, source_digest text, search_doc jsonb)
2460
+ LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
2461
+ SET enable_seqscan = off SET enable_indexscan = on AS $function$
2462
+ DECLARE candidate record; active_cursor refcursor;
2463
+ best_id text; best_digest text; best_doc jsonb; best_seq bigint;
2464
+ ${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
2465
+ (channel) => `
2466
+ ${channel}_positions NO SCROLL CURSOR FOR
2467
+ SELECT ARRAY[event.runtime_scope, event.org_id, event.run_id] AS key_scope,
2468
+ event.search_doc->'producerAttempt' AS key_attempt,
2469
+ event.search_doc->'logPositions'->'${channel}' AS key_position,
2470
+ event.event_id, event.source_digest, event.search_doc, event.log_seq
2471
+ FROM runtime_observability.events AS event
2472
+ WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2473
+ AND event.search_doc ? 'producerAttempt' AND event.search_doc ? 'logPositions'
2474
+ AND (event.search_doc->'logPositions') ? '${channel}'
2475
+ AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
2476
+ event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
2477
+ >= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
2478
+ probe_alias->'producerAttempt', probe_alias->'${channel}')
2479
+ AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
2480
+ event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
2481
+ <= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
2482
+ probe_alias->'producerAttempt', probe_alias->'${channel}')
2483
+ ORDER BY ARRAY[event.runtime_scope, event.org_id, event.run_id],
2484
+ event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}';
2485
+ `,
2486
+ ).join('')}
2487
+ BEGIN
2488
+ CASE probe_channel
2489
+ ${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
2490
+ (channel) => `
2491
+ WHEN '${channel}' THEN OPEN ${channel}_positions; active_cursor := ${channel}_positions;
2492
+ `,
2493
+ ).join('')}
2494
+ ELSE RAISE EXCEPTION 'Legacy log read channel is invalid';
2495
+ END CASE;
2496
+ BEGIN
2497
+ LOOP
2498
+ FETCH active_cursor INTO candidate;
2499
+ EXIT WHEN NOT FOUND;
2500
+ EXIT WHEN candidate.key_scope IS DISTINCT FROM ARRAY[${quoteLiteral(scope)}, probe_org, probe_run]
2501
+ OR candidate.key_attempt IS DISTINCT FROM probe_alias->'producerAttempt'
2502
+ OR candidate.key_position IS DISTINCT FROM probe_alias->probe_channel;
2503
+ IF best_id IS NULL OR (candidate.log_seq IS NOT NULL AND best_seq IS NULL)
2504
+ OR candidate.log_seq < best_seq
2505
+ OR (candidate.log_seq IS NOT DISTINCT FROM best_seq AND candidate.event_id < best_id) THEN
2506
+ best_id := candidate.event_id; best_digest := candidate.source_digest;
2507
+ best_doc := candidate.search_doc; best_seq := candidate.log_seq;
2508
+ END IF;
2509
+ END LOOP;
2510
+ EXCEPTION WHEN OTHERS THEN
2511
+ CLOSE active_cursor;
2512
+ RAISE;
2513
+ END;
2514
+ CLOSE active_cursor;
2515
+ IF best_id IS NOT NULL THEN RETURN QUERY SELECT best_id, best_digest, best_doc; END IF;
2516
+ END
2517
+ $function$;
2518
+ REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_position(text,text,text,jsonb) FROM PUBLIC;
2519
+ -- Resolve direct and aliased positions once per line. This intentionally
2520
+ -- retains the old helper signature above for already-installed callers.
2521
+ CREATE OR REPLACE FUNCTION ${schema}.resolve_legacy_log_position(probe_org text, probe_run text, probe_channel text, probe_alias jsonb, probe_position bigint, probe_worker_key text, probe_ids text[])
2522
+ RETURNS TABLE(event_id text, source_digest text, search_doc jsonb, worker_key_reserved boolean)
2523
+ LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
2524
+ SET enable_seqscan = off SET enable_indexscan = on AS $function$
2525
+ DECLARE candidate record; active_cursor refcursor;
2526
+ best_id text; best_digest text; best_doc jsonb; best_seq bigint; worker_reserved boolean;
2527
+ ${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
2528
+ (channel) => `
2529
+ ${channel}_positions NO SCROLL CURSOR FOR
2530
+ SELECT ARRAY[event.runtime_scope, event.org_id, event.run_id] AS key_scope,
2531
+ event.search_doc->'producerAttempt' AS key_attempt,
2532
+ event.search_doc->'logPositions'->'${channel}' AS key_position,
2533
+ event.event_id, event.source_digest, event.search_doc, event.log_seq
2534
+ FROM runtime_observability.events AS event
2535
+ WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2536
+ AND event.search_doc ? 'producerAttempt' AND event.search_doc ? 'logPositions'
2537
+ AND (event.search_doc->'logPositions') ? '${channel}'
2538
+ AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
2539
+ event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
2540
+ >= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
2541
+ probe_alias->'producerAttempt', probe_alias->'${channel}')
2542
+ AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
2543
+ event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
2544
+ <= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
2545
+ probe_alias->'producerAttempt', probe_alias->'${channel}')
2546
+ ORDER BY ARRAY[event.runtime_scope, event.org_id, event.run_id],
2547
+ event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}';
2548
+ `,
2549
+ ).join('')}
2550
+ BEGIN
2551
+ IF probe_channel NOT IN ('worker','replay','envelope') OR probe_channel IS NULL THEN
2552
+ RAISE EXCEPTION 'Legacy log read channel is invalid';
2553
+ END IF;
2554
+ -- All historical primary-key candidates share this one planner/security
2555
+ -- boundary. Keep the old complete-key seek and exact equality check;
2556
+ -- never prefetch absence across lines or change positional precedence.
2557
+ WITH identities AS MATERIALIZED (
2558
+ SELECT identity.*
2559
+ FROM unnest(probe_ids) AS keys(event_id)
2560
+ CROSS JOIN LATERAL (
2561
+ SELECT identity_candidate.* FROM (
2562
+ SELECT event.runtime_scope, event.org_id, event.event_id, event.run_id,
2563
+ event.kind, event.source_digest, event.search_doc
2564
+ FROM runtime_observability.events AS event
2565
+ WHERE (event.runtime_scope, event.org_id, event.event_id)
2566
+ >= (${quoteLiteral(scope)}, probe_org, keys.event_id)
2567
+ ORDER BY event.runtime_scope, event.org_id, event.event_id
2568
+ LIMIT 1
2569
+ ) AS identity_candidate
2570
+ WHERE identity_candidate.runtime_scope = ${quoteLiteral(scope)}
2571
+ AND identity_candidate.org_id = probe_org AND identity_candidate.event_id = keys.event_id
2572
+ ) AS identity
2573
+ )
2574
+ SELECT matched.event_id, matched.source_digest, matched.search_doc,
2575
+ coalesce(reserved.worker_reserved, false)
2576
+ INTO best_id, best_digest, best_doc, worker_reserved
2577
+ FROM (
2578
+ SELECT bool_or(event.event_id = probe_worker_key
2579
+ AND event.search_doc->>'source' = 'coordinator'
2580
+ AND NOT (coalesce(event.search_doc->'logPositions', '{}'::jsonb) ? 'worker')) AS worker_reserved
2581
+ FROM identities AS event
2582
+ ) AS reserved
2583
+ LEFT JOIN LATERAL (
2584
+ SELECT event.event_id, event.source_digest, event.search_doc
2585
+ FROM identities AS event
2586
+ WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = probe_org
2587
+ AND event.run_id = probe_run AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2588
+ AND (
2589
+ event.search_doc->'logPositions'->>probe_channel = probe_position::text
2590
+ OR (NOT (event.search_doc ? 'logPositions')
2591
+ AND event.event_id = probe_worker_key
2592
+ AND (CASE WHEN event.search_doc->>'source' = 'coordinator'
2593
+ THEN 'replay' ELSE 'worker' END) = probe_channel)
2594
+ )
2595
+ ORDER BY event.event_id LIMIT 1
2596
+ ) AS matched ON true;
2597
+ IF best_id IS NOT NULL THEN
2598
+ RETURN QUERY SELECT best_id, best_digest, best_doc, worker_reserved;
2599
+ RETURN;
2600
+ END IF;
2601
+ CASE probe_channel
2602
+ ${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
2603
+ (channel) => `
2604
+ WHEN '${channel}' THEN OPEN ${channel}_positions; active_cursor := ${channel}_positions;
2605
+ `,
2606
+ ).join('')}
2607
+ ELSE RAISE EXCEPTION 'Legacy log read channel is invalid';
2608
+ END CASE;
2609
+ BEGIN
2610
+ LOOP
2611
+ FETCH active_cursor INTO candidate;
2612
+ EXIT WHEN NOT FOUND;
2613
+ EXIT WHEN candidate.key_scope IS DISTINCT FROM ARRAY[${quoteLiteral(scope)}, probe_org, probe_run]
2614
+ OR candidate.key_attempt IS DISTINCT FROM probe_alias->'producerAttempt'
2615
+ OR candidate.key_position IS DISTINCT FROM probe_alias->probe_channel;
2616
+ IF best_id IS NULL OR (candidate.log_seq IS NOT NULL AND best_seq IS NULL)
2617
+ OR candidate.log_seq < best_seq
2618
+ OR (candidate.log_seq IS NOT DISTINCT FROM best_seq AND candidate.event_id < best_id) THEN
2619
+ best_id := candidate.event_id; best_digest := candidate.source_digest;
2620
+ best_doc := candidate.search_doc; best_seq := candidate.log_seq;
2621
+ END IF;
2622
+ END LOOP;
2623
+ EXCEPTION WHEN OTHERS THEN
2624
+ CLOSE active_cursor;
2625
+ RAISE;
2626
+ END;
2627
+ CLOSE active_cursor;
2628
+ RETURN QUERY SELECT best_id, best_digest, best_doc, worker_reserved;
2629
+ END
2630
+ $function$;
2631
+ REVOKE ALL ON FUNCTION ${schema}.resolve_legacy_log_position(text,text,text,jsonb,bigint,text,text[]) FROM PUBLIC;
2632
+ CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_occurrence(probe_org text, probe_run text, probe_attempt text, probe_digest text, probe_channel text)
2633
+ RETURNS TABLE(event_id text, search_doc jsonb)
2634
+ LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
2635
+ SET enable_seqscan = off SET enable_indexscan = on AS $function$
2636
+ DECLARE candidate record; best_id text; best_doc jsonb; best_seq bigint;
2637
+ digest_occurrences NO SCROLL CURSOR FOR
2638
+ SELECT event.runtime_scope, event.org_id, event.run_id,
2639
+ event.search_doc->>'producerAttempt' AS key_attempt,
2640
+ event.source_digest, event.event_id, event.search_doc, event.log_seq
2641
+ FROM runtime_observability.events AS event
2642
+ WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2643
+ AND event.source_digest IS NOT NULL AND event.search_doc ? 'producerAttempt'
2644
+ AND event.search_doc ? 'logContentDigest'
2645
+ AND ROW(event.runtime_scope, event.org_id, event.run_id,
2646
+ event.search_doc->>'producerAttempt', event.source_digest)
2647
+ >= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
2648
+ AND ROW(event.runtime_scope, event.org_id, event.run_id,
2649
+ event.search_doc->>'producerAttempt', event.source_digest)
2650
+ <= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
2651
+ ORDER BY event.runtime_scope, event.org_id, event.run_id,
2652
+ event.search_doc->>'producerAttempt', event.source_digest;
2653
+ BEGIN
2654
+ IF probe_channel NOT IN ('worker','replay','envelope') OR probe_channel IS NULL THEN
2655
+ RAISE EXCEPTION 'Legacy log read channel is invalid';
2656
+ END IF;
2657
+ OPEN digest_occurrences;
2658
+ BEGIN
2659
+ LOOP
2660
+ FETCH digest_occurrences INTO candidate;
2661
+ EXIT WHEN NOT FOUND;
2662
+ EXIT WHEN candidate.runtime_scope IS DISTINCT FROM ${quoteLiteral(scope)}
2663
+ OR candidate.org_id IS DISTINCT FROM probe_org OR candidate.run_id IS DISTINCT FROM probe_run
2664
+ OR candidate.key_attempt IS DISTINCT FROM probe_attempt OR candidate.source_digest IS DISTINCT FROM probe_digest;
2665
+ IF NOT (candidate.search_doc ? 'entryId')
2666
+ AND candidate.search_doc @> jsonb_build_object('logContentDigest', probe_digest)
2667
+ AND NOT (coalesce(candidate.search_doc->'logPositions', '{}'::jsonb) ? probe_channel)
2668
+ AND (candidate.search_doc ? 'logPositions' OR probe_channel <>
2669
+ CASE WHEN candidate.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END)
2670
+ AND (best_id IS NULL OR (candidate.log_seq IS NOT NULL AND best_seq IS NULL)
2671
+ OR candidate.log_seq < best_seq
2672
+ OR (candidate.log_seq IS NOT DISTINCT FROM best_seq AND candidate.event_id < best_id)) THEN
2673
+ best_id := candidate.event_id; best_doc := candidate.search_doc; best_seq := candidate.log_seq;
2674
+ END IF;
2675
+ END LOOP;
2676
+ EXCEPTION WHEN OTHERS THEN
2677
+ CLOSE digest_occurrences;
2678
+ RAISE;
2679
+ END;
2680
+ CLOSE digest_occurrences;
2681
+ IF best_id IS NOT NULL THEN RETURN QUERY SELECT best_id, best_doc; END IF;
2682
+ END
2683
+ $function$;
2684
+ REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_occurrence(text,text,text,text,text) FROM PUBLIC;
2685
+ -- A request can consume at most probe_count distinct occurrences. Keep
2686
+ -- only that necessary rank, not the run's whole equal-digest history. The
2687
+ -- inner order preserves the existing complete-prefix access contract;
2688
+ -- the outer top-N sort holds only compact identity/sequence metadata.
2689
+ CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_occurrence_pool(
2690
+ probe_org text, probe_run text, probe_attempt text, probe_digest text,
2691
+ probe_channel text, probe_count bigint)
2692
+ RETURNS TABLE(event_id text, cacheable boolean)
2693
+ LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
2694
+ SET enable_seqscan = off SET enable_indexscan = on AS $function$
2695
+ DECLARE candidate record; emitted boolean := false;
2696
+ BEGIN
2697
+ IF probe_channel NOT IN ('worker','replay','envelope') OR probe_channel IS NULL
2698
+ OR probe_count IS NULL OR probe_count < 1 THEN
2699
+ RAISE EXCEPTION 'Legacy log occurrence pool requires a channel and positive request rank';
2700
+ END IF;
2701
+ FOR candidate IN
2702
+ SELECT prefix.event_id, prefix.log_seq,
2703
+ (prefix.null_entry OR prefix.null_channel) IS TRUE AS unsafe
2704
+ FROM (
2705
+ SELECT event.event_id, event.log_seq, event.search_doc ? 'entryId' AS has_entry_id,
2706
+ event.search_doc->'entryId' = 'null'::jsonb AS null_entry,
2707
+ event.search_doc @> jsonb_build_object('logContentDigest', probe_digest) AS same_digest,
2708
+ coalesce(event.search_doc->'logPositions', '{}'::jsonb) ? probe_channel AS has_channel,
2709
+ event.search_doc->'logPositions'->probe_channel = 'null'::jsonb AS null_channel,
2710
+ event.search_doc ? 'logPositions' OR probe_channel <>
2711
+ CASE WHEN event.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END AS cross_channel
2712
+ FROM runtime_observability.events AS event
2713
+ WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2714
+ AND event.source_digest IS NOT NULL AND event.search_doc ? 'producerAttempt'
2715
+ AND event.search_doc ? 'logContentDigest'
2716
+ AND ROW(event.runtime_scope, event.org_id, event.run_id,
2717
+ event.search_doc->>'producerAttempt', event.source_digest)
2718
+ >= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
2719
+ AND ROW(event.runtime_scope, event.org_id, event.run_id,
2720
+ event.search_doc->>'producerAttempt', event.source_digest)
2721
+ <= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
2722
+ ORDER BY event.runtime_scope, event.org_id, event.run_id,
2723
+ event.search_doc->>'producerAttempt', event.source_digest
2724
+ OFFSET 0
2725
+ ) AS prefix
2726
+ WHERE (NOT prefix.has_entry_id AND prefix.same_digest
2727
+ AND NOT prefix.has_channel AND prefix.cross_channel)
2728
+ OR prefix.null_entry OR prefix.null_channel
2729
+ ORDER BY unsafe DESC, prefix.log_seq NULLS LAST, prefix.event_id
2730
+ LIMIT probe_count
2731
+ LOOP
2732
+ -- TTL strips null object members without the log mutex. Such legacy
2733
+ -- metadata can become newly eligible, so retain its scalar semantics.
2734
+ IF candidate.unsafe THEN RETURN QUERY SELECT NULL::text, false; RETURN; END IF;
2735
+ emitted := true;
2736
+ RETURN QUERY SELECT candidate.event_id::text, true;
2737
+ END LOOP;
2738
+ IF NOT emitted THEN RETURN QUERY SELECT NULL::text, true; END IF;
2739
+ END
2740
+ $function$;
2741
+ REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_occurrence_pool(text,text,text,text,text,bigint) FROM PUBLIC;
2742
+ END; $install_legacy_log_access$`);
2375
2743
  const acquireLogCursorSql = `
2376
2744
  IF NOT cursor_locked THEN
2377
2745
  -- One allocation owner supplies final sequences at INSERT time. The
@@ -2398,7 +2766,10 @@ export async function attachRuntimeEventSearchTriggers(
2398
2766
  doc jsonb; line_doc jsonb; line_context jsonb; line_metadata jsonb; line_at timestamptz;
2399
2767
  eid text; existing_digest text; digest text; assigned_seq bigint; terminal_progress_identity boolean;
2400
2768
  log_channel text; log_position bigint; matched_event_id text; matched_doc jsonb;
2401
- legacy_position_prefix text; position_event_ids text[];
2769
+ legacy_position_prefix text; position_event_ids text[]; worker_key_reserved boolean;
2770
+ occurrence_pool_digests text[]; occurrence_pool_ids text[]; occurrence_pool_cacheable boolean[];
2771
+ occurrence_pool_heads integer[]; occurrence_pool_loaded boolean;
2772
+ occurrence_low integer; occurrence_high integer; occurrence_mid integer; occurrence_group integer; occurrence_head integer;
2402
2773
  log_alias jsonb; position_alias jsonb; envelope_attempt jsonb;
2403
2774
  cursor_created boolean := false; cursor_locked boolean := false; line_count bigint; fresh_event_ids text[] := ARRAY[]::text[];
2404
2775
  fresh_tids tid[] := ARRAY[]::tid[]; inserted_tid tid;
@@ -2537,20 +2908,24 @@ export async function attachRuntimeEventSearchTriggers(
2537
2908
  -- unmarked rows otherwise scans the whole attempt for every new line.
2538
2909
  IF EXISTS (SELECT 1 FROM jsonb_array_elements(event_batch) AS entry
2539
2910
  WHERE entry->>'type' = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended} AND (NOT (entry ? 'lineIds') OR EXISTS (SELECT 1 FROM jsonb_array_elements(CASE WHEN jsonb_typeof(entry->'lineIds') = 'array' THEN entry->'lineIds' ELSE '[]'::jsonb END) id WHERE id = 'null'::jsonb))) THEN
2911
+ -- Replan this once-per-batch legacy normalization with its real run.
2912
+ -- A retained empty-table plan otherwise rereads every run's history.
2913
+ EXECUTE $legacy_normalize$
2540
2914
  UPDATE runtime_observability.events AS event SET search_doc = event.search_doc ||
2541
2915
  jsonb_build_object('logContentDigest', event.source_digest) ||
2542
2916
  CASE WHEN NOT (event.search_doc ? 'logPositions')
2543
- AND left(event.event_id, length('log:' || observation.run_id || ':' || (event.search_doc->>'producerAttempt') || ':')) =
2544
- 'log:' || observation.run_id || ':' || (event.search_doc->>'producerAttempt') || ':'
2545
- AND substring(event.event_id FROM length('log:' || observation.run_id || ':' || (event.search_doc->>'producerAttempt') || ':') + 1) ~ '^[0-9]{1,12}$'
2917
+ AND left(event.event_id, length('log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':')) =
2918
+ 'log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':'
2919
+ AND substring(event.event_id FROM length('log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':') + 1) ~ '^[0-9]{1,12}$'
2546
2920
  THEN jsonb_build_object('logPositions', jsonb_build_object(
2547
2921
  CASE WHEN event.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END,
2548
- substring(event.event_id FROM length('log:' || observation.run_id || ':' || (event.search_doc->>'producerAttempt') || ':') + 1)::bigint))
2922
+ substring(event.event_id FROM length('log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':') + 1)::bigint))
2549
2923
  ELSE '{}'::jsonb END
2550
- WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = run_org
2551
- AND event.run_id = observation.run_id AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2924
+ WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = $1
2925
+ AND event.run_id = $2 AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2552
2926
  AND event.source_digest IS NOT NULL AND NOT (event.search_doc ? 'logContentDigest') AND NOT (event.search_doc ? 'entryId')
2553
- AND (event.search_doc->>'producerAttempt') ~ '^[1-9][0-9]{0,5}$';
2927
+ AND (event.search_doc->>'producerAttempt') ~ '^[1-9][0-9]{0,5}$'
2928
+ $legacy_normalize$ USING run_org, observation.run_id;
2554
2929
  END IF;
2555
2930
  FOR item, ordinal IN SELECT value, ordinality FROM jsonb_array_elements(event_batch) WITH ORDINALITY LOOP
2556
2931
  IF jsonb_typeof(item) IS DISTINCT FROM 'object'
@@ -2613,6 +2988,7 @@ export async function attachRuntimeEventSearchTriggers(
2613
2988
  END IF;
2614
2989
  END IF;
2615
2990
  IF kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended} THEN
2991
+ occurrence_pool_loaded := false;
2616
2992
  FOR line, line_ordinal IN SELECT value, ordinality FROM jsonb_array_elements(item->'lines') WITH ORDINALITY LOOP
2617
2993
  IF jsonb_typeof(line) IS DISTINCT FROM 'string' THEN
2618
2994
  RAISE EXCEPTION 'Search projection requires log line strings';
@@ -2700,17 +3076,6 @@ export async function attachRuntimeEventSearchTriggers(
2700
3076
  eid := CASE WHEN log_channel = 'worker' THEN legacy_position_prefix
2701
3077
  ELSE 'log-' || log_channel || ':' || observation.run_id || ':' || (item->>'producerAttempt') || ':' END
2702
3078
  || log_position::text;
2703
- -- Older coordinator replays used the worker-shaped primary
2704
- -- key. Do not overwrite it when a delayed worker owns a
2705
- -- different line at that number; aliases remain authoritative.
2706
- IF log_channel = 'worker' AND EXISTS (
2707
- SELECT 1 FROM runtime_observability.events
2708
- WHERE runtime_scope = ${quoteLiteral(scope)} AND org_id = run_org AND event_id = eid
2709
- AND search_doc->>'source' = 'coordinator'
2710
- AND NOT (coalesce(search_doc->'logPositions', '{}'::jsonb) ? 'worker')
2711
- ) THEN
2712
- eid := 'log-worker:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text;
2713
- END IF;
2714
3079
  log_alias := jsonb_build_object('producerAttempt', (item->>'producerAttempt')::integer,
2715
3080
  'logPositions', jsonb_build_object(log_channel, log_position));
2716
3081
  position_alias := jsonb_build_object(
@@ -2723,53 +3088,18 @@ export async function attachRuntimeEventSearchTriggers(
2723
3088
  'log-replay:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text,
2724
3089
  'log-envelope:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text
2725
3090
  ];
2726
- -- Positional identities have a bounded set of historical IDs.
2727
- -- Probe those primary keys directly; scanning every event in
2728
- -- the run for JSON containment made one lookup grow with run age.
2729
- SELECT event.event_id, event.source_digest, event.search_doc
2730
- INTO matched_event_id, existing_digest, matched_doc
2731
- FROM runtime_observability.events AS event
2732
- WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = run_org
2733
- AND event.run_id = observation.run_id AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2734
- AND event.event_id = ANY(position_event_ids)
2735
- AND (
2736
- event.search_doc->'logPositions'->>log_channel = log_position::text
2737
- OR (NOT (event.search_doc ? 'logPositions')
2738
- AND event.event_id = legacy_position_prefix || log_position::text
2739
- AND (CASE WHEN event.search_doc->>'source' = 'coordinator'
2740
- THEN 'replay' ELSE 'worker' END) = log_channel)
2741
- )
2742
- ORDER BY event.event_id
2743
- LIMIT 1;
2744
- IF matched_event_id IS NULL THEN
2745
- -- Pack scope, organization and run into one indexed key.
2746
- -- The materialization keeps generic plans from choosing a
2747
- -- run-history scan based on the outer identity checks.
2748
- WITH position_matches AS MATERIALIZED (
2749
- ${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
2750
- (channel) => `
2751
- SELECT event.event_id, event.source_digest, event.search_doc,
2752
- event.log_seq, event.runtime_scope, event.org_id, event.run_id
2753
- FROM runtime_observability.events AS event
2754
- WHERE log_channel = '${channel}'
2755
- AND ARRAY[event.runtime_scope, event.org_id, event.run_id]
2756
- = ARRAY[${quoteLiteral(scope)}, run_org, observation.run_id]
2757
- AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2758
- AND event.search_doc ? 'producerAttempt'
2759
- AND event.search_doc ? 'logPositions'
2760
- AND (event.search_doc->'logPositions') ? '${channel}'
2761
- AND event.search_doc->'producerAttempt' = position_alias->'producerAttempt'
2762
- AND event.search_doc->'logPositions'->'${channel}' = position_alias->'${channel}'
2763
- `,
2764
- ).join(' UNION ALL ')}
2765
- )
2766
- SELECT event.event_id, event.source_digest, event.search_doc
2767
- INTO matched_event_id, existing_digest, matched_doc
2768
- FROM position_matches AS event
2769
- WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = run_org
2770
- AND event.run_id = observation.run_id
2771
- ORDER BY event.log_seq NULLS LAST, event.event_id
2772
- LIMIT 1;
3091
+ -- Resolve every direct key and the fallback alias in one
3092
+ -- private scope, preserving the same live per-line decisions.
3093
+ SELECT event.event_id, event.source_digest, event.search_doc,
3094
+ event.worker_key_reserved
3095
+ INTO matched_event_id, existing_digest, matched_doc, worker_key_reserved
3096
+ FROM ${schema}.resolve_legacy_log_position(run_org, observation.run_id,
3097
+ log_channel, position_alias, log_position,
3098
+ legacy_position_prefix || log_position::text, position_event_ids) AS event;
3099
+ -- Older coordinator replays used the worker-shaped primary
3100
+ -- key. Keep that conflict decision even when no position matches.
3101
+ IF log_channel = 'worker' AND worker_key_reserved THEN
3102
+ eid := 'log-worker:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text;
2773
3103
  END IF;
2774
3104
  IF matched_event_id IS NOT NULL THEN
2775
3105
  IF existing_digest IS DISTINCT FROM digest THEN
@@ -2777,30 +3107,84 @@ export async function attachRuntimeEventSearchTriggers(
2777
3107
  END IF;
2778
3108
  CONTINUE;
2779
3109
  END IF;
2780
- -- Bind one equal occurrence from another channel. Aliases
2781
- -- are checked first, so retries cannot consume another copy.
2782
- -- Full digests include context; repeated text is not a set.
2783
- SELECT event.event_id, event.search_doc
2784
- INTO matched_event_id, matched_doc
2785
- FROM runtime_observability.events AS event
2786
- WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = run_org
2787
- AND event.run_id = observation.run_id AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
2788
- AND event.source_digest IS NOT NULL
2789
- AND event.search_doc ? 'producerAttempt'
2790
- AND event.search_doc ? 'logContentDigest' AND NOT (event.search_doc ? 'entryId')
2791
- AND event.search_doc->>'producerAttempt' = ((item->>'producerAttempt')::integer)::text
2792
- AND event.source_digest = digest
2793
- AND event.search_doc @> jsonb_build_object('logContentDigest', digest)
2794
- AND NOT (coalesce(event.search_doc->'logPositions', '{}'::jsonb) ? log_channel)
2795
- AND (event.search_doc ? 'logPositions' OR log_channel <>
2796
- CASE WHEN event.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END)
2797
- ORDER BY event.log_seq NULLS LAST, event.event_id LIMIT 1;
3110
+ -- Positional decisions stay in original line order. Only the
3111
+ -- occurrence candidates are shared within this one item: an
3112
+ -- inserted line already has this channel (or entryId), and an
3113
+ -- alias can only remove eligibility, never add another row.
3114
+ IF NOT occurrence_pool_loaded THEN
3115
+ EXECUTE $legacy_occurrence_pools$
3116
+ WITH requested AS MATERIALIZED (
3117
+ SELECT CASE WHEN NULLIF($2->((entry.ordinality-1)::integer), 'null'::jsonb) IS NULL
3118
+ THEN encode(sha256(convert_to(entry.value #>> '{}','UTF8')),'hex')
3119
+ ELSE encode(sha256(convert_to(jsonb_build_array(entry.value #>> '{}',
3120
+ $2->((entry.ordinality-1)::integer))::text,'UTF8')),'hex') END AS content_digest
3121
+ FROM jsonb_array_elements($1) WITH ORDINALITY AS entry(value, ordinality)
3122
+ WHERE jsonb_typeof(entry.value) = 'string'
3123
+ AND NULLIF($3->((entry.ordinality-1)::integer), 'null'::jsonb) IS NULL
3124
+ ), groups AS (
3125
+ SELECT content_digest, count(*) AS request_count FROM requested GROUP BY content_digest
3126
+ )
3127
+ SELECT array_agg(groups.content_digest ORDER BY groups.content_digest COLLATE "C", pool.ordinality),
3128
+ array_agg(pool.event_id ORDER BY groups.content_digest COLLATE "C", pool.ordinality),
3129
+ array_agg(pool.cacheable ORDER BY groups.content_digest COLLATE "C", pool.ordinality)
3130
+ FROM groups CROSS JOIN LATERAL
3131
+ ${schema}.lookup_legacy_log_occurrence_pool($4,$5,$6,groups.content_digest,$7,groups.request_count)
3132
+ WITH ORDINALITY AS pool(event_id,cacheable,ordinality)
3133
+ $legacy_occurrence_pools$
3134
+ INTO occurrence_pool_digests, occurrence_pool_ids, occurrence_pool_cacheable
3135
+ USING item->'lines', item->'lineContexts', item->'lineIds', run_org, observation.run_id,
3136
+ ((item->>'producerAttempt')::integer)::text, log_channel;
3137
+ occurrence_pool_heads := array_fill(NULL::integer, ARRAY[cardinality(occurrence_pool_digests)]);
3138
+ occurrence_pool_loaded := true;
3139
+ END IF;
3140
+ -- Binary search the flat digest groups; native array element
3141
+ -- assignments retain compact mutable heads without copying a
3142
+ -- growing JSON metadata map for every incoming line.
3143
+ occurrence_low := 1; occurrence_high := cardinality(occurrence_pool_digests);
3144
+ WHILE occurrence_low < occurrence_high LOOP
3145
+ occurrence_mid := (occurrence_low + occurrence_high) / 2;
3146
+ IF occurrence_pool_digests[occurrence_mid] COLLATE "C" < digest COLLATE "C" THEN
3147
+ occurrence_low := occurrence_mid + 1;
3148
+ ELSE occurrence_high := occurrence_mid; END IF;
3149
+ END LOOP;
3150
+ occurrence_group := occurrence_low;
3151
+ IF occurrence_pool_digests[occurrence_group] IS DISTINCT FROM digest THEN
3152
+ RAISE EXCEPTION 'Legacy log occurrence pool omitted an incoming digest';
3153
+ END IF;
3154
+ occurrence_head := coalesce(occurrence_pool_heads[occurrence_group], occurrence_group);
3155
+ matched_event_id := NULL; matched_doc := NULL;
3156
+ IF occurrence_pool_cacheable[occurrence_group]
3157
+ AND occurrence_pool_digests[occurrence_head] IS NOT DISTINCT FROM digest
3158
+ AND occurrence_pool_ids[occurrence_head] IS NOT NULL THEN
3159
+ SELECT event.event_id, event.search_doc INTO matched_event_id, matched_doc
3160
+ FROM ${schema}.lookup_legacy_log_identity(run_org, occurrence_pool_ids[occurrence_head]) AS event
3161
+ WHERE event.run_id = observation.run_id AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
3162
+ AND event.source_digest = digest AND event.search_doc->>'producerAttempt' = ((item->>'producerAttempt')::integer)::text
3163
+ AND NOT (event.search_doc ? 'entryId')
3164
+ AND event.search_doc @> jsonb_build_object('logContentDigest', digest)
3165
+ AND NOT (coalesce(event.search_doc->'logPositions', '{}'::jsonb) ? log_channel)
3166
+ AND (event.search_doc ? 'logPositions' OR log_channel <>
3167
+ CASE WHEN event.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END);
3168
+ IF matched_event_id IS NULL THEN
3169
+ -- A concurrent TTL scrub may remove a null alias. Once
3170
+ -- the snapshot changes, scalar lookup sees the full tail.
3171
+ occurrence_pool_cacheable[occurrence_group] := false;
3172
+ END IF;
3173
+ END IF;
3174
+ IF NOT occurrence_pool_cacheable[occurrence_group] THEN
3175
+ SELECT event.event_id, event.search_doc INTO matched_event_id, matched_doc
3176
+ FROM ${schema}.lookup_legacy_log_occurrence(run_org, observation.run_id,
3177
+ ((item->>'producerAttempt')::integer)::text, digest, log_channel) AS event;
3178
+ END IF;
2798
3179
  IF matched_event_id IS NOT NULL THEN
2799
- UPDATE runtime_observability.events SET search_doc = matched_doc ||
2800
- jsonb_build_object('logContentDigest', digest, 'logPositions',
2801
- coalesce(matched_doc->'logPositions', '{}'::jsonb) || jsonb_build_object(log_channel, log_position))
2802
- WHERE runtime_scope = ${quoteLiteral(scope)} AND org_id = run_org AND event_id = matched_event_id
2803
- RETURNING ctid INTO inserted_tid;
3180
+ matched_doc := matched_doc || jsonb_build_object('logContentDigest', digest, 'logPositions',
3181
+ coalesce(matched_doc->'logPositions', '{}'::jsonb) || jsonb_build_object(log_channel, log_position));
3182
+ SELECT updated.updated_tid INTO inserted_tid
3183
+ FROM ${schema}.update_legacy_log_alias(run_org, matched_event_id, matched_doc, observation.run_id) AS updated;
3184
+ IF occurrence_pool_cacheable[occurrence_group]
3185
+ AND (coalesce(matched_doc->'logPositions', '{}'::jsonb) ? log_channel) THEN
3186
+ occurrence_pool_heads[occurrence_group] := occurrence_head + 1;
3187
+ END IF;
2804
3188
  -- Aliasing a fresh line moves its tuple within this transaction.
2805
3189
  fresh_target_index := array_position(fresh_event_ids, matched_event_id);
2806
3190
  IF fresh_target_index IS NOT NULL THEN