@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
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|
|
@@ -10539,6 +10539,7 @@ function validateForeach(node, topLevelNodeIds, columnIds) {
|
|
|
10539
10539
|
);
|
|
10540
10540
|
}
|
|
10541
10541
|
for (const inner of templateNodes) {
|
|
10542
|
+
validateReviewKind(inner, "nested");
|
|
10542
10543
|
if (inner.kind === "foreach" || inner.kind === "loop") {
|
|
10543
10544
|
throw new WorkflowIrError(
|
|
10544
10545
|
`foreach node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10657,6 +10658,7 @@ function validateLoop(node, topLevelNodeIds, columnIds) {
|
|
|
10657
10658
|
);
|
|
10658
10659
|
}
|
|
10659
10660
|
for (const inner of templateNodes) {
|
|
10661
|
+
validateReviewKind(inner, "nested");
|
|
10660
10662
|
if (inner.kind === "loop" || inner.kind === "foreach") {
|
|
10661
10663
|
throw new WorkflowIrError(
|
|
10662
10664
|
`loop node '${node.id}' template may not contain nested loop/foreach ('${inner.id}')`
|
|
@@ -10750,6 +10752,7 @@ function validateOptionalGroup(node, topLevelNodeIds, columnIds) {
|
|
|
10750
10752
|
throw new WorkflowIrError(`optional-group node '${node.id}' template has duplicate node ids`);
|
|
10751
10753
|
}
|
|
10752
10754
|
for (const inner of templateNodes) {
|
|
10755
|
+
validateReviewKind(inner, "nested");
|
|
10753
10756
|
if (inner.kind === "loop" || inner.kind === "foreach" || inner.kind === "optional-group") {
|
|
10754
10757
|
throw new WorkflowIrError(
|
|
10755
10758
|
`optional-group node '${node.id}' template may not contain nested loop/foreach/optional-group ('${inner.id}')`
|
|
@@ -11421,6 +11424,19 @@ function validateColumnRecovery(column) {
|
|
|
11421
11424
|
);
|
|
11422
11425
|
}
|
|
11423
11426
|
}
|
|
11427
|
+
function validateReviewKind(node, placement) {
|
|
11428
|
+
const value = node.config?.reviewKind;
|
|
11429
|
+
if (value === void 0) return;
|
|
11430
|
+
if (value !== "plan" && value !== "code") {
|
|
11431
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has invalid reviewKind '${String(value)}'; expected 'plan' or 'code'`);
|
|
11432
|
+
}
|
|
11433
|
+
if (placement === "nested") {
|
|
11434
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind in an unsupported nested template placement`);
|
|
11435
|
+
}
|
|
11436
|
+
if (node.kind !== "prompt" && node.kind !== "gate" && node.kind !== "script" && node.kind !== "optional-group") {
|
|
11437
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' has reviewKind on unsupported node kind '${node.kind}'`);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11424
11440
|
function validateV2(ir) {
|
|
11425
11441
|
validateColumns(ir);
|
|
11426
11442
|
for (const [index2, column] of ir.columns.entries()) {
|
|
@@ -11443,6 +11459,7 @@ function validateV2(ir) {
|
|
|
11443
11459
|
}
|
|
11444
11460
|
const nodesById = new Map(ir.nodes.map((n) => [n.id, n]));
|
|
11445
11461
|
for (const node of ir.nodes) {
|
|
11462
|
+
validateReviewKind(node, "top-level");
|
|
11446
11463
|
validateExtensionMetadata(`Workflow node '${node.id}'`, node.extensions);
|
|
11447
11464
|
if (node.column !== void 0 && !columnIds.has(node.column)) {
|
|
11448
11465
|
throw new WorkflowIrError(
|
|
@@ -13613,6 +13630,7 @@ function codeReviewOptionalGroupNode(column, options = {}) {
|
|
|
13613
13630
|
column,
|
|
13614
13631
|
config: {
|
|
13615
13632
|
name: CODE_REVIEW_NAME,
|
|
13633
|
+
reviewKind: "code",
|
|
13616
13634
|
// Default-ON: runs for every coding task by default, but operators can toggle it
|
|
13617
13635
|
// off per task (remove `code-review` from enabledWorkflowSteps).
|
|
13618
13636
|
defaultOn: options.defaultOn ?? true,
|
|
@@ -13743,6 +13761,7 @@ function planReviewOptionalGroupNode(column, options = {}) {
|
|
|
13743
13761
|
...column ? { column } : {},
|
|
13744
13762
|
config: {
|
|
13745
13763
|
name: PLAN_REVIEW_NAME,
|
|
13764
|
+
reviewKind: "plan",
|
|
13746
13765
|
defaultOn: options.defaultOn ?? true,
|
|
13747
13766
|
/*
|
|
13748
13767
|
* FNXC:WorkflowRemediation 2026-06-29-12:14:
|