@rudderhq/server 0.2.0-canary.11 → 0.2.0-canary.13

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 (98) hide show
  1. package/dist/bundled-plugins/plugin-linear/dist/worker.js +2 -1
  2. package/dist/bundled-plugins/plugin-linear/dist/worker.js.map +2 -2
  3. package/dist/onboarding-assets/ceo/HEARTBEAT.md +7 -3
  4. package/dist/onboarding-assets/default/HEARTBEAT.md +6 -3
  5. package/dist/routes/agents.d.ts.map +1 -1
  6. package/dist/routes/agents.js +18 -2
  7. package/dist/routes/agents.js.map +1 -1
  8. package/dist/routes/issues.d.ts.map +1 -1
  9. package/dist/routes/issues.js +55 -5
  10. package/dist/routes/issues.js.map +1 -1
  11. package/dist/services/issue-review-wakeup.d.ts +48 -0
  12. package/dist/services/issue-review-wakeup.d.ts.map +1 -1
  13. package/dist/services/issue-review-wakeup.js +34 -1
  14. package/dist/services/issue-review-wakeup.js.map +1 -1
  15. package/dist/services/runtime-kernel/heartbeat.d.ts.map +1 -1
  16. package/dist/services/runtime-kernel/heartbeat.js +174 -1
  17. package/dist/services/runtime-kernel/heartbeat.js.map +1 -1
  18. package/package.json +13 -13
  19. package/resources/bundled-skills/rudder/SKILL.md +44 -2
  20. package/resources/bundled-skills/rudder/references/cli-reference.md +13 -1
  21. package/skills/rudder/SKILL.md +44 -2
  22. package/skills/rudder/references/cli-reference.md +13 -1
  23. package/ui-dist/assets/{_basePickBy-BSNuB0Qp.js → _basePickBy-Dqxp5nRU.js} +1 -1
  24. package/ui-dist/assets/{_baseUniq-DMFGLRzA.js → _baseUniq-D5cgIII0.js} +1 -1
  25. package/ui-dist/assets/{arc-BjVgvVH1.js → arc-H6KIKqlX.js} +1 -1
  26. package/ui-dist/assets/{architectureDiagram-2XIMDMQ5-CB7zCznq.js → architectureDiagram-2XIMDMQ5-VJn3ZDRh.js} +1 -1
  27. package/ui-dist/assets/{blockDiagram-WCTKOSBZ-C3jem7km.js → blockDiagram-WCTKOSBZ-BUaBtfrU.js} +1 -1
  28. package/ui-dist/assets/{c4Diagram-IC4MRINW-rY-MmiZ9.js → c4Diagram-IC4MRINW-CQApT9vP.js} +1 -1
  29. package/ui-dist/assets/channel-DPsIluDp.js +1 -0
  30. package/ui-dist/assets/{chunk-4BX2VUAB-DQVWgTb2.js → chunk-4BX2VUAB-BBObn37o.js} +1 -1
  31. package/ui-dist/assets/{chunk-55IACEB6-D8lLaAAs.js → chunk-55IACEB6-fRrcrqVQ.js} +1 -1
  32. package/ui-dist/assets/{chunk-FMBD7UC4-xSoWBh6D.js → chunk-FMBD7UC4-CC_JE5Yt.js} +1 -1
  33. package/ui-dist/assets/{chunk-JSJVCQXG-BmLCRZwF.js → chunk-JSJVCQXG-BICuo1Ro.js} +1 -1
  34. package/ui-dist/assets/{chunk-KX2RTZJC-m6CRN7qF.js → chunk-KX2RTZJC-Be3LkPd0.js} +1 -1
  35. package/ui-dist/assets/{chunk-NQ4KR5QH-Ret0vCZK.js → chunk-NQ4KR5QH-Dur-iQYf.js} +1 -1
  36. package/ui-dist/assets/{chunk-QZHKN3VN-DoZpzc7A.js → chunk-QZHKN3VN-D4i79fbz.js} +1 -1
  37. package/ui-dist/assets/{chunk-WL4C6EOR-DWl8Gr_C.js → chunk-WL4C6EOR-Go0XnAaW.js} +1 -1
  38. package/ui-dist/assets/classDiagram-VBA2DB6C-1mGg2M-S.js +1 -0
  39. package/ui-dist/assets/classDiagram-v2-RAHNMMFH-1mGg2M-S.js +1 -0
  40. package/ui-dist/assets/clone-CN9aOgYl.js +1 -0
  41. package/ui-dist/assets/{cose-bilkent-S5V4N54A-m7cOeeMV.js → cose-bilkent-S5V4N54A-Dz_Kbgg2.js} +1 -1
  42. package/ui-dist/assets/{dagre-KLK3FWXG-C5JRz37p.js → dagre-KLK3FWXG-B-AQgng0.js} +1 -1
  43. package/ui-dist/assets/{diagram-E7M64L7V-Dn8iO_Xc.js → diagram-E7M64L7V-a9BLIZwB.js} +1 -1
  44. package/ui-dist/assets/{diagram-IFDJBPK2-CXMHnflP.js → diagram-IFDJBPK2-CvZXFIGJ.js} +1 -1
  45. package/ui-dist/assets/{diagram-P4PSJMXO-CDW1Fld1.js → diagram-P4PSJMXO-C1N1vrCa.js} +1 -1
  46. package/ui-dist/assets/{erDiagram-INFDFZHY-BZS07AxY.js → erDiagram-INFDFZHY-CyXQGMlP.js} +1 -1
  47. package/ui-dist/assets/{flowDiagram-PKNHOUZH-C7aHSfB2.js → flowDiagram-PKNHOUZH-BBpgi6a0.js} +1 -1
  48. package/ui-dist/assets/{ganttDiagram-A5KZAMGK-D3-g8xZO.js → ganttDiagram-A5KZAMGK-5ceIuqjD.js} +1 -1
  49. package/ui-dist/assets/{gitGraphDiagram-K3NZZRJ6-Ce3lsV5J.js → gitGraphDiagram-K3NZZRJ6-DPX1bfNe.js} +1 -1
  50. package/ui-dist/assets/{graph-BSQA2Tac.js → graph--rDszzOT.js} +1 -1
  51. package/ui-dist/assets/{index-BG6W8rES.js → index-2lLnZmyi.js} +1 -1
  52. package/ui-dist/assets/{index-Bnhpm8_1.js → index-7otV2D3a.js} +1 -1
  53. package/ui-dist/assets/{index-DpRC5_-h.js → index-ByxDA0Uk.js} +1 -1
  54. package/ui-dist/assets/{index-DwwIwrNb.js → index-CB9M9iep.js} +1 -1
  55. package/ui-dist/assets/{index-Cnnr67j2.js → index-COOKxTn-.js} +1 -1
  56. package/ui-dist/assets/{index-BvpKZHFa.js → index-CY6mG5Z-.js} +1 -1
  57. package/ui-dist/assets/{index-BL-hv0ZJ.js → index-CgCzNc16.js} +1 -1
  58. package/ui-dist/assets/{index-ClP3hVxI.js → index-CgOJ6ByG.js} +1 -1
  59. package/ui-dist/assets/{index-DsBDXRQ6.js → index-CoiBmREY.js} +1 -1
  60. package/ui-dist/assets/{index-B0IIWpAF.js → index-CxODMF-x.js} +1 -1
  61. package/ui-dist/assets/{index-BonMTgRY.js → index-D18VJfzf.js} +1 -1
  62. package/ui-dist/assets/{index-CoiSCzpg.js → index-D5r2B9Og.js} +1 -1
  63. package/ui-dist/assets/{index-CiJEn3BT.js → index-D6OzdIrJ.js} +1 -1
  64. package/ui-dist/assets/{index-Dg5xtghf.js → index-DCfnKTZL.js} +1 -1
  65. package/ui-dist/assets/{index-Db6iV9WB.js → index-DFk8pAHY.js} +1 -1
  66. package/ui-dist/assets/{index-Buz7A077.js → index-DgKsdvVn.js} +1 -1
  67. package/ui-dist/assets/{index-DAd4YH2B.js → index-DkfYpS54.js} +1 -1
  68. package/ui-dist/assets/{index-BL42NqD3.js → index-DwUtNa8N.js} +1 -1
  69. package/ui-dist/assets/{index-Di77i-N-.js → index-Y_lagrtV.js} +1 -1
  70. package/ui-dist/assets/{index-DDLRI60h.js → index-cD0aid8e.js} +1 -1
  71. package/ui-dist/assets/{index-BOAT-hOe.js → index-iMvpheRJ.js} +1 -1
  72. package/ui-dist/assets/{index-C6Gjk_Wc.js → index-jf039Q5d.js} +1 -1
  73. package/ui-dist/assets/{index-CSOYDpwp.js → index-oCSJw3iz.js} +334 -334
  74. package/ui-dist/assets/{infoDiagram-LFFYTUFH-Byi5aEp7.js → infoDiagram-LFFYTUFH-DVtVGacg.js} +1 -1
  75. package/ui-dist/assets/{ishikawaDiagram-PHBUUO56-C7VoV5Dl.js → ishikawaDiagram-PHBUUO56-Bod1D2n3.js} +1 -1
  76. package/ui-dist/assets/{journeyDiagram-4ABVD52K-D8vtZeMM.js → journeyDiagram-4ABVD52K-DEmEfb66.js} +1 -1
  77. package/ui-dist/assets/{kanban-definition-K7BYSVSG-Cr1Cg4ni.js → kanban-definition-K7BYSVSG-D4zyLZyv.js} +1 -1
  78. package/ui-dist/assets/{layout-CQM7_u2P.js → layout-DOyQIm6v.js} +1 -1
  79. package/ui-dist/assets/{linear-BgTqFq3v.js → linear-BWD9chM2.js} +1 -1
  80. package/ui-dist/assets/{mermaid.core-BMtkWhMl.js → mermaid.core-QDXoS4fc.js} +4 -4
  81. package/ui-dist/assets/{mindmap-definition-YRQLILUH-DMje7VPN.js → mindmap-definition-YRQLILUH-0N37iHLv.js} +1 -1
  82. package/ui-dist/assets/{pieDiagram-SKSYHLDU-bXnNgXju.js → pieDiagram-SKSYHLDU-CzZFyPYV.js} +1 -1
  83. package/ui-dist/assets/{quadrantDiagram-337W2JSQ-BgCu8W3-.js → quadrantDiagram-337W2JSQ-BB9-MmkN.js} +1 -1
  84. package/ui-dist/assets/{requirementDiagram-Z7DCOOCP-CeL0LvKh.js → requirementDiagram-Z7DCOOCP-CKZUv8I1.js} +1 -1
  85. package/ui-dist/assets/{sankeyDiagram-WA2Y5GQK-DNbWkzvg.js → sankeyDiagram-WA2Y5GQK-CG8cyca5.js} +1 -1
  86. package/ui-dist/assets/{sequenceDiagram-2WXFIKYE-NjcPJPRy.js → sequenceDiagram-2WXFIKYE-Cctsg7MS.js} +1 -1
  87. package/ui-dist/assets/{stateDiagram-RAJIS63D-D29VrWKf.js → stateDiagram-RAJIS63D-DylyOw7m.js} +1 -1
  88. package/ui-dist/assets/stateDiagram-v2-FVOUBMTO-6qT1Stha.js +1 -0
  89. package/ui-dist/assets/{timeline-definition-YZTLITO2-YDz034MQ.js → timeline-definition-YZTLITO2-B2m9ypL0.js} +1 -1
  90. package/ui-dist/assets/{treemap-KZPCXAKY-CRC5gIrP.js → treemap-KZPCXAKY-3o_LW7ue.js} +1 -1
  91. package/ui-dist/assets/{vennDiagram-LZ73GAT5-Dga2JKQO.js → vennDiagram-LZ73GAT5-C29S_PD2.js} +1 -1
  92. package/ui-dist/assets/{xychartDiagram-JWTSCODW-DmXqm_OM.js → xychartDiagram-JWTSCODW-BD0t2Urs.js} +1 -1
  93. package/ui-dist/index.html +1 -1
  94. package/ui-dist/assets/channel-D0Qex6rY.js +0 -1
  95. package/ui-dist/assets/classDiagram-VBA2DB6C-CyT0KBGx.js +0 -1
  96. package/ui-dist/assets/classDiagram-v2-RAHNMMFH-CyT0KBGx.js +0 -1
  97. package/ui-dist/assets/clone-Bp0eZgi0.js +0 -1
  98. package/ui-dist/assets/stateDiagram-v2-FVOUBMTO-vEXjZeVI.js +0 -1
@@ -20,7 +20,7 @@ import { summarizeRuntimeSkillsForTrace } from "../runtime-trace-metadata.js";
20
20
  import { buildWorkspaceReadyComment, cleanupExecutionWorkspaceArtifacts, ensureRuntimeServicesForRun, persistAdapterManagedRuntimeServices, realizeExecutionWorkspace, releaseRuntimeServicesForRun, } from "../workspace-runtime.js";
21
21
  import { issueService } from "../issues.js";
22
22
  import { documentService } from "../documents.js";
23
- import { buildIssueConvergenceReviewWakeupOptions } from "../issue-review-wakeup.js";
23
+ import { buildIssueConvergenceReviewWakeupOptions, buildIssueReviewCloseoutWakeupOptions, } from "../issue-review-wakeup.js";
24
24
  import { executionWorkspaceService } from "../execution-workspaces.js";
25
25
  import { buildObservedRunLangfuseScores } from "../run-intelligence.js";
26
26
  import { workspaceOperationService } from "../workspace-operations.js";
@@ -48,6 +48,9 @@ const ISSUE_PASSIVE_FOLLOWUP_REASON = "issue_passive_followup";
48
48
  const ISSUE_PASSIVE_FOLLOWUP_WAKE_SOURCE = "passive_issue_followup";
49
49
  const ISSUE_PASSIVE_FOLLOWUP_FAILURE_REASON = "missing_closure";
50
50
  const ISSUE_PASSIVE_FOLLOWUP_MAX_ATTEMPTS = 2;
51
+ const ISSUE_REVIEW_CLOSEOUT_REASON = "issue_review_closeout_missing";
52
+ const ISSUE_REVIEW_CLOSEOUT_FAILURE_REASON = "missing_review_decision";
53
+ const ISSUE_REVIEW_CLOSEOUT_MAX_ATTEMPTS = 2;
51
54
  const ISSUE_PASSIVE_FOLLOWUP_COOLDOWN_MS_BY_ATTEMPT = new Map([
52
55
  [1, 2 * 60 * 1000],
53
56
  [2, 5 * 60 * 1000],
@@ -787,6 +790,20 @@ function normalizePassiveFollowupContext(raw) {
787
790
  queuedAt: readNonEmptyString(parsed.queuedAt),
788
791
  };
789
792
  }
793
+ function normalizeReviewCloseoutContext(raw) {
794
+ const parsed = parseObject(raw);
795
+ const originRunId = readNonEmptyString(parsed.originRunId);
796
+ if (!originRunId)
797
+ return null;
798
+ const attempt = Math.max(0, Math.floor(asNumber(parsed.attempt, 0)));
799
+ return {
800
+ originRunId,
801
+ previousRunId: readNonEmptyString(parsed.previousRunId),
802
+ attempt,
803
+ maxAttempts: Math.max(1, Math.floor(asNumber(parsed.maxAttempts, ISSUE_REVIEW_CLOSEOUT_MAX_ATTEMPTS))),
804
+ reason: ISSUE_REVIEW_CLOSEOUT_FAILURE_REASON,
805
+ };
806
+ }
790
807
  function passiveFollowupCooldownMs(attempt) {
791
808
  return ISSUE_PASSIVE_FOLLOWUP_COOLDOWN_MS_BY_ATTEMPT.get(attempt) ?? 5 * 60 * 1000;
792
809
  }
@@ -1783,6 +1800,15 @@ export function heartbeatService(db) {
1783
1800
  .then((rows) => rows[0] ?? null);
1784
1801
  return Boolean(commentActivity);
1785
1802
  }
1803
+ async function runHasIssueReviewDecision(tx, run, issueId) {
1804
+ const decisionActivity = await tx
1805
+ .select({ id: activityLog.id })
1806
+ .from(activityLog)
1807
+ .where(and(eq(activityLog.orgId, run.orgId), eq(activityLog.action, "issue.review_decision_recorded"), eq(activityLog.entityType, "issue"), eq(activityLog.entityId, issueId), eq(activityLog.runId, run.id)))
1808
+ .limit(1)
1809
+ .then((rows) => rows[0] ?? null);
1810
+ return Boolean(decisionActivity);
1811
+ }
1786
1812
  async function issueHasDeferredWake(tx, orgId, issueId) {
1787
1813
  const deferred = await tx
1788
1814
  .select({ id: agentWakeupRequests.id })
@@ -1813,6 +1839,23 @@ export function heartbeatService(db) {
1813
1839
  .then((rows) => rows[0] ?? null);
1814
1840
  return Boolean(existingReview);
1815
1841
  }
1842
+ async function reviewerCloseoutAlreadyRecorded(tx, runId) {
1843
+ const existingWake = await tx
1844
+ .select({ id: agentWakeupRequests.id })
1845
+ .from(agentWakeupRequests)
1846
+ .where(eq(agentWakeupRequests.idempotencyKey, `${ISSUE_REVIEW_CLOSEOUT_REASON}:${runId}`))
1847
+ .limit(1)
1848
+ .then((rows) => rows[0] ?? null);
1849
+ if (existingWake)
1850
+ return true;
1851
+ const existingReview = await tx
1852
+ .select({ id: activityLog.id })
1853
+ .from(activityLog)
1854
+ .where(and(eq(activityLog.runId, runId), eq(activityLog.action, "issue.review_closure_needs_operator_review")))
1855
+ .limit(1)
1856
+ .then((rows) => rows[0] ?? null);
1857
+ return Boolean(existingReview);
1858
+ }
1816
1859
  async function evaluatePassiveIssueClosureForLockedIssue(input) {
1817
1860
  const { tx, run, issue, now } = input;
1818
1861
  const context = parseObject(run.contextSnapshot);
@@ -1821,6 +1864,46 @@ export function heartbeatService(db) {
1821
1864
  return { kind: "none", reason: "run_not_issue_backed" };
1822
1865
  if (run.status !== "succeeded")
1823
1866
  return { kind: "none", reason: "run_not_successful" };
1867
+ const reviewerRun = issue.status === "in_review" &&
1868
+ issue.reviewerAgentId === run.agentId &&
1869
+ (run.invocationSource === "review" ||
1870
+ readNonEmptyString(context.role) === "reviewer" ||
1871
+ readNonEmptyString(context.wakeSource) === "review");
1872
+ if (reviewerRun) {
1873
+ if (await runHasIssueReviewDecision(tx, run, issue.id)) {
1874
+ return { kind: "none", reason: "review_decision_recorded" };
1875
+ }
1876
+ if (await issueHasDeferredWake(tx, issue.orgId, issue.id)) {
1877
+ return { kind: "none", reason: "deferred_issue_wake_exists" };
1878
+ }
1879
+ if (await reviewerCloseoutAlreadyRecorded(tx, run.id)) {
1880
+ return { kind: "none", reason: "reviewer_closeout_already_recorded" };
1881
+ }
1882
+ const reviewCloseout = normalizeReviewCloseoutContext(context.reviewCloseout);
1883
+ const currentAttempt = reviewCloseout?.attempt ?? 0;
1884
+ const maxAttempts = reviewCloseout?.maxAttempts ?? ISSUE_REVIEW_CLOSEOUT_MAX_ATTEMPTS;
1885
+ const originRunId = reviewCloseout?.originRunId ?? run.id;
1886
+ if (currentAttempt >= maxAttempts) {
1887
+ return {
1888
+ kind: "reviewer_closeout_operator_review",
1889
+ issue,
1890
+ originRunId,
1891
+ previousRunId: run.id,
1892
+ attempts: currentAttempt,
1893
+ maxAttempts,
1894
+ reason: ISSUE_REVIEW_CLOSEOUT_FAILURE_REASON,
1895
+ };
1896
+ }
1897
+ return {
1898
+ kind: "reviewer_closeout",
1899
+ issue,
1900
+ originRunId,
1901
+ previousRunId: run.id,
1902
+ attempts: currentAttempt + 1,
1903
+ maxAttempts,
1904
+ reason: ISSUE_REVIEW_CLOSEOUT_FAILURE_REASON,
1905
+ };
1906
+ }
1824
1907
  if (issue.status !== "todo" && issue.status !== "in_progress") {
1825
1908
  return { kind: "none", reason: "issue_has_closure_status" };
1826
1909
  }
@@ -3528,6 +3611,96 @@ export function heartbeatService(db) {
3528
3611
  });
3529
3612
  }
3530
3613
  }
3614
+ else if (passiveClosure?.kind === "reviewer_closeout") {
3615
+ await appendRunEvent(run, await nextRunEventSeq(run.id), {
3616
+ eventType: "issue.review_closeout_missing",
3617
+ stream: "system",
3618
+ level: "warn",
3619
+ message: "Reviewer run finished without a structured review decision",
3620
+ payload: {
3621
+ issueId: passiveClosure.issue.id,
3622
+ originRunId: passiveClosure.originRunId,
3623
+ previousRunId: passiveClosure.previousRunId,
3624
+ attempts: passiveClosure.attempts,
3625
+ maxAttempts: passiveClosure.maxAttempts,
3626
+ reason: passiveClosure.reason,
3627
+ },
3628
+ });
3629
+ await logActivity(db, {
3630
+ orgId: passiveClosure.issue.orgId,
3631
+ actorType: "system",
3632
+ actorId: "issue_review_closeout_governance",
3633
+ action: "issue.review_closeout_missing",
3634
+ entityType: "issue",
3635
+ entityId: passiveClosure.issue.id,
3636
+ agentId: run.agentId,
3637
+ runId: run.id,
3638
+ details: {
3639
+ issueId: passiveClosure.issue.id,
3640
+ issueTitle: passiveClosure.issue.title,
3641
+ reviewerAgentId: passiveClosure.issue.reviewerAgentId,
3642
+ originRunId: passiveClosure.originRunId,
3643
+ previousRunId: passiveClosure.previousRunId,
3644
+ attempts: passiveClosure.attempts,
3645
+ maxAttempts: passiveClosure.maxAttempts,
3646
+ reason: passiveClosure.reason,
3647
+ },
3648
+ });
3649
+ if (passiveClosure.issue.reviewerAgentId) {
3650
+ await enqueueWakeup(passiveClosure.issue.reviewerAgentId, {
3651
+ ...buildIssueReviewCloseoutWakeupOptions({
3652
+ issue: passiveClosure.issue,
3653
+ contextSource: "issue.review_closeout_missing",
3654
+ originRunId: passiveClosure.originRunId,
3655
+ previousRunId: passiveClosure.previousRunId,
3656
+ attempts: passiveClosure.attempts,
3657
+ maxAttempts: passiveClosure.maxAttempts,
3658
+ requestedByActorType: "system",
3659
+ requestedByActorId: "issue_review_closeout_governance",
3660
+ }),
3661
+ idempotencyKey: `${ISSUE_REVIEW_CLOSEOUT_REASON}:${run.id}`,
3662
+ }).catch((err) => {
3663
+ logger.warn({ err, issueId: passiveClosure.issue.id }, "failed to wake reviewer after missing review close-out");
3664
+ return null;
3665
+ });
3666
+ }
3667
+ }
3668
+ else if (passiveClosure?.kind === "reviewer_closeout_operator_review") {
3669
+ await appendRunEvent(run, await nextRunEventSeq(run.id), {
3670
+ eventType: "issue.review_closure_needs_operator_review",
3671
+ stream: "system",
3672
+ level: "warn",
3673
+ message: "Reviewer close-out attempts stopped and need operator review",
3674
+ payload: {
3675
+ issueId: passiveClosure.issue.id,
3676
+ originRunId: passiveClosure.originRunId,
3677
+ previousRunId: passiveClosure.previousRunId,
3678
+ attempts: passiveClosure.attempts,
3679
+ maxAttempts: passiveClosure.maxAttempts,
3680
+ reason: passiveClosure.reason,
3681
+ },
3682
+ });
3683
+ await logActivity(db, {
3684
+ orgId: passiveClosure.issue.orgId,
3685
+ actorType: "system",
3686
+ actorId: "issue_review_closeout_governance",
3687
+ action: "issue.review_closure_needs_operator_review",
3688
+ entityType: "issue",
3689
+ entityId: passiveClosure.issue.id,
3690
+ agentId: run.agentId,
3691
+ runId: run.id,
3692
+ details: {
3693
+ issueId: passiveClosure.issue.id,
3694
+ issueTitle: passiveClosure.issue.title,
3695
+ reviewerAgentId: passiveClosure.issue.reviewerAgentId,
3696
+ originRunId: passiveClosure.originRunId,
3697
+ previousRunId: passiveClosure.previousRunId,
3698
+ attempts: passiveClosure.attempts,
3699
+ maxAttempts: passiveClosure.maxAttempts,
3700
+ reason: passiveClosure.reason,
3701
+ },
3702
+ });
3703
+ }
3531
3704
  const promotedRun = outcome.promotedRun;
3532
3705
  if (!promotedRun)
3533
3706
  return;