deepline 0.3.406 → 0.3.408

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 (130) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +56 -57
  2. package/dist/bundling-sources/sdk/src/play.ts +21 -5
  3. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  4. package/dist/bundling-sources/sdk/src/types.ts +27 -3
  5. package/dist/bundling-sources/shared_libs/play-runtime/admission-timings.ts +64 -0
  6. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +11 -1
  7. package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +1 -4
  8. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +4 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +2 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +15 -6
  11. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +275 -73
  13. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +22 -4
  14. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +10 -4
  15. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +72 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/webhook-receipt-source-commit-retry.ts +90 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +5 -0
  18. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +6 -1
  19. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +6 -0
  20. package/dist/cli/auth-3GB2K636.js +40 -0
  21. package/dist/cli/{auth-U7LIMXIS.mjs → auth-UVD3CUBB.mjs} +4 -4
  22. package/dist/cli/{billing-KGGS3444.mjs → billing-BZVTXXLM.mjs} +23 -16
  23. package/dist/cli/{billing-5ABVIJFU.js → billing-BZVYAF6T.js} +92 -85
  24. package/dist/cli/{chunk-KPU53YBB.js → chunk-2XXXFPTD.js} +67 -67
  25. package/dist/cli/{chunk-FQBKK5DG.js → chunk-3ZB6IIA7.js} +26 -26
  26. package/dist/cli/{chunk-5IGBBYXH.mjs → chunk-4CFULMRB.mjs} +73 -4
  27. package/dist/cli/{chunk-OPHLT4TM.mjs → chunk-4QFT5LGV.mjs} +2 -2
  28. package/dist/cli/{chunk-W2BAO4OR.js → chunk-4RNDKFNQ.js} +2 -2
  29. package/dist/cli/{chunk-GAMFK2ZP.mjs → chunk-67RWR34T.mjs} +10 -3
  30. package/dist/cli/{chunk-APLRSERF.js → chunk-AUMD2VXP.js} +60 -63
  31. package/dist/cli/{chunk-N6DJQQ2S.js → chunk-BRJUESQV.js} +50 -50
  32. package/dist/cli/{chunk-W3ZNQE5Y.js → chunk-D6FFBSM5.js} +1 -1
  33. package/dist/cli/{chunk-AYHLUHE5.js → chunk-E3PJF6YP.js} +6 -2
  34. package/dist/cli/{chunk-IE6IKRQA.js → chunk-ECVLPS67.js} +15 -15
  35. package/dist/cli/{chunk-QJBJZVG6.js → chunk-HQY2SG3K.js} +15 -8
  36. package/dist/cli/{chunk-2OFPPAUY.mjs → chunk-I3DHIXVJ.mjs} +4 -4
  37. package/dist/cli/{chunk-RXDJKAM2.mjs → chunk-IOHRWLQE.mjs} +6 -6
  38. package/dist/cli/{chunk-2MLY2ZBT.mjs → chunk-IWBXJDZA.mjs} +2 -2
  39. package/dist/cli/{chunk-URWF7NGQ.js → chunk-J5PTX66Y.js} +28 -14
  40. package/dist/cli/{chunk-7ZMVAV2B.mjs → chunk-LOYISF7S.mjs} +55 -58
  41. package/dist/cli/{chunk-T7YF4MQH.mjs → chunk-MJELBQBU.mjs} +4 -4
  42. package/dist/cli/{chunk-WJYPBHTE.js → chunk-OSFWFV72.js} +11 -4
  43. package/dist/cli/{chunk-ZI2ZNDJK.mjs → chunk-PYZZMAJQ.mjs} +28 -14
  44. package/dist/cli/{chunk-N43PX2CA.js → chunk-Q3LFI3VH.js} +8 -8
  45. package/dist/cli/{chunk-NYDRX6JJ.js → chunk-Q3PUHXOY.js} +99 -30
  46. package/dist/cli/{chunk-YSAZVLJD.js → chunk-QUAQX3FQ.js} +4 -4
  47. package/dist/cli/{chunk-4REBZQNK.js → chunk-RWCY6YI2.js} +53 -53
  48. package/dist/cli/{chunk-CGX4NSS3.mjs → chunk-SD7MXAJA.mjs} +1 -1
  49. package/dist/cli/{chunk-UFS752TU.mjs → chunk-SJVVBWRL.mjs} +5 -1
  50. package/dist/cli/{chunk-V3OTRWVK.mjs → chunk-URACNNLO.mjs} +2 -2
  51. package/dist/cli/{chunk-WXLOW623.mjs → chunk-WPAB4DCU.mjs} +14 -7
  52. package/dist/cli/{chunk-42RUJLQI.mjs → chunk-WTT6CLED.mjs} +1 -1
  53. package/dist/cli/{chunk-YLV6PT6B.mjs → chunk-XXLXOUUU.mjs} +1 -1
  54. package/dist/cli/{chunk-77UGRG6X.mjs → chunk-YMOFWHGO.mjs} +3 -3
  55. package/dist/cli/{chunk-EKS2FXL5.js → chunk-ZBABPK6Y.js} +8 -8
  56. package/dist/cli/command-docs.js +2 -2
  57. package/dist/cli/command-docs.mjs +1 -1
  58. package/dist/cli/{csv-HXJAAW3H.mjs → csv-WPSXG6ZZ.mjs} +3 -3
  59. package/dist/cli/{csv-U36TIOKU.js → csv-XLGLHJ6P.js} +12 -12
  60. package/dist/cli/{db-T5MLQQWJ.js → db-5PTNJG4X.js} +25 -25
  61. package/dist/cli/{db-GRWD3JAC.mjs → db-ABS57ABJ.mjs} +4 -4
  62. package/dist/cli/{describe-NFX6THJE.js → describe-EZS6PQXA.js} +11 -11
  63. package/dist/cli/{describe-HXFEIZFO.mjs → describe-PVWQJ2PB.mjs} +7 -7
  64. package/dist/cli/describe-core.d.mts +2 -2
  65. package/dist/cli/describe-core.d.ts +2 -2
  66. package/dist/cli/{executions-KBHTDL3A.js → executions-FNTAFQ7Y.js} +6 -6
  67. package/dist/cli/{executions-YGOS5E44.mjs → executions-OKJGATQZ.mjs} +4 -4
  68. package/dist/cli/{feedback-VP3GWJIH.js → feedback-6YBOMSUA.js} +7 -7
  69. package/dist/cli/{feedback-NEQGCSHB.mjs → feedback-W27HDMRR.mjs} +3 -3
  70. package/dist/cli/git-YKUXXJOR.js +24 -0
  71. package/dist/cli/{git-JJ3CHOTL.mjs → git-YOOUEL6M.mjs} +4 -4
  72. package/dist/cli/index.js +204 -127
  73. package/dist/cli/index.mjs +124 -47
  74. package/dist/cli/{legacy-noops-ITTD33ZN.js → legacy-noops-2VZ7XT6C.js} +7 -7
  75. package/dist/cli/{legacy-noops-A6KGBODU.mjs → legacy-noops-V6OKW7VR.mjs} +4 -4
  76. package/dist/cli/{monitors-DXVP5YFC.js → monitors-FBWGVIUS.js} +84 -84
  77. package/dist/cli/{monitors-NGEXCUEY.mjs → monitors-P2YYWTWT.mjs} +4 -4
  78. package/dist/cli/{org-C4ZTOSQC.js → org-3XUSVX5T.js} +64 -64
  79. package/dist/cli/{org-34DBJSFP.mjs → org-DVMG6H3C.mjs} +4 -4
  80. package/dist/cli/{play-SVLQKZBG.mjs → play-GNC5CQAS.mjs} +70 -18
  81. package/dist/cli/{play-5FWTZCHN.js → play-YG5L4BWQ.js} +345 -293
  82. package/dist/cli/{providers-QWR2HRNY.js → providers-7PSWG2OV.js} +7 -7
  83. package/dist/cli/{providers-RQTSGYE4.mjs → providers-JR33SLWL.mjs} +4 -4
  84. package/dist/cli/{quickstart-DHFNEMGY.js → quickstart-FDVZ5BL3.js} +5 -5
  85. package/dist/cli/{quickstart-W5UHZAEU.mjs → quickstart-VUOBQYIQ.mjs} +3 -3
  86. package/dist/cli/{search-U4AJC3FH.mjs → search-JZYLO33K.mjs} +5 -5
  87. package/dist/cli/search-PPPYC5OZ.js +30 -0
  88. package/dist/cli/{secrets-YSMQ7CVZ.mjs → secrets-3MCYBT4I.mjs} +4 -4
  89. package/dist/cli/{secrets-HH4H7BLE.js → secrets-VS266FVA.js} +13 -13
  90. package/dist/cli/{sessions-URONRCTV.mjs → sessions-ELLLT23E.mjs} +4 -4
  91. package/dist/cli/{sessions-AJZXYUCJ.js → sessions-TEHEWW7O.js} +5 -5
  92. package/dist/cli/{settings-QAW62BH4.js → settings-7364NMMA.js} +75 -75
  93. package/dist/cli/{settings-KGAMW4MN.mjs → settings-PZCKAFII.mjs} +8 -8
  94. package/dist/cli/{setup-P54DPBFO.mjs → setup-A7GQ4KIA.mjs} +7 -7
  95. package/dist/cli/{setup-KAMFU5VE.js → setup-PMWYLCT6.js} +42 -42
  96. package/dist/cli/skills-SYS7VRRK.js +29 -0
  97. package/dist/cli/{skills-UMWRJ6TL.mjs → skills-WS6BIFPQ.mjs} +5 -5
  98. package/dist/cli/{tools-HN4EFVY7.mjs → tools-BR4DOZA2.mjs} +7 -7
  99. package/dist/cli/{tools-HX3BHT55.js → tools-KK4BKVQR.js} +8 -8
  100. package/dist/cli/update-2IV5JTX2.js +29 -0
  101. package/dist/cli/{update-7AFQCJ75.mjs → update-D2B7UNFT.mjs} +7 -7
  102. package/dist/cli/{workflow-7EHU5ZPX.js → workflow-6ODTCYXU.js} +15 -15
  103. package/dist/cli/{workflow-ARDO4VHU.mjs → workflow-PQXC2R47.mjs} +5 -5
  104. package/dist/{client-Db1jFLpF.d.ts → client-BcvhDfJJ.d.ts} +80 -58
  105. package/dist/{client-Buv1_ktG.d.mts → client-Z9Pye1Wm.d.mts} +80 -58
  106. package/dist/{compiler-manifest-N77W75Py.d.ts → compiler-manifest-Ycx-hoAr.d.mts} +8 -1
  107. package/dist/{compiler-manifest-N77W75Py.d.mts → compiler-manifest-Ycx-hoAr.d.ts} +8 -1
  108. package/dist/{index-3WOfyVhW.d.mts → index-CZXgiN3E.d.mts} +1 -1
  109. package/dist/{index-CtIJFTCl.d.ts → index-NPG5pqxQ.d.ts} +1 -1
  110. package/dist/index.d.mts +13 -10
  111. package/dist/index.d.ts +13 -10
  112. package/dist/index.js +28 -11
  113. package/dist/index.mjs +25 -8
  114. package/dist/install-integrity.json +86 -84
  115. package/dist/plays/bundle-play-file.d.mts +3 -3
  116. package/dist/plays/bundle-play-file.d.ts +3 -3
  117. package/dist/plays/play-description.d.mts +2 -2
  118. package/dist/plays/play-description.d.ts +2 -2
  119. package/dist/plays/run-request.d.mts +2 -2
  120. package/dist/plays/run-request.d.ts +2 -2
  121. package/dist/release.d.mts +1 -1
  122. package/dist/release.d.ts +1 -1
  123. package/dist/release.js +2 -2
  124. package/dist/release.mjs +1 -1
  125. package/package.json +1 -1
  126. package/dist/cli/auth-K5QAZH42.js +0 -40
  127. package/dist/cli/git-63RYCZSI.js +0 -24
  128. package/dist/cli/search-YAYYU3WD.js +0 -30
  129. package/dist/cli/skills-M2GGHYJU.js +0 -29
  130. package/dist/cli/update-I23NN5QI.js +0 -29
@@ -18598,8 +18598,8 @@ function runLedgerOutboxPrefixClaimSql(
18598
18598
  const lockFence = fence
18599
18599
  ? `current_setting('deepline.run_ledger_outbox_lock', true) = ${escapeLiteral(fence.runId)}`
18600
18600
  : undefined;
18601
- const pending = (alias: string) =>
18602
- `${alias}.delivered_at IS NULL${
18601
+ const pending = (alias: string, primaryKeyLookup = false) =>
18602
+ `${primaryKeyLookup ? `coalesce(${alias}.delivered_at IS NULL, false)` : `${alias}.delivered_at IS NULL`}${
18603
18603
  acknowledgement ? ` AND NOT (${alias}.event_id = ANY($5::text[]))` : ''
18604
18604
  }`;
18605
18605
  // The dispatcher already chose this run. Seek its oldest pending fact
@@ -18628,11 +18628,20 @@ function runLedgerOutboxPrefixClaimSql(
18628
18628
  ? `(head.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents})`
18629
18629
  : 'false';
18630
18630
  const findSearchBlockersOnce = seekRunHead && input.searchOnly === true;
18631
- const searchFactColumnsSql = (alias: string) =>
18631
+ // Only ordinary scoped lifecycle enumeration changes. Its existing limit
18632
+ // bounds candidate keys before the original eligibility/fence predicates;
18633
+ // a frozen terminal in that window retains complete receipt membership.
18634
+ // Carry the locked event type instead of fetching it again by primary key.
18635
+ // Recheck pending/run identity without inviting stale partial-index scans.
18636
+ // Predecessor checks share snapshot metadata; bounded keys own live row access.
18637
+ const inspectLifecycleCandidates = seekRunHead && input.searchOnly !== true;
18638
+ const claimFactColumnsSql = (alias: string) =>
18632
18639
  `${alias}.event_id, ${alias}.run_id, ${alias}.event_type,
18633
18640
  ${alias}.created_at, ${alias}.failed_at, ${alias}.next_attempt_at,
18634
18641
  ${alias}.lease_owner, ${alias}.lease_expires_at,
18635
18642
  ${supportsTerminalBatchMarker ? `${alias}.delivery_batch_started_at` : 'NULL::timestamptz AS delivery_batch_started_at'}`;
18643
+ const lifecycleFactColumnsSql = (alias: string) =>
18644
+ `${claimFactColumnsSql(alias)}, ${alias}.delivered_at`;
18636
18645
  const blockingPredecessorSql = (alias: string) => `(
18637
18646
  (${alias}.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents}
18638
18647
  AND NOT (${ingressPrefixSql}))
@@ -18646,6 +18655,27 @@ function runLedgerOutboxPrefixClaimSql(
18646
18655
  AND ${alias}.lease_owner IS DISTINCT FROM $3::text
18647
18656
  )
18648
18657
  )`;
18658
+ // A modern frozen head cannot cross an unmarked predecessor. A witness in
18659
+ // this snapshot's window therefore blocks every later key, even if a live
18660
+ // candidate is rejected after locking. Keep full membership without that
18661
+ // witness: an all-marked window can refill after a concurrent ACK.
18662
+ const lifecycleRequiresFullMembershipSql = inspectLifecycleCandidates
18663
+ ? `EXISTS (
18664
+ SELECT 1 FROM lifecycle_window AS terminal
18665
+ WHERE terminal.delivery_batch_started_at IS NOT NULL
18666
+ AND terminal.event_type IN (${RUN_EVENT_KIND_SQL_LITERAL.runCompleted}, ${RUN_EVENT_KIND_SQL_LITERAL.runFailed}, ${RUN_EVENT_KIND_SQL_LITERAL.runCancelled})${
18667
+ supportsTerminalBatchMarker && input.allowIngressPrefix === true
18668
+ ? `
18669
+ AND NOT EXISTS (
18670
+ SELECT 1 FROM head AS frozen_head
18671
+ CROSS JOIN lifecycle_window AS unmarked
18672
+ WHERE frozen_head.delivery_batch_started_at IS NOT NULL
18673
+ AND unmarked.delivery_batch_started_at IS NULL
18674
+ )`
18675
+ : ''
18676
+ }
18677
+ )`
18678
+ : 'false';
18649
18679
  return `
18650
18680
  WITH ${
18651
18681
  acknowledgement
@@ -18681,9 +18711,8 @@ function runLedgerOutboxPrefixClaimSql(
18681
18711
  ${findSearchBlockersOnce ? 'candidate.created_at,' : ''}
18682
18712
  ${supportsTerminalBatchMarker ? 'candidate.delivery_batch_started_at' : 'NULL::timestamptz'} AS delivery_batch_started_at
18683
18713
  FROM ${tableName('outbox', options)} AS candidate
18684
- ${seekRunHead ? 'JOIN pending_head ON pending_head.event_id = candidate.event_id' : ''}
18685
- ${input.extendOwnedHead ? 'JOIN owned_run ON owned_run.run_id = candidate.run_id' : ''}
18686
- WHERE ${pending('candidate')}
18714
+ ${seekRunHead ? '' : '\n '}${input.extendOwnedHead ? 'JOIN owned_run ON owned_run.run_id = candidate.run_id' : ''}
18715
+ WHERE ${seekRunHead ? `candidate.event_id = (SELECT event_id FROM pending_head) AND ${pending('candidate')}` : pending('candidate')}
18687
18716
  ${lockFence ? `AND (${lockFence})` : ''}
18688
18717
  ${fence?.expectedHeadEventId ? `AND candidate.event_id = ${escapeLiteral(fence.expectedHeadEventId)}` : ''}
18689
18718
  AND ${searchLaneSql('candidate')} = ${input.searchOnly === true ? 'true' : 'false'}
@@ -18766,14 +18795,16 @@ function runLedgerOutboxPrefixClaimSql(
18766
18795
  ), ${
18767
18796
  findSearchBlockersOnce
18768
18797
  ? `search_prefix AS MATERIALIZED (
18769
- SELECT ${searchFactColumnsSql('pending')}
18798
+ SELECT prefix.* FROM head
18799
+ CROSS JOIN LATERAL (
18800
+ SELECT ${claimFactColumnsSql('pending')}
18770
18801
  FROM ${tableName('outbox', options)} AS pending
18771
- JOIN head ON head.run_id = pending.run_id
18772
- WHERE pending.run_id = $2::text
18802
+ WHERE pending.run_id = head.run_id
18773
18803
  AND ${pending('pending')}
18774
18804
  AND ${searchLaneSql('pending')} = true
18775
18805
  ORDER BY ${runLedgerOrderSql('pending')}
18776
18806
  LIMIT $1
18807
+ ) AS prefix
18777
18808
  ), frozen_search_prefix AS MATERIALIZED (
18778
18809
  SELECT EXISTS (
18779
18810
  SELECT 1 FROM search_prefix AS fact
@@ -18791,7 +18822,7 @@ function runLedgerOutboxPrefixClaimSql(
18791
18822
  -- A frozen terminal receipt can contain marked facts beyond newer
18792
18823
  -- unmarked rows. Retain that full membership scan only for this case;
18793
18824
  -- limiting its raw window would strand an already attempted receipt.
18794
- SELECT ${searchFactColumnsSql('pending')}
18825
+ SELECT ${claimFactColumnsSql('pending')}
18795
18826
  FROM ${tableName('outbox', options)} AS pending
18796
18827
  JOIN head ON head.run_id = pending.run_id
18797
18828
  WHERE (SELECT has_terminal FROM frozen_search_prefix)
@@ -18826,13 +18857,49 @@ function runLedgerOutboxPrefixClaimSql(
18826
18857
  LIMIT 1
18827
18858
  ),`
18828
18859
  : ''
18860
+ }${
18861
+ inspectLifecycleCandidates
18862
+ ? `lifecycle_window AS MATERIALIZED (
18863
+ SELECT prefix.* FROM head
18864
+ CROSS JOIN LATERAL (
18865
+ SELECT ${lifecycleFactColumnsSql('pending')}
18866
+ FROM ${tableName('outbox', options)} AS pending
18867
+ WHERE pending.run_id = head.run_id
18868
+ AND pending.run_id = $2::text
18869
+ AND ${pending('pending')}
18870
+ AND ${searchLaneSql('pending')} = false
18871
+ ORDER BY ${runLedgerOrderSql('pending')}
18872
+ LIMIT $1
18873
+ ) AS prefix
18874
+ ), lifecycle_facts AS MATERIALIZED (
18875
+ SELECT prefix.* FROM lifecycle_window AS prefix
18876
+ WHERE NOT ${lifecycleRequiresFullMembershipSql}
18877
+ UNION ALL
18878
+ SELECT ${lifecycleFactColumnsSql('pending')}
18879
+ FROM ${tableName('outbox', options)} AS pending
18880
+ JOIN head ON head.run_id = pending.run_id
18881
+ WHERE ${lifecycleRequiresFullMembershipSql}
18882
+ AND pending.run_id = $2::text
18883
+ AND ${pending('pending')}
18884
+ AND ${searchLaneSql('pending')} = false
18885
+ ), `
18886
+ : ''
18829
18887
  }candidates AS MATERIALIZED (
18830
- SELECT outbox.event_id
18888
+ ${
18889
+ runId !== null
18890
+ ? `SELECT candidate.event_id${inspectLifecycleCandidates ? ', candidate.event_type' : ''} FROM head
18891
+ CROSS JOIN LATERAL (
18892
+ SELECT outbox.event_id${inspectLifecycleCandidates ? ', outbox.event_type' : ''}
18893
+ FROM ${tableName('outbox', options)} AS outbox
18894
+ WHERE ${pending('outbox', inspectLifecycleCandidates)}
18895
+ AND ${inspectLifecycleCandidates ? 'coalesce(outbox.run_id = head.run_id, false)' : 'outbox.run_id = head.run_id'}`
18896
+ : `SELECT outbox.event_id
18831
18897
  FROM ${tableName('outbox', options)} AS outbox
18832
18898
  JOIN head ON head.run_id = outbox.run_id
18833
18899
  WHERE ${pending('outbox')}
18834
- ${runId !== null ? 'AND outbox.run_id = $2::text' : ''}
18835
- ${findSearchBlockersOnce ? 'AND outbox.event_id = ANY(ARRAY(SELECT event_id FROM search_facts))' : ''}
18900
+ `
18901
+ }
18902
+ ${findSearchBlockersOnce ? 'AND outbox.event_id = ANY(ARRAY(SELECT event_id FROM search_facts))' : ''}${inspectLifecycleCandidates ? '\n AND outbox.event_id = ANY(ARRAY(SELECT event_id FROM lifecycle_facts))' : ''}
18836
18903
  AND ${searchLaneSql('outbox')} = ${input.searchOnly === true ? 'true' : 'false'}
18837
18904
  AND ${outboxNotFailedSql('outbox')}
18838
18905
  -- Admission is causally first and must be projected alone. A later
@@ -18881,8 +18948,8 @@ function runLedgerOutboxPrefixClaimSql(
18881
18948
  )`
18882
18949
  : ` AND NOT EXISTS (
18883
18950
  SELECT 1
18884
- FROM ${tableName('outbox', options)} AS terminal_predecessor
18885
- WHERE terminal_predecessor.run_id = outbox.run_id
18951
+ FROM ${inspectLifecycleCandidates ? 'lifecycle_facts' : tableName('outbox', options)} AS terminal_predecessor
18952
+ WHERE terminal_predecessor.run_id = outbox.run_id${inspectLifecycleCandidates ? '\n AND terminal_predecessor.run_id = $2::text' : ''}
18886
18953
  AND ${pending('terminal_predecessor')}
18887
18954
  AND ${
18888
18955
  supportsTerminalBatchMarker
@@ -18897,16 +18964,16 @@ function runLedgerOutboxPrefixClaimSql(
18897
18964
  AND terminal_predecessor.event_type IN (
18898
18965
  ${RUN_EVENT_KIND_SQL_LITERAL.runCompleted}, ${RUN_EVENT_KIND_SQL_LITERAL.runFailed}, ${RUN_EVENT_KIND_SQL_LITERAL.runCancelled}
18899
18966
  )
18900
- AND ${runLedgerPrecedesSql('terminal_predecessor', 'outbox', false, input.searchOnly === true)}
18967
+ AND ${inspectLifecycleCandidates ? `${runLedgerPositionSql('terminal_predecessor')} < ${runLedgerPositionSql('outbox')}` : runLedgerPrecedesSql('terminal_predecessor', 'outbox', false, input.searchOnly === true)}
18901
18968
  )
18902
18969
  -- Claim only the contiguous due prefix. A delayed, leased, or failed
18903
18970
  -- predecessor retains ownership of everything that follows it.
18904
18971
  AND NOT EXISTS (
18905
18972
  SELECT 1
18906
- FROM ${tableName('outbox', options)} AS predecessor
18907
- WHERE predecessor.run_id = outbox.run_id
18973
+ FROM ${inspectLifecycleCandidates ? 'lifecycle_facts' : tableName('outbox', options)} AS predecessor
18974
+ WHERE predecessor.run_id = outbox.run_id${inspectLifecycleCandidates ? '\n AND predecessor.run_id = $2::text' : ''}
18908
18975
  AND ${pending('predecessor')}
18909
- AND ${runLedgerPrecedesSql('predecessor', 'outbox', false, input.searchOnly === true)}
18976
+ AND ${inspectLifecycleCandidates ? `${runLedgerPositionSql('predecessor')} < ${runLedgerPositionSql('outbox')}` : runLedgerPrecedesSql('predecessor', 'outbox', false, input.searchOnly === true)}
18910
18977
  AND ${blockingPredecessorSql('predecessor')}
18911
18978
  )
18912
18979
  `
@@ -18914,14 +18981,18 @@ function runLedgerOutboxPrefixClaimSql(
18914
18981
  ORDER BY ${runLedgerOrderSql('outbox')}
18915
18982
  FOR UPDATE OF outbox
18916
18983
  LIMIT $1
18917
- ), terminal_batch AS (
18984
+ ${runId !== null ? ' ) AS candidate\n ' : ''}), ${
18985
+ inspectLifecycleCandidates
18986
+ ? ''
18987
+ : `terminal_batch AS (
18918
18988
  SELECT EXISTS (
18919
18989
  SELECT 1
18920
18990
  FROM ${tableName('outbox', options)} AS candidate
18921
18991
  JOIN candidates ON candidates.event_id = candidate.event_id
18922
18992
  WHERE candidate.event_type IN (${RUN_EVENT_KIND_SQL_LITERAL.runCompleted}, ${RUN_EVENT_KIND_SQL_LITERAL.runFailed}, ${RUN_EVENT_KIND_SQL_LITERAL.runCancelled})
18923
18993
  ) AS has_terminal
18924
- ), claimed AS (
18994
+ ), `
18995
+ }claimed AS (
18925
18996
  UPDATE ${tableName('outbox', options)} outbox
18926
18997
  SET lease_owner = $3,
18927
18998
  lease_expires_at = CASE
@@ -18931,14 +19002,14 @@ function runLedgerOutboxPrefixClaimSql(
18931
19002
  ${
18932
19003
  supportsTerminalBatchMarker
18933
19004
  ? `, delivery_batch_started_at = CASE
18934
- WHEN terminal_batch.has_terminal ${input.allowIngressPrefix === true ? `OR ${urgentLifecyclePendingSql('outbox')} OR EXISTS (SELECT 1 FROM head WHERE head.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents})` : ''}
19005
+ WHEN ${inspectLifecycleCandidates ? `EXISTS (SELECT 1 FROM candidates AS terminal_candidate WHERE terminal_candidate.event_type IN (${RUN_EVENT_KIND_SQL_LITERAL.runCompleted}, ${RUN_EVENT_KIND_SQL_LITERAL.runFailed}, ${RUN_EVENT_KIND_SQL_LITERAL.runCancelled}))` : 'terminal_batch.has_terminal'} ${input.allowIngressPrefix === true ? `OR ${urgentLifecyclePendingSql('outbox')} OR EXISTS (SELECT 1 FROM head WHERE head.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents})` : ''}
18935
19006
  THEN COALESCE(outbox.delivery_batch_started_at, statement_timestamp())
18936
19007
  ELSE outbox.delivery_batch_started_at
18937
19008
  END`
18938
19009
  : ''
18939
19010
  }
18940
19011
  FROM candidates
18941
- CROSS JOIN terminal_batch
19012
+ ${inspectLifecycleCandidates ? '' : 'CROSS JOIN terminal_batch'}
18942
19013
  WHERE outbox.event_id = candidates.event_id
18943
19014
  RETURNING outbox.event_id, outbox.run_id, outbox.event_type,
18944
19015
  outbox.payload_json, outbox.created_at, outbox.lease_owner,
@@ -19002,9 +19073,34 @@ function runLedgerOutboxPrefixClaimBatchSql(input: {
19002
19073
  lockStrength?: 'no_key_update';
19003
19074
  transportHeadSql?: string;
19004
19075
  }): string {
19005
- const encoded = escapeLiteral(JSON.stringify(input.params));
19076
+ // Ordinary claims have four bounded primitive arguments. Give PostgreSQL
19077
+ // constants instead of a scalar InitPlan for every repeated argument. Keep
19078
+ // the JSON renderer for ACK arrays, transport/extension claims and values
19079
+ // whose existing JSON conversion or cast failure must remain unchanged.
19080
+ const directScalars =
19081
+ input.params.length === 4 &&
19082
+ !input.transportHeadSql &&
19083
+ input.params.every((value, index) =>
19084
+ index === 0 || index === 3
19085
+ ? typeof value === 'number' &&
19086
+ Number.isInteger(value) &&
19087
+ value >= -2_147_483_648 &&
19088
+ value <= 2_147_483_647
19089
+ : value === null ||
19090
+ (typeof value === 'string' &&
19091
+ /^(?:[\u0001-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF])*$/.test(
19092
+ value,
19093
+ )),
19094
+ );
19095
+ const encoded = directScalars
19096
+ ? undefined
19097
+ : escapeLiteral(JSON.stringify(input.params));
19006
19098
  const parameter = (index: number) => {
19007
19099
  const value = input.params[index - 1];
19100
+ if (directScalars) {
19101
+ const type = typeof value === 'number' ? 'integer' : 'text';
19102
+ return `(${value === null ? 'NULL' : escapeLiteral(String(value))}::${type})`;
19103
+ }
19008
19104
  if (Array.isArray(value)) {
19009
19105
  return `(SELECT ARRAY(SELECT jsonb_array_elements_text(values_json->${index - 1})) FROM run_ledger_parameters)`;
19010
19106
  }
@@ -19022,9 +19118,11 @@ function runLedgerOutboxPrefixClaimBatchSql(input: {
19022
19118
  (match, index: string | undefined) =>
19023
19119
  index ? parameter(Number(index)) : match,
19024
19120
  )
19025
- .replace(
19026
- /^\s*WITH\s/,
19027
- `WITH run_ledger_parameters AS MATERIALIZED (SELECT ${encoded}::jsonb AS values_json), `,
19121
+ // Use a callback so replacement metacharacters inside generated IDs stay literal.
19122
+ .replace(/^\s*WITH\s/, (match) =>
19123
+ directScalars
19124
+ ? match
19125
+ : `WITH run_ledger_parameters AS MATERIALIZED (SELECT ${encoded}::jsonb AS values_json), `,
19028
19126
  );
19029
19127
  return `BEGIN;
19030
19128
  SELECT set_config('lock_timeout', '${RUNTIME_SCHEDULER_CANCEL_LOCK_TIMEOUT_MS}ms', true),
@@ -19053,6 +19151,8 @@ async function claimRunLedgerOutboxPrefixInBatch(
19053
19151
  expectedHeadEventId?: string;
19054
19152
  lockStrength?: 'no_key_update';
19055
19153
  transportCandidate?: RunLedgerTransportCandidate;
19154
+ /** Discover the zero-effect transport head under this transaction's run lock. */
19155
+ discoverTransportHead?: boolean;
19056
19156
  recoverTransportDelivery?: boolean;
19057
19157
  },
19058
19158
  options?: Pick<PostgresSchedulerOptions, 'schema'>,
@@ -19093,8 +19193,22 @@ async function claimRunLedgerOutboxPrefixInBatch(
19093
19193
  // run/head locks a never-leased, never-frozen carrier may be acknowledged
19094
19194
  // locally before the next READ COMMITTED statement claims its successor.
19095
19195
  // Keep the successor's existing run.events-first receipt shape unchanged.
19196
+ const recoverTransportDelivery = input.recoverTransportDelivery === true;
19197
+ // An ACK and successor claim commit in the same transaction. For a discovered
19198
+ // carrier whose response was lost, xmin plus the still-live successor owner
19199
+ // proves exactly which delivery consumed this drain's allowance.
19200
+ const ownedTransportSql = (alias: string) => `
19201
+ to_jsonb(${alias})->>'delivery_batch_started_at' IS NULL AND EXISTS (
19202
+ SELECT 1 FROM ${tableName('outbox', options)} AS successor
19203
+ WHERE successor.run_id = ${alias}.run_id AND successor.delivered_at IS NULL
19204
+ AND successor.lease_owner = ${escapeLiteral(leaseOwner!)}
19205
+ AND successor.lease_expires_at > clock_timestamp()
19206
+ AND successor.xmin = ${alias}.xmin
19207
+ AND NOT ${searchLaneSql('successor')}
19208
+ )`;
19096
19209
  const transportHeadSql =
19097
- input.transportCandidate !== undefined &&
19210
+ (input.transportCandidate !== undefined ||
19211
+ input.discoverTransportHead === true) &&
19098
19212
  input.allowIngressPrefix === true &&
19099
19213
  !input.searchOnly &&
19100
19214
  !input.extendOwnedHead &&
@@ -19112,8 +19226,12 @@ async function claimRunLedgerOutboxPrefixInBatch(
19112
19226
  ), eligible_transport_head AS MATERIALIZED (
19113
19227
  SELECT head.* FROM transport_head AS head
19114
19228
  WHERE current_setting('deepline.run_ledger_outbox_lock', true) = ${escapeLiteral(input.runId)}
19115
- AND head.event_id = ${escapeLiteral(input.transportCandidate!.eventId)}
19116
- AND head.delivery_key = ${escapeLiteral(input.transportCandidate!.deliveryKey)}
19229
+ ${
19230
+ input.transportCandidate
19231
+ ? `AND head.event_id = ${escapeLiteral(input.transportCandidate.eventId)}
19232
+ AND head.delivery_key = ${escapeLiteral(input.transportCandidate.deliveryKey)}`
19233
+ : ''
19234
+ }
19117
19235
  AND ${runLedgerZeroEffectTransportSql('head')}
19118
19236
  AND ${runLedgerTerminalPendingSql('head', options)}
19119
19237
  AND EXISTS (
@@ -19142,24 +19260,22 @@ async function claimRunLedgerOutboxPrefixInBatch(
19142
19260
  escapeLiteral(input.runId),
19143
19261
  )}
19144
19262
  )${
19145
- input.recoverTransportDelivery === true
19263
+ recoverTransportDelivery
19146
19264
  ? `, prior_transport AS MATERIALIZED (
19147
19265
  SELECT prior.event_id, prior.run_id, prior.event_type, prior.delivery_key,
19148
19266
  (extract(epoch FROM (prior.delivered_at-prior.created_at))*1000)::float8 AS lag_ms,
19149
- to_jsonb(prior)->>'delivery_batch_started_at' IS NULL AND EXISTS (
19150
- SELECT 1 FROM ${tableName('outbox', options)} AS successor
19151
- WHERE successor.run_id = prior.run_id AND successor.delivered_at IS NULL
19152
- AND successor.lease_owner = ${escapeLiteral(leaseOwner!)}
19153
- AND successor.lease_expires_at > clock_timestamp()
19154
- AND successor.xmin = prior.xmin
19155
- AND NOT ${searchLaneSql('successor')}
19156
- ) AS owned
19267
+ ${ownedTransportSql('prior')} AS owned
19157
19268
  FROM ${tableName('outbox', options)} AS prior
19158
19269
  WHERE current_setting('deepline.run_ledger_outbox_lock', true) = ${escapeLiteral(input.runId)}
19159
19270
  AND prior.run_id = ${escapeLiteral(input.runId)}
19160
- AND prior.event_id = ${escapeLiteral(input.transportCandidate!.eventId)}
19161
- AND prior.delivery_key = ${escapeLiteral(input.transportCandidate!.deliveryKey)}
19162
- AND prior.event_type = ${escapeLiteral(input.transportCandidate!.eventType)}
19271
+ ${
19272
+ input.transportCandidate
19273
+ ? `AND prior.event_id = ${escapeLiteral(input.transportCandidate.eventId)}
19274
+ AND prior.delivery_key = ${escapeLiteral(input.transportCandidate.deliveryKey)}
19275
+ AND prior.event_type = ${escapeLiteral(input.transportCandidate.eventType)}`
19276
+ : `AND ${runLedgerZeroEffectTransportSql('prior')}
19277
+ AND ${ownedTransportSql('prior')}`
19278
+ }
19163
19279
  AND prior.delivered_at IS NOT NULL
19164
19280
  AND NOT EXISTS (SELECT 1 FROM delivered)
19165
19281
  )`
@@ -19168,7 +19284,7 @@ async function claimRunLedgerOutboxPrefixInBatch(
19168
19284
  SELECT delivered.event_id, head.run_id, delivered.event_type, head.delivery_key, delivered.lag_ms
19169
19285
  FROM delivered JOIN eligible_transport_head AS head ON head.event_id = delivered.event_id
19170
19286
  ${
19171
- input.recoverTransportDelivery === true
19287
+ recoverTransportDelivery
19172
19288
  ? `UNION ALL
19173
19289
  SELECT event_id,run_id,event_type,delivery_key,lag_ms FROM prior_transport WHERE owned`
19174
19290
  : ''
@@ -19185,13 +19301,28 @@ async function claimRunLedgerOutboxPrefixInBatch(
19185
19301
  json_build_object('eventId', delivered.event_id, 'kind', 'outbox_delivered')::text)::text
19186
19302
  FROM transport_deliveries AS delivered
19187
19303
  ${
19188
- input.recoverTransportDelivery === true
19304
+ recoverTransportDelivery
19189
19305
  ? `UNION ALL
19190
19306
  SELECT 'transport_unconfirmed'::text,event_id,run_id,event_type,NULL::jsonb,NULL::timestamptz,
19191
19307
  NULL::text,delivery_key,lag_ms,false,NULL::float8,NULL::text,NULL::text
19192
19308
  FROM prior_transport WHERE NOT owned`
19193
19309
  : ''
19194
- }`
19310
+ }` +
19311
+ (recoverTransportDelivery && !input.transportCandidate
19312
+ ? `
19313
+ UNION ALL
19314
+ SELECT 'transport_unconfirmed'::text,pending.event_id,pending.run_id,pending.event_type,NULL::jsonb,NULL::timestamptz,
19315
+ NULL::text,pending.delivery_key,0::float8,false,NULL::float8,NULL::text,NULL::text
19316
+ FROM ${tableName('outbox', options)} AS pending
19317
+ WHERE current_setting('deepline.run_ledger_outbox_lock', true) = ${escapeLiteral(input.runId)}
19318
+ AND pending.run_id = ${escapeLiteral(input.runId)} AND pending.delivered_at IS NULL
19319
+ AND pending.lease_owner = ${escapeLiteral(leaseOwner!)}
19320
+ AND NOT ${searchLaneSql('pending')}
19321
+ AND NOT EXISTS (SELECT 1 FROM transport_deliveries)
19322
+ -- A renewal may have replaced the transaction proof. Hand back the
19323
+ -- prefix instead of guessing whether a carrier spent its allowance.
19324
+ `
19325
+ : '')
19195
19326
  : undefined;
19196
19327
  let result: QueryResult<RunLedgerOutboxPrefixClaimRow>;
19197
19328
  try {
@@ -19992,8 +20123,9 @@ export async function markPostgresSchedulerOutboxDelivered(
19992
20123
 
19993
20124
  /**
19994
20125
  * Shared lease-fenced ACK, including the canonical retained-payload cleanup.
19995
- * Known-run callers keep that scope visible to the planner: a materialized ID
19996
- * array alone can make stale pending-index statistics favor a cross-run scan.
20126
+ * Known-run callers recheck scope and pending state without offering a second
20127
+ * index access path beside their exact IDs. Stale statistics otherwise favor a
20128
+ * full run bitmap or pending partial-index scan before filtering those IDs.
19997
20129
  */
19998
20130
  function runLedgerAcknowledgeSql(
19999
20131
  options: Pick<PostgresSchedulerOptions, 'schema'> | undefined,
@@ -20014,9 +20146,9 @@ function runLedgerAcknowledgeSql(
20014
20146
  AND run.run_event_store = 'planet_scale'
20015
20147
  ) THEN '{}'::jsonb ELSE outbox.payload_json END
20016
20148
  WHERE outbox.event_id = ANY(${eventIdsParameter}::text[])
20017
- ${runIdParameter ? `AND outbox.run_id = ${runIdParameter}::text` : ''}
20149
+ ${runIdParameter ? `AND coalesce(outbox.run_id = ${runIdParameter}::text, false)` : ''}
20018
20150
  ${lockFence ? `AND (${lockFence})` : ''}
20019
- AND outbox.delivered_at IS NULL
20151
+ AND ${runIdParameter ? 'coalesce(outbox.delivered_at IS NULL, false)' : 'outbox.delivered_at IS NULL'}
20020
20152
  AND (${leaseOwnerParameter}::text IS NULL OR outbox.lease_owner = ${leaseOwnerParameter})
20021
20153
  RETURNING outbox.event_id,
20022
20154
  outbox.event_type,
@@ -20587,6 +20719,12 @@ export type RunLedgerOutboxDispatchInput = {
20587
20719
  * explicit context as before.
20588
20720
  */
20589
20721
  runtimeApi?: WorkerRuntimeApiContext | null;
20722
+ /**
20723
+ * Immutable launch already held by a terminal producer. Reuse requires the
20724
+ * same run and the existing qualified projection token; claims and receiver
20725
+ * ownership proofs still read durable state. Other dispatches read SQL.
20726
+ */
20727
+ dispatchLaunch?: RunLedgerDispatchLaunch;
20590
20728
  limit?: number;
20591
20729
  runId?: string | null;
20592
20730
  leaseOwner?: string | null;
@@ -21160,19 +21298,38 @@ async function dispatchRunLedgerOutboxBatchWithScope(
21160
21298
  )
21161
21299
  return null;
21162
21300
  const targetRunId = input.runId?.trim() || null;
21301
+ const producerLaunch =
21302
+ terminalRunId === targetRunId &&
21303
+ !input.headEventId &&
21304
+ tokenAuthority === 'gateway' &&
21305
+ input.dispatchLaunch?.runId === targetRunId &&
21306
+ usableRunLedgerExecutorToken(input.dispatchLaunch, reuseMarginMs, options)
21307
+ ?.runLedgerIngressPrefixBatching === true
21308
+ ? input.dispatchLaunch
21309
+ : null;
21163
21310
  const selected =
21164
21311
  selectedFastRun ??
21165
- (input.waitForRunLock && targetRunId
21166
- ? await client.query<{
21167
- run_id: string;
21168
- dispatch_launch_json: unknown;
21169
- transport_head?: RunLedgerTransportCandidate | null;
21170
- }>(
21171
- `SELECT runs.run_id, ${needsLaunch ? runLedgerDispatchLaunchSql('runs') : 'NULL::jsonb'} AS dispatch_launch_json, ${transportHeadSelection} AS transport_head
21312
+ (producerLaunch
21313
+ ? {
21314
+ rows: [
21315
+ {
21316
+ run_id: producerLaunch.runId,
21317
+ dispatch_launch_json: producerLaunch,
21318
+ transport_head: undefined,
21319
+ },
21320
+ ],
21321
+ }
21322
+ : input.waitForRunLock && targetRunId
21323
+ ? await client.query<{
21324
+ run_id: string;
21325
+ dispatch_launch_json: unknown;
21326
+ transport_head?: RunLedgerTransportCandidate | null;
21327
+ }>(
21328
+ `SELECT runs.run_id, ${needsLaunch ? runLedgerDispatchLaunchSql('runs') : 'NULL::jsonb'} AS dispatch_launch_json, ${transportHeadSelection} AS transport_head
21172
21329
  FROM ${tableName('runs', options)} AS runs WHERE runs.run_id = $1`,
21173
- [targetRunId],
21174
- )
21175
- : await selectRunForClaim(client, targetRunId));
21330
+ [targetRunId],
21331
+ )
21332
+ : await selectRunForClaim(client, targetRunId));
21176
21333
  const runId = selected.rows[0]?.run_id;
21177
21334
  if (!runId)
21178
21335
  return {
@@ -21201,6 +21358,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
21201
21358
  !input.headEventId && ingressPrefixClaimed
21202
21359
  ? (selected.rows[0]?.transport_head ?? undefined)
21203
21360
  : undefined,
21361
+ discoverTransportHead: producerLaunch !== null && ingressPrefixClaimed,
21204
21362
  recoverTransportDelivery: claimInvocations > 1,
21205
21363
  },
21206
21364
  options,
@@ -21393,6 +21551,14 @@ async function dispatchRunLedgerOutboxBatchWithScope(
21393
21551
  }
21394
21552
  }
21395
21553
  let events = claimed.events;
21554
+ const searchOnlyTerminalLogCarrier =
21555
+ input.searchOnly === true &&
21556
+ events.some(
21557
+ (event) =>
21558
+ event.eventType === RUN_SCHEDULER_OUTBOX_EVENT_TYPE.runnerLogs &&
21559
+ (event.eventId.startsWith('runner-terminal-logs:') ||
21560
+ event.eventId.startsWith('terminal-log-chunk:')),
21561
+ );
21396
21562
  const unconfirmedTransportError = claimed.transportOwnershipUnconfirmed
21397
21563
  ? new RunLedgerProjectionLeaseLostError('delivery_lease_not_current')
21398
21564
  : null;
@@ -21462,6 +21628,10 @@ async function dispatchRunLedgerOutboxBatchWithScope(
21462
21628
  const appendAttempt: { transportAttemptId: string | null } = {
21463
21629
  transportAttemptId: null,
21464
21630
  };
21631
+ // Fixed-shape diagnostic timings for the search-only terminal-log carrier.
21632
+ // These are process-local observations and never enter durable run state.
21633
+ let terminalLogMaterializeTransactionCommitMs: number | null = null;
21634
+ let terminalLogAcknowledgeMs: number | null = null;
21465
21635
  const callerOnRequestAttempt = input.runtimeApi?.onRequestAttempt;
21466
21636
  const materializeDeferredObservability = async () => {
21467
21637
  if (
@@ -21520,6 +21690,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
21520
21690
  },
21521
21691
  ),
21522
21692
  );
21693
+ const materializeStartedAtMs = performance.now();
21523
21694
  const checkoutStartedAtMs = performance.now();
21524
21695
  let materializeEnteredAtMs: number | null = null;
21525
21696
  try {
@@ -21580,6 +21751,14 @@ async function dispatchRunLedgerOutboxBatchWithScope(
21580
21751
  (searchPhaseTimingsMs.materializeAcquireAndRetry ?? 0) +
21581
21752
  (materializeEnteredAtMs ?? performance.now()) -
21582
21753
  checkoutStartedAtMs;
21754
+ if (searchOnlyTerminalLogCarrier) {
21755
+ const elapsedMs = Math.max(
21756
+ 0,
21757
+ performance.now() - materializeStartedAtMs,
21758
+ );
21759
+ terminalLogMaterializeTransactionCommitMs =
21760
+ (terminalLogMaterializeTransactionCommitMs ?? 0) + elapsedMs;
21761
+ }
21583
21762
  }
21584
21763
  };
21585
21764
  try {
@@ -21642,20 +21821,31 @@ async function dispatchRunLedgerOutboxBatchWithScope(
21642
21821
  )
21643
21822
  )
21644
21823
  throw new Error('Search lease includes a lifecycle fact.');
21645
- const delivered = await observeSearchPhase('acknowledge', () =>
21646
- withClient(
21647
- (client) =>
21648
- markPostgresSchedulerOutboxDeliveredRows(
21649
- client,
21650
- events.map((event) => event.eventId),
21651
- { ...options, leaseOwner },
21652
- ),
21653
- {
21654
- runId: events[0]!.runId,
21655
- phase: 'run_ledger_outbox_search_acknowledge',
21656
- },
21657
- ),
21658
- );
21824
+ const acknowledgeStartedAtMs = performance.now();
21825
+ let delivered: RunLedgerOutboxDeliveredRow[];
21826
+ try {
21827
+ delivered = await observeSearchPhase('acknowledge', () =>
21828
+ withClient(
21829
+ (client) =>
21830
+ markPostgresSchedulerOutboxDeliveredRows(
21831
+ client,
21832
+ events.map((event) => event.eventId),
21833
+ { ...options, leaseOwner },
21834
+ ),
21835
+ {
21836
+ runId: events[0]!.runId,
21837
+ phase: 'run_ledger_outbox_search_acknowledge',
21838
+ },
21839
+ ),
21840
+ );
21841
+ } finally {
21842
+ if (searchOnlyTerminalLogCarrier) {
21843
+ terminalLogAcknowledgeMs = Math.max(
21844
+ 0,
21845
+ performance.now() - acknowledgeStartedAtMs,
21846
+ );
21847
+ }
21848
+ }
21659
21849
  if (delivered.length !== events.length)
21660
21850
  throw new RunLedgerProjectionLeaseLostError(
21661
21851
  'delivery_lease_not_current',
@@ -22382,6 +22572,18 @@ async function dispatchRunLedgerOutboxBatchWithScope(
22382
22572
  continuationMs:
22383
22573
  acknowledgedAtMs === null ? null : settledAtMs - acknowledgedAtMs,
22384
22574
  durationMs: settledAtMs - dispatchStartedAtMs,
22575
+ ...(searchOnlyTerminalLogCarrier
22576
+ ? {
22577
+ // Keep this fixed-shape scalar packet on the existing diagnostic;
22578
+ // no per-event payload, rows, or durable fields are added.
22579
+ searchOnlyTerminalLogPhaseTimingsMs: {
22580
+ claim: Math.max(0, claimElapsedMs),
22581
+ materializeTransactionCommit:
22582
+ terminalLogMaterializeTransactionCommitMs,
22583
+ acknowledge: terminalLogAcknowledgeMs,
22584
+ },
22585
+ }
22586
+ : {}),
22385
22587
  ...(input.searchOnly ? { searchPhaseTimingsMs } : {}),
22386
22588
  // Which platform requests served the two app hops, so a slow
22387
22589
  // authority or append stage can be found in the app's request log.
@@ -119,6 +119,21 @@ export type RunLedgerOutboxRecoveryDeps = {
119
119
  logger?: RunLedgerOutboxRecoveryLogger;
120
120
  };
121
121
 
122
+ /**
123
+ * Production runs two projector replicas at eight deliveries each. An
124
+ * isolated Preview estate has one replica, so use the existing bounded
125
+ * 32-delivery ceiling there to keep fixture admission and its catalog
126
+ * projection inside the same latency budget. This does not change Production
127
+ * capacity or the controller's hard maximum.
128
+ */
129
+ export function runLedgerOutboxRecoveryParallelism(
130
+ environment: 'preview' | 'production',
131
+ ): number {
132
+ return environment === 'preview'
133
+ ? RUN_LEDGER_OUTBOX_RECOVERY_MAX_IN_FLIGHT
134
+ : RUN_LEDGER_OUTBOX_RECOVERY_PRODUCTION_IN_FLIGHT;
135
+ }
136
+
122
137
  export type RunLedgerOutboxRecoveryController = {
123
138
  /**
124
139
  * Ask the singleton projector to re-read durable outbox work. This is
@@ -1011,6 +1026,7 @@ export async function deliverRunCreatedOutboxEventInline(input: {
1011
1026
  export function startRunLedgerOutboxRecoveryController(input: {
1012
1027
  poolOptions: RuntimeSchedulerPoolOptions;
1013
1028
  schedulerOptions?: Pick<PostgresSchedulerOptions, 'schema'>;
1029
+ environment?: 'preview' | 'production';
1014
1030
  /** Direct LISTEN is a latency hint and may be disabled for isolated schemas. */
1015
1031
  useDirectNotify?: boolean;
1016
1032
  /** Observation hook for acknowledged rows (lag metrics). */
@@ -1071,10 +1087,12 @@ export function startRunLedgerOutboxRecoveryController(input: {
1071
1087
  dispatchObservabilityOnce: (runId) => dispatch('oldest_ready', true, runId),
1072
1088
  observabilityParallelism: RUN_LEDGER_OUTBOX_RECOVERY_INDEX_IN_FLIGHT,
1073
1089
  // `dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope` releases each
1074
- // short scheduler checkout before it calls the Vercel gateway. The two
1075
- // replicas therefore drain up to sixteen independent runs concurrently
1076
- // without turning one outbox notification into sixty-four head scans.
1077
- parallelism: RUN_LEDGER_OUTBOX_RECOVERY_PRODUCTION_IN_FLIGHT,
1090
+ // short scheduler checkout before it calls the Vercel gateway. Production
1091
+ // retains two replicas at eight slots each; one isolated Preview replica
1092
+ // uses the same controller's existing hard ceiling of 32.
1093
+ parallelism: runLedgerOutboxRecoveryParallelism(
1094
+ input.environment ?? 'production',
1095
+ ),
1078
1096
  notifyUnavailableSafetyWakeMs: runLedgerOutboxNotifySafetyWakeMs(
1079
1097
  schedulerOptions.schema,
1080
1098
  ),