@runfusion/fusion 0.74.0-beta.7 → 0.74.0-beta.8

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 (95) hide show
  1. package/dist/bin.js +339 -473
  2. package/dist/child-process-worker.js +144 -278
  3. package/dist/client/.vite/manifest.json +254 -254
  4. package/dist/client/assets/{AgentDetailView-CTdyQL11.js → AgentDetailView-CnzGIxqj.js} +1 -1
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-DBa7nIQV.js → AgentPermissionPolicyEditor-DMnyR96M.js} +1 -1
  6. package/dist/client/assets/{AgentsView-B5tss2oK.js → AgentsView-CzFtICwM.js} +3 -3
  7. package/dist/client/assets/{ChatView-DAKt1a2L.js → ChatView-Cs6B3fNf.js} +1 -1
  8. package/dist/client/assets/{CommandCenter-yPvRo9F6.js → CommandCenter-DADvho3z.js} +1 -1
  9. package/dist/client/assets/{DevServerView-BTyS2owH.js → DevServerView-Bzrzfs8Z.js} +1 -1
  10. package/dist/client/assets/{DirectoryPicker-BjGIupNU.js → DirectoryPicker-rmip5GcI.js} +1 -1
  11. package/dist/client/assets/{DocumentsView-CuxfbpSZ.js → DocumentsView-BEM4nmJT.js} +1 -1
  12. package/dist/client/assets/{EvalsView-DGuy8SHR.js → EvalsView-Du7NaYMJ.js} +1 -1
  13. package/dist/client/assets/{ExperimentalAgentOnboardingModal-lK407ZAq.js → ExperimentalAgentOnboardingModal-BpIMiZOi.js} +1 -1
  14. package/dist/client/assets/{GoalsView-DAVN0ObR.js → GoalsView-BxKRyXM3.js} +1 -1
  15. package/dist/client/assets/{InsightsView-BXQKcNof.js → InsightsView-Dauq6b3M.js} +1 -1
  16. package/dist/client/assets/{MemoryView-D7RKEtV7.js → MemoryView-DRD9Xvwx.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-CrOJ57R2.js → PiExtensionsManager-DJKE1iAX.js} +1 -1
  18. package/dist/client/assets/{PluginManager-D7_evt4j.js → PluginManager-CScwY-Ib.js} +1 -1
  19. package/dist/client/assets/{PullRequestView-C0lRUbth.js → PullRequestView-uAu5_4__.js} +1 -1
  20. package/dist/client/assets/{ReportModal-Cy5fRNDK.js → ReportModal-nNUcGxYj.js} +1 -1
  21. package/dist/client/assets/{ResearchView-e8st2Sxu.js → ResearchView-BX1kGbWP.js} +1 -1
  22. package/dist/client/assets/{SecretsView-BLzckrzb.js → SecretsView-U_itETHx.js} +1 -1
  23. package/dist/client/assets/{SessionTerminal-F_GIj4gh.js → SessionTerminal-_b15vcd9.js} +1 -1
  24. package/dist/client/assets/SettingsModal-B30rPfYC.css +1 -0
  25. package/dist/client/assets/{SettingsModal-XAddgWkF.js → SettingsModal-DkpUKf4k.js} +1 -1
  26. package/dist/client/assets/{SettingsModal-eQbxbkLU.js → SettingsModal-DpbYR3Co.js} +4 -4
  27. package/dist/client/assets/{SettingsTextareaRow-DVjUHNQp.js → SettingsTextareaRow-Dbv-oqsF.js} +1 -1
  28. package/dist/client/assets/{SetupWizardModal-xID9yIff.js → SetupWizardModal-n_kcJfIP.js} +2 -2
  29. package/dist/client/assets/{SkillsView-BNdMGu6E.js → SkillsView-Bv2uqBre.js} +1 -1
  30. package/dist/client/assets/{TodoView-xcOjHZm1.js → TodoView-y11oUvjw.js} +1 -1
  31. package/dist/client/assets/{WorkflowNodeEditor-DZ2WZ-ve.js → WorkflowNodeEditor-DwY4XzNB.js} +1 -1
  32. package/dist/client/assets/{agent-import-generation-0tkW9WMt.js → agent-import-generation-B_UNOAWY.js} +1 -1
  33. package/dist/client/assets/{architectureDiagram-3BPJPVTR-DP9_UvPn.js → architectureDiagram-3BPJPVTR-BpA9_eoq.js} +1 -1
  34. package/dist/client/assets/{blockDiagram-GPEHLZMM-EgKwYMgQ.js → blockDiagram-GPEHLZMM-DFFA8tCG.js} +1 -1
  35. package/dist/client/assets/{c4Diagram-AAUBKEIU-Dzv0-_xt.js → c4Diagram-AAUBKEIU-Fzhn0dG7.js} +1 -1
  36. package/dist/client/assets/channel-C9C9Rxgn.js +1 -0
  37. package/dist/client/assets/{chunk-2J33WTMH-CNmFmJlQ.js → chunk-2J33WTMH-Bi3oPWBJ.js} +1 -1
  38. package/dist/client/assets/{chunk-4BX2VUAB-DwtF2sl5.js → chunk-4BX2VUAB-UmeI_To2.js} +1 -1
  39. package/dist/client/assets/{chunk-55IACEB6-DoDurT6F.js → chunk-55IACEB6-BvNWeThd.js} +1 -1
  40. package/dist/client/assets/{chunk-727SXJPM-DB87A9uH.js → chunk-727SXJPM-OHmjSQwz.js} +1 -1
  41. package/dist/client/assets/{chunk-AQP2D5EJ-ClTDkMp1.js → chunk-AQP2D5EJ-DCi9eQaE.js} +1 -1
  42. package/dist/client/assets/{chunk-FMBD7UC4-BhY2wlYr.js → chunk-FMBD7UC4-CelGyE3R.js} +1 -1
  43. package/dist/client/assets/{chunk-ND2GUHAM-BB8mzlmk.js → chunk-ND2GUHAM-DespM-6E.js} +1 -1
  44. package/dist/client/assets/{chunk-QZHKN3VN-D81qQMGf.js → chunk-QZHKN3VN-DLkr_Pz0.js} +1 -1
  45. package/dist/client/assets/classDiagram-4FO5ZUOK-BGVE_u03.js +1 -0
  46. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BGVE_u03.js +1 -0
  47. package/dist/client/assets/{cose-bilkent-S5V4N54A-CCFUHBJX.js → cose-bilkent-S5V4N54A-I7MlbwDq.js} +1 -1
  48. package/dist/client/assets/{dagre-BM42HDAG-xr9MLhRA.js → dagre-BM42HDAG-DRwLRj5m.js} +1 -1
  49. package/dist/client/assets/{dashboard-view-oTFt91I3.js → dashboard-view-CIwO3ODB.js} +1 -1
  50. package/dist/client/assets/{dashboard-view-RXKFv3QV.js → dashboard-view-CSxVzmpI.js} +1 -1
  51. package/dist/client/assets/{dashboard-view-lqwQ-pMo.js → dashboard-view-Gb436HIO.js} +1 -1
  52. package/dist/client/assets/{diagram-2AECGRRQ-mN_tYnBs.js → diagram-2AECGRRQ-BuWGDbh_.js} +1 -1
  53. package/dist/client/assets/{diagram-5GNKFQAL-xznlq-5C.js → diagram-5GNKFQAL-hG6N6ArX.js} +1 -1
  54. package/dist/client/assets/{diagram-KO2AKTUF-ClRlj1ZA.js → diagram-KO2AKTUF-BSXKqQJA.js} +1 -1
  55. package/dist/client/assets/{diagram-LMA3HP47-CNiPIQqT.js → diagram-LMA3HP47-wNefeM2W.js} +1 -1
  56. package/dist/client/assets/{diagram-OG6HWLK6-DwQD-W0P.js → diagram-OG6HWLK6-nA8v_k_H.js} +1 -1
  57. package/dist/client/assets/{erDiagram-TEJ5UH35-ZXkiCm8S.js → erDiagram-TEJ5UH35-Dwnvvp2x.js} +1 -1
  58. package/dist/client/assets/{flowDiagram-I6XJVG4X-DI5haEH9.js → flowDiagram-I6XJVG4X-FS4W3U0O.js} +1 -1
  59. package/dist/client/assets/{folder-open-NenyCkrb.js → folder-open-C3GXrzUo.js} +1 -1
  60. package/dist/client/assets/{ganttDiagram-6RSMTGT7-BRHJpfOZ.js → ganttDiagram-6RSMTGT7-D95bgKFE.js} +1 -1
  61. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-iXT_YBAZ.js → gitGraphDiagram-PVQCEYII-zqFbK6on.js} +1 -1
  62. package/dist/client/assets/{index-CrAJA2v0.js → index-BWRNl9tu.js} +274 -274
  63. package/dist/client/assets/index-DRZtPb3i.css +1 -0
  64. package/dist/client/assets/{infoDiagram-5YYISTIA-BzkuQtqZ.js → infoDiagram-5YYISTIA-BBELQBNE.js} +1 -1
  65. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-5hnPG_98.js → ishikawaDiagram-YF4QCWOH-bSZkIXd-.js} +1 -1
  66. package/dist/client/assets/{journeyDiagram-JHISSGLW-Co3fnxbr.js → journeyDiagram-JHISSGLW-8wIimXRT.js} +1 -1
  67. package/dist/client/assets/{kanban-definition-UN3LZRKU-PZFl_y-h.js → kanban-definition-UN3LZRKU-DMj6kFc5.js} +1 -1
  68. package/dist/client/assets/{mermaid.core-CJRKeU9s.js → mermaid.core-UDKENpfo.js} +4 -4
  69. package/dist/client/assets/{mindmap-definition-RKZ34NQL-B15e2rkx.js → mindmap-definition-RKZ34NQL-CJGH0VYQ.js} +1 -1
  70. package/dist/client/assets/{pieDiagram-4H26LBE5-kGF592D_.js → pieDiagram-4H26LBE5-B3cZLcOe.js} +1 -1
  71. package/dist/client/assets/{puzzle-Dgc4yzjO.js → puzzle-D85LM19g.js} +1 -1
  72. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CUShcj70.js → quadrantDiagram-W4KKPZXB-bR1CBrVi.js} +1 -1
  73. package/dist/client/assets/{requirementDiagram-4Y6WPE33-D2k4nLqQ.js → requirementDiagram-4Y6WPE33-DnyJ74cE.js} +1 -1
  74. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CA03BxhT.js → sankeyDiagram-5OEKKPKP-ttv4kq0z.js} +1 -1
  75. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-DDuFN2Pi.js → sequenceDiagram-3UESZ5HK-FiUBFoWw.js} +1 -1
  76. package/dist/client/assets/{shield-alert-BlYWqolM.js → shield-alert-D3IVOJV1.js} +1 -1
  77. package/dist/client/assets/{standing-instructions-template-ujl7UARV.js → standing-instructions-template-CWY_pFh6.js} +1 -1
  78. package/dist/client/assets/{stateDiagram-AJRCARHV-yJOkHK4Q.js → stateDiagram-AJRCARHV-BcsYRB77.js} +1 -1
  79. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-BgErHdAN.js → stateDiagram-v2-BHNVJYJU-DsBPFwnG.js} +1 -1
  80. package/dist/client/assets/{timeline-definition-PNZ67QCA-BUiDQw21.js → timeline-definition-PNZ67QCA-B8rOOxEj.js} +1 -1
  81. package/dist/client/assets/{upload-DmlZvpMp.js → upload-WqSaqC__.js} +1 -1
  82. package/dist/client/assets/{users-Cx6ACt-W.js → users-CPP-3wxQ.js} +1 -1
  83. package/dist/client/assets/{vennDiagram-CIIHVFJN-DqyIjBY8.js → vennDiagram-CIIHVFJN-CO0LSFj2.js} +1 -1
  84. package/dist/client/assets/{wardley-L42UT6IY-C93tXAKH.js → wardley-L42UT6IY-QHbclXGi.js} +1 -1
  85. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DmH6-GJV.js → wardleyDiagram-YWT4CUSO-DAsnTuM9.js} +1 -1
  86. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BPwjE4Su.js → xychartDiagram-2RQKCTM6-BmG5EEoO.js} +1 -1
  87. package/dist/client/index.html +2 -2
  88. package/dist/client/version.json +1 -1
  89. package/dist/extension.js +216 -350
  90. package/package.json +1 -1
  91. package/dist/client/assets/SettingsModal-KnUd0942.css +0 -1
  92. package/dist/client/assets/channel-BdTAZBkX.js +0 -1
  93. package/dist/client/assets/classDiagram-4FO5ZUOK-CuoGzmwo.js +0 -1
  94. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CuoGzmwo.js +0 -1
  95. package/dist/client/assets/index-CITV-wDq.css +0 -1
package/dist/bin.js CHANGED
@@ -136278,7 +136278,8 @@ function wrapPluginRuntime(instance, runtimeId, runtimeName) {
136278
136278
  const result2 = await adapter.createSession(options);
136279
136279
  return {
136280
136280
  session: result2.session ?? result2,
136281
- sessionFile: result2.sessionFile
136281
+ sessionFile: result2.sessionFile,
136282
+ settleFallbackDispatch: result2.settleFallbackDispatch
136282
136283
  };
136283
136284
  }
136284
136285
  throw new Error(`Plugin runtime "${runtimeId}" does not implement createSession`);
@@ -136387,11 +136388,15 @@ var init_runtime_resolution = __esm({
136387
136388
  name = "Default PI Runtime";
136388
136389
  async createSession(options) {
136389
136390
  const { toolOutputMaxChars, mcpServers, ...agentOptions } = options;
136390
- return createFnAgent2({
136391
+ const result2 = await createFnAgent2({
136391
136392
  ...agentOptions,
136392
136393
  toolOutputMaxChars,
136393
136394
  mcpServers: normalizeAgentRuntimeMcpServers(mcpServers)
136394
136395
  });
136396
+ return {
136397
+ ...result2,
136398
+ settleFallbackDispatch: result2.settleFallbackDispatch ?? (async () => void 0)
136399
+ };
136395
136400
  }
136396
136401
  async promptWithFallback(session, prompt, options) {
136397
136402
  return promptWithFallback(session, prompt, options);
@@ -137273,6 +137278,7 @@ async function createResolvedAgentSession(options) {
137273
137278
  return {
137274
137279
  session: result2.session,
137275
137280
  sessionFile: result2.sessionFile,
137281
+ settleFallbackDispatch: result2.settleFallbackDispatch,
137276
137282
  runtimeId: resolved.runtimeId,
137277
137283
  wasConfigured: resolved.wasConfigured
137278
137284
  };
@@ -159268,7 +159274,11 @@ async function createFnAgent2(options) {
159268
159274
  }
159269
159275
  });
159270
159276
  attachSessionIdentity(promptableSession);
159271
- return { session: promptableSession, sessionFile: promptableSession.sessionFile };
159277
+ return {
159278
+ session: promptableSession,
159279
+ sessionFile: promptableSession.sessionFile,
159280
+ settleFallbackDispatch: async () => void 0
159281
+ };
159272
159282
  }
159273
159283
  var execAsync, RTK_ACCEPTED_REWRITE_EXIT_CODES, RTK_EXPECTED_PASSTHROUGH_EXIT_CODES, RTK_EXPECTED_FAIL_OPEN_ERROR_CODES, RTK_REWRITE_MAX_BUFFER_BYTES, hostExtensionPaths, FN_MEMORY_APPEND_TOOL_NAME, FUSION_SHUTDOWN_WRAP_FLAG, promptWithFallbackInFlight, COMPACTION_FALLBACK_INSTRUCTIONS, MAX_COMPACTED_PROMPT_MEMORY_CHARS, MAX_COMPACTED_SUBTASK_GUIDANCE_CHARS, MAX_COMPACTED_ATTACHMENTS_CHARS, MAX_COMPACTED_EXISTING_SPEC_CHARS, MAX_COMPACTED_TASK_PROMPT_CHARS, MAX_COMPACTED_USER_COMMENTS_CHARS, ModelFallbackExhaustedError, GATE_BYPASS_TOOL_NAMES, TOOL_OUTPUT_BUDGET_OVERRIDES;
159274
159284
  var init_pi = __esm({
@@ -185757,6 +185767,25 @@ var init_scheduler = __esm({
185757
185767
  });
185758
185768
  }
185759
185769
  }
185770
+ if (from === parked.wip && to2 === parked.hold) {
185771
+ if (source === "engine") {
185772
+ this.recentEngineTodoRequeues.set(task.id, task.columnMovedAt ?? (/* @__PURE__ */ new Date()).toISOString());
185773
+ } else {
185774
+ this.recentEngineTodoRequeues.delete(task.id);
185775
+ }
185776
+ } else if (to2 === parked.review || parked.terminal.has(to2)) {
185777
+ this.recentEngineTodoRequeues.delete(task.id);
185778
+ if (task.dispatchStormCount != null || task.lastDispatchAt != null || task.executeRequeueLoopCount != null || task.executeRequeueLoopSignature != null) {
185779
+ void this.store.updateTask(task.id, {
185780
+ dispatchStormCount: null,
185781
+ lastDispatchAt: null,
185782
+ executeRequeueLoopCount: null,
185783
+ executeRequeueLoopSignature: null
185784
+ }).catch((error3) => {
185785
+ schedulerLog.warn(`Failed to reset dispatch oscillation state for ${task.id} on move to ${to2}: ${error3 instanceof Error ? error3.message : String(error3)}`);
185786
+ });
185787
+ }
185788
+ }
185760
185789
  const resolvedParked = mergeParkedColumns(await resolveTaskParkedColumns(this.store, task.id), lanes);
185761
185790
  if (resolvedParked.terminal.has(to2)) {
185762
185791
  try {
@@ -185817,25 +185846,6 @@ var init_scheduler = __esm({
185817
185846
  schedulerLog.error(`Failed event-driven blocker reconciliation for ${task.id}`, error3);
185818
185847
  }
185819
185848
  }
185820
- if (from === resolvedParked.wip && to2 === resolvedParked.hold) {
185821
- if (source === "engine") {
185822
- this.recentEngineTodoRequeues.set(task.id, task.columnMovedAt ?? (/* @__PURE__ */ new Date()).toISOString());
185823
- } else {
185824
- this.recentEngineTodoRequeues.delete(task.id);
185825
- }
185826
- } else if (to2 === resolvedParked.review || resolvedParked.terminal.has(to2)) {
185827
- this.recentEngineTodoRequeues.delete(task.id);
185828
- if (task.dispatchStormCount != null || task.lastDispatchAt != null || task.executeRequeueLoopCount != null || task.executeRequeueLoopSignature != null) {
185829
- void this.store.updateTask(task.id, {
185830
- dispatchStormCount: null,
185831
- lastDispatchAt: null,
185832
- executeRequeueLoopCount: null,
185833
- executeRequeueLoopSignature: null
185834
- }).catch((error3) => {
185835
- schedulerLog.warn(`Failed to reset dispatch oscillation state for ${task.id} on move to ${to2}: ${error3 instanceof Error ? error3.message : String(error3)}`);
185836
- });
185837
- }
185838
- }
185839
185849
  if (resolvedParked.terminal.has(to2) || to2 === resolvedParked.hold) {
185840
185850
  schedulerLog.log(`Task moved to ${to2} \u2014 triggering scheduling`);
185841
185851
  this.schedule();
@@ -204093,7 +204103,6 @@ var init_self_healing = __esm({
204093
204103
  { name: "reconcile-done-task-integrity", fn: () => this.reconcileDoneTaskIntegrity() },
204094
204104
  { name: "reconcile-stale-merger-status", fn: () => this.reconcileStaleMergerStatus() },
204095
204105
  { name: "reconcile-stale-duplicate-decision", fn: () => this.reconcileStaleDuplicateDecisionPause() },
204096
- { name: "reconcile-external-pr-blockers", fn: () => this.reconcileExternalPrBlockers() },
204097
204106
  // FNXC:OrphanedPendingSteps 2026-07-22-16:35 (FN-8492 review follow-up): also
204098
204107
  // steady-state — a step session can die without an engine restart, and startup-only
204099
204108
  // cadence left that case riding the 3×30-min stall escalator to a deadlock park.
@@ -212990,71 +212999,12 @@ var init_self_healing = __esm({
212990
212999
  }
212991
213000
  }
212992
213001
  /*
212993
- FNXC:HonestBlockedExit 2026-08-02-01:30:
212994
- Durable parks store github-pr externalBlockers (FN-8700 file-claim). When every blocking
212995
- PR is MERGED or CLOSED, clear the failed park so the scheduler can re-dispatch. Fail-soft
212996
- when gh is unavailable leave the park for the operator.
213002
+ FNXC:HonestBlockedExit 2026-08-02-23:59 (operator decision — FN-8728 vs PR #2398):
213003
+ The FN-8700 `reconcile-external-pr-blockers` sweep (gh-backed clearing of PR-claim parks)
213004
+ is REMOVED with the whole PR/file-claim blocking mechanism. Open PRs are never blockers;
213005
+ file-scope conflicts are arbitrated only by Fusion's own board. Legacy PR-claim parks are
213006
+ no longer honored by isDurableBlockedTask, so normal recovery paths reclaim them.
212997
213007
  */
212998
- async reconcileExternalPrBlockers() {
212999
- try {
213000
- if (!await isGhAvailable()) {
213001
- log33.debug("reconcile-external-pr-blockers skipped \u2014 gh unavailable");
213002
- return 0;
213003
- }
213004
- const tasks2 = await this.store.listTasks({ slim: true, includeArchived: false, limit: 500 });
213005
- let cleared = 0;
213006
- for (const task of tasks2.slice(0, 80)) {
213007
- if (task.status !== "failed" || !task.error?.startsWith("BLOCKED:")) continue;
213008
- const meta2 = task.sourceMetadata;
213009
- const blockers = meta2?.externalBlockers;
213010
- if (!Array.isArray(blockers) || blockers.length === 0) continue;
213011
- const prNumbers = blockers.map((b3) => b3 && typeof b3 === "object" && b3.kind === "github-pr" ? Number(b3.number) : NaN).filter((n) => Number.isFinite(n) && n > 0);
213012
- if (prNumbers.length === 0) continue;
213013
- let allResolved = true;
213014
- for (const n of prNumbers) {
213015
- try {
213016
- const pr2 = await runGhJsonAsync(
213017
- ["pr", "view", String(n), "--json", "state,mergedAt"],
213018
- { timeoutMs: 15e3 }
213019
- );
213020
- const state = String(pr2?.state ?? "").toUpperCase();
213021
- const merged = Boolean(pr2?.mergedAt) || state === "MERGED";
213022
- const closed = state === "CLOSED" || state === "MERGED";
213023
- if (!merged && !closed) {
213024
- allResolved = false;
213025
- break;
213026
- }
213027
- } catch {
213028
- allResolved = false;
213029
- break;
213030
- }
213031
- }
213032
- if (!allResolved) continue;
213033
- await this.store.updateTask(task.id, {
213034
- status: null,
213035
- error: null,
213036
- sourceMetadataPatch: {
213037
- externalBlockers: [],
213038
- blockedClass: null,
213039
- blockedThrashSignature: null,
213040
- blockedThrashCount: null,
213041
- externalPrBlockersClearedAt: (/* @__PURE__ */ new Date()).toISOString(),
213042
- externalPrBlockersCleared: prNumbers
213043
- }
213044
- });
213045
- await this.store.logEntry(
213046
- task.id,
213047
- `Auto-recovered: external PR blocker(s) ${prNumbers.map((n) => `#${n}`).join(", ")} merged/closed \u2014 cleared durable BLOCKED park for re-dispatch`
213048
- );
213049
- log33.log(`Cleared durable PR block for ${task.id} (prs=${prNumbers.join(",")})`);
213050
- cleared += 1;
213051
- }
213052
- return cleared;
213053
- } catch (error3) {
213054
- log33.warn(`reconcile-external-pr-blockers failed: ${error3 instanceof Error ? error3.message : String(error3)}`);
213055
- return 0;
213056
- }
213057
- }
213058
213008
  async resolveExplicitDuplicateMarkerTasks() {
213059
213009
  try {
213060
213010
  const settings = await this.store.getSettings();
@@ -213808,6 +213758,7 @@ var init_self_healing = __esm({
213808
213758
  // ../engine/src/triage.ts
213809
213759
  import { Type as Type5 } from "@earendil-works/pi-ai";
213810
213760
  import { exec as exec34 } from "node:child_process";
213761
+ import { existsSync as existsSync60 } from "node:fs";
213811
213762
  import { readFile as readFile38, writeFile as writeFile27, rm as rm8 } from "node:fs/promises";
213812
213763
  import { join as join72 } from "node:path";
213813
213764
  import { promisify as promisify48 } from "node:util";
@@ -214314,6 +214265,8 @@ var init_triage = __esm({
214314
214265
  unregisterAdmissionProvider = null;
214315
214266
  /** Timestamps when tasks entered the `processing` set, for staleness detection. */
214316
214267
  processingSince = /* @__PURE__ */ new Map();
214268
+ /** Monotonic provenance token for attempt-local planner fallback observation. */
214269
+ planningAttemptSequence = 0;
214317
214270
  wasGlobalPaused = false;
214318
214271
  wasEnginePaused = false;
214319
214272
  idleSemaphoreLeakCandidateSince = null;
@@ -215609,7 +215562,28 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
215609
215562
  }
215610
215563
  await this.store.logEntry(task.id, `Planning session running in task worktree ${planningCwd}`).catch(() => void 0);
215611
215564
  }
215612
- const { session } = await createResolvedAgentSession({
215565
+ const authoritativePromptPath = join72(this.rootDir, promptPath);
215566
+ const planningAttemptBaseline = existsSync60(authoritativePromptPath) ? await readFile38(authoritativePromptPath, "utf-8").catch(() => void 0) : void 0;
215567
+ const planningAttempt = {
215568
+ id: `${task.id}:${++this.planningAttemptSequence}`,
215569
+ baseline: planningAttemptBaseline,
215570
+ fallbackEngaged: false,
215571
+ fallbackSettlements: []
215572
+ };
215573
+ const fallbackObserver = createFallbackModelObserver({
215574
+ agent: "triage",
215575
+ label: "triage",
215576
+ store: this.store,
215577
+ taskId: task.id,
215578
+ taskTitle: task.title
215579
+ });
215580
+ const onFallbackModelUsed = (payload) => {
215581
+ planningAttempt.fallbackEngaged = true;
215582
+ const settlement = Promise.resolve(fallbackObserver(payload));
215583
+ planningAttempt.fallbackSettlements.push(settlement);
215584
+ return settlement;
215585
+ };
215586
+ const { session, settleFallbackDispatch, runtimeId } = await createResolvedAgentSession({
215613
215587
  sessionPurpose: "triage",
215614
215588
  runtimeHint: triageRuntimeHint,
215615
215589
  pluginRunner: this.options.pluginRunner,
@@ -215648,13 +215622,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
215648
215622
  taskTitle: task.title,
215649
215623
  actionGateContext: this.buildActionGateContext(task.id, triageRunContext.runId, assignedAgent, settings.defaultAgentPermissionPolicy),
215650
215624
  permanentAgentGating: this.buildPermanentAgentGatingContext(task.id, triageRunContext.runId, assignedAgent, settings.defaultAgentPermissionPolicy),
215651
- onFallbackModelUsed: createFallbackModelObserver({
215652
- agent: "triage",
215653
- label: "triage",
215654
- store: this.store,
215655
- taskId: task.id,
215656
- taskTitle: task.title
215657
- })
215625
+ onFallbackModelUsed
215658
215626
  });
215659
215627
  const modelDesc = formatModelMarkerDetails(describeModel(session), resolvePlanningThinkingLevel(settings, task.planningThinkingLevel ?? task.thinkingLevel));
215660
215628
  planLog.debug(`${task.id}: using model ${modelDesc}`);
@@ -215724,6 +215692,10 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
215724
215692
  agentPrompt,
215725
215693
  imageContents.length > 0 ? { images: imageContents } : void 0
215726
215694
  );
215695
+ const fallbackDispatchBoundaryMissing = typeof settleFallbackDispatch !== "function";
215696
+ if (!fallbackDispatchBoundaryMissing) {
215697
+ await settleFallbackDispatch();
215698
+ }
215727
215699
  checkSessionError(session);
215728
215700
  if (this.pauseAborted.has(task.id)) {
215729
215701
  this.pauseAborted.delete(task.id);
@@ -215816,12 +215788,42 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
215816
215788
  }
215817
215789
  }
215818
215790
  }
215819
- const duplicateReport = { outcome: "parked" };
215820
- if (await this.tryFinalizeExplicitDuplicateMarker(task, written, settings, {
215821
- isReplan,
215822
- feedback
215823
- }, duplicateReport)) {
215824
- this.options.onSpecifyComplete?.(task, duplicateReport);
215791
+ let settledFallbackCount = 0;
215792
+ while (settledFallbackCount < planningAttempt.fallbackSettlements.length) {
215793
+ const pendingSettlements = planningAttempt.fallbackSettlements.slice(settledFallbackCount);
215794
+ settledFallbackCount = planningAttempt.fallbackSettlements.length;
215795
+ await Promise.all(pendingSettlements);
215796
+ }
215797
+ const artifactChangedByAttempt = planningAttempt.baseline !== written;
215798
+ if (fallbackDispatchBoundaryMissing || planningAttempt.fallbackEngaged || !artifactChangedByAttempt) {
215799
+ const failure = fallbackDispatchBoundaryMissing ? `Planner runtime ${runtimeId} did not provide a fallback-dispatch settlement boundary for attempt ${planningAttempt.id}` : planningAttempt.fallbackEngaged ? `Planner fallback engaged during attempt ${planningAttempt.id}` : `Planner did not update the authoritative PROMPT.md during attempt ${planningAttempt.id}`;
215800
+ const decision = computeRecoveryDecision({
215801
+ recoveryRetryCount: task.recoveryRetryCount,
215802
+ nextRecoveryAt: task.nextRecoveryAt
215803
+ });
215804
+ if (decision.shouldRetry) {
215805
+ const retryMessage = `${failure} \u2014 retry ${decision.nextState.recoveryRetryCount}/${MAX_RECOVERY_RETRIES} in ${formatDelay(decision.delayMs)}.`;
215806
+ planLog.warn(`${task.id} ${retryMessage}`);
215807
+ await this.store.logEntry(task.id, retryMessage);
215808
+ await this.updatePlanningStateIfStillCurrent(task, {
215809
+ status: this.restoreStatusAfterInterruptedTriageWork(task),
215810
+ error: null,
215811
+ recoveryRetryCount: decision.nextState.recoveryRetryCount,
215812
+ nextRecoveryAt: decision.nextState.nextRecoveryAt
215813
+ });
215814
+ return;
215815
+ }
215816
+ const failureMessage = `${failure} after ${MAX_RECOVERY_RETRIES} retries. Retry after adjusting the task prompt or model.`;
215817
+ planLog.error(`${task.id} clean planning attempt retry budget exhausted`);
215818
+ await this.store.logEntry(task.id, failureMessage);
215819
+ if (await this.updatePlanningStateIfStillCurrent(task, {
215820
+ status: "failed",
215821
+ error: failureMessage,
215822
+ recoveryRetryCount: null,
215823
+ nextRecoveryAt: null
215824
+ })) {
215825
+ await this.backfillBlankTitleAfterTerminalTriageFailure(task);
215826
+ }
215825
215827
  return;
215826
215828
  }
215827
215829
  const deterministicSpecFailure = await this.validateGeneratedPrompt(task.id, written);
@@ -215863,6 +215865,21 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
215863
215865
  }
215864
215866
  return;
215865
215867
  }
215868
+ const duplicateReport = { outcome: "parked" };
215869
+ if (await this.tryFinalizeExplicitDuplicateMarker(task, written, settings, {
215870
+ isReplan,
215871
+ feedback
215872
+ }, duplicateReport)) {
215873
+ this.options.onSpecifyComplete?.(task, duplicateReport);
215874
+ return;
215875
+ }
215876
+ if (task.recoveryRetryCount != null || task.nextRecoveryAt != null) {
215877
+ await this.updatePlanningStateIfStillCurrent(task, {
215878
+ error: null,
215879
+ recoveryRetryCount: null,
215880
+ nextRecoveryAt: null
215881
+ });
215882
+ }
215866
215883
  const finalizeReport = await this.finalizeApprovedTask(task, written, settings, {
215867
215884
  isReplan,
215868
215885
  feedback
@@ -216899,103 +216916,35 @@ Remove or replace these ids and call fn_task_create again.`
216899
216916
  // ../engine/src/execution-block-classifier.ts
216900
216917
  function partitionBlockedByRefs(blockedBy) {
216901
216918
  const taskIds = [];
216902
- const prNumbers = [];
216903
216919
  for (const raw of blockedBy) {
216904
216920
  const id = raw.trim();
216905
216921
  if (!id) continue;
216906
- const prMatch = id.match(PR_REF_RE);
216907
- if (prMatch) {
216908
- prNumbers.push(Number(prMatch[1]));
216909
- continue;
216910
- }
216922
+ if (LEGACY_PR_REF_RE.test(id)) continue;
216911
216923
  if (TASK_ID_RE.test(id)) {
216912
216924
  const m2 = id.toUpperCase().match(/^([A-Z][A-Z0-9]*)-(\d+)$/);
216913
216925
  taskIds.push(m2 ? `${m2[1]}-${m2[2]}` : id.toUpperCase());
216914
- continue;
216915
216926
  }
216916
216927
  }
216917
- return {
216918
- taskIds: [...new Set(taskIds)],
216919
- prNumbers: [...new Set(prNumbers.filter((n) => Number.isFinite(n) && n > 0))]
216920
- };
216928
+ return { taskIds: [...new Set(taskIds)] };
216921
216929
  }
216922
- function extractPrNumbersFromText(text3) {
216923
- const found = [];
216924
- for (const match of text3.matchAll(PR_IN_TEXT_RE)) {
216925
- const n = Number(match[1]);
216926
- if (Number.isFinite(n) && n > 0) found.push(n);
216927
- }
216928
- return [...new Set(found)];
216929
- }
216930
- function isFileClaimBlockedReason(reason) {
216931
- return CLAIM_REASON_RE.test(reason);
216932
- }
216933
- function classifyBlockedExit(reason, blockedBy = []) {
216934
- const trimmed = reason.trim();
216935
- const partitioned = partitionBlockedByRefs(blockedBy);
216936
- const prFromText = extractPrNumbersFromText(trimmed);
216937
- const prNumbers = [.../* @__PURE__ */ new Set([...partitioned.prNumbers, ...prFromText])];
216938
- const isClaim = isFileClaimBlockedReason(trimmed) || prNumbers.length > 0 && /claim/i.test(trimmed);
216939
- if (isClaim || prNumbers.length > 0 && isFileClaimBlockedReason(trimmed)) {
216940
- const externalBlockers = [
216941
- ...prNumbers.map((number4) => ({ kind: "github-pr", number: number4 }))
216942
- ];
216943
- if (externalBlockers.length === 0 && isClaim) {
216944
- externalBlockers.push({
216945
- kind: "file-claim",
216946
- prNumber: prNumbers[0]
216947
- });
216948
- } else if (isClaim) {
216949
- for (const n of prNumbers) {
216950
- if (!externalBlockers.some((b3) => b3.kind === "github-pr" && b3.number === n)) {
216951
- externalBlockers.push({ kind: "github-pr", number: n });
216952
- }
216953
- }
216954
- if (prNumbers.length === 0) {
216955
- externalBlockers.push({ kind: "file-claim" });
216956
- }
216957
- }
216958
- const thrashSignature = [
216959
- "file-claim",
216960
- ...prNumbers.map((n) => `pr:${n}`).sort(),
216961
- ...partitioned.taskIds.slice().sort()
216962
- ].join("|");
216963
- return {
216964
- allowAutoReplan: false,
216965
- class: "file-claim",
216966
- externalBlockers,
216967
- thrashSignature: thrashSignature || "file-claim",
216968
- prNumbers
216969
- };
216970
- }
216971
- if (partitioned.taskIds.length > 0) {
216972
- return {
216973
- allowAutoReplan: false,
216974
- class: "external",
216975
- externalBlockers: [],
216976
- thrashSignature: `tasks:${partitioned.taskIds.slice().sort().join(",")}`,
216977
- prNumbers
216978
- };
216979
- }
216980
- if (prNumbers.length > 0) {
216930
+ function classifyBlockedExit(_reason, blockedBy = []) {
216931
+ const { taskIds } = partitionBlockedByRefs(blockedBy);
216932
+ if (taskIds.length > 0) {
216981
216933
  return {
216982
216934
  allowAutoReplan: false,
216983
216935
  class: "external",
216984
- externalBlockers: prNumbers.map((number4) => ({ kind: "github-pr", number: number4 })),
216985
- thrashSignature: prNumbers.map((n) => `pr:${n}`).sort().join("|"),
216986
- prNumbers
216936
+ thrashSignature: `tasks:${taskIds.slice().sort().join(",")}`
216987
216937
  };
216988
216938
  }
216989
216939
  return {
216990
216940
  allowAutoReplan: true,
216991
216941
  class: "plan-defect",
216992
- externalBlockers: [],
216993
- thrashSignature: "plan-defect",
216994
- prNumbers: []
216942
+ thrashSignature: "plan-defect"
216995
216943
  };
216996
216944
  }
216997
216945
  function countBlockedThrashHits(log43, signature, nowMs = Date.now(), windowMs = BLOCKED_THRASH_WINDOW_MS) {
216998
216946
  if (!log43?.length) return 0;
216947
+ if (signature === "plan-defect") return 0;
216999
216948
  const cutoff = nowMs - windowMs;
217000
216949
  let count2 = 0;
217001
216950
  for (const entry of log43) {
@@ -217007,18 +216956,7 @@ function countBlockedThrashHits(log43, signature, nowMs = Date.now(), windowMs =
217007
216956
  continue;
217008
216957
  }
217009
216958
  }
217010
- if (signature === "plan-defect") continue;
217011
- if (signature.includes("file-claim") || signature.startsWith("pr:") || signature.includes("|pr:")) {
217012
- if (isFileClaimBlockedReason(action) || /PR\s*#?\s*\d+/i.test(action) || action.includes("durable external block")) {
217013
- count2 += 1;
217014
- continue;
217015
- }
217016
- }
217017
216959
  for (const part of signature.split("|")) {
217018
- if (part.startsWith("pr:") && action.includes(`PR #${part.slice(3)}`)) {
217019
- count2 += 1;
217020
- break;
217021
- }
217022
216960
  if (part.startsWith("tasks:") && part.slice(6).split(",").some((id) => id && action.includes(id))) {
217023
216961
  count2 += 1;
217024
216962
  break;
@@ -217027,38 +216965,26 @@ function countBlockedThrashHits(log43, signature, nowMs = Date.now(), windowMs =
217027
216965
  }
217028
216966
  return count2;
217029
216967
  }
217030
- function isDurableBlockedError(error3) {
217031
- if (!error3?.startsWith("BLOCKED:")) return false;
217032
- const reason = error3.slice("BLOCKED:".length).trim();
217033
- const classification = classifyBlockedExit(reason, []);
217034
- return !classification.allowAutoReplan;
217035
- }
217036
216968
  function isDurableBlockedTask(task) {
217037
- if (task.status === "failed" && isDurableBlockedError(task.error)) return true;
217038
216969
  const meta2 = task.sourceMetadata;
217039
216970
  if (!meta2 || typeof meta2 !== "object") return false;
217040
- if (meta2.blockedClass === "file-claim" || meta2.blockedClass === "external") {
217041
- if (task.status === "failed" || task.status === "needs-replan") return true;
217042
- }
217043
- const blockers = meta2.externalBlockers;
217044
- return Array.isArray(blockers) && blockers.length > 0 && task.status === "failed";
216971
+ if (meta2.blockedClass !== "external") return false;
216972
+ return task.status === "failed" || task.status === "needs-replan";
217045
216973
  }
217046
216974
  function buildExternalBlockMetadataPatch(classification, thrashCount) {
217047
216975
  return {
217048
216976
  blockedClass: classification.class,
217049
216977
  blockedThrashSignature: classification.thrashSignature,
217050
216978
  blockedThrashCount: thrashCount,
217051
- externalBlockers: classification.externalBlockers
216979
+ externalBlockers: []
217052
216980
  };
217053
216981
  }
217054
- var TASK_ID_RE, PR_REF_RE, PR_IN_TEXT_RE, CLAIM_REASON_RE, BLOCKED_THRASH_LIMIT, BLOCKED_THRASH_WINDOW_MS;
216982
+ var TASK_ID_RE, LEGACY_PR_REF_RE, BLOCKED_THRASH_LIMIT, BLOCKED_THRASH_WINDOW_MS;
217055
216983
  var init_execution_block_classifier = __esm({
217056
216984
  "../engine/src/execution-block-classifier.ts"() {
217057
216985
  "use strict";
217058
216986
  TASK_ID_RE = /^[A-Z][A-Z0-9]*-\d+$/i;
217059
- PR_REF_RE = /^(?:pr[:#-]|#|PR-)(\d+)$/i;
217060
- PR_IN_TEXT_RE = /\bPR\s*#?\s*(\d+)\b/gi;
217061
- CLAIM_REASON_RE = /check-file-claimed|actively claimed|file[- ]claim|claimed by (?:open )?pr|open pr\s*#?\s*\d+|collision policy|claimed paths?|file claims?/i;
216987
+ LEGACY_PR_REF_RE = /^(?:pr[:#-]|#|PR-)(\d+)$/i;
217062
216988
  BLOCKED_THRASH_LIMIT = 3;
217063
216989
  BLOCKED_THRASH_WINDOW_MS = 60 * 60 * 1e3;
217064
216990
  }
@@ -219876,7 +219802,7 @@ var init_workflow_completion_summary = __esm({
219876
219802
 
219877
219803
  // ../engine/src/review-checkout.ts
219878
219804
  import { execFileSync as execFileSync3 } from "node:child_process";
219879
- import { existsSync as existsSync60, realpathSync as realpathSync9, statSync as statSync11 } from "node:fs";
219805
+ import { existsSync as existsSync61, realpathSync as realpathSync9, statSync as statSync11 } from "node:fs";
219880
219806
  import { isAbsolute as isAbsolute15 } from "node:path";
219881
219807
  function readMetadataPath(value) {
219882
219808
  if (!value || typeof value !== "object") return void 0;
@@ -219900,7 +219826,7 @@ function resolveReviewCheckoutCwd(task, fallbackCwd) {
219900
219826
  const candidate = getTaskReviewCheckoutPath(task);
219901
219827
  if (!candidate || !isAbsolute15(candidate)) return fallbackCwd;
219902
219828
  try {
219903
- if (!existsSync60(candidate) || !statSync11(candidate).isDirectory()) return fallbackCwd;
219829
+ if (!existsSync61(candidate) || !statSync11(candidate).isDirectory()) return fallbackCwd;
219904
219830
  const realCandidate = realpathSync9(candidate);
219905
219831
  const topLevel = execFileSync3("git", ["rev-parse", "--show-toplevel"], {
219906
219832
  cwd: realCandidate,
@@ -222506,7 +222432,7 @@ var init_external_integration_evidence = __esm({
222506
222432
 
222507
222433
  // ../engine/src/step-runner.ts
222508
222434
  import { exec as exec35 } from "node:child_process";
222509
- import { existsSync as existsSync62, statSync as statSync12 } from "node:fs";
222435
+ import { existsSync as existsSync63, statSync as statSync12 } from "node:fs";
222510
222436
  import { promisify as promisify50 } from "node:util";
222511
222437
  async function runTaskStep(deps, task, stepIndex, opts = {}) {
222512
222438
  const { store, worktreePath } = deps;
@@ -222660,7 +222586,7 @@ function makeAncestryBlastRadiusGuard(opts) {
222660
222586
  function isUsableWorktreeDirectory(candidate) {
222661
222587
  if (!candidate) return false;
222662
222588
  try {
222663
- return existsSync62(candidate) && statSync12(candidate).isDirectory();
222589
+ return existsSync63(candidate) && statSync12(candidate).isDirectory();
222664
222590
  } catch {
222665
222591
  return false;
222666
222592
  }
@@ -222697,7 +222623,7 @@ var init_step_runner = __esm({
222697
222623
 
222698
222624
  // ../engine/src/auto-recovery-handlers/branch-worktree.ts
222699
222625
  import { exec as exec36 } from "node:child_process";
222700
- import { existsSync as existsSync63 } from "node:fs";
222626
+ import { existsSync as existsSync64 } from "node:fs";
222701
222627
  import { promisify as promisify51 } from "node:util";
222702
222628
  var execAsync33, baseLog2, GIT_TIMEOUT_MS8, GIT_MAX_BUFFER6, BranchWorktreeAutoRecoveryHandler;
222703
222629
  var init_branch_worktree = __esm({
@@ -222888,7 +222814,7 @@ var init_branch_worktree = __esm({
222888
222814
  if (inspection.kind === "stale-resolved" || inspection.kind === "fully-subsumed" || inspection.kind === "tip-already-merged") {
222889
222815
  await this.requeueAfterRecovery(ctx.task, failure, inspection.kind, {
222890
222816
  branchExists: await this.hasBranchRef(repoDir, branchName),
222891
- worktreePresent: existsSync63(conflictingWorktreePath),
222817
+ worktreePresent: existsSync64(conflictingWorktreePath),
222892
222818
  tipSha: "tipSha" in inspection ? inspection.tipSha : void 0,
222893
222819
  inspectionKind: inspection.kind
222894
222820
  });
@@ -222958,7 +222884,7 @@ var init_branch_worktree = __esm({
222958
222884
  let branchDeleted = false;
222959
222885
  let worktreeRemoved = false;
222960
222886
  if (!isLiveOwned) {
222961
- if (existsSync63(conflictingWorktreePath)) {
222887
+ if (existsSync64(conflictingWorktreePath)) {
222962
222888
  try {
222963
222889
  await execAsync33(`git worktree remove --force ${this.quote(conflictingWorktreePath)}`, {
222964
222890
  cwd: repoDir,
@@ -223006,7 +222932,7 @@ var init_branch_worktree = __esm({
223006
222932
  });
223007
222933
  await this.requeueAfterRecovery(ctx.task, failure, "live-foreign-discard-and-recreate", {
223008
222934
  branchExists: !branchDeleted,
223009
- worktreePresent: !worktreeRemoved && existsSync63(conflictingWorktreePath),
222935
+ worktreePresent: !worktreeRemoved && existsSync64(conflictingWorktreePath),
223010
222936
  tipSha: tipSha2,
223011
222937
  inspectionKind: inspection.kind
223012
222938
  });
@@ -223019,7 +222945,7 @@ var init_branch_worktree = __esm({
223019
222945
  conflictingWorktreePath,
223020
222946
  inspectionKind: inspection.kind,
223021
222947
  branchExists,
223022
- worktreePresent: existsSync63(conflictingWorktreePath),
222948
+ worktreePresent: existsSync64(conflictingWorktreePath),
223023
222949
  tipSha
223024
222950
  });
223025
222951
  }
@@ -223180,7 +223106,7 @@ var init_file_scope2 = __esm({
223180
223106
  });
223181
223107
 
223182
223108
  // ../engine/src/run-verification-tool.ts
223183
- import { existsSync as existsSync64, readdirSync as readdirSync11, readFileSync as readFileSync23 } from "node:fs";
223109
+ import { existsSync as existsSync65, readdirSync as readdirSync11, readFileSync as readFileSync23 } from "node:fs";
223184
223110
  import { isAbsolute as isAbsolute16, join as join77, relative as relative14 } from "node:path";
223185
223111
  import { Type as Type6 } from "@earendil-works/pi-ai";
223186
223112
  function shellSplit(input) {
@@ -223740,7 +223666,7 @@ function createRunVerificationTool(opts) {
223740
223666
  }
223741
223667
  if (effectiveCommand.trimStart().startsWith("pnpm --filter")) {
223742
223668
  const modulesYaml = join77(rootDir, "node_modules", ".modules.yaml");
223743
- if (!existsSync64(modulesYaml)) {
223669
+ if (!existsSync65(modulesYaml)) {
223744
223670
  const installCmd = "pnpm install --prefer-offline";
223745
223671
  const msg = `node_modules/.modules.yaml not found in workspace root \u2014 auto-prepending \`${installCmd}\` before running the command.`;
223746
223672
  warnings.push(msg);
@@ -224101,7 +224027,7 @@ import { exec as exec39, execFile as execFile26, execSync as execSync7 } from "n
224101
224027
  import { promisify as promisify54 } from "node:util";
224102
224028
  import { setImmediate as setImmediateCb3 } from "node:timers";
224103
224029
  import { basename as basename19, delimiter as delimiter2, isAbsolute as isAbsolute18, join as join78, relative as relative16, resolve as resolvePath3 } from "node:path";
224104
- import { existsSync as existsSync65, lstatSync as lstatSync3, realpathSync as realpathSync10 } from "node:fs";
224030
+ import { existsSync as existsSync66, lstatSync as lstatSync3, realpathSync as realpathSync10 } from "node:fs";
224105
224031
  import { readFile as readFile40, rm as rm12, writeFile as writeFile29 } from "node:fs/promises";
224106
224032
  import { Type as Type7 } from "@earendil-works/pi-ai";
224107
224033
  import { SessionManager as SessionManager2 } from "@earendil-works/pi-coding-agent";
@@ -224119,7 +224045,7 @@ function isWorkflowStepSkillDiscoverable(skillName, additionalSkillPaths, ceSkil
224119
224045
  return false;
224120
224046
  }
224121
224047
  return (additionalSkillPaths ?? []).some(
224122
- (skillPath) => basename19(skillPath) === bareSkillName2 && existsSync65(join78(skillPath, "SKILL.md")) || existsSync65(join78(skillPath, bareSkillName2, "SKILL.md"))
224048
+ (skillPath) => basename19(skillPath) === bareSkillName2 && existsSync66(join78(skillPath, "SKILL.md")) || existsSync66(join78(skillPath, bareSkillName2, "SKILL.md"))
224123
224049
  );
224124
224050
  }
224125
224051
  function getPromptSection(prompt, heading) {
@@ -225092,7 +225018,7 @@ If you have just finished a step's work, immediately call \`fn_task_update\` to
225092
225018
 
225093
225019
  The user is not watching this conversation in real-time. They will read the final result. Asking permission wastes a full retry cycle and may orphan committed work.
225094
225020
 
225095
- **Cannot proceed \u2014 the honest blocked exit.** If the work genuinely cannot be finished (an upstream API break, a missing prerequisite task, an unresolvable external error, or a **file claim / open PR collision**), call \`fn_task_done(outcome="blocked", reason="<concrete blocker + what would unblock it>", blockedBy=["FN-XXXX"] or ["pr:2398"])\`. File-claim reasons must name the PR (e.g. "actively claimed by PR #2398" + \`blockedBy:["pr:2398"]\`). That parks durable failed WITHOUT auto-replan so the engine does not thrash; task IDs requeue when those tasks complete; PR refs clear when the PR merges/closes. Do NOT skip remaining steps to fake completion.
225021
+ **Cannot proceed \u2014 the honest blocked exit.** If the work genuinely cannot be finished (an upstream API break, a missing prerequisite task, or an unresolvable external error), call \`fn_task_done(outcome="blocked", reason="<concrete blocker + what would unblock it>", blockedBy=["FN-XXXX"])\`. That parks durable failed WITHOUT auto-replan so the engine does not thrash; task IDs requeue when those tasks complete. Blockers must be Fusion board tasks \u2014 do NOT treat open GitHub PRs touching the same files as blockers; other PRs are not claims on your file scope. Do NOT skip remaining steps to fake completion.
225096
225022
  This is THE correct action when you are stuck \u2014 do NOT instead mark the remaining steps \`skipped\` and call \`fn_task_done\` to make the task look finished. Skipping steps to escape a blocker launders a failure into \`done\` and is never the right move. (\`skipped\` remains valid only for the stale-premise path below, when the requested work is already present on HEAD.) Never write the blocker as plain prose.
225097
225023
 
225098
225024
  ## How to work
@@ -227681,7 +227607,7 @@ The tool prevents your session from being killed by the inactivity watchdog duri
227681
227607
  );
227682
227608
  return false;
227683
227609
  }
227684
- if (task.worktree && existsSync65(task.worktree)) {
227610
+ if (task.worktree && existsSync66(task.worktree)) {
227685
227611
  const modifiedFiles = await this.captureModifiedFiles(task.worktree, task.baseCommitSha, task.id, void 0, "recovery");
227686
227612
  if (modifiedFiles.length > 0) {
227687
227613
  await this.store.updateTask(task.id, { modifiedFiles });
@@ -230643,7 +230569,7 @@ ${info.feedback}`, revisionKey),
230643
230569
  if (live.firstExecutionAt || live.executionStartedAt) return false;
230644
230570
  if (activeSessionRegistry.isPathActive(live.worktree) || activeSessionRegistry.isPathActive(resolvePath3(live.worktree))) return false;
230645
230571
  if (this.hasLiveTaskSessionSurface(taskId) || executingTaskLock.has(taskId)) return false;
230646
- if (existsSync65(live.worktree)) {
230572
+ if (existsSync66(live.worktree)) {
230647
230573
  if (await this.preExecutionWorktreeHasWork(live.worktree)) {
230648
230574
  executorLog.log(`${taskId}: keeping pre-execution worktree ${live.worktree} \u2014 it carries commits or uncommitted changes`);
230649
230575
  return false;
@@ -230685,7 +230611,7 @@ ${info.feedback}`, revisionKey),
230685
230611
  }
230686
230612
  if (this.workspaceConfig && (this.workspaceConfig.repos.length ?? 0) > 0) return null;
230687
230613
  const live = await this.store.getTask(taskId);
230688
- if (live.worktree && existsSync65(live.worktree)) return live.worktree;
230614
+ if (live.worktree && existsSync66(live.worktree)) return live.worktree;
230689
230615
  const settings = await this.store.getSettings();
230690
230616
  const acquisitionTask = live.worktree ? { ...live, worktree: void 0, sessionFile: void 0 } : live;
230691
230617
  const acquired = await this.ensureGraphCustomNodeWorktree(acquisitionTask, settings, "planning");
@@ -230699,8 +230625,8 @@ ${info.feedback}`, revisionKey),
230699
230625
  if (!requirement.requiresWorktree) return;
230700
230626
  const live = await this.store.getTask(nodeTask.id);
230701
230627
  const executionCodeNode = node.kind === "code";
230702
- if (live.worktree && existsSync65(live.worktree) && !executionCodeNode) return;
230703
- const taskForAcquisition = live.worktree && !existsSync65(live.worktree) ? { ...live, worktree: void 0, sessionFile: void 0 } : live;
230628
+ if (live.worktree && existsSync66(live.worktree) && !executionCodeNode) return;
230629
+ const taskForAcquisition = live.worktree && !existsSync66(live.worktree) ? { ...live, worktree: void 0, sessionFile: void 0 } : live;
230704
230630
  if (live.worktree) {
230705
230631
  await this.store.logEntry(
230706
230632
  live.id,
@@ -230826,7 +230752,7 @@ ${info.feedback}`, revisionKey),
230826
230752
  const nodeDisplayName = typeof cfg.name === "string" && cfg.name.trim() ? cfg.name.trim() : node.id;
230827
230753
  const isPlanReviewNode = node.id === "plan-review-step" || nodeDisplayName === "Plan Review" || optionalGroupId === "plan-review";
230828
230754
  if (!this.workspaceConfig) {
230829
- const recordedWorktreeMissing = Boolean(executionTarget.worktree) && !existsSync65(executionTarget.worktree);
230755
+ const recordedWorktreeMissing = Boolean(executionTarget.worktree) && !existsSync66(executionTarget.worktree);
230830
230756
  const shouldAcquire = !executionTarget.worktree || recordedWorktreeMissing && isPlanReviewNode;
230831
230757
  if (shouldAcquire) {
230832
230758
  if (recordedWorktreeMissing) {
@@ -232500,75 +232426,16 @@ Graph value: ${failureValue}` : ""}`, budget.key),
232500
232426
  );
232501
232427
  }
232502
232428
  }
232503
- /*
232504
- FNXC:HonestBlockedExit 2026-08-02-01:30:
232505
- Agents often log `BLOCKED: … actively claimed by PR #N` without calling fn_task_done.
232506
- Without promotion, incomplete-step graph resume requeues the card and thrash restarts
232507
- (FN-8700). Promote claim/external blocks to a durable failed park here.
232508
- */
232509
- async parkDurableBlockedFromRecentLog(live) {
232510
- const recent = [...live.log ?? []].reverse().find((entry) => {
232511
- const action = entry.action ?? "";
232512
- return action.startsWith("BLOCKED:") || action.includes("durable external block");
232513
- });
232514
- if (!recent?.action) return false;
232515
- const reason = recent.action.startsWith("BLOCKED:") ? recent.action.slice("BLOCKED:".length).trim() : recent.action;
232516
- const classification = classifyBlockedExit(reason, []);
232517
- if (classification.allowAutoReplan) return false;
232518
- const thrashCount = countBlockedThrashHits(live.log, classification.thrashSignature) + 1;
232519
- const thrashExhausted = thrashCount >= BLOCKED_THRASH_LIMIT;
232520
- const parkError = thrashExhausted ? `BLOCKED: ${reason} [thrash-exhausted after ${thrashCount} identical durable blocks]` : `BLOCKED: ${reason}`;
232521
- const metaPatch = buildExternalBlockMetadataPatch(classification, thrashCount);
232522
- await this.store.updateTask(live.id, {
232523
- status: "failed",
232524
- error: parkError,
232525
- paused: false,
232526
- pausedByAgentId: null,
232527
- sourceMetadataPatch: metaPatch
232528
- }, this.getRunContextFor(live.id));
232529
- await this.store.logEntry(
232530
- live.id,
232531
- thrashExhausted ? `${parkError} \u2014 promoted from session log; thrash-exhausted, no auto-requeue` : `${parkError} \u2014 promoted from session log to durable external block park (class=${classification.class})`,
232532
- void 0,
232533
- this.getRunContextFor(live.id)
232534
- );
232535
- await this.store.recordRunAuditEvent?.({
232536
- taskId: live.id,
232537
- agentId: "executor",
232538
- runId: generateSyntheticRunId("execution-blocked-log-promote", live.id),
232539
- domain: "database",
232540
- mutationType: "task:execution-blocked-parked",
232541
- target: live.id,
232542
- metadata: {
232543
- taskId: live.id,
232544
- blockedBy: [],
232545
- hasReason: true,
232546
- parkedAs: "failed",
232547
- blockedClass: classification.class,
232548
- thrashCount,
232549
- thrashExhausted,
232550
- prNumbers: classification.prNumbers,
232551
- source: "session-log-promote"
232552
- }
232553
- });
232554
- executorLog.warn(
232555
- `${live.id}: promoted durable BLOCKED from session log (class=${classification.class}; thrash=${thrashCount})`
232556
- );
232557
- return true;
232558
- }
232559
232429
  async routeGraphFailureToExecutionResume(live, failedNode, failureValue, resumeLanesMemo) {
232560
232430
  if (live.deletedAt) return false;
232561
232431
  if (live.paused || live.userPaused === true) return false;
232562
232432
  if ((await resolveTerminalColumnsFor(this.store, live.id)).includes(live.column)) return false;
232563
- if (isDurableBlockedTask(live) || isDurableBlockedError(live.error)) {
232433
+ if (isDurableBlockedTask(live)) {
232564
232434
  executorLog.log(
232565
- `${live.id}: graph failure resume skipped \u2014 durable BLOCKED park honored (class from error/metadata)`
232435
+ `${live.id}: graph failure resume skipped \u2014 durable BLOCKED park honored (task-dependency block)`
232566
232436
  );
232567
232437
  return false;
232568
232438
  }
232569
- if (await this.parkDurableBlockedFromRecentLog(live)) {
232570
- return false;
232571
- }
232572
232439
  if (failedNode === COMPLETION_SUMMARY_NODE_ID) return false;
232573
232440
  const incompleteSteps = hasNonTerminalWorkflowSteps(live);
232574
232441
  const implementationIncompleteMergeFailure = this.isMergeGraphFailure(failedNode) && failureValue === "implementation-incomplete";
@@ -233749,7 +233616,7 @@ ${summary}`,
233749
233616
  executorLog.warn(`\u26A1 ${task.id} transient error \u2014 retry ${attempt}/${MAX_RECOVERY_RETRIES} in ${delay6}: ${errorMessage5}`);
233750
233617
  await this.store.logEntry(task.id, `Transient error (retry ${attempt}/${MAX_RECOVERY_RETRIES} in ${delay6}): ${errorMessage5}`, void 0, this.getRunContextFor(task.id));
233751
233618
  }
233752
- if (worktreePath && existsSync65(worktreePath)) {
233619
+ if (worktreePath && existsSync66(worktreePath)) {
233753
233620
  try {
233754
233621
  const settings2 = await this.store.getSettings();
233755
233622
  await removeWorktree({
@@ -233830,7 +233697,7 @@ ${summary}`,
233830
233697
  const settings2 = await this.store.getSettings();
233831
233698
  const preserveProgress = settings2.preserveProgressOnStuckRequeue !== false;
233832
233699
  await this.resetStepsIfWorkLost(latestTask);
233833
- if (worktreePath && existsSync65(worktreePath)) {
233700
+ if (worktreePath && existsSync66(worktreePath)) {
233834
233701
  try {
233835
233702
  await removeWorktree({
233836
233703
  worktreePath,
@@ -234113,7 +233980,7 @@ ${summary}`,
234113
233980
  nodeId: detail.effectiveNodeId ?? detail.nodeId ?? null,
234114
233981
  agentId: engineRunContext.agentId ?? null
234115
233982
  });
234116
- let isResuming = !!task.sessionFile && existsSync65(task.sessionFile);
233983
+ let isResuming = !!task.sessionFile && existsSync66(task.sessionFile);
234117
233984
  if (isResuming) {
234118
233985
  const persistedWorktreePath = await extractPersistedSessionWorktreePath(task.sessionFile, this.rootDir, settings);
234119
233986
  if (!isSessionWorktreeCompatible(persistedWorktreePath, worktreePath)) {
@@ -234894,7 +234761,7 @@ ${summary}`,
234894
234761
  return;
234895
234762
  } else {
234896
234763
  executorLog.log(`${task.id} paused \u2014 moving to todo`);
234897
- if (worktreePath && existsSync65(worktreePath)) {
234764
+ if (worktreePath && existsSync66(worktreePath)) {
234898
234765
  try {
234899
234766
  const settings2 = await this.store.getSettings();
234900
234767
  await removeWorktree({
@@ -235291,7 +235158,7 @@ ${summary}`,
235291
235158
  executorLog.warn(`\u26A1 ${task.id} transient error \u2014 retry ${attempt}/${MAX_RECOVERY_RETRIES} in ${delay6}: ${errorMessage5}`);
235292
235159
  await this.store.logEntry(task.id, `Transient error (retry ${attempt}/${MAX_RECOVERY_RETRIES} in ${delay6}): ${errorMessage5}`, void 0, this.getRunContextFor(task.id));
235293
235160
  }
235294
- if (worktreePath && existsSync65(worktreePath)) {
235161
+ if (worktreePath && existsSync66(worktreePath)) {
235295
235162
  try {
235296
235163
  const settings2 = await this.store.getSettings();
235297
235164
  await removeWorktree({
@@ -235427,7 +235294,7 @@ ${summary}`,
235427
235294
  const settings2 = await this.store.getSettings();
235428
235295
  const preserveProgress = settings2.preserveProgressOnStuckRequeue !== false;
235429
235296
  await this.resetStepsIfWorkLost(latestTask);
235430
- if (worktreePath && existsSync65(worktreePath)) {
235297
+ if (worktreePath && existsSync66(worktreePath)) {
235431
235298
  try {
235432
235299
  await removeWorktree({
235433
235300
  worktreePath,
@@ -235854,7 +235721,7 @@ ${summary}`,
235854
235721
  for (const repoRel of Object.keys(workspaceWorktrees).sort()) {
235855
235722
  const repo = workspaceWorktrees[repoRel];
235856
235723
  const expectedBranch = repo.branch || canonicalFusionBranchName(task.id);
235857
- if (!existsSync65(repo.worktreePath)) {
235724
+ if (!existsSync66(repo.worktreePath)) {
235858
235725
  executorLog.log(`${task.id}: workspace worktree for ${repoRel} not found at ${repo.worktreePath} \u2014 skipping git validation`);
235859
235726
  continue;
235860
235727
  }
@@ -235986,7 +235853,7 @@ ${summary}`,
235986
235853
  expected: `resolvable task worktree under ${resolveWorktreesDir(this.rootDir, settings)}/*`
235987
235854
  };
235988
235855
  }
235989
- if (!existsSync65(worktreePath)) {
235856
+ if (!existsSync66(worktreePath)) {
235990
235857
  executorLog.log(
235991
235858
  `${task.id}: worktree directory not found at ${worktreePath} \u2014 skipping git validation for task completion`
235992
235859
  );
@@ -236315,10 +236182,10 @@ ${summary}`,
236315
236182
  { description: '"completed" (default) finishes the task; "blocked" honestly parks it as failed because the work cannot proceed. Use "blocked" instead of skipping steps + completing when you are stuck.' }
236316
236183
  )),
236317
236184
  blockedBy: Type7.Optional(Type7.Array(Type7.String(), {
236318
- description: 'When outcome="blocked": task IDs (e.g. ["FN-8145"]) and/or PR refs (e.g. ["pr:2398"]) that must clear before this task can proceed. Task IDs become real dependency edges; PR refs are stored as external blockers (durable park until the PR merges/closes).'
236185
+ description: 'When outcome="blocked": Fusion task IDs (e.g. ["FN-8145"]) that must complete before this task can proceed. Task IDs become real dependency edges. Open GitHub PRs are not valid blockers.'
236319
236186
  })),
236320
236187
  reason: Type7.Optional(Type7.String({
236321
- description: 'Required when outcome="blocked": concrete explanation of what is blocking the work and what is needed to unblock it. File-claim / open-PR collisions should name the PR (e.g. "actively claimed by PR #2398").'
236188
+ description: 'Required when outcome="blocked": concrete explanation of what is blocking the work and what is needed to unblock it.'
236322
236189
  }))
236323
236190
  }),
236324
236191
  execute: async (_id, params) => {
@@ -236377,7 +236244,7 @@ ${summary}`,
236377
236244
  }, this.getRunContextFor(taskId));
236378
236245
  await store.logEntry(
236379
236246
  taskId,
236380
- thrashExhausted ? `${parkError} \u2014 durable external block thrash-exhausted (signature=${classification.thrashSignature}); parked failed, no auto-requeue` : classification.externalBlockers.length > 0 ? `${parkError} \u2014 durable external block (${classification.class}; pr=${classification.prNumbers.join(",") || "none"}; tasks=${blockedByIds.join(",") || "none"}) \u2014 parked failed (honest blocked exit; steps preserved)` : `${parkError} \u2014 recorded dependencies: ${blockedByIds.join(", ")} \u2014 parked failed (honest blocked exit; steps preserved)`,
236247
+ thrashExhausted ? `${parkError} \u2014 durable external block thrash-exhausted (signature=${classification.thrashSignature}); parked failed, no auto-requeue` : `${parkError} \u2014 recorded dependencies: ${blockedByIds.join(", ")} \u2014 parked failed (honest blocked exit; steps preserved)`,
236381
236248
  void 0,
236382
236249
  this.getRunContextFor(taskId)
236383
236250
  );
@@ -236396,18 +236263,17 @@ ${summary}`,
236396
236263
  parkedAs: autoReplanPark ? "auto-replan" : "failed",
236397
236264
  blockedClass: classification.class,
236398
236265
  thrashCount,
236399
- thrashExhausted,
236400
- prNumbers: classification.prNumbers
236266
+ thrashExhausted
236401
236267
  }
236402
236268
  });
236403
236269
  await this.persistTokenUsage(taskId);
236404
236270
  executorLog.log(
236405
- `\u26D4 ${taskId} ${autoReplanPark ? "parked for automatic replan via blocked exit (plan defect, no dependencies)" : thrashExhausted ? `parked failed via blocked thrash-exhaustion (class=${classification.class})` : `parked failed via durable blocked exit (class=${classification.class}; blockedBy tasks: ${blockedByIds.join(", ") || "none"}; pr: ${classification.prNumbers.join(",") || "none"})`}`
236271
+ `\u26D4 ${taskId} ${autoReplanPark ? "parked for automatic replan via blocked exit (plan defect, no dependencies)" : thrashExhausted ? `parked failed via blocked thrash-exhaustion (class=${classification.class})` : `parked failed via durable blocked exit (class=${classification.class}; blockedBy tasks: ${blockedByIds.join(", ") || "none"})`}`
236406
236272
  );
236407
236273
  return {
236408
236274
  content: [{
236409
236275
  type: "text",
236410
- text: autoReplanPark ? "Task parked as blocked with no external/file-claim blocker \u2014 queued for automatic replan so the plan can resolve the conflict. Steps left in their true statuses; no completion recorded." : thrashExhausted ? "Task parked as blocked (failed) after repeated identical durable blocks \u2014 no further automatic retries. Resolve the external claim/PR or replan manually." : blockedByIds.length > 0 ? `Task parked as blocked (failed). Recorded ${blockedByIds.length} blocking task dependency(ies); it will requeue once they complete. Steps left in their true statuses; no completion recorded.` : classification.prNumbers.length > 0 ? `Task parked as blocked (failed) on open PR #${classification.prNumbers.join(", #")}. It will not auto-replan or re-execute until that claim clears or an operator retries. Steps preserved.` : "Task parked as blocked (failed) on a durable external/file-claim blocker. No automatic replan. Steps preserved."
236276
+ text: autoReplanPark ? "Task parked as blocked with no blocking task dependencies \u2014 queued for automatic replan so the plan can resolve the conflict. Steps left in their true statuses; no completion recorded." : thrashExhausted ? "Task parked as blocked (failed) after repeated identical durable blocks \u2014 no further automatic retries. Resolve the blocking tasks or replan manually." : `Task parked as blocked (failed). Recorded ${blockedByIds.length} blocking task dependency(ies); it will requeue once they complete. Steps left in their true statuses; no completion recorded.`
236411
236277
  }],
236412
236278
  details: {}
236413
236279
  };
@@ -238465,7 +238331,7 @@ ${detectedQuestion}
238465
238331
  * rather than fail the task permanently.
238466
238332
  */
238467
238333
  async resolveWorktreeStartPoint(startPoint, taskId) {
238468
- const command = isAbsolute18(startPoint) && existsSync65(startPoint) ? `git -C "${startPoint}" rev-parse --verify HEAD^{commit}` : `git rev-parse --verify "${startPoint}^{commit}"`;
238334
+ const command = isAbsolute18(startPoint) && existsSync66(startPoint) ? `git -C "${startPoint}" rev-parse --verify HEAD^{commit}` : `git rev-parse --verify "${startPoint}^{commit}"`;
238469
238335
  try {
238470
238336
  const { stdout } = await execAsync36(command, { cwd: this.rootDir });
238471
238337
  return stdout.trim() || startPoint;
@@ -238688,7 +238554,7 @@ ${detectedQuestion}
238688
238554
  throw error3;
238689
238555
  }
238690
238556
  };
238691
- if (existsSync65(path14)) {
238557
+ if (existsSync66(path14)) {
238692
238558
  const isRegistered = await this.isRegisteredWorktree(path14);
238693
238559
  if (!isRegistered) {
238694
238560
  await this.store.logEntry(
@@ -239304,7 +239170,7 @@ ${detectedQuestion}
239304
239170
  const stillRegistered = await isRegisteredGitWorktree2(this.rootDir, worktreePath).catch(() => true);
239305
239171
  const activeOwner2 = await this.findActiveWorktreeOwner(worktreePath, taskId).catch(() => "unknown");
239306
239172
  let safeToRemove = isInsideWorktreesDir(this.rootDir, worktreePath, settings) && !stillRegistered && activeOwner2 === null;
239307
- if (safeToRemove && existsSync65(worktreePath)) {
239173
+ if (safeToRemove && existsSync66(worktreePath)) {
239308
239174
  try {
239309
239175
  if (lstatSync3(worktreePath).isSymbolicLink()) {
239310
239176
  safeToRemove = false;
@@ -239332,7 +239198,7 @@ ${detectedQuestion}
239332
239198
  const pruneMsg = pruneErr instanceof Error ? pruneErr.message : String(pruneErr);
239333
239199
  executorLog.warn(`${taskId}: git worktree prune failed during stale-path cleanup of ${worktreePath}: ${pruneMsg}`);
239334
239200
  }
239335
- if (existsSync65(worktreePath)) {
239201
+ if (existsSync66(worktreePath)) {
239336
239202
  try {
239337
239203
  await rm12(worktreePath, { recursive: true, force: true });
239338
239204
  } catch (rmErr) {
@@ -239779,7 +239645,7 @@ ${detectedQuestion}
239779
239645
  this.clearPausedAborted(taskId);
239780
239646
  await this.resetStepsIfWorkLost(latestTask);
239781
239647
  let cleanupFailed = false;
239782
- if (worktreePath && existsSync65(worktreePath)) {
239648
+ if (worktreePath && existsSync66(worktreePath)) {
239783
239649
  try {
239784
239650
  await removeWorktree({
239785
239651
  worktreePath,
@@ -243866,7 +243732,7 @@ var init_overseer_noop_finalize_veto = __esm({
243866
243732
 
243867
243733
  // ../engine/src/merger-ai-worktree.ts
243868
243734
  import { execFile as execFile27 } from "node:child_process";
243869
- import { appendFileSync as appendFileSync2, existsSync as existsSync66, mkdirSync as mkdirSync11, readdirSync as readdirSync12, readFileSync as readFileSync24, realpathSync as realpathSync11, rmSync as rmSync9, statSync as statSync13 } from "node:fs";
243735
+ import { appendFileSync as appendFileSync2, existsSync as existsSync67, mkdirSync as mkdirSync11, readdirSync as readdirSync12, readFileSync as readFileSync24, realpathSync as realpathSync11, rmSync as rmSync9, statSync as statSync13 } from "node:fs";
243870
243736
  import { rm as rm13 } from "node:fs/promises";
243871
243737
  import { tmpdir as tmpdir10 } from "node:os";
243872
243738
  import { isAbsolute as isAbsolute19, join as join79, relative as relative17 } from "node:path";
@@ -243901,7 +243767,7 @@ function isBenignAbsentWorktreeError(err) {
243901
243767
  }
243902
243768
  function ensureAiMergeRootIgnored(projectRootDir, settings) {
243903
243769
  const excludePath = join79(projectRootDir, ".git", "info", "exclude");
243904
- if (!existsSync66(excludePath)) return;
243770
+ if (!existsSync67(excludePath)) return;
243905
243771
  try {
243906
243772
  const current = readFileSync24(excludePath, "utf-8");
243907
243773
  const legacyAiMergeRoot = resolveLegacyAiMergeRootPath(projectRootDir);
@@ -244032,7 +243898,7 @@ async function cleanupAiMergeWorktree(input) {
244032
243898
  const cleanupMetadata = { taskId, mergeRoot: canonicalRoot, requestedMergeRoot: mergeRoot };
244033
243899
  let alreadyAbsent = false;
244034
243900
  if (worktreeAdded) {
244035
- if (!existsSync66(canonicalRoot) && !existsSync66(mergeRoot)) {
243901
+ if (!existsSync67(canonicalRoot) && !existsSync67(mergeRoot)) {
244036
243902
  alreadyAbsent = true;
244037
243903
  await log43(`AI merge cleanup: worktree ${canonicalRoot} was already absent before git removal; treating cleanup as idempotent`);
244038
243904
  await audit.git({ type: "merge:ai-worktree-cleanup", target: canonicalRoot, metadata: { ...cleanupMetadata, phase: "git-remove", success: true, alreadyAbsent: true, idempotent: true, code: "ENOENT" } });
@@ -250354,12 +250220,12 @@ The note must be specific (what/where/why). Prefer citing File Scope, PROMPT, a
250354
250220
  });
250355
250221
 
250356
250222
  // ../engine/src/overseer-watchdog.ts
250357
- import { existsSync as existsSync67, readFileSync as readFileSync25 } from "node:fs";
250223
+ import { existsSync as existsSync68, readFileSync as readFileSync25 } from "node:fs";
250358
250224
  import { dirname as dirname34, join as join82, relative as relative18, resolve as resolve40, sep as sep11 } from "node:path";
250359
250225
  import { homedir as homedir12 } from "node:os";
250360
250226
  function defaultReadText(path14) {
250361
250227
  try {
250362
- if (!existsSync67(path14)) return null;
250228
+ if (!existsSync68(path14)) return null;
250363
250229
  return readFileSync25(path14, "utf8");
250364
250230
  } catch {
250365
250231
  return null;
@@ -256160,7 +256026,7 @@ var init_adapters = __esm({
256160
256026
  });
256161
256027
 
256162
256028
  // ../engine/src/cli-agent/resume-coordinator.ts
256163
- import { existsSync as existsSync68 } from "node:fs";
256029
+ import { existsSync as existsSync69 } from "node:fs";
256164
256030
  import { execFile as execFile30 } from "node:child_process";
256165
256031
  import { promisify as promisify62 } from "node:util";
256166
256032
  async function defaultIsWorktreeDirty(worktreePath) {
@@ -256205,7 +256071,7 @@ var init_resume_coordinator = __esm({
256205
256071
  this.reattachTelemetry = opts.reattachTelemetry;
256206
256072
  this.maxResumeAttempts = opts.maxResumeAttempts ?? DEFAULT_MAX_RESUME_ATTEMPTS;
256207
256073
  this.resumeBackoffBaseMs = opts.resumeBackoffBaseMs ?? DEFAULT_RESUME_BACKOFF_BASE_MS;
256208
- this.worktreeExists = opts.worktreeExists ?? ((p2) => existsSync68(p2));
256074
+ this.worktreeExists = opts.worktreeExists ?? ((p2) => existsSync69(p2));
256209
256075
  this.isWorktreeDirty = opts.isWorktreeDirty ?? defaultIsWorktreeDirty;
256210
256076
  this.log = opts.log ?? (() => {
256211
256077
  });
@@ -280583,11 +280449,11 @@ var init_task_lookup_error = __esm({
280583
280449
  });
280584
280450
 
280585
280451
  // ../dashboard/src/cli-package-version.ts
280586
- import { existsSync as existsSync69, readFileSync as readFileSync26 } from "node:fs";
280452
+ import { existsSync as existsSync70, readFileSync as readFileSync26 } from "node:fs";
280587
280453
  import { dirname as dirname37, resolve as resolve43 } from "node:path";
280588
280454
  import { fileURLToPath as fileURLToPath5 } from "node:url";
280589
280455
  function readPackageVersion(pkgPath, packageNames) {
280590
- if (!existsSync69(pkgPath)) {
280456
+ if (!existsSync70(pkgPath)) {
280591
280457
  return null;
280592
280458
  }
280593
280459
  try {
@@ -294043,7 +293909,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
294043
293909
  };
294044
293910
  router.get("/tasks/:id/stranded-refinement", async (req, res) => {
294045
293911
  try {
294046
- const { existsSync: existsSync118 } = await import("node:fs");
293912
+ const { existsSync: existsSync119 } = await import("node:fs");
294047
293913
  const { join: join153 } = await import("node:path");
294048
293914
  const { store: scopedStore } = await getProjectContext2(req);
294049
293915
  const task = await scopedStore.getTask(req.params.id);
@@ -294062,7 +293928,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
294062
293928
  ageMs: Math.max(0, Date.now() - Date.parse(task.createdAt))
294063
293929
  };
294064
293930
  const promptPath = join153(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
294065
- const promptExists = existsSync118(promptPath);
293931
+ const promptExists = existsSync119(promptPath);
294066
293932
  const dependencyDetails = await Promise.all((task.dependencies ?? []).map(async (dependencyId) => {
294067
293933
  try {
294068
293934
  const depTask = await scopedStore.getTask(dependencyId);
@@ -298823,7 +298689,7 @@ __export(chat_exports, {
298823
298689
  });
298824
298690
  import { EventEmitter as EventEmitter40 } from "node:events";
298825
298691
  import { randomUUID as randomUUID50 } from "node:crypto";
298826
- import { existsSync as existsSync70 } from "node:fs";
298692
+ import { existsSync as existsSync71 } from "node:fs";
298827
298693
  import { join as join90, resolve as resolve48, relative as relative20 } from "node:path";
298828
298694
  import { SessionManager as SessionManager3 } from "@earendil-works/pi-coding-agent";
298829
298695
  function __getChatDiagnostics() {
@@ -299030,7 +298896,7 @@ function createTaskVerificationTools(taskStore, actionGateContext) {
299030
298896
  const profile = typeof raw.profile === "string" ? raw.profile : "verify:fast";
299031
298897
  if (!taskId || !profiles.has(profile)) return { content: [{ type: "text", text: "ERROR: task_id and an allowlisted profile are required; raw commands are not accepted." }], isError: true, details: {} };
299032
298898
  const task = await taskStore.getTask(taskId);
299033
- if (!task || !(await wipColumnsForTask(taskStore, taskId)).has(task.column) || !task.worktree || !existsSync70(task.worktree)) return { content: [{ type: "text", text: "ERROR: verification requires an in-progress task with a live executor worktree." }], isError: true, details: {} };
298899
+ if (!task || !(await wipColumnsForTask(taskStore, taskId)).has(task.column) || !task.worktree || !existsSync71(task.worktree)) return { content: [{ type: "text", text: "ERROR: verification requires an in-progress task with a live executor worktree." }], isError: true, details: {} };
299034
298900
  const settings = await taskStore.getSettings();
299035
298901
  const command = profile === "verify:fast" ? "pnpm verify:fast" : typeof settings.testCommand === "string" ? settings.testCommand : "";
299036
298902
  if (!command) return { content: [{ type: "text", text: "ERROR: the selected verification profile is not configured." }], isError: true, details: {} };
@@ -299861,7 +299727,7 @@ When you need structured input, or whenever you present options, choices, or a d
299861
299727
  * keep the CLI session stable across user messages.
299862
299728
  */
299863
299729
  async resolveCliSessionManager(session) {
299864
- if (session.cliSessionFile && existsSync70(session.cliSessionFile)) {
299730
+ if (session.cliSessionFile && existsSync71(session.cliSessionFile)) {
299865
299731
  try {
299866
299732
  return SessionManager3.open(session.cliSessionFile);
299867
299733
  } catch (err) {
@@ -351746,7 +351612,7 @@ var init_cli_spawn = __esm({
351746
351612
  // ../../plugins/fusion-plugin-hermes-runtime/src/fusion-skill-install.ts
351747
351613
  import {
351748
351614
  cpSync as cpSync2,
351749
- existsSync as existsSync72,
351615
+ existsSync as existsSync73,
351750
351616
  lstatSync as lstatSync4,
351751
351617
  mkdirSync as mkdirSync13,
351752
351618
  readFileSync as readFileSync28,
@@ -351776,7 +351642,7 @@ function getFusionSkillSourceCandidates(moduleUrl = import.meta.url) {
351776
351642
  function resolveBundledFusionSkillSource() {
351777
351643
  const candidates = getFusionSkillSourceCandidates();
351778
351644
  for (const candidate of candidates) {
351779
- if (existsSync72(join97(candidate, "SKILL.md"))) return candidate;
351645
+ if (existsSync73(join97(candidate, "SKILL.md"))) return candidate;
351780
351646
  }
351781
351647
  return null;
351782
351648
  }
@@ -351794,7 +351660,7 @@ function installFusionSkillIntoHermesHome(options = {}) {
351794
351660
  try {
351795
351661
  mkdirSync13(dirname40(targetDir), { recursive: true });
351796
351662
  let replaced = false;
351797
- if (existsSync72(targetDir) || isBrokenSymlink(targetDir)) {
351663
+ if (existsSync73(targetDir) || isBrokenSymlink(targetDir)) {
351798
351664
  const stat20 = lstatSync4(targetDir);
351799
351665
  if (stat20.isSymbolicLink()) {
351800
351666
  const currentTarget = safeReadlink(targetDir);
@@ -351865,14 +351731,14 @@ function safeReadlink(path14) {
351865
351731
  function isBrokenSymlink(path14) {
351866
351732
  try {
351867
351733
  const stat20 = lstatSync4(path14);
351868
- return stat20.isSymbolicLink() && !existsSync72(path14);
351734
+ return stat20.isSymbolicLink() && !existsSync73(path14);
351869
351735
  } catch {
351870
351736
  return false;
351871
351737
  }
351872
351738
  }
351873
351739
  function looksLikePriorFusionInstall(path14) {
351874
351740
  const skillMd = join97(path14, "SKILL.md");
351875
- if (!existsSync72(skillMd)) return false;
351741
+ if (!existsSync73(skillMd)) return false;
351876
351742
  try {
351877
351743
  const body = readFileSync28(skillMd, "utf-8");
351878
351744
  return /\bfusion\b/i.test(body) && /\bskill\b/i.test(body);
@@ -351883,7 +351749,7 @@ function looksLikePriorFusionInstall(path14) {
351883
351749
  function looksLikeFusionSkillTarget(path14) {
351884
351750
  if (!path14) return false;
351885
351751
  if (basename28(path14).toLowerCase() === FUSION_SKILL_NAME) return true;
351886
- return existsSync72(join97(path14, "SKILL.md"));
351752
+ return existsSync73(join97(path14, "SKILL.md"));
351887
351753
  }
351888
351754
  var FUSION_SKILL_NAME;
351889
351755
  var init_fusion_skill_install = __esm({
@@ -354906,7 +354772,7 @@ var init_provider2 = __esm({
354906
354772
  });
354907
354773
 
354908
354774
  // ../../plugins/fusion-plugin-grok-runtime/src/acp/cli-spawn.ts
354909
- import { existsSync as existsSync74 } from "node:fs";
354775
+ import { existsSync as existsSync75 } from "node:fs";
354910
354776
  import { dirname as dirname42, isAbsolute as isAbsolute28, join as join101, resolve as resolve59 } from "node:path";
354911
354777
  import { fileURLToPath as fileURLToPath9 } from "node:url";
354912
354778
  function asTrimmedString(value) {
@@ -354929,7 +354795,7 @@ function bundledClaudeBridgeBinPath(pluginRoot = pluginRootDir()) {
354929
354795
  }
354930
354796
  function resolveBundledClaudeBridgeBinary(options = {}) {
354931
354797
  const root = options.pluginRoot ?? pluginRootDir();
354932
- const exists2 = options.exists ?? existsSync74;
354798
+ const exists2 = options.exists ?? existsSync75;
354933
354799
  const candidate = bundledClaudeBridgeBinPath(root);
354934
354800
  if (!exists2(candidate)) {
354935
354801
  return {
@@ -356278,7 +356144,7 @@ var init_mcp_forwarding = __esm({
356278
356144
  // ../../plugins/fusion-plugin-grok-runtime/src/skill-loader.ts
356279
356145
  import {
356280
356146
  cpSync as cpSync3,
356281
- existsSync as existsSync75,
356147
+ existsSync as existsSync76,
356282
356148
  mkdirSync as mkdirSync14,
356283
356149
  mkdtempSync as mkdtempSync3,
356284
356150
  readdirSync as readdirSync14,
@@ -356291,7 +356157,7 @@ import { tmpdir as tmpdir16 } from "node:os";
356291
356157
  import { basename as basename30, dirname as dirname44, join as join103, resolve as resolve61 } from "node:path";
356292
356158
  import { fileURLToPath as fileURLToPath10 } from "node:url";
356293
356159
  function isSkillDir(dir2) {
356294
- return existsSync75(join103(dir2, "SKILL.md"));
356160
+ return existsSync76(join103(dir2, "SKILL.md"));
356295
356161
  }
356296
356162
  function pushUnique(out, candidate) {
356297
356163
  if (!candidate) return;
@@ -356355,7 +356221,7 @@ function resolveBundledFusionSkillSource2(moduleUrl = import.meta.url) {
356355
356221
  function installSkillDir(sourceDir, targetDir) {
356356
356222
  if (!isSkillDir(sourceDir)) return false;
356357
356223
  mkdirSync14(dirname44(targetDir), { recursive: true });
356358
- if (existsSync75(targetDir)) {
356224
+ if (existsSync76(targetDir)) {
356359
356225
  rmSync11(targetDir, { recursive: true, force: true });
356360
356226
  }
356361
356227
  try {
@@ -356371,7 +356237,7 @@ function installSkillDir(sourceDir, targetDir) {
356371
356237
  }
356372
356238
  }
356373
356239
  function collectSkillsFromRoot(root, out) {
356374
- if (!existsSync75(root)) return;
356240
+ if (!existsSync76(root)) return;
356375
356241
  if (isSkillDir(root)) {
356376
356242
  out.set(basename30(root), root);
356377
356243
  return;
@@ -356410,7 +356276,7 @@ function stageGrokSessionSkills(options = {}) {
356410
356276
  installSkillDir(source, join103(skillsDir, name2));
356411
356277
  }
356412
356278
  for (const [name2, source] of installed) {
356413
- if (!existsSync75(join103(skillsDir, name2))) {
356279
+ if (!existsSync76(join103(skillsDir, name2))) {
356414
356280
  installSkillDir(source, join103(skillsDir, name2));
356415
356281
  }
356416
356282
  }
@@ -356479,7 +356345,7 @@ var init_skill_loader = __esm({
356479
356345
 
356480
356346
  // ../../plugins/fusion-plugin-grok-runtime/src/tool-bridge.ts
356481
356347
  import { createServer as createServer2 } from "node:http";
356482
- import { existsSync as existsSync76, writeFileSync as writeFileSync15 } from "node:fs";
356348
+ import { existsSync as existsSync77, writeFileSync as writeFileSync15 } from "node:fs";
356483
356349
  import { tmpdir as tmpdir17 } from "node:os";
356484
356350
  import { dirname as dirname45, join as join104 } from "node:path";
356485
356351
  import { fileURLToPath as fileURLToPath11 } from "node:url";
@@ -356525,7 +356391,7 @@ async function startFusionToolBridge(tools) {
356525
356391
  const defs = toolsToMcpToolDefs2(tools);
356526
356392
  if (defs.length === 0) return null;
356527
356393
  const serverPath = fusionToolsMcpServerPath();
356528
- if (!existsSync76(serverPath)) {
356394
+ if (!existsSync77(serverPath)) {
356529
356395
  throw missingMcpSchemaServerError(serverPath);
356530
356396
  }
356531
356397
  const byName = /* @__PURE__ */ new Map();
@@ -356966,7 +356832,7 @@ var init_src11 = __esm({
356966
356832
  });
356967
356833
 
356968
356834
  // ../../plugins/fusion-plugin-claude-runtime/src/acp/cli-spawn.ts
356969
- import { existsSync as existsSync77 } from "node:fs";
356835
+ import { existsSync as existsSync78 } from "node:fs";
356970
356836
  import { dirname as dirname46, isAbsolute as isAbsolute29, join as join105, resolve as resolve62 } from "node:path";
356971
356837
  import { fileURLToPath as fileURLToPath12 } from "node:url";
356972
356838
  function asTrimmedString2(value) {
@@ -356989,7 +356855,7 @@ function bundledClaudeBridgeBinPath2(pluginRoot = pluginRootDir2()) {
356989
356855
  }
356990
356856
  function resolveBundledClaudeBridgeBinary2(options = {}) {
356991
356857
  const root = options.pluginRoot ?? pluginRootDir2();
356992
- const exists2 = options.exists ?? existsSync77;
356858
+ const exists2 = options.exists ?? existsSync78;
356993
356859
  const candidate = bundledClaudeBridgeBinPath2(root);
356994
356860
  if (!exists2(candidate)) {
356995
356861
  return {
@@ -358224,7 +358090,7 @@ var init_acp2 = __esm({
358224
358090
 
358225
358091
  // ../../plugins/fusion-plugin-claude-runtime/src/cli-spawn.ts
358226
358092
  import { spawn as spawn21 } from "node:child_process";
358227
- import { existsSync as existsSync78 } from "node:fs";
358093
+ import { existsSync as existsSync79 } from "node:fs";
358228
358094
  import { basename as basename32, dirname as dirname48, isAbsolute as isAbsolute30, join as join107, resolve as resolve64 } from "node:path";
358229
358095
  import { fileURLToPath as fileURLToPath13 } from "node:url";
358230
358096
  function pluginRootDir3() {
@@ -358236,7 +358102,7 @@ function bundledClaudeBridgeBinPath3(pluginRoot = pluginRootDir3()) {
358236
358102
  }
358237
358103
  function resolveBundledClaudeBridgeBinary3(options = {}) {
358238
358104
  const candidate = bundledClaudeBridgeBinPath3(options.pluginRoot ?? pluginRootDir3());
358239
- const exists2 = options.exists ?? existsSync78;
358105
+ const exists2 = options.exists ?? existsSync79;
358240
358106
  if (!exists2(candidate) || !isAbsolute30(candidate)) return { kind: "not_resolved", requested: CLAUDE_CODE_CLI_ACP_BINARY3, path: candidate, reason: `Staged ${CLAUDE_CODE_CLI_ACP_BINARY3} bridge was not found at ${candidate}` };
358241
358107
  return { kind: "resolved", requested: CLAUDE_CODE_CLI_ACP_BINARY3, path: candidate };
358242
358108
  }
@@ -358399,7 +358265,7 @@ var init_mcp_forwarding2 = __esm({
358399
358265
  // ../../plugins/fusion-plugin-claude-runtime/src/skill-loader.ts
358400
358266
  import {
358401
358267
  cpSync as cpSync4,
358402
- existsSync as existsSync79,
358268
+ existsSync as existsSync80,
358403
358269
  mkdirSync as mkdirSync15,
358404
358270
  mkdtempSync as mkdtempSync4,
358405
358271
  readdirSync as readdirSync15,
@@ -358412,7 +358278,7 @@ import { tmpdir as tmpdir18 } from "node:os";
358412
358278
  import { basename as basename33, dirname as dirname49, join as join108, resolve as resolve65 } from "node:path";
358413
358279
  import { fileURLToPath as fileURLToPath14 } from "node:url";
358414
358280
  function isSkillDir2(dir2) {
358415
- return existsSync79(join108(dir2, "SKILL.md"));
358281
+ return existsSync80(join108(dir2, "SKILL.md"));
358416
358282
  }
358417
358283
  function pushUnique2(out, candidate) {
358418
358284
  if (!candidate) return;
@@ -358476,7 +358342,7 @@ function resolveBundledFusionSkillSource3(moduleUrl = import.meta.url) {
358476
358342
  function installSkillDir2(sourceDir, targetDir) {
358477
358343
  if (!isSkillDir2(sourceDir)) return false;
358478
358344
  mkdirSync15(dirname49(targetDir), { recursive: true });
358479
- if (existsSync79(targetDir)) {
358345
+ if (existsSync80(targetDir)) {
358480
358346
  rmSync12(targetDir, { recursive: true, force: true });
358481
358347
  }
358482
358348
  try {
@@ -358492,7 +358358,7 @@ function installSkillDir2(sourceDir, targetDir) {
358492
358358
  }
358493
358359
  }
358494
358360
  function collectSkillsFromRoot2(root, out) {
358495
- if (!existsSync79(root)) return;
358361
+ if (!existsSync80(root)) return;
358496
358362
  if (isSkillDir2(root)) {
358497
358363
  out.set(basename33(root), root);
358498
358364
  return;
@@ -358531,7 +358397,7 @@ function stageClaudeSessionSkills(options = {}) {
358531
358397
  installSkillDir2(source, join108(skillsDir, name2));
358532
358398
  }
358533
358399
  for (const [name2, source] of installed) {
358534
- if (!existsSync79(join108(skillsDir, name2))) {
358400
+ if (!existsSync80(join108(skillsDir, name2))) {
358535
358401
  installSkillDir2(source, join108(skillsDir, name2));
358536
358402
  }
358537
358403
  }
@@ -358600,7 +358466,7 @@ var init_skill_loader2 = __esm({
358600
358466
 
358601
358467
  // ../../plugins/fusion-plugin-claude-runtime/src/tool-bridge.ts
358602
358468
  import { createServer as createServer3 } from "node:http";
358603
- import { existsSync as existsSync80, rmSync as rmSync13, writeFileSync as writeFileSync17 } from "node:fs";
358469
+ import { existsSync as existsSync81, rmSync as rmSync13, writeFileSync as writeFileSync17 } from "node:fs";
358604
358470
  import { tmpdir as tmpdir19 } from "node:os";
358605
358471
  import { dirname as dirname50, join as join109 } from "node:path";
358606
358472
  import { fileURLToPath as fileURLToPath15 } from "node:url";
@@ -358646,7 +358512,7 @@ async function startFusionToolBridge2(tools, options = {}) {
358646
358512
  const defs = toolsToMcpToolDefs3(tools);
358647
358513
  if (defs.length === 0) return null;
358648
358514
  const serverPath = fusionToolsMcpServerPath2();
358649
- if (!existsSync80(serverPath)) {
358515
+ if (!existsSync81(serverPath)) {
358650
358516
  throw missingMcpSchemaServerError2(serverPath);
358651
358517
  }
358652
358518
  const byName = /* @__PURE__ */ new Map();
@@ -359458,7 +359324,7 @@ var init_provider6 = __esm({
359458
359324
  });
359459
359325
 
359460
359326
  // ../../plugins/fusion-plugin-omp-runtime/src/acp/cli-spawn.ts
359461
- import { existsSync as existsSync81 } from "node:fs";
359327
+ import { existsSync as existsSync82 } from "node:fs";
359462
359328
  import { dirname as dirname51, isAbsolute as isAbsolute31, join as join110, resolve as resolve66 } from "node:path";
359463
359329
  import { fileURLToPath as fileURLToPath16 } from "node:url";
359464
359330
  function asTrimmedString3(value) {
@@ -359481,7 +359347,7 @@ function bundledClaudeBridgeBinPath4(pluginRoot = pluginRootDir4()) {
359481
359347
  }
359482
359348
  function resolveBundledClaudeBridgeBinary4(options = {}) {
359483
359349
  const root = options.pluginRoot ?? pluginRootDir4();
359484
- const exists2 = options.exists ?? existsSync81;
359350
+ const exists2 = options.exists ?? existsSync82;
359485
359351
  const candidate = bundledClaudeBridgeBinPath4(root);
359486
359352
  if (!exists2(candidate)) {
359487
359353
  return {
@@ -360793,7 +360659,7 @@ var init_mcp_forwarding3 = __esm({
360793
360659
 
360794
360660
  // ../../plugins/fusion-plugin-omp-runtime/src/tool-bridge.ts
360795
360661
  import { createServer as createServer4 } from "node:http";
360796
- import { existsSync as existsSync82, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
360662
+ import { existsSync as existsSync83, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
360797
360663
  import { tmpdir as tmpdir20 } from "node:os";
360798
360664
  import { dirname as dirname53, join as join112 } from "node:path";
360799
360665
  import { fileURLToPath as fileURLToPath17 } from "node:url";
@@ -360820,7 +360686,7 @@ function fusionToolsMcpServerPath3() {
360820
360686
  join112(here, "..", "mcp-schema-server.cjs")
360821
360687
  ];
360822
360688
  for (const candidate of candidates) {
360823
- if (existsSync82(candidate)) return candidate;
360689
+ if (existsSync83(candidate)) return candidate;
360824
360690
  }
360825
360691
  return null;
360826
360692
  }
@@ -360958,7 +360824,7 @@ var init_tool_bridge3 = __esm({
360958
360824
  });
360959
360825
 
360960
360826
  // ../../plugins/fusion-plugin-omp-runtime/src/runtime-adapter.ts
360961
- import { existsSync as existsSync83 } from "node:fs";
360827
+ import { existsSync as existsSync84 } from "node:fs";
360962
360828
  function compactDiagnostic3(value) {
360963
360829
  return value.replace(/\s+/g, " ").trim();
360964
360830
  }
@@ -361149,7 +361015,7 @@ var init_runtime_adapter9 = __esm({
361149
361015
  const command = server.command.trim();
361150
361016
  if (!command) return false;
361151
361017
  if (command.includes("/") || command.includes("\\")) {
361152
- return existsSync83(command);
361018
+ return existsSync84(command);
361153
361019
  }
361154
361020
  return true;
361155
361021
  });
@@ -368063,7 +367929,7 @@ var init_auth_provider_catalog = __esm({
368063
367929
  // ../dashboard/src/routes/register-auth-routes.ts
368064
367930
  import { tmpdir as tmpdir21 } from "node:os";
368065
367931
  import { join as join116 } from "node:path";
368066
- import { existsSync as existsSync84, readFileSync as readFileSync29 } from "node:fs";
367932
+ import { existsSync as existsSync85, readFileSync as readFileSync29 } from "node:fs";
368067
367933
  function parseGitHubCopilotDeviceCode(instructions) {
368068
367934
  const match = instructions.match(/Enter code:\s*([A-Z0-9-]+)\b/i);
368069
367935
  return match?.[1];
@@ -368821,7 +368687,7 @@ var init_register_auth_routes = __esm({
368821
368687
  let acpAuthReason;
368822
368688
  try {
368823
368689
  const signalPath = join116(tmpdir21(), "fusion-acp-bridge-auth.json");
368824
- if (existsSync84(signalPath)) {
368690
+ if (existsSync85(signalPath)) {
368825
368691
  const sig = JSON.parse(readFileSync29(signalPath, "utf8"));
368826
368692
  if (sig?.authFailed) {
368827
368693
  acpAuthFailed = true;
@@ -370920,7 +370786,7 @@ import { spawn as spawn27 } from "node:child_process";
370920
370786
  import {
370921
370787
  chmodSync as chmodSync4,
370922
370788
  cpSync as cpSync5,
370923
- existsSync as existsSync85,
370789
+ existsSync as existsSync86,
370924
370790
  lstatSync as lstatSync5,
370925
370791
  mkdirSync as mkdirSync16,
370926
370792
  readlinkSync as readlinkSync3,
@@ -371035,20 +370901,20 @@ function runStreamingCommand(command, args, options) {
371035
370901
  function resolveBunExecutable() {
371036
370902
  if (process.env.BUN_INSTALL) {
371037
370903
  const candidate = join119(process.env.BUN_INSTALL, "bin", process.platform === "win32" ? "bun.exe" : "bun");
371038
- if (existsSync85(candidate)) return candidate;
370904
+ if (existsSync86(candidate)) return candidate;
371039
370905
  }
371040
370906
  const homeBun = join119(homedir19(), ".bun", "bin", process.platform === "win32" ? "bun.exe" : "bun");
371041
- if (existsSync85(homeBun)) return homeBun;
370907
+ if (existsSync86(homeBun)) return homeBun;
371042
370908
  return "bun";
371043
370909
  }
371044
370910
  function installLocalFnBinary(distDir, onLog, paths2 = resolveFnBinaryLocalPaths()) {
371045
370911
  const srcBinary = join119(distDir, process.platform === "win32" ? "fn.exe" : "fn");
371046
370912
  const srcClient = join119(distDir, "client");
371047
370913
  const srcRuntime = join119(distDir, "runtime");
371048
- if (!existsSync85(srcBinary)) {
370914
+ if (!existsSync86(srcBinary)) {
371049
370915
  throw new Error(`Built binary missing at ${srcBinary}. Did the Bun compile step fail?`);
371050
370916
  }
371051
- if (!existsSync85(srcClient)) {
370917
+ if (!existsSync86(srcClient)) {
371052
370918
  throw new Error(`Dashboard client assets missing at ${srcClient}.`);
371053
370919
  }
371054
370920
  mkdirSync16(paths2.installDir, { recursive: true });
@@ -371062,14 +370928,14 @@ function installLocalFnBinary(distDir, onLog, paths2 = resolveFnBinaryLocalPaths
371062
370928
  onLog("system", `Installing client assets \u2192 ${join119(paths2.installDir, "client")}`);
371063
370929
  rmSync14(join119(paths2.installDir, "client"), { recursive: true, force: true });
371064
370930
  cpSync5(srcClient, join119(paths2.installDir, "client"), { recursive: true });
371065
- if (existsSync85(srcRuntime)) {
370931
+ if (existsSync86(srcRuntime)) {
371066
370932
  onLog("system", `Installing runtime assets \u2192 ${join119(paths2.installDir, "runtime")}`);
371067
370933
  rmSync14(join119(paths2.installDir, "runtime"), { recursive: true, force: true });
371068
370934
  cpSync5(srcRuntime, join119(paths2.installDir, "runtime"), { recursive: true });
371069
370935
  }
371070
370936
  for (const shim of [paths2.fnShimPath, paths2.fusionShimPath]) {
371071
370937
  try {
371072
- if (existsSync85(shim) || isSymlink(shim)) {
370938
+ if (existsSync86(shim) || isSymlink(shim)) {
371073
370939
  unlinkSync6(shim);
371074
370940
  }
371075
370941
  } catch {
@@ -371091,7 +370957,7 @@ function removeLocalFnShims(onLog, paths2 = resolveFnBinaryLocalPaths()) {
371091
370957
  const installReal = resolve69(paths2.binaryPath);
371092
370958
  for (const shim of [paths2.fnShimPath, paths2.fusionShimPath]) {
371093
370959
  try {
371094
- if (!existsSync85(shim) && !isSymlink(shim)) {
370960
+ if (!existsSync86(shim) && !isSymlink(shim)) {
371095
370961
  onLog("system", `No shim at ${shim}`);
371096
370962
  continue;
371097
370963
  }
@@ -371123,10 +370989,10 @@ async function runLinkLocalFnBinary(sourceRoot, onLog) {
371123
370989
  const buildScript = join119(sourceRoot, "scripts", "build-workspace.mjs");
371124
370990
  const cliBuild = join119(sourceRoot, "packages", "cli", "build.ts");
371125
370991
  const distDir = join119(sourceRoot, "packages", "cli", "dist");
371126
- if (!existsSync85(buildScript)) {
370992
+ if (!existsSync86(buildScript)) {
371127
370993
  return { success: false, error: `Build script missing: ${buildScript}` };
371128
370994
  }
371129
- if (!existsSync85(cliBuild)) {
370995
+ if (!existsSync86(cliBuild)) {
371130
370996
  return { success: false, error: `CLI build entry missing: ${cliBuild}` };
371131
370997
  }
371132
370998
  onLog("system", "Step 1/3 \u2014 full workspace package build\u2026");
@@ -371202,7 +371068,7 @@ var init_fn_binary_local_install = __esm({
371202
371068
 
371203
371069
  // ../dashboard/src/routes/register-system-routes.ts
371204
371070
  import { randomUUID as randomUUID66 } from "node:crypto";
371205
- import { existsSync as existsSync86 } from "node:fs";
371071
+ import { existsSync as existsSync87 } from "node:fs";
371206
371072
  import { join as join120 } from "node:path";
371207
371073
  function rejectCrossOrigin(req, res) {
371208
371074
  const origin = req.headers.origin;
@@ -371394,7 +371260,7 @@ function registerSystemRoutes(ctx, deps) {
371394
371260
  const restartAfter = body.restart !== false && scope !== "plugins";
371395
371261
  const { args, label } = rebuildScopes[scope];
371396
371262
  const scriptPath = join120(root, args[0]);
371397
- if (!existsSync86(scriptPath)) {
371263
+ if (!existsSync87(scriptPath)) {
371398
371264
  throw new ApiError(409, `Build script missing: ${scriptPath}`);
371399
371265
  }
371400
371266
  const job = {
@@ -382634,7 +382500,7 @@ var init_reliability_metrics = __esm({
382634
382500
  });
382635
382501
 
382636
382502
  // ../dashboard/src/view-chunk-manifest.ts
382637
- import { existsSync as existsSync87, readFileSync as readFileSync31, statSync as statSync15 } from "node:fs";
382503
+ import { existsSync as existsSync88, readFileSync as readFileSync31, statSync as statSync15 } from "node:fs";
382638
382504
  import { join as join124, resolve as resolve73 } from "node:path";
382639
382505
  function warnOnce(set, key, message) {
382640
382506
  if (set.has(key)) {
@@ -382656,7 +382522,7 @@ function loadViewChunkManifest(clientDir) {
382656
382522
  if (cached2 && cached2.mtimeMs === mtimeMs) {
382657
382523
  return cached2.entries;
382658
382524
  }
382659
- if (!existsSync87(manifestPath)) {
382525
+ if (!existsSync88(manifestPath)) {
382660
382526
  warnOnce(warnedMissingManifest, cacheKey, `[dashboard] View chunk manifest missing: ${manifestPath}`);
382661
382527
  const empty = {};
382662
382528
  manifestCache.set(cacheKey, { entries: empty, mtimeMs });
@@ -383234,7 +383100,7 @@ var init_provider_health_monitor = __esm({
383234
383100
  import express3 from "express";
383235
383101
  import { randomUUID as randomUUID67 } from "node:crypto";
383236
383102
  import { join as join125, dirname as dirname57 } from "node:path";
383237
- import { existsSync as existsSync88, readFileSync as readFileSync32, statSync as statSync16 } from "node:fs";
383103
+ import { existsSync as existsSync89, readFileSync as readFileSync32, statSync as statSync16 } from "node:fs";
383238
383104
  import { fileURLToPath as fileURLToPath18 } from "node:url";
383239
383105
  import { createSecureServer as createHttp2SecureServer } from "node:http2";
383240
383106
  import { WebSocketServer as WebSocketServer2 } from "ws";
@@ -383556,7 +383422,7 @@ function createServer5(store, options) {
383556
383422
  getTerminalService(store.getRootDir());
383557
383423
  const isHeadless = options?.headless === true;
383558
383424
  const execDir = dirname57(process.execPath);
383559
- const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync88(join125(execDir, "client", "index.html")) ? join125(execDir, "client") : existsSync88(join125(__dirname2, "..", "dist", "client")) ? join125(__dirname2, "..", "dist", "client") : join125(__dirname2, "..", "client");
383425
+ const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync89(join125(execDir, "client", "index.html")) ? join125(execDir, "client") : existsSync89(join125(__dirname2, "..", "dist", "client")) ? join125(__dirname2, "..", "dist", "client") : join125(__dirname2, "..", "client");
383560
383426
  let cachedIndexClientDir = null;
383561
383427
  let cachedIndexHtml = null;
383562
383428
  let cachedIndexMtimeMs = null;
@@ -383611,7 +383477,7 @@ ${injection}`) : cachedIndexHtml.replace("</head>", `${injection}</head>`);
383611
383477
  }
383612
383478
  });
383613
383479
  });
383614
- if (existsSync88(join125(clientDir, "index.html"))) {
383480
+ if (existsSync89(join125(clientDir, "index.html"))) {
383615
383481
  app.get(["/", "/index.html"], serveIndexHtml);
383616
383482
  app.use(express3.static(clientDir, { index: false }));
383617
383483
  }
@@ -385670,7 +385536,7 @@ var init_src15 = __esm({
385670
385536
  import { Type as Type9 } from "typebox";
385671
385537
  import { StringEnum } from "@earendil-works/pi-ai";
385672
385538
  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";
385673
- import { existsSync as existsSync89 } from "node:fs";
385539
+ import { existsSync as existsSync90 } from "node:fs";
385674
385540
  import { AsyncLocalStorage as AsyncLocalStorage8 } from "node:async_hooks";
385675
385541
  function resolveProjectRoot2(cwd) {
385676
385542
  const worktreeProjectRoot = typeof getProjectRootFromWorktree === "function" ? getProjectRootFromWorktree(cwd) : null;
@@ -385678,12 +385544,12 @@ function resolveProjectRoot2(cwd) {
385678
385544
  warnedMissingProjectRootResolver = true;
385679
385545
  console.warn("[fusion-extension] @fusion/core.getProjectRootFromWorktree is unavailable; using filesystem fallback resolution.");
385680
385546
  }
385681
- if (worktreeProjectRoot && existsSync89(join127(worktreeProjectRoot, ".fusion"))) {
385547
+ if (worktreeProjectRoot && existsSync90(join127(worktreeProjectRoot, ".fusion"))) {
385682
385548
  return worktreeProjectRoot;
385683
385549
  }
385684
385550
  let current = resolve75(cwd);
385685
385551
  while (true) {
385686
- if (existsSync89(join127(current, ".fusion"))) {
385552
+ if (existsSync90(join127(current, ".fusion"))) {
385687
385553
  return current;
385688
385554
  }
385689
385555
  const parent2 = resolve75(current, "..");
@@ -386568,7 +386434,7 @@ var init_migration_holding_server = __esm({
386568
386434
 
386569
386435
  // src/commands/ensure-project-registered.ts
386570
386436
  import { exec as exec49 } from "node:child_process";
386571
- import { existsSync as existsSync90, mkdirSync as mkdirSync17 } from "node:fs";
386437
+ import { existsSync as existsSync91, mkdirSync as mkdirSync17 } from "node:fs";
386572
386438
  import { basename as basename37, join as join128 } from "node:path";
386573
386439
  import { promisify as promisify74 } from "node:util";
386574
386440
  function stampProjectIdentityBestEffort(cwd, project, logPrefix) {
@@ -386596,7 +386462,7 @@ async function ensureCwdProjectRegistered(options) {
386596
386462
  }
386597
386463
  try {
386598
386464
  const fusionDir = join128(cwd, ".fusion");
386599
- if (!existsSync90(fusionDir)) {
386465
+ if (!existsSync91(fusionDir)) {
386600
386466
  mkdirSync17(fusionDir, { recursive: true });
386601
386467
  }
386602
386468
  const projectName = await detectProjectName(cwd);
@@ -386626,7 +386492,7 @@ async function ensureCwdProjectRegistered(options) {
386626
386492
  }
386627
386493
  }
386628
386494
  async function detectProjectName(dir2) {
386629
- if (!existsSync90(join128(dir2, ".git"))) {
386495
+ if (!existsSync91(join128(dir2, ".git"))) {
386630
386496
  return basename37(dir2) || "my-project";
386631
386497
  }
386632
386498
  try {
@@ -386658,7 +386524,7 @@ var init_ensure_project_registered = __esm({
386658
386524
  });
386659
386525
 
386660
386526
  // src/commands/provider-settings.ts
386661
- import { existsSync as existsSync91, readFileSync as readFileSync33, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18 } from "node:fs";
386527
+ import { existsSync as existsSync92, readFileSync as readFileSync33, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18 } from "node:fs";
386662
386528
  import { join as join129, dirname as dirname59, basename as basename38 } from "node:path";
386663
386529
  function siblingAgentDir2(agentDir, siblingRoot) {
386664
386530
  if (basename38(agentDir) !== "agent") {
@@ -386667,7 +386533,7 @@ function siblingAgentDir2(agentDir, siblingRoot) {
386667
386533
  return join129(dirname59(dirname59(agentDir)), siblingRoot, "agent");
386668
386534
  }
386669
386535
  function readJsonObject4(path14) {
386670
- if (!existsSync91(path14)) {
386536
+ if (!existsSync92(path14)) {
386671
386537
  return {};
386672
386538
  }
386673
386539
  try {
@@ -386712,7 +386578,7 @@ var init_provider_auth2 = __esm({
386712
386578
 
386713
386579
  // src/commands/auth-paths.ts
386714
386580
  import { homedir as homedir20 } from "node:os";
386715
- import { existsSync as existsSync92, readFileSync as readFileSync34 } from "node:fs";
386581
+ import { existsSync as existsSync93, readFileSync as readFileSync34 } from "node:fs";
386716
386582
  import { join as join130 } from "node:path";
386717
386583
  function getFusionAgentDir2(home = process.env.HOME || process.env.USERPROFILE || homedir20()) {
386718
386584
  return join130(home, ".fusion", "agent");
@@ -386731,13 +386597,13 @@ function getLegacyModelsPaths2(home = process.env.HOME || process.env.USERPROFIL
386731
386597
  }
386732
386598
  function getModelRegistryModelsPath2(home = process.env.HOME || process.env.USERPROFILE || homedir20()) {
386733
386599
  const fusionModelsPath = getFusionModelsPath2(home);
386734
- if (existsSync92(fusionModelsPath)) {
386600
+ if (existsSync93(fusionModelsPath)) {
386735
386601
  return fusionModelsPath;
386736
386602
  }
386737
- return getLegacyModelsPaths2(home).find((modelsPath) => existsSync92(modelsPath)) ?? fusionModelsPath;
386603
+ return getLegacyModelsPaths2(home).find((modelsPath) => existsSync93(modelsPath)) ?? fusionModelsPath;
386738
386604
  }
386739
386605
  function readJsonObject5(path14) {
386740
- if (!existsSync92(path14)) {
386606
+ if (!existsSync93(path14)) {
386741
386607
  return {};
386742
386608
  }
386743
386609
  try {
@@ -386755,13 +386621,13 @@ function getPackageManagerAgentDir2(home = process.env.HOME || process.env.USERP
386755
386621
  const legacyAgentDir = getLegacyAgentDir(home);
386756
386622
  const fusionSettings = readJsonObject5(join130(fusionAgentDir, "settings.json"));
386757
386623
  const legacySettings = readJsonObject5(join130(legacyAgentDir, "settings.json"));
386758
- if (hasPackageManagerSettings3(fusionSettings) || !existsSync92(legacyAgentDir)) {
386624
+ if (hasPackageManagerSettings3(fusionSettings) || !existsSync93(legacyAgentDir)) {
386759
386625
  return fusionAgentDir;
386760
386626
  }
386761
386627
  if (hasPackageManagerSettings3(legacySettings)) {
386762
386628
  return legacyAgentDir;
386763
386629
  }
386764
- return existsSync92(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
386630
+ return existsSync93(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
386765
386631
  }
386766
386632
  var init_auth_paths2 = __esm({
386767
386633
  "src/commands/auth-paths.ts"() {
@@ -387008,7 +386874,7 @@ var init_project_context = __esm({
387008
386874
  // src/commands/claude-skills.ts
387009
386875
  import {
387010
386876
  cpSync as cpSync6,
387011
- existsSync as existsSync93,
386877
+ existsSync as existsSync94,
387012
386878
  lstatSync as lstatSync6,
387013
386879
  mkdirSync as mkdirSync19,
387014
386880
  readlinkSync as readlinkSync4,
@@ -387037,7 +386903,7 @@ function isPiClaudeCliConfigured(globalSettings) {
387037
386903
  function resolveFusionSkillSource() {
387038
386904
  const here = fileURLToPath19(import.meta.url);
387039
386905
  const candidate = resolve77(dirname61(here), "..", "..", "skill", FUSION_SKILL_NAME4);
387040
- return existsSync93(candidate) ? candidate : null;
386906
+ return existsSync94(candidate) ? candidate : null;
387041
386907
  }
387042
386908
  function installFusionSkillIntoProject(projectPath, options = {}) {
387043
386909
  const target = join131(projectPath, ".claude", "skills", FUSION_SKILL_NAME4);
@@ -387055,7 +386921,7 @@ function installFusionSkillIntoProject(projectPath, options = {}) {
387055
386921
  try {
387056
386922
  mkdirSync19(dirname61(target), { recursive: true });
387057
386923
  let replaced = false;
387058
- if (existsSync93(target) || isBrokenSymlink2(target)) {
386924
+ if (existsSync94(target) || isBrokenSymlink2(target)) {
387059
386925
  const stat20 = lstatSync6(target);
387060
386926
  if (stat20.isSymbolicLink()) {
387061
386927
  const current = safeReadlink2(target);
@@ -387066,7 +386932,7 @@ function installFusionSkillIntoProject(projectPath, options = {}) {
387066
386932
  replaced = true;
387067
386933
  } else {
387068
386934
  const skillMd = join131(target, "SKILL.md");
387069
- if (!existsSync93(skillMd)) {
386935
+ if (!existsSync94(skillMd)) {
387070
386936
  return {
387071
386937
  outcome: "failed",
387072
386938
  target,
@@ -387125,7 +386991,7 @@ function isBrokenSymlink2(path14) {
387125
386991
  try {
387126
386992
  const stat20 = lstatSync6(path14);
387127
386993
  if (!stat20.isSymbolicLink()) return false;
387128
- return !existsSync93(path14);
386994
+ return !existsSync94(path14);
387129
386995
  } catch {
387130
386996
  return false;
387131
386997
  }
@@ -387222,7 +387088,7 @@ var init_claude_skills_runner = __esm({
387222
387088
  });
387223
387089
 
387224
387090
  // src/commands/claude-cli-extension.ts
387225
- import { existsSync as existsSync94, readFileSync as readFileSync35 } from "node:fs";
387091
+ import { existsSync as existsSync95, readFileSync as readFileSync35 } from "node:fs";
387226
387092
  import { createRequire as createRequire10 } from "node:module";
387227
387093
  import { dirname as dirname62, resolve as resolve78 } from "node:path";
387228
387094
  import { fileURLToPath as fileURLToPath20 } from "node:url";
@@ -387231,7 +387097,7 @@ function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
387231
387097
  const here = dirname62(fileURLToPath20(moduleUrl));
387232
387098
  for (const rel of ["pi-claude-cli", "../pi-claude-cli", "../../pi-claude-cli"]) {
387233
387099
  const candidate = resolve78(here, rel, "package.json");
387234
- if (existsSync94(candidate)) {
387100
+ if (existsSync95(candidate)) {
387235
387101
  pkgJsonPath = candidate;
387236
387102
  break;
387237
387103
  }
@@ -387267,7 +387133,7 @@ function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
387267
387133
  };
387268
387134
  }
387269
387135
  const entryPath = resolve78(dirname62(pkgJsonPath), rawEntry);
387270
- if (!existsSync94(entryPath)) {
387136
+ if (!existsSync95(entryPath)) {
387271
387137
  return {
387272
387138
  status: "missing-entry",
387273
387139
  reason: `@fusion/pi-claude-cli extension file not found at ${entryPath}`
@@ -387318,7 +387184,7 @@ var init_claude_cli_extension = __esm({
387318
387184
  });
387319
387185
 
387320
387186
  // src/commands/droid-cli-extension.ts
387321
- import { existsSync as existsSync95, readFileSync as readFileSync36 } from "node:fs";
387187
+ import { existsSync as existsSync96, readFileSync as readFileSync36 } from "node:fs";
387322
387188
  import { createRequire as createRequire11 } from "node:module";
387323
387189
  import { dirname as dirname63, resolve as resolve79 } from "node:path";
387324
387190
  import { fileURLToPath as fileURLToPath21 } from "node:url";
@@ -387327,7 +387193,7 @@ function resolveDroidCliExtensionFromModuleUrl(moduleUrl) {
387327
387193
  const here = dirname63(fileURLToPath21(moduleUrl));
387328
387194
  for (const rel of ["droid-cli", "../droid-cli", "../../droid-cli"]) {
387329
387195
  const candidate = resolve79(here, rel, "package.json");
387330
- if (existsSync95(candidate)) {
387196
+ if (existsSync96(candidate)) {
387331
387197
  pkgJsonPath = candidate;
387332
387198
  break;
387333
387199
  }
@@ -387363,7 +387229,7 @@ function resolveDroidCliExtensionFromModuleUrl(moduleUrl) {
387363
387229
  };
387364
387230
  }
387365
387231
  const entryPath = resolve79(dirname63(pkgJsonPath), rawEntry);
387366
- if (!existsSync95(entryPath)) {
387232
+ if (!existsSync96(entryPath)) {
387367
387233
  return {
387368
387234
  status: "missing-entry",
387369
387235
  reason: `@fusion/droid-cli extension file not found at ${entryPath}`
@@ -387414,7 +387280,7 @@ var init_droid_cli_extension = __esm({
387414
387280
  });
387415
387281
 
387416
387282
  // src/commands/llama-cpp-extension.ts
387417
- import { existsSync as existsSync96, readFileSync as readFileSync37 } from "node:fs";
387283
+ import { existsSync as existsSync97, readFileSync as readFileSync37 } from "node:fs";
387418
387284
  import { createRequire as createRequire12 } from "node:module";
387419
387285
  import { dirname as dirname64, resolve as resolve80 } from "node:path";
387420
387286
  import { fileURLToPath as fileURLToPath22 } from "node:url";
@@ -387423,7 +387289,7 @@ function resolveLlamaCppExtensionFromModuleUrl(moduleUrl) {
387423
387289
  const here = dirname64(fileURLToPath22(moduleUrl));
387424
387290
  for (const rel of ["pi-llama-cpp", "../pi-llama-cpp", "../../pi-llama-cpp", "../../../pi-llama-cpp"]) {
387425
387291
  const candidate = resolve80(here, rel, "package.json");
387426
- if (existsSync96(candidate)) {
387292
+ if (existsSync97(candidate)) {
387427
387293
  pkgJsonPath = candidate;
387428
387294
  break;
387429
387295
  }
@@ -387459,7 +387325,7 @@ function resolveLlamaCppExtensionFromModuleUrl(moduleUrl) {
387459
387325
  };
387460
387326
  }
387461
387327
  const entryPath = resolve80(dirname64(pkgJsonPath), rawEntry);
387462
- if (!existsSync96(entryPath)) {
387328
+ if (!existsSync97(entryPath)) {
387463
387329
  return {
387464
387330
  status: "missing-entry",
387465
387331
  reason: `@fusion/pi-llama-cpp extension file not found at ${entryPath}`
@@ -387558,7 +387424,7 @@ var init_update_cache = __esm({
387558
387424
  });
387559
387425
 
387560
387426
  // src/commands/self-extension.ts
387561
- import { existsSync as existsSync97, readFileSync as readFileSync39 } from "node:fs";
387427
+ import { existsSync as existsSync98, readFileSync as readFileSync39 } from "node:fs";
387562
387428
  import { dirname as dirname65, resolve as resolve81 } from "node:path";
387563
387429
  import { fileURLToPath as fileURLToPath23 } from "node:url";
387564
387430
  function resolveSelfExtension() {
@@ -387566,7 +387432,7 @@ function resolveSelfExtension() {
387566
387432
  let pkgDir;
387567
387433
  let cur = here;
387568
387434
  for (let i = 0; i < 5; i++) {
387569
- if (existsSync97(resolve81(cur, "package.json"))) {
387435
+ if (existsSync98(resolve81(cur, "package.json"))) {
387570
387436
  try {
387571
387437
  const parsed = JSON.parse(readFileSync39(resolve81(cur, "package.json"), "utf-8"));
387572
387438
  if (parsed.name === "@runfusion/fusion") {
@@ -387590,7 +387456,7 @@ function resolveSelfExtension() {
387590
387456
  return { status: "missing", reason: `Failed to read @runfusion/fusion package.json: ${err instanceof Error ? err.message : String(err)}` };
387591
387457
  }
387592
387458
  const srcEntry = resolve81(pkgDir, "src", "extension.ts");
387593
- if (existsSync97(srcEntry)) {
387459
+ if (existsSync98(srcEntry)) {
387594
387460
  return { status: "ok", path: srcEntry, packageVersion: pkgJson.version ?? "unknown" };
387595
387461
  }
387596
387462
  const extensions = pkgJson.pi?.extensions;
@@ -387602,7 +387468,7 @@ function resolveSelfExtension() {
387602
387468
  return { status: "missing", reason: "@runfusion/fusion pi.extensions[0] is not a valid path string" };
387603
387469
  }
387604
387470
  const entryPath = resolve81(pkgDir, rawEntry);
387605
- if (!existsSync97(entryPath)) {
387471
+ if (!existsSync98(entryPath)) {
387606
387472
  return { status: "missing", reason: `@runfusion/fusion extension file not found at ${entryPath}` };
387607
387473
  }
387608
387474
  return { status: "ok", path: entryPath, packageVersion: pkgJson.version ?? "unknown" };
@@ -396064,7 +395930,7 @@ import { join as join134, resolve as pathResolve2 } from "node:path";
396064
395930
  import { execFile as execFileCb, spawn as spawn31 } from "node:child_process";
396065
395931
  import { promisify as promisify75 } from "node:util";
396066
395932
  import { stat as stat18, readdir as readdir16, readFile as fsReadFile4 } from "node:fs/promises";
396067
- import { existsSync as existsSync98, readFileSync as readFileSync40 } from "node:fs";
395933
+ import { existsSync as existsSync99, readFileSync as readFileSync40 } from "node:fs";
396068
395934
  import { fileURLToPath as fileURLToPath25 } from "node:url";
396069
395935
  import { DefaultPackageManager as DefaultPackageManager2, discoverAndLoadExtensions as discoverAndLoadExtensions2, createExtensionRuntime as createExtensionRuntime2 } from "@earendil-works/pi-coding-agent";
396070
395936
  async function countActiveTasks(store, tasks2) {
@@ -398366,7 +398232,7 @@ function resolveFusionSourceWorkspaceRoot() {
398366
398232
  try {
398367
398233
  let dir2 = pathResolve2(fileURLToPath25(import.meta.url), "..");
398368
398234
  for (let i = 0; i < 10; i++) {
398369
- if (existsSync98(join134(dir2, "pnpm-workspace.yaml"))) {
398235
+ if (existsSync99(join134(dir2, "pnpm-workspace.yaml"))) {
398370
398236
  try {
398371
398237
  const pkg = JSON.parse(readFileSync40(join134(dir2, "package.json"), "utf8"));
398372
398238
  return pkg?.name === "fusion-workspace" ? dir2 : void 0;
@@ -400768,7 +400634,7 @@ __export(desktop_exports, {
400768
400634
  });
400769
400635
  import { spawn as spawn32 } from "node:child_process";
400770
400636
  import { once as once2 } from "node:events";
400771
- import { existsSync as existsSync99 } from "node:fs";
400637
+ import { existsSync as existsSync100 } from "node:fs";
400772
400638
  import { dirname as dirname67, isAbsolute as isAbsolute34, join as join137, resolve as resolve83 } from "node:path";
400773
400639
  import { createRequire as createRequire13 } from "node:module";
400774
400640
  import { fileURLToPath as fileURLToPath26 } from "node:url";
@@ -400877,7 +400743,7 @@ function terminateProcess(child, signal = "SIGTERM") {
400877
400743
  }
400878
400744
  function resolveDevDesktopEntry(rootDir) {
400879
400745
  const desktopEntry = join137(rootDir, "packages", "desktop", "dist", "main.js");
400880
- if (existsSync99(desktopEntry)) {
400746
+ if (existsSync100(desktopEntry)) {
400881
400747
  return desktopEntry;
400882
400748
  }
400883
400749
  throw new Error(
@@ -400888,17 +400754,17 @@ function resolvePackagedDesktopEntry() {
400888
400754
  const override = process.env.FUSION_DESKTOP_ENTRY;
400889
400755
  if (override) {
400890
400756
  const resolvedOverride = isAbsolute34(override) ? override : resolve83(process.cwd(), override);
400891
- if (existsSync99(resolvedOverride)) {
400757
+ if (existsSync100(resolvedOverride)) {
400892
400758
  return resolvedOverride;
400893
400759
  }
400894
400760
  throw new Error(`Fusion desktop runtime override is missing: ${resolvedOverride}`);
400895
400761
  }
400896
400762
  const packagedEntry = resolve83(cliModuleDir, "desktop", "main.js");
400897
- if (existsSync99(packagedEntry)) {
400763
+ if (existsSync100(packagedEntry)) {
400898
400764
  return packagedEntry;
400899
400765
  }
400900
400766
  const sourceCheckoutEntry = resolve83(cliModuleDir, "..", "..", "dist", "desktop", "main.js");
400901
- if (existsSync99(sourceCheckoutEntry)) {
400767
+ if (existsSync100(sourceCheckoutEntry)) {
400902
400768
  return sourceCheckoutEntry;
400903
400769
  }
400904
400770
  throw new Error(
@@ -401530,7 +401396,7 @@ __export(task_exports, {
401530
401396
  runTaskUpdate: () => runTaskUpdate
401531
401397
  });
401532
401398
  import { createInterface as createInterface3 } from "node:readline/promises";
401533
- import { watchFile, unwatchFile, statSync as statSync17, existsSync as existsSync100, readFileSync as readFileSync41 } from "node:fs";
401399
+ import { watchFile, unwatchFile, statSync as statSync17, existsSync as existsSync101, readFileSync as readFileSync41 } from "node:fs";
401534
401400
  import { basename as basename40, join as join138 } from "node:path";
401535
401401
  function columnLabel2(column) {
401536
401402
  return COLUMN_LABELS[column] ?? column;
@@ -402104,7 +401970,7 @@ async function runTaskLogs(id, options = {}, projectName) {
402104
401970
  if (options.follow) {
402105
401971
  const projectPath = context.projectPath ?? process.cwd();
402106
401972
  const logPath = join138(projectPath, ".fusion", "tasks", id, "agent.log");
402107
- if (!existsSync100(logPath)) {
401973
+ if (!existsSync101(logPath)) {
402108
401974
  console.log(`
402109
401975
  Waiting for log file to be created...`);
402110
401976
  }
@@ -403788,7 +403654,7 @@ var settings_import_exports = {};
403788
403654
  __export(settings_import_exports, {
403789
403655
  runSettingsImport: () => runSettingsImport
403790
403656
  });
403791
- import { existsSync as existsSync101 } from "node:fs";
403657
+ import { existsSync as existsSync102 } from "node:fs";
403792
403658
  import { resolve as resolve85 } from "node:path";
403793
403659
  async function runSettingsImport(filePath, options = {}) {
403794
403660
  const scope = options.scope ?? "both";
@@ -403807,7 +403673,7 @@ async function runSettingsImport(filePath, options = {}) {
403807
403673
  };
403808
403674
  try {
403809
403675
  const resolvedPath = resolve85(filePath);
403810
- if (!existsSync101(resolvedPath)) {
403676
+ if (!existsSync102(resolvedPath)) {
403811
403677
  console.error(`Error: File not found: ${filePath}`);
403812
403678
  await exitWithStore(1);
403813
403679
  return;
@@ -403915,7 +403781,7 @@ __export(mcp_exports, {
403915
403781
  runMcpRemove: () => runMcpRemove,
403916
403782
  runMcpValidate: () => runMcpValidate
403917
403783
  });
403918
- import { existsSync as existsSync102 } from "node:fs";
403784
+ import { existsSync as existsSync103 } from "node:fs";
403919
403785
  import { readFile as readFile60, writeFile as writeFile41 } from "node:fs/promises";
403920
403786
  import { resolve as resolve86 } from "node:path";
403921
403787
  async function createGlobalSettingsStore() {
@@ -404253,7 +404119,7 @@ async function runMcpImport(filePath, opts = {}) {
404253
404119
  const scope = normalizeScope(opts.scope);
404254
404120
  context = await loadContext(opts.projectName, scope === "project");
404255
404121
  const resolvedPath = resolve86(filePath);
404256
- if (!existsSync102(resolvedPath)) throw new Error(`File not found: ${filePath}`);
404122
+ if (!existsSync103(resolvedPath)) throw new Error(`File not found: ${filePath}`);
404257
404123
  const imported = importMcpServersJson(await readFile60(resolvedPath, "utf-8"), { scope });
404258
404124
  if (imported.errors.length > 0) throw new Error(`Invalid MCP import file:
404259
404125
  ${imported.errors.map((error3) => ` - ${error3}`).join("\n")}`);
@@ -404370,7 +404236,7 @@ var init_mcp = __esm({
404370
404236
  });
404371
404237
 
404372
404238
  // src/project-resolver.ts
404373
- import { existsSync as existsSync103, statSync as statSync18 } from "node:fs";
404239
+ import { existsSync as existsSync104, statSync as statSync18 } from "node:fs";
404374
404240
  import { basename as basename41, dirname as dirname68, join as join140, normalize as normalize9, resolve as resolve87 } from "node:path";
404375
404241
  import { createInterface as createInterface4 } from "node:readline/promises";
404376
404242
  async function getCentralCore() {
@@ -404453,7 +404319,7 @@ async function resolveProject2(options = {}) {
404453
404319
  { searchedName: options.project, availableProjects: projects2.map((p2) => p2.name) }
404454
404320
  );
404455
404321
  }
404456
- if (!existsSync103(match.path)) {
404322
+ if (!existsSync104(match.path)) {
404457
404323
  throw new ProjectResolutionError(
404458
404324
  `Project "${match.name}" is registered but the directory no longer exists: ${match.path}
404459
404325
 
@@ -404471,7 +404337,7 @@ Run \`fn project remove ` + match.name + "` to clean up the registry entry.",
404471
404337
  const normalizedKbDir = normalize9(fusionDir);
404472
404338
  const match = allProjects2.find((p2) => normalize9(p2.path) === normalizedKbDir);
404473
404339
  if (match) {
404474
- if (!existsSync103(match.path)) {
404340
+ if (!existsSync104(match.path)) {
404475
404341
  throw new ProjectResolutionError(
404476
404342
  `Project "${match.name}" is registered but the directory no longer exists: ${match.path}
404477
404343
 
@@ -404597,7 +404463,7 @@ Run \`fn project add ` + fusionDir + "` to register it, or use --project <name>.
404597
404463
  }
404598
404464
  if (allProjects.length === 1) {
404599
404465
  const project = allProjects[0];
404600
- if (!existsSync103(project.path)) {
404466
+ if (!existsSync104(project.path)) {
404601
404467
  throw new ProjectResolutionError(
404602
404468
  `The only registered project "${project.name}" has a missing directory: ${project.path}
404603
404469
 
@@ -405587,7 +405453,7 @@ __export(db_exports, {
405587
405453
  runDbMigrate: () => runDbMigrate,
405588
405454
  runDbVacuum: () => runDbVacuum
405589
405455
  });
405590
- import { existsSync as existsSync104 } from "node:fs";
405456
+ import { existsSync as existsSync105 } from "node:fs";
405591
405457
  import { copyFile as copyFile3, mkdir as mkdir41 } from "node:fs/promises";
405592
405458
  import { join as join141 } from "node:path";
405593
405459
  function formatBytes9(bytes) {
@@ -405668,7 +405534,7 @@ async function runDbMigrate(projectName, opts = {}) {
405668
405534
  const fusionDir = join141(projectRoot, ".fusion");
405669
405535
  const globalDir = resolveGlobalDir();
405670
405536
  const sources = defaultMigrationSources(fusionDir, globalDir);
405671
- const presentSources = sources.filter((s3) => existsSync104(s3.sqlitePath));
405537
+ const presentSources = sources.filter((s3) => existsSync105(s3.sqlitePath));
405672
405538
  if (presentSources.length === 0) {
405673
405539
  console.error(
405674
405540
  `fn db migrate: no legacy SQLite files found under ${fusionDir} (or ${globalDir}). Nothing to migrate.`
@@ -405795,7 +405661,7 @@ async function createPreMigrationBackup(fusionDir, globalDir, sources) {
405795
405661
  const backupDir = join141(globalDir, "migration-backups", `pre-migrate-${ts2}`);
405796
405662
  await mkdir41(backupDir, { recursive: true });
405797
405663
  for (const s3 of sources) {
405798
- if (existsSync104(s3.sqlitePath)) {
405664
+ if (existsSync105(s3.sqlitePath)) {
405799
405665
  const dest = join141(backupDir, s3.sqlitePath.split("/").pop() ?? "source.db");
405800
405666
  await copyFile3(s3.sqlitePath, dest);
405801
405667
  }
@@ -406691,7 +406557,7 @@ __export(project_exports2, {
406691
406557
  runProjectShow: () => runProjectShow
406692
406558
  });
406693
406559
  import { resolve as resolve89, isAbsolute as isAbsolute35, relative as relative26, basename as basename42, join as join142 } from "node:path";
406694
- import { existsSync as existsSync105, statSync as statSync19 } from "node:fs";
406560
+ import { existsSync as existsSync106, statSync as statSync19 } from "node:fs";
406695
406561
  import { createInterface as createInterface8 } from "node:readline/promises";
406696
406562
  function formatDisplayPath(projectPath) {
406697
406563
  const rel = relative26(process.cwd(), projectPath);
@@ -406845,7 +406711,7 @@ async function runProjectAdd(name2, path14, options = {}) {
406845
406711
  projectPath = pathInput.trim() || defaultPath;
406846
406712
  }
406847
406713
  const absolutePath2 = isAbsolute35(projectPath) ? projectPath : resolve89(process.cwd(), projectPath);
406848
- if (!existsSync105(absolutePath2)) {
406714
+ if (!existsSync106(absolutePath2)) {
406849
406715
  console.error(`
406850
406716
  \u2717 Path does not exist: ${projectPath}`);
406851
406717
  rl.close();
@@ -406895,7 +406761,7 @@ async function runProjectAdd(name2, path14, options = {}) {
406895
406761
  process.exit(1);
406896
406762
  }
406897
406763
  const absolutePath = isAbsolute35(projectPath) ? projectPath : resolve89(process.cwd(), projectPath);
406898
- if (!existsSync105(absolutePath)) {
406764
+ if (!existsSync106(absolutePath)) {
406899
406765
  console.error(`
406900
406766
  \u2717 Path does not exist: ${projectPath}
406901
406767
  `);
@@ -407180,7 +407046,7 @@ var init_project2 = __esm({
407180
407046
  });
407181
407047
 
407182
407048
  // src/commands/skill-installation.ts
407183
- import { cpSync as cpSync7, existsSync as existsSync106, mkdirSync as mkdirSync20 } from "node:fs";
407049
+ import { cpSync as cpSync7, existsSync as existsSync107, mkdirSync as mkdirSync20 } from "node:fs";
407184
407050
  import { homedir as homedir21 } from "node:os";
407185
407051
  import { dirname as dirname69, join as join143, resolve as resolve90 } from "node:path";
407186
407052
  import { fileURLToPath as fileURLToPath27 } from "node:url";
@@ -407194,7 +407060,7 @@ function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.e
407194
407060
  function resolveBundledFusionSkillSource4() {
407195
407061
  const here = fileURLToPath27(import.meta.url);
407196
407062
  const source = resolve90(dirname69(here), "..", "..", "skill", FUSION_SKILL_NAME5);
407197
- return existsSync106(source) ? source : null;
407063
+ return existsSync107(source) ? source : null;
407198
407064
  }
407199
407065
  function installBundledFusionSkill(options = {}) {
407200
407066
  const sourceDir = options.sourceDir ?? resolveBundledFusionSkillSource4();
@@ -407212,7 +407078,7 @@ function installBundledFusionSkill(options = {}) {
407212
407078
  }
407213
407079
  const results = targets.map((target) => {
407214
407080
  try {
407215
- if (existsSync106(target.targetDir)) {
407081
+ if (existsSync107(target.targetDir)) {
407216
407082
  return {
407217
407083
  client: target.client,
407218
407084
  targetDir: target.targetDir,
@@ -407251,7 +407117,7 @@ var init_exports = {};
407251
407117
  __export(init_exports, {
407252
407118
  runInit: () => runInit
407253
407119
  });
407254
- import { existsSync as existsSync107, mkdirSync as mkdirSync21, writeFileSync as writeFileSync20, readFileSync as readFileSync42 } from "node:fs";
407120
+ import { existsSync as existsSync108, mkdirSync as mkdirSync21, writeFileSync as writeFileSync20, readFileSync as readFileSync42 } from "node:fs";
407255
407121
  import { join as join144, resolve as resolve91, basename as basename43 } from "node:path";
407256
407122
  import { exec as exec51 } from "node:child_process";
407257
407123
  import { promisify as promisify77 } from "node:util";
@@ -407259,10 +407125,10 @@ async function runInit(options = {}) {
407259
407125
  const cwd = options.path ? resolve91(options.path) : process.cwd();
407260
407126
  const fusionDir = join144(cwd, ".fusion");
407261
407127
  const dbPath = join144(fusionDir, "fusion.db");
407262
- const hasDbPath = existsSync107(dbPath);
407128
+ const hasDbPath = existsSync108(dbPath);
407263
407129
  const hasValidDb = hasDbPath && isValidSqliteDatabaseFile(dbPath);
407264
407130
  const hasIdentity = hasProjectIdentity(fusionDir);
407265
- if (existsSync107(fusionDir) && (hasIdentity || hasValidDb)) {
407131
+ if (existsSync108(fusionDir) && (hasIdentity || hasValidDb)) {
407266
407132
  const central2 = new CentralCore();
407267
407133
  await central2.init();
407268
407134
  const existing = await central2.getProjectByPath(cwd);
@@ -407291,7 +407157,7 @@ async function runInit(options = {}) {
407291
407157
  await central2.close();
407292
407158
  return;
407293
407159
  }
407294
- if (existsSync107(fusionDir) && !hasIdentity && hasDbPath && !hasValidDb) {
407160
+ if (existsSync108(fusionDir) && !hasIdentity && hasDbPath && !hasValidDb) {
407295
407161
  throw new Error(
407296
407162
  `Existing database at ${dbPath} is not a valid SQLite database. Restore it from .fusion/backups or move it aside before re-running fn init.`
407297
407163
  );
@@ -407299,7 +407165,7 @@ async function runInit(options = {}) {
407299
407165
  const projectName = options.name ?? await detectProjectName2(cwd);
407300
407166
  console.log(`Initializing fn project: "${projectName}"`);
407301
407167
  console.log(` Path: ${cwd}`);
407302
- if (!existsSync107(fusionDir)) {
407168
+ if (!existsSync108(fusionDir)) {
407303
407169
  mkdirSync21(fusionDir, { recursive: true });
407304
407170
  console.log(` \u2713 Created .fusion/ directory`);
407305
407171
  }
@@ -407380,7 +407246,7 @@ async function runInit(options = {}) {
407380
407246
  }
407381
407247
  }
407382
407248
  async function detectProjectName2(dir2) {
407383
- if (!existsSync107(join144(dir2, ".git"))) {
407249
+ if (!existsSync108(join144(dir2, ".git"))) {
407384
407250
  return basename43(dir2) || "my-project";
407385
407251
  }
407386
407252
  try {
@@ -407402,7 +407268,7 @@ async function detectProjectName2(dir2) {
407402
407268
  async function addLocalStorageToGitignore(cwd) {
407403
407269
  const gitignorePath = join144(cwd, ".gitignore");
407404
407270
  let content = "";
407405
- if (existsSync107(gitignorePath)) {
407271
+ if (existsSync108(gitignorePath)) {
407406
407272
  try {
407407
407273
  content = readFileSync42(gitignorePath, "utf-8");
407408
407274
  } catch {
@@ -407444,7 +407310,7 @@ async function initializeGitRepo(cwd) {
407444
407310
  await ensureGitConfig(cwd, "user.name", "Fusion");
407445
407311
  await ensureGitConfig(cwd, "user.email", "noreply@runfusion.ai");
407446
407312
  const gitkeepPath = join144(cwd, ".gitkeep");
407447
- if (!existsSync107(gitkeepPath)) {
407313
+ if (!existsSync108(gitkeepPath)) {
407448
407314
  writeFileSync20(gitkeepPath, "\n");
407449
407315
  }
407450
407316
  await execAsync48("git add .gitkeep", { cwd, timeout: 1e4 });
@@ -407510,7 +407376,7 @@ __export(onboard_exports, {
407510
407376
  persistLocalProviderRegistry: () => persistLocalProviderRegistry,
407511
407377
  runOnboard: () => runOnboard
407512
407378
  });
407513
- import { existsSync as existsSync108, mkdirSync as mkdirSync22, readFileSync as readFileSync43, renameSync as renameSync6, unlinkSync as unlinkSync8, writeFileSync as writeFileSync21 } from "node:fs";
407379
+ import { existsSync as existsSync109, mkdirSync as mkdirSync22, readFileSync as readFileSync43, renameSync as renameSync6, unlinkSync as unlinkSync8, writeFileSync as writeFileSync21 } from "node:fs";
407514
407380
  import { dirname as dirname70 } from "node:path";
407515
407381
  import { createInterface as createInterface9 } from "node:readline";
407516
407382
  function createPromptSession(input = process.stdin) {
@@ -407639,7 +407505,7 @@ function composeLocalProviderRegistry(existing, config3) {
407639
407505
  return { ...existing, providers };
407640
407506
  }
407641
407507
  function registryHasProvider(path14, providerId) {
407642
- if (!existsSync108(path14)) return false;
407508
+ if (!existsSync109(path14)) return false;
407643
407509
  try {
407644
407510
  const registry3 = JSON.parse(readFileSync43(path14, "utf8"));
407645
407511
  return isObject2(registry3) && isObject2(registry3.providers) && isObject2(registry3.providers[providerId]);
@@ -407649,7 +407515,7 @@ function registryHasProvider(path14, providerId) {
407649
407515
  }
407650
407516
  function persistLocalProviderRegistry(path14, config3) {
407651
407517
  let existing = {};
407652
- if (existsSync108(path14)) {
407518
+ if (existsSync109(path14)) {
407653
407519
  try {
407654
407520
  existing = JSON.parse(readFileSync43(path14, "utf8"));
407655
407521
  } catch {
@@ -407664,7 +407530,7 @@ function persistLocalProviderRegistry(path14, config3) {
407664
407530
  `, { mode: 384 });
407665
407531
  renameSync6(tempPath, path14);
407666
407532
  } finally {
407667
- if (existsSync108(tempPath)) unlinkSync8(tempPath);
407533
+ if (existsSync109(tempPath)) unlinkSync8(tempPath);
407668
407534
  }
407669
407535
  }
407670
407536
  function validateMaxConcurrent(input) {
@@ -407699,7 +407565,7 @@ async function runOnboard(options = {}) {
407699
407565
  const prompts = createPromptSession(options.input);
407700
407566
  try {
407701
407567
  const centralDbPath = getDefaultCentralDbPath();
407702
- if (existsSync108(centralDbPath)) {
407568
+ if (existsSync109(centralDbPath)) {
407703
407569
  console.log(`\u2713 Central DB already exists: ${centralDbPath}`);
407704
407570
  } else {
407705
407571
  const ranCentralDb = await runSkippableStep(prompts, "Central DB", async () => {
@@ -407996,7 +407862,7 @@ var agent_import_exports = {};
407996
407862
  __export(agent_import_exports, {
407997
407863
  runAgentImport: () => runAgentImport
407998
407864
  });
407999
- import { existsSync as existsSync109, mkdirSync as mkdirSync23, readFileSync as readFileSync44, statSync as statSync20, writeFileSync as writeFileSync22 } from "node:fs";
407865
+ import { existsSync as existsSync110, mkdirSync as mkdirSync23, readFileSync as readFileSync44, statSync as statSync20, writeFileSync as writeFileSync22 } from "node:fs";
408000
407866
  import { resolve as resolve92 } from "node:path";
408001
407867
  function slugifyPathSegment(input) {
408002
407868
  if (!input || typeof input !== "string") {
@@ -408055,7 +407921,7 @@ async function importSkillsToProject(projectPath, skills, companySlug, dryRun) {
408055
407921
  const skillSlug = slugifyPathSegment(skill.name);
408056
407922
  const skillDir = resolve92(baseSkillsDir, skillSlug);
408057
407923
  const skillPath = resolve92(skillDir, "SKILL.md");
408058
- if (existsSync109(skillPath)) {
407924
+ if (existsSync110(skillPath)) {
408059
407925
  result2.skipped.push(skill.name);
408060
407926
  continue;
408061
407927
  }
@@ -408116,7 +407982,7 @@ async function runAgentImport(source, options) {
408116
407982
  const dryRun = options?.dryRun ?? false;
408117
407983
  const skipExisting = options?.skipExisting ?? false;
408118
407984
  const sourcePath = resolve92(source);
408119
- if (!existsSync109(sourcePath)) {
407985
+ if (!existsSync110(sourcePath)) {
408120
407986
  console.error(`Path not found: ${sourcePath}`);
408121
407987
  process.exit(1);
408122
407988
  }
@@ -408990,7 +408856,7 @@ __export(plugin_exports2, {
408990
408856
  runPluginSetupStatus: () => runPluginSetupStatus,
408991
408857
  runPluginUninstall: () => runPluginUninstall
408992
408858
  });
408993
- import { existsSync as existsSync110 } from "node:fs";
408859
+ import { existsSync as existsSync111 } from "node:fs";
408994
408860
  import { dirname as dirname71, extname as extname6, join as join145, resolve as resolve96 } from "node:path";
408995
408861
  import { readFile as readFile63, stat as stat19 } from "node:fs/promises";
408996
408862
  import * as readline from "node:readline";
@@ -409085,7 +408951,7 @@ async function resolvePluginEntryFile(pluginDir) {
409085
408951
  }
409086
408952
  const packageJsonPath = join145(absoluteInputPath, "package.json");
409087
408953
  let selectedCandidate;
409088
- if (existsSync110(packageJsonPath)) {
408954
+ if (existsSync111(packageJsonPath)) {
409089
408955
  const packageJson = JSON.parse(await readFile63(packageJsonPath, "utf-8"));
409090
408956
  const exportsRecord = asRecord6(packageJson.exports);
409091
408957
  const dotExport = exportsRecord?.["."];
@@ -409134,7 +409000,7 @@ async function loadManifestFromPath(pluginPath) {
409134
409000
  const inputStats = await statPath(absoluteInputPath);
409135
409001
  const manifestDir = inputStats?.isFile() ? dirname71(absoluteInputPath) : absoluteInputPath;
409136
409002
  const manifestPath = join145(manifestDir, "manifest.json");
409137
- if (!existsSync110(manifestPath)) {
409003
+ if (!existsSync111(manifestPath)) {
409138
409004
  throw new Error(`Plugin manifest not found at: ${manifestPath}`);
409139
409005
  }
409140
409006
  const content = await readFile63(manifestPath, "utf-8");
@@ -409192,7 +409058,7 @@ async function runPluginInstall(source, options) {
409192
409058
  console.error("Please provide a local path to the plugin directory.");
409193
409059
  process.exit(1);
409194
409060
  }
409195
- if (!existsSync110(source)) {
409061
+ if (!existsSync111(source)) {
409196
409062
  console.error(`Plugin path does not exist: ${source}`);
409197
409063
  process.exit(1);
409198
409064
  }
@@ -409515,7 +409381,7 @@ __export(plugin_scaffold_exports, {
409515
409381
  runPluginCreate: () => runPluginCreate,
409516
409382
  runPluginNew: () => runPluginNew
409517
409383
  });
409518
- import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23, existsSync as existsSync111, readFileSync as readFileSync45 } from "node:fs";
409384
+ import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23, existsSync as existsSync112, readFileSync as readFileSync45 } from "node:fs";
409519
409385
  import { join as join146, dirname as dirname72, resolve as resolve97 } from "node:path";
409520
409386
  import { fileURLToPath as fileURLToPath28 } from "node:url";
409521
409387
  function toTitleCase(str) {
@@ -409536,7 +409402,7 @@ function resolveTargetPath(name2, output) {
409536
409402
  };
409537
409403
  }
409538
409404
  function ensureTargetPathAvailable(targetDir, targetPath) {
409539
- if (existsSync111(targetPath)) {
409405
+ if (existsSync112(targetPath)) {
409540
409406
  console.error(`Error: Directory '${targetDir}' already exists.`);
409541
409407
  console.error("Please choose a different name or remove the existing directory.");
409542
409408
  process.exit(1);
@@ -409551,7 +409417,7 @@ function readOwnCliVersion() {
409551
409417
  }
409552
409418
  for (let i = 0; i < 8; i += 1) {
409553
409419
  const pkgPath = resolve97(currentDir, "package.json");
409554
- if (existsSync111(pkgPath)) {
409420
+ if (existsSync112(pkgPath)) {
409555
409421
  try {
409556
409422
  const parsed = JSON.parse(readFileSync45(pkgPath, "utf-8"));
409557
409423
  if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string") {
@@ -409913,7 +409779,7 @@ var plugin_dev_exports = {};
409913
409779
  __export(plugin_dev_exports, {
409914
409780
  runPluginDev: () => runPluginDev
409915
409781
  });
409916
- import { existsSync as existsSync112, watch as watch2 } from "node:fs";
409782
+ import { existsSync as existsSync113, watch as watch2 } from "node:fs";
409917
409783
  import { join as join147, resolve as resolve98 } from "node:path";
409918
409784
  async function runSupervisedCommand(command, cwd, timeoutMs = 12e4) {
409919
409785
  await new Promise((resolvePromise, rejectPromise) => {
@@ -409959,7 +409825,7 @@ async function defaultBuildFn(pluginDir) {
409959
409825
  await runSupervisedCommand("npm run build", pluginDir);
409960
409826
  }
409961
409827
  function defaultWatchFn(pluginDir, onChange) {
409962
- const watchPath = existsSync112(join147(pluginDir, "src")) ? join147(pluginDir, "src") : pluginDir;
409828
+ const watchPath = existsSync113(join147(pluginDir, "src")) ? join147(pluginDir, "src") : pluginDir;
409963
409829
  try {
409964
409830
  const watcher = watch2(watchPath, { recursive: true }, onChange);
409965
409831
  return { close: () => watcher.close() };
@@ -409975,7 +409841,7 @@ function shouldUseWatcher(options) {
409975
409841
  return Boolean(process.stdout.isTTY && process.stdin.isTTY);
409976
409842
  }
409977
409843
  async function runPluginDev(source, options) {
409978
- if (!existsSync112(source)) {
409844
+ if (!existsSync113(source)) {
409979
409845
  console.error(`Plugin path does not exist: ${source}`);
409980
409846
  process.exit(1);
409981
409847
  }
@@ -410095,7 +409961,7 @@ __export(plugin_publish_exports, {
410095
409961
  collectPluginPreflight: () => collectPluginPreflight,
410096
409962
  runPluginPublish: () => runPluginPublish
410097
409963
  });
410098
- import { existsSync as existsSync113 } from "node:fs";
409964
+ import { existsSync as existsSync114 } from "node:fs";
410099
409965
  import { readFile as readFile64 } from "node:fs/promises";
410100
409966
  import { join as join148, resolve as resolve99 } from "node:path";
410101
409967
  import { pathToFileURL as pathToFileURL2 } from "node:url";
@@ -410256,7 +410122,7 @@ function statusIcon(status) {
410256
410122
  return "\u2717";
410257
410123
  }
410258
410124
  async function runPluginPublish(source, options) {
410259
- if (!existsSync113(source)) {
410125
+ if (!existsSync114(source)) {
410260
410126
  console.error(`Plugin path does not exist: ${source}`);
410261
410127
  process.exit(1);
410262
410128
  }
@@ -410825,7 +410691,7 @@ __export(update_exports, {
410825
410691
  runUpdate: () => runUpdate
410826
410692
  });
410827
410693
  import { exec as exec52 } from "node:child_process";
410828
- import { existsSync as existsSync114, readFileSync as readFileSync46 } from "node:fs";
410694
+ import { existsSync as existsSync115, readFileSync as readFileSync46 } from "node:fs";
410829
410695
  import { promisify as promisify78 } from "node:util";
410830
410696
  import { dirname as dirname73, resolve as resolve102 } from "node:path";
410831
410697
  import { fileURLToPath as fileURLToPath29 } from "node:url";
@@ -410888,7 +410754,7 @@ function readOwnCliVersion2() {
410888
410754
  }
410889
410755
  for (let i = 0; i < 8; i += 1) {
410890
410756
  const pkgPath = resolve102(currentDir, "package.json");
410891
- if (existsSync114(pkgPath)) {
410757
+ if (existsSync115(pkgPath)) {
410892
410758
  try {
410893
410759
  const parsed = JSON.parse(readFileSync46(pkgPath, "utf-8"));
410894
410760
  if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string") {
@@ -411169,7 +411035,7 @@ __export(onboard_autolaunch_exports, {
411169
411035
  maybeAutoLaunchOnboarding: () => maybeAutoLaunchOnboarding,
411170
411036
  shouldAutoLaunchOnboarding: () => shouldAutoLaunchOnboarding
411171
411037
  });
411172
- import { existsSync as existsSync115 } from "node:fs";
411038
+ import { existsSync as existsSync116 } from "node:fs";
411173
411039
  import { join as join150 } from "node:path";
411174
411040
  function shouldAutoLaunchOnboarding(input) {
411175
411041
  const env = input.env ?? process.env;
@@ -411234,7 +411100,7 @@ async function maybeAutoLaunchOnboarding(deps) {
411234
411100
  let centralDbExists = true;
411235
411101
  let projectInitialized = false;
411236
411102
  try {
411237
- const pathExists4 = deps.pathExists ?? existsSync115;
411103
+ const pathExists4 = deps.pathExists ?? existsSync116;
411238
411104
  const centralDbPath = deps.centralDbPath ?? getDefaultCentralDbPath();
411239
411105
  const cwd = deps.cwd ?? process.cwd();
411240
411106
  const projectMarkerPath = join150(cwd, ".fusion", "project.json");
@@ -411295,7 +411161,7 @@ __export(native_patch_exports, {
411295
411161
  setupNativeResolution: () => setupNativeResolution
411296
411162
  });
411297
411163
  import { join as join151, basename as basename44, dirname as dirname74 } from "node:path";
411298
- import { existsSync as existsSync116, copyFileSync as copyFileSync2, mkdirSync as mkdirSync25, symlinkSync as symlinkSync7, rmSync as rmSync16, lstatSync as lstatSync7, readlinkSync as readlinkSync5 } from "node:fs";
411164
+ import { existsSync as existsSync117, copyFileSync as copyFileSync2, mkdirSync as mkdirSync25, symlinkSync as symlinkSync7, rmSync as rmSync16, lstatSync as lstatSync7, readlinkSync as readlinkSync5 } from "node:fs";
411299
411165
  import { tmpdir as tmpdir22 } from "node:os";
411300
411166
  function findStagedNativeDir2() {
411301
411167
  const platform6 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
@@ -411303,12 +411169,12 @@ function findStagedNativeDir2() {
411303
411169
  const prebuildName = `${platform6}-${arch}`;
411304
411170
  const execDir = dirname74(process.execPath);
411305
411171
  const nextToBinary = join151(execDir, "runtime", prebuildName);
411306
- if (existsSync116(join151(nextToBinary, "pty.node"))) {
411172
+ if (existsSync117(join151(nextToBinary, "pty.node"))) {
411307
411173
  return nextToBinary;
411308
411174
  }
411309
411175
  if (process.env.FUSION_RUNTIME_DIR) {
411310
411176
  const envPath = join151(process.env.FUSION_RUNTIME_DIR, prebuildName);
411311
- if (existsSync116(join151(envPath, "pty.node"))) {
411177
+ if (existsSync117(join151(envPath, "pty.node"))) {
411312
411178
  return envPath;
411313
411179
  }
411314
411180
  }
@@ -411318,11 +411184,11 @@ function cleanupStaleBunfsLinks() {
411318
411184
  if (process.platform === "win32") return;
411319
411185
  const bunfsRoot = "/$bunfs/root";
411320
411186
  try {
411321
- if (existsSync116(bunfsRoot)) {
411187
+ if (existsSync117(bunfsRoot)) {
411322
411188
  const stats = lstatSync7(bunfsRoot);
411323
411189
  if (stats.isSymbolicLink()) {
411324
411190
  const target = readlinkSync5(bunfsRoot);
411325
- if (target.includes("fn-bunfs-") && !existsSync116(target)) {
411191
+ if (target.includes("fn-bunfs-") && !existsSync117(target)) {
411326
411192
  rmSync16(bunfsRoot);
411327
411193
  console.log("[fn-native-patch] Cleaned up stale /$bunfs/root symlink");
411328
411194
  }
@@ -411350,14 +411216,14 @@ function setupNativeResolution() {
411350
411216
  mkdirSync25(platformDir, { recursive: true });
411351
411217
  const ptyNodeDest = join151(platformDir, "pty.node");
411352
411218
  copyFileSync2(join151(nativeDir, "pty.node"), ptyNodeDest);
411353
- if (existsSync116(join151(nativeDir, "spawn-helper"))) {
411219
+ if (existsSync117(join151(nativeDir, "spawn-helper"))) {
411354
411220
  copyFileSync2(join151(nativeDir, "spawn-helper"), join151(platformDir, "spawn-helper"));
411355
411221
  }
411356
411222
  process.env.FUSION_FAKE_BUNFS_ROOT = tmpRoot;
411357
411223
  if (process.platform !== "win32") {
411358
411224
  const bunfsRoot = "/$bunfs/root";
411359
411225
  try {
411360
- if (existsSync116(bunfsRoot)) {
411226
+ if (existsSync117(bunfsRoot)) {
411361
411227
  const stats = lstatSync7(bunfsRoot);
411362
411228
  if (stats.isSymbolicLink()) {
411363
411229
  rmSync16(bunfsRoot);
@@ -411380,7 +411246,7 @@ function setupNativeResolution() {
411380
411246
  function cleanupNativeResolution() {
411381
411247
  if (bunfsSymlinkPath && process.platform !== "win32") {
411382
411248
  try {
411383
- if (existsSync116(bunfsSymlinkPath)) {
411249
+ if (existsSync117(bunfsSymlinkPath)) {
411384
411250
  const stats = lstatSync7(bunfsSymlinkPath);
411385
411251
  if (stats.isSymbolicLink()) {
411386
411252
  rmSync16(bunfsSymlinkPath);
@@ -411427,7 +411293,7 @@ var init_native_patch = __esm({
411427
411293
 
411428
411294
  // src/bin.ts
411429
411295
  init_output();
411430
- import { existsSync as existsSync117, mkdtempSync as mkdtempSync5, readFileSync as readFileSync47, symlinkSync as symlinkSync8, writeFileSync as writeFileSync24 } from "node:fs";
411296
+ import { existsSync as existsSync118, mkdtempSync as mkdtempSync5, readFileSync as readFileSync47, symlinkSync as symlinkSync8, writeFileSync as writeFileSync24 } from "node:fs";
411431
411297
  import { createRequire as createRequire14 } from "node:module";
411432
411298
  import { join as join152, dirname as dirname75, resolve as resolve103 } from "node:path";
411433
411299
  import { tmpdir as tmpdir23 } from "node:os";
@@ -411452,7 +411318,7 @@ function configurePiPackage() {
411452
411318
  packageJson = JSON.parse(readFileSync47(piPackagePath, "utf-8"));
411453
411319
  for (const entry of ["dist", "docs", "examples", "README.md", "CHANGELOG.md"]) {
411454
411320
  const source = join152(piPackageDir, entry);
411455
- if (existsSync117(source)) {
411321
+ if (existsSync118(source)) {
411456
411322
  symlinkSync8(source, join152(tmp, entry));
411457
411323
  }
411458
411324
  }
@@ -411472,7 +411338,7 @@ setInterval(() => {
411472
411338
  performance4.clearResourceTimings();
411473
411339
  }, 1e3).unref();
411474
411340
  function loadEnvFile(path14) {
411475
- if (!existsSync117(path14)) return;
411341
+ if (!existsSync118(path14)) return;
411476
411342
  const contents = readFileSync47(path14, "utf-8");
411477
411343
  for (const rawLine of contents.split(/\r?\n/)) {
411478
411344
  const line2 = rawLine.trim();
@@ -411995,7 +411861,7 @@ function readOwnCliVersion3() {
411995
411861
  }
411996
411862
  for (let i = 0; i < 8; i += 1) {
411997
411863
  const pkgPath = resolve103(currentDir, "package.json");
411998
- if (existsSync117(pkgPath)) {
411864
+ if (existsSync118(pkgPath)) {
411999
411865
  try {
412000
411866
  const parsed = JSON.parse(readFileSync47(pkgPath, "utf-8"));
412001
411867
  if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string") {