@runfusion/fusion 0.75.1-beta.1 → 0.75.1-beta.2

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 (117) hide show
  1. package/dist/bin.js +264 -136
  2. package/dist/child-process-worker.js +138 -38
  3. package/dist/client/.vite/manifest.json +253 -253
  4. package/dist/client/assets/{AgentDetailView-CE_7nvDT.js → AgentDetailView-ltOG8f0-.js} +1 -1
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-DYr3dk5X.js → AgentPermissionPolicyEditor-CC_rrbbG.js} +1 -1
  6. package/dist/client/assets/{AgentsView-DZoYoiaD.js → AgentsView-DWUdi27N.js} +3 -3
  7. package/dist/client/assets/{ChatView-BE9zMzYZ.js → ChatView-mFKfoegS.js} +1 -1
  8. package/dist/client/assets/{CommandCenter-DnLsp4_S.js → CommandCenter-C2wvDq_N.js} +1 -1
  9. package/dist/client/assets/{DevServerView-CI-3j-lH.js → DevServerView-0MWEJM7o.js} +1 -1
  10. package/dist/client/assets/{DirectoryPicker-D1ADu0Av.js → DirectoryPicker-BjMPhCdh.js} +1 -1
  11. package/dist/client/assets/{DocumentsView-CF8y1gob.js → DocumentsView-ckH3rjmd.js} +1 -1
  12. package/dist/client/assets/{EvalsView-C9vLiM2_.js → EvalsView-NyA644VF.js} +1 -1
  13. package/dist/client/assets/{ExperimentalAgentOnboardingModal-CX_2Hjh0.js → ExperimentalAgentOnboardingModal-D0ZfbBRN.js} +1 -1
  14. package/dist/client/assets/{GoalsView-DJIA3k8q.js → GoalsView-Ctt5P_yo.js} +1 -1
  15. package/dist/client/assets/{InsightsView--TCeutLO.js → InsightsView-NDp0bdNB.js} +1 -1
  16. package/dist/client/assets/{MemoryView-Btp4m7pK.js → MemoryView-BKbA4Bm4.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-DXdfh-Uf.js → PiExtensionsManager-V3AFWMHm.js} +1 -1
  18. package/dist/client/assets/{PluginManager-BDFelFY6.js → PluginManager-D88G_TZh.js} +1 -1
  19. package/dist/client/assets/{PullRequestView-TSNKGSAg.js → PullRequestView-DQQmFFYC.js} +1 -1
  20. package/dist/client/assets/{ReportModal-DhXMNHDL.js → ReportModal-Clh1S8RF.js} +1 -1
  21. package/dist/client/assets/{ResearchView-0w30HikQ.js → ResearchView-kxvq4zp5.js} +1 -1
  22. package/dist/client/assets/SecretsView-Dm0Vk8SA.js +1 -0
  23. package/dist/client/assets/{SessionTerminal-CF6_uy2u.js → SessionTerminal-DJO4JTEX.js} +1 -1
  24. package/dist/client/assets/{SettingsModal-BMAPX_7v.js → SettingsModal-BN5mL_ym.js} +1 -1
  25. package/dist/client/assets/SettingsModal-CTf5voEW.js +21 -0
  26. package/dist/client/assets/{SettingsTextareaRow-LqXxpJl5.js → SettingsTextareaRow-CvKszqO-.js} +1 -1
  27. package/dist/client/assets/{SetupWizardModal-D1ZvGOcK.js → SetupWizardModal-D5hVZh1G.js} +2 -2
  28. package/dist/client/assets/{SkillsView-CfO5B7SO.js → SkillsView-DQVz21w2.js} +1 -1
  29. package/dist/client/assets/{WorkflowNodeEditor-CjdK9fFS.js → WorkflowNodeEditor-CpKIi6Tb.js} +1 -1
  30. package/dist/client/assets/{agent-import-generation-DqTzyLOZ.js → agent-import-generation-DGUNF3nd.js} +1 -1
  31. package/dist/client/assets/{architectureDiagram-3BPJPVTR-CHkolL_b.js → architectureDiagram-3BPJPVTR-CV83wubP.js} +1 -1
  32. package/dist/client/assets/{blockDiagram-GPEHLZMM-BFRYQi8H.js → blockDiagram-GPEHLZMM-CNQsA3dD.js} +1 -1
  33. package/dist/client/assets/{c4Diagram-AAUBKEIU-D9mMEYbR.js → c4Diagram-AAUBKEIU-CXe7ii5H.js} +1 -1
  34. package/dist/client/assets/channel-DoX862zl.js +1 -0
  35. package/dist/client/assets/{chunk-2J33WTMH-CCv6QaQn.js → chunk-2J33WTMH-BS6W9bWv.js} +1 -1
  36. package/dist/client/assets/{chunk-4BX2VUAB-Bfe22y5T.js → chunk-4BX2VUAB-DbehRhdW.js} +1 -1
  37. package/dist/client/assets/{chunk-55IACEB6-CwicrA9V.js → chunk-55IACEB6-DMI5SR42.js} +1 -1
  38. package/dist/client/assets/{chunk-727SXJPM-DlIpTC03.js → chunk-727SXJPM-D1d-GBVj.js} +1 -1
  39. package/dist/client/assets/{chunk-AQP2D5EJ-CRX4mFVq.js → chunk-AQP2D5EJ-BzO6K3Uf.js} +1 -1
  40. package/dist/client/assets/{chunk-FMBD7UC4-DzG-bovU.js → chunk-FMBD7UC4-BVRLV3lK.js} +1 -1
  41. package/dist/client/assets/{chunk-ND2GUHAM-D5F2jtpM.js → chunk-ND2GUHAM-DdWByQfn.js} +1 -1
  42. package/dist/client/assets/{chunk-QZHKN3VN-BmSaCwG6.js → chunk-QZHKN3VN-1ia12cRV.js} +1 -1
  43. package/dist/client/assets/classDiagram-4FO5ZUOK-mb2IeAGN.js +1 -0
  44. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-mb2IeAGN.js +1 -0
  45. package/dist/client/assets/{cose-bilkent-S5V4N54A-BbKTljui.js → cose-bilkent-S5V4N54A-BPDT41HR.js} +1 -1
  46. package/dist/client/assets/{dagre-BM42HDAG-u0hwXb_T.js → dagre-BM42HDAG-Cktn26EH.js} +1 -1
  47. package/dist/client/assets/{dashboard-view-BfYZZ9Ms.js → dashboard-view-8o0EUcRX.js} +1 -1
  48. package/dist/client/assets/{dashboard-view-faKSXA4_.js → dashboard-view-CkCerlVJ.js} +1 -1
  49. package/dist/client/assets/{dashboard-view-BjPZG2Fv.js → dashboard-view-D_HC4lnr.js} +1 -1
  50. package/dist/client/assets/{dashboard-view-oCjWDGbW.js → dashboard-view-zd8GxC49.js} +1 -1
  51. package/dist/client/assets/{diagram-2AECGRRQ-Q7towbBl.js → diagram-2AECGRRQ-But4Lvf-.js} +1 -1
  52. package/dist/client/assets/{diagram-5GNKFQAL-UAwBmAxb.js → diagram-5GNKFQAL-2bpQAGFc.js} +1 -1
  53. package/dist/client/assets/{diagram-KO2AKTUF-BL1n0pkf.js → diagram-KO2AKTUF-Ckn9Qd1u.js} +1 -1
  54. package/dist/client/assets/{diagram-LMA3HP47-O-v_IZUJ.js → diagram-LMA3HP47-Bjn8h84N.js} +1 -1
  55. package/dist/client/assets/{diagram-OG6HWLK6-CAYSE2Mz.js → diagram-OG6HWLK6-BI6541hx.js} +1 -1
  56. package/dist/client/assets/{erDiagram-TEJ5UH35-Cr_DgCyp.js → erDiagram-TEJ5UH35-BqMiwHiM.js} +1 -1
  57. package/dist/client/assets/{flowDiagram-I6XJVG4X-TdLzHKPW.js → flowDiagram-I6XJVG4X-Q_SAB10M.js} +1 -1
  58. package/dist/client/assets/{folder-open-BoddkTkv.js → folder-open-CHiAJbTN.js} +1 -1
  59. package/dist/client/assets/{ganttDiagram-6RSMTGT7-CO1ErtJY.js → ganttDiagram-6RSMTGT7-CqWFSfPF.js} +1 -1
  60. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-C8_Kx0Yh.js → gitGraphDiagram-PVQCEYII-B1o4uEjO.js} +1 -1
  61. package/dist/client/assets/index-Bdw5eNKV.css +1 -0
  62. package/dist/client/assets/index-kwRywd9M.js +2767 -0
  63. package/dist/client/assets/{infoDiagram-5YYISTIA-Dd6Zo7Dh.js → infoDiagram-5YYISTIA-BzaMa0c2.js} +1 -1
  64. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BE9JCLb5.js → ishikawaDiagram-YF4QCWOH-I38yge00.js} +1 -1
  65. package/dist/client/assets/{journeyDiagram-JHISSGLW-B6RIZGDq.js → journeyDiagram-JHISSGLW-WVQSgx4P.js} +1 -1
  66. package/dist/client/assets/{kanban-definition-UN3LZRKU-CPXff-h-.js → kanban-definition-UN3LZRKU-BWtPQ3AH.js} +1 -1
  67. package/dist/client/assets/{mermaid.core-CbGj7iEw.js → mermaid.core-D1hnBtbi.js} +4 -4
  68. package/dist/client/assets/{mindmap-definition-RKZ34NQL-DF5LZmsH.js → mindmap-definition-RKZ34NQL-DqiSLkW7.js} +1 -1
  69. package/dist/client/assets/{pieDiagram-4H26LBE5-Dpy0Xm9T.js → pieDiagram-4H26LBE5-CcgwbdIN.js} +1 -1
  70. package/dist/client/assets/{puzzle-BZa4U8-N.js → puzzle-BhXUaTQl.js} +1 -1
  71. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BTLAQFpz.js → quadrantDiagram-W4KKPZXB-MsqQQfDN.js} +1 -1
  72. package/dist/client/assets/{requirementDiagram-4Y6WPE33-DSUV9ySs.js → requirementDiagram-4Y6WPE33-CILGjMMA.js} +1 -1
  73. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Fmfn0XDL.js → sankeyDiagram-5OEKKPKP-c14fWbtR.js} +1 -1
  74. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-_343I_b4.js → sequenceDiagram-3UESZ5HK-BD5bxMom.js} +1 -1
  75. package/dist/client/assets/{shield-alert-CdJ55UvI.js → shield-alert-C9W2WywS.js} +1 -1
  76. package/dist/client/assets/{standing-instructions-template-r03dZ5Z0.js → standing-instructions-template-CJdbDSyg.js} +1 -1
  77. package/dist/client/assets/{stateDiagram-AJRCARHV-C9EbWegm.js → stateDiagram-AJRCARHV-CZ5YqeOn.js} +1 -1
  78. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-Bmh2GRh6.js → stateDiagram-v2-BHNVJYJU-mdMN-PNX.js} +1 -1
  79. package/dist/client/assets/{timeline-definition-PNZ67QCA-q86S9wyl.js → timeline-definition-PNZ67QCA-DHKay9uj.js} +1 -1
  80. package/dist/client/assets/{upload-DS9-qtCF.js → upload-DxEwowRU.js} +1 -1
  81. package/dist/client/assets/{users-DP5Sngeg.js → users-mNFgW_Zd.js} +1 -1
  82. package/dist/client/assets/{vennDiagram-CIIHVFJN-BFq8uIt3.js → vennDiagram-CIIHVFJN-X29K9hWM.js} +1 -1
  83. package/dist/client/assets/{wardley-L42UT6IY-BL_sLGYI.js → wardley-L42UT6IY-yEoTrfmN.js} +1 -1
  84. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BEKJJ9Vi.js → wardleyDiagram-YWT4CUSO-ny4k3kG0.js} +1 -1
  85. package/dist/client/assets/{xychartDiagram-2RQKCTM6-DsvFnlxK.js → xychartDiagram-2RQKCTM6-DC8ODtRJ.js} +1 -1
  86. package/dist/client/index.html +2 -2
  87. package/dist/client/version.json +1 -1
  88. package/dist/droid-cli/package.json +1 -1
  89. package/dist/extension.js +225 -93
  90. package/dist/pi-claude-cli/package.json +1 -1
  91. package/dist/plugin-sdk/index.d.ts +2 -1
  92. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  93. package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
  94. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  95. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  96. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  97. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  98. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  99. package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
  100. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  101. package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
  102. package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
  103. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  104. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  105. package/dist/plugins/fusion-plugin-quality/package.json +1 -1
  106. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  107. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  108. package/dist/plugins/fusion-plugin-todos/package.json +1 -1
  109. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  110. package/package.json +1 -1
  111. package/dist/client/assets/SecretsView-DgMu7279.js +0 -1
  112. package/dist/client/assets/SettingsModal-Dckls6LL.js +0 -21
  113. package/dist/client/assets/channel-CLdamWm5.js +0 -1
  114. package/dist/client/assets/classDiagram-4FO5ZUOK-BYWknNX0.js +0 -1
  115. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BYWknNX0.js +0 -1
  116. package/dist/client/assets/index-C7KY0q8Q.js +0 -2767
  117. package/dist/client/assets/index-DHk_s6rA.css +0 -1
package/dist/bin.js CHANGED
@@ -1183,6 +1183,9 @@ function isFusionSiblingBranch(branch) {
1183
1183
  function resolveEffectiveAutoMerge(task, settings) {
1184
1184
  return task.autoMerge ?? settings.autoMerge;
1185
1185
  }
1186
+ function hasUserAutoMergeHold(task) {
1187
+ return task.autoMerge === false && task.autoMergeProvenance === "user";
1188
+ }
1186
1189
  function allowsAutoMergeProcessing(task, settings) {
1187
1190
  return (settings.autoMerge !== false || task.autoMerge === true) && !taskHasManualOpenPullRequest(task);
1188
1191
  }
@@ -63423,7 +63426,7 @@ function rowToTask(row) {
63423
63426
  executionStartBranch: row.executionStartBranch || void 0,
63424
63427
  branch: row.branch || void 0,
63425
63428
  autoMerge: row.autoMerge === null ? void 0 : row.autoMerge === 1,
63426
- autoMergeProvenance: row.autoMergeProvenance === "user" || row.autoMergeProvenance === "legacy-stamp" ? row.autoMergeProvenance : void 0,
63429
+ autoMergeProvenance: row.autoMergeProvenance === "user" || row.autoMergeProvenance === "mission" || row.autoMergeProvenance === "legacy-stamp" ? row.autoMergeProvenance : void 0,
63427
63430
  baseCommitSha: row.baseCommitSha || void 0,
63428
63431
  scopeOverride: row.scopeOverride ? true : void 0,
63429
63432
  scopeOverrideReason: row.scopeOverrideReason || void 0,
@@ -72939,10 +72942,10 @@ ${feature.acceptanceCriteria}`);
72939
72942
  Apply the selected Missions header workflow atomically during TaskStore.createTask so newly triaged features land in the intended workflow lane. Duplicate-guard reuses skip this create path, preserving existing duplicate tasks without workflow mutation.
72940
72943
  */
72941
72944
  /*
72942
- FNXC:MissionAutoMerge 2026-07-18-12:00:
72943
- An autoMerge:false mission stamps each newly triaged task so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override.
72945
+ FNXC:MissionAutoMerge 2026-08-05-22:50:
72946
+ An autoMerge:false mission stamps each newly triaged task as mission policy so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override; policy must not impersonate an operator manual-hold choice.
72944
72947
  */
72945
- ...mission?.autoMerge === false ? { autoMerge: false } : {},
72948
+ ...mission?.autoMerge === false ? { autoMerge: false, autoMergeProvenance: "mission" } : {},
72946
72949
  // FNXC:MissionTaskPrefix 2026-07-26-12:00: thread the mission's optional taskPrefix into TaskCreateInput for distributed id minting.
72947
72950
  ...mission?.taskPrefix ? { taskPrefix: mission.taskPrefix } : {},
72948
72951
  ...branchOptions?.workflowId !== void 0 ? { workflowId: branchOptions.workflowId } : {}
@@ -76120,10 +76123,10 @@ ${feature.acceptanceCriteria}`);
76120
76123
  }
76121
76124
  } : {},
76122
76125
  /*
76123
- FNXC:MissionAutoMerge 2026-07-18-12:00:
76124
- An autoMerge:false mission stamps each newly triaged task so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override.
76126
+ FNXC:MissionAutoMerge 2026-08-05-22:50:
76127
+ An autoMerge:false mission stamps each newly triaged task as mission policy so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override; policy must not impersonate an operator manual-hold choice.
76125
76128
  */
76126
- ...mission?.autoMerge === false ? { autoMerge: false } : {},
76129
+ ...mission?.autoMerge === false ? { autoMerge: false, autoMergeProvenance: "mission" } : {},
76127
76130
  // FNXC:MissionTaskPrefix 2026-07-26-12:00: thread the mission's optional taskPrefix into TaskCreateInput so the distributed allocator mints ERR-N (etc.) instead of the project prefix.
76128
76131
  ...mission?.taskPrefix ? { taskPrefix: mission.taskPrefix } : {},
76129
76132
  ...branchOptions?.workflowId !== void 0 ? { workflowId: branchOptions.workflowId } : {}
@@ -86474,7 +86477,9 @@ async function _createTaskInternalBackendImpl(store, input, title2, resolvedWork
86474
86477
  sourceMetadata: withTaskBranchContextInSourceMetadata(input.source?.sourceMetadata, input.branchContext),
86475
86478
  branchContext: input.branchContext,
86476
86479
  autoMerge: input.autoMerge,
86477
- autoMergeProvenance: input.autoMerge === void 0 ? void 0 : "user",
86480
+ // FNXC:SharedBranchMemberHold 2026-08-05-22:50: trusted mission creation
86481
+ // preserves policy provenance; operator/API create requests retain user provenance.
86482
+ autoMergeProvenance: input.autoMerge === void 0 ? void 0 : input.autoMergeProvenance ?? "user",
86478
86483
  // FNXC:CodingIdeasWorkflow 2026-07-05-19:45: land the task in its
86479
86484
  // workflow's manual intake column (e.g. Coding (Ideas) → "ideas") when
86480
86485
  // no explicit column is given (main FN-7591 parity).
@@ -127352,6 +127357,7 @@ var init_task_timing = __esm({
127352
127357
  });
127353
127358
 
127354
127359
  // ../core/src/session-identity-registry.ts
127360
+ import { AsyncLocalStorage } from "node:async_hooks";
127355
127361
  import { resolve as resolve21 } from "node:path";
127356
127362
  import { realpathSync as realpathSync5 } from "node:fs";
127357
127363
  function getRegistry() {
@@ -127363,6 +127369,16 @@ function getRegistry() {
127363
127369
  }
127364
127370
  return registry3;
127365
127371
  }
127372
+ function getActiveInvocationStorage() {
127373
+ const holder = globalThis;
127374
+ const existing = holder[ACTIVE_INVOCATION_KEY];
127375
+ if (existing instanceof AsyncLocalStorage) {
127376
+ return existing;
127377
+ }
127378
+ const storage = new AsyncLocalStorage();
127379
+ holder[ACTIVE_INVOCATION_KEY] = storage;
127380
+ return storage;
127381
+ }
127366
127382
  function canonicalizeCwd(cwd) {
127367
127383
  const resolved = resolve21(cwd);
127368
127384
  try {
@@ -127390,8 +127406,13 @@ function registerFusionSessionIdentity(cwd, identity) {
127390
127406
  };
127391
127407
  }
127392
127408
  function resolveFusionSessionPrincipal(cwd) {
127409
+ const canonicalCwd = canonicalizeCwd(cwd);
127410
+ const activeInvocation = getActiveInvocationStorage().getStore();
127411
+ if (activeInvocation?.cwdKeys.has(canonicalCwd)) {
127412
+ return { kind: "agent", identity: activeInvocation.identity };
127413
+ }
127393
127414
  const registry3 = getRegistry();
127394
- const list = registry3.get(canonicalizeCwd(cwd));
127415
+ const list = registry3.get(canonicalCwd);
127395
127416
  if (!list || list.length === 0) {
127396
127417
  return { kind: "operator" };
127397
127418
  }
@@ -127400,14 +127421,24 @@ function resolveFusionSessionPrincipal(cwd) {
127400
127421
  }
127401
127422
  return { kind: "ambiguous", identities: [...list] };
127402
127423
  }
127424
+ function runWithFusionSessionIdentity(cwdKeys, identity, callback) {
127425
+ const invocation = {
127426
+ identity: { ...identity, registeredAt: Date.now() },
127427
+ cwdKeys: new Set(cwdKeys.map(canonicalizeCwd))
127428
+ };
127429
+ return getActiveInvocationStorage().run(invocation, callback);
127430
+ }
127403
127431
  function __clearFusionSessionIdentityRegistryForTests() {
127404
- globalThis[REGISTRY_KEY] = /* @__PURE__ */ new Map();
127432
+ const holder = globalThis;
127433
+ holder[REGISTRY_KEY] = /* @__PURE__ */ new Map();
127434
+ holder[ACTIVE_INVOCATION_KEY] = new AsyncLocalStorage();
127405
127435
  }
127406
- var REGISTRY_KEY;
127436
+ var REGISTRY_KEY, ACTIVE_INVOCATION_KEY;
127407
127437
  var init_session_identity_registry = __esm({
127408
127438
  "../core/src/session-identity-registry.ts"() {
127409
127439
  "use strict";
127410
127440
  REGISTRY_KEY = "__FUSION_SESSION_IDENTITY_REGISTRY_V1__";
127441
+ ACTIVE_INVOCATION_KEY = "__FUSION_SESSION_IDENTITY_ACTIVE_INVOCATION_V1__";
127411
127442
  }
127412
127443
  });
127413
127444
 
@@ -128378,6 +128409,7 @@ __export(src_exports, {
128378
128409
  hasRoleOverrides: () => hasRoleOverrides,
128379
128410
  hasSyncPassphraseConfigured: () => hasSyncPassphraseConfigured,
128380
128411
  hasTitleIdDrift: () => hasTitleIdDrift,
128412
+ hasUserAutoMergeHold: () => hasUserAutoMergeHold,
128381
128413
  hashWorkflowIr: () => hashWorkflowIr,
128382
128414
  healSchemaDrift: () => healSchemaDrift,
128383
128415
  importMcpServersJson: () => importMcpServersJson,
@@ -128838,6 +128870,7 @@ __export(src_exports, {
128838
128870
  runMemoryBackupCommand: () => runMemoryBackupCommand,
128839
128871
  runReconciliationAbort: () => runReconciliationAbort,
128840
128872
  runScheduledEvalBatch: () => runScheduledEvalBatch,
128873
+ runWithFusionSessionIdentity: () => runWithFusionSessionIdentity,
128841
128874
  sanitizeBranchSegment: () => sanitizeBranchSegment,
128842
128875
  sanitizeCliAgentSettings: () => sanitizeCliAgentSettings,
128843
128876
  sanitizeCliAgentsSettings: () => sanitizeCliAgentsSettings,
@@ -158229,6 +158262,7 @@ import { existsSync as existsSync43, readFileSync as readFileSync15, realpathSyn
158229
158262
  import { exec as exec2, execFile as execFile7 } from "node:child_process";
158230
158263
  import { promisify as promisify6 } from "node:util";
158231
158264
  import { createRequire as createRequire5 } from "node:module";
158265
+ import { randomUUID as randomUUID43 } from "node:crypto";
158232
158266
  import { basename as basename13, dirname as dirname21, join as join56, relative as relative6, isAbsolute as isAbsolute8, resolve as resolve24 } from "node:path";
158233
158267
  import {
158234
158268
  createAgentSession,
@@ -159939,7 +159973,8 @@ async function createFnAgent2(options) {
159939
159973
  });
159940
159974
  };
159941
159975
  const sessionIdentity = (() => {
159942
- const principalAgentId = options.actionGateContext?.agentId ?? options.permanentAgentGating?.requester?.actorId ?? "engine-session";
159976
+ const namedAgentId = options.actionGateContext?.agentId ?? options.permanentAgentGating?.requester?.actorId;
159977
+ const principalAgentId = namedAgentId ?? `engine-session-${randomUUID43()}`;
159943
159978
  const principalAgentName = options.actionGateContext?.agentName ?? options.permanentAgentGating?.requester?.actorName;
159944
159979
  return {
159945
159980
  agentId: principalAgentId,
@@ -159951,6 +159986,14 @@ async function createFnAgent2(options) {
159951
159986
  const sessionIdentityKeys = [...new Set([options.cwd, resolvedProjectRoot].filter((key) => Boolean(key)))];
159952
159987
  const attachSessionIdentity = (session) => {
159953
159988
  const identityDisposers = sessionIdentityKeys.map((key) => registerFusionSessionIdentity(key, sessionIdentity));
159989
+ const sessionInvocations = session;
159990
+ const wrapInvocation = (methodName) => {
159991
+ const original = sessionInvocations[methodName];
159992
+ if (typeof original !== "function") return;
159993
+ sessionInvocations[methodName] = (...args) => runWithFusionSessionIdentity(sessionIdentityKeys, sessionIdentity, () => original.apply(session, args));
159994
+ };
159995
+ wrapInvocation("prompt");
159996
+ wrapInvocation("promptWithFallback");
159954
159997
  const disposeBeforeIdentity = typeof session.dispose === "function" ? session.dispose.bind(session) : () => void 0;
159955
159998
  session.dispose = async () => {
159956
159999
  for (const disposeIdentity of identityDisposers) {
@@ -168150,10 +168193,11 @@ function createMergeAttemptHandler(deps) {
168150
168193
  );
168151
168194
  };
168152
168195
  }
168153
- function createMergeGateHandler() {
168196
+ function createMergeGateHandler(deps = {}) {
168154
168197
  return async (_node, ctx) => {
168155
168198
  const settingsAutoMerge = ctx.settings?.autoMerge;
168156
- const autoMerge = ctx.task.autoMerge !== false && settingsAutoMerge !== false;
168199
+ const settings = { autoMerge: settingsAutoMerge ?? true };
168200
+ const autoMerge = !hasUserAutoMergeHold(ctx.task) && (await deps.isLiveSharedBranchMember?.(ctx.task, settings) === true || ctx.task.autoMerge !== false && settings.autoMerge !== false);
168157
168201
  return {
168158
168202
  outcome: "success",
168159
168203
  value: autoMerge ? "auto-on" : "auto-off"
@@ -168163,6 +168207,7 @@ function createMergeGateHandler() {
168163
168207
  var init_merge_runner = __esm({
168164
168208
  "../engine/src/workflow-node-runners/merge-runner.ts"() {
168165
168209
  "use strict";
168210
+ init_src2();
168166
168211
  init_workflow_merge_nodes();
168167
168212
  }
168168
168213
  });
@@ -168506,7 +168551,7 @@ function createDefaultNodeHandlers(seams, runCustomNode, deps) {
168506
168551
  "parse-steps": parseSteps,
168507
168552
  code: createCodeNodeHandler(deps?.runCode),
168508
168553
  notify: createNotifyHandler(deps?.notifyDispatch),
168509
- "merge-gate": createMergeGateHandler(),
168554
+ "merge-gate": createMergeGateHandler({ isLiveSharedBranchMember: deps?.isLiveSharedBranchMember }),
168510
168555
  "merge-attempt": createMergeAttemptHandler({
168511
168556
  primitives: deps?.primitives,
168512
168557
  seams,
@@ -168904,7 +168949,7 @@ var init_code_node_runner = __esm({
168904
168949
  // ../engine/src/agent-tools.ts
168905
168950
  import { appendFile as appendFile3, mkdir as mkdir26, readFile as readFile32, readdir as readdir9, realpath, stat as stat9, writeFile as writeFile24 } from "node:fs/promises";
168906
168951
  import { existsSync as existsSync50 } from "node:fs";
168907
- import { createHash as createHash19, randomUUID as randomUUID43 } from "node:crypto";
168952
+ import { createHash as createHash19, randomUUID as randomUUID44 } from "node:crypto";
168908
168953
  import { tmpdir as tmpdir5 } from "node:os";
168909
168954
  import { extname as extname3, isAbsolute as isAbsolute12, join as join62, relative as relative11, resolve as resolve33, sep as sep9 } from "node:path";
168910
168955
  import { Type as Type2 } from "@earendil-works/pi-ai";
@@ -169550,7 +169595,7 @@ function createTaskCreateTool(store, provenance, options) {
169550
169595
  toType: "user",
169551
169596
  type: "agent-to-user",
169552
169597
  content: `Task proposal awaiting validation: ${title2}`,
169553
- metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey: randomUUID43(), taskId: options.sourceTaskId, proposedTask: { title: title2, description: params.description, priority: params.priority, workflowId: params.workflow_id, dependencies: params.dependencies } }
169598
+ metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey: randomUUID44(), taskId: options.sourceTaskId, proposedTask: { title: title2, description: params.description, priority: params.priority, workflowId: params.workflow_id, dependencies: params.dependencies } }
169554
169599
  });
169555
169600
  return { content: [{ type: "text", text: "Task proposal submitted to the operator for validation; no task was created." }], details: { proposed: true } };
169556
169601
  }
@@ -203127,16 +203172,29 @@ var init_self_healing = __esm({
203127
203172
  activeWork: await this.resolveActiveWorkColumnsFor(taskId, cache7)
203128
203173
  };
203129
203174
  }
203130
- classifyPausedAbortWorkflowRecovery(task, settings, isExecuting, columns) {
203175
+ /*
203176
+ FNXC:SharedBranchMemberHold 2026-08-05-23:35:
203177
+ Pause-abort recovery must resolve the same live intermediate-group predicate as
203178
+ merge admission. Shared metadata alone is stale after group closure or a
203179
+ default-branch collision, so it cannot suppress that task's standalone hold.
203180
+ */
203181
+ async isLiveSharedMemberIntegration(task, settings) {
203182
+ const groupId = task.branchContext?.groupId?.trim();
203183
+ const group = groupId ? await this.store.getBranchGroup?.(groupId) : null;
203184
+ const defaultBranch = await resolveIntegrationBranch(this.options.rootDir, settings);
203185
+ return isLiveSharedBranchGroupMemberIntegration(task, group, defaultBranch);
203186
+ }
203187
+ async classifyPausedAbortWorkflowRecovery(task, settings, isExecuting, columns) {
203131
203188
  const isPausedAbortPark = task.status === "failed" && typeof task.error === "string" && task.error.includes(PAUSE_ABORT_PARK_OPERATOR_MARKER) && task.error.includes(PAUSE_ABORT_PARK_ERROR_MARKER);
203132
203189
  if (!isPausedAbortPark) return { kind: "no-action", reason: "not-pause-abort" };
203133
203190
  if (task.paused || task.userPaused || isExecuting) return { kind: "no-action", reason: "unsafe-or-not-routable" };
203134
203191
  const errorText = typeof task.error === "string" ? task.error.toLowerCase() : "";
203135
203192
  const isTerminalMergePark = errorText.includes("conflict") || errorText.includes("contamination") || errorText.includes("foreign") || errorText.includes("retry-exhausted") || errorText.includes("retries exhausted") || errorText.includes("max retries");
203136
203193
  const completedSteps = task.steps.length > 0 && task.steps.every((step) => step.status === "done" || step.status === "skipped");
203137
- const sharedBranchMember = isSharedBranchGroupMemberIntegration(task);
203138
- const hasReviewProgress = columns.review.has(task.column) && allowsAutoMergeProcessing(task, settings) && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
203139
- const hasManualMergeHoldProgress = columns.review.has(task.column) && (!allowsAutoMergeProcessing(task, settings) || resolveEffectiveAutoMerge(task, settings) === false) && !sharedBranchMember && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
203194
+ const liveSharedBranchMember = await this.isLiveSharedMemberIntegration(task, settings);
203195
+ const autoMergeProcessing = allowsAutoMergeProcessing(task, settings) || liveSharedBranchMember;
203196
+ const hasReviewProgress = columns.review.has(task.column) && autoMergeProcessing && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
203197
+ const hasManualMergeHoldProgress = columns.review.has(task.column) && (hasUserAutoMergeHold(task) || !allowsAutoMergeProcessing(task, settings) || resolveEffectiveAutoMerge(task, settings) === false) && (!liveSharedBranchMember || hasUserAutoMergeHold(task)) && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
203140
203198
  if (hasManualMergeHoldProgress) {
203141
203199
  return { kind: "work-item-resume", reason: "pause-abort-manual-merge-hold" };
203142
203200
  }
@@ -208804,8 +208862,23 @@ var init_self_healing = __esm({
208804
208862
  return own.length > 0 ? new Set(own) : /* @__PURE__ */ new Set(["in-review"]);
208805
208863
  };
208806
208864
  const executingIds = this.options.getExecutingTaskIds?.() ?? /* @__PURE__ */ new Set();
208865
+ const canRecoverMergeableReviewTask = async (task) => {
208866
+ if (hasUserAutoMergeHold(task)) return false;
208867
+ const groupId = task.branchContext?.groupId?.trim();
208868
+ const branchGroup = groupId ? await this.store.getBranchGroup(groupId) : null;
208869
+ const projectDefaultBranch = await resolveIntegrationBranch(this.options.rootDir, settings);
208870
+ if (isLiveSharedBranchGroupMemberIntegration(task, branchGroup, projectDefaultBranch)) {
208871
+ return true;
208872
+ }
208873
+ return allowsAutoMergeProcessing(task, settings) && resolveEffectiveAutoMerge(task, settings) !== false;
208874
+ };
208875
+ const mergeAdmission = await Promise.all(tasks2.map(async (task) => [
208876
+ task.id,
208877
+ await canRecoverMergeableReviewTask(task)
208878
+ ]));
208879
+ const mergeAdmissionByTaskId = new Map(mergeAdmission);
208807
208880
  const mergeable = tasks2.filter(
208808
- (t) => allowsAutoMergeProcessing(t, settings) && !t.paused && !executingIds.has(t.id) && t.status !== "failed" && // Exclude transient merge statuses. Active merges should be left alone;
208881
+ (t) => mergeAdmissionByTaskId.get(t.id) === true && !t.paused && !executingIds.has(t.id) && t.status !== "failed" && // Exclude transient merge statuses. Active merges should be left alone;
208809
208882
  // stale ones are handled by recoverStaleMergingStatus().
208810
208883
  t.status !== "merging" && t.status !== "merging-pr" && // FNXC:Workspace 2026-06-22-09:30 (Phase D U1, KTD1 — admit workspace tasks):
208811
208884
  // A workspace task has task.worktree===null (its worktrees live per-repo in
@@ -211852,7 +211925,7 @@ var init_self_healing = __esm({
211852
211925
  for (const t of tasks2) {
211853
211926
  if (!this.isPauseAbortParkCandidate(t)) continue;
211854
211927
  const columns = await this.resolvePauseAbortColumnsFor(t.id, columnCache);
211855
- if (this.classifyPausedAbortWorkflowRecovery(t, settings, executingIds.has(t.id), columns).kind !== "no-action") {
211928
+ if ((await this.classifyPausedAbortWorkflowRecovery(t, settings, executingIds.has(t.id), columns)).kind !== "no-action") {
211856
211929
  parked.push(t);
211857
211930
  }
211858
211931
  }
@@ -211869,7 +211942,7 @@ var init_self_healing = __esm({
211869
211942
  continue;
211870
211943
  }
211871
211944
  const freshColumns = await this.resolvePauseAbortColumnsFor(fresh.id, columnCache);
211872
- const route = this.classifyPausedAbortWorkflowRecovery(fresh, settings, latestExecutingIds.has(fresh.id), freshColumns);
211945
+ const route = await this.classifyPausedAbortWorkflowRecovery(fresh, settings, latestExecutingIds.has(fresh.id), freshColumns);
211873
211946
  if (route.kind === "no-action") {
211874
211947
  continue;
211875
211948
  }
@@ -218920,7 +218993,8 @@ var init_workflow_graph_executor = __esm({
218920
218993
  parseSteps: deps.parseStepsDeps,
218921
218994
  runCode: deps.runCode,
218922
218995
  notifyDispatch: deps.notifyDispatch,
218923
- prNodes: deps.prNodes
218996
+ prNodes: deps.prNodes,
218997
+ isLiveSharedBranchMember: deps.isLiveSharedBranchMember
218924
218998
  }),
218925
218999
  ...deps.runnerRegistry?.toHandlers() ?? {},
218926
219000
  ...deps.handlers ?? {}
@@ -220156,6 +220230,10 @@ var init_workflow_graph_task_runner = __esm({
220156
220230
  runCode: this.deps.runCode,
220157
220231
  notifyDispatch: this.deps.notifyDispatch,
220158
220232
  prNodes: this.deps.prNodes,
220233
+ // FNXC:SharedBranchMemberHold 2026-08-06-00:24: carry the executor's
220234
+ // live group resolver into the graph merge gate; omitting it turns
220235
+ // mission-policy members into manual holds before integration.
220236
+ isLiveSharedBranchMember: this.deps.isLiveSharedBranchMember,
220159
220237
  /*
220160
220238
  FNXC:WorkflowResume 2026-06-29-08:49:
220161
220239
  Production graph runs must fetch live task steps during foreach replay. The runner is the workflow boundary that has store access, so it supplies the fresh projection seam instead of making executor self-healing guess after a stale step node fails.
@@ -228268,6 +228346,7 @@ ${feedback}`,
228268
228346
  if (info.phase !== "pre-merge") return false;
228269
228347
  if (info.status !== "advisory_failure" && info.status !== "failed") return false;
228270
228348
  const liveTask = await this.store.getTask(taskId).catch(() => fallbackTask);
228349
+ if (hasUserAutoMergeHold(liveTask)) return false;
228271
228350
  const missingArtifactKeys = parseRequiredArtifactMissingValue(info.failureValue);
228272
228351
  if (missingArtifactKeys) {
228273
228352
  await this.recoverMissingRequiredArtifacts(liveTask, missingArtifactKeys, {
@@ -228524,6 +228603,7 @@ ${info.feedback}`, revisionKey),
228524
228603
  */
228525
228604
  async recoverFailedPreMergeWorkflowStep(task) {
228526
228605
  try {
228606
+ if (hasUserAutoMergeHold(task)) return false;
228527
228607
  const failed = (task.workflowStepResults ?? []).filter((r) => (r.phase || "pre-merge") === "pre-merge" && r.status === "failed").sort((a, b3) => {
228528
228608
  const aTs = Date.parse(a.completedAt || a.startedAt || "");
228529
228609
  const bTs = Date.parse(b3.completedAt || b3.startedAt || "");
@@ -229050,6 +229130,7 @@ ${info.feedback}`, revisionKey),
229050
229130
  getTask: (taskId) => this.store.getTask(taskId)
229051
229131
  },
229052
229132
  runId: resolvedRunId,
229133
+ isLiveSharedBranchMember: (nodeTask) => this.isLiveSharedBranchGroupMember(nodeTask),
229053
229134
  primitives: this.createAuthoritativeWorkflowPrimitives(settings),
229054
229135
  seams: this.createAuthoritativeWorkflowSeams(settings),
229055
229136
  prepareNodeExecution: (node, nodeTask, requirement) => this.prepareGraphNodeExecution(node, nodeTask, settings, requirement),
@@ -231991,6 +232072,7 @@ Graph value: ${failureValue}` : ""}`, budget.key),
231991
232072
  } catch {
231992
232073
  return false;
231993
232074
  }
232075
+ if (hasUserAutoMergeHold(live)) return false;
231994
232076
  const sharedBranchMember = await this.isLiveSharedBranchGroupMember(live);
231995
232077
  if (!sharedBranchMember && !allowsAutoMergeProcessing(live, settings)) return false;
231996
232078
  if (!sharedBranchMember && resolveEffectiveAutoMerge(live, settings) === false) return false;
@@ -232052,8 +232134,8 @@ Graph value: ${failureValue}` : ""}`, budget.key),
232052
232134
  } catch {
232053
232135
  return false;
232054
232136
  }
232055
- if (await this.isLiveSharedBranchGroupMember(live)) return false;
232056
- return !allowsAutoMergeProcessing(live, settings) || resolveEffectiveAutoMerge(live, settings) === false;
232137
+ if (await this.isLiveSharedBranchGroupMember(live) && !hasUserAutoMergeHold(live)) return false;
232138
+ return hasUserAutoMergeHold(live) || !allowsAutoMergeProcessing(live, settings) || resolveEffectiveAutoMerge(live, settings) === false;
232057
232139
  }
232058
232140
  async handleStaleInReviewPlanPauseAbortReplay(live, result2, abortProvenance, pausedAborted, userCanceled, resumeLanesMemo) {
232059
232141
  if (!pausedAborted) return false;
@@ -232217,9 +232299,9 @@ Graph value: ${failureValue}` : ""}`, budget.key),
232217
232299
  if (settings.globalPause === true) return false;
232218
232300
  }
232219
232301
  if (live.column === resumeLanes.review) {
232220
- if (live.autoMerge === false) return false;
232221
232302
  if (!settings) return false;
232222
232303
  const sharedBranchMember = await this.isLiveSharedBranchGroupMember(live);
232304
+ if (hasUserAutoMergeHold(live) || live.autoMerge === false && !sharedBranchMember) return false;
232223
232305
  if (!sharedBranchMember && !allowsAutoMergeProcessing(live, settings)) return false;
232224
232306
  if (live.mergeDetails?.mergeConfirmed === true) return false;
232225
232307
  }
@@ -249294,7 +249376,7 @@ var init_metric_parser = __esm({
249294
249376
  });
249295
249377
 
249296
249378
  // ../engine/src/eval/experiment-executor.ts
249297
- import { randomUUID as randomUUID44 } from "node:crypto";
249379
+ import { randomUUID as randomUUID45 } from "node:crypto";
249298
249380
  var ExperimentMaxIterationsError, ExperimentGitNotConfiguredError, ExperimentExecutor;
249299
249381
  var init_experiment_executor = __esm({
249300
249382
  "../engine/src/eval/experiment-executor.ts"() {
@@ -249362,7 +249444,7 @@ var init_experiment_executor = __esm({
249362
249444
  }
249363
249445
  await this.semaphore.acquire();
249364
249446
  const controller = new AbortController();
249365
- const runHandle = randomUUID44();
249447
+ const runHandle = randomUUID45();
249366
249448
  if (opts?.abortSignal) {
249367
249449
  opts.abortSignal.addEventListener("abort", () => controller.abort(), { once: true });
249368
249450
  }
@@ -258369,6 +258451,7 @@ var init_in_process_runtime = __esm({
258369
258451
  }
258370
258452
  }
258371
258453
  const prNodeGithubOps = this.config.prNodeGithubOps;
258454
+ const secretsStore = await this.taskStore.getSecretsStore();
258372
258455
  const executorOptions = {
258373
258456
  /*
258374
258457
  FNXC:PlanReviewLease 2026-07-26-21:12:
@@ -258384,6 +258467,7 @@ var init_in_process_runtime = __esm({
258384
258467
  cliAgentRuntime: this.cliAgentRuntime?.bundle,
258385
258468
  pluginRunner: this.pluginRunner,
258386
258469
  messageStore: this.messageStore,
258470
+ secretsStore,
258387
258471
  missionStore,
258388
258472
  reflectionService,
258389
258473
  // PR-entity nodes (U3): assemble the handler deps from the CLI-injected
@@ -258485,6 +258569,7 @@ var init_in_process_runtime = __esm({
258485
258569
  reflectionService,
258486
258570
  selfImproveService,
258487
258571
  credentialRotator: this.credentialRotator,
258572
+ secretsStore,
258488
258573
  snapshotManager: autoClaimSnapshotManager,
258489
258574
  onMissed: (agentId, reason) => {
258490
258575
  runtimeLog.warn(`Agent ${agentId} missed heartbeat: ${reason}`);
@@ -262346,7 +262431,21 @@ var init_project_engine = __esm({
262346
262431
  Cleared on the first non-busy outcome (success path resets it).
262347
262432
  */
262348
262433
  workspaceBusyReenqueues = /* @__PURE__ */ new Map();
262434
+ workspaceBusyReenqueueTimers = /* @__PURE__ */ new Set();
262349
262435
  static WORKSPACE_BUSY_MAX_REENQUEUES = 10;
262436
+ /*
262437
+ FNXC:WorkspaceMergeDispatch 2026-08-05-23:56:
262438
+ Workspace lease-contention retries are engine-owned lifecycle work, not detached callbacks.
262439
+ Track only these busy re-enqueue timers so stop() can cancel them and tests can measure the
262440
+ capped workspace ladder without confusing it with merge-body or maintenance timers.
262441
+ */
262442
+ scheduleWorkspaceBusyReenqueue(taskId, delayMs) {
262443
+ const timer2 = setTimeout(() => {
262444
+ this.workspaceBusyReenqueueTimers.delete(timer2);
262445
+ if (!this.shuttingDown) this.internalEnqueueMerge(taskId);
262446
+ }, delayMs);
262447
+ this.workspaceBusyReenqueueTimers.add(timer2);
262448
+ }
262350
262449
  /**
262351
262450
  * Pending manual merge resolvers — keyed by taskId.
262352
262451
  * When `onMerge` is called, the task is enqueued like auto-merge but a
@@ -262881,6 +262980,10 @@ ${detail}`);
262881
262980
  clearInterval(this.mergeActiveReconcileTimer);
262882
262981
  this.mergeActiveReconcileTimer = null;
262883
262982
  }
262983
+ for (const timer2 of this.workspaceBusyReenqueueTimers) {
262984
+ clearTimeout(timer2);
262985
+ }
262986
+ this.workspaceBusyReenqueueTimers.clear();
262884
262987
  for (const [taskId, deferred] of this.capacityDeferredMerges) {
262885
262988
  clearTimeout(deferred.timer);
262886
262989
  for (const resolver of deferred.resolvers) {
@@ -264180,16 +264283,15 @@ ${detail}`);
264180
264283
  * older low-priority task would start before a later urgent one.
264181
264284
  */
264182
264285
  async allowInReviewMergeProcessing(task, settings, store = this.runtime.getTaskStore()) {
264183
- if (allowsAutoMergeProcessing(task, settings)) {
264184
- return true;
264185
- }
264286
+ if (hasUserAutoMergeHold(task)) return false;
264186
264287
  const groupId = task.branchContext?.groupId?.trim();
264187
264288
  const branchGroup = groupId ? await store.getBranchGroup?.(groupId) : null;
264188
- if (!branchGroup || branchGroup.status !== "open" || !branchGroup.branchName.trim()) {
264189
- return false;
264190
- }
264191
264289
  const projectDefaultBranch = await resolveIntegrationBranch(this.config.workingDirectory, settings);
264192
- return isLiveSharedBranchGroupMemberIntegration(task, branchGroup, projectDefaultBranch);
264290
+ if (isLiveSharedBranchGroupMemberIntegration(task, branchGroup, projectDefaultBranch)) {
264291
+ return true;
264292
+ }
264293
+ if (task.autoMerge === false && groupId) return false;
264294
+ return allowsAutoMergeProcessing(task, settings);
264193
264295
  }
264194
264296
  async emitLegacyAutoMergeStampAdvisory(store) {
264195
264297
  if (this.legacyAutoMergeStampAdvisoryEmitted) {
@@ -265142,9 +265244,7 @@ ${detail}`);
265142
265244
  runtimeLog.log(
265143
265245
  `Workspace land busy re-enqueue ${busyCount + 1}/${_ProjectEngine.WORKSPACE_BUSY_MAX_REENQUEUES} for ${taskId} in ${delayMs / 1e3}s (no mergeRetry consumed \u2014 pure lease contention)`
265144
265246
  );
265145
- setTimeout(() => {
265146
- if (!this.shuttingDown) this.internalEnqueueMerge(taskId);
265147
- }, delayMs);
265247
+ this.scheduleWorkspaceBusyReenqueue(taskId, delayMs);
265148
265248
  } else {
265149
265249
  this.workspaceBusyReenqueues.delete(taskId);
265150
265250
  await store.updateTask(taskId, { status: "failed", error: errorMsg }).catch(() => void 0);
@@ -268782,7 +268882,7 @@ __export(planning_exports, {
268782
268882
  updatePlanningSessionTitle: () => updatePlanningSessionTitle,
268783
268883
  validateSession: () => validateSession
268784
268884
  });
268785
- import { randomUUID as randomUUID45 } from "node:crypto";
268885
+ import { randomUUID as randomUUID46 } from "node:crypto";
268786
268886
  import { EventEmitter as EventEmitter34 } from "node:events";
268787
268887
  async function createPlanningRuntimeSession(options) {
268788
268888
  const { pluginRunner, runtimeHint, settings, ...runtimeOptions } = options ?? {};
@@ -269246,7 +269346,7 @@ async function createSession(ip, initialPlan, store, rootDir, promptOverrides, p
269246
269346
  if (!store) {
269247
269347
  throw new Error("store is required for AI-powered planning sessions");
269248
269348
  }
269249
- const sessionId = randomUUID45();
269349
+ const sessionId = randomUUID46();
269250
269350
  const session = {
269251
269351
  id: sessionId,
269252
269352
  ip,
@@ -269461,7 +269561,7 @@ async function createDraftSession(ip, initialPlan, _rootDir, modelProvider, mode
269461
269561
  `Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR} planning sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
269462
269562
  );
269463
269563
  }
269464
- const sessionId = randomUUID45();
269564
+ const sessionId = randomUUID46();
269465
269565
  const title2 = DRAFT_PLACEHOLDER_TITLE;
269466
269566
  const hasModelOverride = Boolean(modelProvider && modelId);
269467
269567
  const session = {
@@ -269637,7 +269737,7 @@ async function createSessionWithAgent(ip, initialPlan, rootDir, store, modelProv
269637
269737
  `Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR} planning sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
269638
269738
  );
269639
269739
  }
269640
- const sessionId = randomUUID45();
269740
+ const sessionId = randomUUID46();
269641
269741
  const session = {
269642
269742
  id: sessionId,
269643
269743
  ip,
@@ -270147,7 +270247,7 @@ function normalizePlanningQuestion(input, userInput = "") {
270147
270247
  const type = source.type === "multi_select" || source.type === "single_select" ? source.type : "single_select";
270148
270248
  const question = typeof source.question === "string" && source.question.trim() ? source.question.trim() : fallback2.question;
270149
270249
  const normalized = {
270150
- id: typeof source.id === "string" && source.id.trim() ? source.id : randomUUID45(),
270250
+ id: typeof source.id === "string" && source.id.trim() ? source.id : randomUUID46(),
270151
270251
  type,
270152
270252
  question,
270153
270253
  ...typeof source.description === "string" && source.description.trim() ? { description: source.description.trim() } : {}
@@ -270173,7 +270273,7 @@ function normalizePlanningQuestion(input, userInput = "") {
270173
270273
  }
270174
270274
  function coerceQuestionResponse(response, session) {
270175
270275
  if (response.type === "question") return normalizePlanningQuestion(response.data, session.initialPlan);
270176
- return normalizePlanningQuestion({ id: randomUUID45(), type: "single_select", question: planningFallbackCopy(session.initialPlan).question }, session.initialPlan);
270276
+ return normalizePlanningQuestion({ id: randomUUID46(), type: "single_select", question: planningFallbackCopy(session.initialPlan).question }, session.initialPlan);
270177
270277
  }
270178
270278
  async function validateSession(sessionId) {
270179
270279
  const session = await getSession(sessionId);
@@ -271115,7 +271215,7 @@ async function createTaskFromPlanSession(sessionId, store, options) {
271115
271215
  throw new InvalidSessionStateError("PLANNING_CREATED_TASK_MISSING");
271116
271216
  }
271117
271217
  }
271118
- const claimOwnerToken = randomUUID45();
271218
+ const claimOwnerToken = randomUUID46();
271119
271219
  let claimed = await claimPlanningTaskCreation(sessionId, claimOwnerToken, (/* @__PURE__ */ new Date()).toISOString(), claimEpoch);
271120
271220
  if (!claimed) {
271121
271221
  session = await getDurablePlanningSession(sessionId).catch(() => void 0) ?? session;
@@ -271784,7 +271884,7 @@ __export(subtask_breakdown_exports, {
271784
271884
  stopSubtaskGeneration: () => stopSubtaskGeneration,
271785
271885
  subtaskStreamManager: () => subtaskStreamManager
271786
271886
  });
271787
- import { randomUUID as randomUUID46 } from "node:crypto";
271887
+ import { randomUUID as randomUUID47 } from "node:crypto";
271788
271888
  import { EventEmitter as EventEmitter35 } from "node:events";
271789
271889
  function __getSubtaskBreakdownDiagnostics() {
271790
271890
  return diagnostics3;
@@ -271959,7 +272059,7 @@ async function decomposeForTriage(description, rootDir, promptOverrides, store)
271959
272059
  }
271960
272060
  }
271961
272061
  async function createSubtaskSession(initialDescription, store, rootDir, promptOverrides, projectId) {
271962
- const sessionId = randomUUID46();
272062
+ const sessionId = randomUUID47();
271963
272063
  const session = {
271964
272064
  sessionId,
271965
272065
  projectId,
@@ -272396,7 +272496,7 @@ __export(mission_interview_exports, {
272396
272496
  stopMissionInterviewGeneration: () => stopMissionInterviewGeneration,
272397
272497
  submitMissionInterviewResponse: () => submitMissionInterviewResponse
272398
272498
  });
272399
- import { randomUUID as randomUUID47 } from "node:crypto";
272499
+ import { randomUUID as randomUUID48 } from "node:crypto";
272400
272500
  import { EventEmitter as EventEmitter36 } from "node:events";
272401
272501
  function __getMissionInterviewDiagnostics() {
272402
272502
  return diagnostics4;
@@ -273139,7 +273239,7 @@ async function createMissionInterviewSession(ip, missionTitle, rootDir, store, p
273139
273239
  `Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR2} sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
273140
273240
  );
273141
273241
  }
273142
- const sessionId = randomUUID47();
273242
+ const sessionId = randomUUID48();
273143
273243
  const session = {
273144
273244
  id: sessionId,
273145
273245
  ip,
@@ -273602,7 +273702,7 @@ __export(milestone_slice_interview_exports, {
273602
273702
  stopMilestoneSliceInterviewGeneration: () => stopMilestoneSliceInterviewGeneration,
273603
273703
  submitTargetInterviewResponse: () => submitTargetInterviewResponse
273604
273704
  });
273605
- import { randomUUID as randomUUID48 } from "node:crypto";
273705
+ import { randomUUID as randomUUID49 } from "node:crypto";
273606
273706
  import { EventEmitter as EventEmitter37 } from "node:events";
273607
273707
  function parseTargetInterviewResponseImpl(text3) {
273608
273708
  const candidate = extractJsonCandidate3(text3);
@@ -274231,7 +274331,7 @@ async function createTargetInterviewSession(ip, targetType, targetId, targetTitl
274231
274331
  `Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR3} sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
274232
274332
  );
274233
274333
  }
274234
- const sessionId = randomUUID48();
274334
+ const sessionId = randomUUID49();
274235
274335
  const session = {
274236
274336
  id: sessionId,
274237
274337
  ip,
@@ -293375,6 +293475,7 @@ function registerTaskWorkflowRoutes(ctx, deps) {
293375
293475
  reviewLevel,
293376
293476
  executionMode,
293377
293477
  autoMerge,
293478
+ autoMergeProvenance,
293378
293479
  priority,
293379
293480
  source,
293380
293481
  branch,
@@ -293424,6 +293525,9 @@ function registerTaskWorkflowRoutes(ctx, deps) {
293424
293525
  if (autoMerge !== void 0 && typeof autoMerge !== "boolean") {
293425
293526
  throw badRequest("autoMerge must be a boolean");
293426
293527
  }
293528
+ if (autoMergeProvenance !== void 0) {
293529
+ throw badRequest("autoMergeProvenance is server-managed");
293530
+ }
293427
293531
  if (priority !== void 0 && priority !== null && !isTaskPriority(priority)) {
293428
293532
  throw badRequest(`priority must be one of: ${TASK_PRIORITIES.join(", ")}`);
293429
293533
  }
@@ -296122,6 +296226,9 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
296122
296226
  if (hasBodyField("autoMerge") && autoMerge !== void 0 && autoMerge !== null && typeof autoMerge !== "boolean") {
296123
296227
  throw new Error("autoMerge must be a boolean");
296124
296228
  }
296229
+ if (hasBodyField("autoMergeProvenance")) {
296230
+ throw badRequest("autoMergeProvenance is server-managed");
296231
+ }
296125
296232
  let validatedSourceIssue;
296126
296233
  if (hasBodyField("sourceIssue")) {
296127
296234
  if (sourceIssue === null) {
@@ -296343,7 +296450,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
296343
296450
  if (dependencies !== void 0) updates.dependencies = dependencies;
296344
296451
  if (enabledWorkflowSteps !== void 0) updates.enabledWorkflowSteps = enabledWorkflowSteps;
296345
296452
  if (hasBodyField("noCommitsExpected")) updates.noCommitsExpected = noCommitsExpected;
296346
- if (hasBodyField("autoMerge")) updates.autoMerge = autoMerge === null ? void 0 : autoMerge;
296453
+ if (hasBodyField("autoMerge")) updates.autoMerge = autoMerge;
296347
296454
  if (hasBodyField("modelProvider")) updates.modelProvider = validatedModelProvider;
296348
296455
  if (hasBodyField("modelId")) updates.modelId = validatedModelId;
296349
296456
  if (hasBodyField("validatorModelProvider")) updates.validatorModelProvider = validatedValidatorModelProvider;
@@ -297941,7 +298048,7 @@ at this boundary regardless.`;
297941
298048
  });
297942
298049
 
297943
298050
  // ../dashboard/src/routes/register-planning-subtask-routes.ts
297944
- import { randomUUID as randomUUID49 } from "node:crypto";
298051
+ import { randomUUID as randomUUID50 } from "node:crypto";
297945
298052
  async function acquirePlanningCreateLock(sessionId) {
297946
298053
  const previous = planningCreateLocks.get(sessionId);
297947
298054
  let releaseGate;
@@ -298922,7 +299029,7 @@ function registerPlanningSubtaskRoutes(ctx, deps) {
298922
299029
  }
298923
299030
  session = await getDurablePlanningSession2(sessionId) ?? session;
298924
299031
  if (await returnLinkedTask(session)) return;
298925
- const claimOwnerToken = randomUUID49();
299032
+ const claimOwnerToken = randomUUID50();
298926
299033
  claimedOwnerToken = claimOwnerToken;
298927
299034
  claimedSessionId = sessionId;
298928
299035
  const claimStartedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -300098,7 +300205,7 @@ __export(chat_exports, {
300098
300205
  resolveFileReferences: () => resolveFileReferences
300099
300206
  });
300100
300207
  import { EventEmitter as EventEmitter40 } from "node:events";
300101
- import { randomUUID as randomUUID50 } from "node:crypto";
300208
+ import { randomUUID as randomUUID51 } from "node:crypto";
300102
300209
  import { existsSync as existsSync71 } from "node:fs";
300103
300210
  import { join as join90, resolve as resolve48, relative as relative20 } from "node:path";
300104
300211
  import { SessionManager as SessionManager3 } from "@earendil-works/pi-coding-agent";
@@ -300310,7 +300417,7 @@ function createTaskVerificationTools(taskStore, actionGateContext) {
300310
300417
  const settings = await taskStore.getSettings();
300311
300418
  const command = profile === "verify:fast" ? "pnpm verify:fast" : typeof settings.testCommand === "string" ? settings.testCommand : "";
300312
300419
  if (!command) return { content: [{ type: "text", text: "ERROR: the selected verification profile is not configured." }], isError: true, details: {} };
300313
- const created = await taskStore.createTaskVerificationRequest({ taskId, requestId: randomUUID50(), profile, command, scope: "workspace", requestedBy: "chat" });
300420
+ const created = await taskStore.createTaskVerificationRequest({ taskId, requestId: randomUUID51(), profile, command, scope: "workspace", requestedBy: "chat" });
300314
300421
  if (created.inFlightRequestId) return { content: [{ type: "text", text: `ERROR: verification request ${created.inFlightRequestId} is already in flight.` }], isError: true, details: created };
300315
300422
  return { content: [{ type: "text", text: `Queued verification request ${created.request.requestId} for ${taskId}.` }], details: created.request };
300316
300423
  }
@@ -302470,7 +302577,7 @@ var init_rate_limit = __esm({
302470
302577
  });
302471
302578
 
302472
302579
  // ../dashboard/src/routes/register-chat-routes.ts
302473
- import { randomUUID as randomUUID51 } from "node:crypto";
302580
+ import { randomUUID as randomUUID52 } from "node:crypto";
302474
302581
  import { createReadStream as createReadStream2 } from "node:fs";
302475
302582
  import { mkdir as mkdir30, rm as rm16, writeFile as writeFile32 } from "node:fs/promises";
302476
302583
  import { basename as basename22, join as join91, resolve as resolve49 } from "node:path";
@@ -302529,7 +302636,7 @@ function registerChatRoutes(ctx, deps) {
302529
302636
  const filePath = join91(sessionDir, filename);
302530
302637
  await writeFile32(filePath, file.buffer);
302531
302638
  return {
302532
- id: `att-${randomUUID51().slice(0, 8)}`,
302639
+ id: `att-${randomUUID52().slice(0, 8)}`,
302533
302640
  filename,
302534
302641
  originalName: file.originalname,
302535
302642
  mimeType: file.mimetype,
@@ -303296,7 +303403,7 @@ var init_register_chat_routes = __esm({
303296
303403
  });
303297
303404
 
303298
303405
  // ../dashboard/src/routes/register-chat-room-routes.ts
303299
- import { randomUUID as randomUUID52 } from "node:crypto";
303406
+ import { randomUUID as randomUUID53 } from "node:crypto";
303300
303407
  import { createReadStream as createReadStream3 } from "node:fs";
303301
303408
  import { mkdir as mkdir31, writeFile as writeFile33 } from "node:fs/promises";
303302
303409
  import { basename as basename23, join as join92, resolve as resolve50 } from "node:path";
@@ -303637,7 +303744,7 @@ function registerChatRoomRoutes(ctx, deps) {
303637
303744
  const filePath = join92(roomDir, filename);
303638
303745
  await writeFile33(filePath, file.buffer);
303639
303746
  const attachment = {
303640
- id: `att-${randomUUID52().slice(0, 8)}`,
303747
+ id: `att-${randomUUID53().slice(0, 8)}`,
303641
303748
  filename,
303642
303749
  originalName: file.originalname,
303643
303750
  mimeType: file.mimetype,
@@ -310152,6 +310259,17 @@ function assertObject(value) {
310152
310259
  throw badRequest("body must be an object");
310153
310260
  }
310154
310261
  }
310262
+ function getExplicitProjectId(req, ctx) {
310263
+ const projectId = ctx.getProjectIdFromRequest(req);
310264
+ if (!projectId) throw badRequest("projectId is required");
310265
+ return projectId;
310266
+ }
310267
+ async function getExplicitSecretsStore(req, ctx) {
310268
+ const requestedProjectId = getExplicitProjectId(req, ctx);
310269
+ const { store, projectId } = await ctx.getProjectContext(req);
310270
+ if (projectId !== requestedProjectId) throw badRequest("project context does not match projectId");
310271
+ return store.getSecretsStore();
310272
+ }
310155
310273
  function emitSecretsAudit(req, ctx, type, metadata) {
310156
310274
  const requestWithAuditor = req;
310157
310275
  if (requestWithAuditor.runAuditor?.filesystem) {
@@ -310167,11 +310285,10 @@ var init_register_secrets_routes = __esm({
310167
310285
  init_src2();
310168
310286
  init_api_error();
310169
310287
  registerSecretsRoutes = (ctx) => {
310170
- const { router, getProjectContext: getProjectContext2, rethrowAsApiError: rethrowAsApiError8 } = ctx;
310288
+ const { router, rethrowAsApiError: rethrowAsApiError8 } = ctx;
310171
310289
  router.get("/secrets", async (req, res) => {
310172
310290
  try {
310173
- const { store: scopedStore } = await getProjectContext2(req);
310174
- const secretsStore = await scopedStore.getSecretsStore();
310291
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310175
310292
  const secrets2 = await secretsStore.listSecrets();
310176
310293
  const visibleSecrets = secrets2.filter(
310177
310294
  (secret) => !(secret.scope === "global" && secret.key === RESERVED_SYNC_PASSPHRASE_KEY)
@@ -310185,8 +310302,7 @@ var init_register_secrets_routes = __esm({
310185
310302
  });
310186
310303
  router.get("/secrets/sync-passphrase", async (req, res) => {
310187
310304
  try {
310188
- const { store: scopedStore } = await getProjectContext2(req);
310189
- const secretsStore = await scopedStore.getSecretsStore();
310305
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310190
310306
  const configured = await hasSyncPassphraseConfigured(secretsStore);
310191
310307
  res.json({ configured });
310192
310308
  } catch (err) {
@@ -310197,14 +310313,14 @@ var init_register_secrets_routes = __esm({
310197
310313
  });
310198
310314
  router.put("/secrets/sync-passphrase", async (req, res) => {
310199
310315
  try {
310316
+ getExplicitProjectId(req, ctx);
310200
310317
  assertObject(req.body);
310201
310318
  const passphrase = req.body.passphrase;
310202
310319
  if (typeof passphrase !== "string" || passphrase.trim().length === 0) {
310203
310320
  res.status(400).json({ error: "invalid-passphrase" });
310204
310321
  return;
310205
310322
  }
310206
- const { store: scopedStore } = await getProjectContext2(req);
310207
- const secretsStore = await scopedStore.getSecretsStore();
310323
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310208
310324
  const hadConfiguredPassphrase = await hasSyncPassphraseConfigured(secretsStore);
310209
310325
  await setSyncPassphrase(secretsStore, passphrase);
310210
310326
  emitSecretsAudit(req, ctx, hadConfiguredPassphrase ? "secret:update" : "secret:create", {
@@ -310220,8 +310336,7 @@ var init_register_secrets_routes = __esm({
310220
310336
  });
310221
310337
  router.delete("/secrets/sync-passphrase", async (req, res) => {
310222
310338
  try {
310223
- const { store: scopedStore } = await getProjectContext2(req);
310224
- const secretsStore = await scopedStore.getSecretsStore();
310339
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310225
310340
  await clearSyncPassphrase(secretsStore);
310226
310341
  emitSecretsAudit(req, ctx, "secret:delete", { key: RESERVED_SYNC_PASSPHRASE_KEY, scope: "global" });
310227
310342
  res.json({ success: true });
@@ -310233,6 +310348,7 @@ var init_register_secrets_routes = __esm({
310233
310348
  });
310234
310349
  router.post("/secrets", async (req, res) => {
310235
310350
  try {
310351
+ getExplicitProjectId(req, ctx);
310236
310352
  assertObject(req.body);
310237
310353
  const { scope, key, value, description, accessPolicy, envExportable, envExportKey } = req.body;
310238
310354
  const parsedScope = parseScope(scope);
@@ -310249,8 +310365,7 @@ var init_register_secrets_routes = __esm({
310249
310365
  }
310250
310366
  parsedAccessPolicy = accessPolicy;
310251
310367
  }
310252
- const { store: scopedStore } = await getProjectContext2(req);
310253
- const secretsStore = await scopedStore.getSecretsStore();
310368
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310254
310369
  const secret = await secretsStore.createSecret({
310255
310370
  scope: parsedScope,
310256
310371
  key,
@@ -310269,6 +310384,7 @@ var init_register_secrets_routes = __esm({
310269
310384
  });
310270
310385
  router.patch("/secrets/:scope/:id", async (req, res) => {
310271
310386
  try {
310387
+ getExplicitProjectId(req, ctx);
310272
310388
  const scope = parseScope(req.params.scope);
310273
310389
  const id = String(req.params.id ?? "").trim();
310274
310390
  if (!id) throw badRequest("id is required");
@@ -310312,8 +310428,7 @@ var init_register_secrets_routes = __esm({
310312
310428
  patch.plaintextValue = req.body.value;
310313
310429
  }
310314
310430
  }
310315
- const { store: scopedStore } = await getProjectContext2(req);
310316
- const secretsStore = await scopedStore.getSecretsStore();
310431
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310317
310432
  const secret = await secretsStore.updateSecret(id, scope, patch);
310318
310433
  res.json(secret);
310319
310434
  } catch (err) {
@@ -310324,11 +310439,11 @@ var init_register_secrets_routes = __esm({
310324
310439
  });
310325
310440
  router.delete("/secrets/:scope/:id", async (req, res) => {
310326
310441
  try {
310442
+ getExplicitProjectId(req, ctx);
310327
310443
  const scope = parseScope(req.params.scope);
310328
310444
  const id = String(req.params.id ?? "").trim();
310329
310445
  if (!id) throw badRequest("id is required");
310330
- const { store: scopedStore } = await getProjectContext2(req);
310331
- const secretsStore = await scopedStore.getSecretsStore();
310446
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310332
310447
  await secretsStore.deleteSecret(id, scope);
310333
310448
  res.status(204).send();
310334
310449
  } catch (err) {
@@ -310339,11 +310454,11 @@ var init_register_secrets_routes = __esm({
310339
310454
  });
310340
310455
  router.post("/secrets/:scope/:id/reveal", async (req, res) => {
310341
310456
  try {
310457
+ getExplicitProjectId(req, ctx);
310342
310458
  const scope = parseScope(req.params.scope);
310343
310459
  const id = String(req.params.id ?? "").trim();
310344
310460
  if (!id) throw badRequest("id is required");
310345
- const { store: scopedStore } = await getProjectContext2(req);
310346
- const secretsStore = await scopedStore.getSecretsStore();
310461
+ const secretsStore = await getExplicitSecretsStore(req, ctx);
310347
310462
  const secret = await secretsStore.revealSecret(id, scope, {
310348
310463
  userId: null
310349
310464
  });
@@ -311942,7 +312057,7 @@ var init_register_gitlab = __esm({
311942
312057
 
311943
312058
  // ../dashboard/src/terminal.ts
311944
312059
  import { spawn as spawn11 } from "node:child_process";
311945
- import { randomUUID as randomUUID53 } from "node:crypto";
312060
+ import { randomUUID as randomUUID54 } from "node:crypto";
311946
312061
  import { EventEmitter as EventEmitter42 } from "node:events";
311947
312062
  function extractBaseCommand(command) {
311948
312063
  let trimmed = command.trim();
@@ -312102,7 +312217,7 @@ var init_terminal = __esm({
312102
312217
  if (!validation.valid) {
312103
312218
  return { sessionId: "", error: validation.error };
312104
312219
  }
312105
- const sessionId = randomUUID53();
312220
+ const sessionId = randomUUID54();
312106
312221
  const childProcess6 = spawn11(command, [], {
312107
312222
  cwd,
312108
312223
  shell: true,
@@ -340912,7 +341027,7 @@ var init_register_node_routes = __esm({
340912
341027
  });
340913
341028
 
340914
341029
  // ../dashboard/src/routes/register-docker-node-routes.ts
340915
- import { randomUUID as randomUUID54 } from "node:crypto";
341030
+ import { randomUUID as randomUUID55 } from "node:crypto";
340916
341031
  function sanitizeHostConfig(input) {
340917
341032
  const host = input ?? {};
340918
341033
  return {
@@ -341291,7 +341406,7 @@ var init_register_docker_node_routes = __esm({
341291
341406
  if (!managedNode) {
341292
341407
  throw notFound("Managed Docker node not found");
341293
341408
  }
341294
- const newKey = randomUUID54().replace(/-/g, "");
341409
+ const newKey = randomUUID55().replace(/-/g, "");
341295
341410
  await central.updateManagedDockerNode(managedId, { apiKey: newKey });
341296
341411
  if (managedNode.nodeId) {
341297
341412
  await central.updateNode(managedNode.nodeId, { apiKey: newKey });
@@ -350159,7 +350274,7 @@ var init_register_agent_reflection_rating_routes = __esm({
350159
350274
  });
350160
350275
 
350161
350276
  // ../dashboard/src/agent-generation.ts
350162
- import { randomUUID as randomUUID55 } from "node:crypto";
350277
+ import { randomUUID as randomUUID56 } from "node:crypto";
350163
350278
  async function initPromptCatalog() {
350164
350279
  if (promptCatalogReady) return;
350165
350280
  try {
@@ -350365,7 +350480,7 @@ async function startAgentGeneration(ip, roleDescription) {
350365
350480
  `Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR4} generation sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
350366
350481
  );
350367
350482
  }
350368
- const sessionId = randomUUID55();
350483
+ const sessionId = randomUUID56();
350369
350484
  const session = {
350370
350485
  id: sessionId,
350371
350486
  ip,
@@ -350564,7 +350679,7 @@ __export(agent_onboarding_exports, {
350564
350679
  startAgentOnboardingSession: () => startAgentOnboardingSession,
350565
350680
  stopAgentOnboardingGeneration: () => stopAgentOnboardingGeneration
350566
350681
  });
350567
- import { randomUUID as randomUUID56 } from "node:crypto";
350682
+ import { randomUUID as randomUUID57 } from "node:crypto";
350568
350683
  import { EventEmitter as EventEmitter43 } from "node:events";
350569
350684
  function extractJsonCandidate6(text3) {
350570
350685
  const codeBlockMatch = text3.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
@@ -350664,7 +350779,7 @@ Current agent configuration:
350664
350779
  ${currentConfigLines}`;
350665
350780
  }
350666
350781
  async function startAgentOnboardingSession(ip, initialContext, rootDir, modelProvider, modelId, promptOverrides, pluginRunner, store) {
350667
- const id = randomUUID56();
350782
+ const id = randomUUID57();
350668
350783
  const mode = initialContext.mode ?? "create";
350669
350784
  const session = {
350670
350785
  id,
@@ -353446,7 +353561,7 @@ var init_src8 = __esm({
353446
353561
 
353447
353562
  // ../../plugins/fusion-plugin-openclaw-runtime/src/pi-module.ts
353448
353563
  import { spawn as spawn15 } from "node:child_process";
353449
- import { randomUUID as randomUUID57 } from "node:crypto";
353564
+ import { randomUUID as randomUUID58 } from "node:crypto";
353450
353565
  import { readFile as readFile51 } from "node:fs/promises";
353451
353566
  function asString2(v2) {
353452
353567
  return typeof v2 === "string" && v2.trim() !== "" ? v2.trim() : void 0;
@@ -353506,7 +353621,7 @@ function extractStderrError(stderr, stdout) {
353506
353621
  }
353507
353622
  function createCliSession(opts) {
353508
353623
  return {
353509
- sessionId: randomUUID57(),
353624
+ sessionId: randomUUID58(),
353510
353625
  agentId: opts.agentId ?? DEFAULT_AGENT_ID,
353511
353626
  systemPrompt: opts.systemPrompt,
353512
353627
  messages: [{ role: "developer", content: opts.systemPrompt }],
@@ -353701,7 +353816,7 @@ var init_mcp_config2 = __esm({
353701
353816
  });
353702
353817
 
353703
353818
  // ../../plugins/fusion-plugin-openclaw-runtime/src/runtime-adapter.ts
353704
- import { randomUUID as randomUUID58 } from "node:crypto";
353819
+ import { randomUUID as randomUUID59 } from "node:crypto";
353705
353820
  var OpenClawRuntimeAdapter;
353706
353821
  var init_runtime_adapter2 = __esm({
353707
353822
  "../../plugins/fusion-plugin-openclaw-runtime/src/runtime-adapter.ts"() {
@@ -353724,8 +353839,8 @@ var init_runtime_adapter2 = __esm({
353724
353839
  let mcpProfile;
353725
353840
  let mcpConfigPath;
353726
353841
  if (toolDefs.length > 0) {
353727
- const bridge = writeOpenClawMcpBridgeFiles(toolDefs, randomUUID58());
353728
- mcpProfile = `fusion-${randomUUID58()}`;
353842
+ const bridge = writeOpenClawMcpBridgeFiles(toolDefs, randomUUID59());
353843
+ mcpProfile = `fusion-${randomUUID59()}`;
353729
353844
  mcpConfigPath = bridge.serverConfigPath;
353730
353845
  await configureOpenClawMcpServer({
353731
353846
  binaryPath: this.config.binaryPath,
@@ -357780,7 +357895,7 @@ import { existsSync as existsSync77, writeFileSync as writeFileSync15 } from "no
357780
357895
  import { tmpdir as tmpdir17 } from "node:os";
357781
357896
  import { dirname as dirname45, join as join104 } from "node:path";
357782
357897
  import { fileURLToPath as fileURLToPath11 } from "node:url";
357783
- import { randomUUID as randomUUID59 } from "node:crypto";
357898
+ import { randomUUID as randomUUID60 } from "node:crypto";
357784
357899
  function toolsToMcpToolDefs2(tools) {
357785
357900
  if (!Array.isArray(tools)) return [];
357786
357901
  return tools.filter((tool) => tool && typeof tool.name === "string" && tool.name.trim().length > 0 && !BUILT_IN_TOOL_NAMES2.has(tool.name)).map((tool) => ({
@@ -357831,7 +357946,7 @@ async function startFusionToolBridge(tools) {
357831
357946
  byName.set(tool.name, tool);
357832
357947
  }
357833
357948
  }
357834
- const schemaPath = join104(tmpdir17(), `fusion-grok-mcp-schemas-${process.pid}-${randomUUID59()}.json`);
357949
+ const schemaPath = join104(tmpdir17(), `fusion-grok-mcp-schemas-${process.pid}-${randomUUID60()}.json`);
357835
357950
  writeFileSync15(schemaPath, JSON.stringify(defs));
357836
357951
  const server = createServer2(async (req, res) => {
357837
357952
  if (req.method !== "POST" || req.url !== "/tool-call") {
@@ -357857,7 +357972,7 @@ async function startFusionToolBridge(tools) {
357857
357972
  return;
357858
357973
  }
357859
357974
  try {
357860
- const result2 = await tool.execute(`grok-mcp-${randomUUID59()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
357975
+ const result2 = await tool.execute(`grok-mcp-${randomUUID60()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
357861
357976
  res.statusCode = 200;
357862
357977
  res.setHeader("content-type", "application/json");
357863
357978
  res.end(
@@ -359901,7 +360016,7 @@ import { existsSync as existsSync81, rmSync as rmSync13, writeFileSync as writeF
359901
360016
  import { tmpdir as tmpdir19 } from "node:os";
359902
360017
  import { dirname as dirname50, join as join109 } from "node:path";
359903
360018
  import { fileURLToPath as fileURLToPath15 } from "node:url";
359904
- import { randomBytes as randomBytes8, randomUUID as randomUUID60 } from "node:crypto";
360019
+ import { randomBytes as randomBytes8, randomUUID as randomUUID61 } from "node:crypto";
359905
360020
  function toolsToMcpToolDefs3(tools) {
359906
360021
  if (!Array.isArray(tools)) return [];
359907
360022
  return tools.filter((tool) => tool && typeof tool.name === "string" && tool.name.trim().length > 0 && !BUILT_IN_TOOL_NAMES3.has(tool.name)).map((tool) => ({
@@ -359952,7 +360067,7 @@ async function startFusionToolBridge2(tools, options = {}) {
359952
360067
  byName.set(tool.name, tool);
359953
360068
  }
359954
360069
  }
359955
- const schemaPath = join109(tmpdir19(), `fusion-claude-mcp-schemas-${process.pid}-${randomUUID60()}.json`);
360070
+ const schemaPath = join109(tmpdir19(), `fusion-claude-mcp-schemas-${process.pid}-${randomUUID61()}.json`);
359956
360071
  writeFileSync17(schemaPath, JSON.stringify(defs));
359957
360072
  const capabilityToken = randomBytes8(32).toString("base64url");
359958
360073
  const server = createServer3(async (req, res) => {
@@ -360017,7 +360132,7 @@ async function startFusionToolBridge2(tools, options = {}) {
360017
360132
  return;
360018
360133
  }
360019
360134
  try {
360020
- const result2 = await tool.execute(`claude-mcp-${randomUUID60()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
360135
+ const result2 = await tool.execute(`claude-mcp-${randomUUID61()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
360021
360136
  res.statusCode = 200;
360022
360137
  res.setHeader("content-type", "application/json");
360023
360138
  res.end(
@@ -362094,7 +362209,7 @@ import { existsSync as existsSync83, unlinkSync as unlinkSync5, writeFileSync as
362094
362209
  import { tmpdir as tmpdir20 } from "node:os";
362095
362210
  import { dirname as dirname53, join as join112 } from "node:path";
362096
362211
  import { fileURLToPath as fileURLToPath17 } from "node:url";
362097
- import { randomUUID as randomUUID61 } from "node:crypto";
362212
+ import { randomUUID as randomUUID62 } from "node:crypto";
362098
362213
  function toolsToMcpToolDefs4(tools) {
362099
362214
  if (!Array.isArray(tools)) return [];
362100
362215
  return tools.filter(
@@ -362151,7 +362266,7 @@ async function startFusionToolBridge3(tools) {
362151
362266
  byName.set(tool.name, tool);
362152
362267
  }
362153
362268
  }
362154
- const schemaPath = join112(tmpdir20(), `fusion-omp-mcp-schemas-${process.pid}-${randomUUID61()}.json`);
362269
+ const schemaPath = join112(tmpdir20(), `fusion-omp-mcp-schemas-${process.pid}-${randomUUID62()}.json`);
362155
362270
  writeFileSync18(schemaPath, JSON.stringify(defs));
362156
362271
  const server = createServer4(async (req, res) => {
362157
362272
  if (req.method !== "POST" || req.url !== "/tool-call") {
@@ -362178,7 +362293,7 @@ async function startFusionToolBridge3(tools) {
362178
362293
  }
362179
362294
  try {
362180
362295
  const result2 = await tool.execute(
362181
- `omp-mcp-${randomUUID61()}`,
362296
+ `omp-mcp-${randomUUID62()}`,
362182
362297
  parsed.arguments ?? {},
362183
362298
  void 0,
362184
362299
  void 0,
@@ -363274,7 +363389,7 @@ var init_paperclip_client = __esm({
363274
363389
  });
363275
363390
 
363276
363391
  // ../../plugins/fusion-plugin-paperclip-runtime/src/runtime-adapter.ts
363277
- import { randomUUID as randomUUID62 } from "node:crypto";
363392
+ import { randomUUID as randomUUID63 } from "node:crypto";
363278
363393
  function sleep7(ms2) {
363279
363394
  return new Promise((resolve104) => setTimeout(resolve104, ms2));
363280
363395
  }
@@ -363403,7 +363518,7 @@ var init_runtime_adapter10 = __esm({
363403
363518
  apiKey: effectiveApiKey,
363404
363519
  agentId,
363405
363520
  companyId,
363406
- sessionId: randomUUID62(),
363521
+ sessionId: randomUUID63(),
363407
363522
  systemPrompt: options.systemPrompt,
363408
363523
  cwd: options.cwd,
363409
363524
  mode: normalizeMode3(this.config.mode),
@@ -366903,7 +367018,7 @@ var init_command_center_csv = __esm({
366903
367018
  });
366904
367019
 
366905
367020
  // ../dashboard/src/monitor-store.ts
366906
- import { randomUUID as randomUUID63 } from "node:crypto";
367021
+ import { randomUUID as randomUUID64 } from "node:crypto";
366907
367022
  function monitorProjectId(layer) {
366908
367023
  if (!layer.projectId) {
366909
367024
  throw new Error("PostgreSQL monitor writes require asyncLayer.projectId");
@@ -366935,7 +367050,7 @@ async function recordDeployment(db, input) {
366935
367050
  return recordDeploymentAsync(layer.db, input, monitorProjectId(layer));
366936
367051
  }
366937
367052
  const sqliteDb = db;
366938
- const deploymentId = input.deploymentId?.trim() || `dep-${randomUUID63()}`;
367053
+ const deploymentId = input.deploymentId?.trim() || `dep-${randomUUID64()}`;
366939
367054
  const now = (/* @__PURE__ */ new Date()).toISOString();
366940
367055
  const deployedAt = input.deployedAt ?? now;
366941
367056
  const meta2 = input.meta ? JSON.stringify(input.meta) : null;
@@ -367001,7 +367116,7 @@ async function ingestIncidentSignal(db, input) {
367001
367116
  const updated = getIncident(sqliteDb, existing.incidentId);
367002
367117
  return { incident: updated ?? existing, created: false };
367003
367118
  }
367004
- const incidentId = `inc-${randomUUID63()}`;
367119
+ const incidentId = `inc-${randomUUID64()}`;
367005
367120
  const meta2 = {
367006
367121
  ...input.meta ?? {},
367007
367122
  [OCCURRENCES_META_KEY2]: 1,
@@ -371602,7 +371717,7 @@ var init_types6 = __esm({
371602
371717
  });
371603
371718
 
371604
371719
  // ../dashboard/src/stt/model-manager.ts
371605
- import { createHash as createHash31, randomUUID as randomUUID64 } from "node:crypto";
371720
+ import { createHash as createHash31, randomUUID as randomUUID65 } from "node:crypto";
371606
371721
  import { mkdir as mkdir38, open as open4, readFile as readFile56, readdir as readdir14, rename as rename10, rm as rm21, stat as stat16, writeFile as writeFile37 } from "node:fs/promises";
371607
371722
  import { join as join118, relative as relative22, resolve as resolve68, sep as sep18 } from "node:path";
371608
371723
  function parseSafeTarListing(listing) {
@@ -371683,8 +371798,8 @@ function createVoiceModelManager(options = {}) {
371683
371798
  if (!current(g2, signal)) return state;
371684
371799
  await mkdir38(cacheDir(), { recursive: true });
371685
371800
  if (!current(g2, signal)) return state;
371686
- partial2 = join118(cacheDir(), `.partial-${g2}-${randomUUID64()}`);
371687
- staging = join118(cacheDir(), `.staging-${g2}-${randomUUID64()}`);
371801
+ partial2 = join118(cacheDir(), `.partial-${g2}-${randomUUID65()}`);
371802
+ staging = join118(cacheDir(), `.staging-${g2}-${randomUUID65()}`);
371688
371803
  const file = await open4(partial2, "wx");
371689
371804
  try {
371690
371805
  const response = await (options.fetch ?? globalThis.fetch)(asset.url, { signal });
@@ -371732,7 +371847,7 @@ function createVoiceModelManager(options = {}) {
371732
371847
  await writeFile37(join118(staging, "manifest.json"), JSON.stringify({ filename: asset.filename, sha256: asset.sha256, installedAt: (/* @__PURE__ */ new Date()).toISOString(), expectedFiles: asset.expectedFiles }));
371733
371848
  await options.beforePromote?.(signal);
371734
371849
  if (!current(g2, signal)) return state;
371735
- const backup = join118(cacheDir(), `.backup-${g2}-${randomUUID64()}`);
371850
+ const backup = join118(cacheDir(), `.backup-${g2}-${randomUUID65()}`);
371736
371851
  let movedPrevious = false;
371737
371852
  try {
371738
371853
  try {
@@ -371953,7 +372068,7 @@ var init_parakeet_service = __esm({
371953
372068
  });
371954
372069
 
371955
372070
  // ../dashboard/src/routes/register-voice-routes.ts
371956
- import { randomUUID as randomUUID65 } from "node:crypto";
372071
+ import { randomUUID as randomUUID66 } from "node:crypto";
371957
372072
  import express from "express";
371958
372073
  async function settingsFor(ctx, req) {
371959
372074
  const scoped = await ctx.getScopedStore(req);
@@ -372032,7 +372147,7 @@ function createRegisterVoiceRoutes(deps = {}) {
372032
372147
  recognizer.close();
372033
372148
  return error2(res, 409, { error: "unavailable", reason: "model-removed" });
372034
372149
  }
372035
- const id = randomUUID65();
372150
+ const id = randomUUID66();
372036
372151
  const now = Date.now();
372037
372152
  sessions7.set(id, { projectId, recognizer, next: 0, bytes: 0, last: now, expires: now + 3e5 });
372038
372153
  res.status(201).json({ sessionId: id, expiresAt: new Date(now + 3e5).toISOString(), modelId: model.id, language: language.language });
@@ -372503,7 +372618,7 @@ var init_fn_binary_local_install = __esm({
372503
372618
  });
372504
372619
 
372505
372620
  // ../dashboard/src/routes/register-system-routes.ts
372506
- import { randomUUID as randomUUID66 } from "node:crypto";
372621
+ import { randomUUID as randomUUID67 } from "node:crypto";
372507
372622
  import { existsSync as existsSync87 } from "node:fs";
372508
372623
  import { join as join120 } from "node:path";
372509
372624
  function rejectCrossOrigin(req, res) {
@@ -372700,7 +372815,7 @@ function registerSystemRoutes(ctx, deps) {
372700
372815
  throw new ApiError(409, `Build script missing: ${scriptPath}`);
372701
372816
  }
372702
372817
  const job = {
372703
- id: randomUUID66(),
372818
+ id: randomUUID67(),
372704
372819
  kind: "rebuild",
372705
372820
  scope,
372706
372821
  restartAfter,
@@ -372990,7 +373105,7 @@ function registerSystemRoutes(ctx, deps) {
372990
373105
  throw new ApiError(409, `A ${activeJob.kind}/${activeJob.scope} job is already running`);
372991
373106
  }
372992
373107
  const job = {
372993
- id: randomUUID66(),
373108
+ id: randomUUID67(),
372994
373109
  kind,
372995
373110
  scope,
372996
373111
  restartAfter,
@@ -373278,7 +373393,7 @@ var init_cli_agent_settings = __esm({
373278
373393
 
373279
373394
  // ../dashboard/src/mission-routes.ts
373280
373395
  import { Router as Router5 } from "express";
373281
- import { AsyncLocalStorage } from "node:async_hooks";
373396
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
373282
373397
  function resolveMissionInterviewThinkingLevel(settings, thinkingLevel) {
373283
373398
  return resolvePlanningThinkingLevel(settings, thinkingLevel);
373284
373399
  }
@@ -373462,7 +373577,7 @@ function replayBufferedSSE(res, bufferedEvents) {
373462
373577
  }
373463
373578
  function createMissionRouter(store, missionAutopilot, aiSessionStore, missionExecutionLoop, engineManager, pluginRunner, options) {
373464
373579
  const router = Router5();
373465
- const requestContext = new AsyncLocalStorage();
373580
+ const requestContext = new AsyncLocalStorage2();
373466
373581
  function getScopedStore2() {
373467
373582
  return requestContext.getStore() ?? store;
373468
373583
  }
@@ -375973,11 +376088,11 @@ var init_mission_routes = __esm({
375973
376088
  });
375974
376089
 
375975
376090
  // ../dashboard/src/ideation-routes.ts
375976
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
376091
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
375977
376092
  import { Router as Router6 } from "express";
375978
376093
  function createIdeationRouter(store, options) {
375979
376094
  const router = Router6();
375980
- const requestContext = new AsyncLocalStorage2();
376095
+ const requestContext = new AsyncLocalStorage3();
375981
376096
  const ideation = () => (requestContext.getStore() ?? store).getIdeationStore();
375982
376097
  router.use(async (req, _res, next) => {
375983
376098
  try {
@@ -376161,7 +376276,7 @@ var init_insight_run_sweeper = __esm({
376161
376276
 
376162
376277
  // ../dashboard/src/insights-routes.ts
376163
376278
  import { Router as Router7 } from "express";
376164
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
376279
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
376165
376280
  function rethrowAsApiError4(error3, fallbackMessage = "Internal server error") {
376166
376281
  if (error3 instanceof ApiError) throw error3;
376167
376282
  if (error3 instanceof Error) throw new ApiError(500, error3.message);
@@ -376305,7 +376420,7 @@ function toInsightTitle(content) {
376305
376420
  }
376306
376421
  function createInsightsRouter(store, options) {
376307
376422
  const router = Router7();
376308
- const requestContext = new AsyncLocalStorage3();
376423
+ const requestContext = new AsyncLocalStorage4();
376309
376424
  let rootInsightStore;
376310
376425
  if (typeof store.getInsightStore === "function") {
376311
376426
  try {
@@ -376809,7 +376924,7 @@ var init_insights_routes = __esm({
376809
376924
 
376810
376925
  // ../dashboard/src/evals-routes.ts
376811
376926
  import { Router as Router8 } from "express";
376812
- import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
376927
+ import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
376813
376928
  function rethrowAsApiError5(error3, fallbackMessage = "Internal server error") {
376814
376929
  if (error3 instanceof ApiError) throw error3;
376815
376930
  if (error3 instanceof Error) throw new ApiError(500, error3.message);
@@ -376836,7 +376951,7 @@ function normalizeEvalText(result2) {
376836
376951
  }
376837
376952
  function createEvalsRouter(store, options) {
376838
376953
  const router = Router8();
376839
- const requestContext = new AsyncLocalStorage4();
376954
+ const requestContext = new AsyncLocalStorage5();
376840
376955
  router.use((req, _res, next) => {
376841
376956
  getScopedStore(req, store, options).then((scopedStore) => requestContext.run(scopedStore, () => next())).catch((err) => {
376842
376957
  try {
@@ -376920,7 +377035,7 @@ var init_evals_routes = __esm({
376920
377035
 
376921
377036
  // ../dashboard/src/research-routes.ts
376922
377037
  import { Router as Router9 } from "express";
376923
- import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
377038
+ import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
376924
377039
  function rethrowAsApiError6(error3, fallback2 = "Internal server error") {
376925
377040
  if (error3 instanceof ApiError) throw error3;
376926
377041
  if (error3 instanceof ResearchLifecycleError) {
@@ -377012,7 +377127,7 @@ async function addFindingAttachment(scopedStore, taskId, filename, markdown) {
377012
377127
  }
377013
377128
  function createResearchRouter(store, options) {
377014
377129
  const router = Router9();
377015
- const requestContext = new AsyncLocalStorage5();
377130
+ const requestContext = new AsyncLocalStorage6();
377016
377131
  router.use((req, _res, next) => {
377017
377132
  getScopedStore(req, store, options).then((scopedStore) => requestContext.run(scopedStore, () => next())).catch((error3) => {
377018
377133
  try {
@@ -377515,7 +377630,7 @@ var init_experiment_routes = __esm({
377515
377630
 
377516
377631
  // ../dashboard/src/goals-routes.ts
377517
377632
  import { Router as Router11 } from "express";
377518
- import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
377633
+ import { AsyncLocalStorage as AsyncLocalStorage7 } from "node:async_hooks";
377519
377634
  function getGoalStore(store) {
377520
377635
  return store.getGoalStore();
377521
377636
  }
@@ -377571,7 +377686,7 @@ function rethrowGoalCapError(error3) {
377571
377686
  }
377572
377687
  function createGoalsRouter(store, options) {
377573
377688
  const router = Router11();
377574
- const requestContext = new AsyncLocalStorage6();
377689
+ const requestContext = new AsyncLocalStorage7();
377575
377690
  function getScopedStore2() {
377576
377691
  return requestContext.getStore() ?? store;
377577
377692
  }
@@ -384244,7 +384359,7 @@ var init_provider_health_monitor = __esm({
384244
384359
 
384245
384360
  // ../dashboard/src/server.ts
384246
384361
  import express3 from "express";
384247
- import { randomUUID as randomUUID67 } from "node:crypto";
384362
+ import { randomUUID as randomUUID68 } from "node:crypto";
384248
384363
  import { join as join125, dirname as dirname57 } from "node:path";
384249
384364
  import { existsSync as existsSync89, readFileSync as readFileSync32, statSync as statSync16 } from "node:fs";
384250
384365
  import { fileURLToPath as fileURLToPath18 } from "node:url";
@@ -385709,7 +385824,7 @@ function setupBadgeWebSocket(app, server, store, options) {
385709
385824
  const dashboardApp = app;
385710
385825
  const wsManager = new WebSocketManager();
385711
385826
  const badgeSnapshots = /* @__PURE__ */ new Map();
385712
- const serverId = randomUUID67();
385827
+ const serverId = randomUUID68();
385713
385828
  const badgePubSub = options?.badgePubSub ?? createBadgePubSub({ sourceId: serverId });
385714
385829
  void badgePubSub.start();
385715
385830
  const scopedStores = /* @__PURE__ */ new Map();
@@ -385851,7 +385966,7 @@ function setupBadgeWebSocket(app, server, store, options) {
385851
385966
  const url2 = new URL(req.url || "", `http://${req.headers.host}`);
385852
385967
  const projectId = url2.searchParams.get("projectId") ?? "default";
385853
385968
  void ensureScopedListeners(projectId);
385854
- wsManager.addClient(ws2, randomUUID67(), projectId);
385969
+ wsManager.addClient(ws2, randomUUID68(), projectId);
385855
385970
  });
385856
385971
  server.once("close", async () => {
385857
385972
  for (const cleanup of scopedCleanups.values()) {
@@ -386683,7 +386798,7 @@ import { Type as Type9 } from "typebox";
386683
386798
  import { StringEnum } from "@earendil-works/pi-ai";
386684
386799
  import { resolve as resolve75, relative as relative25, isAbsolute as isAbsolute33, sep as sep22, basename as basename36, extname as extname5, join as join127 } from "node:path";
386685
386800
  import { existsSync as existsSync90 } from "node:fs";
386686
- import { AsyncLocalStorage as AsyncLocalStorage7 } from "node:async_hooks";
386801
+ import { AsyncLocalStorage as AsyncLocalStorage8 } from "node:async_hooks";
386687
386802
  function resolveProjectRoot2(cwd) {
386688
386803
  const worktreeProjectRoot = typeof getProjectRootFromWorktree === "function" ? getProjectRootFromWorktree(cwd) : null;
386689
386804
  if (typeof getProjectRootFromWorktree !== "function" && !warnedMissingProjectRootResolver) {
@@ -386749,7 +386864,7 @@ var init_extension = __esm({
386749
386864
  storeCache2 = extensionStoreState.cache;
386750
386865
  storeBootInflight = extensionStoreState.bootInflight;
386751
386866
  storeBootFailureCooldown = extensionStoreState.bootFailureCooldown;
386752
- extensionToolSignal = new AsyncLocalStorage7();
386867
+ extensionToolSignal = new AsyncLocalStorage8();
386753
386868
  }
386754
386869
  });
386755
386870
 
@@ -397152,6 +397267,7 @@ var init_dev_source_restart = __esm({
397152
397267
  var dashboard_exports = {};
397153
397268
  __export(dashboard_exports, {
397154
397269
  StreamedLogBuffer: () => StreamedLogBuffer,
397270
+ buildUiOnlyHeartbeatMonitorOptions: () => buildUiOnlyHeartbeatMonitorOptions,
397155
397271
  classifyDashboardFatalExit: () => classifyDashboardFatalExit,
397156
397272
  countActiveTasks: () => countActiveTasks,
397157
397273
  hasLiveSupervisingParent: () => hasLiveSupervisingParent,
@@ -397180,6 +397296,15 @@ async function countActiveTasks(store, tasks2) {
397180
397296
  }
397181
397297
  return active;
397182
397298
  }
397299
+ function buildUiOnlyHeartbeatMonitorOptions(input) {
397300
+ return {
397301
+ store: input.agentStore,
397302
+ agentStore: input.agentStore,
397303
+ taskStore: input.taskStore,
397304
+ rootDir: input.rootDir,
397305
+ secretsStore: input.secretsStore
397306
+ };
397307
+ }
397183
397308
  function formatRuntimeContext(context) {
397184
397309
  if (context === void 0) {
397185
397310
  return "";
@@ -398664,11 +398789,14 @@ async function runDashboard(port, opts = {}) {
398664
398789
  logSink.warn(`Failed to initialize mesh networking: ${message}`, "dashboard");
398665
398790
  }
398666
398791
  try {
398792
+ const secretsStore = await store.getSecretsStore();
398667
398793
  heartbeatMonitorImpl = new HeartbeatMonitor({
398668
- store: agentStore,
398669
- agentStore,
398670
- taskStore: store,
398671
- rootDir: cwd,
398794
+ ...buildUiOnlyHeartbeatMonitorOptions({
398795
+ agentStore,
398796
+ taskStore: store,
398797
+ rootDir: cwd,
398798
+ secretsStore
398799
+ }),
398672
398800
  onMissed: (agentId, reason) => {
398673
398801
  logSink.warn(`Agent ${agentId} missed heartbeat: ${reason}`, "engine");
398674
398802
  },