@usearazzo/runner 1.0.1-alpha.20 → 1.0.1-alpha.21

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/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.0.1-alpha.21](https://github.com/usearazzo/arazzo-toolkit/compare/v1.0.1-alpha.20...v1.0.1-alpha.21) (2026-11-03)
7
+
8
+ ### Features
9
+
10
+ - **runner:** record criterion outcomes in step run records ([#302](https://github.com/usearazzo/arazzo-toolkit/issues/302)) ([513516b](https://github.com/usearazzo/arazzo-toolkit/commit/513516b80fc7edecae2d3fce74a53e000a494982)), closes [#231](https://github.com/usearazzo/arazzo-toolkit/issues/231)
11
+
12
+ ### BREAKING CHANGES
13
+
14
+ - **runner:** CriterionEvaluator.evaluate returns a CriterionOutcome
15
+ ({ met, error? }) instead of a boolean. StepExecutor.evaluateCriteria
16
+ returns CriterionEvaluationRecord[] instead of a boolean, and
17
+ StepExecutor.selectActions returns { matchedActions, actionCriteria }
18
+ instead of the action list. CriterionPredicate gains a second `action`
19
+ argument and is called for every criterion of an action. StepRunRecord
20
+ and StepExecutionResult gain required `successCriteria` and
21
+ `actionCriteria` fields. Any error a criterion throws other than an
22
+ unevaluable condition, such as a malformed criterion, now aborts the run
23
+ even after an earlier unmet criterion.
24
+
6
25
  ## [1.0.1-alpha.20](https://github.com/usearazzo/arazzo-toolkit/compare/v1.0.1-alpha.19...v1.0.1-alpha.20) (2026-11-01)
7
26
 
8
27
  ### Bug Fixes
package/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  An Arazzo document describes a multi-step API workflow: which operations to call, in what order, what to pass from one step to the next, and what counts as success. This package runs it.
22
22
 
23
- It loads the workflow and the OpenAPI documents its source descriptions point at. For each step it builds a real HTTP request, sends it to the live API, checks the step's success criteria against the response, and follows the control flow the document declares. When the run ends, you get the workflow's outputs and a trace of every step: whether it passed, which action was picked, how many attempts it took, and how long it ran.
23
+ It loads the workflow and the OpenAPI documents its source descriptions point at. For each step it builds a real HTTP request, sends it to the live API, checks the step's success criteria against the response, and follows the control flow the document declares. When the run ends, you get the workflow's outputs and a trace of every step: whether it passed, which action was picked, how many attempts it took, how long it ran, and the outcome of each criterion it evaluated.
24
24
 
25
25
  Use it to test an API flow end to end in CI, to drive a workflow from your own service, or to let an agent run a workflow instead of improvising the calls. It handles:
26
26
 
@@ -44,7 +44,7 @@ A runner is four building blocks, composed bottom-up; `ArazzoRunner` composes th
44
44
  <img alt="Runner architecture: WorkflowExecutor runs steps through StepExecutor, which runs OpenAPI operations through OpenAPIOperationExecutor and the HTTPClient; DocumentRegistry supplies documents to all three executors" src="https://raw.githubusercontent.com/usearazzo/arazzo-toolkit/main/packages/runner/assets/architecture.svg">
45
45
  </p>
46
46
 
47
- A step whose criteria go unmet is a result, not an error: the run resolves with `status: 'failed'`. A criterion whose condition cannot be evaluated (an invalid regex, JSONPath, XPath or simple condition, or non-XML data under an `xpath` query) counts as unmet, as Arazzo 1.1.0 requires, rather than throwing. The type-specific criterion evaluators raise such a condition as `CriterionEvaluationError`, a `CriterionError` subclass, and every `CriterionError` carries a `reason` from `CriterionErrorReason`. Only a document that cannot be loaded or run as written, a request that cannot be built or sent, or a cancelled run throws, and every such error extends `ArazzoRunnerError`; a document that cannot be read or loaded (a missing file, an HTTP error, an unresolvable reference) throws `DocumentLoadError` with the underlying failure as its `cause`.
47
+ A step whose criteria go unmet is a result, not an error: the run resolves with `status: 'failed'`. A criterion whose condition cannot be evaluated (an invalid regex, JSONPath, XPath or simple condition, or non-XML data under an `xpath` query) counts as unmet, as Arazzo 1.1.0 requires, rather than throwing. So does a criterion of a step that calls a workflow when it reads `$statusCode`, `$url`, `$method`, `$request` or `$response`: that step made no HTTP call. Each step record's `successCriteria` and `actionCriteria` list every criterion its last attempt evaluated, as a `CriterionEvaluationRecord` with the condition, whether it was met, the action's name for an action criterion and, when it could not be evaluated, a `diagnostic` with a `code` and `message`, never request or response data. The type-specific criterion evaluators raise an unevaluable condition as `CriterionEvaluationError`, a `CriterionError` subclass, and every `CriterionError` carries a `reason` from `CriterionErrorReason`. Only a document that cannot be loaded or run as written, a request that cannot be built or sent, or a cancelled run throws, and every such error extends `ArazzoRunnerError`; a document that cannot be read or loaded (a missing file, an HTTP error, an unresolvable reference) throws `DocumentLoadError` with the underlying failure as its `cause`.
48
48
 
49
49
  ## Installation
50
50
 
@@ -8960,10 +8960,11 @@ __webpack_require__.r(__webpack_exports__);
8960
8960
 
8961
8961
 
8962
8962
  /**
8963
- * Determines whether a single criterion is met.
8963
+ * Determines whether a single criterion of an action is met. Receives the
8964
+ * action declaring the criterion, so a caller can attribute the outcome to it.
8964
8965
  *
8965
8966
  * Bridged to a criterion evaluator
8966
- * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve)`); an
8967
+ * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve).met`); an
8967
8968
  * unresolvable/failing criterion is `false`, not an error.
8968
8969
  * @public
8969
8970
  */
@@ -9095,6 +9096,7 @@ class ActionResolver {
9095
9096
  reason: 'malformed-criteria'
9096
9097
  });
9097
9098
  }
9099
+ let met = true;
9098
9100
  for (const criterion of criteria) {
9099
9101
  if (!(0,_speclynx_apidom_ns_arazzo_1__WEBPACK_IMPORTED_MODULE_1__.isCriterionElement)(criterion)) {
9100
9102
  throw new _errors_ResolverError_ts__WEBPACK_IMPORTED_MODULE_2__["default"]("An action's `criteria` contains an entry that is not a Criterion Object", {
@@ -9103,9 +9105,11 @@ class ActionResolver {
9103
9105
  reason: 'malformed-criterion'
9104
9106
  });
9105
9107
  }
9106
- if (!isCriterionMet(criterion)) return false;
9108
+ // every criterion is evaluated, not only up to the first unmet one, so
9109
+ // a predicate that records outcomes sees the whole list.
9110
+ if (!isCriterionMet(criterion, action)) met = false;
9107
9111
  }
9108
- return true;
9112
+ return met;
9109
9113
  }
9110
9114
  }
9111
9115
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ActionResolver);
@@ -10034,6 +10038,11 @@ __webpack_require__.r(__webpack_exports__);
10034
10038
  * @public
10035
10039
  */
10036
10040
 
10041
+ /**
10042
+ * The outcome of evaluating one criterion.
10043
+ * @public
10044
+ */
10045
+
10037
10046
  /**
10038
10047
  * Options for the CriterionEvaluator.
10039
10048
  *
@@ -10044,7 +10053,7 @@ __webpack_require__.r(__webpack_exports__);
10044
10053
  */
10045
10054
 
10046
10055
  /**
10047
- * Evaluates an Arazzo Criterion Object to a boolean.
10056
+ * Evaluates an Arazzo Criterion Object to a {@link CriterionOutcome}.
10048
10057
  *
10049
10058
  * Dispatches on the criterion's `type` (defaulting to `simple` when omitted):
10050
10059
  * - `simple` — evaluates the condition directly, resolving the runtime
@@ -10064,12 +10073,13 @@ __webpack_require__.r(__webpack_exports__);
10064
10073
  * the 1.1.0 rule to every document, which accepts more but never evaluates a
10065
10074
  * query under the wrong dialect.
10066
10075
  *
10067
- * A condition that cannot be evaluated fails the criterion (`false`), as
10076
+ * A condition that cannot be evaluated fails the criterion (`met: false`), as
10068
10077
  * Arazzo 1.1.0 requires: a syntax error in the condition, a context the
10069
10078
  * condition cannot apply to (non-XML data for `xpath`), or an XPath evaluation
10070
10079
  * error. The type-specific evaluators report these as a
10071
- * {@link CriterionEvaluationError}, which this facade absorbs; any other error
10072
- * they raise propagates. A criterion that is malformed as written still throws: a
10080
+ * {@link CriterionEvaluationError}, which this facade returns as the
10081
+ * outcome's `error` so the caller can report it; any other error they raise
10082
+ * propagates. A criterion that is malformed as written still throws: a
10073
10083
  * missing `condition`, an unknown or unreadable `type`, an unsupported
10074
10084
  * expression `version`, or a `context` that is missing or not a runtime
10075
10085
  * expression.
@@ -10093,7 +10103,8 @@ class CriterionEvaluator {
10093
10103
  }
10094
10104
 
10095
10105
  /**
10096
- * Evaluates a criterion element, returning whether the condition is met.
10106
+ * Evaluates a criterion element, returning whether the condition is met and,
10107
+ * when it cannot be evaluated, why.
10097
10108
  *
10098
10109
  * `resolve` turns a runtime expression into a value: for `simple` it resolves
10099
10110
  * the expressions embedded in the condition; for the other types it resolves
@@ -10115,23 +10126,28 @@ class CriterionEvaluator {
10115
10126
  }
10116
10127
  const type = this.#resolveType(criterion);
10117
10128
  this.#requireValidContext(criterion, type);
10129
+ let met;
10118
10130
  try {
10119
10131
  switch (type) {
10120
10132
  case 'simple':
10121
- return this.#simple.evaluate(condition, resolve);
10133
+ met = this.#simple.evaluate(condition, resolve);
10134
+ break;
10122
10135
  case 'regex':
10123
- return this.#regex.evaluate(condition, this.#resolveContext(criterion, type, resolve));
10136
+ met = this.#regex.evaluate(condition, this.#resolveContext(criterion, type, resolve));
10137
+ break;
10124
10138
  case 'jsonpath':
10125
10139
  // only rfc9535 is supported, Arazzo 1.1.0's default, so an omitted
10126
10140
  // version is accepted. draft-goessner has different semantics and is
10127
10141
  // rejected rather than mis-evaluated.
10128
10142
  this.#requireVersion(criterion, type, condition, 'rfc9535');
10129
- return this.#jsonpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
10143
+ met = this.#jsonpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
10144
+ break;
10130
10145
  case 'xpath':
10131
10146
  // only XPath 3.1 is supported; xpath-31 is Arazzo 1.1.0's default, so
10132
10147
  // an omitted version is accepted. Older versions are rejected.
10133
10148
  this.#requireVersion(criterion, type, condition, 'xpath-31');
10134
- return this.#xpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
10149
+ met = this.#xpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
10150
+ break;
10135
10151
  default:
10136
10152
  throw new _errors_CriterionError_ts__WEBPACK_IMPORTED_MODULE_4__["default"](`Unknown criterion type "${type}"`, {
10137
10153
  condition,
@@ -10142,9 +10158,15 @@ class CriterionEvaluator {
10142
10158
  } catch (error) {
10143
10159
  // Arazzo 1.1.0: a condition that cannot be evaluated MUST evaluate to fail.
10144
10160
  // The structural checks throw a plain CriterionError and still propagate.
10145
- if (error instanceof _errors_CriterionEvaluationError_ts__WEBPACK_IMPORTED_MODULE_5__["default"]) return false;
10161
+ if (error instanceof _errors_CriterionEvaluationError_ts__WEBPACK_IMPORTED_MODULE_5__["default"]) return {
10162
+ met: false,
10163
+ error
10164
+ };
10146
10165
  throw error;
10147
10166
  }
10167
+ return {
10168
+ met
10169
+ };
10148
10170
  }
10149
10171
 
10150
10172
  /**
@@ -10281,7 +10303,10 @@ class JSONPathCriterionEvaluator {
10281
10303
  return (0,_swaggerexpert_jsonpath__WEBPACK_IMPORTED_MODULE_0__.evaluate)(context, condition).length > 0;
10282
10304
  } catch (error) {
10283
10305
  if (error instanceof _swaggerexpert_jsonpath__WEBPACK_IMPORTED_MODULE_0__.JSONPathError) {
10284
- throw new _errors_CriterionEvaluationError_ts__WEBPACK_IMPORTED_MODULE_1__["default"](`Invalid jsonpath criterion condition "${condition}"`, {
10306
+ // a parse error describes the query only; an evaluation error ran
10307
+ // against the context, so its message is not surfaced.
10308
+ const detail = error instanceof _swaggerexpert_jsonpath__WEBPACK_IMPORTED_MODULE_0__.JSONPathParseError ? `: ${error.message}` : '';
10309
+ throw new _errors_CriterionEvaluationError_ts__WEBPACK_IMPORTED_MODULE_1__["default"](`Invalid jsonpath criterion condition "${condition}"${detail}`, {
10285
10310
  cause: error,
10286
10311
  condition,
10287
10312
  type: 'jsonpath',
@@ -10346,7 +10371,9 @@ class RegexCriterionEvaluator {
10346
10371
  try {
10347
10372
  regExp = new RegExp(condition);
10348
10373
  } catch (error) {
10349
- throw new _errors_CriterionEvaluationError_ts__WEBPACK_IMPORTED_MODULE_0__["default"](`Invalid regex criterion condition "${condition}"`, {
10374
+ // the engine has seen only the pattern, never the context, so its
10375
+ // message is safe to surface.
10376
+ throw new _errors_CriterionEvaluationError_ts__WEBPACK_IMPORTED_MODULE_0__["default"](`Invalid regex criterion condition "${condition}": ${error.message}`, {
10350
10377
  cause: error,
10351
10378
  condition,
10352
10379
  type: 'regex',
@@ -10486,6 +10513,9 @@ class XPathCriterionEvaluator {
10486
10513
  language: evaluateXPath.XPATH_3_1_LANGUAGE
10487
10514
  });
10488
10515
  } catch (error) {
10516
+ // no engine detail: the query has run against the context, and it can
10517
+ // put context values into its own error (a dynamic error, or fn:error
10518
+ // with a code and description of the query's choosing).
10489
10519
  throw new _errors_CriterionEvaluationError_ts__WEBPACK_IMPORTED_MODULE_2__["default"](`Invalid xpath criterion condition "${condition}"`, {
10490
10520
  cause: error,
10491
10521
  condition,
@@ -12300,6 +12330,12 @@ const STEP_TARGET_FIELDS = ['operationId', 'operationPath', 'workflowId'];
12300
12330
  * @public
12301
12331
  */
12302
12332
 
12333
+ /**
12334
+ * The outcome of one criterion a step evaluated: one of its `successCriteria`,
12335
+ * or one of the `criteria` of an action it considered.
12336
+ * @public
12337
+ */
12338
+
12303
12339
  /**
12304
12340
  * The outcome of executing a single step.
12305
12341
  * @public
@@ -12446,16 +12482,22 @@ class StepExecutor {
12446
12482
  // evaluate criteria, outputs, and the next action against the post-request
12447
12483
  // context (with $request / $url / $method and $response / $statusCode).
12448
12484
  const postContext = state.toContext(this.#requestContext(response), this.#responseContext(response));
12449
- const successful = this.evaluateCriteria(step, postContext);
12485
+ const successCriteria = this.evaluateCriteria(step, postContext);
12486
+ const successful = successCriteria.every(criterion => criterion.met);
12450
12487
  const outputs = this.#outputResolver.resolve(step.outputs, expression => this.#evaluate(postContext, expression), scope);
12451
- const matchedActions = this.selectActions(step, successful, postContext);
12488
+ const {
12489
+ matchedActions,
12490
+ actionCriteria
12491
+ } = this.selectActions(step, successful, postContext);
12452
12492
  return {
12453
12493
  stepId,
12454
12494
  response,
12455
12495
  successful,
12456
12496
  outputs,
12457
12497
  action: matchedActions[0],
12458
- matchedActions
12498
+ matchedActions,
12499
+ successCriteria,
12500
+ actionCriteria
12459
12501
  };
12460
12502
  }
12461
12503
 
@@ -12528,9 +12570,12 @@ class StepExecutor {
12528
12570
  }
12529
12571
 
12530
12572
  /**
12531
- * Evaluates the step's `successCriteria`; all criteria must pass. A step with
12532
- * no criteria succeeds on a received response. An unreadable
12533
- * `successCriteria` throws, see {@link StepExecutor.assertSuccessCriteria}.
12573
+ * Evaluates the step's `successCriteria`, returning one record per criterion
12574
+ * in list order; the step succeeds when every record is met. Every criterion
12575
+ * is evaluated, so the records explain each unmet one, not only the first. A
12576
+ * step with no criteria returns no records and succeeds on a received
12577
+ * response. An unreadable `successCriteria` throws, see
12578
+ * {@link StepExecutor.assertSuccessCriteria}.
12534
12579
  *
12535
12580
  * Public for the same reason as {@link StepExecutor.selectActions}: a step
12536
12581
  * targeting a `workflowId` is run by the workflow executor and never reaches
@@ -12540,15 +12585,16 @@ class StepExecutor {
12540
12585
  evaluateCriteria(step, context) {
12541
12586
  this.assertSuccessCriteria(step);
12542
12587
  const criteria = step.successCriteria;
12543
- if (criteria === undefined) return true;
12588
+ if (criteria === undefined) return [];
12544
12589
 
12545
12590
  // assertSuccessCriteria above guarantees every entry is a Criterion Object
12546
- return [...criteria].every(criterion => this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression)));
12591
+ return [...criteria].map(criterion => this.#evaluateCriterion(criterion, context));
12547
12592
  }
12548
12593
 
12549
12594
  /**
12550
12595
  * Selects every matching `onSuccess` / `onFailure` action for the outcome, in
12551
- * list order, gating each action's criteria against the context.
12596
+ * list order, gating each action's criteria against the context, and records
12597
+ * the outcome of every action criterion evaluated.
12552
12598
  *
12553
12599
  * The step's own list is the whole story here: a step that declares none of
12554
12600
  * its own already carries the workflow-level defaults, inherited by
@@ -12567,25 +12613,65 @@ class StepExecutor {
12567
12613
  * the expression context through this one method rather than wiring their own.
12568
12614
  */
12569
12615
  selectActions(step, successful, context) {
12570
- const isCriterionMet = criterion => {
12571
- try {
12572
- return this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression));
12573
- } catch (error) {
12574
- // an action's criteria decide whether it applies to this outcome, and
12575
- // actions are shared — inherited from the workflow, reused from
12576
- // components. A condition on an HTTP exchange cannot apply to a step
12577
- // that calls a workflow, so the action does not match; the run does not
12578
- // abort over a default written for the operation steps.
12579
- if (error instanceof _errors_RuntimeExpressionError_ts__WEBPACK_IMPORTED_MODULE_12__["default"] && error.reason === 'unavailable-expression') {
12580
- return false;
12581
- }
12582
- throw error;
12583
- }
12616
+ const actionCriteria = [];
12617
+ const isCriterionMet = (criterion, action) => {
12618
+ const record = {
12619
+ ...this.#evaluateCriterion(criterion, context),
12620
+ actionName: (0,_speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_0__["default"])(action.name)
12621
+ };
12622
+ actionCriteria.push(record);
12623
+ return record.met;
12584
12624
  };
12585
12625
  const scope = {
12586
12626
  stepId: (0,_speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_0__["default"])(step.stepId)
12587
12627
  };
12588
- return successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
12628
+ const matchedActions = successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
12629
+ return {
12630
+ matchedActions,
12631
+ actionCriteria
12632
+ };
12633
+ }
12634
+
12635
+ /**
12636
+ * Evaluates one criterion into a {@link CriterionEvaluationRecord}. A
12637
+ * condition that cannot be evaluated is unmet and records why; any other
12638
+ * error propagates.
12639
+ */
12640
+ #evaluateCriterion(criterion, context) {
12641
+ const condition = (0,_speclynx_apidom_core__WEBPACK_IMPORTED_MODULE_0__["default"])(criterion.condition);
12642
+ try {
12643
+ const {
12644
+ met,
12645
+ error
12646
+ } = this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression));
12647
+ if (error === undefined) return {
12648
+ condition,
12649
+ met
12650
+ };
12651
+ return {
12652
+ condition,
12653
+ met,
12654
+ diagnostic: {
12655
+ code: error.reason,
12656
+ message: error.message
12657
+ }
12658
+ };
12659
+ } catch (error) {
12660
+ // a step that calls a workflow made no HTTP call, so a condition on one
12661
+ // fails like any unevaluable condition; the diagnostic keeps the
12662
+ // authoring mistake visible.
12663
+ if (error instanceof _errors_RuntimeExpressionError_ts__WEBPACK_IMPORTED_MODULE_12__["default"] && error.reason === 'unavailable-expression') {
12664
+ return {
12665
+ condition,
12666
+ met: false,
12667
+ diagnostic: {
12668
+ code: error.reason,
12669
+ message: error.message
12670
+ }
12671
+ };
12672
+ }
12673
+ throw error;
12674
+ }
12589
12675
  }
12590
12676
 
12591
12677
  /**
@@ -13540,6 +13626,8 @@ class WorkflowExecutor {
13540
13626
  action,
13541
13627
  attempts,
13542
13628
  durationMs: this.#now() - stepStartedAt,
13629
+ successCriteria: outcome.successCriteria,
13630
+ actionCriteria: outcome.actionCriteria,
13543
13631
  ...(subWorkflows.length > 0 ? {
13544
13632
  subWorkflows
13545
13633
  } : {}),
@@ -14070,19 +14158,26 @@ class WorkflowExecutor {
14070
14158
  // apply on top — they are the author's assertion about this step, and
14071
14159
  // dropping them because the step happens to target a workflow would
14072
14160
  // silently discard it. They see the sub-run's own outputs (`{}` when it
14073
- // transferred) through `$outputs` and `$workflows`.
14161
+ // transferred) through `$outputs` and `$workflows`, and are evaluated
14162
+ // even when the sub-run failed, so the record explains them either way.
14074
14163
  // the criteria and actions are the *calling* step's, so they are
14075
14164
  // evaluated by the parent document's step executor — only the sub-run
14076
14165
  // itself switched documents.
14077
14166
  const stepExecutor = this.#stepExecutor.forDocument(document);
14078
- const successful = !this.#settledFailed(result) && stepExecutor.evaluateCriteria(step, context);
14079
- const matchedActions = stepExecutor.selectActions(step, successful, context);
14167
+ const successCriteria = stepExecutor.evaluateCriteria(step, context);
14168
+ const successful = !this.#settledFailed(result) && successCriteria.every(criterion => criterion.met);
14169
+ const {
14170
+ matchedActions,
14171
+ actionCriteria
14172
+ } = stepExecutor.selectActions(step, successful, context);
14080
14173
  return {
14081
14174
  stepId,
14082
14175
  successful,
14083
14176
  outputs,
14084
14177
  action: matchedActions[0],
14085
- matchedActions
14178
+ matchedActions,
14179
+ successCriteria,
14180
+ actionCriteria
14086
14181
  };
14087
14182
  };
14088
14183
  }