@runfusion/fusion 0.75.1-beta.0 → 0.75.1-beta.1
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 +259 -76
- package/dist/child-process-worker.js +185 -61
- package/dist/client/.vite/manifest.json +248 -248
- package/dist/client/assets/{AgentDetailView-swTdiyeE.js → AgentDetailView-CE_7nvDT.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-Dq-KuDaA.js → AgentPermissionPolicyEditor-DYr3dk5X.js} +1 -1
- package/dist/client/assets/{AgentsView-D1GEHyH0.js → AgentsView-DZoYoiaD.js} +3 -3
- package/dist/client/assets/{ChatView-D1czGvvT.js → ChatView-BE9zMzYZ.js} +1 -1
- package/dist/client/assets/{CommandCenter-DWZ7OTOB.js → CommandCenter-DnLsp4_S.js} +1 -1
- package/dist/client/assets/{DevServerView-CAcUKOXd.js → DevServerView-CI-3j-lH.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DVUl5jOk.js → DirectoryPicker-D1ADu0Av.js} +1 -1
- package/dist/client/assets/{DocumentsView-CnexOxtr.js → DocumentsView-CF8y1gob.js} +1 -1
- package/dist/client/assets/{EvalsView-rTupzcDf.js → EvalsView-C9vLiM2_.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CXE6Bj3V.js → ExperimentalAgentOnboardingModal-CX_2Hjh0.js} +1 -1
- package/dist/client/assets/{GoalsView-CjHwnnIi.js → GoalsView-DJIA3k8q.js} +1 -1
- package/dist/client/assets/{InsightsView-C3XocYP-.js → InsightsView--TCeutLO.js} +1 -1
- package/dist/client/assets/{MemoryView-CsNHcx_d.js → MemoryView-Btp4m7pK.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BPTPoZBI.js → PiExtensionsManager-DXdfh-Uf.js} +1 -1
- package/dist/client/assets/{PluginManager-CXadn8JE.js → PluginManager-BDFelFY6.js} +1 -1
- package/dist/client/assets/{PullRequestView-CC03CtZJ.js → PullRequestView-TSNKGSAg.js} +1 -1
- package/dist/client/assets/{ReportModal-Ci0na1eI.js → ReportModal-DhXMNHDL.js} +1 -1
- package/dist/client/assets/{ResearchView-DGWyAo8p.js → ResearchView-0w30HikQ.js} +1 -1
- package/dist/client/assets/{SecretsView-Cv2IuqFO.js → SecretsView-DgMu7279.js} +1 -1
- package/dist/client/assets/{SessionTerminal-B22RlQeo.js → SessionTerminal-CF6_uy2u.js} +1 -1
- package/dist/client/assets/{SettingsModal-BkgBQZ19.js → SettingsModal-BMAPX_7v.js} +1 -1
- package/dist/client/assets/{SettingsModal-CPRpRK71.js → SettingsModal-Dckls6LL.js} +3 -3
- package/dist/client/assets/{SettingsTextareaRow-0LXwMUQR.js → SettingsTextareaRow-LqXxpJl5.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-CyW3AlRO.js → SetupWizardModal-D1ZvGOcK.js} +2 -2
- package/dist/client/assets/{SkillsView-3oqB1ubq.js → SkillsView-CfO5B7SO.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-CfUK_xs1.js → WorkflowNodeEditor-CjdK9fFS.js} +3 -3
- package/dist/client/assets/{agent-import-generation-C7-Cmo3M.js → agent-import-generation-DqTzyLOZ.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-BQ7ZN1r_.js → architectureDiagram-3BPJPVTR-CHkolL_b.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-Debw1Xka.js → blockDiagram-GPEHLZMM-BFRYQi8H.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CiU212s3.js → c4Diagram-AAUBKEIU-D9mMEYbR.js} +1 -1
- package/dist/client/assets/channel-CLdamWm5.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BUJQ86zb.js → chunk-2J33WTMH-CCv6QaQn.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-C6GdEm1z.js → chunk-4BX2VUAB-Bfe22y5T.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CImvrxQL.js → chunk-55IACEB6-CwicrA9V.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-Dt-A3pkM.js → chunk-727SXJPM-DlIpTC03.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DDj4oXTx.js → chunk-AQP2D5EJ-CRX4mFVq.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-BD4r1ukC.js → chunk-FMBD7UC4-DzG-bovU.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-DFSteefi.js → chunk-ND2GUHAM-D5F2jtpM.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-t2zF8tjB.js → chunk-QZHKN3VN-BmSaCwG6.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BYWknNX0.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BYWknNX0.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-tkvDkXQA.js → cose-bilkent-S5V4N54A-BbKTljui.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-DD2rW7wo.js → dagre-BM42HDAG-u0hwXb_T.js} +1 -1
- package/dist/client/assets/{dashboard-view-B1vduc8x.js → dashboard-view-BfYZZ9Ms.js} +1 -1
- package/dist/client/assets/{dashboard-view-DruCruAc.js → dashboard-view-BjPZG2Fv.js} +1 -1
- package/dist/client/assets/{dashboard-view-CciuDS5A.js → dashboard-view-faKSXA4_.js} +1 -1
- package/dist/client/assets/{dashboard-view-C7jJ1lA4.js → dashboard-view-oCjWDGbW.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DASuxGNc.js → diagram-2AECGRRQ-Q7towbBl.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-f9WtiIUk.js → diagram-5GNKFQAL-UAwBmAxb.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-QivICYCd.js → diagram-KO2AKTUF-BL1n0pkf.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CMwcDFHR.js → diagram-LMA3HP47-O-v_IZUJ.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-C-vPMeHZ.js → diagram-OG6HWLK6-CAYSE2Mz.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CxGtk9vj.js → erDiagram-TEJ5UH35-Cr_DgCyp.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-qBZRZoV1.js → flowDiagram-I6XJVG4X-TdLzHKPW.js} +1 -1
- package/dist/client/assets/{folder-open-Dysi9Zzg.js → folder-open-BoddkTkv.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DAaXroiu.js → ganttDiagram-6RSMTGT7-CO1ErtJY.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DNUNQot_.js → gitGraphDiagram-PVQCEYII-C8_Kx0Yh.js} +1 -1
- package/dist/client/assets/index-C7KY0q8Q.js +2767 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BSJmWLwh.js → infoDiagram-5YYISTIA-Dd6Zo7Dh.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-AyVKvoDq.js → ishikawaDiagram-YF4QCWOH-BE9JCLb5.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-972txzzd.js → journeyDiagram-JHISSGLW-B6RIZGDq.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-1xiNvIqK.js → kanban-definition-UN3LZRKU-CPXff-h-.js} +1 -1
- package/dist/client/assets/{mermaid.core-oeDA8jOm.js → mermaid.core-CbGj7iEw.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DcktmI8s.js → mindmap-definition-RKZ34NQL-DF5LZmsH.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-ekBwLt-O.js → pieDiagram-4H26LBE5-Dpy0Xm9T.js} +1 -1
- package/dist/client/assets/{puzzle-I6pr6ZrW.js → puzzle-BZa4U8-N.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-D_wjTsvn.js → quadrantDiagram-W4KKPZXB-BTLAQFpz.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-CKGHyiJ1.js → requirementDiagram-4Y6WPE33-DSUV9ySs.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CtiZFNk5.js → sankeyDiagram-5OEKKPKP-Fmfn0XDL.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B6OMrfGk.js → sequenceDiagram-3UESZ5HK-_343I_b4.js} +1 -1
- package/dist/client/assets/{shield-alert-CVMmviMG.js → shield-alert-CdJ55UvI.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-Cg1a3tjW.js → standing-instructions-template-r03dZ5Z0.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CyTY2M_7.js → stateDiagram-AJRCARHV-C9EbWegm.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-NWPCCiqC.js → stateDiagram-v2-BHNVJYJU-Bmh2GRh6.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DU4TVYpw.js → timeline-definition-PNZ67QCA-q86S9wyl.js} +1 -1
- package/dist/client/assets/{upload-VCzeCiFH.js → upload-DS9-qtCF.js} +1 -1
- package/dist/client/assets/{users-DB3knZtm.js → users-DP5Sngeg.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DX0Ppll6.js → vennDiagram-CIIHVFJN-BFq8uIt3.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-CBoWxpDv.js → wardley-L42UT6IY-BL_sLGYI.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-B_eVqdhC.js → wardleyDiagram-YWT4CUSO-BEKJJ9Vi.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DeZzEX0f.js → xychartDiagram-2RQKCTM6-DsvFnlxK.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +186 -62
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +157 -140
- 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/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
|
@@ -10046,6 +10046,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10046
10046
|
);
|
|
10047
10047
|
}
|
|
10048
10048
|
for (const inner of templateNodes) {
|
|
10049
|
+
validateReviewKind(inner, "nested");
|
|
10049
10050
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10050
10051
|
throw new WorkflowIrError(
|
|
10051
10052
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10164,6 +10165,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10164
10165
|
);
|
|
10165
10166
|
}
|
|
10166
10167
|
for (const inner of templateNodes) {
|
|
10168
|
+
validateReviewKind(inner, "nested");
|
|
10167
10169
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10168
10170
|
throw new WorkflowIrError(
|
|
10169
10171
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10257,6 +10259,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10257
10259
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10258
10260
|
}
|
|
10259
10261
|
for (const inner of templateNodes) {
|
|
10262
|
+
validateReviewKind(inner, "nested");
|
|
10260
10263
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10261
10264
|
throw new WorkflowIrError(
|
|
10262
10265
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -10928,6 +10931,19 @@ function validateColumnRecovery(column) {
|
|
|
10928
10931
|
);
|
|
10929
10932
|
}
|
|
10930
10933
|
}
|
|
10934
|
+
function validateReviewKind(node, placement) {
|
|
10935
|
+
const value = node.config?.reviewKind;
|
|
10936
|
+
if (value === void 0) return;
|
|
10937
|
+
if (value !== "plan" && value !== "code") {
|
|
10938
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
10939
|
+
}
|
|
10940
|
+
if (placement === "nested") {
|
|
10941
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
10942
|
+
}
|
|
10943
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
10944
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
10945
|
+
}
|
|
10946
|
+
}
|
|
10931
10947
|
function validateV2(ir2) {
|
|
10932
10948
|
validateColumns(ir2);
|
|
10933
10949
|
for (const [index2, column] of ir2.columns.entries()) {
|
|
@@ -10950,6 +10966,7 @@ function validateV2(ir2) {
|
|
|
10950
10966
|
}
|
|
10951
10967
|
const nodesById = new Map(ir2.nodes.map((n) => [n.id, n]));
|
|
10952
10968
|
for (const node of ir2.nodes) {
|
|
10969
|
+
validateReviewKind(node, "top-level");
|
|
10953
10970
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
10954
10971
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
10955
10972
|
throw new WorkflowIrError(
|
|
@@ -13413,6 +13430,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13413
13430
|
column,
|
|
13414
13431
|
config: {
|
|
13415
13432
|
name: CODE_REVIEW_NAME,
|
|
13433
|
+
reviewKind: "code",
|
|
13416
13434
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13417
13435
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13418
13436
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13558,6 +13576,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13558
13576
|
...column ? { column } : {},
|
|
13559
13577
|
config: {
|
|
13560
13578
|
name: PLAN_REVIEW_NAME,
|
|
13579
|
+
reviewKind: "plan",
|
|
13561
13580
|
defaultOn: options.defaultOn ?? true,
|
|
13562
13581
|
/*
|
|
13563
13582
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -127158,6 +127177,36 @@ var init_async_knowledge = __esm({
|
|
|
127158
127177
|
});
|
|
127159
127178
|
|
|
127160
127179
|
// ../core/src/workflows/workflow-step-results.ts
|
|
127180
|
+
function normalizeWorkflowReviewFindings(raw) {
|
|
127181
|
+
if (!Array.isArray(raw)) return void 0;
|
|
127182
|
+
const normalized = [];
|
|
127183
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
127184
|
+
for (const candidate of raw) {
|
|
127185
|
+
if (normalized.length >= MAX_WORKFLOW_REVIEW_FINDINGS || !candidate || typeof candidate !== "object") continue;
|
|
127186
|
+
const value = candidate;
|
|
127187
|
+
const title = boundedTrimmedString(value.title, MAX_FINDING_TITLE_LENGTH);
|
|
127188
|
+
const body = boundedTrimmedString(value.body, MAX_FINDING_BODY_LENGTH);
|
|
127189
|
+
if (!title || !body) continue;
|
|
127190
|
+
const baseId = boundedTrimmedString(value.id, MAX_FINDING_ID_LENGTH) || `finding-${normalized.length + 1}`;
|
|
127191
|
+
let id = baseId;
|
|
127192
|
+
let suffix = 2;
|
|
127193
|
+
while (usedIds.has(id)) id = `${baseId.slice(0, Math.max(1, MAX_FINDING_ID_LENGTH - String(suffix).length - 1))}-${suffix++}`;
|
|
127194
|
+
usedIds.add(id);
|
|
127195
|
+
const filePath = boundedTrimmedString(value.filePath, MAX_FINDING_PATH_LENGTH);
|
|
127196
|
+
const line2 = typeof value.line === "number" && Number.isFinite(value.line) && value.line > 0 ? Math.floor(value.line) : void 0;
|
|
127197
|
+
const severity = isWorkflowReviewFindingSeverity(value.severity) ? value.severity : void 0;
|
|
127198
|
+
normalized.push({ id, title, body, ...filePath ? { filePath } : {}, ...line2 ? { line: line2 } : {}, ...severity ? { severity } : {} });
|
|
127199
|
+
}
|
|
127200
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
127201
|
+
}
|
|
127202
|
+
function boundedTrimmedString(value, maxLength) {
|
|
127203
|
+
if (typeof value !== "string") return void 0;
|
|
127204
|
+
const trimmed = value.trim();
|
|
127205
|
+
return trimmed && trimmed.length <= maxLength ? trimmed : void 0;
|
|
127206
|
+
}
|
|
127207
|
+
function isWorkflowReviewFindingSeverity(value) {
|
|
127208
|
+
return typeof value === "string" && WORKFLOW_REVIEW_FINDING_SEVERITIES.includes(value);
|
|
127209
|
+
}
|
|
127161
127210
|
function isTerminalFailure(result) {
|
|
127162
127211
|
return TERMINAL_FAILURE_STATUSES.has(result.status);
|
|
127163
127212
|
}
|
|
@@ -127223,10 +127272,16 @@ function makeReviewLeaseRecord(args) {
|
|
|
127223
127272
|
leaseOwner: args.owner
|
|
127224
127273
|
};
|
|
127225
127274
|
}
|
|
127226
|
-
var MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS, TERMINAL_FAILURE_STATUSES, PLAN_REVIEW_LEASE_STALENESS_MS, TERMINAL_STEP_STATUSES;
|
|
127275
|
+
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;
|
|
127227
127276
|
var init_workflow_step_results = __esm({
|
|
127228
127277
|
"../core/src/workflows/workflow-step-results.ts"() {
|
|
127229
127278
|
"use strict";
|
|
127279
|
+
WORKFLOW_REVIEW_FINDING_SEVERITIES = ["low", "medium", "high", "critical"];
|
|
127280
|
+
MAX_WORKFLOW_REVIEW_FINDINGS = 20;
|
|
127281
|
+
MAX_FINDING_ID_LENGTH = 128;
|
|
127282
|
+
MAX_FINDING_TITLE_LENGTH = 240;
|
|
127283
|
+
MAX_FINDING_BODY_LENGTH = 4e3;
|
|
127284
|
+
MAX_FINDING_PATH_LENGTH = 1e3;
|
|
127230
127285
|
MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS = 5;
|
|
127231
127286
|
TERMINAL_FAILURE_STATUSES = /* @__PURE__ */ new Set([
|
|
127232
127287
|
"failed",
|
|
@@ -127713,6 +127768,7 @@ __export(src_exports, {
|
|
|
127713
127768
|
MAX_TITLE_LENGTH: () => MAX_TITLE_LENGTH,
|
|
127714
127769
|
MAX_TITLE_SUMMARIZE_INPUT_LENGTH: () => MAX_TITLE_SUMMARIZE_INPUT_LENGTH,
|
|
127715
127770
|
MAX_WORKFLOW_ICON_LENGTH: () => MAX_WORKFLOW_ICON_LENGTH,
|
|
127771
|
+
MAX_WORKFLOW_REVIEW_FINDINGS: () => MAX_WORKFLOW_REVIEW_FINDINGS,
|
|
127716
127772
|
MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS: () => MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS,
|
|
127717
127773
|
MEMORY_AUDIT_PATH: () => MEMORY_AUDIT_PATH,
|
|
127718
127774
|
MEMORY_BACKEND_SETTINGS_KEYS: () => MEMORY_BACKEND_SETTINGS_KEYS,
|
|
@@ -127914,6 +127970,7 @@ __export(src_exports, {
|
|
|
127914
127970
|
WAKE_DELTA_ASSIGNED_TASKS_CAP: () => WAKE_DELTA_ASSIGNED_TASKS_CAP,
|
|
127915
127971
|
WEDGE_RENOTIFY_COOLDOWN_MS: () => WEDGE_RENOTIFY_COOLDOWN_MS,
|
|
127916
127972
|
WORKFLOW_EXTENSION_SCHEMA_VERSION: () => WORKFLOW_EXTENSION_SCHEMA_VERSION,
|
|
127973
|
+
WORKFLOW_REVIEW_FINDING_SEVERITIES: () => WORKFLOW_REVIEW_FINDING_SEVERITIES,
|
|
127917
127974
|
WORKFLOW_SETTING_REJECTION_CODES: () => WORKFLOW_SETTING_REJECTION_CODES,
|
|
127918
127975
|
WORKFLOW_SETTING_TYPES: () => WORKFLOW_SETTING_TYPES,
|
|
127919
127976
|
WORKFLOW_WORK_ITEM_KINDS: () => WORKFLOW_WORK_ITEM_KINDS,
|
|
@@ -128441,6 +128498,7 @@ __export(src_exports, {
|
|
|
128441
128498
|
isWipColumn: () => isWipColumn,
|
|
128442
128499
|
isWipColumnRole: () => isWipColumnRole,
|
|
128443
128500
|
isWorkflowOptionalGroupEnabled: () => isWorkflowOptionalGroupEnabled,
|
|
128501
|
+
isWorkflowReviewFindingSeverity: () => isWorkflowReviewFindingSeverity,
|
|
128444
128502
|
isWorkspaceTask: () => isWorkspaceTask,
|
|
128445
128503
|
layoutForIr: () => layoutForIr,
|
|
128446
128504
|
listActiveAiSessions: () => listActiveAiSessions,
|
|
@@ -128514,6 +128572,7 @@ __export(src_exports, {
|
|
|
128514
128572
|
normalizeValidationDiagnostics: () => normalizeValidationDiagnostics,
|
|
128515
128573
|
normalizeWorkflowIcon: () => normalizeWorkflowIcon,
|
|
128516
128574
|
normalizeWorkflowPromptOverrides: () => normalizeWorkflowPromptOverrides,
|
|
128575
|
+
normalizeWorkflowReviewFindings: () => normalizeWorkflowReviewFindings,
|
|
128517
128576
|
notifyOperatorOfNonOperatorDelete: () => notifyOperatorOfNonOperatorDelete,
|
|
128518
128577
|
overseerAdviceSeverityRank: () => overseerAdviceSeverityRank,
|
|
128519
128578
|
parseAgentManifest: () => parseAgentManifest,
|
|
@@ -164660,37 +164719,6 @@ var init_code_node_runner = __esm({
|
|
|
164660
164719
|
}
|
|
164661
164720
|
});
|
|
164662
164721
|
|
|
164663
|
-
// ../engine/src/errors/transient-merge-error-classifier.ts
|
|
164664
|
-
function classifyTransientMergeError(error2) {
|
|
164665
|
-
if (!error2) return null;
|
|
164666
|
-
if (/lease-handoff-failed[^a-z]+target-not-queued/i.test(error2)) {
|
|
164667
|
-
return "lease-handoff-target-not-queued";
|
|
164668
|
-
}
|
|
164669
|
-
if (/\bACP turn failed\b/i.test(error2) || /\bacp rpc code -32(?:603|00[0-3])\b/i.test(error2)) {
|
|
164670
|
-
return "ai-provider-turn-failure";
|
|
164671
|
-
}
|
|
164672
|
-
if (/\bspawn(?:\s+\S+)?\s+ENO(?:TDIR|ENT)\b/i.test(error2)) {
|
|
164673
|
-
return "process-spawn-failure";
|
|
164674
|
-
}
|
|
164675
|
-
if (/\bis not a working tree\b/i.test(error2)) {
|
|
164676
|
-
return "process-spawn-failure";
|
|
164677
|
-
}
|
|
164678
|
-
const sameSha = error2.match(/advanced concurrently \(expected ([0-9a-f]{7,40}),\s+observed ([0-9a-f]{7,40})\)/i);
|
|
164679
|
-
if (sameSha && sameSha[1].toLowerCase() === sameSha[2].toLowerCase()) {
|
|
164680
|
-
return "spurious-concurrent-advance-same-sha";
|
|
164681
|
-
}
|
|
164682
|
-
if (isTransientError(error2)) {
|
|
164683
|
-
return "network-transport-failure";
|
|
164684
|
-
}
|
|
164685
|
-
return null;
|
|
164686
|
-
}
|
|
164687
|
-
var init_transient_merge_error_classifier = __esm({
|
|
164688
|
-
"../engine/src/errors/transient-merge-error-classifier.ts"() {
|
|
164689
|
-
"use strict";
|
|
164690
|
-
init_transient_error_patterns();
|
|
164691
|
-
}
|
|
164692
|
-
});
|
|
164693
|
-
|
|
164694
164722
|
// ../engine/src/notification/ntfy-provider.ts
|
|
164695
164723
|
function resolveParticipantLabel(metadata, kind) {
|
|
164696
164724
|
const nameKey = kind === "from" ? "fromName" : "toName";
|
|
@@ -165164,7 +165192,50 @@ var init_webhook_provider = __esm({
|
|
|
165164
165192
|
}
|
|
165165
165193
|
});
|
|
165166
165194
|
|
|
165195
|
+
// ../engine/src/errors/transient-merge-error-classifier.ts
|
|
165196
|
+
function classifyTransientMergeError(error2) {
|
|
165197
|
+
if (!error2) return null;
|
|
165198
|
+
if (/lease-handoff-failed[^a-z]+target-not-queued/i.test(error2)) {
|
|
165199
|
+
return "lease-handoff-target-not-queued";
|
|
165200
|
+
}
|
|
165201
|
+
if (/\bACP turn failed\b/i.test(error2) || /\bacp rpc code -32(?:603|00[0-3])\b/i.test(error2)) {
|
|
165202
|
+
return "ai-provider-turn-failure";
|
|
165203
|
+
}
|
|
165204
|
+
if (/\bspawn(?:\s+\S+)?\s+ENO(?:TDIR|ENT)\b/i.test(error2)) {
|
|
165205
|
+
return "process-spawn-failure";
|
|
165206
|
+
}
|
|
165207
|
+
if (/\bis not a working tree\b/i.test(error2)) {
|
|
165208
|
+
return "process-spawn-failure";
|
|
165209
|
+
}
|
|
165210
|
+
const sameSha = error2.match(/advanced concurrently \(expected ([0-9a-f]{7,40}),\s+observed ([0-9a-f]{7,40})\)/i);
|
|
165211
|
+
if (sameSha && sameSha[1].toLowerCase() === sameSha[2].toLowerCase()) {
|
|
165212
|
+
return "spurious-concurrent-advance-same-sha";
|
|
165213
|
+
}
|
|
165214
|
+
if (isTransientError(error2)) {
|
|
165215
|
+
return "network-transport-failure";
|
|
165216
|
+
}
|
|
165217
|
+
return null;
|
|
165218
|
+
}
|
|
165219
|
+
function hasTransientMergeRecoveryOwner(task) {
|
|
165220
|
+
return classifyTransientMergeError(task.error) !== null && typeof task.mergeTransientRetryCount === "number" && Number.isInteger(task.mergeTransientRetryCount) && task.mergeTransientRetryCount >= 0 && task.mergeTransientRetryCount < MAX_AUTO_MERGE_TRANSIENT_RETRIES;
|
|
165221
|
+
}
|
|
165222
|
+
var MAX_AUTO_MERGE_TRANSIENT_RETRIES;
|
|
165223
|
+
var init_transient_merge_error_classifier = __esm({
|
|
165224
|
+
"../engine/src/errors/transient-merge-error-classifier.ts"() {
|
|
165225
|
+
"use strict";
|
|
165226
|
+
init_transient_error_patterns();
|
|
165227
|
+
MAX_AUTO_MERGE_TRANSIENT_RETRIES = 5;
|
|
165228
|
+
}
|
|
165229
|
+
});
|
|
165230
|
+
|
|
165167
165231
|
// ../engine/src/notification/task-wedge-notification.ts
|
|
165232
|
+
function describeTaskRecoveryOwner(task) {
|
|
165233
|
+
if (hasTransientMergeRecoveryOwner(task)) return { kind: "transient-merge-retry" };
|
|
165234
|
+
if (typeof task.recoveryRetryCount === "number" && Number.isInteger(task.recoveryRetryCount) && task.recoveryRetryCount >= 0 && typeof task.nextRecoveryAt === "string" && Number.isFinite(Date.parse(task.nextRecoveryAt))) {
|
|
165235
|
+
return { kind: "scheduled-recovery" };
|
|
165236
|
+
}
|
|
165237
|
+
return null;
|
|
165238
|
+
}
|
|
165168
165239
|
function describeSelfHealingNoActionWedge(task, stage, metadata) {
|
|
165169
165240
|
const description = SELF_HEALING_NO_ACTIONS[stage];
|
|
165170
165241
|
if (!description || task.userPaused || task.paused || task.autoMerge === false) return null;
|
|
@@ -165222,6 +165293,7 @@ function describeTaskWedge(task) {
|
|
|
165222
165293
|
if (/merge.*(?:blocked|verification|gate)|(?:verification|gate).*(?:failed|exhaust)/i.test(error2)) {
|
|
165223
165294
|
return { reasonKey: "merge-blocked", reason: "Merge verification cannot progress without operator action.", action: "Fix the failing verification, then retry the task." };
|
|
165224
165295
|
}
|
|
165296
|
+
if (describeTaskRecoveryOwner(task)) return null;
|
|
165225
165297
|
if (!error2 && (task.mergeRetries ?? 0) < 3) return null;
|
|
165226
165298
|
return {
|
|
165227
165299
|
reasonKey: "terminal-failed",
|
|
@@ -165233,6 +165305,7 @@ var SELF_HEALING_NO_ACTIONS;
|
|
|
165233
165305
|
var init_task_wedge_notification = __esm({
|
|
165234
165306
|
"../engine/src/notification/task-wedge-notification.ts"() {
|
|
165235
165307
|
"use strict";
|
|
165308
|
+
init_transient_merge_error_classifier();
|
|
165236
165309
|
SELF_HEALING_NO_ACTIONS = {
|
|
165237
165310
|
"reclaim-pr-conflict": {
|
|
165238
165311
|
reason: "Self-healing could not reclaim a stalled pull-request conflict.",
|
|
@@ -165298,7 +165371,6 @@ var init_notification_service = __esm({
|
|
|
165298
165371
|
init_src2();
|
|
165299
165372
|
init_notifier();
|
|
165300
165373
|
init_logger();
|
|
165301
|
-
init_transient_merge_error_classifier();
|
|
165302
165374
|
init_ntfy_provider();
|
|
165303
165375
|
init_webhook_provider();
|
|
165304
165376
|
init_task_wedge_notification();
|
|
@@ -165524,10 +165596,10 @@ var init_notification_service = __esm({
|
|
|
165524
165596
|
}
|
|
165525
165597
|
}
|
|
165526
165598
|
handleTaskUpdated = (task, meta2) => {
|
|
165527
|
-
const
|
|
165528
|
-
const wedge =
|
|
165599
|
+
const recoveryOwner = task.status === "failed" ? describeTaskRecoveryOwner(task) : null;
|
|
165600
|
+
const wedge = describeTaskWedge(task);
|
|
165529
165601
|
if (wedge) this.cancelPendingFailureNotification(task.id, "classified-terminal-wedge");
|
|
165530
|
-
|
|
165602
|
+
void this.enqueueWedgeHandling(task.id, () => this.maybeNotifyTaskWedge(task, wedge));
|
|
165531
165603
|
void this.maybeSuppressTransientFailedNotification(task, `status=${task.status ?? "undefined"}`);
|
|
165532
165604
|
if (task.status === "awaiting-approval") {
|
|
165533
165605
|
void this.writeAwaitingApprovalMailboxMessage(task);
|
|
@@ -165538,17 +165610,12 @@ var init_notification_service = __esm({
|
|
|
165538
165610
|
if (!this.notificationsEnabled) {
|
|
165539
165611
|
return;
|
|
165540
165612
|
}
|
|
165541
|
-
if (task.status === "failed" &&
|
|
165542
|
-
|
|
165543
|
-
|
|
165544
|
-
|
|
165545
|
-
schedulerLog.debug(
|
|
165546
|
-
`[notify] ${task.id} transient merge failure (${transientClass}) \u2014 suppressed notification (self-heal in flight)`
|
|
165547
|
-
);
|
|
165548
|
-
return;
|
|
165549
|
-
}
|
|
165613
|
+
if (task.status === "failed" && recoveryOwner) {
|
|
165614
|
+
this.failureNotificationSuppressedCount += 1;
|
|
165615
|
+
schedulerLog.debug(`[notify] ${task.id} recovery-owned failure \u2014 suppressed notification`);
|
|
165616
|
+
} else if (task.status === "failed" && !wedge) {
|
|
165550
165617
|
if (this.failureNotificationMode === "all") {
|
|
165551
|
-
|
|
165618
|
+
void this.maybeNotifyImmediateFailure(task);
|
|
165552
165619
|
} else {
|
|
165553
165620
|
this.scheduleFailureNotification(task);
|
|
165554
165621
|
}
|
|
@@ -165635,7 +165702,17 @@ var init_notification_service = __esm({
|
|
|
165635
165702
|
await this.enqueueWedgeHandling(task.id, () => this.maybeNotifyTaskWedge(task, descriptor));
|
|
165636
165703
|
}
|
|
165637
165704
|
async maybeNotifyTaskWedge(task, suppliedDescriptor) {
|
|
165638
|
-
const
|
|
165705
|
+
const liveTask = this.store.getTask ? await this.store.getTask(task.id) ?? task : task;
|
|
165706
|
+
const recoveryOwner = describeTaskRecoveryOwner(liveTask);
|
|
165707
|
+
if (recoveryOwner) {
|
|
165708
|
+
if (this.activeWedgeReasons.has(task.id) || liveTask.wedgeNotification?.status === "active") {
|
|
165709
|
+
this.activeWedgeReasons.delete(task.id);
|
|
165710
|
+
await this.store.claimTaskWedgeNotificationEpisode?.(task.id, null);
|
|
165711
|
+
}
|
|
165712
|
+
return;
|
|
165713
|
+
}
|
|
165714
|
+
const descriptor = suppliedDescriptor ?? describeTaskWedge(liveTask);
|
|
165715
|
+
task = liveTask;
|
|
165639
165716
|
let episode;
|
|
165640
165717
|
if (!descriptor) {
|
|
165641
165718
|
const isActiveSelfHealingNoAction = task.wedgeNotification?.status === "active" && task.wedgeNotification.reasonKey.startsWith("self-healing-no-action:");
|
|
@@ -166002,6 +166079,14 @@ var init_notification_service = __esm({
|
|
|
166002
166079
|
this.failureNotificationDelayMs = typeof settings.failureNotificationDelayMs === "number" && settings.failureNotificationDelayMs >= 0 ? settings.failureNotificationDelayMs : this.failedNotificationGraceMs;
|
|
166003
166080
|
this.failureNotificationMode = settings.failureNotificationMode ?? "sticky-only";
|
|
166004
166081
|
}
|
|
166082
|
+
async maybeNotifyImmediateFailure(task) {
|
|
166083
|
+
const liveTask = this.store.getTask ? await this.store.getTask(task.id) ?? task : task;
|
|
166084
|
+
if (liveTask.status !== "failed" || describeTaskRecoveryOwner(liveTask) || describeTaskWedge(liveTask)) {
|
|
166085
|
+
this.failureNotificationSuppressedCount += 1;
|
|
166086
|
+
return;
|
|
166087
|
+
}
|
|
166088
|
+
this.maybeNotify(liveTask.id, "failed", this.createTaskPayload(liveTask, "failed"));
|
|
166089
|
+
}
|
|
166005
166090
|
scheduleFailureNotification(task) {
|
|
166006
166091
|
if (this.pendingFailureNotifications.has(task.id)) {
|
|
166007
166092
|
return;
|
|
@@ -166058,12 +166143,9 @@ var init_notification_service = __esm({
|
|
|
166058
166143
|
schedulerLog.debug(`[notify] ${taskId} no longer failed at dispatch time \u2014 suppressed notification`);
|
|
166059
166144
|
return;
|
|
166060
166145
|
}
|
|
166061
|
-
|
|
166062
|
-
if (transientClassAtDispatch) {
|
|
166146
|
+
if (describeTaskRecoveryOwner(task)) {
|
|
166063
166147
|
this.failureNotificationSuppressedCount += 1;
|
|
166064
|
-
schedulerLog.debug(
|
|
166065
|
-
`[notify] ${taskId} transient merge failure (${transientClassAtDispatch}) at dispatch time \u2014 suppressed notification (self-heal in flight)`
|
|
166066
|
-
);
|
|
166148
|
+
schedulerLog.debug(`[notify] ${taskId} recovery-owned failure at dispatch time \u2014 suppressed notification`);
|
|
166067
166149
|
return;
|
|
166068
166150
|
}
|
|
166069
166151
|
if (describeTaskWedge(task)) {
|
|
@@ -192043,10 +192125,21 @@ var Scheduler = class {
|
|
|
192043
192125
|
const unmetDeps = getUnmetSchedulingDependencies(task, tasks2, schedulingDependencyOptions);
|
|
192044
192126
|
if (unmetDeps.length > 0) {
|
|
192045
192127
|
const normalizedUnmetDeps = [...new Set(unmetDeps)].sort();
|
|
192128
|
+
let activeOverlapBlockedBy = null;
|
|
192129
|
+
if (activeScopes.size > 0) {
|
|
192130
|
+
try {
|
|
192131
|
+
const taskScope = await getFilteredFileScope(task.id);
|
|
192132
|
+
if (taskScope.length > 0 && !isCoordinationOnlyTask(task, taskScope)) {
|
|
192133
|
+
activeOverlapBlockedBy = Array.from(activeScopes.entries()).sort(([aId], [bId]) => aId.localeCompare(bId)).find(([, activeScope]) => this.pathsOverlap(taskScope, activeScope))?.[0] ?? null;
|
|
192134
|
+
}
|
|
192135
|
+
} catch (error2) {
|
|
192136
|
+
schedulerLog.warn(`Failed to refresh file-scope overlap blocker for dependency-blocked task ${task.id}`, error2);
|
|
192137
|
+
}
|
|
192138
|
+
}
|
|
192046
192139
|
await this.transitionQueuedEpisode(task, {
|
|
192047
192140
|
signature: `dependency:${normalizedUnmetDeps.join(",")}`,
|
|
192048
192141
|
blockedBy: unmetDeps[0] ?? null,
|
|
192049
|
-
overlapBlockedBy:
|
|
192142
|
+
overlapBlockedBy: activeOverlapBlockedBy,
|
|
192050
192143
|
action: `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`
|
|
192051
192144
|
});
|
|
192052
192145
|
this.options.onBlocked?.(task, unmetDeps);
|
|
@@ -194569,6 +194662,7 @@ var SESSION_CONTENTION_HOLD_VALUE = "session-contention-hold";
|
|
|
194569
194662
|
var WORKFLOW_INTERRUPTED_NODE_ID_CONTEXT_KEY = "workflow:interruptedNodeId";
|
|
194570
194663
|
var WORKFLOW_INTERRUPTED_NODE_ABORT_KIND_CONTEXT_KEY = "workflow:interruptedNodeAbortKind";
|
|
194571
194664
|
var WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY = "workflow:optionalGroupActive";
|
|
194665
|
+
var WORKFLOW_REVIEW_KIND_CONTEXT_KEY = "workflow:reviewKind";
|
|
194572
194666
|
var WORKFLOW_NODE_ENGINE_PAUSE_ABORT_KIND = "engine-pause";
|
|
194573
194667
|
var WORKFLOW_DRIFT_PARK_CONTEXT_KEY = "workflow:driftPark";
|
|
194574
194668
|
var WorkflowGraphSuspended = class extends Error {
|
|
@@ -194893,6 +194987,7 @@ var WorkflowGraphExecutor = class {
|
|
|
194893
194987
|
phase: stepPhase,
|
|
194894
194988
|
status: "pending",
|
|
194895
194989
|
source: "optional-group",
|
|
194990
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
194896
194991
|
startedAt: stepStartedAt,
|
|
194897
194992
|
// U3/KTD-4: stamp the lease owner so a concurrent/crashed re-entry
|
|
194898
194993
|
// adopts this pending gate instead of dispatching a second reviewer.
|
|
@@ -194912,7 +195007,8 @@ var WorkflowGraphExecutor = class {
|
|
|
194912
195007
|
runTemplateNode: (tNode, sig, contextOverride) => {
|
|
194913
195008
|
const optionalGroupContext = {
|
|
194914
195009
|
...contextOverride ?? context,
|
|
194915
|
-
[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY]: node.id
|
|
195010
|
+
[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY]: node.id,
|
|
195011
|
+
...this.workflowReviewKind(node) ? { [WORKFLOW_REVIEW_KIND_CONTEXT_KEY]: this.workflowReviewKind(node) } : {}
|
|
194916
195012
|
};
|
|
194917
195013
|
return this.executeNodeWithRetries(tNode, task, settings, optionalGroupContext, ir2, sig, false);
|
|
194918
195014
|
},
|
|
@@ -194930,6 +195026,7 @@ var WorkflowGraphExecutor = class {
|
|
|
194930
195026
|
const exitContextPatch = exitResult?.contextPatch;
|
|
194931
195027
|
let stepOutput = typeof exitContextPatch?.output === "string" ? exitContextPatch.output : void 0;
|
|
194932
195028
|
const stepNotes = typeof exitContextPatch?.notes === "string" ? exitContextPatch.notes : void 0;
|
|
195029
|
+
const stepFindings = this.workflowReviewKind(node) && Array.isArray(exitContextPatch?.findings) ? exitContextPatch.findings : void 0;
|
|
194933
195030
|
if (stepStatus === "failed" && !verdict && stepOutput === void 0 && stepNotes === void 0) {
|
|
194934
195031
|
const lastVisited = groupResult.visitedNodeIds[groupResult.visitedNodeIds.length - 1];
|
|
194935
195032
|
const templateNodeId = lastVisited?.includes("::") ? lastVisited.slice(lastVisited.indexOf("::") + 2) : void 0;
|
|
@@ -194947,9 +195044,11 @@ var WorkflowGraphExecutor = class {
|
|
|
194947
195044
|
phase: stepPhase,
|
|
194948
195045
|
source: "optional-group",
|
|
194949
195046
|
status: stepStatus,
|
|
195047
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
194950
195048
|
...verdict ? { verdict } : {},
|
|
194951
195049
|
...stepOutput !== void 0 ? { output: stepOutput } : {},
|
|
194952
195050
|
...stepNotes !== void 0 ? { notes: stepNotes } : {},
|
|
195051
|
+
...stepFindings?.length ? { findings: stepFindings } : {},
|
|
194953
195052
|
startedAt: stepStartedAt,
|
|
194954
195053
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
194955
195054
|
});
|
|
@@ -195409,9 +195508,15 @@ var WorkflowGraphExecutor = class {
|
|
|
195409
195508
|
}
|
|
195410
195509
|
return failureResult;
|
|
195411
195510
|
}
|
|
195511
|
+
/** FNXC:WorkflowReviewKind 2026-08-05-02:31: Persist only the declared closed
|
|
195512
|
+
* marker; execution never derives review semantics from a label, verdict, or gate mode. */
|
|
195513
|
+
workflowReviewKind(node) {
|
|
195514
|
+
return node.config?.reviewKind === "plan" || node.config?.reviewKind === "code" ? node.config.reviewKind : void 0;
|
|
195515
|
+
}
|
|
195412
195516
|
shouldRecordNodeProgress(node) {
|
|
195413
195517
|
const skillName = typeof node.config?.skillName === "string" ? node.config.skillName.trim() : "";
|
|
195414
|
-
|
|
195518
|
+
const markedReview = this.workflowReviewKind(node) !== void 0;
|
|
195519
|
+
return markedReview && (node.kind === "prompt" || node.kind === "gate" || node.kind === "script") || skillName.length > 0 && (node.kind === "prompt" || node.kind === "gate");
|
|
195415
195520
|
}
|
|
195416
195521
|
workflowNodeProgressName(node) {
|
|
195417
195522
|
const configuredName = typeof node.config?.name === "string" ? node.config.name.trim() : "";
|
|
@@ -195425,6 +195530,7 @@ var WorkflowGraphExecutor = class {
|
|
|
195425
195530
|
phase: node.config?.phase === "post-merge" ? "post-merge" : "pre-merge",
|
|
195426
195531
|
source: "node",
|
|
195427
195532
|
status: "pending",
|
|
195533
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
195428
195534
|
startedAt
|
|
195429
195535
|
};
|
|
195430
195536
|
await this.recordOptionalGroupStepResult(taskId, result);
|
|
@@ -195435,6 +195541,7 @@ var WorkflowGraphExecutor = class {
|
|
|
195435
195541
|
const contextPatch = nodeResult.contextPatch ?? {};
|
|
195436
195542
|
let output = typeof contextPatch.output === "string" ? contextPatch.output : void 0;
|
|
195437
195543
|
const notes = typeof contextPatch.notes === "string" ? contextPatch.notes : void 0;
|
|
195544
|
+
const findings = this.workflowReviewKind(node) && Array.isArray(contextPatch.findings) ? contextPatch.findings : void 0;
|
|
195438
195545
|
if (status === "failed" && output === void 0 && notes === void 0) {
|
|
195439
195546
|
output = this.synthesizeNonVerdictFailureOutput({
|
|
195440
195547
|
stepLabel: this.workflowNodeProgressName(node),
|
|
@@ -195449,8 +195556,10 @@ var WorkflowGraphExecutor = class {
|
|
|
195449
195556
|
phase: started?.phase ?? (node.config?.phase === "post-merge" ? "post-merge" : "pre-merge"),
|
|
195450
195557
|
source: "node",
|
|
195451
195558
|
status,
|
|
195559
|
+
...this.workflowReviewKind(node) ? { reviewKind: this.workflowReviewKind(node) } : {},
|
|
195452
195560
|
...output !== void 0 ? { output } : {},
|
|
195453
195561
|
...notes !== void 0 ? { notes } : {},
|
|
195562
|
+
...findings?.length ? { findings } : {},
|
|
195454
195563
|
startedAt: started?.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
195455
195564
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
195456
195565
|
});
|
|
@@ -219935,9 +220044,11 @@ function parseWorkflowStepVerdict(rawOutput) {
|
|
|
219935
220044
|
verdict = "REVISE";
|
|
219936
220045
|
}
|
|
219937
220046
|
if (!verdict) continue;
|
|
220047
|
+
const findings = normalizeWorkflowReviewFindings(parsed.findings);
|
|
219938
220048
|
return {
|
|
219939
220049
|
verdict,
|
|
219940
|
-
notes: typeof parsed.notes === "string" ? parsed.notes : ""
|
|
220050
|
+
notes: typeof parsed.notes === "string" ? parsed.notes : "",
|
|
220051
|
+
...findings ? { findings } : {}
|
|
219941
220052
|
};
|
|
219942
220053
|
} catch {
|
|
219943
220054
|
}
|
|
@@ -219969,7 +220080,8 @@ function parseWorkflowStepOutput(rawOutput, options = {}) {
|
|
|
219969
220080
|
return {
|
|
219970
220081
|
output: parsed.notes || "",
|
|
219971
220082
|
verdict: parsed.verdict,
|
|
219972
|
-
notes: parsed.notes
|
|
220083
|
+
notes: parsed.notes,
|
|
220084
|
+
...parsed.findings ? { findings: parsed.findings } : {}
|
|
219973
220085
|
};
|
|
219974
220086
|
}
|
|
219975
220087
|
const inferred = inferWorkflowStepVerdictFromProse(trimmed);
|
|
@@ -225794,6 +225906,7 @@ ${info.feedback}`, revisionKey),
|
|
|
225794
225906
|
return this.runCliAgentNode(node, await this.store.getTask(live.id), cfg);
|
|
225795
225907
|
}
|
|
225796
225908
|
const optionalGroupId = typeof graphContext?.[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY] === "string" ? graphContext[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY] : void 0;
|
|
225909
|
+
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;
|
|
225797
225910
|
const isCompletionSummaryNode2 = cfg.summaryTarget === "task" || node.id === "completion-summary";
|
|
225798
225911
|
if (live.executionMode === "fast" && !isCompletionSummaryNode2 && !optionalGroupId && !cfg.seam && (node.kind === "prompt" || node.kind === "script" || node.kind === "gate")) {
|
|
225799
225912
|
executorLog.debug(`${live.id}: fast mode \u2014 skipping custom graph node '${node.id}'`);
|
|
@@ -225942,6 +226055,9 @@ ${prompt}`;
|
|
|
225942
226055
|
if (optionalGroupId) {
|
|
225943
226056
|
step.optionalGroupId = optionalGroupId;
|
|
225944
226057
|
}
|
|
226058
|
+
if (declaredReviewKind) {
|
|
226059
|
+
step.reviewKind = declaredReviewKind;
|
|
226060
|
+
}
|
|
225945
226061
|
if (cfg.reviewCanFixInline === true) {
|
|
225946
226062
|
step.reviewCanFixInline = true;
|
|
225947
226063
|
}
|
|
@@ -225954,7 +226070,11 @@ ${prompt}`;
|
|
|
225954
226070
|
executorLog.debug(`${live.id}: graph node '${node.id}' runtime env injected (${injected.pathEntryCount} PATH entries, ${injected.injectedKeyCount} env keys)`);
|
|
225955
226071
|
}
|
|
225956
226072
|
const unattended = this.graphUnattendedRuns.has(live.id);
|
|
225957
|
-
|
|
226073
|
+
let outcome = mode === "script" ? await this.executeScriptWorkflowStep(live, step, worktreePath, settings, nodeEnv) : await this.executeWorkflowStep(live, step, worktreePath, settings, nodeEnv, { unattended });
|
|
226074
|
+
if (declaredReviewKind && typeof outcome.output === "string") {
|
|
226075
|
+
const parsedReviewOutput = parseWorkflowStepOutput(outcome.output, { requireVerdict: false });
|
|
226076
|
+
if (parsedReviewOutput.findings?.length) outcome = { ...outcome, findings: parsedReviewOutput.findings };
|
|
226077
|
+
}
|
|
225958
226078
|
const awaitQuestion = parseAwaitInputSentinel(outcome.output);
|
|
225959
226079
|
if (awaitQuestion) {
|
|
225960
226080
|
await this.store.logEntry(
|
|
@@ -225977,6 +226097,8 @@ ${prompt}`;
|
|
|
225977
226097
|
const contextPatch = {};
|
|
225978
226098
|
if (typeof stepOutput === "string") contextPatch.output = stepOutput;
|
|
225979
226099
|
if (typeof stepNotes === "string" && stepNotes) contextPatch.notes = stepNotes;
|
|
226100
|
+
const stepFindings = outcome.findings;
|
|
226101
|
+
if (stepFindings?.length) contextPatch.findings = stepFindings;
|
|
225980
226102
|
if (cfg.summaryTarget === "task" && typeof stepOutput === "string" && stepOutput.trim()) {
|
|
225981
226103
|
contextPatch.summary = stepOutput.trim();
|
|
225982
226104
|
}
|
|
@@ -232479,13 +232601,14 @@ CRITICAL SCOPING RULES \u2014 read before doing anything else:
|
|
|
232479
232601
|
const isSkillStep = typeof workflowStep.skillName === "string" && workflowStep.skillName.trim().length > 0;
|
|
232480
232602
|
const isSummaryProjectionStep = workflowStep.summaryTarget === "task";
|
|
232481
232603
|
const requireVerdict = !isSummaryProjectionStep && (workflowStep.gateMode === "gate" || !isSkillStep);
|
|
232604
|
+
const reviewFindingsContract = workflowStepMetadata.reviewKind === "plan" || workflowStepMetadata.reviewKind === "code";
|
|
232482
232605
|
const verdictBlock = requireVerdict ? `
|
|
232483
232606
|
|
|
232484
232607
|
## Feedback Format
|
|
232485
232608
|
|
|
232486
232609
|
When your review is complete, your final line MUST be a single JSON object (no markdown fences):
|
|
232487
232610
|
|
|
232488
|
-
{"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}
|
|
232611
|
+
${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":"..."}'}
|
|
232489
232612
|
|
|
232490
232613
|
Rules:
|
|
232491
232614
|
- Output exactly one trailing JSON object and stop.
|
|
@@ -232795,7 +232918,8 @@ ${detectedQuestion}
|
|
|
232795
232918
|
revisionRequested,
|
|
232796
232919
|
output: parsed.output,
|
|
232797
232920
|
verdict: parsed.verdict,
|
|
232798
|
-
notes: parsed.notes
|
|
232921
|
+
notes: parsed.notes,
|
|
232922
|
+
...parsed.findings ? { findings: parsed.findings } : {}
|
|
232799
232923
|
};
|
|
232800
232924
|
}
|
|
232801
232925
|
if (parsed.malformed) {
|
|
@@ -254982,7 +255106,7 @@ var ProjectEngine = class _ProjectEngine {
|
|
|
254982
255106
|
*
|
|
254983
255107
|
* Readable (not private) so tests derive the cap from this single source of truth rather
|
|
254984
255108
|
* than hardcoding it — the FN-8004 bump broke two suites that had baked in the old `3`. */
|
|
254985
|
-
static MAX_AUTO_MERGE_TRANSIENT_RETRIES =
|
|
255109
|
+
static MAX_AUTO_MERGE_TRANSIENT_RETRIES = MAX_AUTO_MERGE_TRANSIENT_RETRIES;
|
|
254986
255110
|
static MERGE_REQUEST_RETRY_EXHAUSTED_AGE_MS = 30 * 60 * 1e3;
|
|
254987
255111
|
/** Cap on outer in-review→in-progress bounces caused by deterministic
|
|
254988
255112
|
* verification failures during auto-merge. After this many failed merges
|