@mmmnt/cli 0.8.0 → 0.10.0
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/moment.mjs +383 -67
- package/dist/moment.mjs.map +3 -3
- package/package.json +9 -9
package/dist/moment.mjs
CHANGED
|
@@ -55439,6 +55439,9 @@ var PolicyDeclaration = {
|
|
|
55439
55439
|
$type: "PolicyDeclaration",
|
|
55440
55440
|
action: "action",
|
|
55441
55441
|
chainsTo: "chainsTo",
|
|
55442
|
+
conditionAfter: "conditionAfter",
|
|
55443
|
+
conditionField: "conditionField",
|
|
55444
|
+
conditionValue: "conditionValue",
|
|
55442
55445
|
gateways: "gateways",
|
|
55443
55446
|
name: "name",
|
|
55444
55447
|
trigger: "trigger"
|
|
@@ -56130,6 +56133,18 @@ var MomentAstReflection = class extends AbstractAstReflection {
|
|
|
56130
56133
|
chainsTo: {
|
|
56131
56134
|
name: PolicyDeclaration.chainsTo
|
|
56132
56135
|
},
|
|
56136
|
+
conditionAfter: {
|
|
56137
|
+
name: PolicyDeclaration.conditionAfter,
|
|
56138
|
+
optional: true
|
|
56139
|
+
},
|
|
56140
|
+
conditionField: {
|
|
56141
|
+
name: PolicyDeclaration.conditionField,
|
|
56142
|
+
optional: true
|
|
56143
|
+
},
|
|
56144
|
+
conditionValue: {
|
|
56145
|
+
name: PolicyDeclaration.conditionValue,
|
|
56146
|
+
optional: true
|
|
56147
|
+
},
|
|
56133
56148
|
gateways: {
|
|
56134
56149
|
name: PolicyDeclaration.gateways,
|
|
56135
56150
|
defaultValue: [],
|
|
@@ -58059,6 +58074,66 @@ var MomentGrammar = () => loadedMomentGrammar ?? (loadedMomentGrammar = loadGram
|
|
|
58059
58074
|
"arguments": []
|
|
58060
58075
|
}
|
|
58061
58076
|
},
|
|
58077
|
+
{
|
|
58078
|
+
"$type": "Group",
|
|
58079
|
+
"elements": [
|
|
58080
|
+
{
|
|
58081
|
+
"$type": "Keyword",
|
|
58082
|
+
"value": "when"
|
|
58083
|
+
},
|
|
58084
|
+
{
|
|
58085
|
+
"$type": "Assignment",
|
|
58086
|
+
"feature": "conditionField",
|
|
58087
|
+
"operator": "=",
|
|
58088
|
+
"terminal": {
|
|
58089
|
+
"$type": "RuleCall",
|
|
58090
|
+
"rule": {
|
|
58091
|
+
"$ref": "#/rules@50"
|
|
58092
|
+
},
|
|
58093
|
+
"arguments": []
|
|
58094
|
+
}
|
|
58095
|
+
},
|
|
58096
|
+
{
|
|
58097
|
+
"$type": "Keyword",
|
|
58098
|
+
"value": "="
|
|
58099
|
+
},
|
|
58100
|
+
{
|
|
58101
|
+
"$type": "Assignment",
|
|
58102
|
+
"feature": "conditionValue",
|
|
58103
|
+
"operator": "=",
|
|
58104
|
+
"terminal": {
|
|
58105
|
+
"$type": "RuleCall",
|
|
58106
|
+
"rule": {
|
|
58107
|
+
"$ref": "#/rules@10"
|
|
58108
|
+
},
|
|
58109
|
+
"arguments": []
|
|
58110
|
+
}
|
|
58111
|
+
}
|
|
58112
|
+
],
|
|
58113
|
+
"cardinality": "?"
|
|
58114
|
+
},
|
|
58115
|
+
{
|
|
58116
|
+
"$type": "Group",
|
|
58117
|
+
"elements": [
|
|
58118
|
+
{
|
|
58119
|
+
"$type": "Keyword",
|
|
58120
|
+
"value": "after"
|
|
58121
|
+
},
|
|
58122
|
+
{
|
|
58123
|
+
"$type": "Assignment",
|
|
58124
|
+
"feature": "conditionAfter",
|
|
58125
|
+
"operator": "=",
|
|
58126
|
+
"terminal": {
|
|
58127
|
+
"$type": "RuleCall",
|
|
58128
|
+
"rule": {
|
|
58129
|
+
"$ref": "#/rules@56"
|
|
58130
|
+
},
|
|
58131
|
+
"arguments": []
|
|
58132
|
+
}
|
|
58133
|
+
}
|
|
58134
|
+
],
|
|
58135
|
+
"cardinality": "?"
|
|
58136
|
+
},
|
|
58062
58137
|
{
|
|
58063
58138
|
"$type": "Keyword",
|
|
58064
58139
|
"value": "action"
|
|
@@ -59218,6 +59293,14 @@ var MomentGrammar = () => loadedMomentGrammar ?? (loadedMomentGrammar = loadGram
|
|
|
59218
59293
|
{
|
|
59219
59294
|
"$type": "Keyword",
|
|
59220
59295
|
"value": "note"
|
|
59296
|
+
},
|
|
59297
|
+
{
|
|
59298
|
+
"$type": "Keyword",
|
|
59299
|
+
"value": "outcome"
|
|
59300
|
+
},
|
|
59301
|
+
{
|
|
59302
|
+
"$type": "Keyword",
|
|
59303
|
+
"value": "after"
|
|
59221
59304
|
}
|
|
59222
59305
|
]
|
|
59223
59306
|
},
|
|
@@ -59324,6 +59407,10 @@ var MomentGrammar = () => loadedMomentGrammar ?? (loadedMomentGrammar = loadGram
|
|
|
59324
59407
|
{
|
|
59325
59408
|
"$type": "Keyword",
|
|
59326
59409
|
"value": "terminal"
|
|
59410
|
+
},
|
|
59411
|
+
{
|
|
59412
|
+
"$type": "Keyword",
|
|
59413
|
+
"value": "outcome"
|
|
59327
59414
|
}
|
|
59328
59415
|
]
|
|
59329
59416
|
},
|
|
@@ -59765,6 +59852,14 @@ var MomentGrammar = () => loadedMomentGrammar ?? (loadedMomentGrammar = loadGram
|
|
|
59765
59852
|
{
|
|
59766
59853
|
"$type": "Keyword",
|
|
59767
59854
|
"value": "note"
|
|
59855
|
+
},
|
|
59856
|
+
{
|
|
59857
|
+
"$type": "Keyword",
|
|
59858
|
+
"value": "outcome"
|
|
59859
|
+
},
|
|
59860
|
+
{
|
|
59861
|
+
"$type": "Keyword",
|
|
59862
|
+
"value": "after"
|
|
59768
59863
|
}
|
|
59769
59864
|
]
|
|
59770
59865
|
},
|
|
@@ -60291,7 +60386,7 @@ var MomentValidator = class {
|
|
|
60291
60386
|
// those are alternative branch arms, not continuations.
|
|
60292
60387
|
// =========================================================================
|
|
60293
60388
|
checkTerminalIsLast(node, accept) {
|
|
60294
|
-
if (node
|
|
60389
|
+
if (!endsFlow(node))
|
|
60295
60390
|
return;
|
|
60296
60391
|
const container = node.$container;
|
|
60297
60392
|
const siblings = "nodes" in container ? container.nodes : [];
|
|
@@ -60762,6 +60857,10 @@ var MomentValidator = class {
|
|
|
60762
60857
|
return false;
|
|
60763
60858
|
}
|
|
60764
60859
|
};
|
|
60860
|
+
function endsFlow(node) {
|
|
60861
|
+
const type = node.modifier?.type;
|
|
60862
|
+
return type === "terminal" || type === "outcome";
|
|
60863
|
+
}
|
|
60765
60864
|
|
|
60766
60865
|
// ../core/dist/moment-module.js
|
|
60767
60866
|
var MomentModule = {
|
|
@@ -61045,6 +61144,76 @@ function validateMultiEvent(ir, options = {}) {
|
|
|
61045
61144
|
];
|
|
61046
61145
|
}
|
|
61047
61146
|
|
|
61147
|
+
// ../core/dist/validation/policy-condition.js
|
|
61148
|
+
function placedOrder(flow) {
|
|
61149
|
+
return flow.moments.flatMap((m) => [
|
|
61150
|
+
...m.contextEntries.map((e) => e.nodeName),
|
|
61151
|
+
...(m.branches ?? []).flatMap((b) => b.entries.map((e) => e.nodeName))
|
|
61152
|
+
]);
|
|
61153
|
+
}
|
|
61154
|
+
function someFlowPlacesBefore(flows, cause, trigger) {
|
|
61155
|
+
let triggerPlaced = false;
|
|
61156
|
+
for (const flow of flows) {
|
|
61157
|
+
const order = placedOrder(flow);
|
|
61158
|
+
const firstCause = order.indexOf(cause);
|
|
61159
|
+
const lastTrigger = order.lastIndexOf(trigger);
|
|
61160
|
+
if (lastTrigger >= 0)
|
|
61161
|
+
triggerPlaced = true;
|
|
61162
|
+
if (firstCause >= 0 && lastTrigger > firstCause)
|
|
61163
|
+
return { reached: true, triggerPlaced };
|
|
61164
|
+
}
|
|
61165
|
+
return { reached: false, triggerPlaced };
|
|
61166
|
+
}
|
|
61167
|
+
function fieldsByEvent(ir) {
|
|
61168
|
+
const events = /* @__PURE__ */ new Map();
|
|
61169
|
+
for (const ctx of ir.contexts)
|
|
61170
|
+
for (const e of ctx.events) {
|
|
61171
|
+
const fields = events.get(e.name) ?? /* @__PURE__ */ new Set();
|
|
61172
|
+
for (const f of e.fields ?? [])
|
|
61173
|
+
fields.add(f.name);
|
|
61174
|
+
events.set(e.name, fields);
|
|
61175
|
+
}
|
|
61176
|
+
return events;
|
|
61177
|
+
}
|
|
61178
|
+
function v49(p, events) {
|
|
61179
|
+
const c = p.condition;
|
|
61180
|
+
const fields = events.get(p.trigger);
|
|
61181
|
+
if (c?.field === void 0 || fields === void 0 || fields.has(c.field))
|
|
61182
|
+
return [];
|
|
61183
|
+
return [
|
|
61184
|
+
{
|
|
61185
|
+
ruleId: "V49",
|
|
61186
|
+
message: `Policy '${p.name}' reacts when '${c.field}' of '${p.trigger}' is '${c.equals ?? ""}', but '${p.trigger}' has no field '${c.field}'.`
|
|
61187
|
+
}
|
|
61188
|
+
];
|
|
61189
|
+
}
|
|
61190
|
+
function v50v51(p, events, flows) {
|
|
61191
|
+
const after = p.condition?.after;
|
|
61192
|
+
if (after === void 0)
|
|
61193
|
+
return [];
|
|
61194
|
+
if (!events.has(after))
|
|
61195
|
+
return [
|
|
61196
|
+
{
|
|
61197
|
+
ruleId: "V50",
|
|
61198
|
+
message: `Policy '${p.name}' reacts after '${after}', which is no declared event.`
|
|
61199
|
+
}
|
|
61200
|
+
];
|
|
61201
|
+
const { reached, triggerPlaced } = someFlowPlacesBefore(flows, after, p.trigger);
|
|
61202
|
+
if (!triggerPlaced || reached)
|
|
61203
|
+
return [];
|
|
61204
|
+
return [
|
|
61205
|
+
{
|
|
61206
|
+
ruleId: "V51",
|
|
61207
|
+
severity: "warning",
|
|
61208
|
+
message: `Policy '${p.name}' reacts to '${p.trigger}' after '${after}', but no flow places '${after}' before '${p.trigger}'; the condition is never met.`
|
|
61209
|
+
}
|
|
61210
|
+
];
|
|
61211
|
+
}
|
|
61212
|
+
function validatePolicyConditions(ir) {
|
|
61213
|
+
const events = fieldsByEvent(ir);
|
|
61214
|
+
return ir.contexts.flatMap((ctx) => ctx.policies.filter((p) => p.condition !== void 0).flatMap((p) => [...v49(p, events), ...v50v51(p, events, ir.flows ?? [])]));
|
|
61215
|
+
}
|
|
61216
|
+
|
|
61048
61217
|
// ../core/dist/validation/palette-conformance.js
|
|
61049
61218
|
function namesOf2(ir) {
|
|
61050
61219
|
const contexts = ir.contexts;
|
|
@@ -61298,6 +61467,7 @@ function validatePaletteConformance(ir, options = {}) {
|
|
|
61298
61467
|
...v41v42Placements(ir, commands),
|
|
61299
61468
|
...v43(ir),
|
|
61300
61469
|
...validateMultiEvent(ir, options),
|
|
61470
|
+
...validatePolicyConditions(ir),
|
|
61301
61471
|
...(ir.externals ?? []).flatMap((e) => gatewayFindings(`external '${e.name}'`, e.gateways ?? [], known))
|
|
61302
61472
|
];
|
|
61303
61473
|
}
|
|
@@ -61607,6 +61777,12 @@ function transformPolicy(pol, annotations) {
|
|
|
61607
61777
|
trigger: pol.trigger,
|
|
61608
61778
|
action: pol.action,
|
|
61609
61779
|
chainsTo: pol.chainsTo,
|
|
61780
|
+
...pol.conditionField !== void 0 || pol.conditionAfter !== void 0 ? {
|
|
61781
|
+
condition: {
|
|
61782
|
+
...pol.conditionField !== void 0 ? { field: pol.conditionField, equals: pol.conditionValue } : {},
|
|
61783
|
+
...pol.conditionAfter !== void 0 ? { after: pol.conditionAfter } : {}
|
|
61784
|
+
}
|
|
61785
|
+
} : {},
|
|
61610
61786
|
...gatewaysOf(pol.gateways)
|
|
61611
61787
|
};
|
|
61612
61788
|
}
|
|
@@ -61778,13 +61954,18 @@ function transformNodeToEntry(node, laneContextMap, nodeKindMap) {
|
|
|
61778
61954
|
if (node.cause !== void 0) {
|
|
61779
61955
|
entry.cause = node.cause;
|
|
61780
61956
|
}
|
|
61781
|
-
|
|
61957
|
+
applyModifier(entry, node.modifier?.type);
|
|
61958
|
+
return entry;
|
|
61959
|
+
}
|
|
61960
|
+
function applyModifier(entry, modifierType) {
|
|
61782
61961
|
if (modifierType === "optional") {
|
|
61783
61962
|
entry.optional = true;
|
|
61784
61963
|
} else if (modifierType === "terminal") {
|
|
61785
61964
|
entry.terminal = true;
|
|
61965
|
+
} else if (modifierType === "outcome") {
|
|
61966
|
+
entry.terminal = true;
|
|
61967
|
+
entry.exit = "outcome";
|
|
61786
61968
|
}
|
|
61787
|
-
return entry;
|
|
61788
61969
|
}
|
|
61789
61970
|
function extractConnections(flow, laneContextMap) {
|
|
61790
61971
|
const connections = [];
|
|
@@ -64829,6 +65010,7 @@ function multiEventPlacements(steps, commandOf) {
|
|
|
64829
65010
|
}
|
|
64830
65011
|
|
|
64831
65012
|
// ../derive/dist/engine/simulation-scenario-generator.js
|
|
65013
|
+
var BRANCH_KEY = "$branch";
|
|
64832
65014
|
function resolveNodeKind(nodeName, contextId, contextMap, declaredKind) {
|
|
64833
65015
|
const ctx = contextMap.get(contextId);
|
|
64834
65016
|
if (!ctx)
|
|
@@ -64934,14 +65116,16 @@ function resolveScenarioLabel(flow, reachedBranches) {
|
|
|
64934
65116
|
if (deviations.length === 0)
|
|
64935
65117
|
return `Happy Path: ${flow.name}`;
|
|
64936
65118
|
const bracket = deviations.map((b) => b.condition).join(", ");
|
|
64937
|
-
|
|
64938
|
-
return hasTerminalArm ? `Failure Path: ${flow.name} [${bracket}]` : `Variant: ${flow.name} [${bracket}]`;
|
|
65119
|
+
return endsAtFailureExit(deviations) ? `Failure Path: ${flow.name} [${bracket}]` : `Variant: ${flow.name} [${bracket}]`;
|
|
64939
65120
|
}
|
|
64940
65121
|
function resolveScenarioKind(reachedBranches) {
|
|
64941
65122
|
const deviations = reachedBranches.filter((b) => !b.isFirstArm);
|
|
64942
65123
|
if (deviations.length === 0)
|
|
64943
65124
|
return "happy";
|
|
64944
|
-
return deviations
|
|
65125
|
+
return endsAtFailureExit(deviations) ? "failure" : "variant";
|
|
65126
|
+
}
|
|
65127
|
+
function endsAtFailureExit(deviations) {
|
|
65128
|
+
return deviations.some((b) => b.armHasFailureExit);
|
|
64945
65129
|
}
|
|
64946
65130
|
function buildContextMap(ir) {
|
|
64947
65131
|
return new Map(ir.contexts.map((c) => [c.id, c]));
|
|
@@ -65021,6 +65205,10 @@ function selectBranch(moment, branchSelections, state) {
|
|
|
65021
65205
|
const branch = (selected ? branches.find((b) => b.condition === selected) : void 0) ?? branches[0];
|
|
65022
65206
|
return { branch, forced };
|
|
65023
65207
|
}
|
|
65208
|
+
function armEndsAtFailureExit(branch) {
|
|
65209
|
+
const exit = branch.entries.find((e) => e.terminal);
|
|
65210
|
+
return exit !== void 0 && exit.exit !== "outcome";
|
|
65211
|
+
}
|
|
65024
65212
|
function recordBranchPoint(state, moment, branch, branchIdx, forced) {
|
|
65025
65213
|
state.activations.push({ momentName: moment.name, condition: branch.condition });
|
|
65026
65214
|
if (!forced && !state.reachedNames.has(moment.name)) {
|
|
@@ -65029,7 +65217,7 @@ function recordBranchPoint(state, moment, branch, branchIdx, forced) {
|
|
|
65029
65217
|
momentName: moment.name,
|
|
65030
65218
|
condition: branch.condition,
|
|
65031
65219
|
isFirstArm: branchIdx === 0,
|
|
65032
|
-
|
|
65220
|
+
armHasFailureExit: armEndsAtFailureExit(branch)
|
|
65033
65221
|
});
|
|
65034
65222
|
}
|
|
65035
65223
|
}
|
|
@@ -65091,6 +65279,7 @@ function generateEvents(nodes, flow, contextMap, sessionId, correlationId, baseT
|
|
|
65091
65279
|
const eventIds = nodes.map((_, i) => `evt-${String(i + 1).padStart(3, "0")}`);
|
|
65092
65280
|
const placements2 = placementsOf(nodes, contextMap);
|
|
65093
65281
|
const commandOfEvent = new Map(placements2.flatMap((p) => p.events.map((k) => [k, p.command])));
|
|
65282
|
+
const conditioned = policyConditionedOccurrences(nodes, flow, contextMap);
|
|
65094
65283
|
for (let i = 0; i < nodes.length; i++) {
|
|
65095
65284
|
const node = nodes[i];
|
|
65096
65285
|
const recordedBy = commandOfEvent.get(i);
|
|
@@ -65100,6 +65289,7 @@ function generateEvents(nodes, flow, contextMap, sessionId, correlationId, baseT
|
|
|
65100
65289
|
const eventType = resolveEventType(node, effectiveKind);
|
|
65101
65290
|
const productSource = resolveProductSource(node, effectiveKind, contextMap);
|
|
65102
65291
|
const payload = buildPayload(node, effectiveKind, contextMap, flow);
|
|
65292
|
+
applyPolicyConditions(payload, i, node, conditioned, contextMap);
|
|
65103
65293
|
const whenState = placements2.find((p) => p.command === i)?.whenState;
|
|
65104
65294
|
if (whenState !== void 0)
|
|
65105
65295
|
payload.whenState = whenState;
|
|
@@ -65117,6 +65307,89 @@ function generateEvents(nodes, flow, contextMap, sessionId, correlationId, baseT
|
|
|
65117
65307
|
}
|
|
65118
65308
|
return events;
|
|
65119
65309
|
}
|
|
65310
|
+
function guardedPolicies(contextMap) {
|
|
65311
|
+
const byTrigger = /* @__PURE__ */ new Map();
|
|
65312
|
+
for (const ctx of contextMap.values())
|
|
65313
|
+
for (const policy of ctx.policies) {
|
|
65314
|
+
if (policy.condition?.field === void 0)
|
|
65315
|
+
continue;
|
|
65316
|
+
byTrigger.set(policy.trigger, [...byTrigger.get(policy.trigger) ?? [], policy]);
|
|
65317
|
+
}
|
|
65318
|
+
return byTrigger;
|
|
65319
|
+
}
|
|
65320
|
+
function policyConditionedOccurrences(nodes, flow, contextMap) {
|
|
65321
|
+
const guarded = guardedPolicies(contextMap);
|
|
65322
|
+
const named = /* @__PURE__ */ new Map();
|
|
65323
|
+
if (guarded.size === 0)
|
|
65324
|
+
return named;
|
|
65325
|
+
nodes.forEach((node, index) => {
|
|
65326
|
+
for (const conn of flow.connections) {
|
|
65327
|
+
if (!isCausationConnectionFor(conn, node))
|
|
65328
|
+
continue;
|
|
65329
|
+
const triggerName = conn.sourceNodeName ?? conn.eventId.replace(/^evt-/, "");
|
|
65330
|
+
const policies = (guarded.get(triggerName) ?? []).filter((p) => p.chainsTo === node.nodeName);
|
|
65331
|
+
if (policies.length === 0)
|
|
65332
|
+
continue;
|
|
65333
|
+
for (let j = index - 1; j >= 0; j--) {
|
|
65334
|
+
if (nodes[j].nodeName !== triggerName)
|
|
65335
|
+
continue;
|
|
65336
|
+
named.set(j, [...named.get(j) ?? [], ...policies]);
|
|
65337
|
+
break;
|
|
65338
|
+
}
|
|
65339
|
+
}
|
|
65340
|
+
});
|
|
65341
|
+
return named;
|
|
65342
|
+
}
|
|
65343
|
+
function typedValue(type, value) {
|
|
65344
|
+
if (type === "number" && value.trim() !== "" && !Number.isNaN(Number(value)))
|
|
65345
|
+
return Number(value);
|
|
65346
|
+
if (type === "boolean" && (value === "true" || value === "false"))
|
|
65347
|
+
return value === "true";
|
|
65348
|
+
return value;
|
|
65349
|
+
}
|
|
65350
|
+
function otherThan(value) {
|
|
65351
|
+
if (typeof value === "number")
|
|
65352
|
+
return value + 1;
|
|
65353
|
+
if (typeof value === "boolean")
|
|
65354
|
+
return !value;
|
|
65355
|
+
return `${String(value)}-other`;
|
|
65356
|
+
}
|
|
65357
|
+
function guardedField(policy, payload) {
|
|
65358
|
+
const field = policy.condition?.field;
|
|
65359
|
+
return field !== void 0 && field in payload ? field : void 0;
|
|
65360
|
+
}
|
|
65361
|
+
function declaredValue(evt, policy) {
|
|
65362
|
+
const field = policy.condition?.field ?? "";
|
|
65363
|
+
const type = evt.fields.find((f) => f.name === field)?.type ?? "";
|
|
65364
|
+
return typedValue(type, policy.condition?.equals ?? "");
|
|
65365
|
+
}
|
|
65366
|
+
function moveOffDeclared(payload, guarded, evt, fixed) {
|
|
65367
|
+
for (const policy of guarded) {
|
|
65368
|
+
const field = guardedField(policy, payload);
|
|
65369
|
+
if (field === void 0 || fixed.has(field))
|
|
65370
|
+
continue;
|
|
65371
|
+
const declared = declaredValue(evt, policy);
|
|
65372
|
+
if (payload[field] === declared)
|
|
65373
|
+
payload[field] = otherThan(declared);
|
|
65374
|
+
}
|
|
65375
|
+
}
|
|
65376
|
+
function applyPolicyConditions(payload, index, node, conditioned, contextMap) {
|
|
65377
|
+
const ctx = contextMap.get(node.contextId);
|
|
65378
|
+
const evt = ctx ? findEvent(ctx, node.nodeName) : void 0;
|
|
65379
|
+
if (!evt)
|
|
65380
|
+
return;
|
|
65381
|
+
const guarded = [...contextMap.values()].flatMap((c) => c.policies.filter((p) => p.trigger === node.nodeName && p.condition?.field !== void 0));
|
|
65382
|
+
const naming = conditioned.get(index) ?? [];
|
|
65383
|
+
const fixed = /* @__PURE__ */ new Set();
|
|
65384
|
+
for (const policy of guarded.filter((p) => naming.includes(p))) {
|
|
65385
|
+
const field = guardedField(policy, payload);
|
|
65386
|
+
if (field === void 0 || fixed.has(field))
|
|
65387
|
+
continue;
|
|
65388
|
+
payload[field] = declaredValue(evt, policy);
|
|
65389
|
+
fixed.add(field);
|
|
65390
|
+
}
|
|
65391
|
+
moveOffDeclared(payload, guarded, evt, fixed);
|
|
65392
|
+
}
|
|
65120
65393
|
function findCausationEvents(node, allNodes, flow, eventIds, currentIndex, recordedBy) {
|
|
65121
65394
|
const causation = [];
|
|
65122
65395
|
for (const conn of flow.connections) {
|
|
@@ -65193,11 +65466,16 @@ function buildPayload(node, effectiveKind, contextMap, flow) {
|
|
|
65193
65466
|
}
|
|
65194
65467
|
}
|
|
65195
65468
|
addContractFields(payload, node, flow);
|
|
65196
|
-
|
|
65197
|
-
payload.outcome = node.outcome;
|
|
65198
|
-
}
|
|
65469
|
+
stampBranch(payload, node);
|
|
65199
65470
|
return payload;
|
|
65200
65471
|
}
|
|
65472
|
+
function stampBranch(payload, node) {
|
|
65473
|
+
if (node.outcome === void 0)
|
|
65474
|
+
return;
|
|
65475
|
+
payload[BRANCH_KEY] = node.outcome;
|
|
65476
|
+
if (!("outcome" in payload))
|
|
65477
|
+
payload.outcome = node.outcome;
|
|
65478
|
+
}
|
|
65201
65479
|
function addContractFields(payload, node, flow) {
|
|
65202
65480
|
for (const conn of flow.connections) {
|
|
65203
65481
|
if (conn.connectionType !== "crosses-to")
|
|
@@ -65278,23 +65556,40 @@ function findEventAfter(events, eventType, afterIndex) {
|
|
|
65278
65556
|
function deriveNegativeScenarios(ir, flow, options) {
|
|
65279
65557
|
const contextMap = buildContextMap(ir);
|
|
65280
65558
|
const opts = resolveOptions(flow, options);
|
|
65281
|
-
const walk = walkPath(flow, opts.branchSelections);
|
|
65282
|
-
const nodes = walk.nodes;
|
|
65283
65559
|
const scenarios = [];
|
|
65284
65560
|
const usedIds = /* @__PURE__ */ new Set();
|
|
65285
|
-
|
|
65286
|
-
|
|
65287
|
-
const
|
|
65288
|
-
|
|
65289
|
-
|
|
65290
|
-
|
|
65291
|
-
|
|
65292
|
-
|
|
65293
|
-
const
|
|
65294
|
-
|
|
65295
|
-
|
|
65296
|
-
|
|
65561
|
+
const covered = /* @__PURE__ */ new Set();
|
|
65562
|
+
const deriveOnPath = (walk, onlyUncovered) => {
|
|
65563
|
+
const nodes = walk.nodes;
|
|
65564
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
65565
|
+
const node = nodes[i];
|
|
65566
|
+
const kind = resolveNodeKind(node.nodeName, node.contextId, contextMap, node.nodeKind);
|
|
65567
|
+
if (kind !== "command")
|
|
65568
|
+
continue;
|
|
65569
|
+
for (const pre of findPreconditions(node, contextMap)) {
|
|
65570
|
+
const key = [node.nodeName, pre.name, node.cause ?? ""].join("\0");
|
|
65571
|
+
if (onlyUncovered && covered.has(key))
|
|
65572
|
+
continue;
|
|
65573
|
+
covered.add(key);
|
|
65574
|
+
const baseId = `${opts.scenarioId}-neg-${node.nodeName}-${pre.name}`;
|
|
65575
|
+
const scenarioId = usedIds.has(baseId) ? `${baseId}-${i}` : baseId;
|
|
65576
|
+
usedIds.add(scenarioId);
|
|
65577
|
+
usedIds.add(baseId);
|
|
65578
|
+
scenarios.push(buildNegativeScenario(ir, flow, walk, i, pre, contextMap, opts, scenarioId));
|
|
65579
|
+
}
|
|
65297
65580
|
}
|
|
65581
|
+
};
|
|
65582
|
+
deriveOnPath(walkPath(flow, opts.branchSelections), false);
|
|
65583
|
+
if (options?.branchSelections !== void 0)
|
|
65584
|
+
return scenarios;
|
|
65585
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
65586
|
+
for (const selections of enumerateBranchCombinations(flow)) {
|
|
65587
|
+
const walk = walkPath(flow, selections);
|
|
65588
|
+
const pathKey = walk.nodes.map((n) => n.nodeId).join("|");
|
|
65589
|
+
if (seenPaths.has(pathKey))
|
|
65590
|
+
continue;
|
|
65591
|
+
seenPaths.add(pathKey);
|
|
65592
|
+
deriveOnPath(walk, true);
|
|
65298
65593
|
}
|
|
65299
65594
|
return scenarios;
|
|
65300
65595
|
}
|
|
@@ -65560,7 +65855,8 @@ function generatePolicyDefinitions(ir) {
|
|
|
65560
65855
|
contextId: context.id,
|
|
65561
65856
|
trigger: policy.trigger,
|
|
65562
65857
|
...policy.action ? { actionDescription: policy.action } : {},
|
|
65563
|
-
chainsTo: normalizeChainsTo(policy.chainsTo)
|
|
65858
|
+
chainsTo: normalizeChainsTo(policy.chainsTo),
|
|
65859
|
+
...policy.condition ? { condition: { ...policy.condition } } : {}
|
|
65564
65860
|
});
|
|
65565
65861
|
}
|
|
65566
65862
|
}
|
|
@@ -66253,46 +66549,51 @@ function findProcess(nodeName, ctx) {
|
|
|
66253
66549
|
return null;
|
|
66254
66550
|
}
|
|
66255
66551
|
function buildConnections(flow) {
|
|
66256
|
-
return flow.connections.map((conn) => {
|
|
66257
|
-
|
|
66258
|
-
|
|
66259
|
-
|
|
66260
|
-
|
|
66261
|
-
|
|
66262
|
-
|
|
66263
|
-
|
|
66264
|
-
|
|
66265
|
-
|
|
66266
|
-
|
|
66267
|
-
|
|
66268
|
-
|
|
66269
|
-
|
|
66270
|
-
|
|
66271
|
-
};
|
|
66272
|
-
}
|
|
66552
|
+
return flow.connections.map((conn) => ({
|
|
66553
|
+
...buildConnection(conn),
|
|
66554
|
+
// ADR-044: the IR already states which arm declared the connection.
|
|
66555
|
+
...conn.branchCondition !== void 0 ? { branchCondition: conn.branchCondition } : {}
|
|
66556
|
+
}));
|
|
66557
|
+
}
|
|
66558
|
+
function buildConnection(conn) {
|
|
66559
|
+
const eventType = conn.eventId.replace(/^evt-/, "");
|
|
66560
|
+
const endpoints = {
|
|
66561
|
+
eventType,
|
|
66562
|
+
sourceNodeName: conn.sourceNodeName,
|
|
66563
|
+
targetNodeName: conn.targetNodeName
|
|
66564
|
+
};
|
|
66565
|
+
if (conn.connectionType === "returns-to") {
|
|
66566
|
+
if (conn.targetMomentId) {
|
|
66273
66567
|
return {
|
|
66274
66568
|
from: conn.sourceMomentId,
|
|
66275
|
-
to: conn.
|
|
66276
|
-
label: `unresolved returns-to target: ${conn.targetMomentLabel ?? "(unknown)"}`,
|
|
66569
|
+
to: conn.targetMomentId,
|
|
66277
66570
|
style: "return",
|
|
66278
66571
|
targetMomentLabel: conn.targetMomentLabel,
|
|
66279
66572
|
...endpoints
|
|
66280
66573
|
};
|
|
66281
66574
|
}
|
|
66282
|
-
const isCrossing2 = conn.connectionType === "crosses-to";
|
|
66283
66575
|
return {
|
|
66284
66576
|
from: conn.sourceMomentId,
|
|
66285
|
-
// For 'triggers' the core now resolves targetContextId to the context
|
|
66286
|
-
// where the TARGET node is placed (not the source's own lane).
|
|
66287
66577
|
to: conn.targetContextId,
|
|
66288
|
-
label:
|
|
66289
|
-
style:
|
|
66290
|
-
|
|
66291
|
-
relationship: isCrossing2 ? conn.schemaContract.relationshipType : void 0,
|
|
66292
|
-
schemaContract: isCrossing2 ? mapSchemaContract(conn) : void 0,
|
|
66578
|
+
label: `unresolved returns-to target: ${conn.targetMomentLabel ?? "(unknown)"}`,
|
|
66579
|
+
style: "return",
|
|
66580
|
+
targetMomentLabel: conn.targetMomentLabel,
|
|
66293
66581
|
...endpoints
|
|
66294
66582
|
};
|
|
66295
|
-
}
|
|
66583
|
+
}
|
|
66584
|
+
const isCrossing2 = conn.connectionType === "crosses-to";
|
|
66585
|
+
return {
|
|
66586
|
+
from: conn.sourceMomentId,
|
|
66587
|
+
// For 'triggers' the core now resolves targetContextId to the context
|
|
66588
|
+
// where the TARGET node is placed (not the source's own lane).
|
|
66589
|
+
to: conn.targetContextId,
|
|
66590
|
+
label: isCrossing2 ? eventType : void 0,
|
|
66591
|
+
style: mapConnectionStyle(conn),
|
|
66592
|
+
crossBoundary: isCrossing2 || void 0,
|
|
66593
|
+
relationship: isCrossing2 ? conn.schemaContract.relationshipType : void 0,
|
|
66594
|
+
schemaContract: isCrossing2 ? mapSchemaContract(conn) : void 0,
|
|
66595
|
+
...endpoints
|
|
66596
|
+
};
|
|
66296
66597
|
}
|
|
66297
66598
|
function mapConnectionStyle(conn) {
|
|
66298
66599
|
if (conn.connectionType === "crosses-to")
|
|
@@ -66369,7 +66670,7 @@ function buildBranchPredicates(flow) {
|
|
|
66369
66670
|
routes[branch.condition] = branch.condition;
|
|
66370
66671
|
}
|
|
66371
66672
|
predicates[moment.id] = {
|
|
66372
|
-
field:
|
|
66673
|
+
field: BRANCH_KEY,
|
|
66373
66674
|
defaultRoute: moment.branches[0].condition,
|
|
66374
66675
|
routes
|
|
66375
66676
|
};
|
|
@@ -66565,12 +66866,16 @@ function renderNoteOnlyMoment(lines, moment, flow) {
|
|
|
66565
66866
|
lines.push(...noteComments(moment, flow, " "));
|
|
66566
66867
|
lines.push("");
|
|
66567
66868
|
}
|
|
66869
|
+
function armEndsAtOutcome(branchEntries) {
|
|
66870
|
+
return branchEntries.find((e) => e.terminal)?.exit === "outcome";
|
|
66871
|
+
}
|
|
66568
66872
|
function renderTerminalBranchScenario(lines, moment, condition, branchEntries, flow, ctxMap, ir) {
|
|
66569
|
-
const
|
|
66873
|
+
const endsAtOutcome = armEndsAtOutcome(branchEntries);
|
|
66874
|
+
const tags = ["@terminal", endsAtOutcome ? "@alt-path" : "@failure-path"];
|
|
66570
66875
|
lines.push(` ${tags.join(" ")}`);
|
|
66571
66876
|
lines.push(` Scenario: ${moment.name} [${condition}]`);
|
|
66572
66877
|
lines.push(...noteComments(moment, flow, " "));
|
|
66573
|
-
const failedPrecondition = findFailedPrecondition(moment, ctxMap);
|
|
66878
|
+
const failedPrecondition = endsAtOutcome ? void 0 : findFailedPrecondition(moment, ctxMap);
|
|
66574
66879
|
lines.push(` Given the ${moment.name.toLowerCase()} is evaluated`);
|
|
66575
66880
|
if (failedPrecondition) {
|
|
66576
66881
|
lines.push(` When ${failedPrecondition.name} is not satisfied`);
|
|
@@ -66585,7 +66890,8 @@ function renderTerminalBranchScenario(lines, moment, condition, branchEntries, f
|
|
|
66585
66890
|
lines.push(` Then the flow terminates because ${failedPrecondition.description}`);
|
|
66586
66891
|
} else {
|
|
66587
66892
|
const terminalNode = branchEntries.find((e) => e.terminal)?.nodeName;
|
|
66588
|
-
|
|
66893
|
+
const verb = endsAtOutcome ? "ends" : "terminates";
|
|
66894
|
+
lines.push(` Then the flow ${verb}${terminalNode ? ` at ${terminalNode}` : ""}`);
|
|
66589
66895
|
}
|
|
66590
66896
|
const compensation = findCompensationForMoment(moment, ir);
|
|
66591
66897
|
if (compensation) {
|
|
@@ -66714,7 +67020,7 @@ function readOrEmit(entry) {
|
|
|
66714
67020
|
return "emits";
|
|
66715
67021
|
}
|
|
66716
67022
|
function renderInternalEventStep(lines, entry, evt, ctxName) {
|
|
66717
|
-
const modifier = entry.optional ? " (optional)" : entry.terminal ? " (terminal)" : "";
|
|
67023
|
+
const modifier = entry.optional ? " (optional)" : entry.terminal ? entry.exit === "outcome" ? " (outcome)" : " (terminal)" : "";
|
|
66718
67024
|
lines.push(` Then ${ctxName} ${readOrEmit(entry)} ${entry.nodeName}${modifier}`);
|
|
66719
67025
|
if (evt && evt.fields.length > 0) {
|
|
66720
67026
|
lines.push(` carrying ${evt.fields.map((f) => f.name).join(", ")}`);
|
|
@@ -67221,8 +67527,10 @@ var SpecificationDocumentGenerator = class {
|
|
|
67221
67527
|
}
|
|
67222
67528
|
renderTerminalBranch(lines, moment, branch, flow, ir) {
|
|
67223
67529
|
const usedConnections = /* @__PURE__ */ new Set();
|
|
67224
|
-
const
|
|
67225
|
-
|
|
67530
|
+
const exit = branch.entries.find((e) => e.terminal);
|
|
67531
|
+
const terminalNode = exit?.nodeName;
|
|
67532
|
+
const [mark, verb] = exit?.exit === "outcome" ? ["\u2705", "ends"] : ["\u274C", "terminates"];
|
|
67533
|
+
lines.push(` - ${mark} **If ${branch.condition}:** flow ${verb}${terminalNode ? ` at **${terminalNode}**` : ""}`);
|
|
67226
67534
|
for (const entry of branch.entries) {
|
|
67227
67535
|
if (entry.terminal)
|
|
67228
67536
|
continue;
|
|
@@ -67548,8 +67856,11 @@ var SpecificationDocumentGenerator = class {
|
|
|
67548
67856
|
}
|
|
67549
67857
|
renderBranchAltBlock(lines, moment, ctxName, flow, ir) {
|
|
67550
67858
|
const nonTerminal = moment.branches.filter((b) => !b.entries.some((e) => e.terminal));
|
|
67551
|
-
const
|
|
67552
|
-
|
|
67859
|
+
const ending = moment.branches.filter((b) => b.entries.some((e) => e.terminal));
|
|
67860
|
+
const isOutcome = (b) => b.entries.find((e) => e.terminal)?.exit === "outcome";
|
|
67861
|
+
const terminal = ending.filter((b) => !isOutcome(b));
|
|
67862
|
+
const outcome = ending.filter(isOutcome);
|
|
67863
|
+
if (nonTerminal.length === 0 && ending.length === 0)
|
|
67553
67864
|
return;
|
|
67554
67865
|
for (let i = 0; i < nonTerminal.length; i++) {
|
|
67555
67866
|
const branch = nonTerminal[i];
|
|
@@ -67557,11 +67868,16 @@ var SpecificationDocumentGenerator = class {
|
|
|
67557
67868
|
lines.push(` ${keyword} ${branch.condition}`);
|
|
67558
67869
|
this.renderSequenceEntries(lines, branch.entries, moment, branch.condition, flow, ir);
|
|
67559
67870
|
}
|
|
67560
|
-
|
|
67561
|
-
|
|
67562
|
-
|
|
67563
|
-
|
|
67564
|
-
|
|
67871
|
+
let opened = nonTerminal.length > 0;
|
|
67872
|
+
for (const [arms, note] of [
|
|
67873
|
+
[terminal, "Flow terminates"],
|
|
67874
|
+
[outcome, "Flow ends at an outcome"]
|
|
67875
|
+
]) {
|
|
67876
|
+
if (arms.length === 0)
|
|
67877
|
+
continue;
|
|
67878
|
+
lines.push(` ${opened ? "else" : "alt"} ${arms.map((b) => b.condition).join(" / ")}`);
|
|
67879
|
+
lines.push(` Note over ${ctxName}: ${note}`);
|
|
67880
|
+
opened = true;
|
|
67565
67881
|
}
|
|
67566
67882
|
lines.push(" end");
|
|
67567
67883
|
}
|