@usearazzo/runner 1.0.1-alpha.19 → 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.
@@ -37,6 +37,12 @@ export const STEP_TARGET_FIELDS = ['operationId', 'operationPath', 'workflowId']
37
37
  * @public
38
38
  */
39
39
 
40
+ /**
41
+ * The outcome of one criterion a step evaluated: one of its `successCriteria`,
42
+ * or one of the `criteria` of an action it considered.
43
+ * @public
44
+ */
45
+
40
46
  /**
41
47
  * The outcome of executing a single step.
42
48
  * @public
@@ -183,16 +189,22 @@ class StepExecutor {
183
189
  // evaluate criteria, outputs, and the next action against the post-request
184
190
  // context (with $request / $url / $method and $response / $statusCode).
185
191
  const postContext = state.toContext(this.#requestContext(response), this.#responseContext(response));
186
- const successful = this.evaluateCriteria(step, postContext);
192
+ const successCriteria = this.evaluateCriteria(step, postContext);
193
+ const successful = successCriteria.every(criterion => criterion.met);
187
194
  const outputs = this.#outputResolver.resolve(step.outputs, expression => this.#evaluate(postContext, expression), scope);
188
- const matchedActions = this.selectActions(step, successful, postContext);
195
+ const {
196
+ matchedActions,
197
+ actionCriteria
198
+ } = this.selectActions(step, successful, postContext);
189
199
  return {
190
200
  stepId,
191
201
  response,
192
202
  successful,
193
203
  outputs,
194
204
  action: matchedActions[0],
195
- matchedActions
205
+ matchedActions,
206
+ successCriteria,
207
+ actionCriteria
196
208
  };
197
209
  }
198
210
 
@@ -265,9 +277,12 @@ class StepExecutor {
265
277
  }
266
278
 
267
279
  /**
268
- * Evaluates the step's `successCriteria`; all criteria must pass. A step with
269
- * no criteria succeeds on a received response. An unreadable
270
- * `successCriteria` throws, see {@link StepExecutor.assertSuccessCriteria}.
280
+ * Evaluates the step's `successCriteria`, returning one record per criterion
281
+ * in list order; the step succeeds when every record is met. Every criterion
282
+ * is evaluated, so the records explain each unmet one, not only the first. A
283
+ * step with no criteria returns no records and succeeds on a received
284
+ * response. An unreadable `successCriteria` throws, see
285
+ * {@link StepExecutor.assertSuccessCriteria}.
271
286
  *
272
287
  * Public for the same reason as {@link StepExecutor.selectActions}: a step
273
288
  * targeting a `workflowId` is run by the workflow executor and never reaches
@@ -277,15 +292,16 @@ class StepExecutor {
277
292
  evaluateCriteria(step, context) {
278
293
  this.assertSuccessCriteria(step);
279
294
  const criteria = step.successCriteria;
280
- if (criteria === undefined) return true;
295
+ if (criteria === undefined) return [];
281
296
 
282
297
  // assertSuccessCriteria above guarantees every entry is a Criterion Object
283
- return [...criteria].every(criterion => this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression)));
298
+ return [...criteria].map(criterion => this.#evaluateCriterion(criterion, context));
284
299
  }
285
300
 
286
301
  /**
287
302
  * Selects every matching `onSuccess` / `onFailure` action for the outcome, in
288
- * list order, gating each action's criteria against the context.
303
+ * list order, gating each action's criteria against the context, and records
304
+ * the outcome of every action criterion evaluated.
289
305
  *
290
306
  * The step's own list is the whole story here: a step that declares none of
291
307
  * its own already carries the workflow-level defaults, inherited by
@@ -304,25 +320,65 @@ class StepExecutor {
304
320
  * the expression context through this one method rather than wiring their own.
305
321
  */
306
322
  selectActions(step, successful, context) {
307
- const isCriterionMet = criterion => {
308
- try {
309
- return this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression));
310
- } catch (error) {
311
- // an action's criteria decide whether it applies to this outcome, and
312
- // actions are shared — inherited from the workflow, reused from
313
- // components. A condition on an HTTP exchange cannot apply to a step
314
- // that calls a workflow, so the action does not match; the run does not
315
- // abort over a default written for the operation steps.
316
- if (error instanceof RuntimeExpressionError && error.reason === 'unavailable-expression') {
317
- return false;
318
- }
319
- throw error;
320
- }
323
+ const actionCriteria = [];
324
+ const isCriterionMet = (criterion, action) => {
325
+ const record = {
326
+ ...this.#evaluateCriterion(criterion, context),
327
+ actionName: toValue(action.name)
328
+ };
329
+ actionCriteria.push(record);
330
+ return record.met;
321
331
  };
322
332
  const scope = {
323
333
  stepId: toValue(step.stepId)
324
334
  };
325
- return successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
335
+ const matchedActions = successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
336
+ return {
337
+ matchedActions,
338
+ actionCriteria
339
+ };
340
+ }
341
+
342
+ /**
343
+ * Evaluates one criterion into a {@link CriterionEvaluationRecord}. A
344
+ * condition that cannot be evaluated is unmet and records why; any other
345
+ * error propagates.
346
+ */
347
+ #evaluateCriterion(criterion, context) {
348
+ const condition = toValue(criterion.condition);
349
+ try {
350
+ const {
351
+ met,
352
+ error
353
+ } = this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression));
354
+ if (error === undefined) return {
355
+ condition,
356
+ met
357
+ };
358
+ return {
359
+ condition,
360
+ met,
361
+ diagnostic: {
362
+ code: error.reason,
363
+ message: error.message
364
+ }
365
+ };
366
+ } catch (error) {
367
+ // a step that calls a workflow made no HTTP call, so a condition on one
368
+ // fails like any unevaluable condition; the diagnostic keeps the
369
+ // authoring mistake visible.
370
+ if (error instanceof RuntimeExpressionError && error.reason === 'unavailable-expression') {
371
+ return {
372
+ condition,
373
+ met: false,
374
+ diagnostic: {
375
+ code: error.reason,
376
+ message: error.message
377
+ }
378
+ };
379
+ }
380
+ throw error;
381
+ }
326
382
  }
327
383
 
328
384
  /**
@@ -359,6 +359,8 @@ class WorkflowExecutor {
359
359
  action,
360
360
  attempts,
361
361
  durationMs: this.#now() - stepStartedAt,
362
+ successCriteria: outcome.successCriteria,
363
+ actionCriteria: outcome.actionCriteria,
362
364
  ...(subWorkflows.length > 0 ? {
363
365
  subWorkflows
364
366
  } : {}),
@@ -889,19 +891,26 @@ class WorkflowExecutor {
889
891
  // apply on top — they are the author's assertion about this step, and
890
892
  // dropping them because the step happens to target a workflow would
891
893
  // silently discard it. They see the sub-run's own outputs (`{}` when it
892
- // transferred) through `$outputs` and `$workflows`.
894
+ // transferred) through `$outputs` and `$workflows`, and are evaluated
895
+ // even when the sub-run failed, so the record explains them either way.
893
896
  // the criteria and actions are the *calling* step's, so they are
894
897
  // evaluated by the parent document's step executor — only the sub-run
895
898
  // itself switched documents.
896
899
  const stepExecutor = this.#stepExecutor.forDocument(document);
897
- const successful = !this.#settledFailed(result) && stepExecutor.evaluateCriteria(step, context);
898
- const matchedActions = stepExecutor.selectActions(step, successful, context);
900
+ const successCriteria = stepExecutor.evaluateCriteria(step, context);
901
+ const successful = !this.#settledFailed(result) && successCriteria.every(criterion => criterion.met);
902
+ const {
903
+ matchedActions,
904
+ actionCriteria
905
+ } = stepExecutor.selectActions(step, successful, context);
899
906
  return {
900
907
  stepId,
901
908
  successful,
902
909
  outputs,
903
910
  action: matchedActions[0],
904
- matchedActions
911
+ matchedActions,
912
+ successCriteria,
913
+ actionCriteria
905
914
  };
906
915
  };
907
916
  }
@@ -345,6 +345,8 @@ class WorkflowExecutor {
345
345
  action,
346
346
  attempts,
347
347
  durationMs: this.#now() - stepStartedAt,
348
+ successCriteria: outcome.successCriteria,
349
+ actionCriteria: outcome.actionCriteria,
348
350
  ...(subWorkflows.length > 0 ? {
349
351
  subWorkflows
350
352
  } : {}),
@@ -875,19 +877,26 @@ class WorkflowExecutor {
875
877
  // apply on top — they are the author's assertion about this step, and
876
878
  // dropping them because the step happens to target a workflow would
877
879
  // silently discard it. They see the sub-run's own outputs (`{}` when it
878
- // transferred) through `$outputs` and `$workflows`.
880
+ // transferred) through `$outputs` and `$workflows`, and are evaluated
881
+ // even when the sub-run failed, so the record explains them either way.
879
882
  // the criteria and actions are the *calling* step's, so they are
880
883
  // evaluated by the parent document's step executor — only the sub-run
881
884
  // itself switched documents.
882
885
  const stepExecutor = this.#stepExecutor.forDocument(document);
883
- const successful = !this.#settledFailed(result) && stepExecutor.evaluateCriteria(step, context);
884
- const matchedActions = stepExecutor.selectActions(step, successful, context);
886
+ const successCriteria = stepExecutor.evaluateCriteria(step, context);
887
+ const successful = !this.#settledFailed(result) && successCriteria.every(criterion => criterion.met);
888
+ const {
889
+ matchedActions,
890
+ actionCriteria
891
+ } = stepExecutor.selectActions(step, successful, context);
885
892
  return {
886
893
  stepId,
887
894
  successful,
888
895
  outputs,
889
896
  action: matchedActions[0],
890
- matchedActions
897
+ matchedActions,
898
+ successCriteria,
899
+ actionCriteria
891
900
  };
892
901
  };
893
902
  }
package/src/index.cjs CHANGED
@@ -113,6 +113,18 @@ Object.defineProperty(exports, "CriterionError", {
113
113
  return _CriterionError.default;
114
114
  }
115
115
  });
116
+ Object.defineProperty(exports, "CriterionErrorReason", {
117
+ enumerable: true,
118
+ get: function () {
119
+ return _CriterionErrorReason.default;
120
+ }
121
+ });
122
+ Object.defineProperty(exports, "CriterionEvaluationError", {
123
+ enumerable: true,
124
+ get: function () {
125
+ return _CriterionEvaluationError.default;
126
+ }
127
+ });
116
128
  Object.defineProperty(exports, "CriterionEvaluator", {
117
129
  enumerable: true,
118
130
  get: function () {
@@ -405,6 +417,7 @@ var _SimpleCriterionEvaluator = _interopRequireDefault(require("./criterion/Simp
405
417
  var _RegexCriterionEvaluator = _interopRequireDefault(require("./criterion/RegexCriterionEvaluator.cjs"));
406
418
  var _JSONPathCriterionEvaluator = _interopRequireDefault(require("./criterion/JSONPathCriterionEvaluator.cjs"));
407
419
  var _XPathCriterionEvaluator = _interopRequireDefault(require("./criterion/XPathCriterionEvaluator.cjs"));
420
+ var _CriterionErrorReason = _interopRequireDefault(require("./criterion/CriterionErrorReason.cjs"));
408
421
  var _WorkflowExecutionState = _interopRequireDefault(require("./state/WorkflowExecutionState.cjs"));
409
422
  var _ArazzoValueResolver = _interopRequireDefault(require("./resolver/ArazzoValueResolver.cjs"));
410
423
  var _StepParameterResolver = _interopRequireDefault(require("./resolver/StepParameterResolver.cjs"));
@@ -429,5 +442,6 @@ var _UnmatchedProviderError = _interopRequireDefault(require("./errors/Unmatched
429
442
  var _DocumentLoadError = _interopRequireDefault(require("./errors/DocumentLoadError.cjs"));
430
443
  var _RuntimeExpressionError = _interopRequireDefault(require("./errors/RuntimeExpressionError.cjs"));
431
444
  var _CriterionError = _interopRequireDefault(require("./errors/CriterionError.cjs"));
445
+ var _CriterionEvaluationError = _interopRequireDefault(require("./errors/CriterionEvaluationError.cjs"));
432
446
  var _ResolverError = _interopRequireDefault(require("./errors/ResolverError.cjs"));
433
447
  var _ExecutionError = _interopRequireDefault(require("./errors/ExecutionError.cjs"));
package/src/index.mjs CHANGED
@@ -43,6 +43,7 @@ export { default as SimpleCriterionEvaluator } from "./criterion/SimpleCriterion
43
43
  export { default as RegexCriterionEvaluator } from "./criterion/RegexCriterionEvaluator.mjs";
44
44
  export { default as JSONPathCriterionEvaluator } from "./criterion/JSONPathCriterionEvaluator.mjs";
45
45
  export { default as XPathCriterionEvaluator } from "./criterion/XPathCriterionEvaluator.mjs";
46
+ export { default as CriterionErrorReason } from "./criterion/CriterionErrorReason.mjs";
46
47
  /* Execution State */
47
48
  export { default as WorkflowExecutionState } from "./state/WorkflowExecutionState.mjs";
48
49
  /* Resolvers */
@@ -72,5 +73,6 @@ export { default as UnmatchedProviderError } from "./errors/UnmatchedProviderErr
72
73
  export { default as DocumentLoadError } from "./errors/DocumentLoadError.mjs";
73
74
  export { default as RuntimeExpressionError } from "./errors/RuntimeExpressionError.mjs";
74
75
  export { default as CriterionError } from "./errors/CriterionError.mjs";
76
+ export { default as CriterionEvaluationError } from "./errors/CriterionEvaluationError.mjs";
75
77
  export { default as ResolverError } from "./errors/ResolverError.mjs";
76
78
  export { default as ExecutionError } from "./errors/ExecutionError.mjs";
package/types/runner.d.ts CHANGED
@@ -473,11 +473,106 @@ export declare type CriterionContextResolver = (expression: string) => unknown;
473
473
  export declare class CriterionError extends ArazzoRunnerError {
474
474
  readonly condition?: string;
475
475
  readonly type?: string;
476
- readonly reason?: string;
476
+ readonly reason?: CriterionErrorReason;
477
+ }
478
+
479
+ /**
480
+ * The `reason` a {@link CriterionError} carries.
481
+ *
482
+ * Structural reasons mark a criterion that is malformed as written; they are
483
+ * thrown as a plain `CriterionError`. Evaluation reasons (`InvalidSimple`,
484
+ * `InvalidRegex`, `InvalidJSONPath`, `InvalidXPath`, `InvalidXPathContext`) mark
485
+ * a condition that cannot be evaluated; they are thrown as a
486
+ * {@link CriterionEvaluationError}, which `CriterionEvaluator` turns into an
487
+ * unmet criterion.
488
+ * @public
489
+ */
490
+ export declare const CriterionErrorReason: {
491
+ /** The element is not a Criterion Object. */
492
+ readonly InvalidCriterion: "invalid-criterion";
493
+ /** The `condition` is missing or empty. */
494
+ readonly MissingCondition: "missing-condition";
495
+ /** The `type` is present but unreadable. */
496
+ readonly InvalidType: "invalid-type";
497
+ /** The `type` names no known criterion type. */
498
+ readonly UnknownType: "unknown-type";
499
+ /** The expression type `version` is present but not a string. */
500
+ readonly InvalidVersion: "invalid-version";
501
+ /** The expression type `version` is not the one this runner supports. */
502
+ readonly UnsupportedVersion: "unsupported-version";
503
+ /** The `context` is not a runtime expression. */
504
+ readonly InvalidContext: "invalid-context";
505
+ /** A `regex`, `jsonpath` or `xpath` criterion has no `context`. */
506
+ readonly MissingContext: "missing-context";
507
+ /** The `simple` condition cannot be parsed. */
508
+ readonly InvalidSimple: "invalid-simple";
509
+ /** The `regex` condition is not a valid regular expression. */
510
+ readonly InvalidRegex: "invalid-regex";
511
+ /** The `jsonpath` condition is not a valid JSONPath query. */
512
+ readonly InvalidJSONPath: "invalid-jsonpath";
513
+ /** The `xpath` condition is invalid or fails to evaluate. */
514
+ readonly InvalidXPath: "invalid-xpath";
515
+ /** The resolved `xpath` context is not XML. */
516
+ readonly InvalidXPathContext: "invalid-xpath-context";
517
+ };
518
+
519
+ /**
520
+ * One of the `CriterionErrorReason` values.
521
+ * @public
522
+ */
523
+ export declare type CriterionErrorReason = (typeof CriterionErrorReason)[keyof typeof CriterionErrorReason];
524
+
525
+ /**
526
+ * A criterion condition that cannot be evaluated: a syntax error in the
527
+ * condition, a context the condition cannot apply to, or an error raised while
528
+ * evaluating it. The type-specific criterion evaluators throw it;
529
+ * `CriterionEvaluator` turns it into an unmet criterion, as Arazzo 1.1.0
530
+ * requires.
531
+ * @public
532
+ */
533
+ export declare class CriterionEvaluationError extends CriterionError {
477
534
  }
478
535
 
479
536
  /**
480
- * Evaluates an Arazzo Criterion Object to a boolean.
537
+ * The outcome of one criterion a step evaluated: one of its `successCriteria`,
538
+ * or one of the `criteria` of an action it considered.
539
+ * @public
540
+ */
541
+ export declare interface CriterionEvaluationRecord {
542
+ /**
543
+ * The criterion's `condition`, as written.
544
+ */
545
+ readonly condition: string;
546
+ /**
547
+ * Whether the condition is met.
548
+ */
549
+ readonly met: boolean;
550
+ /**
551
+ * The `name` of the action declaring the criterion — present only on an
552
+ * action criterion.
553
+ */
554
+ readonly actionName?: string;
555
+ /**
556
+ * Why the condition could not be evaluated — present only then, with `met`
557
+ * `false`.
558
+ */
559
+ readonly diagnostic?: {
560
+ /**
561
+ * Machine-readable: the `reason` of the error that failed the criterion, a
562
+ * `CriterionErrorReason` value or `'unavailable-expression'` for an
563
+ * HTTP-exchange expression in a step that calls a workflow.
564
+ */
565
+ readonly code?: CriterionErrorReason | 'unavailable-expression';
566
+ /**
567
+ * Human-readable: names the condition or expression and, for a syntax
568
+ * error, what is wrong with it; never request or response data.
569
+ */
570
+ readonly message: string;
571
+ };
572
+ }
573
+
574
+ /**
575
+ * Evaluates an Arazzo Criterion Object to a {@link CriterionOutcome}.
481
576
  *
482
577
  * Dispatches on the criterion's `type` (defaulting to `simple` when omitted):
483
578
  * - `simple` — evaluates the condition directly, resolving the runtime
@@ -486,12 +581,27 @@ export declare class CriterionError extends ArazzoRunnerError {
486
581
  * pattern to the resolved value.
487
582
  * - `jsonpath` — resolves the `context` runtime expression, then applies the
488
583
  * JSONPath query to the resolved value (met when the query matches). Only the
489
- * `rfc9535` version is supported (the spec default); an explicit other version
490
- * throws.
584
+ * `rfc9535` version is supported; an explicit other version throws.
491
585
  * - `xpath` — resolves the `context` runtime expression, then applies the XPath
492
586
  * 3.1 query to the resolved XML value (met by the Effective Boolean Value).
493
- * Only the `xpath-31` version is supported (the spec default); an explicit
494
- * other version throws.
587
+ * Only the `xpath-31` version is supported; an explicit other version throws.
588
+ *
589
+ * Versions follow Arazzo 1.1.0's Expression Type Object: `rfc9535` and
590
+ * `xpath-31` are allowed values, and an omitted `version` defaults to them.
591
+ * Arazzo 1.0.x lists neither and requires `version`; this evaluator applies
592
+ * the 1.1.0 rule to every document, which accepts more but never evaluates a
593
+ * query under the wrong dialect.
594
+ *
595
+ * A condition that cannot be evaluated fails the criterion (`met: false`), as
596
+ * Arazzo 1.1.0 requires: a syntax error in the condition, a context the
597
+ * condition cannot apply to (non-XML data for `xpath`), or an XPath evaluation
598
+ * error. The type-specific evaluators report these as a
599
+ * {@link CriterionEvaluationError}, which this facade returns as the
600
+ * outcome's `error` so the caller can report it; any other error they raise
601
+ * propagates. A criterion that is malformed as written still throws: a
602
+ * missing `condition`, an unknown or unreadable `type`, an unsupported
603
+ * expression `version`, or a `context` that is missing or not a runtime
604
+ * expression.
495
605
  *
496
606
  * The evaluator is agnostic about how runtime expressions are resolved: the
497
607
  * caller supplies a {@link CriterionContextResolver} per evaluation, keeping
@@ -503,17 +613,22 @@ export declare class CriterionEvaluator {
503
613
  #private;
504
614
  constructor(options?: CriterionEvaluatorOptions);
505
615
  /**
506
- * Evaluates a criterion element, returning whether the condition is met.
616
+ * Evaluates a criterion element, returning whether the condition is met and,
617
+ * when it cannot be evaluated, why.
507
618
  *
508
619
  * `resolve` turns a runtime expression into a value: for `simple` it resolves
509
620
  * the expressions embedded in the condition; for the other types it resolves
510
621
  * the criterion's `context` expression that the condition is applied to.
511
622
  */
512
- evaluate(criterion: CriterionElement, resolve: CriterionContextResolver): boolean;
623
+ evaluate(criterion: CriterionElement, resolve: CriterionContextResolver): CriterionOutcome;
513
624
  }
514
625
 
515
626
  /**
516
627
  * Options for the CriterionEvaluator.
628
+ *
629
+ * An injected evaluator signals a condition it cannot evaluate by throwing a
630
+ * {@link CriterionEvaluationError}, which fails the criterion; any other error
631
+ * it throws, a plain {@link CriterionError} included, propagates.
517
632
  * @public
518
633
  */
519
634
  export declare interface CriterionEvaluatorOptions {
@@ -536,14 +651,32 @@ export declare interface CriterionEvaluatorOptions {
536
651
  }
537
652
 
538
653
  /**
539
- * Determines whether a single criterion is met.
654
+ * The outcome of evaluating one criterion.
655
+ * @public
656
+ */
657
+ export declare interface CriterionOutcome {
658
+ /**
659
+ * Whether the condition is met. `false` when it evaluates to false or cannot
660
+ * be evaluated; only in the latter case is {@link CriterionOutcome.error}
661
+ * present, saying why.
662
+ */
663
+ readonly met: boolean;
664
+ /**
665
+ * Why the condition could not be evaluated: present only when it was not.
666
+ */
667
+ readonly error?: CriterionEvaluationError;
668
+ }
669
+
670
+ /**
671
+ * Determines whether a single criterion of an action is met. Receives the
672
+ * action declaring the criterion, so a caller can attribute the outcome to it.
540
673
  *
541
674
  * Bridged to a criterion evaluator
542
- * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve)`); an
675
+ * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve).met`); an
543
676
  * unresolvable/failing criterion is `false`, not an error.
544
677
  * @public
545
678
  */
546
- export declare type CriterionPredicate = (criterion: CriterionElement) => boolean;
679
+ export declare type CriterionPredicate = (criterion: CriterionElement, action: SelectedAction) => boolean;
547
680
 
548
681
  /** @public */
549
682
  export declare class DocumentLoadError extends ArazzoRunnerError {
@@ -701,7 +834,7 @@ export declare class JSONPathCriterionEvaluator {
701
834
  * whether it matched anything.
702
835
  *
703
836
  * Returns `false` when the context is `null` or `undefined`. Throws
704
- * {@link CriterionError} when the condition is not a valid JSONPath query.
837
+ * {@link CriterionEvaluationError} when the condition is not a valid JSONPath query.
705
838
  */
706
839
  evaluate(condition: string, context: unknown): boolean;
707
840
  }
@@ -1420,7 +1553,7 @@ export declare class RegexCriterionEvaluator {
1420
1553
  * Tests the resolved context value against the regular expression `condition`.
1421
1554
  *
1422
1555
  * The context is coerced to a string before matching. Returns `false` when the
1423
- * context is `null` or `undefined`. Throws {@link CriterionError} when the
1556
+ * context is `null` or `undefined`. Throws {@link CriterionEvaluationError} when the
1424
1557
  * condition is not a valid regular expression.
1425
1558
  */
1426
1559
  evaluate(condition: string, context: unknown): boolean;
@@ -1780,7 +1913,7 @@ export declare function settledResult(result: WorkflowExecutionResult): Workflow
1780
1913
  * compared per the library's rules (e.g. `undefined == x` and relational
1781
1914
  * comparisons are false, matching the spec's "null equals only null"), so a
1782
1915
  * negated or disjunctive condition may still pass. A malformed condition throws
1783
- * {@link CriterionError}.
1916
+ * {@link CriterionEvaluationError}.
1784
1917
  * @public
1785
1918
  */
1786
1919
  export declare class SimpleCriterionEvaluator {
@@ -1854,6 +1987,16 @@ export declare interface StepExecutionResult {
1854
1987
  * matching action. Empty when none matched.
1855
1988
  */
1856
1989
  readonly matchedActions: readonly SelectedAction[];
1990
+ /**
1991
+ * The outcome of each of the step's `successCriteria`, in list order.
1992
+ */
1993
+ readonly successCriteria: readonly CriterionEvaluationRecord[];
1994
+ /**
1995
+ * The outcome of each criterion of the actions the step considered — its
1996
+ * `onSuccess` actions when it succeeded, its `onFailure` actions otherwise —
1997
+ * in list order.
1998
+ */
1999
+ readonly actionCriteria: readonly CriterionEvaluationRecord[];
1857
2000
  }
1858
2001
 
1859
2002
  /**
@@ -1921,19 +2064,23 @@ export declare class StepExecutor {
1921
2064
  */
1922
2065
  assertSuccessCriteria(step: StepElement, workflowId?: string): void;
1923
2066
  /**
1924
- * Evaluates the step's `successCriteria`; all criteria must pass. A step with
1925
- * no criteria succeeds on a received response. An unreadable
1926
- * `successCriteria` throws, see {@link StepExecutor.assertSuccessCriteria}.
2067
+ * Evaluates the step's `successCriteria`, returning one record per criterion
2068
+ * in list order; the step succeeds when every record is met. Every criterion
2069
+ * is evaluated, so the records explain each unmet one, not only the first. A
2070
+ * step with no criteria returns no records and succeeds on a received
2071
+ * response. An unreadable `successCriteria` throws, see
2072
+ * {@link StepExecutor.assertSuccessCriteria}.
1927
2073
  *
1928
2074
  * Public for the same reason as {@link StepExecutor.selectActions}: a step
1929
2075
  * targeting a `workflowId` is run by the workflow executor and never reaches
1930
2076
  * {@link StepExecutor.execute}, but its criteria are still the author's
1931
2077
  * assertion about the step and must be evaluated somewhere.
1932
2078
  */
1933
- evaluateCriteria(step: StepElement, context: RuntimeExpressionContext): boolean;
2079
+ evaluateCriteria(step: StepElement, context: RuntimeExpressionContext): CriterionEvaluationRecord[];
1934
2080
  /**
1935
2081
  * Selects every matching `onSuccess` / `onFailure` action for the outcome, in
1936
- * list order, gating each action's criteria against the context.
2082
+ * list order, gating each action's criteria against the context, and records
2083
+ * the outcome of every action criterion evaluated.
1937
2084
  *
1938
2085
  * The step's own list is the whole story here: a step that declares none of
1939
2086
  * its own already carries the workflow-level defaults, inherited by
@@ -1951,7 +2098,7 @@ export declare class StepExecutor {
1951
2098
  * {@link StepExecutor.execute}. Both callers reach the criteria evaluator and
1952
2099
  * the expression context through this one method rather than wiring their own.
1953
2100
  */
1954
- selectActions(step: StepElement, successful: boolean, context: RuntimeExpressionContext): SelectedAction[];
2101
+ selectActions(step: StepElement, successful: boolean, context: RuntimeExpressionContext): Pick<StepExecutionResult, 'matchedActions' | 'actionCriteria'>;
1955
2102
  }
1956
2103
 
1957
2104
  /**
@@ -2029,6 +2176,17 @@ export declare interface StepRunRecord {
2029
2176
  * fractional and is unaffected by system clock changes.
2030
2177
  */
2031
2178
  readonly durationMs: number;
2179
+ /**
2180
+ * The outcome of each of the step's `successCriteria` in its last attempt, in
2181
+ * list order — why the step succeeded or failed.
2182
+ */
2183
+ readonly successCriteria: readonly CriterionEvaluationRecord[];
2184
+ /**
2185
+ * The outcome of each criterion of the actions the last attempt considered —
2186
+ * its `onSuccess` actions when it succeeded, its `onFailure` actions
2187
+ * otherwise — in list order: why an action matched or did not.
2188
+ */
2189
+ readonly actionCriteria: readonly CriterionEvaluationRecord[];
2032
2190
  /**
2033
2191
  * The sub-workflow runs this step produced, in attempt order — present only on
2034
2192
  * a step targeting a `workflowId`.
@@ -2455,7 +2613,7 @@ export declare interface WorkflowReferenceContext {
2455
2613
  *
2456
2614
  * Only XPath 3.1 is supported (`fontoxpath`'s engine); version gating happens in
2457
2615
  * the facade. Per Arazzo 1.1.0, a `null` or `undefined` context fails the
2458
- * condition. An invalid query throws {@link CriterionError}.
2616
+ * condition. An invalid query throws {@link CriterionEvaluationError}.
2459
2617
  * @public
2460
2618
  */
2461
2619
  export declare class XPathCriterionEvaluator {
@@ -2465,7 +2623,7 @@ export declare class XPathCriterionEvaluator {
2465
2623
  * its Effective Boolean Value.
2466
2624
  *
2467
2625
  * Returns `false` when the context is `null` or `undefined`. Throws
2468
- * {@link CriterionError} when the context is not XML or the query is invalid.
2626
+ * {@link CriterionEvaluationError} when the context is not XML or the query is invalid.
2469
2627
  */
2470
2628
  evaluate(condition: string, context: unknown): boolean;
2471
2629
  }