@uipath/maestro-builder-sdk 6.46.5 → 6.46.7

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/api-index.md CHANGED
@@ -58,7 +58,7 @@ could hand you spans for a version you do not have.
58
58
  | `apiWorkflow` | function | `dist/nodes/process/flow/factories.d.ts:53-87` | Actions | Invoke a deployed API workflow — a coded workflow published to Orchestrator, run as a serverless job rather than by a… |
59
59
  | `ApiWorkflowInputs` | interface | `dist/nodes/process/flow/spec.d.ts:70-101` | Option shapes | 5 field(s) |
60
60
  | `AppRef` | interface | `dist/nodes/hitl/flow/spec.d.ts:140-185` | Supporting types | A deployed Action App that supplies a human task's form — the `'action-app'` variant's subject. |
61
- | `ArmBuilder` | class | `dist/flow-sdk.d.ts:1358-1381` | Builders | The sub-builder an ARM callback receives — a `StepList` that can also name itself with `.label(...)`. |
61
+ | `ArmBuilder` | class | `dist/flow-sdk.d.ts:1364-1387` | Builders | The sub-builder an ARM callback receives — a `StepList` that can also name itself with `.label(...)`. |
62
62
  | `AskedField` | interface | `dist/core/actions.d.ts:221-240` | Supporting types | A value the reviewer FILLS IN: read downstream with `out('<step>', '<id>')`. |
63
63
  | `at` | function | `dist/flow-sdk.d.ts:693-721` | Flow construction | A node's layout at a canvas position — the short form of a NodeLayout for the `nodes` map of FlowBuilder.layout. |
64
64
  | `batchTransform` | function | `dist/nodes/ai-patterns/flow/factories.d.ts:49-83` | Actions | Add AI-generated columns to a CSV — the platform's **Batch transform** node, `uipath.pattern.batch-transform` (service… |
@@ -133,11 +133,11 @@ could hand you spans for a version you do not have.
133
133
  | `FilterCondition` | type | `dist/nodes/transform/flow/spec.d.ts:10-11` | Supporting types | Comparison a filter rule applies to a field. |
134
134
  | `FilterMatch` | type | `dist/nodes/transform/flow/spec.d.ts:8-9` | Supporting types | How a filter combines its rules: every rule must match, or any one. |
135
135
  | `FilterRule` | interface | `dist/nodes/transform/flow/spec.d.ts:12-24` | Supporting types | 3 field(s) |
136
- | `flow` | function | `dist/flow-sdk.d.ts:1763-1778` | Flow construction | Start building a flow with the given id. |
136
+ | `flow` | function | `dist/flow-sdk.d.ts:1769-1784` | Flow construction | Start building a flow with the given id. |
137
137
  | `FlowAction` | class | `dist/core/node-classes.d.ts:162-168` | Supporting types | A node placed as a step — pass an instance to `.step(name, …)`. |
138
138
  | `FlowActionSpec` | type | `dist/flow-sdk.d.ts:55-56` | Supporting types | What `.step()` accepts here: the shared actions plus this SDK's subflow. |
139
139
  | `FlowActionSpecs` | interface | `dist/core/actions.d.ts:905-942` | Supporting types | Every action kind, keyed by kind, to the body of its spec — the arm's fields other than `kind`. |
140
- | `FlowBuilder` | class | `dist/flow-sdk.d.ts:1382-1762` | Builders | 15 member(s) |
140
+ | `FlowBuilder` | class | `dist/flow-sdk.d.ts:1388-1768` | Builders | 15 member(s) |
141
141
  | `FlowLayout` | interface | `dist/flow-sdk.d.ts:807-820` | Supporting types | Designer layout for a flow, keyed by AUTHOR-level ids: node entries by step name (plus the trigger id and `end`), edge… |
142
142
  | `FlowNode` | class | `dist/core/node-classes.d.ts:126-161` | Supporting types | The abstract root of every definition-backed node the builder can place. |
143
143
  | `FlowResource` | class | `dist/core/node-classes.d.ts:176-183` | Supporting types | A node attached to another semantic node — an inline agent's tool, context, memory, or escalation. |
@@ -237,11 +237,11 @@ could hand you spans for a version you do not have.
237
237
  | `SendMessageInputs` | interface | `dist/nodes/conversation/flow/spec.d.ts:8-27` | Option shapes | 4 field(s) |
238
238
  | `ShownField` | interface | `dist/core/actions.d.ts:205-220` | Supporting types | A value the reviewer READS: shown on the form, filled in from the flow. |
239
239
  | `Step` | type | `dist/flow-sdk.d.ts:557-677` | Supporting types | |
240
- | `StepList` | class | `dist/flow-sdk.d.ts:882-1357` | Builders | Collects a sequence of steps. |
240
+ | `StepList` | class | `dist/flow-sdk.d.ts:882-1363` | Builders | Collects a sequence of steps. |
241
241
  | `STICKY_NOTE_COLORS` | const | `dist/flow-sdk.d.ts:760-765` | Flow construction | The designer's sticky-note palette. |
242
242
  | `StickyNote` | interface | `dist/flow-sdk.d.ts:772-806` | Supporting types | A canvas sticky note — free text pinned to the diagram, for the humans reading it. |
243
243
  | `StickyNoteColor` | type | `dist/flow-sdk.d.ts:766-771` | Supporting types | A sticky note's swatch. |
244
- | `subflow` | function | `dist/flow-sdk.d.ts:1779-1818` | Flow construction | Run another flow as one step, and read back what it returns. |
244
+ | `subflow` | function | `dist/flow-sdk.d.ts:1785-1824` | Flow construction | Run another flow as one step, and read back what it returns. |
245
245
  | `SubflowSpec` | interface | `dist/flow-sdk.d.ts:47-54` | Supporting types | A step that runs a child flow. |
246
246
  | `summarize` | function | `dist/nodes/ai-patterns/flow/factories.d.ts:8-48` | Actions | Summarize a document with citations — the platform's **Summarize** node. |
247
247
  | `SummarizeInputs` | interface | `dist/nodes/ai-patterns/flow/spec.d.ts:8-40` | Option shapes | 3 field(s) |
@@ -67,7 +67,7 @@ not find it either.
67
67
  | `app` | property | `HumanTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1363-1364` |
68
68
  | `appSystemName` | property | `AppRef` | `dist/nodes/hitl/flow/spec.d.ts:170-175` |
69
69
  | `appVersion` | property | `HumanTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1365-1366` |
70
- | `armLabel` | property | `ArmBuilder` | `dist/flow-sdk.d.ts:1370` |
70
+ | `armLabel` | property | `ArmBuilder` | `dist/flow-sdk.d.ts:1376` |
71
71
  | `assignee` | property | `HitlRecipient` | `dist/nodes/hitl/flow/spec.d.ts:52-63` |
72
72
  | `async` | property | `OrchestratorAsyncOpts` | `dist/bpmn/bpmn-sdk.d.ts:1307-1311` |
73
73
  | `atRiskPercentage` | property | `EscalationOpts` | `dist/case/case-sdk.d.ts:132-137` |
@@ -100,12 +100,12 @@ not find it either.
100
100
  | `boundaryEvent` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2278-2285` |
101
101
  | `branch` | method | `StepList` | `dist/flow-sdk.d.ts:1081-1099` |
102
102
  | `branches` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:25-30` |
103
- | `break` | method | `StepList` | `dist/flow-sdk.d.ts:1217-1226` |
103
+ | `break` | method | `StepList` | `dist/flow-sdk.d.ts:1223-1232` |
104
104
  | `breakEnabled` | property | `DoWhileOptions` | `dist/flow-sdk.d.ts:554-555` |
105
105
  | `breakEnabled` | property | `LoopOptions` | `dist/flow-sdk.d.ts:541-545` |
106
106
  | `build` | method | `BpmnBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3581-3586` |
107
107
  | `build` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1370-1375` |
108
- | `build` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1755-1761` |
108
+ | `build` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1761-1767` |
109
109
  | `businessRule` | property | `BuiltTask` | `dist/case/case-sdk.d.ts:563-564` |
110
110
  | `businessRule` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2577-2641` |
111
111
  | `businessRule` | method | `TaskBuilder` | `dist/case/case-sdk.d.ts:854-882` |
@@ -177,7 +177,7 @@ not find it either.
177
177
  | `context` | property | `RegistryTypeSpec` | `dist/bpmn/typed-node.d.ts:94` |
178
178
  | `contextRows` | property | `ActivityNodeOpts` | `dist/bpmn/bpmn-sdk.d.ts:1559-1566` |
179
179
  | `contextVerbatim` | property | `ActivityNodeOpts` | `dist/bpmn/bpmn-sdk.d.ts:1631-1636` |
180
- | `continue` | method | `StepList` | `dist/flow-sdk.d.ts:1227-1241` |
180
+ | `continue` | method | `StepList` | `dist/flow-sdk.d.ts:1233-1247` |
181
181
  | `contribute` | method | `FlowNode` | `dist/core/node-classes.d.ts:144-153` |
182
182
  | `controlType` | property | `FormFieldSettings` | `dist/core/actions.d.ts:187-191` |
183
183
  | `conversationalAgent` | property | `FlowActionSpecs` | `dist/nodes/agent/flow/spec.d.ts:439-442` |
@@ -217,7 +217,7 @@ not find it either.
217
217
  | `deferDate` | property | `QueueItemInputs` | `dist/nodes/queue/flow/spec.d.ts:48-49` |
218
218
  | `definition` | property | `NodeContribution` | `dist/core/node-classes.d.ts:111-112` |
219
219
  | `definitions` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:860-865` |
220
- | `definitions` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1615-1655` |
220
+ | `definitions` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1621-1661` |
221
221
  | `delay` | property | `FlowActionSpecs` | `dist/nodes/delay/flow/spec.d.ts:38-41` |
222
222
  | `dependsOn` | property | `LookupSpec` | `dist/core/lookups.d.ts:34-35` |
223
223
  | `description` | property | `AgentMemoryRef` | `dist/core/actions.d.ts:643` |
@@ -234,7 +234,7 @@ not find it either.
234
234
  | `description` | property | `CustomGuardrail` | `dist/core/actions.d.ts:436` |
235
235
  | `description` | property | `EscalationRef` | `dist/core/actions.d.ts:805-806` |
236
236
  | `description` | property | `EventTriggerOpts` | `dist/case/case-sdk.d.ts:243` |
237
- | `description` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1408-1415` |
237
+ | `description` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1414-1421` |
238
238
  | `description` | property | `FormFieldSettings` | `dist/core/actions.d.ts:202-203` |
239
239
  | `description` | property | `HttpRequestToolRef` | `dist/core/actions.d.ts:610` |
240
240
  | `description` | property | `IxpExtractInputs` | `dist/core/actions.d.ts:343-350` |
@@ -277,7 +277,7 @@ not find it either.
277
277
  | `document` | property | `HitlInputs` | `dist/nodes/hitl/flow/spec.d.ts:285-289` |
278
278
  | `documentClassify` | property | `FlowActionSpecs` | `dist/nodes/document/flow/spec.d.ts:56-59` |
279
279
  | `documentId` | property | `DocValidationInputs` | `dist/nodes/hitl/flow/spec.d.ts:84-85` |
280
- | `doWhile` | method | `StepList` | `dist/flow-sdk.d.ts:1192-1216` |
280
+ | `doWhile` | method | `StepList` | `dist/flow-sdk.d.ts:1198-1222` |
281
281
  | `dueDate` | property | `QueueItemInputs` | `dist/nodes/queue/flow/spec.d.ts:50-51` |
282
282
  | `duration` | property | `TimerSpec` | `dist/bpmn/bpmn-sdk.d.ts:33-34` |
283
283
  | `dynamicExtract` | property | `FlowActionSpecs` | `dist/nodes/document/flow/spec.d.ts:60-63` |
@@ -302,7 +302,7 @@ not find it either.
302
302
  | `entity` | property | `DataServiceOpts` | `dist/bpmn/bpmn-sdk.d.ts:1116-1117` |
303
303
  | `entry` | property | `BuiltStage` | `dist/case/case-sdk.d.ts:588` |
304
304
  | `entry` | property | `BuiltTask` | `dist/case/case-sdk.d.ts:580` |
305
- | `entryPoint` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1490-1540` |
305
+ | `entryPoint` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1496-1546` |
306
306
  | `entryPointId` | property | `ActivityNodeOpts` | `dist/bpmn/bpmn-sdk.d.ts:1637-1642` |
307
307
  | `entryPointId` | property | `ConnectorEventOpts` | `dist/bpmn/bpmn-sdk.d.ts:1522-1526` |
308
308
  | `entryPointId` | property | `ProcessMetadata` | `dist/bpmn/bpmn-sdk.d.ts:544-556` |
@@ -482,7 +482,7 @@ not find it either.
482
482
  | `inclusiveGateway` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2305-2312` |
483
483
  | `inlineAgent` | property | `FlowActionSpecs` | `dist/nodes/agent/flow/spec.d.ts:443-446` |
484
484
  | `input` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1261-1286` |
485
- | `input` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1696-1708` |
485
+ | `input` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1702-1714` |
486
486
  | `input` | property | `HumanTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1381-1382` |
487
487
  | `input` | property | `OrchestratorOpts` | `dist/bpmn/bpmn-sdk.d.ts:1267-1268` |
488
488
  | `input` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3137-3145` |
@@ -558,7 +558,7 @@ not find it either.
558
558
  | `kind` | property | `SubflowSpec` | `dist/flow-sdk.d.ts:49` |
559
559
  | `kind` | property | `WhenExpression` | `dist/case/case-sdk.d.ts:99-100` |
560
560
  | `kValue` | property | `AgentMemoryRef` | `dist/core/actions.d.ts:650-651` |
561
- | `label` | method | `ArmBuilder` | `dist/flow-sdk.d.ts:1371-1380` |
561
+ | `label` | method | `ArmBuilder` | `dist/flow-sdk.d.ts:1377-1386` |
562
562
  | `label` | property | `AskedField` | `dist/core/actions.d.ts:225-226` |
563
563
  | `label` | property | `BuiltStage` | `dist/case/case-sdk.d.ts:583` |
564
564
  | `label` | property | `ContextIndexRef` | `dist/core/actions.d.ts:899-903` |
@@ -574,7 +574,7 @@ not find it either.
574
574
  | `layout` | property | `BuiltCase` | `dist/case/case-sdk.d.ts:706-707` |
575
575
  | `layout` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:856-857` |
576
576
  | `layout` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1240-1260` |
577
- | `layout` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1416-1442` |
577
+ | `layout` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1422-1448` |
578
578
  | `legacyCompleted` | property | `HitlInputs` | `dist/nodes/hitl/flow/spec.d.ts:252-284` |
579
579
  | `limit` | property | `DataFabricReadInputs` | `dist/nodes/data-fabric/flow/spec.d.ts:95-100` |
580
580
  | `limit` | property | `DoWhileOptions` | `dist/flow-sdk.d.ts:552-553` |
@@ -585,7 +585,7 @@ not find it either.
585
585
  | `lookups` | property | `ConnectorMeta` | `dist/core/connectors.d.ts:76-87` |
586
586
  | `loop` | property | `ActivityNodeFields` | `dist/bpmn/bpmn-sdk.d.ts:345-346` |
587
587
  | `loop` | property | `ActivityOpts` | `dist/bpmn/bpmn-sdk.d.ts:858-859` |
588
- | `loop` | method | `StepList` | `dist/flow-sdk.d.ts:1180-1191` |
588
+ | `loop` | method | `StepList` | `dist/flow-sdk.d.ts:1186-1197` |
589
589
  | `managed` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:37-67` |
590
590
  | `marksCaseComplete` | property | `BuiltCaseExitCondition` | `dist/case/case-sdk.d.ts:372` |
591
591
  | `marksStageComplete` | property | `BuiltExitCondition` | `dist/case/case-sdk.d.ts:339` |
@@ -677,7 +677,7 @@ not find it either.
677
677
  | `name` | property | `EventSubProcessOpts` | `dist/bpmn/bpmn-sdk.d.ts:1877-1878` |
678
678
  | `name` | property | `EventTriggerOpts` | `dist/case/case-sdk.d.ts:242` |
679
679
  | `name` | property | `ExternalTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1530-1531` |
680
- | `name` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1400-1407` |
680
+ | `name` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1406-1413` |
681
681
  | `name` | property | `FlowOpts` | `dist/bpmn/bpmn-sdk.d.ts:1674-1675` |
682
682
  | `name` | property | `GatewayOpts` | `dist/bpmn/bpmn-sdk.d.ts:786-787` |
683
683
  | `name` | property | `HandlerOpts` | `dist/bpmn/bpmn-sdk.d.ts:1772-1773` |
@@ -748,7 +748,7 @@ not find it either.
748
748
  | `onTimer` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3382-3390` |
749
749
  | `onTimer` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3391-3399` |
750
750
  | `openTails` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:875-880` |
751
- | `openTails` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1656-1695` |
751
+ | `openTails` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1662-1701` |
752
752
  | `operation` | property | `Aggregation` | `dist/nodes/transform/flow/spec.d.ts:37` |
753
753
  | `operation` | property | `ConnectorToolRef` | `dist/core/actions.d.ts:686-687` |
754
754
  | `operation` | property | `WaitConnectorPlaceholderSpec` | `dist/case/case-sdk.d.ts:386-387` |
@@ -764,7 +764,7 @@ not find it either.
764
764
  | `outcomes` | property | `EscalationRef` | `dist/core/actions.d.ts:851-856` |
765
765
  | `outcomes` | property | `HitlInputs` | `dist/nodes/hitl/flow/spec.d.ts:211-225` |
766
766
  | `output` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1287-1299` |
767
- | `output` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1709-1744` |
767
+ | `output` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1715-1750` |
768
768
  | `output` | property | `RegistryTypeSpec` | `dist/bpmn/typed-node.d.ts:97` |
769
769
  | `output` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3146-3154` |
770
770
  | `outputColumns` | property | `BatchTransformInputs` | `dist/nodes/ai-patterns/flow/spec.d.ts:56-60` |
@@ -800,7 +800,7 @@ not find it either.
800
800
  | `pageRange` | property | `DynamicExtractInputs` | `dist/nodes/document/flow/spec.d.ts:49-50` |
801
801
  | `pageRange` | property | `IxpExtractInputs` | `dist/core/actions.d.ts:332-333` |
802
802
  | `parallel` | property | `LoopOptions` | `dist/flow-sdk.d.ts:534-535` |
803
- | `parallel` | method | `StepList` | `dist/flow-sdk.d.ts:1143-1179` |
803
+ | `parallel` | method | `StepList` | `dist/flow-sdk.d.ts:1143-1185` |
804
804
  | `parallelGateway` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2295-2304` |
805
805
  | `parameters` | property | `ConnectorEventOpts` | `dist/bpmn/bpmn-sdk.d.ts:1505-1506` |
806
806
  | `parameters` | property | `HttpOpts` | `dist/bpmn/bpmn-sdk.d.ts:1166-1171` |
@@ -903,7 +903,7 @@ not find it either.
903
903
  | `retry` | property | `ActivityOpts` | `dist/bpmn/bpmn-sdk.d.ts:856-857` |
904
904
  | `retryable` | property | `ErrorMappingRow` | `dist/bpmn/bpmn-sdk.d.ts:318-319` |
905
905
  | `retryCount` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:109-123` |
906
- | `return` | method | `StepList` | `dist/flow-sdk.d.ts:1347-1356` |
906
+ | `return` | method | `StepList` | `dist/flow-sdk.d.ts:1353-1362` |
907
907
  | `returnCitations` | property | `SummarizeInputs` | `dist/nodes/ai-patterns/flow/spec.d.ts:34-39` |
908
908
  | `returns` | property | `AgentInputs` | `dist/nodes/process/flow/spec.d.ts:302-321` |
909
909
  | `returns` | property | `ApiWorkflowInputs` | `dist/nodes/process/flow/spec.d.ts:88-100` |
@@ -945,7 +945,7 @@ not find it either.
945
945
  | `schemaVersion` | method | `BpmnBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3473-3502` |
946
946
  | `schemaVersion` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:840-846` |
947
947
  | `schemaVersion` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1169-1195` |
948
- | `schemaVersion` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1575-1614` |
948
+ | `schemaVersion` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1581-1620` |
949
949
  | `scope` | property | `EscalationRecipient` | `dist/case/case-sdk.d.ts:121` |
950
950
  | `scopes` | property | `GuardrailSelector` | `dist/core/actions.d.ts:382` |
951
951
  | `script` | property | `FlowActionSpecs` | `dist/nodes/script/flow/spec.d.ts:47-50` |
@@ -1026,10 +1026,10 @@ not find it either.
1026
1026
  | `steps` | property | `StepList` | `dist/flow-sdk.d.ts:884` |
1027
1027
  | `stepSwitch` | method | `StepList` | `dist/flow-sdk.d.ts:927-969` |
1028
1028
  | `stepToList` | method | `StepList` | `dist/flow-sdk.d.ts:1044-1072` |
1029
- | `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:1281-1325` |
1030
- | `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:1326-1346` |
1029
+ | `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:1287-1331` |
1030
+ | `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:1332-1352` |
1031
1031
  | `stickyNotes` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:858-859` |
1032
- | `stickyNotes` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1443-1468` |
1032
+ | `stickyNotes` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1449-1474` |
1033
1033
  | `storageBucket` | property | `DocValidationInputs` | `dist/nodes/hitl/flow/spec.d.ts:82-83` |
1034
1034
  | `strategy` | property | `LookupSpec` | `dist/core/lookups.d.ts:33` |
1035
1035
  | `style` | property | `CaseNodeLayout` | `dist/case/case-sdk.d.ts:657-658` |
@@ -1067,7 +1067,7 @@ not find it either.
1067
1067
  | `temperature` | property | `InlineAgentInputs` | `dist/nodes/agent/flow/spec.d.ts:283-284` |
1068
1068
  | `temperature` | property | `VoiceSettings` | `dist/nodes/agent/flow/spec.d.ts:121-122` |
1069
1069
  | `terminate` | property | `EndOpts` | `dist/bpmn/bpmn-sdk.d.ts:718-719` |
1070
- | `terminate` | method | `StepList` | `dist/flow-sdk.d.ts:1242-1280` |
1070
+ | `terminate` | method | `StepList` | `dist/flow-sdk.d.ts:1248-1286` |
1071
1071
  | `threshold` | property | `ContextIndexRef` | `dist/core/actions.d.ts:895-896` |
1072
1072
  | `timeCycle` | property | `BuiltTrigger` | `dist/case/case-sdk.d.ts:201-202` |
1073
1073
  | `timeout` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:91-108` |
@@ -1091,11 +1091,11 @@ not find it either.
1091
1091
  | `trigger` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:851-853` |
1092
1092
  | `trigger` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1325-1333` |
1093
1093
  | `trigger` | property | `EscalationOpts` | `dist/case/case-sdk.d.ts:128-129` |
1094
- | `trigger` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1469-1489` |
1094
+ | `trigger` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1475-1495` |
1095
1095
  | `trigger` | property | `StartOpts` | `dist/bpmn/bpmn-sdk.d.ts:641-688` |
1096
1096
  | `triggeredByEvent` | property | `SubProcessOpts` | `dist/bpmn/bpmn-sdk.d.ts:1002-1003` |
1097
1097
  | `triggerId` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:868-874` |
1098
- | `triggerId` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1541-1560` |
1098
+ | `triggerId` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1547-1566` |
1099
1099
  | `triggerOptions` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:854-855` |
1100
1100
  | `triggers` | property | `BuiltCase` | `dist/case/case-sdk.d.ts:704-705` |
1101
1101
  | `triggers` | property | `CaseLayout` | `dist/case/case-sdk.d.ts:680-681` |
@@ -1153,7 +1153,7 @@ not find it either.
1153
1153
  | `value` | property | `TypedInputRow` | `dist/bpmn/typed-node.d.ts:250-251` |
1154
1154
  | `values` | property | `DataFabricCreateInputs` | `dist/nodes/data-fabric/flow/spec.d.ts:132-137` |
1155
1155
  | `var` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1300-1324` |
1156
- | `var` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1745-1754` |
1156
+ | `var` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1751-1760` |
1157
1157
  | `var` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3128-3136` |
1158
1158
  | `var` | property | `TaskOutputBinding` | `dist/case/case-sdk.d.ts:551-552` |
1159
1159
  | `var` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:296-297` |
@@ -1177,7 +1177,7 @@ not find it either.
1177
1177
  | `version` | property | `ConnectorToolRef` | `dist/core/actions.d.ts:688-689` |
1178
1178
  | `version` | property | `EventSubscription` | `dist/core/actions.d.ts:1206` |
1179
1179
  | `version` | property | `ExternalTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1538-1539` |
1180
- | `version` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1561-1574` |
1180
+ | `version` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1567-1580` |
1181
1181
  | `version` | property | `NodeOptions` | `dist/flow-sdk.d.ts:399-406` |
1182
1182
  | `version` | property | `TriggerMeta` | `dist/core/connectors.d.ts:126` |
1183
1183
  | `version` | property | `TriggerOptions` | `dist/core/actions.d.ts:1163-1164` |
@@ -5,6 +5,7 @@ import { preserveSchemaVersion } from '../schema-version.js';
5
5
  import { ownEntry } from '../core/own-entry.js';
6
6
  import { isUnrestorableSlotId } from './preserve.js';
7
7
  import { isInSolutionKey, SOLUTION_FOLDER } from './resource-identity.js';
8
+ import { offlineBindingLabel } from './ids.js';
8
9
  const TASK_KIND_METHOD = {
9
10
  process: 'process',
10
11
  agent: 'agent',
@@ -342,7 +343,18 @@ function bindingName(value, refs) {
342
343
  if (typeof value !== 'string' || !value.startsWith('=bindings.'))
343
344
  return undefined;
344
345
  const id = value.slice('=bindings.'.length);
345
- return refs.bindingById.get(id)?.id ?? id;
346
+ return bindingLabel(refs, id);
347
+ }
348
+ /**
349
+ * The name a binding reference decompiles to: the authored label when
350
+ * `serialize` minted the row offline (so a recompile with no bindings.json
351
+ * mints the same row, and a later bindings.json entry for that label matches),
352
+ * else the row id (a bindings.json or Designer row, which the recompile
353
+ * resolves by id).
354
+ */
355
+ function bindingLabel(refs, id) {
356
+ const row = refs.bindingById.get(id);
357
+ return offlineBindingLabel(row) ?? row?.id ?? id;
346
358
  }
347
359
  /**
348
360
  * The literal a resource task's `data.name` / `data.folderPath` names: the
@@ -567,7 +579,7 @@ function externalCall(task, refs, library) {
567
579
  const id = value.slice('=bindings.'.length);
568
580
  if (!refs.bindingById.has(id))
569
581
  throw new Error(`${owner} context ${name} references missing root binding "${id}".`);
570
- return id;
582
+ return bindingLabel(refs, id);
571
583
  };
572
584
  const identity = library.identifyAction({
573
585
  connectorKey: stringValue('connectorKey'),
@@ -22,3 +22,29 @@ export declare class IdGen {
22
22
  conditionId(seed: string): string;
23
23
  ruleId(seed: string): string;
24
24
  }
25
+ /**
26
+ * The seed `serialize` mints an offline binding id from (a connection or
27
+ * folder label no bindings.json declares). One definition for both sides, so
28
+ * {@link offlineBindingLabel} can recognise exactly the ids `serialize` mints.
29
+ *
30
+ * @param resource - The binding's `resource` (`Connection`).
31
+ * @param propertyAttribute - `ConnectionId` or `folderKey`.
32
+ * @param name - The authored label.
33
+ * @param connectionKey - For a folder bound to a connection, that connection's resourceKey.
34
+ * @returns The seed string.
35
+ */
36
+ export declare function offlineBindingSeed(resource: string, propertyAttribute: string, name: string, connectionKey?: string): string;
37
+ /**
38
+ * The authored label behind a root binding row that `serialize` minted offline,
39
+ * or `undefined` for any other row (a bindings.json entry, a Designer row).
40
+ *
41
+ * Offline the label is the row's only real content: a connection row carries
42
+ * it as `resourceKey`, a folder row on a connection as `default`, a plain
43
+ * folder row as `resourceKey`. The row is recognised only when its `id` is
44
+ * exactly the id that label mints, so decompile can name it by the label and
45
+ * a recompile with no bindings mints the same row again.
46
+ *
47
+ * @param row - A root binding entry.
48
+ * @returns The label, or `undefined`.
49
+ */
50
+ export declare function offlineBindingLabel(row: Record<string, unknown> | undefined): string | undefined;
package/dist/case/ids.js CHANGED
@@ -74,3 +74,52 @@ export class IdGen {
74
74
  return this.make('Rule_', 6, seed);
75
75
  }
76
76
  }
77
+ /**
78
+ * The seed `serialize` mints an offline binding id from (a connection or
79
+ * folder label no bindings.json declares). One definition for both sides, so
80
+ * {@link offlineBindingLabel} can recognise exactly the ids `serialize` mints.
81
+ *
82
+ * @param resource - The binding's `resource` (`Connection`).
83
+ * @param propertyAttribute - `ConnectionId` or `folderKey`.
84
+ * @param name - The authored label.
85
+ * @param connectionKey - For a folder bound to a connection, that connection's resourceKey.
86
+ * @returns The seed string.
87
+ */
88
+ export function offlineBindingSeed(resource, propertyAttribute, name, connectionKey) {
89
+ return connectionKey === undefined
90
+ ? `binding:${resource}:${propertyAttribute}:${name}`
91
+ : `binding:${resource}:${propertyAttribute}:${connectionKey}:${name}`;
92
+ }
93
+ /** The binding id {@link IdGen.make} gives `seed` at salt 0..3 (`b` + 8 base-62). */
94
+ function offlineBindingIds(seed) {
95
+ return [0, 1, 2, 3].map((salt) => 'b' + base62(salt === 0 ? seed : `${seed}~${salt}`, 8));
96
+ }
97
+ /**
98
+ * The authored label behind a root binding row that `serialize` minted offline,
99
+ * or `undefined` for any other row (a bindings.json entry, a Designer row).
100
+ *
101
+ * Offline the label is the row's only real content: a connection row carries
102
+ * it as `resourceKey`, a folder row on a connection as `default`, a plain
103
+ * folder row as `resourceKey`. The row is recognised only when its `id` is
104
+ * exactly the id that label mints, so decompile can name it by the label and
105
+ * a recompile with no bindings mints the same row again.
106
+ *
107
+ * @param row - A root binding entry.
108
+ * @returns The label, or `undefined`.
109
+ */
110
+ export function offlineBindingLabel(row) {
111
+ if (!row || typeof row.id !== 'string')
112
+ return undefined;
113
+ const { id, resource, propertyAttribute, resourceKey } = row;
114
+ if (typeof resource !== 'string' || typeof propertyAttribute !== 'string' || typeof resourceKey !== 'string')
115
+ return undefined;
116
+ const candidates = [
117
+ [resourceKey, offlineBindingSeed(resource, propertyAttribute, resourceKey)],
118
+ ];
119
+ if (propertyAttribute === 'folderKey' && typeof row.default === 'string')
120
+ candidates.push([row.default, offlineBindingSeed(resource, propertyAttribute, row.default, resourceKey)]);
121
+ for (const [label, seed] of candidates)
122
+ if (offlineBindingIds(seed).includes(id))
123
+ return label;
124
+ return undefined;
125
+ }
@@ -8,7 +8,7 @@
8
8
  * `metadata.caseExitRules`. Symbolic references in rules (a stage label, a task
9
9
  * name) are resolved here to the generated ids.
10
10
  */
11
- import { IdGen } from './ids.js';
11
+ import { IdGen, offlineBindingSeed } from './ids.js';
12
12
  import { isUnrestorableSlotId } from './preserve.js';
13
13
  import { v31TaskSets } from './task-sets.js';
14
14
  import { buildConnectorInputs, nestConnectorBody, transportHttpMethod } from '../core/connector-inputs.js';
@@ -81,6 +81,8 @@ export function serialize(built, opts = {}) {
81
81
  library: opts.library,
82
82
  bindings: opts.bindings,
83
83
  bindingSink: new Map(),
84
+ ids,
85
+ offlineBindingIds: new Map(),
84
86
  varCompanions: new Map(),
85
87
  outputIds: new Set(),
86
88
  ownOutputVars: ownOutputVars(built),
@@ -1469,6 +1471,20 @@ function ioSlot(name, bodyObj, elementId) {
1469
1471
  const v = `v${name}`;
1470
1472
  return { name, type: 'json', target: name, body: bodyObj, var: v, id: v, elementId };
1471
1473
  }
1474
+ /**
1475
+ * The binding id for a label no bindings.json declares. The row's
1476
+ * `resourceKey`/`default` stays the label, and the id is minted from it (`b` +
1477
+ * 8, as Studio Web mints one), once per label; `offlineBindingLabel` reverses
1478
+ * it for decompile.
1479
+ */
1480
+ function offlineBindingId(resolver, seed) {
1481
+ let id = resolver.offlineBindingIds.get(seed);
1482
+ if (id === undefined) {
1483
+ id = resolver.ids.make('b', 8, seed);
1484
+ resolver.offlineBindingIds.set(seed, id);
1485
+ }
1486
+ return id;
1487
+ }
1472
1488
  /** Resolve a symbolic connection/folder to a root binding entry (collected once),
1473
1489
  * returning its id + resourceKey for the `=bindings.<id>` reference. */
1474
1490
  function bindingRef(resolver, name, resource, propertyAttribute, displayName, site) {
@@ -1483,8 +1499,12 @@ function bindingRef(resolver, name, resource, propertyAttribute, displayName, si
1483
1499
  if (refused)
1484
1500
  throw refused;
1485
1501
  const entry = resolver.bindings?.entry(name);
1486
- const id = entry?.id ?? name;
1487
1502
  const resourceKey = entry?.resourceKey ?? entry?.default ?? name;
1503
+ // Only a label with no bindings.json entry gets a minted id: an entry's
1504
+ // `resourceKey` is the real key, so its id (or its name) cannot clash with it.
1505
+ const id = entry
1506
+ ? String(entry.id ?? name)
1507
+ : offlineBindingId(resolver, offlineBindingSeed(resource, propertyAttribute, name));
1488
1508
  if (!resolver.bindingSink.has(id)) {
1489
1509
  resolver.bindingSink.set(id, {
1490
1510
  id,
@@ -1501,7 +1521,8 @@ function bindingRef(resolver, name, resource, propertyAttribute, displayName, si
1501
1521
  /**
1502
1522
  * A connector's folder is a property of its connection:
1503
1523
  * { resourceKey: <connection key>, default: <folder key>, propertyAttribute: 'folderKey' }.
1504
- * One folder label on two connections gets one row each: `shared`, `shared_2`.
1524
+ * One folder label on two connections gets one row each: `shared`, `shared_2`
1525
+ * (offline, the minted id is seeded on the connection, so the rows differ anyway).
1505
1526
  * One connection with two different folders is refused: a connection lives in
1506
1527
  * one folder, and the syncs group rows by `resourceKey`, so one value would win.
1507
1528
  * Without a connection the folder binds as a plain binding.
@@ -1515,7 +1536,9 @@ function folderBindingRef(resolver, name, connection, site) {
1515
1536
  if (refused)
1516
1537
  throw refused;
1517
1538
  const entry = resolver.bindings?.entry(name);
1518
- const baseId = entry?.id ?? name;
1539
+ const baseId = entry
1540
+ ? String(entry.id ?? name)
1541
+ : offlineBindingId(resolver, offlineBindingSeed('Connection', 'folderKey', name, connection.resourceKey));
1519
1542
  const folderKey = entry?.default ?? entry?.resourceKey ?? name;
1520
1543
  const matches = (row) => row?.resourceKey === connection.resourceKey && row?.default === folderKey
1521
1544
  && row?.propertyAttribute === 'folderKey';
package/dist/check.js CHANGED
@@ -2356,7 +2356,7 @@ function checkParallel(s, diags) {
2356
2356
  // flows have (a bare fan-out from the trigger, one arm terminating, the other
2357
2357
  // ending) — and the rule would be rejecting a correct flow. A terminate arm
2358
2358
  // never starves a join either: it stops the run, so the join is moot.
2359
- const reachesJoin = (arm) => arm.length > 0 && !arm.some((st) => st.kind === 'return' || st.kind === 'terminate');
2359
+ const reachesJoin = armReachesJoin;
2360
2360
  if (arms.some(reachesJoin)) {
2361
2361
  arms.forEach((arm, i) => {
2362
2362
  const steps = Array.isArray(arm) ? arm : [];
@@ -2369,11 +2369,26 @@ function checkParallel(s, diags) {
2369
2369
  });
2370
2370
  }
2371
2371
  }
2372
+ /**
2373
+ * Whether a `.parallel` arm hands its join an edge, as serialize wires it: it
2374
+ * has a step, and `armTails` (serialize's `emit` tail for tail) leaves it at
2375
+ * least one tail. So an arm that ends by `.return`, `.terminate`, `.break`,
2376
+ * `.continue` or a `.stepToRef` on the default port does not, and neither does
2377
+ * one that ends in a `.branch` / `.switch` / `.stepSwitch` every arm of which
2378
+ * ends, or in a nested `.parallel` none of whose arms reaches its own join.
2379
+ * When no arm hands on a tail, serialize emits no Merge at all (#1267), so the
2380
+ * join rules (PARALLEL_ARM_RETURNS, REF_INTO_PARALLEL_ARM,
2381
+ * REF_OUT_OF_PARALLEL_ARM) have no join to protect.
2382
+ */
2383
+ function armReachesJoin(arm) {
2384
+ return arm.length > 0 && armTails(arm, [{ from: '' }]).length > 0;
2385
+ }
2372
2386
  /**
2373
2387
  * The edges a step list hands on, mirroring serialize's `emit` tail for tail.
2374
2388
  *
2375
2389
  * `.branch` / `.switch` / `.stepSwitch` hand on every arm's tails (an empty arm
2376
- * hands on the port it started from), a fan-out human task one per continuing
2390
+ * hands on the port it started from), a `.parallel` its Merge when an arm
2391
+ * reaches it and nothing otherwise, a fan-out human task one per continuing
2377
2392
  * outcome, a routed one its primary outcome; `.return` / `.terminate` / `.break`
2378
2393
  * and a `stepToRef('output', …)` hand on none, `.stepToList` leaves the path as
2379
2394
  * it was, and every other step hands on its own single edge.
@@ -2408,6 +2423,13 @@ function armTails(steps, incoming) {
2408
2423
  ...(st.default !== undefined ? armTails(st.default, [{ from: st.name }]) : []),
2409
2424
  ];
2410
2425
  }
2426
+ else if (st.kind === 'parallel') {
2427
+ // serialize joins a nested `.parallel` at its Merge, the one edge it hands
2428
+ // on, and emits no Merge, so no edge, when no arm hands on a tail (#1267).
2429
+ // An empty arm hands on the path it started from, which the Merge joins.
2430
+ const arms = Array.isArray(st.arms) ? st.arms : [];
2431
+ tails = arms.some((arm) => armTails(arm, tails).length > 0) ? [{ from: st.name }] : [];
2432
+ }
2411
2433
  else {
2412
2434
  tails = [{ from: st.name ?? st.kind }];
2413
2435
  }
@@ -3273,6 +3295,8 @@ function checkStepRefs(built, diags, reservedIds = []) {
3273
3295
  const scopeOf = new Map();
3274
3296
  /** Step name → the parallel arm it lives in, as `<parallel>#<index>`. */
3275
3297
  const armOf = new Map();
3298
+ /** Every `.parallel` no arm of which reaches its join, so it has no Merge (#1267). */
3299
+ const unjoined = new Set();
3276
3300
  /**
3277
3301
  * How many nodes answer to each NAMED End's name (`.return({}, { name })`), and
3278
3302
  * how many of those are steps. A named End is a ref target too (#1223): a side
@@ -3348,6 +3372,8 @@ function checkStepRefs(built, diags, reservedIds = []) {
3348
3372
  index(s.default ?? [], portList, scope, arm);
3349
3373
  }
3350
3374
  else if (s.kind === 'parallel') {
3375
+ if (!s.arms.some(armReachesJoin))
3376
+ unjoined.add(s.name);
3351
3377
  // The fork node (`{ fork }`, #1310) is a node in this scope like the
3352
3378
  // join: a `.stepToRef(<fork>)` is an edge serialize resolves.
3353
3379
  const fork = parallelFork(s.options);
@@ -3555,8 +3581,11 @@ function checkStepRefs(built, diags, reservedIds = []) {
3555
3581
  // A Terminate stops the whole run, every branch with it, so no Merge is left
3556
3582
  // waiting: a ref into or out of an arm that ends at one cannot hang a join
3557
3583
  // (#1239). An End stops only its own path, so it keeps the warnings.
3584
+ // A `.parallel` whose arms all end has no Merge to wait (#1267), so a ref
3585
+ // into or out of one of its arms cannot hang a join either.
3586
+ const joined = (a) => a !== undefined && !unjoined.has(a.slice(0, a.lastIndexOf('#')));
3558
3587
  if (targetArm !== arm && !terminateNames.has(target)) {
3559
- if (targetArm !== undefined) {
3588
+ if (joined(targetArm)) {
3560
3589
  say('warning', 'REF_INTO_PARALLEL_ARM', `.stepToRef('${target}') ${where} points INTO a parallel arm from outside it. The Merge those arms join `
3561
3590
  + `on is a bpmn:ParallelGateway, which waits for every branch it forked — an extra token arriving inside `
3562
3591
  + `an arm is not one of them, so the join may never settle. Verify with uip maestro flow validate.`);
@@ -3577,7 +3606,7 @@ function checkStepRefs(built, diags, reservedIds = []) {
3577
3606
  + `so leave a decompiled one as it is.`);
3578
3607
  }
3579
3608
  }
3580
- else if (arm !== undefined) {
3609
+ else if (joined(arm)) {
3581
3610
  say('warning', 'REF_OUT_OF_PARALLEL_ARM', `.stepToRef('${target}') ${where} leaves a parallel arm without reaching its Merge. That Merge waits for `
3582
3611
  + `every branch it forked, so the token this arm owed it never arrives and the join may hang. Verify with `
3583
3612
  + `uip maestro flow validate.`);
package/dist/decompile.js CHANGED
@@ -1598,10 +1598,13 @@ function commonPostDominator(targets, ipdom) {
1598
1598
  *
1599
1599
  * When the arms meet at a merge node, every edge in `edges` is accounted
1600
1600
  * (edge accounting, #1125): the fold recreates each one. A fork whose arms
1601
- * never meet at a merge node has no builder spelling. Like the same shape
1602
- * mid-flow (`region`), it throws under `bestEffort: false`, and otherwise keeps
1603
- * the first arm behind a `TODO: unstructured fan-out` marker. Only the kept
1604
- * first edge is accounted; the others are reported as dropped at the marker.
1601
+ * never meet again and each end (`unjoinedFork`) is a `.parallel(...)` whose
1602
+ * arms all end, which serialize writes with no merge node (#1267); it folds the
1603
+ * same way, and nothing follows it. Any other fork has no builder spelling.
1604
+ * Like the same shape mid-flow (`region`), it throws under `bestEffort: false`,
1605
+ * and otherwise keeps the first arm behind a `TODO: unstructured fan-out`
1606
+ * marker. Only the kept first edge is accounted; the others are reported as
1607
+ * dropped at the marker.
1605
1608
  */
1606
1609
  function forkRegion(edges, stop, scope, ipdom, ctx, refInto) {
1607
1610
  if (edges.length <= 1)
@@ -1614,11 +1617,19 @@ function forkRegion(edges, stop, scope, ipdom, ctx, refInto) {
1614
1617
  // here. Not at a merge node that is `stop`: the enclosing construct continues
1615
1618
  // from it, so a `.parallel` inside this arm cannot also own it.
1616
1619
  if (join === undefined || joinNode === undefined || !parallelJoinable(joinNode) || (join === stop && joinNode.type === T.merge)) {
1620
+ const unjoined = unjoinedFork(targets, scope, ctx);
1621
+ const stopBehind = unjoined ? terminateBehindStep(targets, scope, ipdom, ctx) : undefined;
1622
+ if (unjoined && stopBehind === undefined) {
1623
+ for (const e of edges)
1624
+ ctx.graph.accounted.add(e);
1625
+ return [parallelSeg(undefined, undefined, targets, scope, ipdom, ctx, refInto, undefined, edges[0].sourceNodeId).seg];
1626
+ }
1627
+ const why = stopBehind !== undefined ? terminateBehindStepWhy(stopBehind) : '';
1617
1628
  if (ctx.o.bestEffort === false)
1618
- throw new Error(`decompile: unstructured fan-out (${edges.length} edges).`);
1629
+ throw new Error(`decompile: unstructured fan-out (${edges.length} edges)${why}.`);
1619
1630
  ctx.graph.accounted.add(edges[0]);
1620
1631
  return [
1621
- `/* TODO: unstructured fan-out (${commentText(edges.length)} edges) */`,
1632
+ `/* TODO: unstructured fan-out (${commentText(edges.length)} edges)${commentText(why)} */`,
1622
1633
  dropEdges(edges.slice(1), ctx),
1623
1634
  ...region(targets[0], stop, scope, ipdom, ctx, refInto),
1624
1635
  ];
@@ -1657,8 +1668,18 @@ function parallelJoinable(join) {
1657
1668
  *
1658
1669
  * `fork` is the merge node a designer-drawn split leaves from, written as
1659
1670
  * `{ fork }` (#1310); the caller accounts its outgoing edges.
1671
+ *
1672
+ * With no `join` the fork is unjoined (`unjoinedFork`, #1267): every arm runs
1673
+ * to its own End or Terminate, the `.parallel` gets a fresh name (`forkName`),
1674
+ * and `next` is empty because nothing can follow it.
1660
1675
  */
1661
1676
  function parallelSeg(join, joinNode, targets, scope, ipdom, ctx, refInto, fork, source) {
1677
+ if (join === undefined || joinNode === undefined) {
1678
+ const name = forkName(source ?? fork?.id, ctx);
1679
+ const arms = targets.map((t, i) => armCb(`a${i}`, region(t, EXIT, scope, ipdom, ctx, refInto)));
1680
+ const seg = `.parallel(${tsLiteral(name)}, [\n${arms.map((a) => reindent(a, ' ')).join(',\n')},\n]${forkOptsArg(undefined, fork)})`;
1681
+ return { seg, next: {} };
1682
+ }
1662
1683
  const atMerge = joinNode.type === T.merge;
1663
1684
  const name = atMerge ? join : forkName(source ?? fork?.id, ctx);
1664
1685
  const arms = targets.map((t, i) => {
@@ -1677,13 +1698,80 @@ function parallelSeg(join, joinNode, targets, scope, ipdom, ctx, refInto, fork,
1677
1698
  function endsPath(seg) {
1678
1699
  return seg !== undefined && /^\.(stepToRef|break|continue|return|terminate)\(/.test(seg);
1679
1700
  }
1701
+ /**
1702
+ * Whether a fan-out into `targets` is a `.parallel(...)` whose arms all end
1703
+ * (#1267). serialize writes that `.parallel` with NO merge node: when no arm
1704
+ * hands the join a tail there is nothing to join, so the fork's node just has
1705
+ * one edge per arm out of one port. The canvas and the classic CLI draw the
1706
+ * same shape (two edges out of one port, each into its own End). The file
1707
+ * therefore holds everything but the fork's name, which no node carries.
1708
+ *
1709
+ * It is that shape when, within `scope`:
1710
+ * - every path out of every arm ends at an End or a Terminate. A path that
1711
+ * just stops on a step (a dangling node) would recompile with a tail, and a
1712
+ * tail makes serialize add a merge node the file does not have;
1713
+ * - the arms share no node but an End or Terminate. A shared End or Terminate
1714
+ * is fine: the second arm to reach it ends with `.stepToRef(...)`
1715
+ * (#1231/#1239). A shared step would be a reconvergence with no join.
1716
+ */
1717
+ function unjoinedFork(targets, scope, ctx) {
1718
+ const owner = new Map();
1719
+ for (const [i, t] of targets.entries()) {
1720
+ for (const n of forwardReach([t], scope, ctx.graph)) {
1721
+ const type = ctx.graph.byId.get(n)?.type;
1722
+ if (type === T.end || type === T.terminate)
1723
+ continue;
1724
+ if (scopeSucc(ctx.graph, n, scope).length === 0)
1725
+ return false;
1726
+ if ((owner.get(n) ?? i) !== i)
1727
+ return false;
1728
+ owner.set(n, i);
1729
+ }
1730
+ }
1731
+ return true;
1732
+ }
1733
+ /**
1734
+ * The Terminate an unjoined fork's arm would spell as `.terminate(...)` behind
1735
+ * another step, or `undefined` when there is none. check refuses that inside a
1736
+ * `.parallel` (TERMINATE_NOT_ARM_HEAD, an error), so folding it would turn a
1737
+ * flow the user did not edit into source that fails compile with check; the
1738
+ * fork stays unstructured instead. Whether the rule still holds now that the
1739
+ * FIL lowering it was written for is gone is #1388.
1740
+ *
1741
+ * Mirrors check, which looks at an arm's top-level steps only: the nodes the
1742
+ * arm's walk emits at top level are the arm target's post-dominator chain, so
1743
+ * a Terminate on that chain, other than the target, is a top-level terminate
1744
+ * behind a step. A Terminate an earlier arm already reaches is not: this arm
1745
+ * spells it `.stepToRef(...)` (#1231/#1239). A Terminate on one side of a
1746
+ * decision is nested in a `.branch` / `.switch`, which check accepts.
1747
+ */
1748
+ function terminateBehindStep(targets, scope, ipdom, ctx) {
1749
+ const earlier = new Set();
1750
+ for (const t of targets) {
1751
+ const seen = new Set([t]);
1752
+ for (let n = ipdom.get(t); n !== undefined && n !== EXIT && !seen.has(n); n = ipdom.get(n)) {
1753
+ seen.add(n);
1754
+ if (ctx.graph.byId.get(n)?.type === T.terminate && !earlier.has(n))
1755
+ return n;
1756
+ }
1757
+ for (const n of forwardReach([t], scope, ctx.graph))
1758
+ earlier.add(n);
1759
+ }
1760
+ return undefined;
1761
+ }
1762
+ /** Why a fork with a Terminate behind a step stays unstructured, for the marker and the `--strict` error. */
1763
+ function terminateBehindStepWhy(stop) {
1764
+ return `: terminate "${stop}" is not the first step of its arm, which check refuses inside a .parallel `
1765
+ + '(TERMINATE_NOT_ARM_HEAD, flow-builder-sdk#1388)';
1766
+ }
1680
1767
  /**
1681
1768
  * A name for a `.parallel(...)` that creates no merge node: `<source>Fork`,
1682
1769
  * numbered when that is a node id, a declared input, variable or output, or a
1683
1770
  * name already minted. No node carries it (the arms join on a plain step by
1684
- * ref), but it must still not collide with any of those: check reads a
1685
- * `$vars.<name>` of a parallel's name as a read of its merge, so a variable
1686
- * of that name would fail PARALLEL_HAS_NO_OUTPUT on recompile.
1771
+ * ref, or never join, #1267), but it must still not collide with any of
1772
+ * those: check reads a `$vars.<name>` of a parallel's name as a read of its
1773
+ * merge, so a variable of that name would fail PARALLEL_HAS_NO_OUTPUT on
1774
+ * recompile.
1687
1775
  */
1688
1776
  function forkName(source, ctx) {
1689
1777
  const base = `${source ?? 'parallel'}Fork`;
@@ -2125,11 +2213,21 @@ function region(cursor, stop, scope, ipdom, ctx, refInto) {
2125
2213
  cursor = fork.next.cursor;
2126
2214
  continue;
2127
2215
  }
2216
+ // Parallel with no join: every arm ends, so serialize wrote no merge (#1267).
2217
+ const unjoined = unjoinedFork(succ, scope, ctx);
2218
+ const stopBehind = unjoined ? terminateBehindStep(succ, scope, ipdom, ctx) : undefined;
2219
+ if (unjoined && stopBehind === undefined) {
2220
+ const arms = succ.map((t) => follow(ctx.graph, node.id, t));
2221
+ segs.push(parallelSeg(undefined, undefined, arms, scope, ipdom, ctx, refInto, undefined, node.id).seg);
2222
+ flagDropped(node, ctx, segs);
2223
+ return segs;
2224
+ }
2128
2225
  // Unstructured fan-out we can't fold — best-effort marker.
2129
2226
  // No successor is walked: leave the edges unaccounted so `flagDropped` names each.
2227
+ const why = stopBehind !== undefined ? terminateBehindStepWhy(stopBehind) : '';
2130
2228
  if (ctx.o.bestEffort === false)
2131
- throw new Error(`decompile: unstructured fan-out at "${node.id}".`);
2132
- segs.push(`/* TODO: unstructured fan-out at ${commentText(node.id)} (${commentText(succ.length)} successors) */`);
2229
+ throw new Error(`decompile: unstructured fan-out at "${node.id}"${why}.`);
2230
+ segs.push(`/* TODO: unstructured fan-out at ${commentText(node.id)} (${commentText(succ.length)} successors)${commentText(why)} */`);
2133
2231
  flagDropped(node, ctx, segs);
2134
2232
  return segs;
2135
2233
  }
@@ -1154,6 +1154,12 @@ declare class StepList {
1154
1154
  * arm's output. The Merge itself computes nothing and publishes nothing — read
1155
1155
  * the steps inside the arms, never `$vars.<merge>`.
1156
1156
  *
1157
+ * When EVERY arm ends — with `.return`, `.terminate`, or a `.stepToRef` to an
1158
+ * End another arm wrote — there is nothing to join: no Merge is emitted, the
1159
+ * fork is just one edge per arm, `name` names no node, and nothing may follow
1160
+ * the `.parallel`. Decompile writes a fan-out whose arms never meet again
1161
+ * this way, naming it `<node>Fork` after the node it leaves.
1162
+ *
1157
1163
  * Arm semantics, what a local run does and does not prove, and the rules
1158
1164
  * `check` enforces: `references/parallel-merge.md`.
1159
1165
  *
package/dist/flow-sdk.js CHANGED
@@ -759,6 +759,12 @@ class StepList {
759
759
  * arm's output. The Merge itself computes nothing and publishes nothing — read
760
760
  * the steps inside the arms, never `$vars.<merge>`.
761
761
  *
762
+ * When EVERY arm ends — with `.return`, `.terminate`, or a `.stepToRef` to an
763
+ * End another arm wrote — there is nothing to join: no Merge is emitted, the
764
+ * fork is just one edge per arm, `name` names no node, and nothing may follow
765
+ * the `.parallel`. Decompile writes a fan-out whose arms never meet again
766
+ * this way, naming it `<node>Fork` after the node it leaves.
767
+ *
762
768
  * Arm semantics, what a local run does and does not prove, and the rules
763
769
  * `check` enforces: `references/parallel-merge.md`.
764
770
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.46.5",
3
+ "version": "6.46.7",
4
4
  "description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.uipath.com/maestro",
@@ -93,5 +93,5 @@
93
93
  "@types/node": "^22.7.0",
94
94
  "esbuild": "^0.28.1"
95
95
  },
96
- "gitref": "0edb50d70d9787a64a6c66ce37b5e1eed45d2a0d"
96
+ "gitref": "68e27a784a7d9b4fff5177074148d05e0c993a65"
97
97
  }