@runfusion/fusion 0.75.1-beta.0 → 0.75.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +523 -212
- package/dist/child-process-worker.js +323 -99
- package/dist/client/.vite/manifest.json +249 -249
- package/dist/client/assets/{AgentDetailView-swTdiyeE.js → AgentDetailView-ltOG8f0-.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-Dq-KuDaA.js → AgentPermissionPolicyEditor-CC_rrbbG.js} +1 -1
- package/dist/client/assets/{AgentsView-D1GEHyH0.js → AgentsView-DWUdi27N.js} +3 -3
- package/dist/client/assets/{ChatView-D1czGvvT.js → ChatView-mFKfoegS.js} +1 -1
- package/dist/client/assets/{CommandCenter-DWZ7OTOB.js → CommandCenter-C2wvDq_N.js} +1 -1
- package/dist/client/assets/{DevServerView-CAcUKOXd.js → DevServerView-0MWEJM7o.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DVUl5jOk.js → DirectoryPicker-BjMPhCdh.js} +1 -1
- package/dist/client/assets/{DocumentsView-CnexOxtr.js → DocumentsView-ckH3rjmd.js} +1 -1
- package/dist/client/assets/{EvalsView-rTupzcDf.js → EvalsView-NyA644VF.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CXE6Bj3V.js → ExperimentalAgentOnboardingModal-D0ZfbBRN.js} +1 -1
- package/dist/client/assets/{GoalsView-CjHwnnIi.js → GoalsView-Ctt5P_yo.js} +1 -1
- package/dist/client/assets/{InsightsView-C3XocYP-.js → InsightsView-NDp0bdNB.js} +1 -1
- package/dist/client/assets/{MemoryView-CsNHcx_d.js → MemoryView-BKbA4Bm4.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BPTPoZBI.js → PiExtensionsManager-V3AFWMHm.js} +1 -1
- package/dist/client/assets/{PluginManager-CXadn8JE.js → PluginManager-D88G_TZh.js} +1 -1
- package/dist/client/assets/{PullRequestView-CC03CtZJ.js → PullRequestView-DQQmFFYC.js} +1 -1
- package/dist/client/assets/{ReportModal-Ci0na1eI.js → ReportModal-Clh1S8RF.js} +1 -1
- package/dist/client/assets/{ResearchView-DGWyAo8p.js → ResearchView-kxvq4zp5.js} +1 -1
- package/dist/client/assets/SecretsView-Dm0Vk8SA.js +1 -0
- package/dist/client/assets/{SessionTerminal-B22RlQeo.js → SessionTerminal-DJO4JTEX.js} +1 -1
- package/dist/client/assets/{SettingsModal-BkgBQZ19.js → SettingsModal-BN5mL_ym.js} +1 -1
- package/dist/client/assets/SettingsModal-CTf5voEW.js +21 -0
- package/dist/client/assets/{SettingsTextareaRow-0LXwMUQR.js → SettingsTextareaRow-CvKszqO-.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-CyW3AlRO.js → SetupWizardModal-D5hVZh1G.js} +2 -2
- package/dist/client/assets/{SkillsView-3oqB1ubq.js → SkillsView-DQVz21w2.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-CfUK_xs1.js → WorkflowNodeEditor-CpKIi6Tb.js} +3 -3
- package/dist/client/assets/{agent-import-generation-C7-Cmo3M.js → agent-import-generation-DGUNF3nd.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-BQ7ZN1r_.js → architectureDiagram-3BPJPVTR-CV83wubP.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-Debw1Xka.js → blockDiagram-GPEHLZMM-CNQsA3dD.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CiU212s3.js → c4Diagram-AAUBKEIU-CXe7ii5H.js} +1 -1
- package/dist/client/assets/channel-DoX862zl.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BUJQ86zb.js → chunk-2J33WTMH-BS6W9bWv.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-C6GdEm1z.js → chunk-4BX2VUAB-DbehRhdW.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CImvrxQL.js → chunk-55IACEB6-DMI5SR42.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-Dt-A3pkM.js → chunk-727SXJPM-D1d-GBVj.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DDj4oXTx.js → chunk-AQP2D5EJ-BzO6K3Uf.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-BD4r1ukC.js → chunk-FMBD7UC4-BVRLV3lK.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-DFSteefi.js → chunk-ND2GUHAM-DdWByQfn.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-t2zF8tjB.js → chunk-QZHKN3VN-1ia12cRV.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-mb2IeAGN.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-mb2IeAGN.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-tkvDkXQA.js → cose-bilkent-S5V4N54A-BPDT41HR.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-DD2rW7wo.js → dagre-BM42HDAG-Cktn26EH.js} +1 -1
- package/dist/client/assets/{dashboard-view-B1vduc8x.js → dashboard-view-8o0EUcRX.js} +1 -1
- package/dist/client/assets/{dashboard-view-CciuDS5A.js → dashboard-view-CkCerlVJ.js} +1 -1
- package/dist/client/assets/{dashboard-view-DruCruAc.js → dashboard-view-D_HC4lnr.js} +1 -1
- package/dist/client/assets/{dashboard-view-C7jJ1lA4.js → dashboard-view-zd8GxC49.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DASuxGNc.js → diagram-2AECGRRQ-But4Lvf-.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-f9WtiIUk.js → diagram-5GNKFQAL-2bpQAGFc.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-QivICYCd.js → diagram-KO2AKTUF-Ckn9Qd1u.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CMwcDFHR.js → diagram-LMA3HP47-Bjn8h84N.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-C-vPMeHZ.js → diagram-OG6HWLK6-BI6541hx.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CxGtk9vj.js → erDiagram-TEJ5UH35-BqMiwHiM.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-qBZRZoV1.js → flowDiagram-I6XJVG4X-Q_SAB10M.js} +1 -1
- package/dist/client/assets/{folder-open-Dysi9Zzg.js → folder-open-CHiAJbTN.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DAaXroiu.js → ganttDiagram-6RSMTGT7-CqWFSfPF.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DNUNQot_.js → gitGraphDiagram-PVQCEYII-B1o4uEjO.js} +1 -1
- package/dist/client/assets/index-Bdw5eNKV.css +1 -0
- package/dist/client/assets/index-kwRywd9M.js +2767 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BSJmWLwh.js → infoDiagram-5YYISTIA-BzaMa0c2.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-AyVKvoDq.js → ishikawaDiagram-YF4QCWOH-I38yge00.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-972txzzd.js → journeyDiagram-JHISSGLW-WVQSgx4P.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-1xiNvIqK.js → kanban-definition-UN3LZRKU-BWtPQ3AH.js} +1 -1
- package/dist/client/assets/{mermaid.core-oeDA8jOm.js → mermaid.core-D1hnBtbi.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DcktmI8s.js → mindmap-definition-RKZ34NQL-DqiSLkW7.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-ekBwLt-O.js → pieDiagram-4H26LBE5-CcgwbdIN.js} +1 -1
- package/dist/client/assets/{puzzle-I6pr6ZrW.js → puzzle-BhXUaTQl.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-D_wjTsvn.js → quadrantDiagram-W4KKPZXB-MsqQQfDN.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-CKGHyiJ1.js → requirementDiagram-4Y6WPE33-CILGjMMA.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CtiZFNk5.js → sankeyDiagram-5OEKKPKP-c14fWbtR.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B6OMrfGk.js → sequenceDiagram-3UESZ5HK-BD5bxMom.js} +1 -1
- package/dist/client/assets/{shield-alert-CVMmviMG.js → shield-alert-C9W2WywS.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-Cg1a3tjW.js → standing-instructions-template-CJdbDSyg.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CyTY2M_7.js → stateDiagram-AJRCARHV-CZ5YqeOn.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-NWPCCiqC.js → stateDiagram-v2-BHNVJYJU-mdMN-PNX.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DU4TVYpw.js → timeline-definition-PNZ67QCA-DHKay9uj.js} +1 -1
- package/dist/client/assets/{upload-VCzeCiFH.js → upload-DxEwowRU.js} +1 -1
- package/dist/client/assets/{users-DB3knZtm.js → users-mNFgW_Zd.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DX0Ppll6.js → vennDiagram-CIIHVFJN-X29K9hWM.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-CBoWxpDv.js → wardley-L42UT6IY-yEoTrfmN.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-B_eVqdhC.js → wardleyDiagram-YWT4CUSO-ny4k3kG0.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DeZzEX0f.js → xychartDiagram-2RQKCTM6-DC8ODtRJ.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 +411 -155
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +159 -141
- package/dist/plugin-sdk/index.js +19 -0
- package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +19 -0
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/SecretsView-Cv2IuqFO.js +0 -1
- package/dist/client/assets/SettingsModal-CPRpRK71.js +0 -21
- package/dist/client/assets/channel-D-O4mRXx.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BhHdSetA.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BhHdSetA.js +0 -1
- package/dist/client/assets/index-D0QgE5F5.js +0 -2767
- package/dist/client/assets/index-DHk_s6rA.css +0 -1
package/dist/bin.js
CHANGED
|
@@ -1183,6 +1183,9 @@ function isFusionSiblingBranch(branch) {
|
|
|
1183
1183
|
function resolveEffectiveAutoMerge(task, settings) {
|
|
1184
1184
|
return task.autoMerge ?? settings.autoMerge;
|
|
1185
1185
|
}
|
|
1186
|
+
function hasUserAutoMergeHold(task) {
|
|
1187
|
+
return task.autoMerge === false && task.autoMergeProvenance === "user";
|
|
1188
|
+
}
|
|
1186
1189
|
function allowsAutoMergeProcessing(task, settings) {
|
|
1187
1190
|
return (settings.autoMerge !== false || task.autoMerge === true) && !taskHasManualOpenPullRequest(task);
|
|
1188
1191
|
}
|
|
@@ -10048,6 +10051,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10048
10051
|
);
|
|
10049
10052
|
}
|
|
10050
10053
|
for (const inner of templateNodes) {
|
|
10054
|
+
validateReviewKind(inner, "nested");
|
|
10051
10055
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10052
10056
|
throw new WorkflowIrError(
|
|
10053
10057
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10166,6 +10170,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10166
10170
|
);
|
|
10167
10171
|
}
|
|
10168
10172
|
for (const inner of templateNodes) {
|
|
10173
|
+
validateReviewKind(inner, "nested");
|
|
10169
10174
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10170
10175
|
throw new WorkflowIrError(
|
|
10171
10176
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10259,6 +10264,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10259
10264
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10260
10265
|
}
|
|
10261
10266
|
for (const inner of templateNodes) {
|
|
10267
|
+
validateReviewKind(inner, "nested");
|
|
10262
10268
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10263
10269
|
throw new WorkflowIrError(
|
|
10264
10270
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -10930,6 +10936,19 @@ function validateColumnRecovery(column) {
|
|
|
10930
10936
|
);
|
|
10931
10937
|
}
|
|
10932
10938
|
}
|
|
10939
|
+
function validateReviewKind(node, placement) {
|
|
10940
|
+
const value = node.config?.reviewKind;
|
|
10941
|
+
if (value === void 0) return;
|
|
10942
|
+
if (value !== "plan" && value !== "code") {
|
|
10943
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
10944
|
+
}
|
|
10945
|
+
if (placement === "nested") {
|
|
10946
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
10947
|
+
}
|
|
10948
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
10949
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
10950
|
+
}
|
|
10951
|
+
}
|
|
10933
10952
|
function validateV2(ir2) {
|
|
10934
10953
|
validateColumns(ir2);
|
|
10935
10954
|
for (const [index3, column] of ir2.columns.entries()) {
|
|
@@ -10952,6 +10971,7 @@ function validateV2(ir2) {
|
|
|
10952
10971
|
}
|
|
10953
10972
|
const nodesById = new Map(ir2.nodes.map((n) => [n.id, n]));
|
|
10954
10973
|
for (const node of ir2.nodes) {
|
|
10974
|
+
validateReviewKind(node, "top-level");
|
|
10955
10975
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
10956
10976
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
10957
10977
|
throw new WorkflowIrError(
|
|
@@ -13415,6 +13435,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13415
13435
|
column,
|
|
13416
13436
|
config: {
|
|
13417
13437
|
name: CODE_REVIEW_NAME,
|
|
13438
|
+
reviewKind: "code",
|
|
13418
13439
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13419
13440
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13420
13441
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13560,6 +13581,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13560
13581
|
...column ? { column } : {},
|
|
13561
13582
|
config: {
|
|
13562
13583
|
name: PLAN_REVIEW_NAME,
|
|
13584
|
+
reviewKind: "plan",
|
|
13563
13585
|
defaultOn: options.defaultOn ?? true,
|
|
13564
13586
|
/*
|
|
13565
13587
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -63404,7 +63426,7 @@ function rowToTask(row) {
|
|
|
63404
63426
|
executionStartBranch: row.executionStartBranch || void 0,
|
|
63405
63427
|
branch: row.branch || void 0,
|
|
63406
63428
|
autoMerge: row.autoMerge === null ? void 0 : row.autoMerge === 1,
|
|
63407
|
-
autoMergeProvenance: row.autoMergeProvenance === "user" || row.autoMergeProvenance === "legacy-stamp" ? row.autoMergeProvenance : void 0,
|
|
63429
|
+
autoMergeProvenance: row.autoMergeProvenance === "user" || row.autoMergeProvenance === "mission" || row.autoMergeProvenance === "legacy-stamp" ? row.autoMergeProvenance : void 0,
|
|
63408
63430
|
baseCommitSha: row.baseCommitSha || void 0,
|
|
63409
63431
|
scopeOverride: row.scopeOverride ? true : void 0,
|
|
63410
63432
|
scopeOverrideReason: row.scopeOverrideReason || void 0,
|
|
@@ -72920,10 +72942,10 @@ ${feature.acceptanceCriteria}`);
|
|
|
72920
72942
|
Apply the selected Missions header workflow atomically during TaskStore.createTask so newly triaged features land in the intended workflow lane. Duplicate-guard reuses skip this create path, preserving existing duplicate tasks without workflow mutation.
|
|
72921
72943
|
*/
|
|
72922
72944
|
/*
|
|
72923
|
-
FNXC:MissionAutoMerge 2026-
|
|
72924
|
-
An autoMerge:false mission stamps each newly triaged task so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override.
|
|
72945
|
+
FNXC:MissionAutoMerge 2026-08-05-22:50:
|
|
72946
|
+
An autoMerge:false mission stamps each newly triaged task as mission policy so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override; policy must not impersonate an operator manual-hold choice.
|
|
72925
72947
|
*/
|
|
72926
|
-
...mission?.autoMerge === false ? { autoMerge: false } : {},
|
|
72948
|
+
...mission?.autoMerge === false ? { autoMerge: false, autoMergeProvenance: "mission" } : {},
|
|
72927
72949
|
// FNXC:MissionTaskPrefix 2026-07-26-12:00: thread the mission's optional taskPrefix into TaskCreateInput for distributed id minting.
|
|
72928
72950
|
...mission?.taskPrefix ? { taskPrefix: mission.taskPrefix } : {},
|
|
72929
72951
|
...branchOptions?.workflowId !== void 0 ? { workflowId: branchOptions.workflowId } : {}
|
|
@@ -76101,10 +76123,10 @@ ${feature.acceptanceCriteria}`);
|
|
|
76101
76123
|
}
|
|
76102
76124
|
} : {},
|
|
76103
76125
|
/*
|
|
76104
|
-
FNXC:MissionAutoMerge 2026-
|
|
76105
|
-
An autoMerge:false mission stamps each newly triaged task so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override.
|
|
76126
|
+
FNXC:MissionAutoMerge 2026-08-05-22:50:
|
|
76127
|
+
An autoMerge:false mission stamps each newly triaged task as mission policy so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override; policy must not impersonate an operator manual-hold choice.
|
|
76106
76128
|
*/
|
|
76107
|
-
...mission?.autoMerge === false ? { autoMerge: false } : {},
|
|
76129
|
+
...mission?.autoMerge === false ? { autoMerge: false, autoMergeProvenance: "mission" } : {},
|
|
76108
76130
|
// FNXC:MissionTaskPrefix 2026-07-26-12:00: thread the mission's optional taskPrefix into TaskCreateInput so the distributed allocator mints ERR-N (etc.) instead of the project prefix.
|
|
76109
76131
|
...mission?.taskPrefix ? { taskPrefix: mission.taskPrefix } : {},
|
|
76110
76132
|
...branchOptions?.workflowId !== void 0 ? { workflowId: branchOptions.workflowId } : {}
|
|
@@ -86455,7 +86477,9 @@ async function _createTaskInternalBackendImpl(store, input, title2, resolvedWork
|
|
|
86455
86477
|
sourceMetadata: withTaskBranchContextInSourceMetadata(input.source?.sourceMetadata, input.branchContext),
|
|
86456
86478
|
branchContext: input.branchContext,
|
|
86457
86479
|
autoMerge: input.autoMerge,
|
|
86458
|
-
|
|
86480
|
+
// FNXC:SharedBranchMemberHold 2026-08-05-22:50: trusted mission creation
|
|
86481
|
+
// preserves policy provenance; operator/API create requests retain user provenance.
|
|
86482
|
+
autoMergeProvenance: input.autoMerge === void 0 ? void 0 : input.autoMergeProvenance ?? "user",
|
|
86459
86483
|
// FNXC:CodingIdeasWorkflow 2026-07-05-19:45: land the task in its
|
|
86460
86484
|
// workflow's manual intake column (e.g. Coding (Ideas) → "ideas") when
|
|
86461
86485
|
// no explicit column is given (main FN-7591 parity).
|
|
@@ -127160,6 +127184,36 @@ var init_async_knowledge = __esm({
|
|
|
127160
127184
|
});
|
|
127161
127185
|
|
|
127162
127186
|
// ../core/src/workflows/workflow-step-results.ts
|
|
127187
|
+
function normalizeWorkflowReviewFindings(raw) {
|
|
127188
|
+
if (!Array.isArray(raw)) return void 0;
|
|
127189
|
+
const normalized = [];
|
|
127190
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
127191
|
+
for (const candidate of raw) {
|
|
127192
|
+
if (normalized.length >= MAX_WORKFLOW_REVIEW_FINDINGS || !candidate || typeof candidate !== "object") continue;
|
|
127193
|
+
const value = candidate;
|
|
127194
|
+
const title2 = boundedTrimmedString(value.title, MAX_FINDING_TITLE_LENGTH);
|
|
127195
|
+
const body = boundedTrimmedString(value.body, MAX_FINDING_BODY_LENGTH);
|
|
127196
|
+
if (!title2 || !body) continue;
|
|
127197
|
+
const baseId = boundedTrimmedString(value.id, MAX_FINDING_ID_LENGTH) || `finding-${normalized.length + 1}`;
|
|
127198
|
+
let id = baseId;
|
|
127199
|
+
let suffix = 2;
|
|
127200
|
+
while (usedIds.has(id)) id = `${baseId.slice(0, Math.max(1, MAX_FINDING_ID_LENGTH - String(suffix).length - 1))}-${suffix++}`;
|
|
127201
|
+
usedIds.add(id);
|
|
127202
|
+
const filePath = boundedTrimmedString(value.filePath, MAX_FINDING_PATH_LENGTH);
|
|
127203
|
+
const line2 = typeof value.line === "number" && Number.isFinite(value.line) && value.line > 0 ? Math.floor(value.line) : void 0;
|
|
127204
|
+
const severity = isWorkflowReviewFindingSeverity(value.severity) ? value.severity : void 0;
|
|
127205
|
+
normalized.push({ id, title: title2, body, ...filePath ? { filePath } : {}, ...line2 ? { line: line2 } : {}, ...severity ? { severity } : {} });
|
|
127206
|
+
}
|
|
127207
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
127208
|
+
}
|
|
127209
|
+
function boundedTrimmedString(value, maxLength) {
|
|
127210
|
+
if (typeof value !== "string") return void 0;
|
|
127211
|
+
const trimmed = value.trim();
|
|
127212
|
+
return trimmed && trimmed.length <= maxLength ? trimmed : void 0;
|
|
127213
|
+
}
|
|
127214
|
+
function isWorkflowReviewFindingSeverity(value) {
|
|
127215
|
+
return typeof value === "string" && WORKFLOW_REVIEW_FINDING_SEVERITIES.includes(value);
|
|
127216
|
+
}
|
|
127163
127217
|
function isTerminalFailure(result2) {
|
|
127164
127218
|
return TERMINAL_FAILURE_STATUSES.has(result2.status);
|
|
127165
127219
|
}
|
|
@@ -127225,10 +127279,16 @@ function makeReviewLeaseRecord(args) {
|
|
|
127225
127279
|
leaseOwner: args.owner
|
|
127226
127280
|
};
|
|
127227
127281
|
}
|
|
127228
|
-
var MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS, TERMINAL_FAILURE_STATUSES, PLAN_REVIEW_LEASE_STALENESS_MS, TERMINAL_STEP_STATUSES;
|
|
127282
|
+
var WORKFLOW_REVIEW_FINDING_SEVERITIES, MAX_WORKFLOW_REVIEW_FINDINGS, MAX_FINDING_ID_LENGTH, MAX_FINDING_TITLE_LENGTH, MAX_FINDING_BODY_LENGTH, MAX_FINDING_PATH_LENGTH, MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS, TERMINAL_FAILURE_STATUSES, PLAN_REVIEW_LEASE_STALENESS_MS, TERMINAL_STEP_STATUSES;
|
|
127229
127283
|
var init_workflow_step_results = __esm({
|
|
127230
127284
|
"../core/src/workflows/workflow-step-results.ts"() {
|
|
127231
127285
|
"use strict";
|
|
127286
|
+
WORKFLOW_REVIEW_FINDING_SEVERITIES = ["low", "medium", "high", "critical"];
|
|
127287
|
+
MAX_WORKFLOW_REVIEW_FINDINGS = 20;
|
|
127288
|
+
MAX_FINDING_ID_LENGTH = 128;
|
|
127289
|
+
MAX_FINDING_TITLE_LENGTH = 240;
|
|
127290
|
+
MAX_FINDING_BODY_LENGTH = 4e3;
|
|
127291
|
+
MAX_FINDING_PATH_LENGTH = 1e3;
|
|
127232
127292
|
MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS = 5;
|
|
127233
127293
|
TERMINAL_FAILURE_STATUSES = /* @__PURE__ */ new Set([
|
|
127234
127294
|
"failed",
|
|
@@ -127297,6 +127357,7 @@ var init_task_timing = __esm({
|
|
|
127297
127357
|
});
|
|
127298
127358
|
|
|
127299
127359
|
// ../core/src/session-identity-registry.ts
|
|
127360
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
127300
127361
|
import { resolve as resolve21 } from "node:path";
|
|
127301
127362
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
127302
127363
|
function getRegistry() {
|
|
@@ -127308,6 +127369,16 @@ function getRegistry() {
|
|
|
127308
127369
|
}
|
|
127309
127370
|
return registry3;
|
|
127310
127371
|
}
|
|
127372
|
+
function getActiveInvocationStorage() {
|
|
127373
|
+
const holder = globalThis;
|
|
127374
|
+
const existing = holder[ACTIVE_INVOCATION_KEY];
|
|
127375
|
+
if (existing instanceof AsyncLocalStorage) {
|
|
127376
|
+
return existing;
|
|
127377
|
+
}
|
|
127378
|
+
const storage = new AsyncLocalStorage();
|
|
127379
|
+
holder[ACTIVE_INVOCATION_KEY] = storage;
|
|
127380
|
+
return storage;
|
|
127381
|
+
}
|
|
127311
127382
|
function canonicalizeCwd(cwd) {
|
|
127312
127383
|
const resolved = resolve21(cwd);
|
|
127313
127384
|
try {
|
|
@@ -127335,8 +127406,13 @@ function registerFusionSessionIdentity(cwd, identity) {
|
|
|
127335
127406
|
};
|
|
127336
127407
|
}
|
|
127337
127408
|
function resolveFusionSessionPrincipal(cwd) {
|
|
127409
|
+
const canonicalCwd = canonicalizeCwd(cwd);
|
|
127410
|
+
const activeInvocation = getActiveInvocationStorage().getStore();
|
|
127411
|
+
if (activeInvocation?.cwdKeys.has(canonicalCwd)) {
|
|
127412
|
+
return { kind: "agent", identity: activeInvocation.identity };
|
|
127413
|
+
}
|
|
127338
127414
|
const registry3 = getRegistry();
|
|
127339
|
-
const list = registry3.get(
|
|
127415
|
+
const list = registry3.get(canonicalCwd);
|
|
127340
127416
|
if (!list || list.length === 0) {
|
|
127341
127417
|
return { kind: "operator" };
|
|
127342
127418
|
}
|
|
@@ -127345,14 +127421,24 @@ function resolveFusionSessionPrincipal(cwd) {
|
|
|
127345
127421
|
}
|
|
127346
127422
|
return { kind: "ambiguous", identities: [...list] };
|
|
127347
127423
|
}
|
|
127424
|
+
function runWithFusionSessionIdentity(cwdKeys, identity, callback) {
|
|
127425
|
+
const invocation = {
|
|
127426
|
+
identity: { ...identity, registeredAt: Date.now() },
|
|
127427
|
+
cwdKeys: new Set(cwdKeys.map(canonicalizeCwd))
|
|
127428
|
+
};
|
|
127429
|
+
return getActiveInvocationStorage().run(invocation, callback);
|
|
127430
|
+
}
|
|
127348
127431
|
function __clearFusionSessionIdentityRegistryForTests() {
|
|
127349
|
-
|
|
127432
|
+
const holder = globalThis;
|
|
127433
|
+
holder[REGISTRY_KEY] = /* @__PURE__ */ new Map();
|
|
127434
|
+
holder[ACTIVE_INVOCATION_KEY] = new AsyncLocalStorage();
|
|
127350
127435
|
}
|
|
127351
|
-
var REGISTRY_KEY;
|
|
127436
|
+
var REGISTRY_KEY, ACTIVE_INVOCATION_KEY;
|
|
127352
127437
|
var init_session_identity_registry = __esm({
|
|
127353
127438
|
"../core/src/session-identity-registry.ts"() {
|
|
127354
127439
|
"use strict";
|
|
127355
127440
|
REGISTRY_KEY = "__FUSION_SESSION_IDENTITY_REGISTRY_V1__";
|
|
127441
|
+
ACTIVE_INVOCATION_KEY = "__FUSION_SESSION_IDENTITY_ACTIVE_INVOCATION_V1__";
|
|
127356
127442
|
}
|
|
127357
127443
|
});
|
|
127358
127444
|
|
|
@@ -127715,6 +127801,7 @@ __export(src_exports, {
|
|
|
127715
127801
|
MAX_TITLE_LENGTH: () => MAX_TITLE_LENGTH,
|
|
127716
127802
|
MAX_TITLE_SUMMARIZE_INPUT_LENGTH: () => MAX_TITLE_SUMMARIZE_INPUT_LENGTH,
|
|
127717
127803
|
MAX_WORKFLOW_ICON_LENGTH: () => MAX_WORKFLOW_ICON_LENGTH,
|
|
127804
|
+
MAX_WORKFLOW_REVIEW_FINDINGS: () => MAX_WORKFLOW_REVIEW_FINDINGS,
|
|
127718
127805
|
MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS: () => MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS,
|
|
127719
127806
|
MEMORY_AUDIT_PATH: () => MEMORY_AUDIT_PATH,
|
|
127720
127807
|
MEMORY_BACKEND_SETTINGS_KEYS: () => MEMORY_BACKEND_SETTINGS_KEYS,
|
|
@@ -127916,6 +128003,7 @@ __export(src_exports, {
|
|
|
127916
128003
|
WAKE_DELTA_ASSIGNED_TASKS_CAP: () => WAKE_DELTA_ASSIGNED_TASKS_CAP,
|
|
127917
128004
|
WEDGE_RENOTIFY_COOLDOWN_MS: () => WEDGE_RENOTIFY_COOLDOWN_MS,
|
|
127918
128005
|
WORKFLOW_EXTENSION_SCHEMA_VERSION: () => WORKFLOW_EXTENSION_SCHEMA_VERSION,
|
|
128006
|
+
WORKFLOW_REVIEW_FINDING_SEVERITIES: () => WORKFLOW_REVIEW_FINDING_SEVERITIES,
|
|
127919
128007
|
WORKFLOW_SETTING_REJECTION_CODES: () => WORKFLOW_SETTING_REJECTION_CODES,
|
|
127920
128008
|
WORKFLOW_SETTING_TYPES: () => WORKFLOW_SETTING_TYPES,
|
|
127921
128009
|
WORKFLOW_WORK_ITEM_KINDS: () => WORKFLOW_WORK_ITEM_KINDS,
|
|
@@ -128321,6 +128409,7 @@ __export(src_exports, {
|
|
|
128321
128409
|
hasRoleOverrides: () => hasRoleOverrides,
|
|
128322
128410
|
hasSyncPassphraseConfigured: () => hasSyncPassphraseConfigured,
|
|
128323
128411
|
hasTitleIdDrift: () => hasTitleIdDrift,
|
|
128412
|
+
hasUserAutoMergeHold: () => hasUserAutoMergeHold,
|
|
128324
128413
|
hashWorkflowIr: () => hashWorkflowIr,
|
|
128325
128414
|
healSchemaDrift: () => healSchemaDrift,
|
|
128326
128415
|
importMcpServersJson: () => importMcpServersJson,
|
|
@@ -128443,6 +128532,7 @@ __export(src_exports, {
|
|
|
128443
128532
|
isWipColumn: () => isWipColumn,
|
|
128444
128533
|
isWipColumnRole: () => isWipColumnRole,
|
|
128445
128534
|
isWorkflowOptionalGroupEnabled: () => isWorkflowOptionalGroupEnabled,
|
|
128535
|
+
isWorkflowReviewFindingSeverity: () => isWorkflowReviewFindingSeverity,
|
|
128446
128536
|
isWorkspaceTask: () => isWorkspaceTask,
|
|
128447
128537
|
layoutForIr: () => layoutForIr,
|
|
128448
128538
|
listActiveAiSessions: () => listActiveAiSessions,
|
|
@@ -128516,6 +128606,7 @@ __export(src_exports, {
|
|
|
128516
128606
|
normalizeValidationDiagnostics: () => normalizeValidationDiagnostics,
|
|
128517
128607
|
normalizeWorkflowIcon: () => normalizeWorkflowIcon,
|
|
128518
128608
|
normalizeWorkflowPromptOverrides: () => normalizeWorkflowPromptOverrides,
|
|
128609
|
+
normalizeWorkflowReviewFindings: () => normalizeWorkflowReviewFindings,
|
|
128519
128610
|
notifyOperatorOfNonOperatorDelete: () => notifyOperatorOfNonOperatorDelete,
|
|
128520
128611
|
overseerAdviceSeverityRank: () => overseerAdviceSeverityRank,
|
|
128521
128612
|
parseAgentManifest: () => parseAgentManifest,
|
|
@@ -128779,6 +128870,7 @@ __export(src_exports, {
|
|
|
128779
128870
|
runMemoryBackupCommand: () => runMemoryBackupCommand,
|
|
128780
128871
|
runReconciliationAbort: () => runReconciliationAbort,
|
|
128781
128872
|
runScheduledEvalBatch: () => runScheduledEvalBatch,
|
|
128873
|
+
runWithFusionSessionIdentity: () => runWithFusionSessionIdentity,
|
|
128782
128874
|
sanitizeBranchSegment: () => sanitizeBranchSegment,
|
|
128783
128875
|
sanitizeCliAgentSettings: () => sanitizeCliAgentSettings,
|
|
128784
128876
|
sanitizeCliAgentsSettings: () => sanitizeCliAgentsSettings,
|
|
@@ -158170,6 +158262,7 @@ import { existsSync as existsSync43, readFileSync as readFileSync15, realpathSyn
|
|
|
158170
158262
|
import { exec as exec2, execFile as execFile7 } from "node:child_process";
|
|
158171
158263
|
import { promisify as promisify6 } from "node:util";
|
|
158172
158264
|
import { createRequire as createRequire5 } from "node:module";
|
|
158265
|
+
import { randomUUID as randomUUID43 } from "node:crypto";
|
|
158173
158266
|
import { basename as basename13, dirname as dirname21, join as join56, relative as relative6, isAbsolute as isAbsolute8, resolve as resolve24 } from "node:path";
|
|
158174
158267
|
import {
|
|
158175
158268
|
createAgentSession,
|
|
@@ -159880,7 +159973,8 @@ async function createFnAgent2(options) {
|
|
|
159880
159973
|
});
|
|
159881
159974
|
};
|
|
159882
159975
|
const sessionIdentity = (() => {
|
|
159883
|
-
const
|
|
159976
|
+
const namedAgentId = options.actionGateContext?.agentId ?? options.permanentAgentGating?.requester?.actorId;
|
|
159977
|
+
const principalAgentId = namedAgentId ?? `engine-session-${randomUUID43()}`;
|
|
159884
159978
|
const principalAgentName = options.actionGateContext?.agentName ?? options.permanentAgentGating?.requester?.actorName;
|
|
159885
159979
|
return {
|
|
159886
159980
|
agentId: principalAgentId,
|
|
@@ -159892,6 +159986,14 @@ async function createFnAgent2(options) {
|
|
|
159892
159986
|
const sessionIdentityKeys = [...new Set([options.cwd, resolvedProjectRoot].filter((key) => Boolean(key)))];
|
|
159893
159987
|
const attachSessionIdentity = (session) => {
|
|
159894
159988
|
const identityDisposers = sessionIdentityKeys.map((key) => registerFusionSessionIdentity(key, sessionIdentity));
|
|
159989
|
+
const sessionInvocations = session;
|
|
159990
|
+
const wrapInvocation = (methodName) => {
|
|
159991
|
+
const original = sessionInvocations[methodName];
|
|
159992
|
+
if (typeof original !== "function") return;
|
|
159993
|
+
sessionInvocations[methodName] = (...args) => runWithFusionSessionIdentity(sessionIdentityKeys, sessionIdentity, () => original.apply(session, args));
|
|
159994
|
+
};
|
|
159995
|
+
wrapInvocation("prompt");
|
|
159996
|
+
wrapInvocation("promptWithFallback");
|
|
159895
159997
|
const disposeBeforeIdentity = typeof session.dispose === "function" ? session.dispose.bind(session) : () => void 0;
|
|
159896
159998
|
session.dispose = async () => {
|
|
159897
159999
|
for (const disposeIdentity of identityDisposers) {
|
|
@@ -168091,10 +168193,11 @@ function createMergeAttemptHandler(deps) {
|
|
|
168091
168193
|
);
|
|
168092
168194
|
};
|
|
168093
168195
|
}
|
|
168094
|
-
function createMergeGateHandler() {
|
|
168196
|
+
function createMergeGateHandler(deps = {}) {
|
|
168095
168197
|
return async (_node, ctx) => {
|
|
168096
168198
|
const settingsAutoMerge = ctx.settings?.autoMerge;
|
|
168097
|
-
const
|
|
168199
|
+
const settings = { autoMerge: settingsAutoMerge ?? true };
|
|
168200
|
+
const autoMerge = !hasUserAutoMergeHold(ctx.task) && (await deps.isLiveSharedBranchMember?.(ctx.task, settings) === true || ctx.task.autoMerge !== false && settings.autoMerge !== false);
|
|
168098
168201
|
return {
|
|
168099
168202
|
outcome: "success",
|
|
168100
168203
|
value: autoMerge ? "auto-on" : "auto-off"
|
|
@@ -168104,6 +168207,7 @@ function createMergeGateHandler() {
|
|
|
168104
168207
|
var init_merge_runner = __esm({
|
|
168105
168208
|
"../engine/src/workflow-node-runners/merge-runner.ts"() {
|
|
168106
168209
|
"use strict";
|
|
168210
|
+
init_src2();
|
|
168107
168211
|
init_workflow_merge_nodes();
|
|
168108
168212
|
}
|
|
168109
168213
|
});
|
|
@@ -168447,7 +168551,7 @@ function createDefaultNodeHandlers(seams, runCustomNode, deps) {
|
|
|
168447
168551
|
"parse-steps": parseSteps,
|
|
168448
168552
|
code: createCodeNodeHandler(deps?.runCode),
|
|
168449
168553
|
notify: createNotifyHandler(deps?.notifyDispatch),
|
|
168450
|
-
"merge-gate": createMergeGateHandler(),
|
|
168554
|
+
"merge-gate": createMergeGateHandler({ isLiveSharedBranchMember: deps?.isLiveSharedBranchMember }),
|
|
168451
168555
|
"merge-attempt": createMergeAttemptHandler({
|
|
168452
168556
|
primitives: deps?.primitives,
|
|
168453
168557
|
seams,
|
|
@@ -168845,7 +168949,7 @@ var init_code_node_runner = __esm({
|
|
|
168845
168949
|
// ../engine/src/agent-tools.ts
|
|
168846
168950
|
import { appendFile as appendFile3, mkdir as mkdir26, readFile as readFile32, readdir as readdir9, realpath, stat as stat9, writeFile as writeFile24 } from "node:fs/promises";
|
|
168847
168951
|
import { existsSync as existsSync50 } from "node:fs";
|
|
168848
|
-
import { createHash as createHash19, randomUUID as
|
|
168952
|
+
import { createHash as createHash19, randomUUID as randomUUID44 } from "node:crypto";
|
|
168849
168953
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
168850
168954
|
import { extname as extname3, isAbsolute as isAbsolute12, join as join62, relative as relative11, resolve as resolve33, sep as sep9 } from "node:path";
|
|
168851
168955
|
import { Type as Type2 } from "@earendil-works/pi-ai";
|
|
@@ -169491,7 +169595,7 @@ function createTaskCreateTool(store, provenance, options) {
|
|
|
169491
169595
|
toType: "user",
|
|
169492
169596
|
type: "agent-to-user",
|
|
169493
169597
|
content: `Task proposal awaiting validation: ${title2}`,
|
|
169494
|
-
metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey:
|
|
169598
|
+
metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey: randomUUID44(), taskId: options.sourceTaskId, proposedTask: { title: title2, description: params.description, priority: params.priority, workflowId: params.workflow_id, dependencies: params.dependencies } }
|
|
169495
169599
|
});
|
|
169496
169600
|
return { content: [{ type: "text", text: "Task proposal submitted to the operator for validation; no task was created." }], details: { proposed: true } };
|
|
169497
169601
|
}
|
|
@@ -173916,37 +174020,6 @@ var init_effective_settings = __esm({
|
|
|
173916
174020
|
}
|
|
173917
174021
|
});
|
|
173918
174022
|
|
|
173919
|
-
// ../engine/src/errors/transient-merge-error-classifier.ts
|
|
173920
|
-
function classifyTransientMergeError(error3) {
|
|
173921
|
-
if (!error3) return null;
|
|
173922
|
-
if (/lease-handoff-failed[^a-z]+target-not-queued/i.test(error3)) {
|
|
173923
|
-
return "lease-handoff-target-not-queued";
|
|
173924
|
-
}
|
|
173925
|
-
if (/\bACP turn failed\b/i.test(error3) || /\bacp rpc code -32(?:603|00[0-3])\b/i.test(error3)) {
|
|
173926
|
-
return "ai-provider-turn-failure";
|
|
173927
|
-
}
|
|
173928
|
-
if (/\bspawn(?:\s+\S+)?\s+ENO(?:TDIR|ENT)\b/i.test(error3)) {
|
|
173929
|
-
return "process-spawn-failure";
|
|
173930
|
-
}
|
|
173931
|
-
if (/\bis not a working tree\b/i.test(error3)) {
|
|
173932
|
-
return "process-spawn-failure";
|
|
173933
|
-
}
|
|
173934
|
-
const sameSha = error3.match(/advanced concurrently \(expected ([0-9a-f]{7,40}),\s+observed ([0-9a-f]{7,40})\)/i);
|
|
173935
|
-
if (sameSha && sameSha[1].toLowerCase() === sameSha[2].toLowerCase()) {
|
|
173936
|
-
return "spurious-concurrent-advance-same-sha";
|
|
173937
|
-
}
|
|
173938
|
-
if (isTransientError(error3)) {
|
|
173939
|
-
return "network-transport-failure";
|
|
173940
|
-
}
|
|
173941
|
-
return null;
|
|
173942
|
-
}
|
|
173943
|
-
var init_transient_merge_error_classifier = __esm({
|
|
173944
|
-
"../engine/src/errors/transient-merge-error-classifier.ts"() {
|
|
173945
|
-
"use strict";
|
|
173946
|
-
init_transient_error_patterns();
|
|
173947
|
-
}
|
|
173948
|
-
});
|
|
173949
|
-
|
|
173950
174023
|
// ../engine/src/notification/ntfy-provider.ts
|
|
173951
174024
|
function resolveParticipantLabel(metadata, kind) {
|
|
173952
174025
|
const nameKey = kind === "from" ? "fromName" : "toName";
|
|
@@ -174420,7 +174493,50 @@ var init_webhook_provider = __esm({
|
|
|
174420
174493
|
}
|
|
174421
174494
|
});
|
|
174422
174495
|
|
|
174496
|
+
// ../engine/src/errors/transient-merge-error-classifier.ts
|
|
174497
|
+
function classifyTransientMergeError(error3) {
|
|
174498
|
+
if (!error3) return null;
|
|
174499
|
+
if (/lease-handoff-failed[^a-z]+target-not-queued/i.test(error3)) {
|
|
174500
|
+
return "lease-handoff-target-not-queued";
|
|
174501
|
+
}
|
|
174502
|
+
if (/\bACP turn failed\b/i.test(error3) || /\bacp rpc code -32(?:603|00[0-3])\b/i.test(error3)) {
|
|
174503
|
+
return "ai-provider-turn-failure";
|
|
174504
|
+
}
|
|
174505
|
+
if (/\bspawn(?:\s+\S+)?\s+ENO(?:TDIR|ENT)\b/i.test(error3)) {
|
|
174506
|
+
return "process-spawn-failure";
|
|
174507
|
+
}
|
|
174508
|
+
if (/\bis not a working tree\b/i.test(error3)) {
|
|
174509
|
+
return "process-spawn-failure";
|
|
174510
|
+
}
|
|
174511
|
+
const sameSha = error3.match(/advanced concurrently \(expected ([0-9a-f]{7,40}),\s+observed ([0-9a-f]{7,40})\)/i);
|
|
174512
|
+
if (sameSha && sameSha[1].toLowerCase() === sameSha[2].toLowerCase()) {
|
|
174513
|
+
return "spurious-concurrent-advance-same-sha";
|
|
174514
|
+
}
|
|
174515
|
+
if (isTransientError(error3)) {
|
|
174516
|
+
return "network-transport-failure";
|
|
174517
|
+
}
|
|
174518
|
+
return null;
|
|
174519
|
+
}
|
|
174520
|
+
function hasTransientMergeRecoveryOwner(task) {
|
|
174521
|
+
return classifyTransientMergeError(task.error) !== null && typeof task.mergeTransientRetryCount === "number" && Number.isInteger(task.mergeTransientRetryCount) && task.mergeTransientRetryCount >= 0 && task.mergeTransientRetryCount < MAX_AUTO_MERGE_TRANSIENT_RETRIES;
|
|
174522
|
+
}
|
|
174523
|
+
var MAX_AUTO_MERGE_TRANSIENT_RETRIES;
|
|
174524
|
+
var init_transient_merge_error_classifier = __esm({
|
|
174525
|
+
"../engine/src/errors/transient-merge-error-classifier.ts"() {
|
|
174526
|
+
"use strict";
|
|
174527
|
+
init_transient_error_patterns();
|
|
174528
|
+
MAX_AUTO_MERGE_TRANSIENT_RETRIES = 5;
|
|
174529
|
+
}
|
|
174530
|
+
});
|
|
174531
|
+
|
|
174423
174532
|
// ../engine/src/notification/task-wedge-notification.ts
|
|
174533
|
+
function describeTaskRecoveryOwner(task) {
|
|
174534
|
+
if (hasTransientMergeRecoveryOwner(task)) return { kind: "transient-merge-retry" };
|
|
174535
|
+
if (typeof task.recoveryRetryCount === "number" && Number.isInteger(task.recoveryRetryCount) && task.recoveryRetryCount >= 0 && typeof task.nextRecoveryAt === "string" && Number.isFinite(Date.parse(task.nextRecoveryAt))) {
|
|
174536
|
+
return { kind: "scheduled-recovery" };
|
|
174537
|
+
}
|
|
174538
|
+
return null;
|
|
174539
|
+
}
|
|
174424
174540
|
function describeSelfHealingNoActionWedge(task, stage, metadata) {
|
|
174425
174541
|
const description = SELF_HEALING_NO_ACTIONS[stage];
|
|
174426
174542
|
if (!description || task.userPaused || task.paused || task.autoMerge === false) return null;
|
|
@@ -174478,6 +174594,7 @@ function describeTaskWedge(task) {
|
|
|
174478
174594
|
if (/merge.*(?:blocked|verification|gate)|(?:verification|gate).*(?:failed|exhaust)/i.test(error3)) {
|
|
174479
174595
|
return { reasonKey: "merge-blocked", reason: "Merge verification cannot progress without operator action.", action: "Fix the failing verification, then retry the task." };
|
|
174480
174596
|
}
|
|
174597
|
+
if (describeTaskRecoveryOwner(task)) return null;
|
|
174481
174598
|
if (!error3 && (task.mergeRetries ?? 0) < 3) return null;
|
|
174482
174599
|
return {
|
|
174483
174600
|
reasonKey: "terminal-failed",
|
|
@@ -174489,6 +174606,7 @@ var SELF_HEALING_NO_ACTIONS;
|
|
|
174489
174606
|
var init_task_wedge_notification = __esm({
|
|
174490
174607
|
"../engine/src/notification/task-wedge-notification.ts"() {
|
|
174491
174608
|
"use strict";
|
|
174609
|
+
init_transient_merge_error_classifier();
|
|
174492
174610
|
SELF_HEALING_NO_ACTIONS = {
|
|
174493
174611
|
"reclaim-pr-conflict": {
|
|
174494
174612
|
reason: "Self-healing could not reclaim a stalled pull-request conflict.",
|
|
@@ -174554,7 +174672,6 @@ var init_notification_service = __esm({
|
|
|
174554
174672
|
init_src2();
|
|
174555
174673
|
init_notifier();
|
|
174556
174674
|
init_logger3();
|
|
174557
|
-
init_transient_merge_error_classifier();
|
|
174558
174675
|
init_ntfy_provider();
|
|
174559
174676
|
init_webhook_provider();
|
|
174560
174677
|
init_task_wedge_notification();
|
|
@@ -174780,10 +174897,10 @@ var init_notification_service = __esm({
|
|
|
174780
174897
|
}
|
|
174781
174898
|
}
|
|
174782
174899
|
handleTaskUpdated = (task, meta2) => {
|
|
174783
|
-
const
|
|
174784
|
-
const wedge =
|
|
174900
|
+
const recoveryOwner = task.status === "failed" ? describeTaskRecoveryOwner(task) : null;
|
|
174901
|
+
const wedge = describeTaskWedge(task);
|
|
174785
174902
|
if (wedge) this.cancelPendingFailureNotification(task.id, "classified-terminal-wedge");
|
|
174786
|
-
|
|
174903
|
+
void this.enqueueWedgeHandling(task.id, () => this.maybeNotifyTaskWedge(task, wedge));
|
|
174787
174904
|
void this.maybeSuppressTransientFailedNotification(task, `status=${task.status ?? "undefined"}`);
|
|
174788
174905
|
if (task.status === "awaiting-approval") {
|
|
174789
174906
|
void this.writeAwaitingApprovalMailboxMessage(task);
|
|
@@ -174794,17 +174911,12 @@ var init_notification_service = __esm({
|
|
|
174794
174911
|
if (!this.notificationsEnabled) {
|
|
174795
174912
|
return;
|
|
174796
174913
|
}
|
|
174797
|
-
if (task.status === "failed" &&
|
|
174798
|
-
|
|
174799
|
-
|
|
174800
|
-
|
|
174801
|
-
schedulerLog.debug(
|
|
174802
|
-
`[notify] ${task.id} transient merge failure (${transientClass}) \u2014 suppressed notification (self-heal in flight)`
|
|
174803
|
-
);
|
|
174804
|
-
return;
|
|
174805
|
-
}
|
|
174914
|
+
if (task.status === "failed" && recoveryOwner) {
|
|
174915
|
+
this.failureNotificationSuppressedCount += 1;
|
|
174916
|
+
schedulerLog.debug(`[notify] ${task.id} recovery-owned failure \u2014 suppressed notification`);
|
|
174917
|
+
} else if (task.status === "failed" && !wedge) {
|
|
174806
174918
|
if (this.failureNotificationMode === "all") {
|
|
174807
|
-
|
|
174919
|
+
void this.maybeNotifyImmediateFailure(task);
|
|
174808
174920
|
} else {
|
|
174809
174921
|
this.scheduleFailureNotification(task);
|
|
174810
174922
|
}
|
|
@@ -174891,7 +175003,17 @@ var init_notification_service = __esm({
|
|
|
174891
175003
|
await this.enqueueWedgeHandling(task.id, () => this.maybeNotifyTaskWedge(task, descriptor));
|
|
174892
175004
|
}
|
|
174893
175005
|
async maybeNotifyTaskWedge(task, suppliedDescriptor) {
|
|
174894
|
-
const
|
|
175006
|
+
const liveTask = this.store.getTask ? await this.store.getTask(task.id) ?? task : task;
|
|
175007
|
+
const recoveryOwner = describeTaskRecoveryOwner(liveTask);
|
|
175008
|
+
if (recoveryOwner) {
|
|
175009
|
+
if (this.activeWedgeReasons.has(task.id) || liveTask.wedgeNotification?.status === "active") {
|
|
175010
|
+
this.activeWedgeReasons.delete(task.id);
|
|
175011
|
+
await this.store.claimTaskWedgeNotificationEpisode?.(task.id, null);
|
|
175012
|
+
}
|
|
175013
|
+
return;
|
|
175014
|
+
}
|
|
175015
|
+
const descriptor = suppliedDescriptor ?? describeTaskWedge(liveTask);
|
|
175016
|
+
task = liveTask;
|
|
174895
175017
|
let episode;
|
|
174896
175018
|
if (!descriptor) {
|
|
174897
175019
|
const isActiveSelfHealingNoAction = task.wedgeNotification?.status === "active" && task.wedgeNotification.reasonKey.startsWith("self-healing-no-action:");
|
|
@@ -175258,6 +175380,14 @@ var init_notification_service = __esm({
|
|
|
175258
175380
|
this.failureNotificationDelayMs = typeof settings.failureNotificationDelayMs === "number" && settings.failureNotificationDelayMs >= 0 ? settings.failureNotificationDelayMs : this.failedNotificationGraceMs;
|
|
175259
175381
|
this.failureNotificationMode = settings.failureNotificationMode ?? "sticky-only";
|
|
175260
175382
|
}
|
|
175383
|
+
async maybeNotifyImmediateFailure(task) {
|
|
175384
|
+
const liveTask = this.store.getTask ? await this.store.getTask(task.id) ?? task : task;
|
|
175385
|
+
if (liveTask.status !== "failed" || describeTaskRecoveryOwner(liveTask) || describeTaskWedge(liveTask)) {
|
|
175386
|
+
this.failureNotificationSuppressedCount += 1;
|
|
175387
|
+
return;
|
|
175388
|
+
}
|
|
175389
|
+
this.maybeNotify(liveTask.id, "failed", this.createTaskPayload(liveTask, "failed"));
|
|
175390
|
+
}
|
|
175261
175391
|
scheduleFailureNotification(task) {
|
|
175262
175392
|
if (this.pendingFailureNotifications.has(task.id)) {
|
|
175263
175393
|
return;
|
|
@@ -175314,12 +175444,9 @@ var init_notification_service = __esm({
|
|
|
175314
175444
|
schedulerLog.debug(`[notify] ${taskId} no longer failed at dispatch time \u2014 suppressed notification`);
|
|
175315
175445
|
return;
|
|
175316
175446
|
}
|
|
175317
|
-
|
|
175318
|
-
if (transientClassAtDispatch) {
|
|
175447
|
+
if (describeTaskRecoveryOwner(task)) {
|
|
175319
175448
|
this.failureNotificationSuppressedCount += 1;
|
|
175320
|
-
schedulerLog.debug(
|
|
175321
|
-
`[notify] ${taskId} transient merge failure (${transientClassAtDispatch}) at dispatch time \u2014 suppressed notification (self-heal in flight)`
|
|
175322
|
-
);
|
|
175449
|
+
schedulerLog.debug(`[notify] ${taskId} recovery-owned failure at dispatch time \u2014 suppressed notification`);
|
|
175323
175450
|
return;
|
|
175324
175451
|
}
|
|
175325
175452
|
if (describeTaskWedge(task)) {
|
|
@@ -186974,10 +187101,21 @@ var init_scheduler = __esm({
|
|
|
186974
187101
|
const unmetDeps = getUnmetSchedulingDependencies(task, tasks2, schedulingDependencyOptions);
|
|
186975
187102
|
if (unmetDeps.length > 0) {
|
|
186976
187103
|
const normalizedUnmetDeps = [...new Set(unmetDeps)].sort();
|
|
187104
|
+
let activeOverlapBlockedBy = null;
|
|
187105
|
+
if (activeScopes.size > 0) {
|
|
187106
|
+
try {
|
|
187107
|
+
const taskScope = await getFilteredFileScope(task.id);
|
|
187108
|
+
if (taskScope.length > 0 && !isCoordinationOnlyTask(task, taskScope)) {
|
|
187109
|
+
activeOverlapBlockedBy = Array.from(activeScopes.entries()).sort(([aId], [bId]) => aId.localeCompare(bId)).find(([, activeScope]) => this.pathsOverlap(taskScope, activeScope))?.[0] ?? null;
|
|
187110
|
+
}
|
|
187111
|
+
} catch (error3) {
|
|
187112
|
+
schedulerLog.warn(`Failed to refresh file-scope overlap blocker for dependency-blocked task ${task.id}`, error3);
|
|
187113
|
+
}
|
|
187114
|
+
}
|
|
186977
187115
|
await this.transitionQueuedEpisode(task, {
|
|
186978
187116
|
signature: `dependency:${normalizedUnmetDeps.join(",")}`,
|
|
186979
187117
|
blockedBy: unmetDeps[0] ?? null,
|
|
186980
|
-
overlapBlockedBy:
|
|
187118
|
+
overlapBlockedBy: activeOverlapBlockedBy,
|
|
186981
187119
|
action: `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`
|
|
186982
187120
|
});
|
|
186983
187121
|
this.options.onBlocked?.(task, unmetDeps);
|
|
@@ -203034,16 +203172,29 @@ var init_self_healing = __esm({
|
|
|
203034
203172
|
activeWork: await this.resolveActiveWorkColumnsFor(taskId, cache7)
|
|
203035
203173
|
};
|
|
203036
203174
|
}
|
|
203037
|
-
|
|
203175
|
+
/*
|
|
203176
|
+
FNXC:SharedBranchMemberHold 2026-08-05-23:35:
|
|
203177
|
+
Pause-abort recovery must resolve the same live intermediate-group predicate as
|
|
203178
|
+
merge admission. Shared metadata alone is stale after group closure or a
|
|
203179
|
+
default-branch collision, so it cannot suppress that task's standalone hold.
|
|
203180
|
+
*/
|
|
203181
|
+
async isLiveSharedMemberIntegration(task, settings) {
|
|
203182
|
+
const groupId = task.branchContext?.groupId?.trim();
|
|
203183
|
+
const group = groupId ? await this.store.getBranchGroup?.(groupId) : null;
|
|
203184
|
+
const defaultBranch = await resolveIntegrationBranch(this.options.rootDir, settings);
|
|
203185
|
+
return isLiveSharedBranchGroupMemberIntegration(task, group, defaultBranch);
|
|
203186
|
+
}
|
|
203187
|
+
async classifyPausedAbortWorkflowRecovery(task, settings, isExecuting, columns) {
|
|
203038
203188
|
const isPausedAbortPark = task.status === "failed" && typeof task.error === "string" && task.error.includes(PAUSE_ABORT_PARK_OPERATOR_MARKER) && task.error.includes(PAUSE_ABORT_PARK_ERROR_MARKER);
|
|
203039
203189
|
if (!isPausedAbortPark) return { kind: "no-action", reason: "not-pause-abort" };
|
|
203040
203190
|
if (task.paused || task.userPaused || isExecuting) return { kind: "no-action", reason: "unsafe-or-not-routable" };
|
|
203041
203191
|
const errorText = typeof task.error === "string" ? task.error.toLowerCase() : "";
|
|
203042
203192
|
const isTerminalMergePark = errorText.includes("conflict") || errorText.includes("contamination") || errorText.includes("foreign") || errorText.includes("retry-exhausted") || errorText.includes("retries exhausted") || errorText.includes("max retries");
|
|
203043
203193
|
const completedSteps = task.steps.length > 0 && task.steps.every((step) => step.status === "done" || step.status === "skipped");
|
|
203044
|
-
const
|
|
203045
|
-
const
|
|
203046
|
-
const
|
|
203194
|
+
const liveSharedBranchMember = await this.isLiveSharedMemberIntegration(task, settings);
|
|
203195
|
+
const autoMergeProcessing = allowsAutoMergeProcessing(task, settings) || liveSharedBranchMember;
|
|
203196
|
+
const hasReviewProgress = columns.review.has(task.column) && autoMergeProcessing && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
|
|
203197
|
+
const hasManualMergeHoldProgress = columns.review.has(task.column) && (hasUserAutoMergeHold(task) || !allowsAutoMergeProcessing(task, settings) || resolveEffectiveAutoMerge(task, settings) === false) && (!liveSharedBranchMember || hasUserAutoMergeHold(task)) && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
|
|
203047
203198
|
if (hasManualMergeHoldProgress) {
|
|
203048
203199
|
return { kind: "work-item-resume", reason: "pause-abort-manual-merge-hold" };
|
|
203049
203200
|
}
|
|
@@ -208711,8 +208862,23 @@ var init_self_healing = __esm({
|
|
|
208711
208862
|
return own.length > 0 ? new Set(own) : /* @__PURE__ */ new Set(["in-review"]);
|
|
208712
208863
|
};
|
|
208713
208864
|
const executingIds = this.options.getExecutingTaskIds?.() ?? /* @__PURE__ */ new Set();
|
|
208865
|
+
const canRecoverMergeableReviewTask = async (task) => {
|
|
208866
|
+
if (hasUserAutoMergeHold(task)) return false;
|
|
208867
|
+
const groupId = task.branchContext?.groupId?.trim();
|
|
208868
|
+
const branchGroup = groupId ? await this.store.getBranchGroup(groupId) : null;
|
|
208869
|
+
const projectDefaultBranch = await resolveIntegrationBranch(this.options.rootDir, settings);
|
|
208870
|
+
if (isLiveSharedBranchGroupMemberIntegration(task, branchGroup, projectDefaultBranch)) {
|
|
208871
|
+
return true;
|
|
208872
|
+
}
|
|
208873
|
+
return allowsAutoMergeProcessing(task, settings) && resolveEffectiveAutoMerge(task, settings) !== false;
|
|
208874
|
+
};
|
|
208875
|
+
const mergeAdmission = await Promise.all(tasks2.map(async (task) => [
|
|
208876
|
+
task.id,
|
|
208877
|
+
await canRecoverMergeableReviewTask(task)
|
|
208878
|
+
]));
|
|
208879
|
+
const mergeAdmissionByTaskId = new Map(mergeAdmission);
|
|
208714
208880
|
const mergeable = tasks2.filter(
|
|
208715
|
-
(t) =>
|
|
208881
|
+
(t) => mergeAdmissionByTaskId.get(t.id) === true && !t.paused && !executingIds.has(t.id) && t.status !== "failed" && // Exclude transient merge statuses. Active merges should be left alone;
|
|
208716
208882
|
// stale ones are handled by recoverStaleMergingStatus().
|
|
208717
208883
|
t.status !== "merging" && t.status !== "merging-pr" && // FNXC:Workspace 2026-06-22-09:30 (Phase D U1, KTD1 — admit workspace tasks):
|
|
208718
208884
|
// A workspace task has task.worktree===null (its worktrees live per-repo in
|
|
@@ -211759,7 +211925,7 @@ var init_self_healing = __esm({
|
|
|
211759
211925
|
for (const t of tasks2) {
|
|
211760
211926
|
if (!this.isPauseAbortParkCandidate(t)) continue;
|
|
211761
211927
|
const columns = await this.resolvePauseAbortColumnsFor(t.id, columnCache);
|
|
211762
|
-
if (this.classifyPausedAbortWorkflowRecovery(t, settings, executingIds.has(t.id), columns).kind !== "no-action") {
|
|
211928
|
+
if ((await this.classifyPausedAbortWorkflowRecovery(t, settings, executingIds.has(t.id), columns)).kind !== "no-action") {
|
|
211763
211929
|
parked.push(t);
|
|
211764
211930
|
}
|
|
211765
211931
|
}
|
|
@@ -211776,7 +211942,7 @@ var init_self_healing = __esm({
|
|
|
211776
211942
|
continue;
|
|
211777
211943
|
}
|
|
211778
211944
|
const freshColumns = await this.resolvePauseAbortColumnsFor(fresh.id, columnCache);
|
|
211779
|
-
const route = this.classifyPausedAbortWorkflowRecovery(fresh, settings, latestExecutingIds.has(fresh.id), freshColumns);
|
|
211945
|
+
const route = await this.classifyPausedAbortWorkflowRecovery(fresh, settings, latestExecutingIds.has(fresh.id), freshColumns);
|
|
211780
211946
|
if (route.kind === "no-action") {
|
|
211781
211947
|
continue;
|
|
211782
211948
|
}
|
|
@@ -218779,7 +218945,7 @@ function recoverPassedPlanReviewFromLatestLog(task) {
|
|
|
218779
218945
|
completedAt: latest.timestamp
|
|
218780
218946
|
};
|
|
218781
218947
|
}
|
|
218782
|
-
var PLAN_REVIEW_PROVIDER_FAILURE_HOLD_VALUE, PLAN_REVIEW_LEASE_HELD_VALUE, SESSION_CONTENTION_HOLD_VALUE, WORKFLOW_INTERRUPTED_NODE_ID_CONTEXT_KEY, WORKFLOW_INTERRUPTED_NODE_ABORT_KIND_CONTEXT_KEY, WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY, WORKFLOW_NODE_ENGINE_PAUSE_ABORT_KIND, WORKFLOW_DRIFT_PARK_CONTEXT_KEY, WorkflowGraphSuspended, MERGE_REGION_KINDS, WorkflowGraphExecutor;
|
|
218948
|
+
var PLAN_REVIEW_PROVIDER_FAILURE_HOLD_VALUE, PLAN_REVIEW_LEASE_HELD_VALUE, SESSION_CONTENTION_HOLD_VALUE, WORKFLOW_INTERRUPTED_NODE_ID_CONTEXT_KEY, WORKFLOW_INTERRUPTED_NODE_ABORT_KIND_CONTEXT_KEY, WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY, WORKFLOW_REVIEW_KIND_CONTEXT_KEY, WORKFLOW_NODE_ENGINE_PAUSE_ABORT_KIND, WORKFLOW_DRIFT_PARK_CONTEXT_KEY, WorkflowGraphSuspended, MERGE_REGION_KINDS, WorkflowGraphExecutor;
|
|
218783
218949
|
var init_workflow_graph_executor = __esm({
|
|
218784
218950
|
"../engine/src/workflows/workflow-graph-executor.ts"() {
|
|
218785
218951
|
"use strict";
|
|
@@ -218799,6 +218965,7 @@ var init_workflow_graph_executor = __esm({
|
|
|
218799
218965
|
WORKFLOW_INTERRUPTED_NODE_ID_CONTEXT_KEY = "workflow:interruptedNodeId";
|
|
218800
218966
|
WORKFLOW_INTERRUPTED_NODE_ABORT_KIND_CONTEXT_KEY = "workflow:interruptedNodeAbortKind";
|
|
218801
218967
|
WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY = "workflow:optionalGroupActive";
|
|
218968
|
+
WORKFLOW_REVIEW_KIND_CONTEXT_KEY = "workflow:reviewKind";
|
|
218802
218969
|
WORKFLOW_NODE_ENGINE_PAUSE_ABORT_KIND = "engine-pause";
|
|
218803
218970
|
WORKFLOW_DRIFT_PARK_CONTEXT_KEY = "workflow:driftPark";
|
|
218804
218971
|
WorkflowGraphSuspended = class extends Error {
|
|
@@ -218826,7 +218993,8 @@ var init_workflow_graph_executor = __esm({
|
|
|
218826
218993
|
parseSteps: deps.parseStepsDeps,
|
|
218827
218994
|
runCode: deps.runCode,
|
|
218828
218995
|
notifyDispatch: deps.notifyDispatch,
|
|
218829
|
-
prNodes: deps.prNodes
|
|
218996
|
+
prNodes: deps.prNodes,
|
|
218997
|
+
isLiveSharedBranchMember: deps.isLiveSharedBranchMember
|
|
218830
218998
|
}),
|
|
218831
218999
|
...deps.runnerRegistry?.toHandlers() ?? {},
|
|
218832
219000
|
...deps.handlers ?? {}
|
|
@@ -219047,6 +219215,7 @@ var init_workflow_graph_executor = __esm({
|
|
|
219047
219215
|
phase: stepPhase,
|
|
219048
219216
|
status: "pending",
|
|
219049
219217
|
source: "optional-group",
|
|
219218
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
219050
219219
|
startedAt: stepStartedAt,
|
|
219051
219220
|
// U3/KTD-4: stamp the lease owner so a concurrent/crashed re-entry
|
|
219052
219221
|
// adopts this pending gate instead of dispatching a second reviewer.
|
|
@@ -219066,7 +219235,8 @@ var init_workflow_graph_executor = __esm({
|
|
|
219066
219235
|
runTemplateNode: (tNode, sig, contextOverride) => {
|
|
219067
219236
|
const optionalGroupContext = {
|
|
219068
219237
|
...contextOverride ?? context,
|
|
219069
|
-
[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY]: node.id
|
|
219238
|
+
[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY]: node.id,
|
|
219239
|
+
...this.workflowReviewKind(node) ? { [WORKFLOW_REVIEW_KIND_CONTEXT_KEY]: this.workflowReviewKind(node) } : {}
|
|
219070
219240
|
};
|
|
219071
219241
|
return this.executeNodeWithRetries(tNode, task, settings, optionalGroupContext, ir2, sig, false);
|
|
219072
219242
|
},
|
|
@@ -219084,6 +219254,7 @@ var init_workflow_graph_executor = __esm({
|
|
|
219084
219254
|
const exitContextPatch = exitResult?.contextPatch;
|
|
219085
219255
|
let stepOutput = typeof exitContextPatch?.output === "string" ? exitContextPatch.output : void 0;
|
|
219086
219256
|
const stepNotes = typeof exitContextPatch?.notes === "string" ? exitContextPatch.notes : void 0;
|
|
219257
|
+
const stepFindings = this.workflowReviewKind(node) && Array.isArray(exitContextPatch?.findings) ? exitContextPatch.findings : void 0;
|
|
219087
219258
|
if (stepStatus === "failed" && !verdict && stepOutput === void 0 && stepNotes === void 0) {
|
|
219088
219259
|
const lastVisited = groupResult.visitedNodeIds[groupResult.visitedNodeIds.length - 1];
|
|
219089
219260
|
const templateNodeId = lastVisited?.includes("::") ? lastVisited.slice(lastVisited.indexOf("::") + 2) : void 0;
|
|
@@ -219101,9 +219272,11 @@ var init_workflow_graph_executor = __esm({
|
|
|
219101
219272
|
phase: stepPhase,
|
|
219102
219273
|
source: "optional-group",
|
|
219103
219274
|
status: stepStatus,
|
|
219275
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
219104
219276
|
...verdict ? { verdict } : {},
|
|
219105
219277
|
...stepOutput !== void 0 ? { output: stepOutput } : {},
|
|
219106
219278
|
...stepNotes !== void 0 ? { notes: stepNotes } : {},
|
|
219279
|
+
...stepFindings?.length ? { findings: stepFindings } : {},
|
|
219107
219280
|
startedAt: stepStartedAt,
|
|
219108
219281
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
219109
219282
|
});
|
|
@@ -219563,9 +219736,15 @@ var init_workflow_graph_executor = __esm({
|
|
|
219563
219736
|
}
|
|
219564
219737
|
return failureResult;
|
|
219565
219738
|
}
|
|
219739
|
+
/** FNXC:WorkflowReviewKind 2026-08-05-02:31: Persist only the declared closed
|
|
219740
|
+
* marker; execution never derives review semantics from a label, verdict, or gate mode. */
|
|
219741
|
+
workflowReviewKind(node) {
|
|
219742
|
+
return node.config?.reviewKind === "plan" || node.config?.reviewKind === "code" ? node.config.reviewKind : void 0;
|
|
219743
|
+
}
|
|
219566
219744
|
shouldRecordNodeProgress(node) {
|
|
219567
219745
|
const skillName = typeof node.config?.skillName === "string" ? node.config.skillName.trim() : "";
|
|
219568
|
-
|
|
219746
|
+
const markedReview = this.workflowReviewKind(node) !== void 0;
|
|
219747
|
+
return markedReview && (node.kind === "prompt" || node.kind === "gate" || node.kind === "script") || skillName.length > 0 && (node.kind === "prompt" || node.kind === "gate");
|
|
219569
219748
|
}
|
|
219570
219749
|
workflowNodeProgressName(node) {
|
|
219571
219750
|
const configuredName = typeof node.config?.name === "string" ? node.config.name.trim() : "";
|
|
@@ -219579,6 +219758,7 @@ var init_workflow_graph_executor = __esm({
|
|
|
219579
219758
|
phase: node.config?.phase === "post-merge" ? "post-merge" : "pre-merge",
|
|
219580
219759
|
source: "node",
|
|
219581
219760
|
status: "pending",
|
|
219761
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
219582
219762
|
startedAt
|
|
219583
219763
|
};
|
|
219584
219764
|
await this.recordOptionalGroupStepResult(taskId, result2);
|
|
@@ -219589,6 +219769,7 @@ var init_workflow_graph_executor = __esm({
|
|
|
219589
219769
|
const contextPatch = nodeResult.contextPatch ?? {};
|
|
219590
219770
|
let output = typeof contextPatch.output === "string" ? contextPatch.output : void 0;
|
|
219591
219771
|
const notes = typeof contextPatch.notes === "string" ? contextPatch.notes : void 0;
|
|
219772
|
+
const findings = this.workflowReviewKind(node) && Array.isArray(contextPatch.findings) ? contextPatch.findings : void 0;
|
|
219592
219773
|
if (status === "failed" && output === void 0 && notes === void 0) {
|
|
219593
219774
|
output = this.synthesizeNonVerdictFailureOutput({
|
|
219594
219775
|
stepLabel: this.workflowNodeProgressName(node),
|
|
@@ -219603,8 +219784,10 @@ var init_workflow_graph_executor = __esm({
|
|
|
219603
219784
|
phase: started?.phase ?? (node.config?.phase === "post-merge" ? "post-merge" : "pre-merge"),
|
|
219604
219785
|
source: "node",
|
|
219605
219786
|
status,
|
|
219787
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
219606
219788
|
...output !== void 0 ? { output } : {},
|
|
219607
219789
|
...notes !== void 0 ? { notes } : {},
|
|
219790
|
+
...findings?.length ? { findings } : {},
|
|
219608
219791
|
startedAt: started?.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
219609
219792
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
219610
219793
|
});
|
|
@@ -220047,6 +220230,10 @@ var init_workflow_graph_task_runner = __esm({
|
|
|
220047
220230
|
runCode: this.deps.runCode,
|
|
220048
220231
|
notifyDispatch: this.deps.notifyDispatch,
|
|
220049
220232
|
prNodes: this.deps.prNodes,
|
|
220233
|
+
// FNXC:SharedBranchMemberHold 2026-08-06-00:24: carry the executor's
|
|
220234
|
+
// live group resolver into the graph merge gate; omitting it turns
|
|
220235
|
+
// mission-policy members into manual holds before integration.
|
|
220236
|
+
isLiveSharedBranchMember: this.deps.isLiveSharedBranchMember,
|
|
220050
220237
|
/*
|
|
220051
220238
|
FNXC:WorkflowResume 2026-06-29-08:49:
|
|
220052
220239
|
Production graph runs must fetch live task steps during foreach replay. The runner is the workflow boundary that has store access, so it supplies the fresh projection seam instead of making executor self-healing guess after a stale step node fails.
|
|
@@ -224885,9 +225072,11 @@ function parseWorkflowStepVerdict(rawOutput) {
|
|
|
224885
225072
|
verdict = "REVISE";
|
|
224886
225073
|
}
|
|
224887
225074
|
if (!verdict) continue;
|
|
225075
|
+
const findings = normalizeWorkflowReviewFindings(parsed.findings);
|
|
224888
225076
|
return {
|
|
224889
225077
|
verdict,
|
|
224890
|
-
notes: typeof parsed.notes === "string" ? parsed.notes : ""
|
|
225078
|
+
notes: typeof parsed.notes === "string" ? parsed.notes : "",
|
|
225079
|
+
...findings ? { findings } : {}
|
|
224891
225080
|
};
|
|
224892
225081
|
} catch {
|
|
224893
225082
|
}
|
|
@@ -224919,7 +225108,8 @@ function parseWorkflowStepOutput(rawOutput, options = {}) {
|
|
|
224919
225108
|
return {
|
|
224920
225109
|
output: parsed.notes || "",
|
|
224921
225110
|
verdict: parsed.verdict,
|
|
224922
|
-
notes: parsed.notes
|
|
225111
|
+
notes: parsed.notes,
|
|
225112
|
+
...parsed.findings ? { findings: parsed.findings } : {}
|
|
224923
225113
|
};
|
|
224924
225114
|
}
|
|
224925
225115
|
const inferred = inferWorkflowStepVerdictFromProse(trimmed);
|
|
@@ -228156,6 +228346,7 @@ ${feedback}`,
|
|
|
228156
228346
|
if (info.phase !== "pre-merge") return false;
|
|
228157
228347
|
if (info.status !== "advisory_failure" && info.status !== "failed") return false;
|
|
228158
228348
|
const liveTask = await this.store.getTask(taskId).catch(() => fallbackTask);
|
|
228349
|
+
if (hasUserAutoMergeHold(liveTask)) return false;
|
|
228159
228350
|
const missingArtifactKeys = parseRequiredArtifactMissingValue(info.failureValue);
|
|
228160
228351
|
if (missingArtifactKeys) {
|
|
228161
228352
|
await this.recoverMissingRequiredArtifacts(liveTask, missingArtifactKeys, {
|
|
@@ -228412,6 +228603,7 @@ ${info.feedback}`, revisionKey),
|
|
|
228412
228603
|
*/
|
|
228413
228604
|
async recoverFailedPreMergeWorkflowStep(task) {
|
|
228414
228605
|
try {
|
|
228606
|
+
if (hasUserAutoMergeHold(task)) return false;
|
|
228415
228607
|
const failed = (task.workflowStepResults ?? []).filter((r) => (r.phase || "pre-merge") === "pre-merge" && r.status === "failed").sort((a, b3) => {
|
|
228416
228608
|
const aTs = Date.parse(a.completedAt || a.startedAt || "");
|
|
228417
228609
|
const bTs = Date.parse(b3.completedAt || b3.startedAt || "");
|
|
@@ -228938,6 +229130,7 @@ ${info.feedback}`, revisionKey),
|
|
|
228938
229130
|
getTask: (taskId) => this.store.getTask(taskId)
|
|
228939
229131
|
},
|
|
228940
229132
|
runId: resolvedRunId,
|
|
229133
|
+
isLiveSharedBranchMember: (nodeTask) => this.isLiveSharedBranchGroupMember(nodeTask),
|
|
228941
229134
|
primitives: this.createAuthoritativeWorkflowPrimitives(settings),
|
|
228942
229135
|
seams: this.createAuthoritativeWorkflowSeams(settings),
|
|
228943
229136
|
prepareNodeExecution: (node, nodeTask, requirement) => this.prepareGraphNodeExecution(node, nodeTask, settings, requirement),
|
|
@@ -231180,6 +231373,7 @@ ${info.feedback}`, revisionKey),
|
|
|
231180
231373
|
return this.runCliAgentNode(node, await this.store.getTask(live.id), cfg);
|
|
231181
231374
|
}
|
|
231182
231375
|
const optionalGroupId = typeof graphContext?.[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY] === "string" ? graphContext[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY] : void 0;
|
|
231376
|
+
const declaredReviewKind = cfg.reviewKind === "plan" || cfg.reviewKind === "code" ? cfg.reviewKind : graphContext?.[WORKFLOW_REVIEW_KIND_CONTEXT_KEY] === "plan" || graphContext?.[WORKFLOW_REVIEW_KIND_CONTEXT_KEY] === "code" ? graphContext[WORKFLOW_REVIEW_KIND_CONTEXT_KEY] : void 0;
|
|
231183
231377
|
const isCompletionSummaryNode2 = cfg.summaryTarget === "task" || node.id === "completion-summary";
|
|
231184
231378
|
if (live.executionMode === "fast" && !isCompletionSummaryNode2 && !optionalGroupId && !cfg.seam && (node.kind === "prompt" || node.kind === "script" || node.kind === "gate")) {
|
|
231185
231379
|
executorLog.debug(`${live.id}: fast mode \u2014 skipping custom graph node '${node.id}'`);
|
|
@@ -231328,6 +231522,9 @@ ${prompt}`;
|
|
|
231328
231522
|
if (optionalGroupId) {
|
|
231329
231523
|
step.optionalGroupId = optionalGroupId;
|
|
231330
231524
|
}
|
|
231525
|
+
if (declaredReviewKind) {
|
|
231526
|
+
step.reviewKind = declaredReviewKind;
|
|
231527
|
+
}
|
|
231331
231528
|
if (cfg.reviewCanFixInline === true) {
|
|
231332
231529
|
step.reviewCanFixInline = true;
|
|
231333
231530
|
}
|
|
@@ -231340,7 +231537,11 @@ ${prompt}`;
|
|
|
231340
231537
|
executorLog.debug(`${live.id}: graph node '${node.id}' runtime env injected (${injected.pathEntryCount} PATH entries, ${injected.injectedKeyCount} env keys)`);
|
|
231341
231538
|
}
|
|
231342
231539
|
const unattended = this.graphUnattendedRuns.has(live.id);
|
|
231343
|
-
|
|
231540
|
+
let outcome = mode === "script" ? await this.executeScriptWorkflowStep(live, step, worktreePath, settings, nodeEnv) : await this.executeWorkflowStep(live, step, worktreePath, settings, nodeEnv, { unattended });
|
|
231541
|
+
if (declaredReviewKind && typeof outcome.output === "string") {
|
|
231542
|
+
const parsedReviewOutput = parseWorkflowStepOutput(outcome.output, { requireVerdict: false });
|
|
231543
|
+
if (parsedReviewOutput.findings?.length) outcome = { ...outcome, findings: parsedReviewOutput.findings };
|
|
231544
|
+
}
|
|
231344
231545
|
const awaitQuestion = parseAwaitInputSentinel(outcome.output);
|
|
231345
231546
|
if (awaitQuestion) {
|
|
231346
231547
|
await this.store.logEntry(
|
|
@@ -231363,6 +231564,8 @@ ${prompt}`;
|
|
|
231363
231564
|
const contextPatch = {};
|
|
231364
231565
|
if (typeof stepOutput === "string") contextPatch.output = stepOutput;
|
|
231365
231566
|
if (typeof stepNotes === "string" && stepNotes) contextPatch.notes = stepNotes;
|
|
231567
|
+
const stepFindings = outcome.findings;
|
|
231568
|
+
if (stepFindings?.length) contextPatch.findings = stepFindings;
|
|
231366
231569
|
if (cfg.summaryTarget === "task" && typeof stepOutput === "string" && stepOutput.trim()) {
|
|
231367
231570
|
contextPatch.summary = stepOutput.trim();
|
|
231368
231571
|
}
|
|
@@ -231869,6 +232072,7 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
231869
232072
|
} catch {
|
|
231870
232073
|
return false;
|
|
231871
232074
|
}
|
|
232075
|
+
if (hasUserAutoMergeHold(live)) return false;
|
|
231872
232076
|
const sharedBranchMember = await this.isLiveSharedBranchGroupMember(live);
|
|
231873
232077
|
if (!sharedBranchMember && !allowsAutoMergeProcessing(live, settings)) return false;
|
|
231874
232078
|
if (!sharedBranchMember && resolveEffectiveAutoMerge(live, settings) === false) return false;
|
|
@@ -231930,8 +232134,8 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
231930
232134
|
} catch {
|
|
231931
232135
|
return false;
|
|
231932
232136
|
}
|
|
231933
|
-
if (await this.isLiveSharedBranchGroupMember(live)) return false;
|
|
231934
|
-
return !allowsAutoMergeProcessing(live, settings) || resolveEffectiveAutoMerge(live, settings) === false;
|
|
232137
|
+
if (await this.isLiveSharedBranchGroupMember(live) && !hasUserAutoMergeHold(live)) return false;
|
|
232138
|
+
return hasUserAutoMergeHold(live) || !allowsAutoMergeProcessing(live, settings) || resolveEffectiveAutoMerge(live, settings) === false;
|
|
231935
232139
|
}
|
|
231936
232140
|
async handleStaleInReviewPlanPauseAbortReplay(live, result2, abortProvenance, pausedAborted, userCanceled, resumeLanesMemo) {
|
|
231937
232141
|
if (!pausedAborted) return false;
|
|
@@ -232095,9 +232299,9 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
232095
232299
|
if (settings.globalPause === true) return false;
|
|
232096
232300
|
}
|
|
232097
232301
|
if (live.column === resumeLanes.review) {
|
|
232098
|
-
if (live.autoMerge === false) return false;
|
|
232099
232302
|
if (!settings) return false;
|
|
232100
232303
|
const sharedBranchMember = await this.isLiveSharedBranchGroupMember(live);
|
|
232304
|
+
if (hasUserAutoMergeHold(live) || live.autoMerge === false && !sharedBranchMember) return false;
|
|
232101
232305
|
if (!sharedBranchMember && !allowsAutoMergeProcessing(live, settings)) return false;
|
|
232102
232306
|
if (live.mergeDetails?.mergeConfirmed === true) return false;
|
|
232103
232307
|
}
|
|
@@ -237865,13 +238069,14 @@ CRITICAL SCOPING RULES \u2014 read before doing anything else:
|
|
|
237865
238069
|
const isSkillStep = typeof workflowStep.skillName === "string" && workflowStep.skillName.trim().length > 0;
|
|
237866
238070
|
const isSummaryProjectionStep = workflowStep.summaryTarget === "task";
|
|
237867
238071
|
const requireVerdict = !isSummaryProjectionStep && (workflowStep.gateMode === "gate" || !isSkillStep);
|
|
238072
|
+
const reviewFindingsContract = workflowStepMetadata.reviewKind === "plan" || workflowStepMetadata.reviewKind === "code";
|
|
237868
238073
|
const verdictBlock = requireVerdict ? `
|
|
237869
238074
|
|
|
237870
238075
|
## Feedback Format
|
|
237871
238076
|
|
|
237872
238077
|
When your review is complete, your final line MUST be a single JSON object (no markdown fences):
|
|
237873
238078
|
|
|
237874
|
-
{"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}
|
|
238079
|
+
${reviewFindingsContract ? '{"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"...","findings":[{"id":"stable-id","title":"concise issue","body":"actionable detail","filePath":"optional/path","line":1,"severity":"low|medium|high|critical"}]}' : '{"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}'}
|
|
237875
238080
|
|
|
237876
238081
|
Rules:
|
|
237877
238082
|
- Output exactly one trailing JSON object and stop.
|
|
@@ -238181,7 +238386,8 @@ ${detectedQuestion}
|
|
|
238181
238386
|
revisionRequested,
|
|
238182
238387
|
output: parsed.output,
|
|
238183
238388
|
verdict: parsed.verdict,
|
|
238184
|
-
notes: parsed.notes
|
|
238389
|
+
notes: parsed.notes,
|
|
238390
|
+
...parsed.findings ? { findings: parsed.findings } : {}
|
|
238185
238391
|
};
|
|
238186
238392
|
}
|
|
238187
238393
|
if (parsed.malformed) {
|
|
@@ -249170,7 +249376,7 @@ var init_metric_parser = __esm({
|
|
|
249170
249376
|
});
|
|
249171
249377
|
|
|
249172
249378
|
// ../engine/src/eval/experiment-executor.ts
|
|
249173
|
-
import { randomUUID as
|
|
249379
|
+
import { randomUUID as randomUUID45 } from "node:crypto";
|
|
249174
249380
|
var ExperimentMaxIterationsError, ExperimentGitNotConfiguredError, ExperimentExecutor;
|
|
249175
249381
|
var init_experiment_executor = __esm({
|
|
249176
249382
|
"../engine/src/eval/experiment-executor.ts"() {
|
|
@@ -249238,7 +249444,7 @@ var init_experiment_executor = __esm({
|
|
|
249238
249444
|
}
|
|
249239
249445
|
await this.semaphore.acquire();
|
|
249240
249446
|
const controller = new AbortController();
|
|
249241
|
-
const runHandle =
|
|
249447
|
+
const runHandle = randomUUID45();
|
|
249242
249448
|
if (opts?.abortSignal) {
|
|
249243
249449
|
opts.abortSignal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
249244
249450
|
}
|
|
@@ -258245,6 +258451,7 @@ var init_in_process_runtime = __esm({
|
|
|
258245
258451
|
}
|
|
258246
258452
|
}
|
|
258247
258453
|
const prNodeGithubOps = this.config.prNodeGithubOps;
|
|
258454
|
+
const secretsStore = await this.taskStore.getSecretsStore();
|
|
258248
258455
|
const executorOptions = {
|
|
258249
258456
|
/*
|
|
258250
258457
|
FNXC:PlanReviewLease 2026-07-26-21:12:
|
|
@@ -258260,6 +258467,7 @@ var init_in_process_runtime = __esm({
|
|
|
258260
258467
|
cliAgentRuntime: this.cliAgentRuntime?.bundle,
|
|
258261
258468
|
pluginRunner: this.pluginRunner,
|
|
258262
258469
|
messageStore: this.messageStore,
|
|
258470
|
+
secretsStore,
|
|
258263
258471
|
missionStore,
|
|
258264
258472
|
reflectionService,
|
|
258265
258473
|
// PR-entity nodes (U3): assemble the handler deps from the CLI-injected
|
|
@@ -258361,6 +258569,7 @@ var init_in_process_runtime = __esm({
|
|
|
258361
258569
|
reflectionService,
|
|
258362
258570
|
selfImproveService,
|
|
258363
258571
|
credentialRotator: this.credentialRotator,
|
|
258572
|
+
secretsStore,
|
|
258364
258573
|
snapshotManager: autoClaimSnapshotManager,
|
|
258365
258574
|
onMissed: (agentId, reason) => {
|
|
258366
258575
|
runtimeLog.warn(`Agent ${agentId} missed heartbeat: ${reason}`);
|
|
@@ -262222,7 +262431,21 @@ var init_project_engine = __esm({
|
|
|
262222
262431
|
Cleared on the first non-busy outcome (success path resets it).
|
|
262223
262432
|
*/
|
|
262224
262433
|
workspaceBusyReenqueues = /* @__PURE__ */ new Map();
|
|
262434
|
+
workspaceBusyReenqueueTimers = /* @__PURE__ */ new Set();
|
|
262225
262435
|
static WORKSPACE_BUSY_MAX_REENQUEUES = 10;
|
|
262436
|
+
/*
|
|
262437
|
+
FNXC:WorkspaceMergeDispatch 2026-08-05-23:56:
|
|
262438
|
+
Workspace lease-contention retries are engine-owned lifecycle work, not detached callbacks.
|
|
262439
|
+
Track only these busy re-enqueue timers so stop() can cancel them and tests can measure the
|
|
262440
|
+
capped workspace ladder without confusing it with merge-body or maintenance timers.
|
|
262441
|
+
*/
|
|
262442
|
+
scheduleWorkspaceBusyReenqueue(taskId, delayMs) {
|
|
262443
|
+
const timer2 = setTimeout(() => {
|
|
262444
|
+
this.workspaceBusyReenqueueTimers.delete(timer2);
|
|
262445
|
+
if (!this.shuttingDown) this.internalEnqueueMerge(taskId);
|
|
262446
|
+
}, delayMs);
|
|
262447
|
+
this.workspaceBusyReenqueueTimers.add(timer2);
|
|
262448
|
+
}
|
|
262226
262449
|
/**
|
|
262227
262450
|
* Pending manual merge resolvers — keyed by taskId.
|
|
262228
262451
|
* When `onMerge` is called, the task is enqueued like auto-merge but a
|
|
@@ -262283,7 +262506,7 @@ var init_project_engine = __esm({
|
|
|
262283
262506
|
*
|
|
262284
262507
|
* Readable (not private) so tests derive the cap from this single source of truth rather
|
|
262285
262508
|
* than hardcoding it — the FN-8004 bump broke two suites that had baked in the old `3`. */
|
|
262286
|
-
static MAX_AUTO_MERGE_TRANSIENT_RETRIES =
|
|
262509
|
+
static MAX_AUTO_MERGE_TRANSIENT_RETRIES = MAX_AUTO_MERGE_TRANSIENT_RETRIES;
|
|
262287
262510
|
static MERGE_REQUEST_RETRY_EXHAUSTED_AGE_MS = 30 * 60 * 1e3;
|
|
262288
262511
|
/** Cap on outer in-review→in-progress bounces caused by deterministic
|
|
262289
262512
|
* verification failures during auto-merge. After this many failed merges
|
|
@@ -262757,6 +262980,10 @@ ${detail}`);
|
|
|
262757
262980
|
clearInterval(this.mergeActiveReconcileTimer);
|
|
262758
262981
|
this.mergeActiveReconcileTimer = null;
|
|
262759
262982
|
}
|
|
262983
|
+
for (const timer2 of this.workspaceBusyReenqueueTimers) {
|
|
262984
|
+
clearTimeout(timer2);
|
|
262985
|
+
}
|
|
262986
|
+
this.workspaceBusyReenqueueTimers.clear();
|
|
262760
262987
|
for (const [taskId, deferred] of this.capacityDeferredMerges) {
|
|
262761
262988
|
clearTimeout(deferred.timer);
|
|
262762
262989
|
for (const resolver of deferred.resolvers) {
|
|
@@ -264056,16 +264283,15 @@ ${detail}`);
|
|
|
264056
264283
|
* older low-priority task would start before a later urgent one.
|
|
264057
264284
|
*/
|
|
264058
264285
|
async allowInReviewMergeProcessing(task, settings, store = this.runtime.getTaskStore()) {
|
|
264059
|
-
if (
|
|
264060
|
-
return true;
|
|
264061
|
-
}
|
|
264286
|
+
if (hasUserAutoMergeHold(task)) return false;
|
|
264062
264287
|
const groupId = task.branchContext?.groupId?.trim();
|
|
264063
264288
|
const branchGroup = groupId ? await store.getBranchGroup?.(groupId) : null;
|
|
264064
|
-
if (!branchGroup || branchGroup.status !== "open" || !branchGroup.branchName.trim()) {
|
|
264065
|
-
return false;
|
|
264066
|
-
}
|
|
264067
264289
|
const projectDefaultBranch = await resolveIntegrationBranch(this.config.workingDirectory, settings);
|
|
264068
|
-
|
|
264290
|
+
if (isLiveSharedBranchGroupMemberIntegration(task, branchGroup, projectDefaultBranch)) {
|
|
264291
|
+
return true;
|
|
264292
|
+
}
|
|
264293
|
+
if (task.autoMerge === false && groupId) return false;
|
|
264294
|
+
return allowsAutoMergeProcessing(task, settings);
|
|
264069
264295
|
}
|
|
264070
264296
|
async emitLegacyAutoMergeStampAdvisory(store) {
|
|
264071
264297
|
if (this.legacyAutoMergeStampAdvisoryEmitted) {
|
|
@@ -265018,9 +265244,7 @@ ${detail}`);
|
|
|
265018
265244
|
runtimeLog.log(
|
|
265019
265245
|
`Workspace land busy re-enqueue ${busyCount + 1}/${_ProjectEngine.WORKSPACE_BUSY_MAX_REENQUEUES} for ${taskId} in ${delayMs / 1e3}s (no mergeRetry consumed \u2014 pure lease contention)`
|
|
265020
265246
|
);
|
|
265021
|
-
|
|
265022
|
-
if (!this.shuttingDown) this.internalEnqueueMerge(taskId);
|
|
265023
|
-
}, delayMs);
|
|
265247
|
+
this.scheduleWorkspaceBusyReenqueue(taskId, delayMs);
|
|
265024
265248
|
} else {
|
|
265025
265249
|
this.workspaceBusyReenqueues.delete(taskId);
|
|
265026
265250
|
await store.updateTask(taskId, { status: "failed", error: errorMsg }).catch(() => void 0);
|
|
@@ -268658,7 +268882,7 @@ __export(planning_exports, {
|
|
|
268658
268882
|
updatePlanningSessionTitle: () => updatePlanningSessionTitle,
|
|
268659
268883
|
validateSession: () => validateSession
|
|
268660
268884
|
});
|
|
268661
|
-
import { randomUUID as
|
|
268885
|
+
import { randomUUID as randomUUID46 } from "node:crypto";
|
|
268662
268886
|
import { EventEmitter as EventEmitter34 } from "node:events";
|
|
268663
268887
|
async function createPlanningRuntimeSession(options) {
|
|
268664
268888
|
const { pluginRunner, runtimeHint, settings, ...runtimeOptions } = options ?? {};
|
|
@@ -269122,7 +269346,7 @@ async function createSession(ip, initialPlan, store, rootDir, promptOverrides, p
|
|
|
269122
269346
|
if (!store) {
|
|
269123
269347
|
throw new Error("store is required for AI-powered planning sessions");
|
|
269124
269348
|
}
|
|
269125
|
-
const sessionId =
|
|
269349
|
+
const sessionId = randomUUID46();
|
|
269126
269350
|
const session = {
|
|
269127
269351
|
id: sessionId,
|
|
269128
269352
|
ip,
|
|
@@ -269337,7 +269561,7 @@ async function createDraftSession(ip, initialPlan, _rootDir, modelProvider, mode
|
|
|
269337
269561
|
`Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR} planning sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
|
|
269338
269562
|
);
|
|
269339
269563
|
}
|
|
269340
|
-
const sessionId =
|
|
269564
|
+
const sessionId = randomUUID46();
|
|
269341
269565
|
const title2 = DRAFT_PLACEHOLDER_TITLE;
|
|
269342
269566
|
const hasModelOverride = Boolean(modelProvider && modelId);
|
|
269343
269567
|
const session = {
|
|
@@ -269513,7 +269737,7 @@ async function createSessionWithAgent(ip, initialPlan, rootDir, store, modelProv
|
|
|
269513
269737
|
`Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR} planning sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
|
|
269514
269738
|
);
|
|
269515
269739
|
}
|
|
269516
|
-
const sessionId =
|
|
269740
|
+
const sessionId = randomUUID46();
|
|
269517
269741
|
const session = {
|
|
269518
269742
|
id: sessionId,
|
|
269519
269743
|
ip,
|
|
@@ -270023,7 +270247,7 @@ function normalizePlanningQuestion(input, userInput = "") {
|
|
|
270023
270247
|
const type = source.type === "multi_select" || source.type === "single_select" ? source.type : "single_select";
|
|
270024
270248
|
const question = typeof source.question === "string" && source.question.trim() ? source.question.trim() : fallback2.question;
|
|
270025
270249
|
const normalized = {
|
|
270026
|
-
id: typeof source.id === "string" && source.id.trim() ? source.id :
|
|
270250
|
+
id: typeof source.id === "string" && source.id.trim() ? source.id : randomUUID46(),
|
|
270027
270251
|
type,
|
|
270028
270252
|
question,
|
|
270029
270253
|
...typeof source.description === "string" && source.description.trim() ? { description: source.description.trim() } : {}
|
|
@@ -270049,7 +270273,7 @@ function normalizePlanningQuestion(input, userInput = "") {
|
|
|
270049
270273
|
}
|
|
270050
270274
|
function coerceQuestionResponse(response, session) {
|
|
270051
270275
|
if (response.type === "question") return normalizePlanningQuestion(response.data, session.initialPlan);
|
|
270052
|
-
return normalizePlanningQuestion({ id:
|
|
270276
|
+
return normalizePlanningQuestion({ id: randomUUID46(), type: "single_select", question: planningFallbackCopy(session.initialPlan).question }, session.initialPlan);
|
|
270053
270277
|
}
|
|
270054
270278
|
async function validateSession(sessionId) {
|
|
270055
270279
|
const session = await getSession(sessionId);
|
|
@@ -270991,7 +271215,7 @@ async function createTaskFromPlanSession(sessionId, store, options) {
|
|
|
270991
271215
|
throw new InvalidSessionStateError("PLANNING_CREATED_TASK_MISSING");
|
|
270992
271216
|
}
|
|
270993
271217
|
}
|
|
270994
|
-
const claimOwnerToken =
|
|
271218
|
+
const claimOwnerToken = randomUUID46();
|
|
270995
271219
|
let claimed = await claimPlanningTaskCreation(sessionId, claimOwnerToken, (/* @__PURE__ */ new Date()).toISOString(), claimEpoch);
|
|
270996
271220
|
if (!claimed) {
|
|
270997
271221
|
session = await getDurablePlanningSession(sessionId).catch(() => void 0) ?? session;
|
|
@@ -271660,7 +271884,7 @@ __export(subtask_breakdown_exports, {
|
|
|
271660
271884
|
stopSubtaskGeneration: () => stopSubtaskGeneration,
|
|
271661
271885
|
subtaskStreamManager: () => subtaskStreamManager
|
|
271662
271886
|
});
|
|
271663
|
-
import { randomUUID as
|
|
271887
|
+
import { randomUUID as randomUUID47 } from "node:crypto";
|
|
271664
271888
|
import { EventEmitter as EventEmitter35 } from "node:events";
|
|
271665
271889
|
function __getSubtaskBreakdownDiagnostics() {
|
|
271666
271890
|
return diagnostics3;
|
|
@@ -271835,7 +272059,7 @@ async function decomposeForTriage(description, rootDir, promptOverrides, store)
|
|
|
271835
272059
|
}
|
|
271836
272060
|
}
|
|
271837
272061
|
async function createSubtaskSession(initialDescription, store, rootDir, promptOverrides, projectId) {
|
|
271838
|
-
const sessionId =
|
|
272062
|
+
const sessionId = randomUUID47();
|
|
271839
272063
|
const session = {
|
|
271840
272064
|
sessionId,
|
|
271841
272065
|
projectId,
|
|
@@ -272272,7 +272496,7 @@ __export(mission_interview_exports, {
|
|
|
272272
272496
|
stopMissionInterviewGeneration: () => stopMissionInterviewGeneration,
|
|
272273
272497
|
submitMissionInterviewResponse: () => submitMissionInterviewResponse
|
|
272274
272498
|
});
|
|
272275
|
-
import { randomUUID as
|
|
272499
|
+
import { randomUUID as randomUUID48 } from "node:crypto";
|
|
272276
272500
|
import { EventEmitter as EventEmitter36 } from "node:events";
|
|
272277
272501
|
function __getMissionInterviewDiagnostics() {
|
|
272278
272502
|
return diagnostics4;
|
|
@@ -273015,7 +273239,7 @@ async function createMissionInterviewSession(ip, missionTitle, rootDir, store, p
|
|
|
273015
273239
|
`Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR2} sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
|
|
273016
273240
|
);
|
|
273017
273241
|
}
|
|
273018
|
-
const sessionId =
|
|
273242
|
+
const sessionId = randomUUID48();
|
|
273019
273243
|
const session = {
|
|
273020
273244
|
id: sessionId,
|
|
273021
273245
|
ip,
|
|
@@ -273478,7 +273702,7 @@ __export(milestone_slice_interview_exports, {
|
|
|
273478
273702
|
stopMilestoneSliceInterviewGeneration: () => stopMilestoneSliceInterviewGeneration,
|
|
273479
273703
|
submitTargetInterviewResponse: () => submitTargetInterviewResponse
|
|
273480
273704
|
});
|
|
273481
|
-
import { randomUUID as
|
|
273705
|
+
import { randomUUID as randomUUID49 } from "node:crypto";
|
|
273482
273706
|
import { EventEmitter as EventEmitter37 } from "node:events";
|
|
273483
273707
|
function parseTargetInterviewResponseImpl(text3) {
|
|
273484
273708
|
const candidate = extractJsonCandidate3(text3);
|
|
@@ -274107,7 +274331,7 @@ async function createTargetInterviewSession(ip, targetType, targetId, targetTitl
|
|
|
274107
274331
|
`Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR3} sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
|
|
274108
274332
|
);
|
|
274109
274333
|
}
|
|
274110
|
-
const sessionId =
|
|
274334
|
+
const sessionId = randomUUID49();
|
|
274111
274335
|
const session = {
|
|
274112
274336
|
id: sessionId,
|
|
274113
274337
|
ip,
|
|
@@ -292714,10 +292938,32 @@ function parseTaskReviewVerdict(value) {
|
|
|
292714
292938
|
return void 0;
|
|
292715
292939
|
}
|
|
292716
292940
|
}
|
|
292717
|
-
function
|
|
292718
|
-
return
|
|
292941
|
+
function hasCurrentWorkflowReviewIdentity(result2) {
|
|
292942
|
+
return result2.supersededAt === void 0 && result2.supersededReason === void 0 && result2.bypassedBy === void 0 && result2.bypassedAt === void 0 && result2.bypassReason === void 0 && result2.bypassedFromStatus === void 0 && result2.bypassedFromVerdict === void 0;
|
|
292943
|
+
}
|
|
292944
|
+
function isCurrentMarkedWorkflowReviewResult(result2) {
|
|
292945
|
+
return CURRENT_WORKFLOW_REVIEW_STATUSES.has(result2.status) && hasCurrentWorkflowReviewIdentity(result2) && Boolean(result2.output?.trim() || result2.notes?.trim()) && (result2.reviewKind === "plan" || result2.reviewKind === "code") && (result2.source === "node" || result2.source === "optional-group");
|
|
292946
|
+
}
|
|
292947
|
+
async function getDeclaredTopLevelReviewResultSources(task, store) {
|
|
292948
|
+
const resolved = await resolveWorkflowIrForTaskWithProvenance(store, task.id);
|
|
292949
|
+
if (resolved.source !== "selection") return /* @__PURE__ */ new Map();
|
|
292950
|
+
return new Map(resolved.ir.nodes.flatMap((node) => {
|
|
292951
|
+
if (node.kind === "optional-group") return [[node.id, "optional-group"]];
|
|
292952
|
+
if (node.kind === "prompt" || node.kind === "gate" || node.kind === "script") return [[node.id, "node"]];
|
|
292953
|
+
return [];
|
|
292954
|
+
}));
|
|
292719
292955
|
}
|
|
292720
|
-
function
|
|
292956
|
+
function isCurrentLegacyWorkflowReviewResult(result2) {
|
|
292957
|
+
return CURRENT_WORKFLOW_REVIEW_STEP_IDS.has(result2.workflowStepId) && result2.reviewKind === void 0 && LEGACY_WORKFLOW_REVIEW_STATUSES.has(result2.status) && result2.verdict !== void 0 && hasCurrentWorkflowReviewIdentity(result2);
|
|
292958
|
+
}
|
|
292959
|
+
function getWorkflowReviewKind(result2, declaredTopLevelReviewResultSources) {
|
|
292960
|
+
if (isCurrentMarkedWorkflowReviewResult(result2) && declaredTopLevelReviewResultSources.get(result2.workflowStepId) === result2.source) return result2.reviewKind;
|
|
292961
|
+
if (isCurrentLegacyWorkflowReviewResult(result2)) {
|
|
292962
|
+
return result2.workflowStepId === "plan-review" ? "plan" : "code";
|
|
292963
|
+
}
|
|
292964
|
+
return void 0;
|
|
292965
|
+
}
|
|
292966
|
+
function buildWorkflowReviewItemId(task, result2, findingId) {
|
|
292721
292967
|
const identity = JSON.stringify({
|
|
292722
292968
|
taskId: task.id,
|
|
292723
292969
|
workflowStepId: result2.workflowStepId,
|
|
@@ -292725,22 +292971,44 @@ function buildWorkflowReviewItemId(task, result2) {
|
|
|
292725
292971
|
phase: result2.phase,
|
|
292726
292972
|
status: result2.status,
|
|
292727
292973
|
verdict: result2.verdict,
|
|
292974
|
+
reviewKind: result2.reviewKind,
|
|
292728
292975
|
completedAt: result2.completedAt,
|
|
292729
292976
|
startedAt: result2.startedAt,
|
|
292730
292977
|
output: result2.output,
|
|
292731
|
-
notes: result2.notes
|
|
292978
|
+
notes: result2.notes,
|
|
292979
|
+
findingId
|
|
292732
292980
|
});
|
|
292733
292981
|
return `workflow-review-${createHash29("sha256").update(identity).digest("hex").slice(0, 24)}`;
|
|
292734
292982
|
}
|
|
292735
|
-
function buildWorkflowReviewItems(task) {
|
|
292736
|
-
|
|
292737
|
-
|
|
292738
|
-
const
|
|
292983
|
+
async function buildWorkflowReviewItems(task, store) {
|
|
292984
|
+
const declaredTopLevelReviewResultSources = await getDeclaredTopLevelReviewResultSources(task, store);
|
|
292985
|
+
return (task.workflowStepResults ?? []).flatMap((result2) => {
|
|
292986
|
+
const reviewType = getWorkflowReviewKind(result2, declaredTopLevelReviewResultSources);
|
|
292987
|
+
if (!reviewType) return [];
|
|
292739
292988
|
const timestamp2 = result2.completedAt ?? result2.startedAt ?? task.updatedAt ?? task.createdAt;
|
|
292740
|
-
|
|
292989
|
+
if (result2.findings?.length) {
|
|
292990
|
+
return result2.findings.map((finding) => ({
|
|
292991
|
+
itemId: buildWorkflowReviewItemId(task, result2, finding.id),
|
|
292992
|
+
sourceMode: "reviewer-agent",
|
|
292993
|
+
title: finding.title,
|
|
292994
|
+
body: finding.body,
|
|
292995
|
+
author: "reviewer-agent",
|
|
292996
|
+
createdAt: timestamp2,
|
|
292997
|
+
updatedAt: timestamp2,
|
|
292998
|
+
...finding.filePath ? { filePath: finding.filePath } : {},
|
|
292999
|
+
...finding.line ? { line: finding.line } : {},
|
|
293000
|
+
...finding.severity ? { severity: finding.severity } : {},
|
|
293001
|
+
reviewState: result2.verdict,
|
|
293002
|
+
verdict: result2.verdict,
|
|
293003
|
+
reviewType,
|
|
293004
|
+
progressStatus: null
|
|
293005
|
+
}));
|
|
293006
|
+
}
|
|
293007
|
+
const body = result2.output?.trim() || result2.notes?.trim() || "No written feedback was provided by this review step.";
|
|
293008
|
+
return [{
|
|
292741
293009
|
itemId: buildWorkflowReviewItemId(task, result2),
|
|
292742
293010
|
sourceMode: "reviewer-agent",
|
|
292743
|
-
title: `${result2.workflowStepName || result2.workflowStepId} ${result2.verdict}`,
|
|
293011
|
+
title: `${result2.workflowStepName || result2.workflowStepId} ${result2.verdict ?? result2.status}`,
|
|
292744
293012
|
body,
|
|
292745
293013
|
author: "reviewer-agent",
|
|
292746
293014
|
createdAt: timestamp2,
|
|
@@ -292749,7 +293017,7 @@ function buildWorkflowReviewItems(task) {
|
|
|
292749
293017
|
verdict: result2.verdict,
|
|
292750
293018
|
reviewType,
|
|
292751
293019
|
progressStatus: null
|
|
292752
|
-
};
|
|
293020
|
+
}];
|
|
292753
293021
|
}).sort((a, b3) => Date.parse(b3.createdAt ?? "") - Date.parse(a.createdAt ?? "") || a.itemId.localeCompare(b3.itemId));
|
|
292754
293022
|
}
|
|
292755
293023
|
function buildDirectReviewSummary(items) {
|
|
@@ -292757,7 +293025,7 @@ function buildDirectReviewSummary(items) {
|
|
|
292757
293025
|
return latest ? { summary: latest.title, verdict: latest.verdict } : null;
|
|
292758
293026
|
}
|
|
292759
293027
|
async function buildDirectTaskReviewData(task, store) {
|
|
292760
|
-
const structuredItems = buildWorkflowReviewItems(task);
|
|
293028
|
+
const structuredItems = await buildWorkflowReviewItems(task, store);
|
|
292761
293029
|
if (structuredItems.length > 0) {
|
|
292762
293030
|
return {
|
|
292763
293031
|
mode: "reviewer-agent",
|
|
@@ -293207,6 +293475,7 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
293207
293475
|
reviewLevel,
|
|
293208
293476
|
executionMode,
|
|
293209
293477
|
autoMerge,
|
|
293478
|
+
autoMergeProvenance,
|
|
293210
293479
|
priority,
|
|
293211
293480
|
source,
|
|
293212
293481
|
branch,
|
|
@@ -293256,6 +293525,9 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
293256
293525
|
if (autoMerge !== void 0 && typeof autoMerge !== "boolean") {
|
|
293257
293526
|
throw badRequest("autoMerge must be a boolean");
|
|
293258
293527
|
}
|
|
293528
|
+
if (autoMergeProvenance !== void 0) {
|
|
293529
|
+
throw badRequest("autoMergeProvenance is server-managed");
|
|
293530
|
+
}
|
|
293259
293531
|
if (priority !== void 0 && priority !== null && !isTaskPriority(priority)) {
|
|
293260
293532
|
throw badRequest(`priority must be one of: ${TASK_PRIORITIES.join(", ")}`);
|
|
293261
293533
|
}
|
|
@@ -294821,6 +295093,17 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
294821
295093
|
rethrowTaskApiError(err, req.params.id, "Failed to read task verification status");
|
|
294822
295094
|
}
|
|
294823
295095
|
});
|
|
295096
|
+
router.get("/tasks/:id/prompt", async (req, res) => {
|
|
295097
|
+
try {
|
|
295098
|
+
const { store: scopedStore } = await getProjectContext2(req);
|
|
295099
|
+
const task = await scopedStore.getTask(req.params.id);
|
|
295100
|
+
res.json(task.prompt === void 0 ? { id: task.id } : { id: task.id, prompt: task.prompt });
|
|
295101
|
+
} catch (err) {
|
|
295102
|
+
if (err instanceof ApiError) throw err;
|
|
295103
|
+
if (isTaskLookupMiss(err)) throw notFound(`Task ${req.params.id} not found`);
|
|
295104
|
+
rethrowAsApiError8(err, "Internal server error");
|
|
295105
|
+
}
|
|
295106
|
+
});
|
|
294824
295107
|
router.get("/tasks/:id", async (req, res) => {
|
|
294825
295108
|
try {
|
|
294826
295109
|
const { store: scopedStore, engine } = await getProjectContext2(req);
|
|
@@ -295943,6 +296226,9 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
295943
296226
|
if (hasBodyField("autoMerge") && autoMerge !== void 0 && autoMerge !== null && typeof autoMerge !== "boolean") {
|
|
295944
296227
|
throw new Error("autoMerge must be a boolean");
|
|
295945
296228
|
}
|
|
296229
|
+
if (hasBodyField("autoMergeProvenance")) {
|
|
296230
|
+
throw badRequest("autoMergeProvenance is server-managed");
|
|
296231
|
+
}
|
|
295946
296232
|
let validatedSourceIssue;
|
|
295947
296233
|
if (hasBodyField("sourceIssue")) {
|
|
295948
296234
|
if (sourceIssue === null) {
|
|
@@ -296164,7 +296450,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296164
296450
|
if (dependencies !== void 0) updates.dependencies = dependencies;
|
|
296165
296451
|
if (enabledWorkflowSteps !== void 0) updates.enabledWorkflowSteps = enabledWorkflowSteps;
|
|
296166
296452
|
if (hasBodyField("noCommitsExpected")) updates.noCommitsExpected = noCommitsExpected;
|
|
296167
|
-
if (hasBodyField("autoMerge")) updates.autoMerge = autoMerge
|
|
296453
|
+
if (hasBodyField("autoMerge")) updates.autoMerge = autoMerge;
|
|
296168
296454
|
if (hasBodyField("modelProvider")) updates.modelProvider = validatedModelProvider;
|
|
296169
296455
|
if (hasBodyField("modelId")) updates.modelId = validatedModelId;
|
|
296170
296456
|
if (hasBodyField("validatorModelProvider")) updates.validatorModelProvider = validatedValidatorModelProvider;
|
|
@@ -296466,6 +296752,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296466
296752
|
updatedAt: item.updatedAt ?? void 0,
|
|
296467
296753
|
path: item.filePath,
|
|
296468
296754
|
line: item.line,
|
|
296755
|
+
severity: item.severity,
|
|
296469
296756
|
threadId: item.threadId,
|
|
296470
296757
|
htmlUrl: item.url,
|
|
296471
296758
|
state: item.reviewState ?? void 0,
|
|
@@ -296508,6 +296795,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296508
296795
|
author: item.author.login,
|
|
296509
296796
|
filePath: item.path,
|
|
296510
296797
|
lineNumber: item.line,
|
|
296798
|
+
severity: item.severity,
|
|
296511
296799
|
threadId: item.threadId,
|
|
296512
296800
|
url: item.htmlUrl
|
|
296513
296801
|
};
|
|
@@ -296543,6 +296831,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296543
296831
|
authorLogin: item.author,
|
|
296544
296832
|
filePath: item.filePath,
|
|
296545
296833
|
lineNumber: item.lineNumber,
|
|
296834
|
+
severity: item.severity,
|
|
296546
296835
|
threadId: item.threadId,
|
|
296547
296836
|
url: item.url
|
|
296548
296837
|
},
|
|
@@ -296835,7 +297124,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296835
297124
|
}
|
|
296836
297125
|
});
|
|
296837
297126
|
}
|
|
296838
|
-
var severityAuditLog33, AWAITING_PLANNING_ENRICH_LIMIT, LEGACY_WIP_LANES3, LEGACY_ARCHIVE_LANES5, REVIEW_BLOCK_RE, REVIEW_VERDICT_RE, REVIEW_STEP_RE, DUPLICATE_STOPWORDS, ARTIFACT_TYPES, ADDRESS_PR_FEEDBACK_PROMPT, __fingerprintCreateLocksForTests, RESET_TASK_FIELDS, RESET_DRIFT_CORRECTION_FIELDS, CURRENT_WORKFLOW_REVIEW_STEP_IDS, CURRENT_WORKFLOW_REVIEW_STATUSES;
|
|
297127
|
+
var severityAuditLog33, AWAITING_PLANNING_ENRICH_LIMIT, LEGACY_WIP_LANES3, LEGACY_ARCHIVE_LANES5, REVIEW_BLOCK_RE, REVIEW_VERDICT_RE, REVIEW_STEP_RE, DUPLICATE_STOPWORDS, ARTIFACT_TYPES, ADDRESS_PR_FEEDBACK_PROMPT, __fingerprintCreateLocksForTests, RESET_TASK_FIELDS, RESET_DRIFT_CORRECTION_FIELDS, CURRENT_WORKFLOW_REVIEW_STEP_IDS, CURRENT_WORKFLOW_REVIEW_STATUSES, LEGACY_WORKFLOW_REVIEW_STATUSES;
|
|
296839
297128
|
var init_register_task_workflow_routes = __esm({
|
|
296840
297129
|
"../dashboard/src/routes/register-task-workflow-routes.ts"() {
|
|
296841
297130
|
"use strict";
|
|
@@ -296898,7 +297187,8 @@ var init_register_task_workflow_routes = __esm({
|
|
|
296898
297187
|
sessionFile: null
|
|
296899
297188
|
};
|
|
296900
297189
|
CURRENT_WORKFLOW_REVIEW_STEP_IDS = /* @__PURE__ */ new Set(["code-review", "plan-review"]);
|
|
296901
|
-
CURRENT_WORKFLOW_REVIEW_STATUSES = /* @__PURE__ */ new Set(["passed", "failed"
|
|
297190
|
+
CURRENT_WORKFLOW_REVIEW_STATUSES = /* @__PURE__ */ new Set(["passed", "failed"]);
|
|
297191
|
+
LEGACY_WORKFLOW_REVIEW_STATUSES = /* @__PURE__ */ new Set(["passed", "failed", "advisory_failure"]);
|
|
296902
297192
|
}
|
|
296903
297193
|
});
|
|
296904
297194
|
|
|
@@ -297758,7 +298048,7 @@ at this boundary regardless.`;
|
|
|
297758
298048
|
});
|
|
297759
298049
|
|
|
297760
298050
|
// ../dashboard/src/routes/register-planning-subtask-routes.ts
|
|
297761
|
-
import { randomUUID as
|
|
298051
|
+
import { randomUUID as randomUUID50 } from "node:crypto";
|
|
297762
298052
|
async function acquirePlanningCreateLock(sessionId) {
|
|
297763
298053
|
const previous = planningCreateLocks.get(sessionId);
|
|
297764
298054
|
let releaseGate;
|
|
@@ -298739,7 +299029,7 @@ function registerPlanningSubtaskRoutes(ctx, deps) {
|
|
|
298739
299029
|
}
|
|
298740
299030
|
session = await getDurablePlanningSession2(sessionId) ?? session;
|
|
298741
299031
|
if (await returnLinkedTask(session)) return;
|
|
298742
|
-
const claimOwnerToken =
|
|
299032
|
+
const claimOwnerToken = randomUUID50();
|
|
298743
299033
|
claimedOwnerToken = claimOwnerToken;
|
|
298744
299034
|
claimedSessionId = sessionId;
|
|
298745
299035
|
const claimStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -299915,7 +300205,7 @@ __export(chat_exports, {
|
|
|
299915
300205
|
resolveFileReferences: () => resolveFileReferences
|
|
299916
300206
|
});
|
|
299917
300207
|
import { EventEmitter as EventEmitter40 } from "node:events";
|
|
299918
|
-
import { randomUUID as
|
|
300208
|
+
import { randomUUID as randomUUID51 } from "node:crypto";
|
|
299919
300209
|
import { existsSync as existsSync71 } from "node:fs";
|
|
299920
300210
|
import { join as join90, resolve as resolve48, relative as relative20 } from "node:path";
|
|
299921
300211
|
import { SessionManager as SessionManager3 } from "@earendil-works/pi-coding-agent";
|
|
@@ -300127,7 +300417,7 @@ function createTaskVerificationTools(taskStore, actionGateContext) {
|
|
|
300127
300417
|
const settings = await taskStore.getSettings();
|
|
300128
300418
|
const command = profile === "verify:fast" ? "pnpm verify:fast" : typeof settings.testCommand === "string" ? settings.testCommand : "";
|
|
300129
300419
|
if (!command) return { content: [{ type: "text", text: "ERROR: the selected verification profile is not configured." }], isError: true, details: {} };
|
|
300130
|
-
const created = await taskStore.createTaskVerificationRequest({ taskId, requestId:
|
|
300420
|
+
const created = await taskStore.createTaskVerificationRequest({ taskId, requestId: randomUUID51(), profile, command, scope: "workspace", requestedBy: "chat" });
|
|
300131
300421
|
if (created.inFlightRequestId) return { content: [{ type: "text", text: `ERROR: verification request ${created.inFlightRequestId} is already in flight.` }], isError: true, details: created };
|
|
300132
300422
|
return { content: [{ type: "text", text: `Queued verification request ${created.request.requestId} for ${taskId}.` }], details: created.request };
|
|
300133
300423
|
}
|
|
@@ -302287,7 +302577,7 @@ var init_rate_limit = __esm({
|
|
|
302287
302577
|
});
|
|
302288
302578
|
|
|
302289
302579
|
// ../dashboard/src/routes/register-chat-routes.ts
|
|
302290
|
-
import { randomUUID as
|
|
302580
|
+
import { randomUUID as randomUUID52 } from "node:crypto";
|
|
302291
302581
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
302292
302582
|
import { mkdir as mkdir30, rm as rm16, writeFile as writeFile32 } from "node:fs/promises";
|
|
302293
302583
|
import { basename as basename22, join as join91, resolve as resolve49 } from "node:path";
|
|
@@ -302346,7 +302636,7 @@ function registerChatRoutes(ctx, deps) {
|
|
|
302346
302636
|
const filePath = join91(sessionDir, filename);
|
|
302347
302637
|
await writeFile32(filePath, file.buffer);
|
|
302348
302638
|
return {
|
|
302349
|
-
id: `att-${
|
|
302639
|
+
id: `att-${randomUUID52().slice(0, 8)}`,
|
|
302350
302640
|
filename,
|
|
302351
302641
|
originalName: file.originalname,
|
|
302352
302642
|
mimeType: file.mimetype,
|
|
@@ -303113,7 +303403,7 @@ var init_register_chat_routes = __esm({
|
|
|
303113
303403
|
});
|
|
303114
303404
|
|
|
303115
303405
|
// ../dashboard/src/routes/register-chat-room-routes.ts
|
|
303116
|
-
import { randomUUID as
|
|
303406
|
+
import { randomUUID as randomUUID53 } from "node:crypto";
|
|
303117
303407
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
303118
303408
|
import { mkdir as mkdir31, writeFile as writeFile33 } from "node:fs/promises";
|
|
303119
303409
|
import { basename as basename23, join as join92, resolve as resolve50 } from "node:path";
|
|
@@ -303454,7 +303744,7 @@ function registerChatRoomRoutes(ctx, deps) {
|
|
|
303454
303744
|
const filePath = join92(roomDir, filename);
|
|
303455
303745
|
await writeFile33(filePath, file.buffer);
|
|
303456
303746
|
const attachment = {
|
|
303457
|
-
id: `att-${
|
|
303747
|
+
id: `att-${randomUUID53().slice(0, 8)}`,
|
|
303458
303748
|
filename,
|
|
303459
303749
|
originalName: file.originalname,
|
|
303460
303750
|
mimeType: file.mimetype,
|
|
@@ -309969,6 +310259,17 @@ function assertObject(value) {
|
|
|
309969
310259
|
throw badRequest("body must be an object");
|
|
309970
310260
|
}
|
|
309971
310261
|
}
|
|
310262
|
+
function getExplicitProjectId(req, ctx) {
|
|
310263
|
+
const projectId = ctx.getProjectIdFromRequest(req);
|
|
310264
|
+
if (!projectId) throw badRequest("projectId is required");
|
|
310265
|
+
return projectId;
|
|
310266
|
+
}
|
|
310267
|
+
async function getExplicitSecretsStore(req, ctx) {
|
|
310268
|
+
const requestedProjectId = getExplicitProjectId(req, ctx);
|
|
310269
|
+
const { store, projectId } = await ctx.getProjectContext(req);
|
|
310270
|
+
if (projectId !== requestedProjectId) throw badRequest("project context does not match projectId");
|
|
310271
|
+
return store.getSecretsStore();
|
|
310272
|
+
}
|
|
309972
310273
|
function emitSecretsAudit(req, ctx, type, metadata) {
|
|
309973
310274
|
const requestWithAuditor = req;
|
|
309974
310275
|
if (requestWithAuditor.runAuditor?.filesystem) {
|
|
@@ -309984,11 +310285,10 @@ var init_register_secrets_routes = __esm({
|
|
|
309984
310285
|
init_src2();
|
|
309985
310286
|
init_api_error();
|
|
309986
310287
|
registerSecretsRoutes = (ctx) => {
|
|
309987
|
-
const { router,
|
|
310288
|
+
const { router, rethrowAsApiError: rethrowAsApiError8 } = ctx;
|
|
309988
310289
|
router.get("/secrets", async (req, res) => {
|
|
309989
310290
|
try {
|
|
309990
|
-
const
|
|
309991
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310291
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
309992
310292
|
const secrets2 = await secretsStore.listSecrets();
|
|
309993
310293
|
const visibleSecrets = secrets2.filter(
|
|
309994
310294
|
(secret) => !(secret.scope === "global" && secret.key === RESERVED_SYNC_PASSPHRASE_KEY)
|
|
@@ -310002,8 +310302,7 @@ var init_register_secrets_routes = __esm({
|
|
|
310002
310302
|
});
|
|
310003
310303
|
router.get("/secrets/sync-passphrase", async (req, res) => {
|
|
310004
310304
|
try {
|
|
310005
|
-
const
|
|
310006
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310305
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
310007
310306
|
const configured = await hasSyncPassphraseConfigured(secretsStore);
|
|
310008
310307
|
res.json({ configured });
|
|
310009
310308
|
} catch (err) {
|
|
@@ -310014,14 +310313,14 @@ var init_register_secrets_routes = __esm({
|
|
|
310014
310313
|
});
|
|
310015
310314
|
router.put("/secrets/sync-passphrase", async (req, res) => {
|
|
310016
310315
|
try {
|
|
310316
|
+
getExplicitProjectId(req, ctx);
|
|
310017
310317
|
assertObject(req.body);
|
|
310018
310318
|
const passphrase = req.body.passphrase;
|
|
310019
310319
|
if (typeof passphrase !== "string" || passphrase.trim().length === 0) {
|
|
310020
310320
|
res.status(400).json({ error: "invalid-passphrase" });
|
|
310021
310321
|
return;
|
|
310022
310322
|
}
|
|
310023
|
-
const
|
|
310024
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310323
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
310025
310324
|
const hadConfiguredPassphrase = await hasSyncPassphraseConfigured(secretsStore);
|
|
310026
310325
|
await setSyncPassphrase(secretsStore, passphrase);
|
|
310027
310326
|
emitSecretsAudit(req, ctx, hadConfiguredPassphrase ? "secret:update" : "secret:create", {
|
|
@@ -310037,8 +310336,7 @@ var init_register_secrets_routes = __esm({
|
|
|
310037
310336
|
});
|
|
310038
310337
|
router.delete("/secrets/sync-passphrase", async (req, res) => {
|
|
310039
310338
|
try {
|
|
310040
|
-
const
|
|
310041
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310339
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
310042
310340
|
await clearSyncPassphrase(secretsStore);
|
|
310043
310341
|
emitSecretsAudit(req, ctx, "secret:delete", { key: RESERVED_SYNC_PASSPHRASE_KEY, scope: "global" });
|
|
310044
310342
|
res.json({ success: true });
|
|
@@ -310050,6 +310348,7 @@ var init_register_secrets_routes = __esm({
|
|
|
310050
310348
|
});
|
|
310051
310349
|
router.post("/secrets", async (req, res) => {
|
|
310052
310350
|
try {
|
|
310351
|
+
getExplicitProjectId(req, ctx);
|
|
310053
310352
|
assertObject(req.body);
|
|
310054
310353
|
const { scope, key, value, description, accessPolicy, envExportable, envExportKey } = req.body;
|
|
310055
310354
|
const parsedScope = parseScope(scope);
|
|
@@ -310066,8 +310365,7 @@ var init_register_secrets_routes = __esm({
|
|
|
310066
310365
|
}
|
|
310067
310366
|
parsedAccessPolicy = accessPolicy;
|
|
310068
310367
|
}
|
|
310069
|
-
const
|
|
310070
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310368
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
310071
310369
|
const secret = await secretsStore.createSecret({
|
|
310072
310370
|
scope: parsedScope,
|
|
310073
310371
|
key,
|
|
@@ -310086,6 +310384,7 @@ var init_register_secrets_routes = __esm({
|
|
|
310086
310384
|
});
|
|
310087
310385
|
router.patch("/secrets/:scope/:id", async (req, res) => {
|
|
310088
310386
|
try {
|
|
310387
|
+
getExplicitProjectId(req, ctx);
|
|
310089
310388
|
const scope = parseScope(req.params.scope);
|
|
310090
310389
|
const id = String(req.params.id ?? "").trim();
|
|
310091
310390
|
if (!id) throw badRequest("id is required");
|
|
@@ -310129,8 +310428,7 @@ var init_register_secrets_routes = __esm({
|
|
|
310129
310428
|
patch.plaintextValue = req.body.value;
|
|
310130
310429
|
}
|
|
310131
310430
|
}
|
|
310132
|
-
const
|
|
310133
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310431
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
310134
310432
|
const secret = await secretsStore.updateSecret(id, scope, patch);
|
|
310135
310433
|
res.json(secret);
|
|
310136
310434
|
} catch (err) {
|
|
@@ -310141,11 +310439,11 @@ var init_register_secrets_routes = __esm({
|
|
|
310141
310439
|
});
|
|
310142
310440
|
router.delete("/secrets/:scope/:id", async (req, res) => {
|
|
310143
310441
|
try {
|
|
310442
|
+
getExplicitProjectId(req, ctx);
|
|
310144
310443
|
const scope = parseScope(req.params.scope);
|
|
310145
310444
|
const id = String(req.params.id ?? "").trim();
|
|
310146
310445
|
if (!id) throw badRequest("id is required");
|
|
310147
|
-
const
|
|
310148
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310446
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
310149
310447
|
await secretsStore.deleteSecret(id, scope);
|
|
310150
310448
|
res.status(204).send();
|
|
310151
310449
|
} catch (err) {
|
|
@@ -310156,11 +310454,11 @@ var init_register_secrets_routes = __esm({
|
|
|
310156
310454
|
});
|
|
310157
310455
|
router.post("/secrets/:scope/:id/reveal", async (req, res) => {
|
|
310158
310456
|
try {
|
|
310457
|
+
getExplicitProjectId(req, ctx);
|
|
310159
310458
|
const scope = parseScope(req.params.scope);
|
|
310160
310459
|
const id = String(req.params.id ?? "").trim();
|
|
310161
310460
|
if (!id) throw badRequest("id is required");
|
|
310162
|
-
const
|
|
310163
|
-
const secretsStore = await scopedStore.getSecretsStore();
|
|
310461
|
+
const secretsStore = await getExplicitSecretsStore(req, ctx);
|
|
310164
310462
|
const secret = await secretsStore.revealSecret(id, scope, {
|
|
310165
310463
|
userId: null
|
|
310166
310464
|
});
|
|
@@ -311759,7 +312057,7 @@ var init_register_gitlab = __esm({
|
|
|
311759
312057
|
|
|
311760
312058
|
// ../dashboard/src/terminal.ts
|
|
311761
312059
|
import { spawn as spawn11 } from "node:child_process";
|
|
311762
|
-
import { randomUUID as
|
|
312060
|
+
import { randomUUID as randomUUID54 } from "node:crypto";
|
|
311763
312061
|
import { EventEmitter as EventEmitter42 } from "node:events";
|
|
311764
312062
|
function extractBaseCommand(command) {
|
|
311765
312063
|
let trimmed = command.trim();
|
|
@@ -311919,7 +312217,7 @@ var init_terminal = __esm({
|
|
|
311919
312217
|
if (!validation.valid) {
|
|
311920
312218
|
return { sessionId: "", error: validation.error };
|
|
311921
312219
|
}
|
|
311922
|
-
const sessionId =
|
|
312220
|
+
const sessionId = randomUUID54();
|
|
311923
312221
|
const childProcess6 = spawn11(command, [], {
|
|
311924
312222
|
cwd,
|
|
311925
312223
|
shell: true,
|
|
@@ -340729,7 +341027,7 @@ var init_register_node_routes = __esm({
|
|
|
340729
341027
|
});
|
|
340730
341028
|
|
|
340731
341029
|
// ../dashboard/src/routes/register-docker-node-routes.ts
|
|
340732
|
-
import { randomUUID as
|
|
341030
|
+
import { randomUUID as randomUUID55 } from "node:crypto";
|
|
340733
341031
|
function sanitizeHostConfig(input) {
|
|
340734
341032
|
const host = input ?? {};
|
|
340735
341033
|
return {
|
|
@@ -341108,7 +341406,7 @@ var init_register_docker_node_routes = __esm({
|
|
|
341108
341406
|
if (!managedNode) {
|
|
341109
341407
|
throw notFound("Managed Docker node not found");
|
|
341110
341408
|
}
|
|
341111
|
-
const newKey =
|
|
341409
|
+
const newKey = randomUUID55().replace(/-/g, "");
|
|
341112
341410
|
await central.updateManagedDockerNode(managedId, { apiKey: newKey });
|
|
341113
341411
|
if (managedNode.nodeId) {
|
|
341114
341412
|
await central.updateNode(managedNode.nodeId, { apiKey: newKey });
|
|
@@ -349976,7 +350274,7 @@ var init_register_agent_reflection_rating_routes = __esm({
|
|
|
349976
350274
|
});
|
|
349977
350275
|
|
|
349978
350276
|
// ../dashboard/src/agent-generation.ts
|
|
349979
|
-
import { randomUUID as
|
|
350277
|
+
import { randomUUID as randomUUID56 } from "node:crypto";
|
|
349980
350278
|
async function initPromptCatalog() {
|
|
349981
350279
|
if (promptCatalogReady) return;
|
|
349982
350280
|
try {
|
|
@@ -350182,7 +350480,7 @@ async function startAgentGeneration(ip, roleDescription) {
|
|
|
350182
350480
|
`Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR4} generation sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
|
|
350183
350481
|
);
|
|
350184
350482
|
}
|
|
350185
|
-
const sessionId =
|
|
350483
|
+
const sessionId = randomUUID56();
|
|
350186
350484
|
const session = {
|
|
350187
350485
|
id: sessionId,
|
|
350188
350486
|
ip,
|
|
@@ -350381,7 +350679,7 @@ __export(agent_onboarding_exports, {
|
|
|
350381
350679
|
startAgentOnboardingSession: () => startAgentOnboardingSession,
|
|
350382
350680
|
stopAgentOnboardingGeneration: () => stopAgentOnboardingGeneration
|
|
350383
350681
|
});
|
|
350384
|
-
import { randomUUID as
|
|
350682
|
+
import { randomUUID as randomUUID57 } from "node:crypto";
|
|
350385
350683
|
import { EventEmitter as EventEmitter43 } from "node:events";
|
|
350386
350684
|
function extractJsonCandidate6(text3) {
|
|
350387
350685
|
const codeBlockMatch = text3.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
|
|
@@ -350481,7 +350779,7 @@ Current agent configuration:
|
|
|
350481
350779
|
${currentConfigLines}`;
|
|
350482
350780
|
}
|
|
350483
350781
|
async function startAgentOnboardingSession(ip, initialContext, rootDir, modelProvider, modelId, promptOverrides, pluginRunner, store) {
|
|
350484
|
-
const id =
|
|
350782
|
+
const id = randomUUID57();
|
|
350485
350783
|
const mode = initialContext.mode ?? "create";
|
|
350486
350784
|
const session = {
|
|
350487
350785
|
id,
|
|
@@ -353263,7 +353561,7 @@ var init_src8 = __esm({
|
|
|
353263
353561
|
|
|
353264
353562
|
// ../../plugins/fusion-plugin-openclaw-runtime/src/pi-module.ts
|
|
353265
353563
|
import { spawn as spawn15 } from "node:child_process";
|
|
353266
|
-
import { randomUUID as
|
|
353564
|
+
import { randomUUID as randomUUID58 } from "node:crypto";
|
|
353267
353565
|
import { readFile as readFile51 } from "node:fs/promises";
|
|
353268
353566
|
function asString2(v2) {
|
|
353269
353567
|
return typeof v2 === "string" && v2.trim() !== "" ? v2.trim() : void 0;
|
|
@@ -353323,7 +353621,7 @@ function extractStderrError(stderr, stdout) {
|
|
|
353323
353621
|
}
|
|
353324
353622
|
function createCliSession(opts) {
|
|
353325
353623
|
return {
|
|
353326
|
-
sessionId:
|
|
353624
|
+
sessionId: randomUUID58(),
|
|
353327
353625
|
agentId: opts.agentId ?? DEFAULT_AGENT_ID,
|
|
353328
353626
|
systemPrompt: opts.systemPrompt,
|
|
353329
353627
|
messages: [{ role: "developer", content: opts.systemPrompt }],
|
|
@@ -353518,7 +353816,7 @@ var init_mcp_config2 = __esm({
|
|
|
353518
353816
|
});
|
|
353519
353817
|
|
|
353520
353818
|
// ../../plugins/fusion-plugin-openclaw-runtime/src/runtime-adapter.ts
|
|
353521
|
-
import { randomUUID as
|
|
353819
|
+
import { randomUUID as randomUUID59 } from "node:crypto";
|
|
353522
353820
|
var OpenClawRuntimeAdapter;
|
|
353523
353821
|
var init_runtime_adapter2 = __esm({
|
|
353524
353822
|
"../../plugins/fusion-plugin-openclaw-runtime/src/runtime-adapter.ts"() {
|
|
@@ -353541,8 +353839,8 @@ var init_runtime_adapter2 = __esm({
|
|
|
353541
353839
|
let mcpProfile;
|
|
353542
353840
|
let mcpConfigPath;
|
|
353543
353841
|
if (toolDefs.length > 0) {
|
|
353544
|
-
const bridge = writeOpenClawMcpBridgeFiles(toolDefs,
|
|
353545
|
-
mcpProfile = `fusion-${
|
|
353842
|
+
const bridge = writeOpenClawMcpBridgeFiles(toolDefs, randomUUID59());
|
|
353843
|
+
mcpProfile = `fusion-${randomUUID59()}`;
|
|
353546
353844
|
mcpConfigPath = bridge.serverConfigPath;
|
|
353547
353845
|
await configureOpenClawMcpServer({
|
|
353548
353846
|
binaryPath: this.config.binaryPath,
|
|
@@ -357597,7 +357895,7 @@ import { existsSync as existsSync77, writeFileSync as writeFileSync15 } from "no
|
|
|
357597
357895
|
import { tmpdir as tmpdir17 } from "node:os";
|
|
357598
357896
|
import { dirname as dirname45, join as join104 } from "node:path";
|
|
357599
357897
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
357600
|
-
import { randomUUID as
|
|
357898
|
+
import { randomUUID as randomUUID60 } from "node:crypto";
|
|
357601
357899
|
function toolsToMcpToolDefs2(tools) {
|
|
357602
357900
|
if (!Array.isArray(tools)) return [];
|
|
357603
357901
|
return tools.filter((tool) => tool && typeof tool.name === "string" && tool.name.trim().length > 0 && !BUILT_IN_TOOL_NAMES2.has(tool.name)).map((tool) => ({
|
|
@@ -357648,7 +357946,7 @@ async function startFusionToolBridge(tools) {
|
|
|
357648
357946
|
byName.set(tool.name, tool);
|
|
357649
357947
|
}
|
|
357650
357948
|
}
|
|
357651
|
-
const schemaPath = join104(tmpdir17(), `fusion-grok-mcp-schemas-${process.pid}-${
|
|
357949
|
+
const schemaPath = join104(tmpdir17(), `fusion-grok-mcp-schemas-${process.pid}-${randomUUID60()}.json`);
|
|
357652
357950
|
writeFileSync15(schemaPath, JSON.stringify(defs));
|
|
357653
357951
|
const server = createServer2(async (req, res) => {
|
|
357654
357952
|
if (req.method !== "POST" || req.url !== "/tool-call") {
|
|
@@ -357674,7 +357972,7 @@ async function startFusionToolBridge(tools) {
|
|
|
357674
357972
|
return;
|
|
357675
357973
|
}
|
|
357676
357974
|
try {
|
|
357677
|
-
const result2 = await tool.execute(`grok-mcp-${
|
|
357975
|
+
const result2 = await tool.execute(`grok-mcp-${randomUUID60()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
|
|
357678
357976
|
res.statusCode = 200;
|
|
357679
357977
|
res.setHeader("content-type", "application/json");
|
|
357680
357978
|
res.end(
|
|
@@ -359718,7 +360016,7 @@ import { existsSync as existsSync81, rmSync as rmSync13, writeFileSync as writeF
|
|
|
359718
360016
|
import { tmpdir as tmpdir19 } from "node:os";
|
|
359719
360017
|
import { dirname as dirname50, join as join109 } from "node:path";
|
|
359720
360018
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
359721
|
-
import { randomBytes as randomBytes8, randomUUID as
|
|
360019
|
+
import { randomBytes as randomBytes8, randomUUID as randomUUID61 } from "node:crypto";
|
|
359722
360020
|
function toolsToMcpToolDefs3(tools) {
|
|
359723
360021
|
if (!Array.isArray(tools)) return [];
|
|
359724
360022
|
return tools.filter((tool) => tool && typeof tool.name === "string" && tool.name.trim().length > 0 && !BUILT_IN_TOOL_NAMES3.has(tool.name)).map((tool) => ({
|
|
@@ -359769,7 +360067,7 @@ async function startFusionToolBridge2(tools, options = {}) {
|
|
|
359769
360067
|
byName.set(tool.name, tool);
|
|
359770
360068
|
}
|
|
359771
360069
|
}
|
|
359772
|
-
const schemaPath = join109(tmpdir19(), `fusion-claude-mcp-schemas-${process.pid}-${
|
|
360070
|
+
const schemaPath = join109(tmpdir19(), `fusion-claude-mcp-schemas-${process.pid}-${randomUUID61()}.json`);
|
|
359773
360071
|
writeFileSync17(schemaPath, JSON.stringify(defs));
|
|
359774
360072
|
const capabilityToken = randomBytes8(32).toString("base64url");
|
|
359775
360073
|
const server = createServer3(async (req, res) => {
|
|
@@ -359834,7 +360132,7 @@ async function startFusionToolBridge2(tools, options = {}) {
|
|
|
359834
360132
|
return;
|
|
359835
360133
|
}
|
|
359836
360134
|
try {
|
|
359837
|
-
const result2 = await tool.execute(`claude-mcp-${
|
|
360135
|
+
const result2 = await tool.execute(`claude-mcp-${randomUUID61()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
|
|
359838
360136
|
res.statusCode = 200;
|
|
359839
360137
|
res.setHeader("content-type", "application/json");
|
|
359840
360138
|
res.end(
|
|
@@ -361911,7 +362209,7 @@ import { existsSync as existsSync83, unlinkSync as unlinkSync5, writeFileSync as
|
|
|
361911
362209
|
import { tmpdir as tmpdir20 } from "node:os";
|
|
361912
362210
|
import { dirname as dirname53, join as join112 } from "node:path";
|
|
361913
362211
|
import { fileURLToPath as fileURLToPath17 } from "node:url";
|
|
361914
|
-
import { randomUUID as
|
|
362212
|
+
import { randomUUID as randomUUID62 } from "node:crypto";
|
|
361915
362213
|
function toolsToMcpToolDefs4(tools) {
|
|
361916
362214
|
if (!Array.isArray(tools)) return [];
|
|
361917
362215
|
return tools.filter(
|
|
@@ -361968,7 +362266,7 @@ async function startFusionToolBridge3(tools) {
|
|
|
361968
362266
|
byName.set(tool.name, tool);
|
|
361969
362267
|
}
|
|
361970
362268
|
}
|
|
361971
|
-
const schemaPath = join112(tmpdir20(), `fusion-omp-mcp-schemas-${process.pid}-${
|
|
362269
|
+
const schemaPath = join112(tmpdir20(), `fusion-omp-mcp-schemas-${process.pid}-${randomUUID62()}.json`);
|
|
361972
362270
|
writeFileSync18(schemaPath, JSON.stringify(defs));
|
|
361973
362271
|
const server = createServer4(async (req, res) => {
|
|
361974
362272
|
if (req.method !== "POST" || req.url !== "/tool-call") {
|
|
@@ -361995,7 +362293,7 @@ async function startFusionToolBridge3(tools) {
|
|
|
361995
362293
|
}
|
|
361996
362294
|
try {
|
|
361997
362295
|
const result2 = await tool.execute(
|
|
361998
|
-
`omp-mcp-${
|
|
362296
|
+
`omp-mcp-${randomUUID62()}`,
|
|
361999
362297
|
parsed.arguments ?? {},
|
|
362000
362298
|
void 0,
|
|
362001
362299
|
void 0,
|
|
@@ -363091,7 +363389,7 @@ var init_paperclip_client = __esm({
|
|
|
363091
363389
|
});
|
|
363092
363390
|
|
|
363093
363391
|
// ../../plugins/fusion-plugin-paperclip-runtime/src/runtime-adapter.ts
|
|
363094
|
-
import { randomUUID as
|
|
363392
|
+
import { randomUUID as randomUUID63 } from "node:crypto";
|
|
363095
363393
|
function sleep7(ms2) {
|
|
363096
363394
|
return new Promise((resolve104) => setTimeout(resolve104, ms2));
|
|
363097
363395
|
}
|
|
@@ -363220,7 +363518,7 @@ var init_runtime_adapter10 = __esm({
|
|
|
363220
363518
|
apiKey: effectiveApiKey,
|
|
363221
363519
|
agentId,
|
|
363222
363520
|
companyId,
|
|
363223
|
-
sessionId:
|
|
363521
|
+
sessionId: randomUUID63(),
|
|
363224
363522
|
systemPrompt: options.systemPrompt,
|
|
363225
363523
|
cwd: options.cwd,
|
|
363226
363524
|
mode: normalizeMode3(this.config.mode),
|
|
@@ -366720,7 +367018,7 @@ var init_command_center_csv = __esm({
|
|
|
366720
367018
|
});
|
|
366721
367019
|
|
|
366722
367020
|
// ../dashboard/src/monitor-store.ts
|
|
366723
|
-
import { randomUUID as
|
|
367021
|
+
import { randomUUID as randomUUID64 } from "node:crypto";
|
|
366724
367022
|
function monitorProjectId(layer) {
|
|
366725
367023
|
if (!layer.projectId) {
|
|
366726
367024
|
throw new Error("PostgreSQL monitor writes require asyncLayer.projectId");
|
|
@@ -366752,7 +367050,7 @@ async function recordDeployment(db, input) {
|
|
|
366752
367050
|
return recordDeploymentAsync(layer.db, input, monitorProjectId(layer));
|
|
366753
367051
|
}
|
|
366754
367052
|
const sqliteDb = db;
|
|
366755
|
-
const deploymentId = input.deploymentId?.trim() || `dep-${
|
|
367053
|
+
const deploymentId = input.deploymentId?.trim() || `dep-${randomUUID64()}`;
|
|
366756
367054
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
366757
367055
|
const deployedAt = input.deployedAt ?? now;
|
|
366758
367056
|
const meta2 = input.meta ? JSON.stringify(input.meta) : null;
|
|
@@ -366818,7 +367116,7 @@ async function ingestIncidentSignal(db, input) {
|
|
|
366818
367116
|
const updated = getIncident(sqliteDb, existing.incidentId);
|
|
366819
367117
|
return { incident: updated ?? existing, created: false };
|
|
366820
367118
|
}
|
|
366821
|
-
const incidentId = `inc-${
|
|
367119
|
+
const incidentId = `inc-${randomUUID64()}`;
|
|
366822
367120
|
const meta2 = {
|
|
366823
367121
|
...input.meta ?? {},
|
|
366824
367122
|
[OCCURRENCES_META_KEY2]: 1,
|
|
@@ -371419,7 +371717,7 @@ var init_types6 = __esm({
|
|
|
371419
371717
|
});
|
|
371420
371718
|
|
|
371421
371719
|
// ../dashboard/src/stt/model-manager.ts
|
|
371422
|
-
import { createHash as createHash31, randomUUID as
|
|
371720
|
+
import { createHash as createHash31, randomUUID as randomUUID65 } from "node:crypto";
|
|
371423
371721
|
import { mkdir as mkdir38, open as open4, readFile as readFile56, readdir as readdir14, rename as rename10, rm as rm21, stat as stat16, writeFile as writeFile37 } from "node:fs/promises";
|
|
371424
371722
|
import { join as join118, relative as relative22, resolve as resolve68, sep as sep18 } from "node:path";
|
|
371425
371723
|
function parseSafeTarListing(listing) {
|
|
@@ -371500,8 +371798,8 @@ function createVoiceModelManager(options = {}) {
|
|
|
371500
371798
|
if (!current(g2, signal)) return state;
|
|
371501
371799
|
await mkdir38(cacheDir(), { recursive: true });
|
|
371502
371800
|
if (!current(g2, signal)) return state;
|
|
371503
|
-
partial2 = join118(cacheDir(), `.partial-${g2}-${
|
|
371504
|
-
staging = join118(cacheDir(), `.staging-${g2}-${
|
|
371801
|
+
partial2 = join118(cacheDir(), `.partial-${g2}-${randomUUID65()}`);
|
|
371802
|
+
staging = join118(cacheDir(), `.staging-${g2}-${randomUUID65()}`);
|
|
371505
371803
|
const file = await open4(partial2, "wx");
|
|
371506
371804
|
try {
|
|
371507
371805
|
const response = await (options.fetch ?? globalThis.fetch)(asset.url, { signal });
|
|
@@ -371549,7 +371847,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
371549
371847
|
await writeFile37(join118(staging, "manifest.json"), JSON.stringify({ filename: asset.filename, sha256: asset.sha256, installedAt: (/* @__PURE__ */ new Date()).toISOString(), expectedFiles: asset.expectedFiles }));
|
|
371550
371848
|
await options.beforePromote?.(signal);
|
|
371551
371849
|
if (!current(g2, signal)) return state;
|
|
371552
|
-
const backup = join118(cacheDir(), `.backup-${g2}-${
|
|
371850
|
+
const backup = join118(cacheDir(), `.backup-${g2}-${randomUUID65()}`);
|
|
371553
371851
|
let movedPrevious = false;
|
|
371554
371852
|
try {
|
|
371555
371853
|
try {
|
|
@@ -371770,7 +372068,7 @@ var init_parakeet_service = __esm({
|
|
|
371770
372068
|
});
|
|
371771
372069
|
|
|
371772
372070
|
// ../dashboard/src/routes/register-voice-routes.ts
|
|
371773
|
-
import { randomUUID as
|
|
372071
|
+
import { randomUUID as randomUUID66 } from "node:crypto";
|
|
371774
372072
|
import express from "express";
|
|
371775
372073
|
async function settingsFor(ctx, req) {
|
|
371776
372074
|
const scoped = await ctx.getScopedStore(req);
|
|
@@ -371849,7 +372147,7 @@ function createRegisterVoiceRoutes(deps = {}) {
|
|
|
371849
372147
|
recognizer.close();
|
|
371850
372148
|
return error2(res, 409, { error: "unavailable", reason: "model-removed" });
|
|
371851
372149
|
}
|
|
371852
|
-
const id =
|
|
372150
|
+
const id = randomUUID66();
|
|
371853
372151
|
const now = Date.now();
|
|
371854
372152
|
sessions7.set(id, { projectId, recognizer, next: 0, bytes: 0, last: now, expires: now + 3e5 });
|
|
371855
372153
|
res.status(201).json({ sessionId: id, expiresAt: new Date(now + 3e5).toISOString(), modelId: model.id, language: language.language });
|
|
@@ -372320,7 +372618,7 @@ var init_fn_binary_local_install = __esm({
|
|
|
372320
372618
|
});
|
|
372321
372619
|
|
|
372322
372620
|
// ../dashboard/src/routes/register-system-routes.ts
|
|
372323
|
-
import { randomUUID as
|
|
372621
|
+
import { randomUUID as randomUUID67 } from "node:crypto";
|
|
372324
372622
|
import { existsSync as existsSync87 } from "node:fs";
|
|
372325
372623
|
import { join as join120 } from "node:path";
|
|
372326
372624
|
function rejectCrossOrigin(req, res) {
|
|
@@ -372517,7 +372815,7 @@ function registerSystemRoutes(ctx, deps) {
|
|
|
372517
372815
|
throw new ApiError(409, `Build script missing: ${scriptPath}`);
|
|
372518
372816
|
}
|
|
372519
372817
|
const job = {
|
|
372520
|
-
id:
|
|
372818
|
+
id: randomUUID67(),
|
|
372521
372819
|
kind: "rebuild",
|
|
372522
372820
|
scope,
|
|
372523
372821
|
restartAfter,
|
|
@@ -372807,7 +373105,7 @@ function registerSystemRoutes(ctx, deps) {
|
|
|
372807
373105
|
throw new ApiError(409, `A ${activeJob.kind}/${activeJob.scope} job is already running`);
|
|
372808
373106
|
}
|
|
372809
373107
|
const job = {
|
|
372810
|
-
id:
|
|
373108
|
+
id: randomUUID67(),
|
|
372811
373109
|
kind,
|
|
372812
373110
|
scope,
|
|
372813
373111
|
restartAfter,
|
|
@@ -373095,7 +373393,7 @@ var init_cli_agent_settings = __esm({
|
|
|
373095
373393
|
|
|
373096
373394
|
// ../dashboard/src/mission-routes.ts
|
|
373097
373395
|
import { Router as Router5 } from "express";
|
|
373098
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
373396
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
373099
373397
|
function resolveMissionInterviewThinkingLevel(settings, thinkingLevel) {
|
|
373100
373398
|
return resolvePlanningThinkingLevel(settings, thinkingLevel);
|
|
373101
373399
|
}
|
|
@@ -373279,7 +373577,7 @@ function replayBufferedSSE(res, bufferedEvents) {
|
|
|
373279
373577
|
}
|
|
373280
373578
|
function createMissionRouter(store, missionAutopilot, aiSessionStore, missionExecutionLoop, engineManager, pluginRunner, options) {
|
|
373281
373579
|
const router = Router5();
|
|
373282
|
-
const requestContext = new
|
|
373580
|
+
const requestContext = new AsyncLocalStorage2();
|
|
373283
373581
|
function getScopedStore2() {
|
|
373284
373582
|
return requestContext.getStore() ?? store;
|
|
373285
373583
|
}
|
|
@@ -375790,11 +376088,11 @@ var init_mission_routes = __esm({
|
|
|
375790
376088
|
});
|
|
375791
376089
|
|
|
375792
376090
|
// ../dashboard/src/ideation-routes.ts
|
|
375793
|
-
import { AsyncLocalStorage as
|
|
376091
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
|
|
375794
376092
|
import { Router as Router6 } from "express";
|
|
375795
376093
|
function createIdeationRouter(store, options) {
|
|
375796
376094
|
const router = Router6();
|
|
375797
|
-
const requestContext = new
|
|
376095
|
+
const requestContext = new AsyncLocalStorage3();
|
|
375798
376096
|
const ideation = () => (requestContext.getStore() ?? store).getIdeationStore();
|
|
375799
376097
|
router.use(async (req, _res, next) => {
|
|
375800
376098
|
try {
|
|
@@ -375978,7 +376276,7 @@ var init_insight_run_sweeper = __esm({
|
|
|
375978
376276
|
|
|
375979
376277
|
// ../dashboard/src/insights-routes.ts
|
|
375980
376278
|
import { Router as Router7 } from "express";
|
|
375981
|
-
import { AsyncLocalStorage as
|
|
376279
|
+
import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
|
|
375982
376280
|
function rethrowAsApiError4(error3, fallbackMessage = "Internal server error") {
|
|
375983
376281
|
if (error3 instanceof ApiError) throw error3;
|
|
375984
376282
|
if (error3 instanceof Error) throw new ApiError(500, error3.message);
|
|
@@ -376122,7 +376420,7 @@ function toInsightTitle(content) {
|
|
|
376122
376420
|
}
|
|
376123
376421
|
function createInsightsRouter(store, options) {
|
|
376124
376422
|
const router = Router7();
|
|
376125
|
-
const requestContext = new
|
|
376423
|
+
const requestContext = new AsyncLocalStorage4();
|
|
376126
376424
|
let rootInsightStore;
|
|
376127
376425
|
if (typeof store.getInsightStore === "function") {
|
|
376128
376426
|
try {
|
|
@@ -376626,7 +376924,7 @@ var init_insights_routes = __esm({
|
|
|
376626
376924
|
|
|
376627
376925
|
// ../dashboard/src/evals-routes.ts
|
|
376628
376926
|
import { Router as Router8 } from "express";
|
|
376629
|
-
import { AsyncLocalStorage as
|
|
376927
|
+
import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
|
|
376630
376928
|
function rethrowAsApiError5(error3, fallbackMessage = "Internal server error") {
|
|
376631
376929
|
if (error3 instanceof ApiError) throw error3;
|
|
376632
376930
|
if (error3 instanceof Error) throw new ApiError(500, error3.message);
|
|
@@ -376653,7 +376951,7 @@ function normalizeEvalText(result2) {
|
|
|
376653
376951
|
}
|
|
376654
376952
|
function createEvalsRouter(store, options) {
|
|
376655
376953
|
const router = Router8();
|
|
376656
|
-
const requestContext = new
|
|
376954
|
+
const requestContext = new AsyncLocalStorage5();
|
|
376657
376955
|
router.use((req, _res, next) => {
|
|
376658
376956
|
getScopedStore(req, store, options).then((scopedStore) => requestContext.run(scopedStore, () => next())).catch((err) => {
|
|
376659
376957
|
try {
|
|
@@ -376737,7 +377035,7 @@ var init_evals_routes = __esm({
|
|
|
376737
377035
|
|
|
376738
377036
|
// ../dashboard/src/research-routes.ts
|
|
376739
377037
|
import { Router as Router9 } from "express";
|
|
376740
|
-
import { AsyncLocalStorage as
|
|
377038
|
+
import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
|
|
376741
377039
|
function rethrowAsApiError6(error3, fallback2 = "Internal server error") {
|
|
376742
377040
|
if (error3 instanceof ApiError) throw error3;
|
|
376743
377041
|
if (error3 instanceof ResearchLifecycleError) {
|
|
@@ -376829,7 +377127,7 @@ async function addFindingAttachment(scopedStore, taskId, filename, markdown) {
|
|
|
376829
377127
|
}
|
|
376830
377128
|
function createResearchRouter(store, options) {
|
|
376831
377129
|
const router = Router9();
|
|
376832
|
-
const requestContext = new
|
|
377130
|
+
const requestContext = new AsyncLocalStorage6();
|
|
376833
377131
|
router.use((req, _res, next) => {
|
|
376834
377132
|
getScopedStore(req, store, options).then((scopedStore) => requestContext.run(scopedStore, () => next())).catch((error3) => {
|
|
376835
377133
|
try {
|
|
@@ -377332,7 +377630,7 @@ var init_experiment_routes = __esm({
|
|
|
377332
377630
|
|
|
377333
377631
|
// ../dashboard/src/goals-routes.ts
|
|
377334
377632
|
import { Router as Router11 } from "express";
|
|
377335
|
-
import { AsyncLocalStorage as
|
|
377633
|
+
import { AsyncLocalStorage as AsyncLocalStorage7 } from "node:async_hooks";
|
|
377336
377634
|
function getGoalStore(store) {
|
|
377337
377635
|
return store.getGoalStore();
|
|
377338
377636
|
}
|
|
@@ -377388,7 +377686,7 @@ function rethrowGoalCapError(error3) {
|
|
|
377388
377686
|
}
|
|
377389
377687
|
function createGoalsRouter(store, options) {
|
|
377390
377688
|
const router = Router11();
|
|
377391
|
-
const requestContext = new
|
|
377689
|
+
const requestContext = new AsyncLocalStorage7();
|
|
377392
377690
|
function getScopedStore2() {
|
|
377393
377691
|
return requestContext.getStore() ?? store;
|
|
377394
377692
|
}
|
|
@@ -384061,7 +384359,7 @@ var init_provider_health_monitor = __esm({
|
|
|
384061
384359
|
|
|
384062
384360
|
// ../dashboard/src/server.ts
|
|
384063
384361
|
import express3 from "express";
|
|
384064
|
-
import { randomUUID as
|
|
384362
|
+
import { randomUUID as randomUUID68 } from "node:crypto";
|
|
384065
384363
|
import { join as join125, dirname as dirname57 } from "node:path";
|
|
384066
384364
|
import { existsSync as existsSync89, readFileSync as readFileSync32, statSync as statSync16 } from "node:fs";
|
|
384067
384365
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
@@ -385526,7 +385824,7 @@ function setupBadgeWebSocket(app, server, store, options) {
|
|
|
385526
385824
|
const dashboardApp = app;
|
|
385527
385825
|
const wsManager = new WebSocketManager();
|
|
385528
385826
|
const badgeSnapshots = /* @__PURE__ */ new Map();
|
|
385529
|
-
const serverId =
|
|
385827
|
+
const serverId = randomUUID68();
|
|
385530
385828
|
const badgePubSub = options?.badgePubSub ?? createBadgePubSub({ sourceId: serverId });
|
|
385531
385829
|
void badgePubSub.start();
|
|
385532
385830
|
const scopedStores = /* @__PURE__ */ new Map();
|
|
@@ -385668,7 +385966,7 @@ function setupBadgeWebSocket(app, server, store, options) {
|
|
|
385668
385966
|
const url2 = new URL(req.url || "", `http://${req.headers.host}`);
|
|
385669
385967
|
const projectId = url2.searchParams.get("projectId") ?? "default";
|
|
385670
385968
|
void ensureScopedListeners(projectId);
|
|
385671
|
-
wsManager.addClient(ws2,
|
|
385969
|
+
wsManager.addClient(ws2, randomUUID68(), projectId);
|
|
385672
385970
|
});
|
|
385673
385971
|
server.once("close", async () => {
|
|
385674
385972
|
for (const cleanup of scopedCleanups.values()) {
|
|
@@ -386500,7 +386798,7 @@ import { Type as Type9 } from "typebox";
|
|
|
386500
386798
|
import { StringEnum } from "@earendil-works/pi-ai";
|
|
386501
386799
|
import { resolve as resolve75, relative as relative25, isAbsolute as isAbsolute33, sep as sep22, basename as basename36, extname as extname5, join as join127 } from "node:path";
|
|
386502
386800
|
import { existsSync as existsSync90 } from "node:fs";
|
|
386503
|
-
import { AsyncLocalStorage as
|
|
386801
|
+
import { AsyncLocalStorage as AsyncLocalStorage8 } from "node:async_hooks";
|
|
386504
386802
|
function resolveProjectRoot2(cwd) {
|
|
386505
386803
|
const worktreeProjectRoot = typeof getProjectRootFromWorktree === "function" ? getProjectRootFromWorktree(cwd) : null;
|
|
386506
386804
|
if (typeof getProjectRootFromWorktree !== "function" && !warnedMissingProjectRootResolver) {
|
|
@@ -386566,7 +386864,7 @@ var init_extension = __esm({
|
|
|
386566
386864
|
storeCache2 = extensionStoreState.cache;
|
|
386567
386865
|
storeBootInflight = extensionStoreState.bootInflight;
|
|
386568
386866
|
storeBootFailureCooldown = extensionStoreState.bootFailureCooldown;
|
|
386569
|
-
extensionToolSignal = new
|
|
386867
|
+
extensionToolSignal = new AsyncLocalStorage8();
|
|
386570
386868
|
}
|
|
386571
386869
|
});
|
|
386572
386870
|
|
|
@@ -396969,6 +397267,7 @@ var init_dev_source_restart = __esm({
|
|
|
396969
397267
|
var dashboard_exports = {};
|
|
396970
397268
|
__export(dashboard_exports, {
|
|
396971
397269
|
StreamedLogBuffer: () => StreamedLogBuffer,
|
|
397270
|
+
buildUiOnlyHeartbeatMonitorOptions: () => buildUiOnlyHeartbeatMonitorOptions,
|
|
396972
397271
|
classifyDashboardFatalExit: () => classifyDashboardFatalExit,
|
|
396973
397272
|
countActiveTasks: () => countActiveTasks,
|
|
396974
397273
|
hasLiveSupervisingParent: () => hasLiveSupervisingParent,
|
|
@@ -396997,6 +397296,15 @@ async function countActiveTasks(store, tasks2) {
|
|
|
396997
397296
|
}
|
|
396998
397297
|
return active;
|
|
396999
397298
|
}
|
|
397299
|
+
function buildUiOnlyHeartbeatMonitorOptions(input) {
|
|
397300
|
+
return {
|
|
397301
|
+
store: input.agentStore,
|
|
397302
|
+
agentStore: input.agentStore,
|
|
397303
|
+
taskStore: input.taskStore,
|
|
397304
|
+
rootDir: input.rootDir,
|
|
397305
|
+
secretsStore: input.secretsStore
|
|
397306
|
+
};
|
|
397307
|
+
}
|
|
397000
397308
|
function formatRuntimeContext(context) {
|
|
397001
397309
|
if (context === void 0) {
|
|
397002
397310
|
return "";
|
|
@@ -398481,11 +398789,14 @@ async function runDashboard(port, opts = {}) {
|
|
|
398481
398789
|
logSink.warn(`Failed to initialize mesh networking: ${message}`, "dashboard");
|
|
398482
398790
|
}
|
|
398483
398791
|
try {
|
|
398792
|
+
const secretsStore = await store.getSecretsStore();
|
|
398484
398793
|
heartbeatMonitorImpl = new HeartbeatMonitor({
|
|
398485
|
-
|
|
398486
|
-
|
|
398487
|
-
|
|
398488
|
-
|
|
398794
|
+
...buildUiOnlyHeartbeatMonitorOptions({
|
|
398795
|
+
agentStore,
|
|
398796
|
+
taskStore: store,
|
|
398797
|
+
rootDir: cwd,
|
|
398798
|
+
secretsStore
|
|
398799
|
+
}),
|
|
398489
398800
|
onMissed: (agentId, reason) => {
|
|
398490
398801
|
logSink.warn(`Agent ${agentId} missed heartbeat: ${reason}`, "engine");
|
|
398491
398802
|
},
|