@runfusion/fusion 0.77.0-beta.0 → 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 +387 -72
- package/dist/child-process-worker.js +2479 -2196
- package/dist/client/.vite/manifest.json +262 -262
- package/dist/client/assets/{AgentDetailView-0G9qFd4j.js → AgentDetailView-Dew3af1O.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-BM68g7wo.js → AgentPermissionPolicyEditor-CxPQffiY.js} +1 -1
- package/dist/client/assets/{AgentsView-DkOUZWw4.js → AgentsView-Cr4LDGdt.js} +3 -3
- package/dist/client/assets/ChatView-cNYtYx05.js +13 -0
- package/dist/client/assets/{CommandCenter-DxRSFWNc.js → CommandCenter-DCC90LOP.js} +1 -1
- package/dist/client/assets/{DevServerView-DO-bqJFE.js → DevServerView-B5b520w6.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-Cp2gddTE.js → DirectoryPicker-1JvRd5mC.js} +1 -1
- package/dist/client/assets/{DocumentsView-D0E-3G96.js → DocumentsView-ksK9f7xt.js} +1 -1
- package/dist/client/assets/{EvalsView-BoFVq5hw.js → EvalsView-a3LhgRSo.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CS1Sdogm.js → ExperimentalAgentOnboardingModal-vdVa8h7F.js} +1 -1
- package/dist/client/assets/{GoalsView-sybf7JY4.js → GoalsView-Dz2o91fd.js} +1 -1
- package/dist/client/assets/{InsightsView-nHa7aShn.js → InsightsView-De3R_46d.js} +1 -1
- package/dist/client/assets/{MemoryView-D0IG44za.js → MemoryView-Cagk2wZG.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-CU76weJe.js → PiExtensionsManager-C9JABO_4.js} +1 -1
- package/dist/client/assets/{PluginManager-DyT8XbcG.js → PluginManager-D2csmdQa.js} +1 -1
- package/dist/client/assets/{PullRequestView-CnxWUSen.js → PullRequestView-DT8vTeVi.js} +1 -1
- package/dist/client/assets/{ReportModal-CMrmMQjD.js → ReportModal-YMP6V4vu.js} +1 -1
- package/dist/client/assets/{ResearchView-BTytQSgy.js → ResearchView-cNsjYu8F.js} +1 -1
- package/dist/client/assets/{SecretsView-BuSH5J87.js → SecretsView-BAmf7KyS.js} +1 -1
- package/dist/client/assets/{SessionTerminal-D04kYRrT.js → SessionTerminal-BjGcxq22.js} +1 -1
- package/dist/client/assets/{SettingsModal-Dm-ngbRr.js → SettingsModal-C_9RiEI7.js} +1 -1
- package/dist/client/assets/{SettingsModal-xSLhH7Tr.js → SettingsModal-DLfy2e_5.js} +4 -4
- package/dist/client/assets/{SettingsTextareaRow-CHPgocEp.js → SettingsTextareaRow-D8RHSj8b.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-y88aXNIQ.js → SetupWizardModal-DRJ96pHQ.js} +2 -2
- package/dist/client/assets/{SkillsView-CYyQW1Hv.js → SkillsView-DyeCwYit.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-hYeoz1X8.js → WorkflowNodeEditor-C5Jc9w_A.js} +3 -3
- package/dist/client/assets/{agent-import-generation-CjiYXzCr.js → agent-import-generation-SCPNeF25.js} +1 -1
- package/dist/client/assets/{agentsOrgChartLayout-C0UP_X3z.js → agentsOrgChartLayout-CqKtNCjy.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-Dd6GPcqM.js → architectureDiagram-3BPJPVTR-Cz2HYn0b.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-CC6pLxlz.js → blockDiagram-GPEHLZMM-IimJVscG.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-DxMP_l6y.js → c4Diagram-AAUBKEIU-C-xii7zn.js} +1 -1
- package/dist/client/assets/channel-D-UHgx8G.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BKYToL43.js → chunk-2J33WTMH-DQ-9Xccu.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-Bg6rjQb3.js → chunk-4BX2VUAB-DmdAX9Bx.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CPUwbbGa.js → chunk-55IACEB6-IF2bk5IL.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DScQBCvv.js → chunk-727SXJPM-AeYpIzVu.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DbX7uaXK.js → chunk-AQP2D5EJ-DV942DD9.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DvYKea1c.js → chunk-FMBD7UC4-Bt_riVlZ.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-CH-Tvw7w.js → chunk-ND2GUHAM-CbyjNbXR.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-CbyEvOoM.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-BPB5fV3A.js → cose-bilkent-S5V4N54A-UCvthviL.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-CilYJ3rR.js → dagre-BM42HDAG-DnMlT1Oi.js} +1 -1
- package/dist/client/assets/{dashboard-view-dChSM_So.js → dashboard-view-C9D0aoRW.js} +1 -1
- package/dist/client/assets/dashboard-view-Cz0sp2Wl.js +1 -0
- package/dist/client/assets/{dashboard-view-DoLU6FxZ.js → dashboard-view-JysoyDRX.js} +1 -1
- package/dist/client/assets/{dashboard-view-DnVf3tmI.js → dashboard-view-myjM9tr8.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-m9u1Qhyx.js → diagram-2AECGRRQ-BYFiqXGw.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-DVr7Kf0N.js → diagram-5GNKFQAL-DZU3pSYq.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-D7sgJDFx.js → diagram-KO2AKTUF-0ybdKuMm.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DNKNDS6r.js → diagram-LMA3HP47-Rxbgnbsp.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-1Bff4FWn.js → diagram-OG6HWLK6-BAU_hTeV.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DGua1UHN.js → erDiagram-TEJ5UH35-zr8HrwTt.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-UDfDtwsE.js → flowDiagram-I6XJVG4X-CrTw0iFw.js} +1 -1
- package/dist/client/assets/{folder-open-CteOypVk.js → folder-open-DnAlsXXn.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-COdmD328.js → ganttDiagram-6RSMTGT7-CCORsxxz.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-SUSls7Kw.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-e_DloXj7.js → infoDiagram-5YYISTIA-hAeccD_4.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DVWqihXg.js → ishikawaDiagram-YF4QCWOH-WLCzv-NH.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BcPY-XP0.js → journeyDiagram-JHISSGLW-ClnasNhy.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-BCFG2Jle.js → kanban-definition-UN3LZRKU-CAuARhUz.js} +1 -1
- package/dist/client/assets/{mermaid.core-5yPje9Bi.js → mermaid.core-Bh02RvfX.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DDApeT3K.js → mindmap-definition-RKZ34NQL-KNTlbW4V.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-N61_jyeP.js → pieDiagram-4H26LBE5-BouAfBEw.js} +1 -1
- package/dist/client/assets/{puzzle-BkaCP30D.js → puzzle-CC8Ur3Cy.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-C5qHiApF.js → quadrantDiagram-W4KKPZXB-wTdkCUJU.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-C71okgzt.js → requirementDiagram-4Y6WPE33-BnjY4Tc_.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-B2iKyLjB.js → sankeyDiagram-5OEKKPKP-C-QsS08u.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-DfdoYKKk.js → sequenceDiagram-3UESZ5HK-DD36MILE.js} +1 -1
- package/dist/client/assets/{shield-alert-BNSeDB8l.js → shield-alert-DcXc56Fy.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-pZtzo1lK.js → standing-instructions-template-BF5y1BLz.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-lS-sUi12.js → stateDiagram-AJRCARHV-WTq1wQr1.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-DXJNDrV9.js → stateDiagram-v2-BHNVJYJU-eILJdjII.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CCwvX81K.js → timeline-definition-PNZ67QCA-PRNwI0NR.js} +1 -1
- package/dist/client/assets/{upload-CDovVbu2.js → upload-qH_64O-B.js} +1 -1
- package/dist/client/assets/{useDiscoveredSkillsCache-BYqP-afh.js → useDiscoveredSkillsCache-C-GPCNaO.js} +1 -1
- package/dist/client/assets/{users-CTqECGLo.js → users-D2UesRE4.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DaiR5nv9.js → vennDiagram-CIIHVFJN-CG2Z4T4O.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-hA5IHyPW.js → wardley-L42UT6IY-gO_fGvF9.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CILUNESc.js → wardleyDiagram-YWT4CUSO-BkyNpjUb.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-72eNMmjz.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 +345 -61
- 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/ChatView-BPSm2JIH.js +0 -13
- package/dist/client/assets/channel-DlCEMoEf.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-Bc92O8Ks.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Bc92O8Ks.js +0 -1
- package/dist/client/assets/dashboard-view-BnGe8cWo.js +0 -1
- package/dist/client/assets/index-0ovTXt3t.css +0 -1
- package/dist/client/assets/index-DpCHwyiD.js +0 -2818
package/dist/bin.js
CHANGED
|
@@ -16882,8 +16882,34 @@ function didFallBackToDefault(ir2) {
|
|
|
16882
16882
|
async function resolveWorkflowIrForTaskWithProvenance(store, taskId, irCache, selectionCache) {
|
|
16883
16883
|
let workflowId;
|
|
16884
16884
|
try {
|
|
16885
|
-
const
|
|
16886
|
-
|
|
16885
|
+
const isSelectionCached = selectionCache?.has(taskId) ?? false;
|
|
16886
|
+
let selection = isSelectionCached && selectionCache ? selectionCache.get(taskId) : void 0;
|
|
16887
|
+
if (!isSelectionCached) {
|
|
16888
|
+
let inflight;
|
|
16889
|
+
let coalesced = false;
|
|
16890
|
+
if (selectionCache) {
|
|
16891
|
+
inflight = inflightSelectionReads.get(selectionCache);
|
|
16892
|
+
if (!inflight) {
|
|
16893
|
+
inflight = /* @__PURE__ */ new Map();
|
|
16894
|
+
inflightSelectionReads.set(selectionCache, inflight);
|
|
16895
|
+
}
|
|
16896
|
+
const pending = inflight.get(taskId);
|
|
16897
|
+
if (pending) {
|
|
16898
|
+
selection = await pending;
|
|
16899
|
+
coalesced = true;
|
|
16900
|
+
}
|
|
16901
|
+
}
|
|
16902
|
+
if (!coalesced) {
|
|
16903
|
+
const readPromise = store.getTaskWorkflowSelectionAsync ? store.getTaskWorkflowSelectionAsync(taskId) : Promise.resolve(store.getTaskWorkflowSelection(taskId));
|
|
16904
|
+
if (inflight) inflight.set(taskId, readPromise);
|
|
16905
|
+
try {
|
|
16906
|
+
selection = await readPromise;
|
|
16907
|
+
} finally {
|
|
16908
|
+
inflight?.delete(taskId);
|
|
16909
|
+
}
|
|
16910
|
+
}
|
|
16911
|
+
selectionCache?.set(taskId, selection);
|
|
16912
|
+
}
|
|
16887
16913
|
workflowId = selection?.workflowId;
|
|
16888
16914
|
} catch {
|
|
16889
16915
|
return { ir: defaultCodingWorkflowIr(), source: "default" };
|
|
@@ -16907,13 +16933,14 @@ async function isTaskTerminalNodeIdAsync(store, taskId, nodeId) {
|
|
|
16907
16933
|
}
|
|
16908
16934
|
return nodeId === "end";
|
|
16909
16935
|
}
|
|
16910
|
-
var FELL_BACK_TO_DEFAULT;
|
|
16936
|
+
var inflightSelectionReads, FELL_BACK_TO_DEFAULT;
|
|
16911
16937
|
var init_workflow_ir_resolver = __esm({
|
|
16912
16938
|
"../core/src/workflows/workflow-ir-resolver.ts"() {
|
|
16913
16939
|
"use strict";
|
|
16914
16940
|
init_builtin_workflows();
|
|
16915
16941
|
init_workflow_ir();
|
|
16916
16942
|
init_workflow_prompt_overrides();
|
|
16943
|
+
inflightSelectionReads = /* @__PURE__ */ new WeakMap();
|
|
16917
16944
|
FELL_BACK_TO_DEFAULT = /* @__PURE__ */ Symbol.for("fusion.workflowIr.fellBackToDefault");
|
|
16918
16945
|
}
|
|
16919
16946
|
});
|
|
@@ -36534,9 +36561,12 @@ async function markApprovalRequestCompleted(layer, requestId, input) {
|
|
|
36534
36561
|
});
|
|
36535
36562
|
}
|
|
36536
36563
|
async function getApprovalAuditHistory(handle2, requestId, projectId2) {
|
|
36537
|
-
const
|
|
36538
|
-
|
|
36539
|
-
|
|
36564
|
+
const eventType = project_exports.approvalRequestAuditEvents.eventType;
|
|
36565
|
+
const lifecycleRank = sql`CASE ${eventType} ${sql.join(
|
|
36566
|
+
APPROVAL_REQUEST_AUDIT_EVENT_TYPES.map((type, rank) => sql`WHEN ${type} THEN ${rank}`),
|
|
36567
|
+
sql` `
|
|
36568
|
+
)} ELSE ${APPROVAL_REQUEST_AUDIT_EVENT_TYPES.length} END`;
|
|
36569
|
+
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`);
|
|
36540
36570
|
return rows.map((row) => rowToAuditEvent(row));
|
|
36541
36571
|
}
|
|
36542
36572
|
var init_async_approval_request_store = __esm({
|
|
@@ -140804,17 +140834,40 @@ var init_auth_storage = __esm({
|
|
|
140804
140834
|
async getApiKey(provider, instance) {
|
|
140805
140835
|
return resolveStoredCredentialApiKey(provider, instance ? this.getInstance(instance) : this.get(provider));
|
|
140806
140836
|
}
|
|
140837
|
+
/*
|
|
140838
|
+
FNXC:ProviderAuth 2026-08-18-04:40:
|
|
140839
|
+
MODIFY MUST BE ABLE TO CREATE. This is the seam pi persists a COMPLETED LOGIN through
|
|
140840
|
+
(`Models.login` -> `credentials.modify(provider.id, ...)` in pi-ai's models.js), not just the seam
|
|
140841
|
+
it refreshes an existing token through.
|
|
140842
|
+
|
|
140843
|
+
It used to resolve its write target with `creating: false` and then bail —
|
|
140844
|
+
`if (!target || !this.credential(target, current)) return { changed: false }` — whenever the
|
|
140845
|
+
provider had no credential row yet. The callback was never invoked, nothing was written, and pi's
|
|
140846
|
+
login resolved as a SUCCESS. So a first-ever login for a provider could not be saved: the browser
|
|
140847
|
+
flow completed, the token exchange succeeded, the lock file was taken and released, `auth.json`
|
|
140848
|
+
stayed `{}`, and the dashboard's poll saw `authenticated: false` and reported the useless "Login
|
|
140849
|
+
did not complete. Please try again."
|
|
140850
|
+
|
|
140851
|
+
It looked provider-specific and environment-specific for the worst possible reason: it only
|
|
140852
|
+
reproduces on a store with NO existing row, so every developer and every long-lived install — where
|
|
140853
|
+
a row already exists and this path is a plain refresh — works flawlessly, while every fresh install
|
|
140854
|
+
(a new container, a new machine, a wiped `~/.fusion`) can never complete its first login.
|
|
140855
|
+
|
|
140856
|
+
Create when absent, update when present. A callback returning undefined still writes nothing, so
|
|
140857
|
+
pi's refresh-bails-out behaviour is unchanged.
|
|
140858
|
+
*/
|
|
140807
140859
|
async modify(provider, fn2) {
|
|
140808
140860
|
this.assertRefFromKey(provider);
|
|
140809
140861
|
return this.withLock(async (current) => {
|
|
140810
|
-
const target = this.resolveWriteTarget(provider, current,
|
|
140811
|
-
if (!target
|
|
140812
|
-
const
|
|
140862
|
+
const target = this.resolveWriteTarget(provider, current, true);
|
|
140863
|
+
if (!target) return { result: void 0, changed: false };
|
|
140864
|
+
const existing = this.credential(target, current);
|
|
140865
|
+
const next = await fn2(existing);
|
|
140813
140866
|
if (next !== void 0) {
|
|
140814
140867
|
current[formatProviderInstanceKey(target)] = next;
|
|
140815
140868
|
return { result: next, changed: true };
|
|
140816
140869
|
}
|
|
140817
|
-
return { result:
|
|
140870
|
+
return { result: existing, changed: false };
|
|
140818
140871
|
});
|
|
140819
140872
|
}
|
|
140820
140873
|
getOAuthProviders() {
|
|
@@ -140827,11 +140880,24 @@ var init_auth_storage = __esm({
|
|
|
140827
140880
|
if (!this.modelRuntime) throw new Error("OAuth login requires a ModelRuntime-backed Fusion auth storage");
|
|
140828
140881
|
const executionProvider = toExecutionModelProviderId(provider);
|
|
140829
140882
|
const legacy = callbacks;
|
|
140830
|
-
const interaction = {
|
|
140831
|
-
|
|
140832
|
-
|
|
140833
|
-
|
|
140834
|
-
|
|
140883
|
+
const interaction = {
|
|
140884
|
+
signal: legacy.signal,
|
|
140885
|
+
prompt: async (prompt) => {
|
|
140886
|
+
if (prompt.type === "select") {
|
|
140887
|
+
const chosen = await legacy.onSelect?.({ message: prompt.message, options: prompt.options });
|
|
140888
|
+
return chosen ?? prompt.options[0]?.id ?? "";
|
|
140889
|
+
}
|
|
140890
|
+
if (prompt.type === "manual_code" && legacy.onManualCodeInput) {
|
|
140891
|
+
return await legacy.onManualCodeInput();
|
|
140892
|
+
}
|
|
140893
|
+
return await legacy.onPrompt?.({ message: prompt.message, placeholder: "placeholder" in prompt ? prompt.placeholder : void 0 }) ?? "";
|
|
140894
|
+
},
|
|
140895
|
+
notify: (event) => {
|
|
140896
|
+
if (event.type === "auth_url") legacy.onAuth?.({ url: event.url, instructions: event.instructions });
|
|
140897
|
+
else if (event.type === "device_code") legacy.onDeviceCode?.(event);
|
|
140898
|
+
else if (event.type === "progress") legacy.onProgress?.(event.message);
|
|
140899
|
+
}
|
|
140900
|
+
};
|
|
140835
140901
|
await this.modelRuntime.login(executionProvider, "oauth", interaction);
|
|
140836
140902
|
this.reload();
|
|
140837
140903
|
}
|
|
@@ -144506,7 +144572,8 @@ var init_runtime_resolution = __esm({
|
|
|
144506
144572
|
const result2 = await createFnAgent2({
|
|
144507
144573
|
...agentOptions,
|
|
144508
144574
|
toolOutputMaxChars,
|
|
144509
|
-
mcpServers: normalizeAgentRuntimeMcpServers(mcpServers)
|
|
144575
|
+
mcpServers: normalizeAgentRuntimeMcpServers(mcpServers),
|
|
144576
|
+
__rawPiSession: true
|
|
144510
144577
|
});
|
|
144511
144578
|
return {
|
|
144512
144579
|
...result2,
|
|
@@ -145696,6 +145763,7 @@ var init_agent_session_helpers = __esm({
|
|
|
145696
145763
|
init_runtime_resolution();
|
|
145697
145764
|
init_logger3();
|
|
145698
145765
|
init_pi();
|
|
145766
|
+
init_pi();
|
|
145699
145767
|
init_auth_storage();
|
|
145700
145768
|
init_mock_provider();
|
|
145701
145769
|
init_cli_provider_routing();
|
|
@@ -145703,6 +145771,12 @@ var init_agent_session_helpers = __esm({
|
|
|
145703
145771
|
sessionLog = createLogger2("agent-session");
|
|
145704
145772
|
mockRuntimeSingleton = new MockAgentRuntime();
|
|
145705
145773
|
RUNTIMES_WITH_INTERNAL_TOOL_GATING = /* @__PURE__ */ new Set(["pi"]);
|
|
145774
|
+
try {
|
|
145775
|
+
registerRoutedAgentSessionFactory?.(
|
|
145776
|
+
createResolvedAgentSession
|
|
145777
|
+
);
|
|
145778
|
+
} catch {
|
|
145779
|
+
}
|
|
145706
145780
|
}
|
|
145707
145781
|
});
|
|
145708
145782
|
|
|
@@ -167249,7 +167323,49 @@ function withMcpPromptOptions(promptOptions, mcpServers) {
|
|
|
167249
167323
|
}
|
|
167250
167324
|
return { mcpServers };
|
|
167251
167325
|
}
|
|
167326
|
+
function agentPluginRunnerRegistry() {
|
|
167327
|
+
return defaultAgentPluginRunners ??= /* @__PURE__ */ new Map();
|
|
167328
|
+
}
|
|
167329
|
+
function registerRoutedAgentSessionFactory(factory) {
|
|
167330
|
+
routedAgentSessionFactory = factory;
|
|
167331
|
+
}
|
|
167332
|
+
function registerDefaultAgentPluginRunner(rootDir, pluginRunner) {
|
|
167333
|
+
agentPluginRunnerRegistry().set(rootDir, pluginRunner);
|
|
167334
|
+
}
|
|
167335
|
+
function unregisterDefaultAgentPluginRunner(rootDir) {
|
|
167336
|
+
agentPluginRunnerRegistry().delete(rootDir);
|
|
167337
|
+
}
|
|
167338
|
+
function resolveDefaultAgentPluginRunner(cwd) {
|
|
167339
|
+
const registry3 = agentPluginRunnerRegistry();
|
|
167340
|
+
if (registry3.size === 0) return void 0;
|
|
167341
|
+
if (cwd) {
|
|
167342
|
+
let best;
|
|
167343
|
+
for (const [rootDir, runner] of registry3) {
|
|
167344
|
+
if ((cwd === rootDir || cwd.startsWith(`${rootDir}/`)) && (!best || rootDir.length > best.rootDir.length)) {
|
|
167345
|
+
best = { rootDir, runner };
|
|
167346
|
+
}
|
|
167347
|
+
}
|
|
167348
|
+
if (best) return best.runner;
|
|
167349
|
+
}
|
|
167350
|
+
if (registry3.size === 1) {
|
|
167351
|
+
return registry3.values().next().value;
|
|
167352
|
+
}
|
|
167353
|
+
return void 0;
|
|
167354
|
+
}
|
|
167252
167355
|
async function createFnAgent2(options) {
|
|
167356
|
+
const { __rawPiSession, ...routableOptions } = options;
|
|
167357
|
+
if (!__rawPiSession && routedAgentSessionFactory) {
|
|
167358
|
+
const optionsWithRouting = routableOptions;
|
|
167359
|
+
const pluginRunner = optionsWithRouting.pluginRunner ?? resolveDefaultAgentPluginRunner(routableOptions.cwd);
|
|
167360
|
+
return routedAgentSessionFactory({
|
|
167361
|
+
...routableOptions,
|
|
167362
|
+
sessionPurpose: routableOptions.sessionPurpose ?? "executor",
|
|
167363
|
+
...pluginRunner ? { pluginRunner } : {}
|
|
167364
|
+
});
|
|
167365
|
+
}
|
|
167366
|
+
return createPiAgentSessionRaw(routableOptions);
|
|
167367
|
+
}
|
|
167368
|
+
async function createPiAgentSessionRaw(options) {
|
|
167253
167369
|
piLog.debug(`createFnAgent called (tools=${options.tools}, provider=${options.defaultProvider}, model=${options.defaultModelId})`);
|
|
167254
167370
|
const requestedMcpServers = options.mcpServers ?? [];
|
|
167255
167371
|
const forwardedMcpServers = runtimeSupportsMcp("pi", options.defaultProvider) ? requestedMcpServers : [];
|
|
@@ -167806,7 +167922,7 @@ async function createFnAgent2(options) {
|
|
|
167806
167922
|
settleFallbackDispatch: async () => void 0
|
|
167807
167923
|
};
|
|
167808
167924
|
}
|
|
167809
|
-
var execAsync, RTK_ACCEPTED_REWRITE_EXIT_CODES, RTK_EXPECTED_PASSTHROUGH_EXIT_CODES, RTK_EXPECTED_FAIL_OPEN_ERROR_CODES, RTK_REWRITE_MAX_BUFFER_BYTES, hostExtensionPaths, FN_MEMORY_APPEND_TOOL_NAME, FUSION_SHUTDOWN_WRAP_FLAG, promptWithFallbackInFlight, COMPACTION_FALLBACK_INSTRUCTIONS, MAX_COMPACTED_PROMPT_MEMORY_CHARS, MAX_COMPACTED_SUBTASK_GUIDANCE_CHARS, MAX_COMPACTED_ATTACHMENTS_CHARS, MAX_COMPACTED_EXISTING_SPEC_CHARS, MAX_COMPACTED_TASK_PROMPT_CHARS, MAX_COMPACTED_USER_COMMENTS_CHARS, ModelFallbackExhaustedError, GATE_BYPASS_TOOL_NAMES, TOOL_OUTPUT_BUDGET_OVERRIDES;
|
|
167925
|
+
var execAsync, RTK_ACCEPTED_REWRITE_EXIT_CODES, RTK_EXPECTED_PASSTHROUGH_EXIT_CODES, RTK_EXPECTED_FAIL_OPEN_ERROR_CODES, RTK_REWRITE_MAX_BUFFER_BYTES, hostExtensionPaths, FN_MEMORY_APPEND_TOOL_NAME, FUSION_SHUTDOWN_WRAP_FLAG, promptWithFallbackInFlight, COMPACTION_FALLBACK_INSTRUCTIONS, MAX_COMPACTED_PROMPT_MEMORY_CHARS, MAX_COMPACTED_SUBTASK_GUIDANCE_CHARS, MAX_COMPACTED_ATTACHMENTS_CHARS, MAX_COMPACTED_EXISTING_SPEC_CHARS, MAX_COMPACTED_TASK_PROMPT_CHARS, MAX_COMPACTED_USER_COMMENTS_CHARS, ModelFallbackExhaustedError, GATE_BYPASS_TOOL_NAMES, TOOL_OUTPUT_BUDGET_OVERRIDES, routedAgentSessionFactory, defaultAgentPluginRunners;
|
|
167810
167926
|
var init_pi = __esm({
|
|
167811
167927
|
"../engine/src/pi.ts"() {
|
|
167812
167928
|
"use strict";
|
|
@@ -178484,9 +178600,9 @@ function mergeParkedColumns(base, lanes) {
|
|
|
178484
178600
|
terminal: /* @__PURE__ */ new Set([...base.terminal, ...lanes.terminal ?? [], complete, archived])
|
|
178485
178601
|
};
|
|
178486
178602
|
}
|
|
178487
|
-
async function resolveTaskParkedColumns(store, taskId) {
|
|
178603
|
+
async function resolveTaskParkedColumns(store, taskId, selectionCache) {
|
|
178488
178604
|
try {
|
|
178489
|
-
const ir2 = await resolveWorkflowIrForTask(store, taskId);
|
|
178605
|
+
const ir2 = await resolveWorkflowIrForTask(store, taskId, void 0, selectionCache);
|
|
178490
178606
|
const l = resolveLifecycleColumns(ir2);
|
|
178491
178607
|
const complete = l?.complete ?? LEGACY_PARKED_COLUMNS2.complete;
|
|
178492
178608
|
const archived = l?.archived ?? LEGACY_PARKED_COLUMNS2.archived;
|
|
@@ -178731,6 +178847,7 @@ var init_scheduler = __esm({
|
|
|
178731
178847
|
}
|
|
178732
178848
|
});
|
|
178733
178849
|
this.store.on("task:moved", async ({ task, from, to: to2, source, lanes }) => {
|
|
178850
|
+
const movedSelectionCache = /* @__PURE__ */ new Map();
|
|
178734
178851
|
this.lastAutoClaimFingerprint.set(task.id, computeAutoClaimFingerprint(task));
|
|
178735
178852
|
const parked = mergeParkedColumns(LEGACY_PARKED_COLUMNS2, lanes);
|
|
178736
178853
|
if (from === parked.hold || to2 === parked.hold) {
|
|
@@ -178786,7 +178903,7 @@ var init_scheduler = __esm({
|
|
|
178786
178903
|
});
|
|
178787
178904
|
}
|
|
178788
178905
|
}
|
|
178789
|
-
const resolvedParked = mergeParkedColumns(await resolveTaskParkedColumns(this.store, task.id), lanes);
|
|
178906
|
+
const resolvedParked = mergeParkedColumns(await resolveTaskParkedColumns(this.store, task.id, movedSelectionCache), lanes);
|
|
178790
178907
|
if (resolvedParked.terminal.has(to2)) {
|
|
178791
178908
|
try {
|
|
178792
178909
|
const settings = await this.store.getSettings();
|
|
@@ -178852,6 +178969,7 @@ var init_scheduler = __esm({
|
|
|
178852
178969
|
}
|
|
178853
178970
|
});
|
|
178854
178971
|
this.store.on("task:updated", (task, meta2) => {
|
|
178972
|
+
const updatedSelectionCache = /* @__PURE__ */ new Map();
|
|
178855
178973
|
const nextFingerprint = computeAutoClaimFingerprint(task);
|
|
178856
178974
|
const previousFingerprint = this.lastAutoClaimFingerprint.get(task.id);
|
|
178857
178975
|
if (!previousFingerprint || previousFingerprint !== nextFingerprint) {
|
|
@@ -178882,7 +179000,7 @@ var init_scheduler = __esm({
|
|
|
178882
179000
|
});
|
|
178883
179001
|
}
|
|
178884
179002
|
void (async () => {
|
|
178885
|
-
const unpausedParked = await resolveTaskParkedColumns(this.store, task.id);
|
|
179003
|
+
const unpausedParked = await resolveTaskParkedColumns(this.store, task.id, updatedSelectionCache);
|
|
178886
179004
|
if (this.running && unpausedParked.wake.has(task.column)) {
|
|
178887
179005
|
schedulerLog.log(`Task ${task.id} unpaused \u2014 triggering scheduling`);
|
|
178888
179006
|
void this.schedule();
|
|
@@ -178894,7 +179012,7 @@ var init_scheduler = __esm({
|
|
|
178894
179012
|
} else if (this.planningTaskIds.has(task.id)) {
|
|
178895
179013
|
this.planningTaskIds.delete(task.id);
|
|
178896
179014
|
void (async () => {
|
|
178897
|
-
const planningParked = await resolveTaskParkedColumns(this.store, task.id);
|
|
179015
|
+
const planningParked = await resolveTaskParkedColumns(this.store, task.id, updatedSelectionCache);
|
|
178898
179016
|
if (this.running && !task.status && !task.paused && !task.userPaused && planningParked.wake.has(task.column)) {
|
|
178899
179017
|
schedulerLog.log(`Task ${task.id} finished planning \u2014 triggering scheduling`);
|
|
178900
179018
|
void this.schedule();
|
|
@@ -178907,7 +179025,7 @@ var init_scheduler = __esm({
|
|
|
178907
179025
|
} 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))) {
|
|
178908
179026
|
this.approvalReleasedTaskIds.add(task.id);
|
|
178909
179027
|
void (async () => {
|
|
178910
|
-
const approvalParked = await resolveTaskParkedColumns(this.store, task.id);
|
|
179028
|
+
const approvalParked = await resolveTaskParkedColumns(this.store, task.id, updatedSelectionCache);
|
|
178911
179029
|
if (this.running && !task.status && !task.paused && !task.userPaused && approvalParked.wake.has(task.column)) {
|
|
178912
179030
|
schedulerLog.log(`Task ${task.id} plan approval cleared \u2014 triggering scheduling`);
|
|
178913
179031
|
void this.schedule();
|
|
@@ -178946,7 +179064,8 @@ var init_scheduler = __esm({
|
|
|
178946
179064
|
if (settings.globalPause || settings.enginePaused) {
|
|
178947
179065
|
return;
|
|
178948
179066
|
}
|
|
178949
|
-
const
|
|
179067
|
+
const deletedSelectionCache = /* @__PURE__ */ new Map();
|
|
179068
|
+
const deletedParked = await resolveTaskParkedColumns(this.store, task.id, deletedSelectionCache);
|
|
178950
179069
|
const deletedWipColumns = await resolveProjectColumnsForRoles(this.store, ["countsTowardWip"]);
|
|
178951
179070
|
const todoTasks = await this.store.listTasks({ column: deletedParked.hold, slim: true });
|
|
178952
179071
|
const inProgressById = /* @__PURE__ */ new Map();
|
|
@@ -179155,7 +179274,16 @@ var init_scheduler = __esm({
|
|
|
179155
179274
|
}
|
|
179156
179275
|
}
|
|
179157
179276
|
async transitionQueuedEpisode(task, input) {
|
|
179158
|
-
|
|
179277
|
+
if (typeof this.store.transitionQueuedEpisode === "function") {
|
|
179278
|
+
return (await this.store.transitionQueuedEpisode(task.id, input)).appended;
|
|
179279
|
+
}
|
|
179280
|
+
await this.store.updateTask(task.id, {
|
|
179281
|
+
status: "queued",
|
|
179282
|
+
blockedBy: input.blockedBy ?? null,
|
|
179283
|
+
overlapBlockedBy: input.overlapBlockedBy ?? null
|
|
179284
|
+
});
|
|
179285
|
+
await this.logDispatchQueuedReason(task.id, input.action);
|
|
179286
|
+
return true;
|
|
179159
179287
|
}
|
|
179160
179288
|
async logDispatchQueuedReason(taskId, reason, memoKey) {
|
|
179161
179289
|
const key = `${taskId}:${memoKey ?? reason}`;
|
|
@@ -179207,13 +179335,14 @@ var init_scheduler = __esm({
|
|
|
179207
179335
|
}
|
|
179208
179336
|
async emitHighOverlapFanoutWarnings(tasks2) {
|
|
179209
179337
|
const escalationIrCache = /* @__PURE__ */ new Map();
|
|
179338
|
+
const escalationSelectionCache = /* @__PURE__ */ new Map();
|
|
179210
179339
|
const escalationByTaskId = /* @__PURE__ */ new Map();
|
|
179211
179340
|
const escalationColumns = /* @__PURE__ */ new Set();
|
|
179212
179341
|
const holdByTaskId = /* @__PURE__ */ new Map();
|
|
179213
179342
|
const terminalByTaskId = /* @__PURE__ */ new Map();
|
|
179214
179343
|
const blockerReviewColumns = /* @__PURE__ */ new Set();
|
|
179215
179344
|
for (const task of tasks2) {
|
|
179216
|
-
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, escalationIrCache).catch(() => void 0);
|
|
179345
|
+
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, escalationIrCache, escalationSelectionCache).catch(() => void 0);
|
|
179217
179346
|
if (!ir2) continue;
|
|
179218
179347
|
for (const id of columnsWithFlag(ir2, "countsTowardWip")) escalationColumns.add(id);
|
|
179219
179348
|
for (const id of columnsWithFlag(ir2, "mergeOrchestration")) escalationColumns.add(id);
|
|
@@ -179283,9 +179412,10 @@ var init_scheduler = __esm({
|
|
|
179283
179412
|
if (!agentStore) return;
|
|
179284
179413
|
const runningAgents = await agentStore.listAgents({ state: "running", includeEphemeral: false });
|
|
179285
179414
|
const linkedAgents = runningAgents.filter((agent) => agent.taskId === taskId);
|
|
179415
|
+
const rollbackSelectionCache = /* @__PURE__ */ new Map();
|
|
179286
179416
|
for (const agent of linkedAgents) {
|
|
179287
179417
|
const activeRun = await agentStore.getActiveHeartbeatRun?.(agent.id);
|
|
179288
|
-
const rollbackParked = await resolveTaskParkedColumns(this.store, taskId);
|
|
179418
|
+
const rollbackParked = await resolveTaskParkedColumns(this.store, taskId, rollbackSelectionCache);
|
|
179289
179419
|
const proof = evaluateParkedAgentTaskLink({
|
|
179290
179420
|
agent,
|
|
179291
179421
|
linkedTask: { column: rollbackParked.hold },
|
|
@@ -179333,11 +179463,12 @@ var init_scheduler = __esm({
|
|
|
179333
179463
|
const repo = getCurrentRepo(this.store.getRootDir());
|
|
179334
179464
|
if (!repo) return;
|
|
179335
179465
|
const hydrationIrCache = /* @__PURE__ */ new Map();
|
|
179466
|
+
const hydrationSelectionCache = /* @__PURE__ */ new Map();
|
|
179336
179467
|
for (const task of tasks2) {
|
|
179337
179468
|
if (!task.prInfo) continue;
|
|
179338
179469
|
let flags;
|
|
179339
179470
|
try {
|
|
179340
|
-
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, hydrationIrCache);
|
|
179471
|
+
const ir2 = await resolveWorkflowIrForTask(this.store, task.id, hydrationIrCache, hydrationSelectionCache);
|
|
179341
179472
|
const column = ir2.columns?.find((candidate) => candidate.id === task.column);
|
|
179342
179473
|
if (column) flags = resolveColumnFlags(column);
|
|
179343
179474
|
} catch {
|
|
@@ -180266,19 +180397,20 @@ var init_scheduler = __esm({
|
|
|
180266
180397
|
return;
|
|
180267
180398
|
}
|
|
180268
180399
|
const sliceIdBeforeUpdate = feature.sliceId;
|
|
180269
|
-
|
|
180270
|
-
|
|
180271
|
-
|
|
180272
|
-
|
|
180273
|
-
|
|
180274
|
-
|
|
180275
|
-
|
|
180276
|
-
|
|
180277
|
-
|
|
180400
|
+
let missionId = task.missionId;
|
|
180401
|
+
try {
|
|
180402
|
+
if (!missionId && typeof missionStore.getSlice === "function") {
|
|
180403
|
+
const featureSlice = await missionStore.getSlice(feature.sliceId);
|
|
180404
|
+
const milestone = featureSlice && typeof missionStore.getMilestone === "function" ? await missionStore.getMilestone(featureSlice.milestoneId) : void 0;
|
|
180405
|
+
missionId = milestone?.missionId;
|
|
180406
|
+
}
|
|
180407
|
+
if (!missionId) {
|
|
180408
|
+
schedulerLog.warn(`Task ${taskId} feature ${feature.id} has no resolvable mission; skipping reconciliation`);
|
|
180409
|
+
} else if (missionId !== task.missionId) {
|
|
180278
180410
|
await reconcileMissionState({ taskStore: this.store, missionStore }, { missionId, source: "task-move" });
|
|
180279
|
-
} catch (error3) {
|
|
180280
|
-
schedulerLog.warn(`Mission reconciliation failed after resolving task ${taskId}; continuing mission completion handling:`, error3);
|
|
180281
180411
|
}
|
|
180412
|
+
} catch (error3) {
|
|
180413
|
+
schedulerLog.warn(`Task ${taskId} feature ${feature.id} mission reconcile skipped (${String(error3)}); continuing to completion check`);
|
|
180282
180414
|
}
|
|
180283
180415
|
let completionFlags;
|
|
180284
180416
|
try {
|
|
@@ -187947,7 +188079,6 @@ var init_notifier = __esm({
|
|
|
187947
188079
|
}
|
|
187948
188080
|
notifyGridlock(event) {
|
|
187949
188081
|
if (event === null) {
|
|
187950
|
-
this.lastGridlockNotificationAt = null;
|
|
187951
188082
|
return;
|
|
187952
188083
|
}
|
|
187953
188084
|
if (!this.config.enabled || !this.config.topic || !this.isEventEnabled("gridlock")) return;
|
|
@@ -198763,6 +198894,63 @@ var init_agent_user_comments = __esm({
|
|
|
198763
198894
|
}
|
|
198764
198895
|
});
|
|
198765
198896
|
|
|
198897
|
+
// ../engine/src/git-identity.ts
|
|
198898
|
+
function slugifyAgentEmailLocalPart(value2) {
|
|
198899
|
+
return value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
198900
|
+
}
|
|
198901
|
+
function resolveCommitIdentity(input = {}) {
|
|
198902
|
+
const { agent, settings } = input;
|
|
198903
|
+
if (settings?.commitAuthorEnabled === false) {
|
|
198904
|
+
return void 0;
|
|
198905
|
+
}
|
|
198906
|
+
const configuredName = settings?.commitAuthorName?.trim();
|
|
198907
|
+
const configuredEmail = settings?.commitAuthorEmail?.trim();
|
|
198908
|
+
if (configuredName && configuredEmail) {
|
|
198909
|
+
return { name: configuredName, email: configuredEmail };
|
|
198910
|
+
}
|
|
198911
|
+
const agentName = agent?.name?.trim() || agent?.id?.trim() || "";
|
|
198912
|
+
if (agentName) {
|
|
198913
|
+
const localPart = slugifyAgentEmailLocalPart(agentName);
|
|
198914
|
+
if (localPart) {
|
|
198915
|
+
return {
|
|
198916
|
+
name: configuredName || `${agentName} (Fusion)`,
|
|
198917
|
+
email: configuredEmail || `${localPart}@agents.fusion.local`
|
|
198918
|
+
};
|
|
198919
|
+
}
|
|
198920
|
+
}
|
|
198921
|
+
return {
|
|
198922
|
+
name: configuredName || FUSION_FALLBACK_IDENTITY.name,
|
|
198923
|
+
email: configuredEmail || FUSION_FALLBACK_IDENTITY.email
|
|
198924
|
+
};
|
|
198925
|
+
}
|
|
198926
|
+
function commitIdentityEnv(identity) {
|
|
198927
|
+
if (!identity) {
|
|
198928
|
+
return {};
|
|
198929
|
+
}
|
|
198930
|
+
return {
|
|
198931
|
+
GIT_AUTHOR_NAME: identity.name,
|
|
198932
|
+
GIT_AUTHOR_EMAIL: identity.email,
|
|
198933
|
+
GIT_COMMITTER_NAME: identity.name,
|
|
198934
|
+
GIT_COMMITTER_EMAIL: identity.email
|
|
198935
|
+
};
|
|
198936
|
+
}
|
|
198937
|
+
function commitIdentityArgs(identity) {
|
|
198938
|
+
if (!identity) {
|
|
198939
|
+
return [];
|
|
198940
|
+
}
|
|
198941
|
+
return ["-c", `user.name=${identity.name}`, "-c", `user.email=${identity.email}`];
|
|
198942
|
+
}
|
|
198943
|
+
var FUSION_FALLBACK_IDENTITY;
|
|
198944
|
+
var init_git_identity = __esm({
|
|
198945
|
+
"../engine/src/git-identity.ts"() {
|
|
198946
|
+
"use strict";
|
|
198947
|
+
FUSION_FALLBACK_IDENTITY = {
|
|
198948
|
+
name: "Fusion",
|
|
198949
|
+
email: "noreply@runfusion.ai"
|
|
198950
|
+
};
|
|
198951
|
+
}
|
|
198952
|
+
});
|
|
198953
|
+
|
|
198766
198954
|
// ../engine/src/sandbox/bubblewrap-detect.ts
|
|
198767
198955
|
import { exec as exec20 } from "node:child_process";
|
|
198768
198956
|
import { promisify as promisify30 } from "node:util";
|
|
@@ -204000,8 +204188,12 @@ import { createHash as createHash29 } from "node:crypto";
|
|
|
204000
204188
|
import { join as join73, resolve as resolve45 } from "node:path";
|
|
204001
204189
|
import { hostname as hostname3 } from "node:os";
|
|
204002
204190
|
import { Type as Type4 } from "typebox";
|
|
204003
|
-
function mergerCommitEnv() {
|
|
204004
|
-
return {
|
|
204191
|
+
function mergerCommitEnv(identity) {
|
|
204192
|
+
return {
|
|
204193
|
+
...process.env,
|
|
204194
|
+
[IDENTITY_GUARD_BYPASS_ENV]: "1",
|
|
204195
|
+
...commitIdentityEnv(identity ?? resolveCommitIdentity())
|
|
204196
|
+
};
|
|
204005
204197
|
}
|
|
204006
204198
|
async function resolveMergerLifecycleColumn(store, taskId, which) {
|
|
204007
204199
|
const fallback2 = which === "complete" ? "done" : which === "merge" ? "in-review" : "todo";
|
|
@@ -211977,6 +212169,7 @@ var init_merger = __esm({
|
|
|
211977
212169
|
init_worktree_hooks();
|
|
211978
212170
|
init_effective_settings();
|
|
211979
212171
|
init_agent_user_comments();
|
|
212172
|
+
init_git_identity();
|
|
211980
212173
|
init_verification_utils();
|
|
211981
212174
|
init_sandbox();
|
|
211982
212175
|
init_verification_utils();
|
|
@@ -212172,7 +212365,7 @@ function hasTerminalInvalidDoneTransition(task) {
|
|
|
212172
212365
|
function isPrincipalHeldPlanningStatusOwned(status) {
|
|
212173
212366
|
return status === null || status === void 0;
|
|
212174
212367
|
}
|
|
212175
|
-
var log34, worktreeMetadataReconcileLog, yieldEventLoop2, DONE_TASK_INTEGRITY_SWEEP_LIMIT, BOARD_STALL_NOTIFICATION_COOLDOWN_MS, DB_CORRUPTION_NOTIFICATION_COOLDOWN_MS, PHANTOM_EXECUTOR_BINDING_AGE_MULTIPLIER, MAX_NO_PROGRESS_RESUME_ATTEMPTS, PRE_EXECUTION_WORKTREE_MAX_IDLE_MS, APPROVED_TRIAGE_RECOVERY_GRACE_MS, STARVED_REFINEMENT_RECOVERY_GRACE_MS, STARVED_PEER_PROGRESS_THRESHOLD, STARVED_REFINEMENT_ESCALATION_COOLDOWN_MS, ORPHANED_EXECUTION_RECOVERY_GRACE_MS, STALLED_CARD_WATCHDOG_MS, LEAKED_WORKTREE_SLOT_GRACE_MS, NON_TERMINAL_STEP_STATUSES2, STRANDED_COMPLETED_TODO_ACTIVE_STATUSES, GHOST_REVIEW_PRESERVED_STATUSES, ORPHANED_WITH_WORKTREE_GRACE_MS, MAX_TASK_DONE_RETRIES, RECONCILE_SCOPE_OVERRIDE_MERGE_ACTIVE_STATUS_SET, MAX_STARVATION_DROPS, TERMINAL_WORKSPACE_WORKTREE_TEARDOWN_MIN_IDLE_MS, DEADLOCK_RECOVERY_COOLDOWN_MS, DEFAULT_STALE_MERGING_FANOUT_MIN_AGE_MS, DEFAULT_UNBACKED_MERGING_FANOUT_GRACE_MS, DURABLE_ERROR_RECOVERY_BASE_COOLDOWN_MS, DURABLE_ERROR_RECOVERY_MAX_COOLDOWN_MS, RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS, UNREADABLE_WORKFLOW_SELECTION, SelfHealingManager;
|
|
212368
|
+
var log34, worktreeMetadataReconcileLog, yieldEventLoop2, DONE_METADATA_REPAIR_CAP, DONE_TASK_INTEGRITY_SWEEP_LIMIT, GIT_WORKTREE_CHURN_INTERVAL_MS, BOARD_STALL_NOTIFICATION_COOLDOWN_MS, DB_CORRUPTION_NOTIFICATION_COOLDOWN_MS, PHANTOM_EXECUTOR_BINDING_AGE_MULTIPLIER, MAX_NO_PROGRESS_RESUME_ATTEMPTS, PRE_EXECUTION_WORKTREE_MAX_IDLE_MS, APPROVED_TRIAGE_RECOVERY_GRACE_MS, STARVED_REFINEMENT_RECOVERY_GRACE_MS, STARVED_PEER_PROGRESS_THRESHOLD, STARVED_REFINEMENT_ESCALATION_COOLDOWN_MS, ORPHANED_EXECUTION_RECOVERY_GRACE_MS, STALLED_CARD_WATCHDOG_MS, LEAKED_WORKTREE_SLOT_GRACE_MS, NON_TERMINAL_STEP_STATUSES2, STRANDED_COMPLETED_TODO_ACTIVE_STATUSES, GHOST_REVIEW_PRESERVED_STATUSES, ORPHANED_WITH_WORKTREE_GRACE_MS, MAX_TASK_DONE_RETRIES, RECONCILE_SCOPE_OVERRIDE_MERGE_ACTIVE_STATUS_SET, MAX_STARVATION_DROPS, TERMINAL_WORKSPACE_WORKTREE_TEARDOWN_MIN_IDLE_MS, DEADLOCK_RECOVERY_COOLDOWN_MS, DEFAULT_STALE_MERGING_FANOUT_MIN_AGE_MS, DEFAULT_UNBACKED_MERGING_FANOUT_GRACE_MS, DURABLE_ERROR_RECOVERY_BASE_COOLDOWN_MS, DURABLE_ERROR_RECOVERY_MAX_COOLDOWN_MS, RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS, UNREADABLE_WORKFLOW_SELECTION, SelfHealingManager;
|
|
212176
212369
|
var init_self_healing = __esm({
|
|
212177
212370
|
"../engine/src/self-healing.ts"() {
|
|
212178
212371
|
"use strict";
|
|
@@ -212235,7 +212428,9 @@ var init_self_healing = __esm({
|
|
|
212235
212428
|
log34 = createLogger2("self-healing");
|
|
212236
212429
|
worktreeMetadataReconcileLog = createLogger2("worktree-metadata-reconcile");
|
|
212237
212430
|
yieldEventLoop2 = () => new Promise((resolve112) => setImmediateCb2(resolve112));
|
|
212431
|
+
DONE_METADATA_REPAIR_CAP = 25;
|
|
212238
212432
|
DONE_TASK_INTEGRITY_SWEEP_LIMIT = 50;
|
|
212433
|
+
GIT_WORKTREE_CHURN_INTERVAL_MS = 60 * 60 * 1e3;
|
|
212239
212434
|
BOARD_STALL_NOTIFICATION_COOLDOWN_MS = 60 * 6e4;
|
|
212240
212435
|
DB_CORRUPTION_NOTIFICATION_COOLDOWN_MS = 60 * 60 * 1e3;
|
|
212241
212436
|
PHANTOM_EXECUTOR_BINDING_AGE_MULTIPLIER = 3;
|
|
@@ -212291,7 +212486,10 @@ var init_self_healing = __esm({
|
|
|
212291
212486
|
lastUnpauseAt = 0;
|
|
212292
212487
|
// ── Maintenance timer ───────────────────────────────────────────────
|
|
212293
212488
|
maintenanceInterval = null;
|
|
212489
|
+
maintenanceStarting = false;
|
|
212294
212490
|
maintenanceRunning = false;
|
|
212491
|
+
/** Last wall-clock a batch-1 git-churn pass ran on this manager (coarse-cadence gate). */
|
|
212492
|
+
lastGitWorktreeChurnAt = 0;
|
|
212295
212493
|
/** In-process belt only; the durable apply token remains the cross-process fence. */
|
|
212296
212494
|
autoRecoverTerminalFailuresInFlight = false;
|
|
212297
212495
|
// ── Event listener cleanup ──────────────────────────────────────────
|
|
@@ -213189,6 +213387,7 @@ var init_self_healing = __esm({
|
|
|
213189
213387
|
}
|
|
213190
213388
|
// ── Auto-unpause ───────────────────────────────────────────────────
|
|
213191
213389
|
onSettingsUpdated(settings, previous) {
|
|
213390
|
+
this.syncMaintenanceOnRefresh(settings);
|
|
213192
213391
|
if (!previous.globalPause && settings.globalPause) {
|
|
213193
213392
|
if (!settings.autoUnpauseEnabled) {
|
|
213194
213393
|
log34.log("Global pause activated \u2014 auto-unpause disabled, requires manual intervention");
|
|
@@ -213372,6 +213571,7 @@ var init_self_healing = __esm({
|
|
|
213372
213571
|
try {
|
|
213373
213572
|
await this.store.moveTask(taskId, await resolveReboundTargetForTask(this.store, taskId), {
|
|
213374
213573
|
preserveProgress: true,
|
|
213574
|
+
preserveWorktree: true,
|
|
213375
213575
|
preserveStatus: true,
|
|
213376
213576
|
// #1411: backward recovery — skip order-derived adjacency.
|
|
213377
213577
|
moveSource: "engine",
|
|
@@ -213452,7 +213652,23 @@ var init_self_healing = __esm({
|
|
|
213452
213652
|
}
|
|
213453
213653
|
// ── Periodic maintenance ──────────────────────────────────────────
|
|
213454
213654
|
async startMaintenance() {
|
|
213655
|
+
if (this.maintenanceInterval) return;
|
|
213656
|
+
if (this.maintenanceStarting) return;
|
|
213657
|
+
this.maintenanceStarting = true;
|
|
213658
|
+
try {
|
|
213659
|
+
await this.armMaintenanceInternal();
|
|
213660
|
+
} finally {
|
|
213661
|
+
this.maintenanceStarting = false;
|
|
213662
|
+
}
|
|
213663
|
+
}
|
|
213664
|
+
async armMaintenanceInternal() {
|
|
213665
|
+
if (this.maintenanceInterval) return;
|
|
213455
213666
|
const settings = await this.store.getSettings();
|
|
213667
|
+
if (this.maintenanceInterval) return;
|
|
213668
|
+
if (settings.globalPause || settings.enginePaused) {
|
|
213669
|
+
log34.debug("Periodic maintenance not armed \u2014 engine/global pause is active");
|
|
213670
|
+
return;
|
|
213671
|
+
}
|
|
213456
213672
|
const intervalMs = settings.maintenanceIntervalMs ?? 9e5;
|
|
213457
213673
|
if (intervalMs <= 0) {
|
|
213458
213674
|
log34.debug("Periodic maintenance disabled (maintenanceIntervalMs <= 0)");
|
|
@@ -213463,6 +213679,38 @@ var init_self_healing = __esm({
|
|
|
213463
213679
|
void this.runMaintenance();
|
|
213464
213680
|
}, intervalMs);
|
|
213465
213681
|
}
|
|
213682
|
+
/*
|
|
213683
|
+
* FNXC:PauseGatedMaintenance 2026-08-13-03:08 (RUFU-076):
|
|
213684
|
+
* Keep the periodic maintenance timer in sync with the engine/global pause state. `onSettingsUpdated`
|
|
213685
|
+
* calls this on every settings:updated event; pausing clears the armed timer (stopping the git churn),
|
|
213686
|
+
* unpausing (re)arms it idempotently via `startMaintenance`'s guard. This is the only writer of the
|
|
213687
|
+
* pause->stop-maintenance transition besides `stop()` teardown.
|
|
213688
|
+
*/
|
|
213689
|
+
/*
|
|
213690
|
+
* FNXC:GitWorktreeChurnCadenceCoarsen 2026-08-13-04:05 (RUFU-076):
|
|
213691
|
+
* Coarse-cadence gate for batch-1 git-churn steps. Returns true only when a full coarse window
|
|
213692
|
+
* (hourly) has elapsed since the last batch-1 git-worktree pass, so an idle/healthy active project
|
|
213693
|
+
* does not re-run `git worktree prune` / `git worktree list` / `git branch` on every maintenance
|
|
213694
|
+
* interval. Note the shared timestamp also bounds cleanup-orphaned-branches and enforce-worktree-cap
|
|
213695
|
+
* even though they live further down batch-1.
|
|
213696
|
+
*/
|
|
213697
|
+
isGitWorktreeChurnDue() {
|
|
213698
|
+
return Date.now() - this.lastGitWorktreeChurnAt >= GIT_WORKTREE_CHURN_INTERVAL_MS;
|
|
213699
|
+
}
|
|
213700
|
+
syncMaintenanceOnRefresh(settings) {
|
|
213701
|
+
const paused = settings.globalPause || settings.enginePaused;
|
|
213702
|
+
if (paused) {
|
|
213703
|
+
if (this.maintenanceInterval) {
|
|
213704
|
+
clearInterval(this.maintenanceInterval);
|
|
213705
|
+
this.maintenanceInterval = null;
|
|
213706
|
+
log34.debug("Periodic maintenance paused \u2014 cleared maintenance timer");
|
|
213707
|
+
}
|
|
213708
|
+
return;
|
|
213709
|
+
}
|
|
213710
|
+
if (!this.maintenanceInterval) {
|
|
213711
|
+
void this.startMaintenance();
|
|
213712
|
+
}
|
|
213713
|
+
}
|
|
213466
213714
|
/*
|
|
213467
213715
|
FNXC:CrossProcessDeleteObservation 2026-08-01-11:39:
|
|
213468
213716
|
Periodic self-healing owns outbox retention. Each already-open PostgreSQL project is gated to
|
|
@@ -213799,17 +214047,26 @@ var init_self_healing = __esm({
|
|
|
213799
214047
|
log34.debug("Maintenance cycle starting");
|
|
213800
214048
|
try {
|
|
213801
214049
|
const settings = await this.store.getSettings();
|
|
214050
|
+
const maintenancePaused = settings.globalPause || settings.enginePaused;
|
|
214051
|
+
const gitWorktreeChurnDue = this.isGitWorktreeChurnDue();
|
|
214052
|
+
if (!maintenancePaused && gitWorktreeChurnDue) {
|
|
214053
|
+
this.lastGitWorktreeChurnAt = Date.now();
|
|
214054
|
+
}
|
|
213802
214055
|
const batch1Fns = [
|
|
213803
|
-
{
|
|
214056
|
+
{
|
|
214057
|
+
name: "prune-worktrees",
|
|
214058
|
+
fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.pruneWorktrees()
|
|
214059
|
+
},
|
|
213804
214060
|
{
|
|
213805
214061
|
name: "prune-task-lifecycle-events",
|
|
213806
214062
|
fn: async () => this.pruneTaskLifecycleEventsForMaintenance()
|
|
213807
214063
|
},
|
|
213808
214064
|
{ name: "prune-github-check-states", fn: async () => this.pruneGitHubCheckStatesForMaintenance() },
|
|
213809
|
-
{ name: "cleanup-orphans", fn: () => this.cleanupOrphans() },
|
|
214065
|
+
{ name: "cleanup-orphans", fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.cleanupOrphans() },
|
|
213810
214066
|
{
|
|
213811
214067
|
name: "cleanup-stale-temp-merge-worktrees",
|
|
213812
214068
|
fn: async () => {
|
|
214069
|
+
if (maintenancePaused || !gitWorktreeChurnDue) return 0;
|
|
213813
214070
|
const cleaned = await this.cleanupStaleTempMergeWorktrees();
|
|
213814
214071
|
if (cleaned > 0) {
|
|
213815
214072
|
log34.debug(`Cleaned ${cleaned} stale AI merge temp worktree(s)`);
|
|
@@ -213817,7 +214074,10 @@ var init_self_healing = __esm({
|
|
|
213817
214074
|
return cleaned;
|
|
213818
214075
|
}
|
|
213819
214076
|
},
|
|
213820
|
-
{
|
|
214077
|
+
{
|
|
214078
|
+
name: "cleanup-orphaned-branches",
|
|
214079
|
+
fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.cleanupOrphanedBranches()
|
|
214080
|
+
},
|
|
213821
214081
|
{
|
|
213822
214082
|
name: "reconcile-orphaned-task-dirs",
|
|
213823
214083
|
fn: async () => {
|
|
@@ -213925,7 +214185,7 @@ var init_self_healing = __esm({
|
|
|
213925
214185
|
},
|
|
213926
214186
|
{ name: "fts-maintenance", fn: () => this.maintainTaskFts() },
|
|
213927
214187
|
{ name: "checkpoint-wal", fn: () => Promise.resolve(this.checkpointWal()) },
|
|
213928
|
-
{ name: "enforce-worktree-cap", fn: () => this.enforceWorktreeCap() }
|
|
214188
|
+
{ name: "enforce-worktree-cap", fn: () => maintenancePaused || !gitWorktreeChurnDue ? Promise.resolve(0) : this.enforceWorktreeCap() }
|
|
213929
214189
|
];
|
|
213930
214190
|
for (const fn2 of batch1Fns) {
|
|
213931
214191
|
try {
|
|
@@ -215207,6 +215467,7 @@ var init_self_healing = __esm({
|
|
|
215207
215467
|
moveSource: "engine",
|
|
215208
215468
|
// #1411: backward recovery — skip order-derived adjacency.
|
|
215209
215469
|
recoveryRehome: true,
|
|
215470
|
+
// 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.
|
|
215210
215471
|
preserveProgress: true,
|
|
215211
215472
|
preserveResumeState: true
|
|
215212
215473
|
});
|
|
@@ -215297,6 +215558,7 @@ var init_self_healing = __esm({
|
|
|
215297
215558
|
moveSource: "engine",
|
|
215298
215559
|
// #1411: backward recovery — skip order-derived adjacency.
|
|
215299
215560
|
recoveryRehome: true,
|
|
215561
|
+
// 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.
|
|
215300
215562
|
preserveProgress: true,
|
|
215301
215563
|
preserveResumeState: true
|
|
215302
215564
|
});
|
|
@@ -216093,7 +216355,18 @@ var init_self_healing = __esm({
|
|
|
216093
216355
|
const withUniqueWork = existingCandidates.filter((candidate) => candidate.aheadCount > 0);
|
|
216094
216356
|
if (withUniqueWork.length === 1) {
|
|
216095
216357
|
const selected = withUniqueWork[0];
|
|
216096
|
-
|
|
216358
|
+
let preservedWorktree = false;
|
|
216359
|
+
if (task.worktree && existsSync60(task.worktree)) {
|
|
216360
|
+
try {
|
|
216361
|
+
const { stdout } = await execAsync18("git rev-parse --abbrev-ref HEAD", {
|
|
216362
|
+
cwd: task.worktree,
|
|
216363
|
+
timeout: 3e4
|
|
216364
|
+
});
|
|
216365
|
+
preservedWorktree = stdout.trim() === selected.branch;
|
|
216366
|
+
} catch {
|
|
216367
|
+
}
|
|
216368
|
+
}
|
|
216369
|
+
const patch = preservedWorktree ? { branch: selected.branch } : { branch: selected.branch, worktree: null };
|
|
216097
216370
|
if (!task.baseCommitSha) {
|
|
216098
216371
|
const derivedBaseCommit = (await execAsync18(
|
|
216099
216372
|
`git merge-base ${shellQuote2(integrationBase)} ${shellQuote2(selected.branch)}`,
|
|
@@ -216132,7 +216405,8 @@ var init_self_healing = __esm({
|
|
|
216132
216405
|
aheadCount: selected.aheadCount,
|
|
216133
216406
|
integrationBase,
|
|
216134
216407
|
source: "auto-rebind-in-review",
|
|
216135
|
-
previousBranch: task.branch ?? null
|
|
216408
|
+
previousBranch: task.branch ?? null,
|
|
216409
|
+
preservedWorktree
|
|
216136
216410
|
}
|
|
216137
216411
|
});
|
|
216138
216412
|
result2.repaired++;
|
|
@@ -216142,7 +216416,8 @@ var init_self_healing = __esm({
|
|
|
216142
216416
|
branch: selected.branch,
|
|
216143
216417
|
aheadCount: selected.aheadCount,
|
|
216144
216418
|
integrationBase,
|
|
216145
|
-
previousBranch: task.branch ?? null
|
|
216419
|
+
previousBranch: task.branch ?? null,
|
|
216420
|
+
preservedWorktree
|
|
216146
216421
|
});
|
|
216147
216422
|
continue;
|
|
216148
216423
|
}
|
|
@@ -217674,7 +217949,8 @@ var init_self_healing = __esm({
|
|
|
217674
217949
|
*/
|
|
217675
217950
|
recoveryRehome: true,
|
|
217676
217951
|
bypassGuards: true,
|
|
217677
|
-
preserveProgress: true
|
|
217952
|
+
preserveProgress: true,
|
|
217953
|
+
preserveWorktree: true
|
|
217678
217954
|
});
|
|
217679
217955
|
rehomed += 1;
|
|
217680
217956
|
await createRunAuditor(this.store, {
|
|
@@ -218312,7 +218588,7 @@ var init_self_healing = __esm({
|
|
|
218312
218588
|
await this.emitBackwardMoveNoAction(task, "finalize-no-op-review", "task:finalize-no-op-review-no-action", proof);
|
|
218313
218589
|
continue;
|
|
218314
218590
|
}
|
|
218315
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
218591
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
218316
218592
|
continue;
|
|
218317
218593
|
}
|
|
218318
218594
|
const mergedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -218362,7 +218638,7 @@ var init_self_healing = __esm({
|
|
|
218362
218638
|
baseRef: classification.baseRef,
|
|
218363
218639
|
lane: "self-healing-finalize-no-op-review"
|
|
218364
218640
|
});
|
|
218365
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
218641
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
218366
218642
|
recovered++;
|
|
218367
218643
|
continue;
|
|
218368
218644
|
}
|
|
@@ -218381,7 +218657,7 @@ var init_self_healing = __esm({
|
|
|
218381
218657
|
classification: "proven-no-op",
|
|
218382
218658
|
baseRef: classification.baseRef
|
|
218383
218659
|
});
|
|
218384
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
218660
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
218385
218661
|
recovered++;
|
|
218386
218662
|
continue;
|
|
218387
218663
|
}
|
|
@@ -218924,7 +219200,7 @@ var init_self_healing = __esm({
|
|
|
218924
219200
|
task.id,
|
|
218925
219201
|
"Auto-recovered: in-review task still had incomplete steps \u2014 moved back to todo for retry"
|
|
218926
219202
|
);
|
|
218927
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
219203
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
218928
219204
|
log34.log(`Recovered stale incomplete review task ${task.id}: moved back to todo`);
|
|
218929
219205
|
recovered++;
|
|
218930
219206
|
} catch (err) {
|
|
@@ -219318,7 +219594,7 @@ var init_self_healing = __esm({
|
|
|
219318
219594
|
task.id,
|
|
219319
219595
|
"Auto-recovered: in-review task idle past stuck-task timeout \u2014 kicked back to todo"
|
|
219320
219596
|
);
|
|
219321
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
219597
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
219322
219598
|
log34.log(`Kicked ghost review task ${task.id} back to todo`);
|
|
219323
219599
|
recovered++;
|
|
219324
219600
|
} catch (err) {
|
|
@@ -220242,8 +220518,9 @@ var init_self_healing = __esm({
|
|
|
220242
220518
|
return Boolean(task.baseCommitSha);
|
|
220243
220519
|
});
|
|
220244
220520
|
if (candidates.length === 0) return 0;
|
|
220521
|
+
const batch = candidates.slice(0, DONE_METADATA_REPAIR_CAP);
|
|
220245
220522
|
let repaired = 0;
|
|
220246
|
-
for (const task of
|
|
220523
|
+
for (const task of batch) {
|
|
220247
220524
|
if (isWorkspaceTask(task)) continue;
|
|
220248
220525
|
if (task.mergeDetails?.landedFilesAttributionRestricted || task.mergeDetails?.noOpVerifiedShortCircuit) {
|
|
220249
220526
|
log34.debug(`recoverDoneTaskMergeMetadata: skipped ${task.id} \u2014 attribution-restricted`);
|
|
@@ -221900,7 +222177,7 @@ var init_self_healing = __esm({
|
|
|
221900
222177
|
nextRecoveryAt: new Date(Date.now() + delayMs).toISOString()
|
|
221901
222178
|
},
|
|
221902
222179
|
targetColumn: await resolveReboundTargetForTask(this.store, task.id),
|
|
221903
|
-
moveOptions: { preserveProgress: true, moveSource: "engine" }
|
|
222180
|
+
moveOptions: { preserveProgress: true, preserveWorktree: true, moveSource: "engine" }
|
|
221904
222181
|
});
|
|
221905
222182
|
if (applied.outcome === "applied") {
|
|
221906
222183
|
await this.store.logEntry(task.id, `Auto-recovered generic terminal failure (attempt ${claim.attempt}/${MAX_TERMINAL_FAILURE_AUTO_RETRIES})`);
|
|
@@ -222042,6 +222319,7 @@ var init_self_healing = __esm({
|
|
|
222042
222319
|
if (route.kind === "node-requeue" && fresh.column !== requeueTarget) {
|
|
222043
222320
|
await this.store.moveTask(task.id, requeueTarget, {
|
|
222044
222321
|
preserveProgress: true,
|
|
222322
|
+
preserveWorktree: true,
|
|
222045
222323
|
moveSource: "engine",
|
|
222046
222324
|
recoveryRehome: true
|
|
222047
222325
|
});
|
|
@@ -222275,6 +222553,7 @@ var init_self_healing = __esm({
|
|
|
222275
222553
|
const leaseRecovered = await this.options.leaseManager.recoverAbandonedLease(
|
|
222276
222554
|
task.id,
|
|
222277
222555
|
`in-progress limbo: ${describeWorktreeState(task)} + null branch`,
|
|
222556
|
+
// worktree-discard-intended: limbo recovery — the worktree is already missing or its metadata cleared; there is no live checkout to hold.
|
|
222278
222557
|
{ preserveProgress: true }
|
|
222279
222558
|
);
|
|
222280
222559
|
if (!leaseRecovered) {
|
|
@@ -223460,7 +223739,7 @@ var init_self_healing = __esm({
|
|
|
223460
223739
|
task.id,
|
|
223461
223740
|
`Auto-retry ${nextCount}/${MAX_TASK_DONE_RETRIES}: agent finished without fn_task_done \u2014 requeuing to todo to resume partial work`
|
|
223462
223741
|
);
|
|
223463
|
-
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
|
223742
|
+
await this.store.moveTask(task.id, await resolveReboundTargetForTask(this.store, task.id), { preserveProgress: true, preserveWorktree: true, moveSource: "engine", recoveryRehome: true });
|
|
223464
223743
|
recovered++;
|
|
223465
223744
|
} catch (err) {
|
|
223466
223745
|
const errorMessage5 = err instanceof Error ? err.message : String(err);
|
|
@@ -261297,7 +261576,7 @@ async function ensureCommitTaskMetadata(mergeRoot, taskId, includeTaskId, traile
|
|
|
261297
261576
|
const needsPrefix = includeTaskId && !subject.toLowerCase().startsWith(taskId.toLowerCase());
|
|
261298
261577
|
const missingTrailers = trailers.filter((t) => !fullMessage.includes(t));
|
|
261299
261578
|
if (!needsPrefix && missingTrailers.length === 0) return;
|
|
261300
|
-
const args = ["-c", "trailer.ifExists=addIfDifferent", "commit", "--amend"];
|
|
261579
|
+
const args = [...commitIdentityArgs(resolveCommitIdentity()), "-c", "trailer.ifExists=addIfDifferent", "commit", "--amend"];
|
|
261301
261580
|
if (needsPrefix) {
|
|
261302
261581
|
args.push("-m", `${taskId}: ${subject}`);
|
|
261303
261582
|
if (body.trim()) args.push("-m", body);
|
|
@@ -262932,6 +263211,7 @@ var execFileAsync25, aiMergeLog, MAX_CONCURRENT_ADVANCE_RETRIES, AiMergeBlockedE
|
|
|
262932
263211
|
var init_merger_ai = __esm({
|
|
262933
263212
|
"../engine/src/merge/merger-ai.ts"() {
|
|
262934
263213
|
"use strict";
|
|
263214
|
+
init_git_identity();
|
|
262935
263215
|
init_src2();
|
|
262936
263216
|
init_agent_user_comments();
|
|
262937
263217
|
init_worktree_names();
|
|
@@ -265710,7 +265990,7 @@ function defaultGitOps(cwd) {
|
|
|
265710
265990
|
await runGit8(cwd, ["add", ...paths3]);
|
|
265711
265991
|
},
|
|
265712
265992
|
async commit(message) {
|
|
265713
|
-
await runGit8(cwd, ["commit", "-m", JSON.stringify(message)]);
|
|
265993
|
+
await runGit8(cwd, [...commitIdentityArgs(resolveCommitIdentity()), "commit", "-m", JSON.stringify(message)]);
|
|
265714
265994
|
return await runGit8(cwd, ["rev-parse", "HEAD"]);
|
|
265715
265995
|
},
|
|
265716
265996
|
async resetHard(ref) {
|
|
@@ -265788,6 +266068,7 @@ var execAsync55, GIT_TIMEOUT_MS10, GIT_MAX_BUFFER8;
|
|
|
265788
266068
|
var init_git_ops = __esm({
|
|
265789
266069
|
"../engine/src/experiment/git-ops.ts"() {
|
|
265790
266070
|
"use strict";
|
|
266071
|
+
init_git_identity();
|
|
265791
266072
|
init_finalize_types();
|
|
265792
266073
|
execAsync55 = promisify81(exec59);
|
|
265793
266074
|
GIT_TIMEOUT_MS10 = 3e4;
|
|
@@ -274280,6 +274561,7 @@ var init_in_process_runtime = __esm({
|
|
|
274280
274561
|
"use strict";
|
|
274281
274562
|
init_src2();
|
|
274282
274563
|
init_scheduler();
|
|
274564
|
+
init_pi();
|
|
274283
274565
|
init_executor();
|
|
274284
274566
|
init_pr_nodes();
|
|
274285
274567
|
init_src2();
|
|
@@ -274536,6 +274818,7 @@ var init_in_process_runtime = __esm({
|
|
|
274536
274818
|
rootDir: this.config.workingDirectory
|
|
274537
274819
|
});
|
|
274538
274820
|
await this.pluginRunner.init();
|
|
274821
|
+
registerDefaultAgentPluginRunner(this.config.workingDirectory, this.pluginRunner);
|
|
274539
274822
|
const projectScopedPluginMcpProvider = createProjectScopedPluginMcpProvider2(
|
|
274540
274823
|
createRuntimePluginMcpProviderOptions({
|
|
274541
274824
|
hostRootDir: this.config.workingDirectory,
|
|
@@ -275421,6 +275704,7 @@ var init_in_process_runtime = __esm({
|
|
|
275421
275704
|
);
|
|
275422
275705
|
}
|
|
275423
275706
|
if (this.pluginRunner) {
|
|
275707
|
+
unregisterDefaultAgentPluginRunner(this.config.workingDirectory);
|
|
275424
275708
|
await this.pluginRunner.shutdown();
|
|
275425
275709
|
runtimeLog.log("PluginRunner shutdown complete");
|
|
275426
275710
|
}
|
|
@@ -294517,6 +294801,8 @@ async function createMissionInterviewAgent(session, rootDir, store, promptOverri
|
|
|
294517
294801
|
tools: "readonly",
|
|
294518
294802
|
mcpServers,
|
|
294519
294803
|
allowMcpToolsInReadonly: true,
|
|
294804
|
+
// FNXC:MissionInterviewRuntimeResolution 2026-08-16-14:37: forward the plugin runner so the shared seam can route CLI-runtime model selections (cursor/claude/grok/omp/hermes) to their runtime plugins.
|
|
294805
|
+
...pluginRunner ? { pluginRunner } : {},
|
|
294520
294806
|
...skillContext.skillSelectionContext ? { skillSelection: skillContext.skillSelectionContext } : {},
|
|
294521
294807
|
builtinToolsAllowlist: [...MISSION_INTERVIEW_BUILTIN_WEB_TOOLS],
|
|
294522
294808
|
customTools: [...createPlanningBoardTools(store)],
|
|
@@ -294637,7 +294923,8 @@ async function ensureMissionInterviewAgent(session, rootDir, store, historyForRe
|
|
|
294637
294923
|
if (abortSignal.aborted) {
|
|
294638
294924
|
throw createAbortError3();
|
|
294639
294925
|
}
|
|
294640
|
-
await
|
|
294926
|
+
await promptWithFallback(
|
|
294927
|
+
session.agent.session,
|
|
294641
294928
|
[
|
|
294642
294929
|
"Previous conversation summary:",
|
|
294643
294930
|
historySummary,
|
|
@@ -294689,7 +294976,7 @@ async function continueAgentConversation2(session, message) {
|
|
|
294689
294976
|
if (abortSignal.aborted) {
|
|
294690
294977
|
throw createAbortError3();
|
|
294691
294978
|
}
|
|
294692
|
-
await agent.session
|
|
294979
|
+
await promptWithFallback(agent.session, message, { signal: abortSignal });
|
|
294693
294980
|
if (abortSignal.aborted) {
|
|
294694
294981
|
throw createAbortError3();
|
|
294695
294982
|
}
|
|
@@ -294720,7 +295007,8 @@ async function continueAgentConversation2(session, message) {
|
|
|
294720
295007
|
if (abortSignal.aborted) {
|
|
294721
295008
|
throw createAbortError3();
|
|
294722
295009
|
}
|
|
294723
|
-
await
|
|
295010
|
+
await promptWithFallback(
|
|
295011
|
+
agent.session,
|
|
294724
295012
|
'Your previous response could not be parsed as JSON. Please respond with ONLY a valid JSON object: either {"type":"question","data":{...}} or {"type":"complete","data":{"missionTitle":"...","missionDescription":"...","milestones":[...]}}. No markdown, no explanation, just the JSON.',
|
|
294725
295013
|
{ signal: abortSignal }
|
|
294726
295014
|
);
|
|
@@ -295047,7 +295335,16 @@ var init_mission_interview = __esm({
|
|
|
295047
295335
|
init_src5();
|
|
295048
295336
|
init_planning_board_tools();
|
|
295049
295337
|
MISSION_INTERVIEW_BUILTIN_WEB_TOOLS = ["WebSearch", "WebFetch"];
|
|
295050
|
-
createFnAgent6 =
|
|
295338
|
+
createFnAgent6 = async (options) => {
|
|
295339
|
+
const { pluginRunner, runtimeHint, settings, ...runtimeOptions } = options ?? {};
|
|
295340
|
+
return createResolvedAgentSession({
|
|
295341
|
+
sessionPurpose: "executor",
|
|
295342
|
+
...runtimeHint ? { runtimeHint } : {},
|
|
295343
|
+
...pluginRunner ? { pluginRunner } : {},
|
|
295344
|
+
...settings ? { settings } : {},
|
|
295345
|
+
...runtimeOptions
|
|
295346
|
+
});
|
|
295347
|
+
};
|
|
295051
295348
|
diagnostics4 = createSessionDiagnostics("mission-interview");
|
|
295052
295349
|
SESSION_TTL_MS3 = 7 * 24 * 60 * 60 * 1e3;
|
|
295053
295350
|
CLEANUP_INTERVAL_MS4 = 5 * 60 * 1e3;
|
|
@@ -295607,6 +295904,8 @@ async function createTargetInterviewAgent(session, rootDir, store, pluginRunner)
|
|
|
295607
295904
|
mcpServers,
|
|
295608
295905
|
...laneModelOptions(model),
|
|
295609
295906
|
allowMcpToolsInReadonly: true,
|
|
295907
|
+
// FNXC:MissionInterviewRuntimeResolution 2026-08-16-14:37: forward the plugin runner so the shared seam can route CLI-runtime model selections to their runtime plugins.
|
|
295908
|
+
...pluginRunner ? { pluginRunner } : {},
|
|
295610
295909
|
customTools: [...createPlanningBoardTools(store)],
|
|
295611
295910
|
/*
|
|
295612
295911
|
FNXC:InterviewSkills 2026-06-17-21:42:
|
|
@@ -295719,7 +296018,8 @@ async function ensureInterviewAgent(session, rootDir, store, historyForReplay, p
|
|
|
295719
296018
|
if (abortSignal.aborted) {
|
|
295720
296019
|
throw createAbortError3();
|
|
295721
296020
|
}
|
|
295722
|
-
await
|
|
296021
|
+
await promptWithFallback(
|
|
296022
|
+
session.agent.session,
|
|
295723
296023
|
[
|
|
295724
296024
|
"Previous conversation summary:",
|
|
295725
296025
|
historySummary,
|
|
@@ -295781,7 +296081,7 @@ async function continueAgentConversation3(session, message) {
|
|
|
295781
296081
|
if (abortSignal.aborted) {
|
|
295782
296082
|
throw createAbortError3();
|
|
295783
296083
|
}
|
|
295784
|
-
await agent.session
|
|
296084
|
+
await promptWithFallback(agent.session, message, { signal: abortSignal });
|
|
295785
296085
|
if (abortSignal.aborted) {
|
|
295786
296086
|
throw createAbortError3();
|
|
295787
296087
|
}
|
|
@@ -295812,7 +296112,8 @@ async function continueAgentConversation3(session, message) {
|
|
|
295812
296112
|
if (abortSignal.aborted) {
|
|
295813
296113
|
throw createAbortError3();
|
|
295814
296114
|
}
|
|
295815
|
-
await
|
|
296115
|
+
await promptWithFallback(
|
|
296116
|
+
agent.session,
|
|
295816
296117
|
'Your previous response could not be parsed as JSON. Please respond with ONLY a valid JSON object: either {"type":"question","data":{...}} or {"type":"complete","data":{"title":"...","description":"...","planningNotes":"...","verification":"..."}}. No markdown, no explanation, just the JSON.',
|
|
295817
296118
|
{ signal: abortSignal }
|
|
295818
296119
|
);
|
|
@@ -296135,7 +296436,16 @@ var init_milestone_slice_interview = __esm({
|
|
|
296135
296436
|
init_planning_board_tools();
|
|
296136
296437
|
init_lane_session_model();
|
|
296137
296438
|
diagnostics5 = createSessionDiagnostics("milestone-slice-interview");
|
|
296138
|
-
createFnAgent7 =
|
|
296439
|
+
createFnAgent7 = async (options) => {
|
|
296440
|
+
const { pluginRunner, runtimeHint, settings, ...runtimeOptions } = options ?? {};
|
|
296441
|
+
return createResolvedAgentSession({
|
|
296442
|
+
sessionPurpose: "executor",
|
|
296443
|
+
...runtimeHint ? { runtimeHint } : {},
|
|
296444
|
+
...pluginRunner ? { pluginRunner } : {},
|
|
296445
|
+
...settings ? { settings } : {},
|
|
296446
|
+
...runtimeOptions
|
|
296447
|
+
});
|
|
296448
|
+
};
|
|
296139
296449
|
SESSION_TTL_MS4 = 7 * 24 * 60 * 60 * 1e3;
|
|
296140
296450
|
CLEANUP_INTERVAL_MS5 = 5 * 60 * 1e3;
|
|
296141
296451
|
MAX_SESSIONS_PER_IP_PER_HOUR3 = 5;
|
|
@@ -390530,9 +390840,14 @@ var init_register_auth_routes = __esm({
|
|
|
390530
390840
|
}
|
|
390531
390841
|
return await pendingLogin.inputPromise;
|
|
390532
390842
|
},
|
|
390533
|
-
|
|
390534
|
-
|
|
390535
|
-
|
|
390843
|
+
/*
|
|
390844
|
+
FNXC:ProviderAuth 2026-08-18-00:26:
|
|
390845
|
+
`onManualCodeInput` and `onSelect` are dispatched by prompt TYPE in AuthStorage.login()'s
|
|
390846
|
+
pi `AuthInteraction` shim (packages/engine/src/auth/auth-storage.ts), not forwarded
|
|
390847
|
+
verbatim as an older comment here claimed. Both were dead code after login moved to pi's
|
|
390848
|
+
ModelRuntime, which is what broke Codex login: its `select` prompt fell through to
|
|
390849
|
+
`onPrompt` and waited on a paste the UI never asked for.
|
|
390850
|
+
*/
|
|
390536
390851
|
onManualCodeInput: async () => await pendingLogin.inputPromise,
|
|
390537
390852
|
onProgress: () => {
|
|
390538
390853
|
},
|