@runfusion/fusion 0.77.0-beta.1 → 0.77.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +298 -62
- package/dist/child-process-worker.js +287 -57
- package/dist/client/.vite/manifest.json +262 -262
- package/dist/client/assets/{AgentDetailView-Crk9OdF-.js → AgentDetailView-Dew3af1O.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-BHQ9RPKE.js → AgentPermissionPolicyEditor-CxPQffiY.js} +1 -1
- package/dist/client/assets/{AgentsView-BWOl5J6F.js → AgentsView-Cr4LDGdt.js} +3 -3
- package/dist/client/assets/{ChatView-BP8-Are_.js → ChatView-cNYtYx05.js} +1 -1
- package/dist/client/assets/{CommandCenter-C1adapJC.js → CommandCenter-DCC90LOP.js} +1 -1
- package/dist/client/assets/{DevServerView-B2wexHCU.js → DevServerView-B5b520w6.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-C7rzLVyD.js → DirectoryPicker-1JvRd5mC.js} +1 -1
- package/dist/client/assets/{DocumentsView-hOjlyCfz.js → DocumentsView-ksK9f7xt.js} +1 -1
- package/dist/client/assets/{EvalsView-CdAB_4D_.js → EvalsView-a3LhgRSo.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-GEypAOXx.js → ExperimentalAgentOnboardingModal-vdVa8h7F.js} +1 -1
- package/dist/client/assets/{GoalsView-DW1qRxeP.js → GoalsView-Dz2o91fd.js} +1 -1
- package/dist/client/assets/{InsightsView-B5roc0nI.js → InsightsView-De3R_46d.js} +1 -1
- package/dist/client/assets/{MemoryView-B0mSfU8f.js → MemoryView-Cagk2wZG.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-ps7tZzok.js → PiExtensionsManager-C9JABO_4.js} +1 -1
- package/dist/client/assets/{PluginManager-BrsdP_Zs.js → PluginManager-D2csmdQa.js} +1 -1
- package/dist/client/assets/{PullRequestView-CkLoEm3J.js → PullRequestView-DT8vTeVi.js} +1 -1
- package/dist/client/assets/{ReportModal-BKdSSVii.js → ReportModal-YMP6V4vu.js} +1 -1
- package/dist/client/assets/{ResearchView-OZW77xd4.js → ResearchView-cNsjYu8F.js} +1 -1
- package/dist/client/assets/{SecretsView-CawXNPvr.js → SecretsView-BAmf7KyS.js} +1 -1
- package/dist/client/assets/{SessionTerminal-C26iOW6f.js → SessionTerminal-BjGcxq22.js} +1 -1
- package/dist/client/assets/{SettingsModal-BNWlULmc.js → SettingsModal-C_9RiEI7.js} +1 -1
- package/dist/client/assets/{SettingsModal-CfXTMT99.js → SettingsModal-DLfy2e_5.js} +4 -4
- package/dist/client/assets/{SettingsTextareaRow-DrXj-rTG.js → SettingsTextareaRow-D8RHSj8b.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-Dk4cldse.js → SetupWizardModal-DRJ96pHQ.js} +2 -2
- package/dist/client/assets/{SkillsView-NBEe0Qjt.js → SkillsView-DyeCwYit.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-CZX7Mlum.js → WorkflowNodeEditor-C5Jc9w_A.js} +3 -3
- package/dist/client/assets/{agent-import-generation-TK-wCZBK.js → agent-import-generation-SCPNeF25.js} +1 -1
- package/dist/client/assets/{agentsOrgChartLayout-BFC39-tw.js → agentsOrgChartLayout-CqKtNCjy.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-CYHuEL_5.js → architectureDiagram-3BPJPVTR-Cz2HYn0b.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-BhFoNt44.js → blockDiagram-GPEHLZMM-IimJVscG.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CQorfIRn.js → c4Diagram-AAUBKEIU-C-xii7zn.js} +1 -1
- package/dist/client/assets/channel-D-UHgx8G.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-DLyODy_m.js → chunk-2J33WTMH-DQ-9Xccu.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-C4ZfqjSh.js → chunk-4BX2VUAB-DmdAX9Bx.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CvGg-ubc.js → chunk-55IACEB6-IF2bk5IL.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-jCzUYl5C.js → chunk-727SXJPM-AeYpIzVu.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DYLT-tu8.js → chunk-AQP2D5EJ-DV942DD9.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-CCgBBj1Z.js → chunk-FMBD7UC4-Bt_riVlZ.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-BFdFrIja.js → chunk-ND2GUHAM-CbyjNbXR.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-BUTaQ50G.js → chunk-QZHKN3VN-DqiRniYQ.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-Do-8MdAc.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Do-8MdAc.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DUbNlc_8.js → cose-bilkent-S5V4N54A-UCvthviL.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-Db_33UO6.js → dagre-BM42HDAG-DnMlT1Oi.js} +1 -1
- package/dist/client/assets/{dashboard-view-C3PU63FX.js → dashboard-view-C9D0aoRW.js} +1 -1
- package/dist/client/assets/dashboard-view-Cz0sp2Wl.js +1 -0
- package/dist/client/assets/{dashboard-view-CblIAx4p.js → dashboard-view-JysoyDRX.js} +1 -1
- package/dist/client/assets/{dashboard-view-ZGZ80pF3.js → dashboard-view-myjM9tr8.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BCTLM-Gj.js → diagram-2AECGRRQ-BYFiqXGw.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CkYPWqJ0.js → diagram-5GNKFQAL-DZU3pSYq.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-7_DJ9TOL.js → diagram-KO2AKTUF-0ybdKuMm.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-BAkMEapl.js → diagram-LMA3HP47-Rxbgnbsp.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-DbsQHZ0F.js → diagram-OG6HWLK6-BAU_hTeV.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-Bz1kISgV.js → erDiagram-TEJ5UH35-zr8HrwTt.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-fkBLx_JW.js → flowDiagram-I6XJVG4X-CrTw0iFw.js} +1 -1
- package/dist/client/assets/{folder-open-l8Z1o786.js → folder-open-DnAlsXXn.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-BEDb0Uyw.js → ganttDiagram-6RSMTGT7-CCORsxxz.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-Cen5lgL7.js → gitGraphDiagram-PVQCEYII-C07wWSjj.js} +1 -1
- package/dist/client/assets/index-B_z7OKl4.js +2818 -0
- package/dist/client/assets/index-DPo-IAb2.css +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BHqjYX5-.js → infoDiagram-5YYISTIA-hAeccD_4.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-6JaCT-0H.js → ishikawaDiagram-YF4QCWOH-WLCzv-NH.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-C_sUwyWW.js → journeyDiagram-JHISSGLW-ClnasNhy.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-__o8oDEP.js → kanban-definition-UN3LZRKU-CAuARhUz.js} +1 -1
- package/dist/client/assets/{mermaid.core-BwF2BF3U.js → mermaid.core-Bh02RvfX.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DMhvCrGK.js → mindmap-definition-RKZ34NQL-KNTlbW4V.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-Dk0KKcwv.js → pieDiagram-4H26LBE5-BouAfBEw.js} +1 -1
- package/dist/client/assets/{puzzle-DcLi6jmv.js → puzzle-CC8Ur3Cy.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-DXcBYGil.js → quadrantDiagram-W4KKPZXB-wTdkCUJU.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33--GXgKHm2.js → requirementDiagram-4Y6WPE33-BnjY4Tc_.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-fX5WAFdr.js → sankeyDiagram-5OEKKPKP-C-QsS08u.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-VQOx2wc2.js → sequenceDiagram-3UESZ5HK-DD36MILE.js} +1 -1
- package/dist/client/assets/{shield-alert-DLW2jAvI.js → shield-alert-DcXc56Fy.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-RbXYE69q.js → standing-instructions-template-BF5y1BLz.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-COZ_NGxp.js → stateDiagram-AJRCARHV-WTq1wQr1.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-CmgPEZwe.js → stateDiagram-v2-BHNVJYJU-eILJdjII.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-eJYKjHOn.js → timeline-definition-PNZ67QCA-PRNwI0NR.js} +1 -1
- package/dist/client/assets/{upload-DwRVPojw.js → upload-qH_64O-B.js} +1 -1
- package/dist/client/assets/{useDiscoveredSkillsCache-DhScYUmX.js → useDiscoveredSkillsCache-C-GPCNaO.js} +1 -1
- package/dist/client/assets/{users-BrTlKeXP.js → users-D2UesRE4.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-Ddt59BdZ.js → vennDiagram-CIIHVFJN-CG2Z4T4O.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-C4R0wOO2.js → wardley-L42UT6IY-gO_fGvF9.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BJDm4S7I.js → wardleyDiagram-YWT4CUSO-BkyNpjUb.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DlypQnRH.js → xychartDiagram-2RQKCTM6-CMlZsiPq.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +290 -59
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.js +29 -2
- package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +269 -16
- package/dist/plugins/fusion-plugin-acp-runtime/mcp-schema-server.cjs +171 -0
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +29 -2
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/channel-DgImfyB5.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C3pUNxZS.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C3pUNxZS.js +0 -1
- package/dist/client/assets/dashboard-view-c3FuWBJb.js +0 -1
- package/dist/client/assets/index-BnZB0GkD.js +0 -2818
- package/dist/client/assets/index-CPGSlKrd.css +0 -1
|
@@ -16843,8 +16843,34 @@ function didFallBackToDefault(ir2) {
|
|
|
16843
16843
|
async function resolveWorkflowIrForTaskWithProvenance(store, taskId, irCache, selectionCache) {
|
|
16844
16844
|
let workflowId;
|
|
16845
16845
|
try {
|
|
16846
|
-
const
|
|
16847
|
-
|
|
16846
|
+
const isSelectionCached = selectionCache?.has(taskId) ?? false;
|
|
16847
|
+
let selection = isSelectionCached && selectionCache ? selectionCache.get(taskId) : void 0;
|
|
16848
|
+
if (!isSelectionCached) {
|
|
16849
|
+
let inflight;
|
|
16850
|
+
let coalesced = false;
|
|
16851
|
+
if (selectionCache) {
|
|
16852
|
+
inflight = inflightSelectionReads.get(selectionCache);
|
|
16853
|
+
if (!inflight) {
|
|
16854
|
+
inflight = /* @__PURE__ */ new Map();
|
|
16855
|
+
inflightSelectionReads.set(selectionCache, inflight);
|
|
16856
|
+
}
|
|
16857
|
+
const pending = inflight.get(taskId);
|
|
16858
|
+
if (pending) {
|
|
16859
|
+
selection = await pending;
|
|
16860
|
+
coalesced = true;
|
|
16861
|
+
}
|
|
16862
|
+
}
|
|
16863
|
+
if (!coalesced) {
|
|
16864
|
+
const readPromise = store.getTaskWorkflowSelectionAsync ? store.getTaskWorkflowSelectionAsync(taskId) : Promise.resolve(store.getTaskWorkflowSelection(taskId));
|
|
16865
|
+
if (inflight) inflight.set(taskId, readPromise);
|
|
16866
|
+
try {
|
|
16867
|
+
selection = await readPromise;
|
|
16868
|
+
} finally {
|
|
16869
|
+
inflight?.delete(taskId);
|
|
16870
|
+
}
|
|
16871
|
+
}
|
|
16872
|
+
selectionCache?.set(taskId, selection);
|
|
16873
|
+
}
|
|
16848
16874
|
workflowId = selection?.workflowId;
|
|
16849
16875
|
} catch {
|
|
16850
16876
|
return { ir: defaultCodingWorkflowIr(), source: "default" };
|
|
@@ -16868,13 +16894,14 @@ async function isTaskTerminalNodeIdAsync(store, taskId, nodeId) {
|
|
|
16868
16894
|
}
|
|
16869
16895
|
return nodeId === "end";
|
|
16870
16896
|
}
|
|
16871
|
-
var FELL_BACK_TO_DEFAULT;
|
|
16897
|
+
var inflightSelectionReads, FELL_BACK_TO_DEFAULT;
|
|
16872
16898
|
var init_workflow_ir_resolver = __esm({
|
|
16873
16899
|
"../core/src/workflows/workflow-ir-resolver.ts"() {
|
|
16874
16900
|
"use strict";
|
|
16875
16901
|
init_builtin_workflows();
|
|
16876
16902
|
init_workflow_ir();
|
|
16877
16903
|
init_workflow_prompt_overrides();
|
|
16904
|
+
inflightSelectionReads = /* @__PURE__ */ new WeakMap();
|
|
16878
16905
|
FELL_BACK_TO_DEFAULT = /* @__PURE__ */ Symbol.for("fusion.workflowIr.fellBackToDefault");
|
|
16879
16906
|
}
|
|
16880
16907
|
});
|
|
@@ -36495,9 +36522,12 @@ async function markApprovalRequestCompleted(layer, requestId, input) {
|
|
|
36495
36522
|
});
|
|
36496
36523
|
}
|
|
36497
36524
|
async function getApprovalAuditHistory(handle2, requestId, projectId2) {
|
|
36498
|
-
const
|
|
36499
|
-
|
|
36500
|
-
|
|
36525
|
+
const eventType = project_exports.approvalRequestAuditEvents.eventType;
|
|
36526
|
+
const lifecycleRank = sql`CASE ${eventType} ${sql.join(
|
|
36527
|
+
APPROVAL_REQUEST_AUDIT_EVENT_TYPES.map((type, rank) => sql`WHEN ${type} THEN ${rank}`),
|
|
36528
|
+
sql` `
|
|
36529
|
+
)} ELSE ${APPROVAL_REQUEST_AUDIT_EVENT_TYPES.length} END`;
|
|
36530
|
+
const rows = await handle2.select().from(project_exports.approvalRequestAuditEvents).where(and(eq(project_exports.approvalRequestAuditEvents.requestId, requestId), projectScopeFor(project_exports.approvalRequestAuditEvents.projectId, projectId2))).orderBy(sql`${project_exports.approvalRequestAuditEvents.createdAt} ASC, ${lifecycleRank} ASC, ${project_exports.approvalRequestAuditEvents.id} ASC`);
|
|
36501
36531
|
return rows.map((row) => rowToAuditEvent(row));
|
|
36502
36532
|
}
|
|
36503
36533
|
var init_async_approval_request_store = __esm({
|
|
@@ -143585,9 +143615,9 @@ function mergeParkedColumns(base, lanes) {
|
|
|
143585
143615
|
terminal: /* @__PURE__ */ new Set([...base.terminal, ...lanes.terminal ?? [], complete, archived])
|
|
143586
143616
|
};
|
|
143587
143617
|
}
|
|
143588
|
-
async function resolveTaskParkedColumns(store, taskId) {
|
|
143618
|
+
async function resolveTaskParkedColumns(store, taskId, selectionCache) {
|
|
143589
143619
|
try {
|
|
143590
|
-
const ir2 = await resolveWorkflowIrForTask(store, taskId);
|
|
143620
|
+
const ir2 = await resolveWorkflowIrForTask(store, taskId, void 0, selectionCache);
|
|
143591
143621
|
const l = resolveLifecycleColumns(ir2);
|
|
143592
143622
|
const complete = l?.complete ?? LEGACY_PARKED_COLUMNS2.complete;
|
|
143593
143623
|
const archived = l?.archived ?? LEGACY_PARKED_COLUMNS2.archived;
|
|
@@ -143832,6 +143862,7 @@ var init_scheduler = __esm({
|
|
|
143832
143862
|
}
|
|
143833
143863
|
});
|
|
143834
143864
|
this.store.on("task:moved", async ({ task, from, to: to2, source, lanes }) => {
|
|
143865
|
+
const movedSelectionCache = /* @__PURE__ */ new Map();
|
|
143835
143866
|
this.lastAutoClaimFingerprint.set(task.id, computeAutoClaimFingerprint(task));
|
|
143836
143867
|
const parked = mergeParkedColumns(LEGACY_PARKED_COLUMNS2, lanes);
|
|
143837
143868
|
if (from === parked.hold || to2 === parked.hold) {
|
|
@@ -143887,7 +143918,7 @@ var init_scheduler = __esm({
|
|
|
143887
143918
|
});
|
|
143888
143919
|
}
|
|
143889
143920
|
}
|
|
143890
|
-
const resolvedParked = mergeParkedColumns(await resolveTaskParkedColumns(this.store, task.id), lanes);
|
|
143921
|
+
const resolvedParked = mergeParkedColumns(await resolveTaskParkedColumns(this.store, task.id, movedSelectionCache), lanes);
|
|
143891
143922
|
if (resolvedParked.terminal.has(to2)) {
|
|
143892
143923
|
try {
|
|
143893
143924
|
const settings = await this.store.getSettings();
|
|
@@ -143953,6 +143984,7 @@ var init_scheduler = __esm({
|
|
|
143953
143984
|
}
|
|
143954
143985
|
});
|
|
143955
143986
|
this.store.on("task:updated", (task, meta2) => {
|
|
143987
|
+
const updatedSelectionCache = /* @__PURE__ */ new Map();
|
|
143956
143988
|
const nextFingerprint = computeAutoClaimFingerprint(task);
|
|
143957
143989
|
const previousFingerprint = this.lastAutoClaimFingerprint.get(task.id);
|
|
143958
143990
|
if (!previousFingerprint || previousFingerprint !== nextFingerprint) {
|
|
@@ -143983,7 +144015,7 @@ var init_scheduler = __esm({
|
|
|
143983
144015
|
});
|
|
143984
144016
|
}
|
|
143985
144017
|
void (async () => {
|
|
143986
|
-
const unpausedParked = await resolveTaskParkedColumns(this.store, task.id);
|
|
144018
|
+
const unpausedParked = await resolveTaskParkedColumns(this.store, task.id, updatedSelectionCache);
|
|
143987
144019
|
if (this.running && unpausedParked.wake.has(task.column)) {
|
|
143988
144020
|
schedulerLog.log(`Task ${task.id} unpaused \u2014 triggering scheduling`);
|
|
143989
144021
|
void this.schedule();
|
|
@@ -143995,7 +144027,7 @@ var init_scheduler = __esm({
|
|
|
143995
144027
|
} else if (this.planningTaskIds.has(task.id)) {
|
|
143996
144028
|
this.planningTaskIds.delete(task.id);
|
|
143997
144029
|
void (async () => {
|
|
143998
|
-
const planningParked = await resolveTaskParkedColumns(this.store, task.id);
|
|
144030
|
+
const planningParked = await resolveTaskParkedColumns(this.store, task.id, updatedSelectionCache);
|
|
143999
144031
|
if (this.running && !task.status && !task.paused && !task.userPaused && planningParked.wake.has(task.column)) {
|
|
144000
144032
|
schedulerLog.log(`Task ${task.id} finished planning \u2014 triggering scheduling`);
|
|
144001
144033
|
void this.schedule();
|
|
@@ -144008,7 +144040,7 @@ var init_scheduler = __esm({
|
|
|
144008
144040
|
} else if (!task.status && !task.paused && !task.userPaused && (this.approvalHeldTaskIds.delete(task.id) || (Boolean(task.approvedPlanFingerprint) || task.workflowStepResults?.some(isPlanReviewSatisfied) === true) && !this.approvalReleasedTaskIds.has(task.id))) {
|
|
144009
144041
|
this.approvalReleasedTaskIds.add(task.id);
|
|
144010
144042
|
void (async () => {
|
|
144011
|
-
const approvalParked = await resolveTaskParkedColumns(this.store, task.id);
|
|
144043
|
+
const approvalParked = await resolveTaskParkedColumns(this.store, task.id, updatedSelectionCache);
|
|
144012
144044
|
if (this.running && !task.status && !task.paused && !task.userPaused && approvalParked.wake.has(task.column)) {
|
|
144013
144045
|
schedulerLog.log(`Task ${task.id} plan approval cleared \u2014 triggering scheduling`);
|
|
144014
144046
|
void this.schedule();
|
|
@@ -144047,7 +144079,8 @@ var init_scheduler = __esm({
|
|
|
144047
144079
|
if (settings.globalPause || settings.enginePaused) {
|
|
144048
144080
|
return;
|
|
144049
144081
|
}
|
|
144050
|
-
const
|
|
144082
|
+
const deletedSelectionCache = /* @__PURE__ */ new Map();
|
|
144083
|
+
const deletedParked = await resolveTaskParkedColumns(this.store, task.id, deletedSelectionCache);
|
|
144051
144084
|
const deletedWipColumns = await resolveProjectColumnsForRoles(this.store, ["countsTowardWip"]);
|
|
144052
144085
|
const todoTasks = await this.store.listTasks({ column: deletedParked.hold, slim: true });
|
|
144053
144086
|
const inProgressById = /* @__PURE__ */ new Map();
|
|
@@ -144256,7 +144289,16 @@ var init_scheduler = __esm({
|
|
|
144256
144289
|
}
|
|
144257
144290
|
}
|
|
144258
144291
|
async transitionQueuedEpisode(task, input) {
|
|
144259
|
-
|
|
144292
|
+
if (typeof this.store.transitionQueuedEpisode === "function") {
|
|
144293
|
+
return (await this.store.transitionQueuedEpisode(task.id, input)).appended;
|
|
144294
|
+
}
|
|
144295
|
+
await this.store.updateTask(task.id, {
|
|
144296
|
+
status: "queued",
|
|
144297
|
+
blockedBy: input.blockedBy ?? null,
|
|
144298
|
+
overlapBlockedBy: input.overlapBlockedBy ?? null
|
|
144299
|
+
});
|
|
144300
|
+
await this.logDispatchQueuedReason(task.id, input.action);
|
|
144301
|
+
return true;
|
|
144260
144302
|
}
|
|
144261
144303
|
async logDispatchQueuedReason(taskId, reason, memoKey) {
|
|
144262
144304
|
const key = `${taskId}:${memoKey ?? reason}`;
|
|
@@ -144308,13 +144350,14 @@ var init_scheduler = __esm({
|
|
|
144308
144350
|
}
|
|
144309
144351
|
async emitHighOverlapFanoutWarnings(tasks2) {
|
|
144310
144352
|
const escalationIrCache = /* @__PURE__ */ new Map();
|
|
144353
|
+
const escalationSelectionCache = /* @__PURE__ */ new Map();
|
|
144311
144354
|
const escalationByTaskId = /* @__PURE__ */ new Map();
|
|
144312
144355
|
const escalationColumns = /* @__PURE__ */ new Set();
|
|
144313
144356
|
const holdByTaskId = /* @__PURE__ */ new Map();
|
|
144314
144357
|
const terminalByTaskId = /* @__PURE__ */ new Map();
|
|
144315
144358
|
const blockerReviewColumns = /* @__PURE__ */ new Set();
|
|
144316
144359
|
for (const task of tasks2) {
|
|
144317
|
-
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, escalationIrCache).catch(() => void 0);
|
|
144360
|
+
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, escalationIrCache, escalationSelectionCache).catch(() => void 0);
|
|
144318
144361
|
if (!ir2) continue;
|
|
144319
144362
|
for (const id of columnsWithFlag(ir2, "countsTowardWip")) escalationColumns.add(id);
|
|
144320
144363
|
for (const id of columnsWithFlag(ir2, "mergeOrchestration")) escalationColumns.add(id);
|
|
@@ -144384,9 +144427,10 @@ var init_scheduler = __esm({
|
|
|
144384
144427
|
if (!agentStore) return;
|
|
144385
144428
|
const runningAgents = await agentStore.listAgents({ state: "running", includeEphemeral: false });
|
|
144386
144429
|
const linkedAgents = runningAgents.filter((agent) => agent.taskId === taskId);
|
|
144430
|
+
const rollbackSelectionCache = /* @__PURE__ */ new Map();
|
|
144387
144431
|
for (const agent of linkedAgents) {
|
|
144388
144432
|
const activeRun = await agentStore.getActiveHeartbeatRun?.(agent.id);
|
|
144389
|
-
const rollbackParked = await resolveTaskParkedColumns(this.store, taskId);
|
|
144433
|
+
const rollbackParked = await resolveTaskParkedColumns(this.store, taskId, rollbackSelectionCache);
|
|
144390
144434
|
const proof = evaluateParkedAgentTaskLink({
|
|
144391
144435
|
agent,
|
|
144392
144436
|
linkedTask: { column: rollbackParked.hold },
|
|
@@ -144434,11 +144478,12 @@ var init_scheduler = __esm({
|
|
|
144434
144478
|
const repo = getCurrentRepo(this.store.getRootDir());
|
|
144435
144479
|
if (!repo) return;
|
|
144436
144480
|
const hydrationIrCache = /* @__PURE__ */ new Map();
|
|
144481
|
+
const hydrationSelectionCache = /* @__PURE__ */ new Map();
|
|
144437
144482
|
for (const task of tasks2) {
|
|
144438
144483
|
if (!task.prInfo) continue;
|
|
144439
144484
|
let flags;
|
|
144440
144485
|
try {
|
|
144441
|
-
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, hydrationIrCache);
|
|
144486
|
+
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, hydrationIrCache, hydrationSelectionCache);
|
|
144442
144487
|
const column = ir2.columns?.find((candidate) => candidate.id === task.column);
|
|
144443
144488
|
if (column) flags = resolveColumnFlags(column);
|
|
144444
144489
|
} catch {
|
|
@@ -145367,19 +145412,20 @@ var init_scheduler = __esm({
|
|
|
145367
145412
|
return;
|
|
145368
145413
|
}
|
|
145369
145414
|
const sliceIdBeforeUpdate = feature.sliceId;
|
|
145370
|
-
|
|
145371
|
-
|
|
145372
|
-
|
|
145373
|
-
|
|
145374
|
-
|
|
145375
|
-
|
|
145376
|
-
|
|
145377
|
-
|
|
145378
|
-
|
|
145415
|
+
let missionId = task.missionId;
|
|
145416
|
+
try {
|
|
145417
|
+
if (!missionId && typeof missionStore.getSlice === "function") {
|
|
145418
|
+
const featureSlice = await missionStore.getSlice(feature.sliceId);
|
|
145419
|
+
const milestone = featureSlice && typeof missionStore.getMilestone === "function" ? await missionStore.getMilestone(featureSlice.milestoneId) : void 0;
|
|
145420
|
+
missionId = milestone?.missionId;
|
|
145421
|
+
}
|
|
145422
|
+
if (!missionId) {
|
|
145423
|
+
schedulerLog.warn(`Task ${taskId} feature ${feature.id} has no resolvable mission; skipping reconciliation`);
|
|
145424
|
+
} else if (missionId !== task.missionId) {
|
|
145379
145425
|
await reconcileMissionState({ taskStore: this.store, missionStore }, { missionId, source: "task-move" });
|
|
145380
|
-
} catch (error2) {
|
|
145381
|
-
schedulerLog.warn(`Mission reconciliation failed after resolving task ${taskId}; continuing mission completion handling:`, error2);
|
|
145382
145426
|
}
|
|
145427
|
+
} catch (error2) {
|
|
145428
|
+
schedulerLog.warn(`Task ${taskId} feature ${feature.id} mission reconcile skipped (${String(error2)}); continuing to completion check`);
|
|
145383
145429
|
}
|
|
145384
145430
|
let completionFlags;
|
|
145385
145431
|
try {
|
|
@@ -148355,17 +148401,40 @@ var init_auth_storage = __esm({
|
|
|
148355
148401
|
async getApiKey(provider, instance) {
|
|
148356
148402
|
return resolveStoredCredentialApiKey(provider, instance ? this.getInstance(instance) : this.get(provider));
|
|
148357
148403
|
}
|
|
148404
|
+
/*
|
|
148405
|
+
FNXC:ProviderAuth 2026-08-18-04:40:
|
|
148406
|
+
MODIFY MUST BE ABLE TO CREATE. This is the seam pi persists a COMPLETED LOGIN through
|
|
148407
|
+
(`Models.login` -> `credentials.modify(provider.id, ...)` in pi-ai's models.js), not just the seam
|
|
148408
|
+
it refreshes an existing token through.
|
|
148409
|
+
|
|
148410
|
+
It used to resolve its write target with `creating: false` and then bail —
|
|
148411
|
+
`if (!target || !this.credential(target, current)) return { changed: false }` — whenever the
|
|
148412
|
+
provider had no credential row yet. The callback was never invoked, nothing was written, and pi's
|
|
148413
|
+
login resolved as a SUCCESS. So a first-ever login for a provider could not be saved: the browser
|
|
148414
|
+
flow completed, the token exchange succeeded, the lock file was taken and released, `auth.json`
|
|
148415
|
+
stayed `{}`, and the dashboard's poll saw `authenticated: false` and reported the useless "Login
|
|
148416
|
+
did not complete. Please try again."
|
|
148417
|
+
|
|
148418
|
+
It looked provider-specific and environment-specific for the worst possible reason: it only
|
|
148419
|
+
reproduces on a store with NO existing row, so every developer and every long-lived install — where
|
|
148420
|
+
a row already exists and this path is a plain refresh — works flawlessly, while every fresh install
|
|
148421
|
+
(a new container, a new machine, a wiped `~/.fusion`) can never complete its first login.
|
|
148422
|
+
|
|
148423
|
+
Create when absent, update when present. A callback returning undefined still writes nothing, so
|
|
148424
|
+
pi's refresh-bails-out behaviour is unchanged.
|
|
148425
|
+
*/
|
|
148358
148426
|
async modify(provider, fn2) {
|
|
148359
148427
|
this.assertRefFromKey(provider);
|
|
148360
148428
|
return this.withLock(async (current) => {
|
|
148361
|
-
const target = this.resolveWriteTarget(provider, current,
|
|
148362
|
-
if (!target
|
|
148363
|
-
const
|
|
148429
|
+
const target = this.resolveWriteTarget(provider, current, true);
|
|
148430
|
+
if (!target) return { result: void 0, changed: false };
|
|
148431
|
+
const existing = this.credential(target, current);
|
|
148432
|
+
const next = await fn2(existing);
|
|
148364
148433
|
if (next !== void 0) {
|
|
148365
148434
|
current[formatProviderInstanceKey(target)] = next;
|
|
148366
148435
|
return { result: next, changed: true };
|
|
148367
148436
|
}
|
|
148368
|
-
return { result:
|
|
148437
|
+
return { result: existing, changed: false };
|
|
148369
148438
|
});
|
|
148370
148439
|
}
|
|
148371
148440
|
getOAuthProviders() {
|
|
@@ -148378,11 +148447,24 @@ var init_auth_storage = __esm({
|
|
|
148378
148447
|
if (!this.modelRuntime) throw new Error("OAuth login requires a ModelRuntime-backed Fusion auth storage");
|
|
148379
148448
|
const executionProvider = toExecutionModelProviderId(provider);
|
|
148380
148449
|
const legacy = callbacks;
|
|
148381
|
-
const interaction = {
|
|
148382
|
-
|
|
148383
|
-
|
|
148384
|
-
|
|
148385
|
-
|
|
148450
|
+
const interaction = {
|
|
148451
|
+
signal: legacy.signal,
|
|
148452
|
+
prompt: async (prompt) => {
|
|
148453
|
+
if (prompt.type === "select") {
|
|
148454
|
+
const chosen = await legacy.onSelect?.({ message: prompt.message, options: prompt.options });
|
|
148455
|
+
return chosen ?? prompt.options[0]?.id ?? "";
|
|
148456
|
+
}
|
|
148457
|
+
if (prompt.type === "manual_code" && legacy.onManualCodeInput) {
|
|
148458
|
+
return await legacy.onManualCodeInput();
|
|
148459
|
+
}
|
|
148460
|
+
return await legacy.onPrompt?.({ message: prompt.message, placeholder: "placeholder" in prompt ? prompt.placeholder : void 0 }) ?? "";
|
|
148461
|
+
},
|
|
148462
|
+
notify: (event) => {
|
|
148463
|
+
if (event.type === "auth_url") legacy.onAuth?.({ url: event.url, instructions: event.instructions });
|
|
148464
|
+
else if (event.type === "device_code") legacy.onDeviceCode?.(event);
|
|
148465
|
+
else if (event.type === "progress") legacy.onProgress?.(event.message);
|
|
148466
|
+
}
|
|
148467
|
+
};
|
|
148386
148468
|
await this.modelRuntime.login(executionProvider, "oauth", interaction);
|
|
148387
148469
|
this.reload();
|
|
148388
148470
|
}
|
|
@@ -186396,7 +186478,6 @@ var init_notifier = __esm({
|
|
|
186396
186478
|
}
|
|
186397
186479
|
notifyGridlock(event) {
|
|
186398
186480
|
if (event === null) {
|
|
186399
|
-
this.lastGridlockNotificationAt = null;
|
|
186400
186481
|
return;
|
|
186401
186482
|
}
|
|
186402
186483
|
if (!this.config.enabled || !this.config.topic || !this.isEventEnabled("gridlock")) return;
|
|
@@ -187533,6 +187614,63 @@ var init_agent_user_comments = __esm({
|
|
|
187533
187614
|
}
|
|
187534
187615
|
});
|
|
187535
187616
|
|
|
187617
|
+
// ../engine/src/git-identity.ts
|
|
187618
|
+
function slugifyAgentEmailLocalPart(value) {
|
|
187619
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
187620
|
+
}
|
|
187621
|
+
function resolveCommitIdentity(input = {}) {
|
|
187622
|
+
const { agent, settings } = input;
|
|
187623
|
+
if (settings?.commitAuthorEnabled === false) {
|
|
187624
|
+
return void 0;
|
|
187625
|
+
}
|
|
187626
|
+
const configuredName = settings?.commitAuthorName?.trim();
|
|
187627
|
+
const configuredEmail = settings?.commitAuthorEmail?.trim();
|
|
187628
|
+
if (configuredName && configuredEmail) {
|
|
187629
|
+
return { name: configuredName, email: configuredEmail };
|
|
187630
|
+
}
|
|
187631
|
+
const agentName = agent?.name?.trim() || agent?.id?.trim() || "";
|
|
187632
|
+
if (agentName) {
|
|
187633
|
+
const localPart = slugifyAgentEmailLocalPart(agentName);
|
|
187634
|
+
if (localPart) {
|
|
187635
|
+
return {
|
|
187636
|
+
name: configuredName || `${agentName} (Fusion)`,
|
|
187637
|
+
email: configuredEmail || `${localPart}@agents.fusion.local`
|
|
187638
|
+
};
|
|
187639
|
+
}
|
|
187640
|
+
}
|
|
187641
|
+
return {
|
|
187642
|
+
name: configuredName || FUSION_FALLBACK_IDENTITY.name,
|
|
187643
|
+
email: configuredEmail || FUSION_FALLBACK_IDENTITY.email
|
|
187644
|
+
};
|
|
187645
|
+
}
|
|
187646
|
+
function commitIdentityEnv(identity) {
|
|
187647
|
+
if (!identity) {
|
|
187648
|
+
return {};
|
|
187649
|
+
}
|
|
187650
|
+
return {
|
|
187651
|
+
GIT_AUTHOR_NAME: identity.name,
|
|
187652
|
+
GIT_AUTHOR_EMAIL: identity.email,
|
|
187653
|
+
GIT_COMMITTER_NAME: identity.name,
|
|
187654
|
+
GIT_COMMITTER_EMAIL: identity.email
|
|
187655
|
+
};
|
|
187656
|
+
}
|
|
187657
|
+
function commitIdentityArgs(identity) {
|
|
187658
|
+
if (!identity) {
|
|
187659
|
+
return [];
|
|
187660
|
+
}
|
|
187661
|
+
return ["-c", `user.name=${identity.name}`, "-c", `user.email=${identity.email}`];
|
|
187662
|
+
}
|
|
187663
|
+
var FUSION_FALLBACK_IDENTITY;
|
|
187664
|
+
var init_git_identity = __esm({
|
|
187665
|
+
"../engine/src/git-identity.ts"() {
|
|
187666
|
+
"use strict";
|
|
187667
|
+
FUSION_FALLBACK_IDENTITY = {
|
|
187668
|
+
name: "Fusion",
|
|
187669
|
+
email: "noreply@runfusion.ai"
|
|
187670
|
+
};
|
|
187671
|
+
}
|
|
187672
|
+
});
|
|
187673
|
+
|
|
187536
187674
|
// ../engine/src/sandbox/bubblewrap-detect.ts
|
|
187537
187675
|
import { exec as exec20 } from "node:child_process";
|
|
187538
187676
|
import { promisify as promisify30 } from "node:util";
|
|
@@ -192765,8 +192903,12 @@ import { createHash as createHash29 } from "node:crypto";
|
|
|
192765
192903
|
import { join as join72, resolve as resolve44 } from "node:path";
|
|
192766
192904
|
import { hostname as hostname3 } from "node:os";
|
|
192767
192905
|
import { Type as Type4 } from "typebox";
|
|
192768
|
-
function mergerCommitEnv() {
|
|
192769
|
-
return {
|
|
192906
|
+
function mergerCommitEnv(identity) {
|
|
192907
|
+
return {
|
|
192908
|
+
...process.env,
|
|
192909
|
+
[IDENTITY_GUARD_BYPASS_ENV]: "1",
|
|
192910
|
+
...commitIdentityEnv(identity ?? resolveCommitIdentity())
|
|
192911
|
+
};
|
|
192770
192912
|
}
|
|
192771
192913
|
async function resolveMergerLifecycleColumn(store, taskId, which) {
|
|
192772
192914
|
const fallback = which === "complete" ? "done" : which === "merge" ? "in-review" : "todo";
|
|
@@ -200742,6 +200884,7 @@ var init_merger = __esm({
|
|
|
200742
200884
|
init_worktree_hooks();
|
|
200743
200885
|
init_effective_settings();
|
|
200744
200886
|
init_agent_user_comments();
|
|
200887
|
+
init_git_identity();
|
|
200745
200888
|
init_verification_utils();
|
|
200746
200889
|
init_sandbox();
|
|
200747
200890
|
init_verification_utils();
|
|
@@ -211629,7 +211772,9 @@ function isLegacyCompleteColumnForWorkspaceTeardown(column) {
|
|
|
211629
211772
|
}
|
|
211630
211773
|
var worktreeMetadataReconcileLog = createLogger("worktree-metadata-reconcile");
|
|
211631
211774
|
var yieldEventLoop2 = () => new Promise((resolve48) => setImmediateCb2(resolve48));
|
|
211775
|
+
var DONE_METADATA_REPAIR_CAP = 25;
|
|
211632
211776
|
var DONE_TASK_INTEGRITY_SWEEP_LIMIT = 50;
|
|
211777
|
+
var GIT_WORKTREE_CHURN_INTERVAL_MS = 60 * 60 * 1e3;
|
|
211633
211778
|
var BOARD_STALL_NOTIFICATION_COOLDOWN_MS = 60 * 6e4;
|
|
211634
211779
|
var DB_CORRUPTION_NOTIFICATION_COOLDOWN_MS = 60 * 60 * 1e3;
|
|
211635
211780
|
var PHANTOM_EXECUTOR_BINDING_AGE_MULTIPLIER = 3;
|
|
@@ -211733,7 +211878,10 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
211733
211878
|
lastUnpauseAt = 0;
|
|
211734
211879
|
// ── Maintenance timer ───────────────────────────────────────────────
|
|
211735
211880
|
maintenanceInterval = null;
|
|
211881
|
+
maintenanceStarting = false;
|
|
211736
211882
|
maintenanceRunning = false;
|
|
211883
|
+
/** Last wall-clock a batch-1 git-churn pass ran on this manager (coarse-cadence gate). */
|
|
211884
|
+
lastGitWorktreeChurnAt = 0;
|
|
211737
211885
|
/** In-process belt only; the durable apply token remains the cross-process fence. */
|
|
211738
211886
|
autoRecoverTerminalFailuresInFlight = false;
|
|
211739
211887
|
// ── Event listener cleanup ──────────────────────────────────────────
|
|
@@ -212631,6 +212779,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
212631
212779
|
}
|
|
212632
212780
|
// ── Auto-unpause ───────────────────────────────────────────────────
|
|
212633
212781
|
onSettingsUpdated(settings, previous) {
|
|
212782
|
+
this.syncMaintenanceOnRefresh(settings);
|
|
212634
212783
|
if (!previous.globalPause && settings.globalPause) {
|
|
212635
212784
|
if (!settings.autoUnpauseEnabled) {
|
|
212636
212785
|
log34.log("Global pause activated \u2014 auto-unpause disabled, requires manual intervention");
|
|
@@ -212814,6 +212963,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
212814
212963
|
try {
|
|
212815
212964
|
await this.store.moveTask(taskId, await resolveReboundTargetForTask(this.store, taskId), {
|
|
212816
212965
|
preserveProgress: true,
|
|
212966
|
+
preserveWorktree: true,
|
|
212817
212967
|
preserveStatus: true,
|
|
212818
212968
|
// #1411: backward recovery — skip order-derived adjacency.
|
|
212819
212969
|
moveSource: "engine",
|
|
@@ -212894,7 +213044,23 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
212894
213044
|
}
|
|
212895
213045
|
// ── Periodic maintenance ──────────────────────────────────────────
|
|
212896
213046
|
async startMaintenance() {
|
|
213047
|
+
if (this.maintenanceInterval) return;
|
|
213048
|
+
if (this.maintenanceStarting) return;
|
|
213049
|
+
this.maintenanceStarting = true;
|
|
213050
|
+
try {
|
|
213051
|
+
await this.armMaintenanceInternal();
|
|
213052
|
+
} finally {
|
|
213053
|
+
this.maintenanceStarting = false;
|
|
213054
|
+
}
|
|
213055
|
+
}
|
|
213056
|
+
async armMaintenanceInternal() {
|
|
213057
|
+
if (this.maintenanceInterval) return;
|
|
212897
213058
|
const settings = await this.store.getSettings();
|
|
213059
|
+
if (this.maintenanceInterval) return;
|
|
213060
|
+
if (settings.globalPause || settings.enginePaused) {
|
|
213061
|
+
log34.debug("Periodic maintenance not armed \u2014 engine/global pause is active");
|
|
213062
|
+
return;
|
|
213063
|
+
}
|
|
212898
213064
|
const intervalMs = settings.maintenanceIntervalMs ?? 9e5;
|
|
212899
213065
|
if (intervalMs <= 0) {
|
|
212900
213066
|
log34.debug("Periodic maintenance disabled (maintenanceIntervalMs <= 0)");
|
|
@@ -212905,6 +213071,38 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
212905
213071
|
void this.runMaintenance();
|
|
212906
213072
|
}, intervalMs);
|
|
212907
213073
|
}
|
|
213074
|
+
/*
|
|
213075
|
+
* FNXC:PauseGatedMaintenance 2026-08-13-03:08 (RUFU-076):
|
|
213076
|
+
* Keep the periodic maintenance timer in sync with the engine/global pause state. `onSettingsUpdated`
|
|
213077
|
+
* calls this on every settings:updated event; pausing clears the armed timer (stopping the git churn),
|
|
213078
|
+
* unpausing (re)arms it idempotently via `startMaintenance`'s guard. This is the only writer of the
|
|
213079
|
+
* pause->stop-maintenance transition besides `stop()` teardown.
|
|
213080
|
+
*/
|
|
213081
|
+
/*
|
|
213082
|
+
* FNXC:GitWorktreeChurnCadenceCoarsen 2026-08-13-04:05 (RUFU-076):
|
|
213083
|
+
* Coarse-cadence gate for batch-1 git-churn steps. Returns true only when a full coarse window
|
|
213084
|
+
* (hourly) has elapsed since the last batch-1 git-worktree pass, so an idle/healthy active project
|
|
213085
|
+
* does not re-run `git worktree prune` / `git worktree list` / `git branch` on every maintenance
|
|
213086
|
+
* interval. Note the shared timestamp also bounds cleanup-orphaned-branches and enforce-worktree-cap
|
|
213087
|
+
* even though they live further down batch-1.
|
|
213088
|
+
*/
|
|
213089
|
+
isGitWorktreeChurnDue() {
|
|
213090
|
+
return Date.now() - this.lastGitWorktreeChurnAt >= GIT_WORKTREE_CHURN_INTERVAL_MS;
|
|
213091
|
+
}
|
|
213092
|
+
syncMaintenanceOnRefresh(settings) {
|
|
213093
|
+
const paused = settings.globalPause || settings.enginePaused;
|
|
213094
|
+
if (paused) {
|
|
213095
|
+
if (this.maintenanceInterval) {
|
|
213096
|
+
clearInterval(this.maintenanceInterval);
|
|
213097
|
+
this.maintenanceInterval = null;
|
|
213098
|
+
log34.debug("Periodic maintenance paused \u2014 cleared maintenance timer");
|
|
213099
|
+
}
|
|
213100
|
+
return;
|
|
213101
|
+
}
|
|
213102
|
+
if (!this.maintenanceInterval) {
|
|
213103
|
+
void this.startMaintenance();
|
|
213104
|
+
}
|
|
213105
|
+
}
|
|
212908
213106
|
/*
|
|
212909
213107
|
FNXC:CrossProcessDeleteObservation 2026-08-01-11:39:
|
|
212910
213108
|
Periodic self-healing owns outbox retention. Each already-open PostgreSQL project is gated to
|
|
@@ -213241,17 +213439,26 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
213241
213439
|
log34.debug("Maintenance cycle starting");
|
|
213242
213440
|
try {
|
|
213243
213441
|
const settings = await this.store.getSettings();
|
|
213442
|
+
const maintenancePaused = settings.globalPause || settings.enginePaused;
|
|
213443
|
+
const gitWorktreeChurnDue = this.isGitWorktreeChurnDue();
|
|
213444
|
+
if (!maintenancePaused && gitWorktreeChurnDue) {
|
|
213445
|
+
this.lastGitWorktreeChurnAt = Date.now();
|
|
213446
|
+
}
|
|
213244
213447
|
const batch1Fns = [
|
|
213245
|
-
{
|
|
213448
|
+
{
|
|
213449
|
+
name: "prune-worktrees",
|
|
213450
|
+
fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.pruneWorktrees()
|
|
213451
|
+
},
|
|
213246
213452
|
{
|
|
213247
213453
|
name: "prune-task-lifecycle-events",
|
|
213248
213454
|
fn: async () => this.pruneTaskLifecycleEventsForMaintenance()
|
|
213249
213455
|
},
|
|
213250
213456
|
{ name: "prune-github-check-states", fn: async () => this.pruneGitHubCheckStatesForMaintenance() },
|
|
213251
|
-
{ name: "cleanup-orphans", fn: () => this.cleanupOrphans() },
|
|
213457
|
+
{ name: "cleanup-orphans", fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.cleanupOrphans() },
|
|
213252
213458
|
{
|
|
213253
213459
|
name: "cleanup-stale-temp-merge-worktrees",
|
|
213254
213460
|
fn: async () => {
|
|
213461
|
+
if (maintenancePaused || !gitWorktreeChurnDue) return 0;
|
|
213255
213462
|
const cleaned = await this.cleanupStaleTempMergeWorktrees();
|
|
213256
213463
|
if (cleaned > 0) {
|
|
213257
213464
|
log34.debug(`Cleaned ${cleaned} stale AI merge temp worktree(s)`);
|
|
@@ -213259,7 +213466,10 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
213259
213466
|
return cleaned;
|
|
213260
213467
|
}
|
|
213261
213468
|
},
|
|
213262
|
-
{
|
|
213469
|
+
{
|
|
213470
|
+
name: "cleanup-orphaned-branches",
|
|
213471
|
+
fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.cleanupOrphanedBranches()
|
|
213472
|
+
},
|
|
213263
213473
|
{
|
|
213264
213474
|
name: "reconcile-orphaned-task-dirs",
|
|
213265
213475
|
fn: async () => {
|
|
@@ -213367,7 +213577,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
213367
213577
|
},
|
|
213368
213578
|
{ name: "fts-maintenance", fn: () => this.maintainTaskFts() },
|
|
213369
213579
|
{ name: "checkpoint-wal", fn: () => Promise.resolve(this.checkpointWal()) },
|
|
213370
|
-
{ name: "enforce-worktree-cap", fn: () => this.enforceWorktreeCap() }
|
|
213580
|
+
{ name: "enforce-worktree-cap", fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.enforceWorktreeCap() }
|
|
213371
213581
|
];
|
|
213372
213582
|
for (const fn2 of batch1Fns) {
|
|
213373
213583
|
try {
|
|
@@ -214649,6 +214859,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
214649
214859
|
moveSource: "engine",
|
|
214650
214860
|
// #1411: backward recovery — skip order-derived adjacency.
|
|
214651
214861
|
recoveryRehome: true,
|
|
214862
|
+
// worktree-discard-intended: reclaim proved the branch already merged / has zero unique commits; the checkout holds nothing worth keeping and worktree was explicitly nulled above.
|
|
214652
214863
|
preserveProgress: true,
|
|
214653
214864
|
preserveResumeState: true
|
|
214654
214865
|
});
|
|
@@ -214739,6 +214950,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
214739
214950
|
moveSource: "engine",
|
|
214740
214951
|
// #1411: backward recovery — skip order-derived adjacency.
|
|
214741
214952
|
recoveryRehome: true,
|
|
214953
|
+
// worktree-discard-intended: reclaim proved the branch already merged / has zero unique commits; the checkout holds nothing worth keeping and worktree was explicitly nulled above.
|
|
214742
214954
|
preserveProgress: true,
|
|
214743
214955
|
preserveResumeState: true
|
|
214744
214956
|
});
|
|
@@ -215535,7 +215747,18 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
215535
215747
|
const withUniqueWork = existingCandidates.filter((candidate) => candidate.aheadCount > 0);
|
|
215536
215748
|
if (withUniqueWork.length === 1) {
|
|
215537
215749
|
const selected = withUniqueWork[0];
|
|
215538
|
-
|
|
215750
|
+
let preservedWorktree = false;
|
|
215751
|
+
if (task.worktree && existsSync58(task.worktree)) {
|
|
215752
|
+
try {
|
|
215753
|
+
const { stdout } = await execAsync18("git rev-parse --abbrev-ref HEAD", {
|
|
215754
|
+
cwd: task.worktree,
|
|
215755
|
+
timeout: 3e4
|
|
215756
|
+
});
|
|
215757
|
+
preservedWorktree = stdout.trim() === selected.branch;
|
|
215758
|
+
} catch {
|
|
215759
|
+
}
|
|
215760
|
+
}
|
|
215761
|
+
const patch = preservedWorktree ? { branch: selected.branch } : { branch: selected.branch, worktree: null };
|
|
215539
215762
|
if (!task.baseCommitSha) {
|
|
215540
215763
|
const derivedBaseCommit = (await execAsync18(
|
|
215541
215764
|
`git merge-base ${shellQuote2(integrationBase)} ${shellQuote2(selected.branch)}`,
|
|
@@ -215574,7 +215797,8 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
215574
215797
|
aheadCount: selected.aheadCount,
|
|
215575
215798
|
integrationBase,
|
|
215576
215799
|
source: "auto-rebind-in-review",
|
|
215577
|
-
previousBranch: task.branch ?? null
|
|
215800
|
+
previousBranch: task.branch ?? null,
|
|
215801
|
+
preservedWorktree
|
|
215578
215802
|
}
|
|
215579
215803
|
});
|
|
215580
215804
|
result.repaired++;
|
|
@@ -215584,7 +215808,8 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
215584
215808
|
branch: selected.branch,
|
|
215585
215809
|
aheadCount: selected.aheadCount,
|
|
215586
215810
|
integrationBase,
|
|
215587
|
-
previousBranch: task.branch ?? null
|
|
215811
|
+
previousBranch: task.branch ?? null,
|
|
215812
|
+
preservedWorktree
|
|
215588
215813
|
});
|
|
215589
215814
|
continue;
|
|
215590
215815
|
}
|
|
@@ -217116,7 +217341,8 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
217116
217341
|
*/
|
|
217117
217342
|
recoveryRehome: true,
|
|
217118
217343
|
bypassGuards: true,
|
|
217119
|
-
preserveProgress: true
|
|
217344
|
+
preserveProgress: true,
|
|
217345
|
+
preserveWorktree: true
|
|
217120
217346
|
});
|
|
217121
217347
|
rehomed += 1;
|
|
217122
217348
|
await createRunAuditor(this.store, {
|
|
@@ -217754,7 +217980,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
217754
217980
|
await this.emitBackwardMoveNoAction(task, "finalize-no-op-review", "task:finalize-no-op-review-no-action", proof);
|
|
217755
217981
|
continue;
|
|
217756
217982
|
}
|
|
217757
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
217983
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
217758
217984
|
continue;
|
|
217759
217985
|
}
|
|
217760
217986
|
const mergedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -217804,7 +218030,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
217804
218030
|
baseRef: classification.baseRef,
|
|
217805
218031
|
lane: "self-healing-finalize-no-op-review"
|
|
217806
218032
|
});
|
|
217807
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
218033
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
217808
218034
|
recovered++;
|
|
217809
218035
|
continue;
|
|
217810
218036
|
}
|
|
@@ -217823,7 +218049,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
217823
218049
|
classification: "proven-no-op",
|
|
217824
218050
|
baseRef: classification.baseRef
|
|
217825
218051
|
});
|
|
217826
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
218052
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
217827
218053
|
recovered++;
|
|
217828
218054
|
continue;
|
|
217829
218055
|
}
|
|
@@ -218366,7 +218592,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
218366
218592
|
task.id,
|
|
218367
218593
|
"Auto-recovered: in-review task still had incomplete steps \u2014 moved back to todo for retry"
|
|
218368
218594
|
);
|
|
218369
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
218595
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
218370
218596
|
log34.log(`Recovered stale incomplete review task ${task.id}: moved back to todo`);
|
|
218371
218597
|
recovered++;
|
|
218372
218598
|
} catch (err) {
|
|
@@ -218760,7 +218986,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
218760
218986
|
task.id,
|
|
218761
218987
|
"Auto-recovered: in-review task idle past stuck-task timeout \u2014 kicked back to todo"
|
|
218762
218988
|
);
|
|
218763
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
218989
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
218764
218990
|
log34.log(`Kicked ghost review task ${task.id} back to todo`);
|
|
218765
218991
|
recovered++;
|
|
218766
218992
|
} catch (err) {
|
|
@@ -219684,8 +219910,9 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
219684
219910
|
return Boolean(task.baseCommitSha);
|
|
219685
219911
|
});
|
|
219686
219912
|
if (candidates.length === 0) return 0;
|
|
219913
|
+
const batch = candidates.slice(0, DONE_METADATA_REPAIR_CAP);
|
|
219687
219914
|
let repaired = 0;
|
|
219688
|
-
for (const task of
|
|
219915
|
+
for (const task of batch) {
|
|
219689
219916
|
if (isWorkspaceTask(task)) continue;
|
|
219690
219917
|
if (task.mergeDetails?.landedFilesAttributionRestricted || task.mergeDetails?.noOpVerifiedShortCircuit) {
|
|
219691
219918
|
log34.debug(`recoverDoneTaskMergeMetadata: skipped ${task.id} \u2014 attribution-restricted`);
|
|
@@ -221342,7 +221569,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
221342
221569
|
nextRecoveryAt: new Date(Date.now() + delayMs).toISOString()
|
|
221343
221570
|
},
|
|
221344
221571
|
targetColumn: await resolveReboundTargetForTask(this.store, task.id),
|
|
221345
|
-
moveOptions: { preserveProgress: true, moveSource: "engine" }
|
|
221572
|
+
moveOptions: { preserveProgress: true, preserveWorktree: true, moveSource: "engine" }
|
|
221346
221573
|
});
|
|
221347
221574
|
if (applied.outcome === "applied") {
|
|
221348
221575
|
await this.store.logEntry(task.id, `Auto-recovered generic terminal failure (attempt ${claim.attempt}/${MAX_TERMINAL_FAILURE_AUTO_RETRIES})`);
|
|
@@ -221484,6 +221711,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
221484
221711
|
if (route.kind === "node-requeue" && fresh.column !== requeueTarget) {
|
|
221485
221712
|
await this.store.moveTask(task.id, requeueTarget, {
|
|
221486
221713
|
preserveProgress: true,
|
|
221714
|
+
preserveWorktree: true,
|
|
221487
221715
|
moveSource: "engine",
|
|
221488
221716
|
recoveryRehome: true
|
|
221489
221717
|
});
|
|
@@ -221717,6 +221945,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
221717
221945
|
const leaseRecovered = await this.options.leaseManager.recoverAbandonedLease(
|
|
221718
221946
|
task.id,
|
|
221719
221947
|
`in-progress limbo: ${describeWorktreeState(task)} + null branch`,
|
|
221948
|
+
// worktree-discard-intended: limbo recovery — the worktree is already missing or its metadata cleared; there is no live checkout to hold.
|
|
221720
221949
|
{ preserveProgress: true }
|
|
221721
221950
|
);
|
|
221722
221951
|
if (!leaseRecovered) {
|
|
@@ -222902,7 +223131,7 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
222902
223131
|
task.id,
|
|
222903
223132
|
`Auto-retry ${nextCount}/${MAX_TASK_DONE_RETRIES}: agent finished without fn_task_done \u2014 requeuing to todo to resume partial work`
|
|
222904
223133
|
);
|
|
222905
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
223134
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
222906
223135
|
recovered++;
|
|
222907
223136
|
} catch (err) {
|
|
222908
223137
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
@@ -265940,6 +266169,7 @@ init_auth_storage();
|
|
|
265940
266169
|
init_merger();
|
|
265941
266170
|
|
|
265942
266171
|
// ../engine/src/merge/merger-ai.ts
|
|
266172
|
+
init_git_identity();
|
|
265943
266173
|
init_src2();
|
|
265944
266174
|
init_agent_user_comments();
|
|
265945
266175
|
init_worktree_names();
|
|
@@ -266938,7 +267168,7 @@ async function ensureCommitTaskMetadata(mergeRoot, taskId, includeTaskId, traile
|
|
|
266938
267168
|
const needsPrefix = includeTaskId && !subject.toLowerCase().startsWith(taskId.toLowerCase());
|
|
266939
267169
|
const missingTrailers = trailers.filter((t) => !fullMessage.includes(t));
|
|
266940
267170
|
if (!needsPrefix && missingTrailers.length === 0) return;
|
|
266941
|
-
const args = ["-c", "trailer.ifExists=addIfDifferent", "commit", "--amend"];
|
|
267171
|
+
const args = [...commitIdentityArgs(resolveCommitIdentity()), "-c", "trailer.ifExists=addIfDifferent", "commit", "--amend"];
|
|
266942
267172
|
if (needsPrefix) {
|
|
266943
267173
|
args.push("-m", `${taskId}: ${subject}`);
|
|
266944
267174
|
if (body.trim()) args.push("-m", body);
|