@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.
- package/dist/bin.js +339 -473
- package/dist/child-process-worker.js +144 -278
- package/dist/client/.vite/manifest.json +254 -254
- package/dist/client/assets/{AgentDetailView-CTdyQL11.js → AgentDetailView-CnzGIxqj.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-DBa7nIQV.js → AgentPermissionPolicyEditor-DMnyR96M.js} +1 -1
- package/dist/client/assets/{AgentsView-B5tss2oK.js → AgentsView-CzFtICwM.js} +3 -3
- package/dist/client/assets/{ChatView-DAKt1a2L.js → ChatView-Cs6B3fNf.js} +1 -1
- package/dist/client/assets/{CommandCenter-yPvRo9F6.js → CommandCenter-DADvho3z.js} +1 -1
- package/dist/client/assets/{DevServerView-BTyS2owH.js → DevServerView-Bzrzfs8Z.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-BjGIupNU.js → DirectoryPicker-rmip5GcI.js} +1 -1
- package/dist/client/assets/{DocumentsView-CuxfbpSZ.js → DocumentsView-BEM4nmJT.js} +1 -1
- package/dist/client/assets/{EvalsView-DGuy8SHR.js → EvalsView-Du7NaYMJ.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-lK407ZAq.js → ExperimentalAgentOnboardingModal-BpIMiZOi.js} +1 -1
- package/dist/client/assets/{GoalsView-DAVN0ObR.js → GoalsView-BxKRyXM3.js} +1 -1
- package/dist/client/assets/{InsightsView-BXQKcNof.js → InsightsView-Dauq6b3M.js} +1 -1
- package/dist/client/assets/{MemoryView-D7RKEtV7.js → MemoryView-DRD9Xvwx.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-CrOJ57R2.js → PiExtensionsManager-DJKE1iAX.js} +1 -1
- package/dist/client/assets/{PluginManager-D7_evt4j.js → PluginManager-CScwY-Ib.js} +1 -1
- package/dist/client/assets/{PullRequestView-C0lRUbth.js → PullRequestView-uAu5_4__.js} +1 -1
- package/dist/client/assets/{ReportModal-Cy5fRNDK.js → ReportModal-nNUcGxYj.js} +1 -1
- package/dist/client/assets/{ResearchView-e8st2Sxu.js → ResearchView-BX1kGbWP.js} +1 -1
- package/dist/client/assets/{SecretsView-BLzckrzb.js → SecretsView-U_itETHx.js} +1 -1
- package/dist/client/assets/{SessionTerminal-F_GIj4gh.js → SessionTerminal-_b15vcd9.js} +1 -1
- package/dist/client/assets/SettingsModal-B30rPfYC.css +1 -0
- package/dist/client/assets/{SettingsModal-XAddgWkF.js → SettingsModal-DkpUKf4k.js} +1 -1
- package/dist/client/assets/{SettingsModal-eQbxbkLU.js → SettingsModal-DpbYR3Co.js} +4 -4
- package/dist/client/assets/{SettingsTextareaRow-DVjUHNQp.js → SettingsTextareaRow-Dbv-oqsF.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-xID9yIff.js → SetupWizardModal-n_kcJfIP.js} +2 -2
- package/dist/client/assets/{SkillsView-BNdMGu6E.js → SkillsView-Bv2uqBre.js} +1 -1
- package/dist/client/assets/{TodoView-xcOjHZm1.js → TodoView-y11oUvjw.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-DZ2WZ-ve.js → WorkflowNodeEditor-DwY4XzNB.js} +1 -1
- package/dist/client/assets/{agent-import-generation-0tkW9WMt.js → agent-import-generation-B_UNOAWY.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DP9_UvPn.js → architectureDiagram-3BPJPVTR-BpA9_eoq.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-EgKwYMgQ.js → blockDiagram-GPEHLZMM-DFFA8tCG.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-Dzv0-_xt.js → c4Diagram-AAUBKEIU-Fzhn0dG7.js} +1 -1
- package/dist/client/assets/channel-C9C9Rxgn.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CNmFmJlQ.js → chunk-2J33WTMH-Bi3oPWBJ.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-DwtF2sl5.js → chunk-4BX2VUAB-UmeI_To2.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-DoDurT6F.js → chunk-55IACEB6-BvNWeThd.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DB87A9uH.js → chunk-727SXJPM-OHmjSQwz.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-ClTDkMp1.js → chunk-AQP2D5EJ-DCi9eQaE.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-BhY2wlYr.js → chunk-FMBD7UC4-CelGyE3R.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-BB8mzlmk.js → chunk-ND2GUHAM-DespM-6E.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-D81qQMGf.js → chunk-QZHKN3VN-DLkr_Pz0.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BGVE_u03.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BGVE_u03.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-CCFUHBJX.js → cose-bilkent-S5V4N54A-I7MlbwDq.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-xr9MLhRA.js → dagre-BM42HDAG-DRwLRj5m.js} +1 -1
- package/dist/client/assets/{dashboard-view-oTFt91I3.js → dashboard-view-CIwO3ODB.js} +1 -1
- package/dist/client/assets/{dashboard-view-RXKFv3QV.js → dashboard-view-CSxVzmpI.js} +1 -1
- package/dist/client/assets/{dashboard-view-lqwQ-pMo.js → dashboard-view-Gb436HIO.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-mN_tYnBs.js → diagram-2AECGRRQ-BuWGDbh_.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-xznlq-5C.js → diagram-5GNKFQAL-hG6N6ArX.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-ClRlj1ZA.js → diagram-KO2AKTUF-BSXKqQJA.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CNiPIQqT.js → diagram-LMA3HP47-wNefeM2W.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-DwQD-W0P.js → diagram-OG6HWLK6-nA8v_k_H.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-ZXkiCm8S.js → erDiagram-TEJ5UH35-Dwnvvp2x.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-DI5haEH9.js → flowDiagram-I6XJVG4X-FS4W3U0O.js} +1 -1
- package/dist/client/assets/{folder-open-NenyCkrb.js → folder-open-C3GXrzUo.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-BRHJpfOZ.js → ganttDiagram-6RSMTGT7-D95bgKFE.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-iXT_YBAZ.js → gitGraphDiagram-PVQCEYII-zqFbK6on.js} +1 -1
- package/dist/client/assets/{index-CrAJA2v0.js → index-BWRNl9tu.js} +274 -274
- package/dist/client/assets/index-DRZtPb3i.css +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BzkuQtqZ.js → infoDiagram-5YYISTIA-BBELQBNE.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-5hnPG_98.js → ishikawaDiagram-YF4QCWOH-bSZkIXd-.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-Co3fnxbr.js → journeyDiagram-JHISSGLW-8wIimXRT.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-PZFl_y-h.js → kanban-definition-UN3LZRKU-DMj6kFc5.js} +1 -1
- package/dist/client/assets/{mermaid.core-CJRKeU9s.js → mermaid.core-UDKENpfo.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-B15e2rkx.js → mindmap-definition-RKZ34NQL-CJGH0VYQ.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-kGF592D_.js → pieDiagram-4H26LBE5-B3cZLcOe.js} +1 -1
- package/dist/client/assets/{puzzle-Dgc4yzjO.js → puzzle-D85LM19g.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CUShcj70.js → quadrantDiagram-W4KKPZXB-bR1CBrVi.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-D2k4nLqQ.js → requirementDiagram-4Y6WPE33-DnyJ74cE.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CA03BxhT.js → sankeyDiagram-5OEKKPKP-ttv4kq0z.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-DDuFN2Pi.js → sequenceDiagram-3UESZ5HK-FiUBFoWw.js} +1 -1
- package/dist/client/assets/{shield-alert-BlYWqolM.js → shield-alert-D3IVOJV1.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-ujl7UARV.js → standing-instructions-template-CWY_pFh6.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-yJOkHK4Q.js → stateDiagram-AJRCARHV-BcsYRB77.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-BgErHdAN.js → stateDiagram-v2-BHNVJYJU-DsBPFwnG.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-BUiDQw21.js → timeline-definition-PNZ67QCA-B8rOOxEj.js} +1 -1
- package/dist/client/assets/{upload-DmlZvpMp.js → upload-WqSaqC__.js} +1 -1
- package/dist/client/assets/{users-Cx6ACt-W.js → users-CPP-3wxQ.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DqyIjBY8.js → vennDiagram-CIIHVFJN-CO0LSFj2.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-C93tXAKH.js → wardley-L42UT6IY-QHbclXGi.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DmH6-GJV.js → wardleyDiagram-YWT4CUSO-DAsnTuM9.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-BPwjE4Su.js → xychartDiagram-2RQKCTM6-BmG5EEoO.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +216 -350
- package/package.json +1 -1
- package/dist/client/assets/SettingsModal-KnUd0942.css +0 -1
- package/dist/client/assets/channel-BdTAZBkX.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CuoGzmwo.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CuoGzmwo.js +0 -1
- package/dist/client/assets/index-CITV-wDq.css +0 -1
|
@@ -159300,7 +159300,11 @@ async function createFnAgent2(options) {
|
|
|
159300
159300
|
}
|
|
159301
159301
|
});
|
|
159302
159302
|
attachSessionIdentity(promptableSession);
|
|
159303
|
-
return {
|
|
159303
|
+
return {
|
|
159304
|
+
session: promptableSession,
|
|
159305
|
+
sessionFile: promptableSession.sessionFile,
|
|
159306
|
+
settleFallbackDispatch: async () => void 0
|
|
159307
|
+
};
|
|
159304
159308
|
}
|
|
159305
159309
|
var execAsync10, 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;
|
|
159306
159310
|
var init_pi = __esm({
|
|
@@ -159424,7 +159428,8 @@ function wrapPluginRuntime(instance, runtimeId, runtimeName) {
|
|
|
159424
159428
|
const result = await adapter.createSession(options);
|
|
159425
159429
|
return {
|
|
159426
159430
|
session: result.session ?? result,
|
|
159427
|
-
sessionFile: result.sessionFile
|
|
159431
|
+
sessionFile: result.sessionFile,
|
|
159432
|
+
settleFallbackDispatch: result.settleFallbackDispatch
|
|
159428
159433
|
};
|
|
159429
159434
|
}
|
|
159430
159435
|
throw new Error(`Plugin runtime "${runtimeId}" does not implement createSession`);
|
|
@@ -159533,11 +159538,15 @@ var init_runtime_resolution = __esm({
|
|
|
159533
159538
|
name = "Default PI Runtime";
|
|
159534
159539
|
async createSession(options) {
|
|
159535
159540
|
const { toolOutputMaxChars, mcpServers, ...agentOptions } = options;
|
|
159536
|
-
|
|
159541
|
+
const result = await createFnAgent2({
|
|
159537
159542
|
...agentOptions,
|
|
159538
159543
|
toolOutputMaxChars,
|
|
159539
159544
|
mcpServers: normalizeAgentRuntimeMcpServers(mcpServers)
|
|
159540
159545
|
});
|
|
159546
|
+
return {
|
|
159547
|
+
...result,
|
|
159548
|
+
settleFallbackDispatch: result.settleFallbackDispatch ?? (async () => void 0)
|
|
159549
|
+
};
|
|
159541
159550
|
}
|
|
159542
159551
|
async promptWithFallback(session, prompt, options) {
|
|
159543
159552
|
return promptWithFallback(session, prompt, options);
|
|
@@ -160404,6 +160413,7 @@ async function createResolvedAgentSession(options) {
|
|
|
160404
160413
|
return {
|
|
160405
160414
|
session: result.session,
|
|
160406
160415
|
sessionFile: result.sessionFile,
|
|
160416
|
+
settleFallbackDispatch: result.settleFallbackDispatch,
|
|
160407
160417
|
runtimeId: resolved.runtimeId,
|
|
160408
160418
|
wasConfigured: resolved.wasConfigured
|
|
160409
160419
|
};
|
|
@@ -190840,6 +190850,25 @@ var Scheduler = class {
|
|
|
190840
190850
|
});
|
|
190841
190851
|
}
|
|
190842
190852
|
}
|
|
190853
|
+
if (from === parked.wip && to2 === parked.hold) {
|
|
190854
|
+
if (source === "engine") {
|
|
190855
|
+
this.recentEngineTodoRequeues.set(task.id, task.columnMovedAt ?? (/* @__PURE__ */ new Date()).toISOString());
|
|
190856
|
+
} else {
|
|
190857
|
+
this.recentEngineTodoRequeues.delete(task.id);
|
|
190858
|
+
}
|
|
190859
|
+
} else if (to2 === parked.review || parked.terminal.has(to2)) {
|
|
190860
|
+
this.recentEngineTodoRequeues.delete(task.id);
|
|
190861
|
+
if (task.dispatchStormCount != null || task.lastDispatchAt != null || task.executeRequeueLoopCount != null || task.executeRequeueLoopSignature != null) {
|
|
190862
|
+
void this.store.updateTask(task.id, {
|
|
190863
|
+
dispatchStormCount: null,
|
|
190864
|
+
lastDispatchAt: null,
|
|
190865
|
+
executeRequeueLoopCount: null,
|
|
190866
|
+
executeRequeueLoopSignature: null
|
|
190867
|
+
}).catch((error2) => {
|
|
190868
|
+
schedulerLog.warn(`Failed to reset dispatch oscillation state for ${task.id} on move to ${to2}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
190869
|
+
});
|
|
190870
|
+
}
|
|
190871
|
+
}
|
|
190843
190872
|
const resolvedParked = mergeParkedColumns(await resolveTaskParkedColumns(this.store, task.id), lanes);
|
|
190844
190873
|
if (resolvedParked.terminal.has(to2)) {
|
|
190845
190874
|
try {
|
|
@@ -190900,25 +190929,6 @@ var Scheduler = class {
|
|
|
190900
190929
|
schedulerLog.error(`Failed event-driven blocker reconciliation for ${task.id}`, error2);
|
|
190901
190930
|
}
|
|
190902
190931
|
}
|
|
190903
|
-
if (from === resolvedParked.wip && to2 === resolvedParked.hold) {
|
|
190904
|
-
if (source === "engine") {
|
|
190905
|
-
this.recentEngineTodoRequeues.set(task.id, task.columnMovedAt ?? (/* @__PURE__ */ new Date()).toISOString());
|
|
190906
|
-
} else {
|
|
190907
|
-
this.recentEngineTodoRequeues.delete(task.id);
|
|
190908
|
-
}
|
|
190909
|
-
} else if (to2 === resolvedParked.review || resolvedParked.terminal.has(to2)) {
|
|
190910
|
-
this.recentEngineTodoRequeues.delete(task.id);
|
|
190911
|
-
if (task.dispatchStormCount != null || task.lastDispatchAt != null || task.executeRequeueLoopCount != null || task.executeRequeueLoopSignature != null) {
|
|
190912
|
-
void this.store.updateTask(task.id, {
|
|
190913
|
-
dispatchStormCount: null,
|
|
190914
|
-
lastDispatchAt: null,
|
|
190915
|
-
executeRequeueLoopCount: null,
|
|
190916
|
-
executeRequeueLoopSignature: null
|
|
190917
|
-
}).catch((error2) => {
|
|
190918
|
-
schedulerLog.warn(`Failed to reset dispatch oscillation state for ${task.id} on move to ${to2}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
190919
|
-
});
|
|
190920
|
-
}
|
|
190921
|
-
}
|
|
190922
190932
|
if (resolvedParked.terminal.has(to2) || to2 === resolvedParked.hold) {
|
|
190923
190933
|
schedulerLog.log(`Task moved to ${to2} \u2014 triggering scheduling`);
|
|
190924
190934
|
this.schedule();
|
|
@@ -192692,110 +192702,40 @@ init_src2();
|
|
|
192692
192702
|
|
|
192693
192703
|
// ../engine/src/execution-block-classifier.ts
|
|
192694
192704
|
var TASK_ID_RE = /^[A-Z][A-Z0-9]*-\d+$/i;
|
|
192695
|
-
var
|
|
192696
|
-
var PR_IN_TEXT_RE = /\bPR\s*#?\s*(\d+)\b/gi;
|
|
192697
|
-
var 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;
|
|
192705
|
+
var LEGACY_PR_REF_RE = /^(?:pr[:#-]|#|PR-)(\d+)$/i;
|
|
192698
192706
|
function partitionBlockedByRefs(blockedBy) {
|
|
192699
192707
|
const taskIds = [];
|
|
192700
|
-
const prNumbers = [];
|
|
192701
192708
|
for (const raw of blockedBy) {
|
|
192702
192709
|
const id = raw.trim();
|
|
192703
192710
|
if (!id) continue;
|
|
192704
|
-
|
|
192705
|
-
if (prMatch) {
|
|
192706
|
-
prNumbers.push(Number(prMatch[1]));
|
|
192707
|
-
continue;
|
|
192708
|
-
}
|
|
192711
|
+
if (LEGACY_PR_REF_RE.test(id)) continue;
|
|
192709
192712
|
if (TASK_ID_RE.test(id)) {
|
|
192710
192713
|
const m2 = id.toUpperCase().match(/^([A-Z][A-Z0-9]*)-(\d+)$/);
|
|
192711
192714
|
taskIds.push(m2 ? `${m2[1]}-${m2[2]}` : id.toUpperCase());
|
|
192712
|
-
continue;
|
|
192713
192715
|
}
|
|
192714
192716
|
}
|
|
192715
|
-
return {
|
|
192716
|
-
taskIds: [...new Set(taskIds)],
|
|
192717
|
-
prNumbers: [...new Set(prNumbers.filter((n) => Number.isFinite(n) && n > 0))]
|
|
192718
|
-
};
|
|
192717
|
+
return { taskIds: [...new Set(taskIds)] };
|
|
192719
192718
|
}
|
|
192720
|
-
function
|
|
192721
|
-
const
|
|
192722
|
-
|
|
192723
|
-
const n = Number(match[1]);
|
|
192724
|
-
if (Number.isFinite(n) && n > 0) found.push(n);
|
|
192725
|
-
}
|
|
192726
|
-
return [...new Set(found)];
|
|
192727
|
-
}
|
|
192728
|
-
function isFileClaimBlockedReason(reason) {
|
|
192729
|
-
return CLAIM_REASON_RE.test(reason);
|
|
192730
|
-
}
|
|
192731
|
-
function classifyBlockedExit(reason, blockedBy = []) {
|
|
192732
|
-
const trimmed = reason.trim();
|
|
192733
|
-
const partitioned = partitionBlockedByRefs(blockedBy);
|
|
192734
|
-
const prFromText = extractPrNumbersFromText(trimmed);
|
|
192735
|
-
const prNumbers = [.../* @__PURE__ */ new Set([...partitioned.prNumbers, ...prFromText])];
|
|
192736
|
-
const isClaim = isFileClaimBlockedReason(trimmed) || prNumbers.length > 0 && /claim/i.test(trimmed);
|
|
192737
|
-
if (isClaim || prNumbers.length > 0 && isFileClaimBlockedReason(trimmed)) {
|
|
192738
|
-
const externalBlockers = [
|
|
192739
|
-
...prNumbers.map((number4) => ({ kind: "github-pr", number: number4 }))
|
|
192740
|
-
];
|
|
192741
|
-
if (externalBlockers.length === 0 && isClaim) {
|
|
192742
|
-
externalBlockers.push({
|
|
192743
|
-
kind: "file-claim",
|
|
192744
|
-
prNumber: prNumbers[0]
|
|
192745
|
-
});
|
|
192746
|
-
} else if (isClaim) {
|
|
192747
|
-
for (const n of prNumbers) {
|
|
192748
|
-
if (!externalBlockers.some((b3) => b3.kind === "github-pr" && b3.number === n)) {
|
|
192749
|
-
externalBlockers.push({ kind: "github-pr", number: n });
|
|
192750
|
-
}
|
|
192751
|
-
}
|
|
192752
|
-
if (prNumbers.length === 0) {
|
|
192753
|
-
externalBlockers.push({ kind: "file-claim" });
|
|
192754
|
-
}
|
|
192755
|
-
}
|
|
192756
|
-
const thrashSignature = [
|
|
192757
|
-
"file-claim",
|
|
192758
|
-
...prNumbers.map((n) => `pr:${n}`).sort(),
|
|
192759
|
-
...partitioned.taskIds.slice().sort()
|
|
192760
|
-
].join("|");
|
|
192761
|
-
return {
|
|
192762
|
-
allowAutoReplan: false,
|
|
192763
|
-
class: "file-claim",
|
|
192764
|
-
externalBlockers,
|
|
192765
|
-
thrashSignature: thrashSignature || "file-claim",
|
|
192766
|
-
prNumbers
|
|
192767
|
-
};
|
|
192768
|
-
}
|
|
192769
|
-
if (partitioned.taskIds.length > 0) {
|
|
192719
|
+
function classifyBlockedExit(_reason, blockedBy = []) {
|
|
192720
|
+
const { taskIds } = partitionBlockedByRefs(blockedBy);
|
|
192721
|
+
if (taskIds.length > 0) {
|
|
192770
192722
|
return {
|
|
192771
192723
|
allowAutoReplan: false,
|
|
192772
192724
|
class: "external",
|
|
192773
|
-
|
|
192774
|
-
thrashSignature: `tasks:${partitioned.taskIds.slice().sort().join(",")}`,
|
|
192775
|
-
prNumbers
|
|
192776
|
-
};
|
|
192777
|
-
}
|
|
192778
|
-
if (prNumbers.length > 0) {
|
|
192779
|
-
return {
|
|
192780
|
-
allowAutoReplan: false,
|
|
192781
|
-
class: "external",
|
|
192782
|
-
externalBlockers: prNumbers.map((number4) => ({ kind: "github-pr", number: number4 })),
|
|
192783
|
-
thrashSignature: prNumbers.map((n) => `pr:${n}`).sort().join("|"),
|
|
192784
|
-
prNumbers
|
|
192725
|
+
thrashSignature: `tasks:${taskIds.slice().sort().join(",")}`
|
|
192785
192726
|
};
|
|
192786
192727
|
}
|
|
192787
192728
|
return {
|
|
192788
192729
|
allowAutoReplan: true,
|
|
192789
192730
|
class: "plan-defect",
|
|
192790
|
-
|
|
192791
|
-
thrashSignature: "plan-defect",
|
|
192792
|
-
prNumbers: []
|
|
192731
|
+
thrashSignature: "plan-defect"
|
|
192793
192732
|
};
|
|
192794
192733
|
}
|
|
192795
192734
|
var BLOCKED_THRASH_LIMIT = 3;
|
|
192796
192735
|
var BLOCKED_THRASH_WINDOW_MS = 60 * 60 * 1e3;
|
|
192797
192736
|
function countBlockedThrashHits(log41, signature, nowMs = Date.now(), windowMs = BLOCKED_THRASH_WINDOW_MS) {
|
|
192798
192737
|
if (!log41?.length) return 0;
|
|
192738
|
+
if (signature === "plan-defect") return 0;
|
|
192799
192739
|
const cutoff = nowMs - windowMs;
|
|
192800
192740
|
let count2 = 0;
|
|
192801
192741
|
for (const entry of log41) {
|
|
@@ -192807,18 +192747,7 @@ function countBlockedThrashHits(log41, signature, nowMs = Date.now(), windowMs =
|
|
|
192807
192747
|
continue;
|
|
192808
192748
|
}
|
|
192809
192749
|
}
|
|
192810
|
-
if (signature === "plan-defect") continue;
|
|
192811
|
-
if (signature.includes("file-claim") || signature.startsWith("pr:") || signature.includes("|pr:")) {
|
|
192812
|
-
if (isFileClaimBlockedReason(action) || /PR\s*#?\s*\d+/i.test(action) || action.includes("durable external block")) {
|
|
192813
|
-
count2 += 1;
|
|
192814
|
-
continue;
|
|
192815
|
-
}
|
|
192816
|
-
}
|
|
192817
192750
|
for (const part of signature.split("|")) {
|
|
192818
|
-
if (part.startsWith("pr:") && action.includes(`PR #${part.slice(3)}`)) {
|
|
192819
|
-
count2 += 1;
|
|
192820
|
-
break;
|
|
192821
|
-
}
|
|
192822
192751
|
if (part.startsWith("tasks:") && part.slice(6).split(",").some((id) => id && action.includes(id))) {
|
|
192823
192752
|
count2 += 1;
|
|
192824
192753
|
break;
|
|
@@ -192827,28 +192756,18 @@ function countBlockedThrashHits(log41, signature, nowMs = Date.now(), windowMs =
|
|
|
192827
192756
|
}
|
|
192828
192757
|
return count2;
|
|
192829
192758
|
}
|
|
192830
|
-
function isDurableBlockedError(error2) {
|
|
192831
|
-
if (!error2?.startsWith("BLOCKED:")) return false;
|
|
192832
|
-
const reason = error2.slice("BLOCKED:".length).trim();
|
|
192833
|
-
const classification = classifyBlockedExit(reason, []);
|
|
192834
|
-
return !classification.allowAutoReplan;
|
|
192835
|
-
}
|
|
192836
192759
|
function isDurableBlockedTask(task) {
|
|
192837
|
-
if (task.status === "failed" && isDurableBlockedError(task.error)) return true;
|
|
192838
192760
|
const meta2 = task.sourceMetadata;
|
|
192839
192761
|
if (!meta2 || typeof meta2 !== "object") return false;
|
|
192840
|
-
if (meta2.blockedClass
|
|
192841
|
-
|
|
192842
|
-
}
|
|
192843
|
-
const blockers = meta2.externalBlockers;
|
|
192844
|
-
return Array.isArray(blockers) && blockers.length > 0 && task.status === "failed";
|
|
192762
|
+
if (meta2.blockedClass !== "external") return false;
|
|
192763
|
+
return task.status === "failed" || task.status === "needs-replan";
|
|
192845
192764
|
}
|
|
192846
192765
|
function buildExternalBlockMetadataPatch(classification, thrashCount) {
|
|
192847
192766
|
return {
|
|
192848
192767
|
blockedClass: classification.class,
|
|
192849
192768
|
blockedThrashSignature: classification.thrashSignature,
|
|
192850
192769
|
blockedThrashCount: thrashCount,
|
|
192851
|
-
externalBlockers:
|
|
192770
|
+
externalBlockers: []
|
|
192852
192771
|
};
|
|
192853
192772
|
}
|
|
192854
192773
|
|
|
@@ -208426,7 +208345,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
208426
208345
|
{ name: "reconcile-done-task-integrity", fn: () => this.reconcileDoneTaskIntegrity() },
|
|
208427
208346
|
{ name: "reconcile-stale-merger-status", fn: () => this.reconcileStaleMergerStatus() },
|
|
208428
208347
|
{ name: "reconcile-stale-duplicate-decision", fn: () => this.reconcileStaleDuplicateDecisionPause() },
|
|
208429
|
-
{ name: "reconcile-external-pr-blockers", fn: () => this.reconcileExternalPrBlockers() },
|
|
208430
208348
|
// FNXC:OrphanedPendingSteps 2026-07-22-16:35 (FN-8492 review follow-up): also
|
|
208431
208349
|
// steady-state — a step session can die without an engine restart, and startup-only
|
|
208432
208350
|
// cadence left that case riding the 3×30-min stall escalator to a deadlock park.
|
|
@@ -217323,71 +217241,12 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
217323
217241
|
}
|
|
217324
217242
|
}
|
|
217325
217243
|
/*
|
|
217326
|
-
FNXC:HonestBlockedExit 2026-08-02-
|
|
217327
|
-
|
|
217328
|
-
|
|
217329
|
-
|
|
217244
|
+
FNXC:HonestBlockedExit 2026-08-02-23:59 (operator decision — FN-8728 vs PR #2398):
|
|
217245
|
+
The FN-8700 `reconcile-external-pr-blockers` sweep (gh-backed clearing of PR-claim parks)
|
|
217246
|
+
is REMOVED with the whole PR/file-claim blocking mechanism. Open PRs are never blockers;
|
|
217247
|
+
file-scope conflicts are arbitrated only by Fusion's own board. Legacy PR-claim parks are
|
|
217248
|
+
no longer honored by isDurableBlockedTask, so normal recovery paths reclaim them.
|
|
217330
217249
|
*/
|
|
217331
|
-
async reconcileExternalPrBlockers() {
|
|
217332
|
-
try {
|
|
217333
|
-
if (!await isGhAvailable()) {
|
|
217334
|
-
log34.debug("reconcile-external-pr-blockers skipped \u2014 gh unavailable");
|
|
217335
|
-
return 0;
|
|
217336
|
-
}
|
|
217337
|
-
const tasks2 = await this.store.listTasks({ slim: true, includeArchived: false, limit: 500 });
|
|
217338
|
-
let cleared = 0;
|
|
217339
|
-
for (const task of tasks2.slice(0, 80)) {
|
|
217340
|
-
if (task.status !== "failed" || !task.error?.startsWith("BLOCKED:")) continue;
|
|
217341
|
-
const meta2 = task.sourceMetadata;
|
|
217342
|
-
const blockers = meta2?.externalBlockers;
|
|
217343
|
-
if (!Array.isArray(blockers) || blockers.length === 0) continue;
|
|
217344
|
-
const prNumbers = blockers.map((b3) => b3 && typeof b3 === "object" && b3.kind === "github-pr" ? Number(b3.number) : NaN).filter((n) => Number.isFinite(n) && n > 0);
|
|
217345
|
-
if (prNumbers.length === 0) continue;
|
|
217346
|
-
let allResolved = true;
|
|
217347
|
-
for (const n of prNumbers) {
|
|
217348
|
-
try {
|
|
217349
|
-
const pr2 = await runGhJsonAsync(
|
|
217350
|
-
["pr", "view", String(n), "--json", "state,mergedAt"],
|
|
217351
|
-
{ timeoutMs: 15e3 }
|
|
217352
|
-
);
|
|
217353
|
-
const state = String(pr2?.state ?? "").toUpperCase();
|
|
217354
|
-
const merged = Boolean(pr2?.mergedAt) || state === "MERGED";
|
|
217355
|
-
const closed = state === "CLOSED" || state === "MERGED";
|
|
217356
|
-
if (!merged && !closed) {
|
|
217357
|
-
allResolved = false;
|
|
217358
|
-
break;
|
|
217359
|
-
}
|
|
217360
|
-
} catch {
|
|
217361
|
-
allResolved = false;
|
|
217362
|
-
break;
|
|
217363
|
-
}
|
|
217364
|
-
}
|
|
217365
|
-
if (!allResolved) continue;
|
|
217366
|
-
await this.store.updateTask(task.id, {
|
|
217367
|
-
status: null,
|
|
217368
|
-
error: null,
|
|
217369
|
-
sourceMetadataPatch: {
|
|
217370
|
-
externalBlockers: [],
|
|
217371
|
-
blockedClass: null,
|
|
217372
|
-
blockedThrashSignature: null,
|
|
217373
|
-
blockedThrashCount: null,
|
|
217374
|
-
externalPrBlockersClearedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
217375
|
-
externalPrBlockersCleared: prNumbers
|
|
217376
|
-
}
|
|
217377
|
-
});
|
|
217378
|
-
await this.store.logEntry(
|
|
217379
|
-
task.id,
|
|
217380
|
-
`Auto-recovered: external PR blocker(s) ${prNumbers.map((n) => `#${n}`).join(", ")} merged/closed \u2014 cleared durable BLOCKED park for re-dispatch`
|
|
217381
|
-
);
|
|
217382
|
-
log34.log(`Cleared durable PR block for ${task.id} (prs=${prNumbers.join(",")})`);
|
|
217383
|
-
cleared += 1;
|
|
217384
|
-
}
|
|
217385
|
-
return cleared;
|
|
217386
|
-
} catch (error2) {
|
|
217387
|
-
log34.warn(`reconcile-external-pr-blockers failed: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
217388
|
-
return 0;
|
|
217389
|
-
}
|
|
217390
|
-
}
|
|
217391
217250
|
async resolveExplicitDuplicateMarkerTasks() {
|
|
217392
217251
|
try {
|
|
217393
217252
|
const settings = await this.store.getSettings();
|
|
@@ -219772,7 +219631,7 @@ If you have just finished a step's work, immediately call \`fn_task_update\` to
|
|
|
219772
219631
|
|
|
219773
219632
|
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.
|
|
219774
219633
|
|
|
219775
|
-
**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
|
|
219634
|
+
**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.
|
|
219776
219635
|
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.
|
|
219777
219636
|
|
|
219778
219637
|
## How to work
|
|
@@ -227231,75 +227090,16 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
227231
227090
|
);
|
|
227232
227091
|
}
|
|
227233
227092
|
}
|
|
227234
|
-
/*
|
|
227235
|
-
FNXC:HonestBlockedExit 2026-08-02-01:30:
|
|
227236
|
-
Agents often log `BLOCKED: … actively claimed by PR #N` without calling fn_task_done.
|
|
227237
|
-
Without promotion, incomplete-step graph resume requeues the card and thrash restarts
|
|
227238
|
-
(FN-8700). Promote claim/external blocks to a durable failed park here.
|
|
227239
|
-
*/
|
|
227240
|
-
async parkDurableBlockedFromRecentLog(live) {
|
|
227241
|
-
const recent = [...live.log ?? []].reverse().find((entry) => {
|
|
227242
|
-
const action = entry.action ?? "";
|
|
227243
|
-
return action.startsWith("BLOCKED:") || action.includes("durable external block");
|
|
227244
|
-
});
|
|
227245
|
-
if (!recent?.action) return false;
|
|
227246
|
-
const reason = recent.action.startsWith("BLOCKED:") ? recent.action.slice("BLOCKED:".length).trim() : recent.action;
|
|
227247
|
-
const classification = classifyBlockedExit(reason, []);
|
|
227248
|
-
if (classification.allowAutoReplan) return false;
|
|
227249
|
-
const thrashCount = countBlockedThrashHits(live.log, classification.thrashSignature) + 1;
|
|
227250
|
-
const thrashExhausted = thrashCount >= BLOCKED_THRASH_LIMIT;
|
|
227251
|
-
const parkError = thrashExhausted ? `BLOCKED: ${reason} [thrash-exhausted after ${thrashCount} identical durable blocks]` : `BLOCKED: ${reason}`;
|
|
227252
|
-
const metaPatch = buildExternalBlockMetadataPatch(classification, thrashCount);
|
|
227253
|
-
await this.store.updateTask(live.id, {
|
|
227254
|
-
status: "failed",
|
|
227255
|
-
error: parkError,
|
|
227256
|
-
paused: false,
|
|
227257
|
-
pausedByAgentId: null,
|
|
227258
|
-
sourceMetadataPatch: metaPatch
|
|
227259
|
-
}, this.getRunContextFor(live.id));
|
|
227260
|
-
await this.store.logEntry(
|
|
227261
|
-
live.id,
|
|
227262
|
-
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})`,
|
|
227263
|
-
void 0,
|
|
227264
|
-
this.getRunContextFor(live.id)
|
|
227265
|
-
);
|
|
227266
|
-
await this.store.recordRunAuditEvent?.({
|
|
227267
|
-
taskId: live.id,
|
|
227268
|
-
agentId: "executor",
|
|
227269
|
-
runId: generateSyntheticRunId("execution-blocked-log-promote", live.id),
|
|
227270
|
-
domain: "database",
|
|
227271
|
-
mutationType: "task:execution-blocked-parked",
|
|
227272
|
-
target: live.id,
|
|
227273
|
-
metadata: {
|
|
227274
|
-
taskId: live.id,
|
|
227275
|
-
blockedBy: [],
|
|
227276
|
-
hasReason: true,
|
|
227277
|
-
parkedAs: "failed",
|
|
227278
|
-
blockedClass: classification.class,
|
|
227279
|
-
thrashCount,
|
|
227280
|
-
thrashExhausted,
|
|
227281
|
-
prNumbers: classification.prNumbers,
|
|
227282
|
-
source: "session-log-promote"
|
|
227283
|
-
}
|
|
227284
|
-
});
|
|
227285
|
-
executorLog.warn(
|
|
227286
|
-
`${live.id}: promoted durable BLOCKED from session log (class=${classification.class}; thrash=${thrashCount})`
|
|
227287
|
-
);
|
|
227288
|
-
return true;
|
|
227289
|
-
}
|
|
227290
227093
|
async routeGraphFailureToExecutionResume(live, failedNode, failureValue, resumeLanesMemo) {
|
|
227291
227094
|
if (live.deletedAt) return false;
|
|
227292
227095
|
if (live.paused || live.userPaused === true) return false;
|
|
227293
227096
|
if ((await resolveTerminalColumnsFor(this.store, live.id)).includes(live.column)) return false;
|
|
227294
|
-
if (isDurableBlockedTask(live)
|
|
227097
|
+
if (isDurableBlockedTask(live)) {
|
|
227295
227098
|
executorLog.log(
|
|
227296
|
-
`${live.id}: graph failure resume skipped \u2014 durable BLOCKED park honored (
|
|
227099
|
+
`${live.id}: graph failure resume skipped \u2014 durable BLOCKED park honored (task-dependency block)`
|
|
227297
227100
|
);
|
|
227298
227101
|
return false;
|
|
227299
227102
|
}
|
|
227300
|
-
if (await this.parkDurableBlockedFromRecentLog(live)) {
|
|
227301
|
-
return false;
|
|
227302
|
-
}
|
|
227303
227103
|
if (failedNode === COMPLETION_SUMMARY_NODE_ID) return false;
|
|
227304
227104
|
const incompleteSteps = hasNonTerminalWorkflowSteps(live);
|
|
227305
227105
|
const implementationIncompleteMergeFailure = this.isMergeGraphFailure(failedNode) && failureValue === "implementation-incomplete";
|
|
@@ -231046,10 +230846,10 @@ ${summary}`,
|
|
|
231046
230846
|
{ 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.' }
|
|
231047
230847
|
)),
|
|
231048
230848
|
blockedBy: Type6.Optional(Type6.Array(Type6.String(), {
|
|
231049
|
-
description: 'When outcome="blocked": task IDs (e.g. ["FN-8145"])
|
|
230849
|
+
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.'
|
|
231050
230850
|
})),
|
|
231051
230851
|
reason: Type6.Optional(Type6.String({
|
|
231052
|
-
description: 'Required when outcome="blocked": concrete explanation of what is blocking the work and what is needed to unblock it.
|
|
230852
|
+
description: 'Required when outcome="blocked": concrete explanation of what is blocking the work and what is needed to unblock it.'
|
|
231053
230853
|
}))
|
|
231054
230854
|
}),
|
|
231055
230855
|
execute: async (_id, params) => {
|
|
@@ -231108,7 +230908,7 @@ ${summary}`,
|
|
|
231108
230908
|
}, this.getRunContextFor(taskId));
|
|
231109
230909
|
await store.logEntry(
|
|
231110
230910
|
taskId,
|
|
231111
|
-
thrashExhausted ? `${parkError} \u2014 durable external block thrash-exhausted (signature=${classification.thrashSignature}); parked failed, no auto-requeue` :
|
|
230911
|
+
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)`,
|
|
231112
230912
|
void 0,
|
|
231113
230913
|
this.getRunContextFor(taskId)
|
|
231114
230914
|
);
|
|
@@ -231127,18 +230927,17 @@ ${summary}`,
|
|
|
231127
230927
|
parkedAs: autoReplanPark ? "auto-replan" : "failed",
|
|
231128
230928
|
blockedClass: classification.class,
|
|
231129
230929
|
thrashCount,
|
|
231130
|
-
thrashExhausted
|
|
231131
|
-
prNumbers: classification.prNumbers
|
|
230930
|
+
thrashExhausted
|
|
231132
230931
|
}
|
|
231133
230932
|
});
|
|
231134
230933
|
await this.persistTokenUsage(taskId);
|
|
231135
230934
|
executorLog.log(
|
|
231136
|
-
`\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"}
|
|
230935
|
+
`\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"})`}`
|
|
231137
230936
|
);
|
|
231138
230937
|
return {
|
|
231139
230938
|
content: [{
|
|
231140
230939
|
type: "text",
|
|
231141
|
-
text: autoReplanPark ? "Task parked as blocked with no
|
|
230940
|
+
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.`
|
|
231142
230941
|
}],
|
|
231143
230942
|
details: {}
|
|
231144
230943
|
};
|
|
@@ -243299,6 +243098,7 @@ init_transient_error_detector();
|
|
|
243299
243098
|
init_rate_limit_retry();
|
|
243300
243099
|
init_agent_tools();
|
|
243301
243100
|
import { exec as exec42 } from "node:child_process";
|
|
243101
|
+
import { existsSync as existsSync67 } from "node:fs";
|
|
243302
243102
|
import { readFile as readFile40, writeFile as writeFile29, rm as rm12 } from "node:fs/promises";
|
|
243303
243103
|
import { join as join78 } from "node:path";
|
|
243304
243104
|
import { promisify as promisify57 } from "node:util";
|
|
@@ -243600,6 +243400,8 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
243600
243400
|
unregisterAdmissionProvider = null;
|
|
243601
243401
|
/** Timestamps when tasks entered the `processing` set, for staleness detection. */
|
|
243602
243402
|
processingSince = /* @__PURE__ */ new Map();
|
|
243403
|
+
/** Monotonic provenance token for attempt-local planner fallback observation. */
|
|
243404
|
+
planningAttemptSequence = 0;
|
|
243603
243405
|
wasGlobalPaused = false;
|
|
243604
243406
|
wasEnginePaused = false;
|
|
243605
243407
|
idleSemaphoreLeakCandidateSince = null;
|
|
@@ -244895,7 +244697,28 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
244895
244697
|
}
|
|
244896
244698
|
await this.store.logEntry(task.id, `Planning session running in task worktree ${planningCwd}`).catch(() => void 0);
|
|
244897
244699
|
}
|
|
244898
|
-
const
|
|
244700
|
+
const authoritativePromptPath = join78(this.rootDir, promptPath);
|
|
244701
|
+
const planningAttemptBaseline = existsSync67(authoritativePromptPath) ? await readFile40(authoritativePromptPath, "utf-8").catch(() => void 0) : void 0;
|
|
244702
|
+
const planningAttempt = {
|
|
244703
|
+
id: `${task.id}:${++this.planningAttemptSequence}`,
|
|
244704
|
+
baseline: planningAttemptBaseline,
|
|
244705
|
+
fallbackEngaged: false,
|
|
244706
|
+
fallbackSettlements: []
|
|
244707
|
+
};
|
|
244708
|
+
const fallbackObserver = createFallbackModelObserver({
|
|
244709
|
+
agent: "triage",
|
|
244710
|
+
label: "triage",
|
|
244711
|
+
store: this.store,
|
|
244712
|
+
taskId: task.id,
|
|
244713
|
+
taskTitle: task.title
|
|
244714
|
+
});
|
|
244715
|
+
const onFallbackModelUsed = (payload) => {
|
|
244716
|
+
planningAttempt.fallbackEngaged = true;
|
|
244717
|
+
const settlement = Promise.resolve(fallbackObserver(payload));
|
|
244718
|
+
planningAttempt.fallbackSettlements.push(settlement);
|
|
244719
|
+
return settlement;
|
|
244720
|
+
};
|
|
244721
|
+
const { session, settleFallbackDispatch, runtimeId } = await createResolvedAgentSession({
|
|
244899
244722
|
sessionPurpose: "triage",
|
|
244900
244723
|
runtimeHint: triageRuntimeHint,
|
|
244901
244724
|
pluginRunner: this.options.pluginRunner,
|
|
@@ -244934,13 +244757,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
244934
244757
|
taskTitle: task.title,
|
|
244935
244758
|
actionGateContext: this.buildActionGateContext(task.id, triageRunContext.runId, assignedAgent, settings.defaultAgentPermissionPolicy),
|
|
244936
244759
|
permanentAgentGating: this.buildPermanentAgentGatingContext(task.id, triageRunContext.runId, assignedAgent, settings.defaultAgentPermissionPolicy),
|
|
244937
|
-
onFallbackModelUsed
|
|
244938
|
-
agent: "triage",
|
|
244939
|
-
label: "triage",
|
|
244940
|
-
store: this.store,
|
|
244941
|
-
taskId: task.id,
|
|
244942
|
-
taskTitle: task.title
|
|
244943
|
-
})
|
|
244760
|
+
onFallbackModelUsed
|
|
244944
244761
|
});
|
|
244945
244762
|
const modelDesc = formatModelMarkerDetails(describeModel(session), resolvePlanningThinkingLevel(settings, task.planningThinkingLevel ?? task.thinkingLevel));
|
|
244946
244763
|
planLog.debug(`${task.id}: using model ${modelDesc}`);
|
|
@@ -245010,6 +244827,10 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
245010
244827
|
agentPrompt,
|
|
245011
244828
|
imageContents.length > 0 ? { images: imageContents } : void 0
|
|
245012
244829
|
);
|
|
244830
|
+
const fallbackDispatchBoundaryMissing = typeof settleFallbackDispatch !== "function";
|
|
244831
|
+
if (!fallbackDispatchBoundaryMissing) {
|
|
244832
|
+
await settleFallbackDispatch();
|
|
244833
|
+
}
|
|
245013
244834
|
checkSessionError(session);
|
|
245014
244835
|
if (this.pauseAborted.has(task.id)) {
|
|
245015
244836
|
this.pauseAborted.delete(task.id);
|
|
@@ -245102,12 +244923,42 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
245102
244923
|
}
|
|
245103
244924
|
}
|
|
245104
244925
|
}
|
|
245105
|
-
|
|
245106
|
-
|
|
245107
|
-
|
|
245108
|
-
|
|
245109
|
-
|
|
245110
|
-
|
|
244926
|
+
let settledFallbackCount = 0;
|
|
244927
|
+
while (settledFallbackCount < planningAttempt.fallbackSettlements.length) {
|
|
244928
|
+
const pendingSettlements = planningAttempt.fallbackSettlements.slice(settledFallbackCount);
|
|
244929
|
+
settledFallbackCount = planningAttempt.fallbackSettlements.length;
|
|
244930
|
+
await Promise.all(pendingSettlements);
|
|
244931
|
+
}
|
|
244932
|
+
const artifactChangedByAttempt = planningAttempt.baseline !== written;
|
|
244933
|
+
if (fallbackDispatchBoundaryMissing || planningAttempt.fallbackEngaged || !artifactChangedByAttempt) {
|
|
244934
|
+
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}`;
|
|
244935
|
+
const decision = computeRecoveryDecision({
|
|
244936
|
+
recoveryRetryCount: task.recoveryRetryCount,
|
|
244937
|
+
nextRecoveryAt: task.nextRecoveryAt
|
|
244938
|
+
});
|
|
244939
|
+
if (decision.shouldRetry) {
|
|
244940
|
+
const retryMessage = `${failure} \u2014 retry ${decision.nextState.recoveryRetryCount}/${MAX_RECOVERY_RETRIES} in ${formatDelay(decision.delayMs)}.`;
|
|
244941
|
+
planLog.warn(`${task.id} ${retryMessage}`);
|
|
244942
|
+
await this.store.logEntry(task.id, retryMessage);
|
|
244943
|
+
await this.updatePlanningStateIfStillCurrent(task, {
|
|
244944
|
+
status: this.restoreStatusAfterInterruptedTriageWork(task),
|
|
244945
|
+
error: null,
|
|
244946
|
+
recoveryRetryCount: decision.nextState.recoveryRetryCount,
|
|
244947
|
+
nextRecoveryAt: decision.nextState.nextRecoveryAt
|
|
244948
|
+
});
|
|
244949
|
+
return;
|
|
244950
|
+
}
|
|
244951
|
+
const failureMessage = `${failure} after ${MAX_RECOVERY_RETRIES} retries. Retry after adjusting the task prompt or model.`;
|
|
244952
|
+
planLog.error(`${task.id} clean planning attempt retry budget exhausted`);
|
|
244953
|
+
await this.store.logEntry(task.id, failureMessage);
|
|
244954
|
+
if (await this.updatePlanningStateIfStillCurrent(task, {
|
|
244955
|
+
status: "failed",
|
|
244956
|
+
error: failureMessage,
|
|
244957
|
+
recoveryRetryCount: null,
|
|
244958
|
+
nextRecoveryAt: null
|
|
244959
|
+
})) {
|
|
244960
|
+
await this.backfillBlankTitleAfterTerminalTriageFailure(task);
|
|
244961
|
+
}
|
|
245111
244962
|
return;
|
|
245112
244963
|
}
|
|
245113
244964
|
const deterministicSpecFailure = await this.validateGeneratedPrompt(task.id, written);
|
|
@@ -245149,6 +245000,21 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
245149
245000
|
}
|
|
245150
245001
|
return;
|
|
245151
245002
|
}
|
|
245003
|
+
const duplicateReport = { outcome: "parked" };
|
|
245004
|
+
if (await this.tryFinalizeExplicitDuplicateMarker(task, written, settings, {
|
|
245005
|
+
isReplan,
|
|
245006
|
+
feedback
|
|
245007
|
+
}, duplicateReport)) {
|
|
245008
|
+
this.options.onSpecifyComplete?.(task, duplicateReport);
|
|
245009
|
+
return;
|
|
245010
|
+
}
|
|
245011
|
+
if (task.recoveryRetryCount != null || task.nextRecoveryAt != null) {
|
|
245012
|
+
await this.updatePlanningStateIfStillCurrent(task, {
|
|
245013
|
+
error: null,
|
|
245014
|
+
recoveryRetryCount: null,
|
|
245015
|
+
nextRecoveryAt: null
|
|
245016
|
+
});
|
|
245017
|
+
}
|
|
245152
245018
|
const finalizeReport = await this.finalizeApprovedTask(task, written, settings, {
|
|
245153
245019
|
isReplan,
|
|
245154
245020
|
feedback
|
|
@@ -249882,14 +249748,14 @@ function extractAdvisorAssistantText(session) {
|
|
|
249882
249748
|
|
|
249883
249749
|
// ../engine/src/overseer-watchdog.ts
|
|
249884
249750
|
init_logger();
|
|
249885
|
-
import { existsSync as
|
|
249751
|
+
import { existsSync as existsSync68, readFileSync as readFileSync24 } from "node:fs";
|
|
249886
249752
|
import { dirname as dirname34, join as join79, relative as relative17, resolve as resolve40, sep as sep11 } from "node:path";
|
|
249887
249753
|
import { homedir as homedir12 } from "node:os";
|
|
249888
249754
|
var log38 = createLogger("overseer-watchdog");
|
|
249889
249755
|
var WATCHDOG_FILENAMES = ["OVERSEER.md", "WATCHDOG.md"];
|
|
249890
249756
|
function defaultReadText(path5) {
|
|
249891
249757
|
try {
|
|
249892
|
-
if (!
|
|
249758
|
+
if (!existsSync68(path5)) return null;
|
|
249893
249759
|
return readFileSync24(path5, "utf8");
|
|
249894
249760
|
} catch {
|
|
249895
249761
|
return null;
|
|
@@ -251033,7 +250899,7 @@ init_worktree_paths();
|
|
|
251033
250899
|
// ../engine/src/merger-ai-worktree.ts
|
|
251034
250900
|
init_active_session_registry();
|
|
251035
250901
|
import { execFile as execFile28 } from "node:child_process";
|
|
251036
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
250902
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync69, mkdirSync as mkdirSync11, readdirSync as readdirSync12, readFileSync as readFileSync25, realpathSync as realpathSync11, rmSync as rmSync9, statSync as statSync13 } from "node:fs";
|
|
251037
250903
|
import { rm as rm13 } from "node:fs/promises";
|
|
251038
250904
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
251039
250905
|
import { isAbsolute as isAbsolute21, join as join80, relative as relative18 } from "node:path";
|
|
@@ -251070,7 +250936,7 @@ function isBenignAbsentWorktreeError(err) {
|
|
|
251070
250936
|
}
|
|
251071
250937
|
function ensureAiMergeRootIgnored(projectRootDir, settings) {
|
|
251072
250938
|
const excludePath = join80(projectRootDir, ".git", "info", "exclude");
|
|
251073
|
-
if (!
|
|
250939
|
+
if (!existsSync69(excludePath)) return;
|
|
251074
250940
|
try {
|
|
251075
250941
|
const current = readFileSync25(excludePath, "utf-8");
|
|
251076
250942
|
const legacyAiMergeRoot = resolveLegacyAiMergeRootPath(projectRootDir);
|
|
@@ -251201,7 +251067,7 @@ async function cleanupAiMergeWorktree(input) {
|
|
|
251201
251067
|
const cleanupMetadata = { taskId, mergeRoot: canonicalRoot, requestedMergeRoot: mergeRoot };
|
|
251202
251068
|
let alreadyAbsent = false;
|
|
251203
251069
|
if (worktreeAdded) {
|
|
251204
|
-
if (!
|
|
251070
|
+
if (!existsSync69(canonicalRoot) && !existsSync69(mergeRoot)) {
|
|
251205
251071
|
alreadyAbsent = true;
|
|
251206
251072
|
await log41(`AI merge cleanup: worktree ${canonicalRoot} was already absent before git removal; treating cleanup as idempotent`);
|
|
251207
251073
|
await audit.git({ type: "merge:ai-worktree-cleanup", target: canonicalRoot, metadata: { ...cleanupMetadata, phase: "git-remove", success: true, alreadyAbsent: true, idempotent: true, code: "ENOENT" } });
|