@sanity/workflow-engine 0.32.0 → 0.34.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/define.d.ts CHANGED
@@ -17,12 +17,12 @@ import * as v from "valibot";
17
17
  *
18
18
  * @interface
19
19
  */
20
- declare type Action = ActionFields<Op, string[]> & {
20
+ declare type Action = ActionFields<Op, string[], Effect> & {
21
21
  roles?: string[] | undefined;
22
22
  };
23
23
 
24
24
  /** @inline */
25
- declare type ActionFields<TOp, TGroup> = {
25
+ declare type ActionFields<TOp, TGroup, TEffect> = {
26
26
  name: string;
27
27
  semantics?: ActionSemantic[] | undefined;
28
28
  title?: string | undefined;
@@ -32,7 +32,7 @@ declare type ActionFields<TOp, TGroup> = {
32
32
  filter?: string | undefined;
33
33
  params?: ActionParam[] | undefined;
34
34
  ops?: TOp[] | undefined;
35
- effects?: Effect[] | undefined;
35
+ effects?: TEffect[] | undefined;
36
36
  spawn?: Subworkflows | undefined;
37
37
  };
38
38
 
@@ -250,6 +250,23 @@ declare type AuthoringActivity = ActivityFields<
250
250
  */
251
251
  declare type AuthoringEditable = true | string[] | string;
252
252
 
253
+ /**
254
+ * An {@link Effect} whose `retry` block may omit its `kind`, plus the
255
+ * authoring-only `runtime` block that says where the generated runtime hosts
256
+ * this handler. `retry` is stored; `runtime` is stripped before the deploy
257
+ * writes the definition.
258
+ *
259
+ * @interface
260
+ */
261
+ declare type AuthoringEffect = EffectFields<AuthoringEffectRetry> & {
262
+ runtime?: EffectRuntimeBlock | undefined;
263
+ };
264
+
265
+ /** An {@link EffectRetry} whose omitted `kind` defaults to `engine`. */
266
+ declare type AuthoringEffectRetry = EffectRetryFields & {
267
+ kind?: EffectRetryKind | undefined;
268
+ };
269
+
253
270
  /**
254
271
  * A raw field entry or one of the authoring-only field sugars. `todoList`
255
272
  * expands to an array of objects with `label`, `status`, optional `assignee`,
@@ -257,6 +274,7 @@ declare type AuthoringEditable = true | string[] | string;
257
274
  * `notes` expands to an array of audit-shaped objects with `body`, `actor`,
258
275
  * and `at` fields. Sugar type names are compiled away and never become stored
259
276
  * field kinds.
277
+ * See {@link FieldEntry} for scope, required-input, and field-type constraints.
260
278
  */
261
279
  declare type AuthoringFieldEntry =
262
280
  | AuthoringRawFieldEntry
@@ -288,8 +306,22 @@ declare const AuthoringFieldRefSchema: v.StrictObjectSchema<
288
306
  >;
289
307
 
290
308
  /**
291
- * {@link Guard}'s contract as authored: `match.idRefs` and `metadata` carry
292
- * typed {@link GuardRead} values that deploy resolves to bare ones.
309
+ * A stage's content mutation guard. Its name must be unique across the whole
310
+ * definition and use lowercase letters, digits, and dashes, starting with a
311
+ * letter or digit. `match.actions` must contain at least one action.
312
+ *
313
+ * `match.types` intersects the ID criteria. Within the ID criteria, matching
314
+ * either `idRefs` or `idPatterns` is sufficient. Omitted or empty optional
315
+ * criteria do not constrain the match. `idRefs` uses typed {@link GuardRead}s.
316
+ * Patterns use resource-local document-ID characters and `*` wildcards.
317
+ * A release-version pattern is rejected if translating it for a lifecycle
318
+ * action would broaden it to every document.
319
+ *
320
+ * `predicate` is delta-mode GROQ over `document`, `guard`, and `mutation`;
321
+ * see {@link GUARD_PREDICATE_VARS}. Only a strict `true` allows a matching
322
+ * mutation. An omitted or empty predicate denies it. `metadata` resolves
323
+ * {@link GuardRead}s into values available as `guard.metadata` in the predicate.
324
+ * Engine evaluations are advisory; the Content Lake is the enforcement point.
293
325
  *
294
326
  * @interface
295
327
  */
@@ -408,7 +440,11 @@ declare type AuthoringOp =
408
440
  };
409
441
 
410
442
  /** @inline */
411
- declare type AuthoringRawAction = ActionFields<AuthoringOp, GroupMembership> & {
443
+ declare type AuthoringRawAction = ActionFields<
444
+ AuthoringOp,
445
+ GroupMembership,
446
+ AuthoringEffect
447
+ > & {
412
448
  roles?: string[] | undefined;
413
449
  status?: TerminalActivityStatus | undefined;
414
450
  };
@@ -419,7 +455,12 @@ declare type AuthoringRawFieldEntry = FieldEntryFields<
419
455
  GroupMembership
420
456
  >;
421
457
 
422
- /** @interface */
458
+ /**
459
+ * A {@link Stage} accepting authoring fields, activities, transitions, guards,
460
+ * and role-list editability. The same terminal-stage constraints apply.
461
+ *
462
+ * @interface
463
+ */
423
464
  declare type AuthoringStage = StageFields<
424
465
  AuthoringFieldEntry,
425
466
  AuthoringActivity,
@@ -428,21 +469,23 @@ declare type AuthoringStage = StageFields<
428
469
  AuthoringEditable
429
470
  >;
430
471
 
472
+ /** A {@link StartBlock} whose omitted `kind` defaults to `interactive`. */
431
473
  declare type AuthoringStartBlock = StartFields & {
432
474
  kind?: StartKind | undefined;
433
475
  };
434
476
 
435
477
  /**
436
- * Authoring transitions may omit `when`; desugar fills the safe,
437
- * overwhelmingly-common trigger `"$allActivitiesDone"`. "Fire unconditionally"
438
- * stays spellable as an explicit `when: "true"`.
478
+ * A {@link Transition} whose `when` may be omitted, defaulting to
479
+ * `$allActivitiesDone`. Use `when: 'true'` for an unconditional route.
439
480
  */
440
481
  declare type AuthoringTransition = TransitionFields & {
441
482
  when?: string | undefined;
442
483
  };
443
484
 
444
485
  /**
445
- * The authoring surface: stored primitives plus the define-time sugar.
486
+ * The authoring surface: stored primitives plus the define-time sugar. `runtime`
487
+ * says where the generated unattended runtime hosts this workflow, overriding
488
+ * its deployment's kind; an effect node overrides it in turn.
446
489
  *
447
490
  * @interface
448
491
  */
@@ -450,13 +493,24 @@ declare type AuthoringWorkflow = WorkflowFields<
450
493
  AuthoringFieldEntry,
451
494
  AuthoringStage,
452
495
  AuthoringStartBlock
453
- >;
496
+ > & {
497
+ runtime?: RuntimeBlock | undefined;
498
+ };
454
499
 
455
500
  declare interface ChoiceOption {
456
501
  title: string;
457
502
  value: ChoiceValue;
458
503
  }
459
504
 
505
+ /**
506
+ * A closed list of allowed non-null scalar values. The list must be nonempty,
507
+ * with unique values and nonempty titles. Each value must satisfy the
508
+ * receiving type and its validation bounds.
509
+ *
510
+ * Fields accept choices on `string`, `text`, `number`, `url`, `date`,
511
+ * `dueDate`, `datetime`, and `dueDatetime`. Action parameters accept choices
512
+ * on `string`, `number`, `url`, and `dateTime`.
513
+ */
460
514
  declare interface ChoiceOptions {
461
515
  list: ChoiceOption[];
462
516
  }
@@ -534,11 +588,21 @@ export declare function defineActivity(
534
588
  activity: AuthoringActivity,
535
589
  ): AuthoringActivity;
536
590
 
591
+ /**
592
+ * What `defineWorkflow` returns: the stored definition, plus `runtime` when the
593
+ * workflow or one of its effects declared a hosting kind. Generation and the
594
+ * blueprint tooling read `runtime`; the deploy drops it, so it never reaches the
595
+ * Content Lake and never affects a definition's content fingerprint.
596
+ */
597
+ declare type DefinedWorkflow = WorkflowDefinition & {
598
+ runtime?: DefinitionRuntime | undefined;
599
+ };
600
+
537
601
  /**
538
602
  * Validate and return an effect declaration — the registry model: `name` is
539
603
  * the effect's only identity; the host app registers a handler against it.
540
604
  */
541
- export declare function defineEffect(effect: Effect): Effect;
605
+ export declare function defineEffect(effect: AuthoringEffect): AuthoringEffect;
542
606
 
543
607
  export declare function defineEffectDescriptor(
544
608
  descriptor: EffectDescriptor,
@@ -567,8 +631,9 @@ export declare function defineTransition(
567
631
  ): AuthoringTransition;
568
632
 
569
633
  /**
570
- * Validate, desugar, and return a workflow definition in its stored shape.
571
- * Throws with a formatted, path-prefixed error message if validation fails.
634
+ * Validate, desugar, and return a workflow definition in its stored shape, plus
635
+ * the `runtime` hosting the workflow or its effects declared. Throws with a
636
+ * formatted, path-prefixed error message if validation fails.
572
637
  *
573
638
  * Example error:
574
639
  *
@@ -580,7 +645,7 @@ export declare function defineTransition(
580
645
  */
581
646
  export declare function defineWorkflow(
582
647
  definition: AuthoringWorkflow,
583
- ): WorkflowDefinition;
648
+ ): DefinedWorkflow;
584
649
 
585
650
  /**
586
651
  * Validate a deploy config — the binding of each definition's logical resource
@@ -602,6 +667,17 @@ export declare function defineWorkflowConfig(
602
667
  config: WorkflowConfigInput,
603
668
  ): WorkflowConfig;
604
669
 
670
+ /**
671
+ * The hosting declarations {@link DefinedWorkflow} carries for the generator,
672
+ * collected out of the authored tree. `kind` is present only when the workflow
673
+ * declared one, so an absent `kind` inherits the deployment's. `effects` holds
674
+ * one entry per effect that declared a block, keyed by effect name.
675
+ */
676
+ declare interface DefinitionRuntime {
677
+ kind?: RuntimeKind | undefined;
678
+ effects?: Record<string, EffectRuntimeBlock> | undefined;
679
+ }
680
+
605
681
  /**
606
682
  * Declared editability of a field — the generic edit seam's gate. Default
607
683
  * (absent) is NOT editable: a field is op-only engine working memory unless the
@@ -614,20 +690,24 @@ export declare function defineWorkflowConfig(
614
690
  declare type Editable = true | string;
615
691
 
616
692
  /**
617
- * A registered effect: `name` is its only identity (unique per definition,
618
- * read downstream as `$effects.<name>`) the host app registers a handler
619
- * against it 1:1, and the stored definition never references code.
620
- * `bindings` are GROQ reads over the rendered scope, resolved to concrete
621
- * JSON at queue time; `input` is static config passed through verbatim.
622
- * `outputs` (typed {@link FieldShape}s) is a STRICT allowlist: at completion
623
- * an undeclared output key, or a value that doesn't fit its shape, fails the
624
- * completion and nothing is stored. Omitting `outputs` is an EMPTY allowlist,
625
- * so ANY returned output is rejected and fails the completion — the bound is
626
- * universal, not opt-in.
693
+ * External work queued for the handler registered under `name`. Names are
694
+ * unique within a definition; completed outputs are read as `$effects['<name>']`.
695
+ *
696
+ * `bindings` resolves GROQ expressions against the action's rendered scope
697
+ * when the effect is queued. The handler receives one parameter bag combining
698
+ * those values with static `input`. An `input` key overrides a same-named
699
+ * binding, including when its value is null.
700
+ *
701
+ * `outputs` declares the allowed result keys and their {@link FieldShape}s.
702
+ * An undeclared key or invalid value rejects the completion without storing
703
+ * it. Omitting `outputs` allows no output keys.
704
+ *
705
+ * `retry` ({@link EffectRetry}) bounds how many times a failing handler is
706
+ * attempted. Omitting it completes the effect as failed on the first failure.
627
707
  *
628
708
  * @interface
629
709
  */
630
- declare type Effect = v.InferOutput<typeof EffectSchema>;
710
+ declare type Effect = EffectFields<EffectRetry>;
631
711
 
632
712
  /**
633
713
  * Effect handler descriptor, registered by the runtime against an effect
@@ -648,43 +728,96 @@ export declare interface EffectDescriptorParam {
648
728
  description?: string;
649
729
  }
650
730
 
651
- declare const EffectSchema: v.StrictObjectSchema<
652
- {
653
- readonly name: v.SchemaWithPipe<
654
- readonly [
655
- v.StringSchema<undefined>,
656
- v.MinLengthAction<string, 1, "must be a non-empty string">,
657
- ]
658
- >;
659
- readonly title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
660
- readonly description: v.OptionalSchema<
661
- v.StringSchema<undefined>,
662
- undefined
663
- >;
664
- readonly bindings: v.OptionalSchema<
665
- v.RecordSchema<
666
- v.StringSchema<undefined>,
667
- v.SchemaWithPipe<
668
- readonly [
669
- v.StringSchema<undefined>,
670
- v.MinLengthAction<string, 1, "must be a non-empty string">,
671
- ]
672
- >,
673
- undefined
674
- >,
675
- undefined
676
- >;
677
- readonly input: v.OptionalSchema<
678
- v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>,
679
- undefined
680
- >;
681
- readonly outputs: v.OptionalSchema<
682
- v.ArraySchema<v.GenericSchema<FieldShape>, undefined>,
683
- undefined
684
- >;
685
- },
686
- undefined
687
- >;
731
+ /** @inline */
732
+ declare type EffectFields<TRetry> = {
733
+ name: string;
734
+ title?: string | undefined;
735
+ description?: string | undefined;
736
+ bindings?: Record<string, string> | undefined;
737
+ input?: Record<string, unknown> | undefined;
738
+ outputs?: FieldShape[] | undefined;
739
+ retry?: TRetry | undefined;
740
+ };
741
+
742
+ /**
743
+ * A bounded retry policy for one effect. Both bounds govern one drain's run of
744
+ * the policy, not the effect's lifetime: a drainer that dies mid-run leaves the
745
+ * entry for the next drain, which starts a fresh run with the full budget, so
746
+ * an effect can see more handler calls in total than `attempts`.
747
+ *
748
+ * `attempts` is the total number of attempts in a run, the first included, so
749
+ * `1` means "never retry".
750
+ *
751
+ * `expiryMs` and the backoff a policy accumulates are each capped at 366 days
752
+ * (`31_622_400_000` ms), inclusive. Deploy refuses a policy declaring more,
753
+ * and one whose accumulated backoff reaches its own `expiryMs` before its
754
+ * `attempts` are spent. Those checks weigh the declared waits alone. At
755
+ * runtime every elapsed millisecond counts against `expiryMs`, handler time
756
+ * included, so a slow handler can leave attempts unused. `backoff` paces
757
+ * them; omitting it retries with no wait. Every duration is a whole number of
758
+ * milliseconds above zero, and `attempts` a whole count above zero; deploy
759
+ * rejects anything else.
760
+ *
761
+ * `expiryMs` decides whether a further attempt may start, measured from the
762
+ * moment this run dispatched its first attempt. The window closes
763
+ * on reaching it, so an attempt is admitted only while less than `expiryMs`
764
+ * has elapsed. It is not a handler timeout. An attempt already running is
765
+ * never interrupted, so a run can finish after the window, and a success then
766
+ * still counts. Omitting it leaves `attempts` as the only bound.
767
+ *
768
+ * A policy that runs out of attempts, or that `expiryMs` stops, completes the
769
+ * effect as failed, and `$effectStatus['<name>'] == 'failed'` routes the
770
+ * instance. A successful attempt completes it as done, whichever attempt
771
+ * succeeded. An effect with no `retry` completes as failed on its handler's
772
+ * first failure.
773
+ */
774
+ declare type EffectRetry = EffectRetryFields & {
775
+ kind: EffectRetryKind;
776
+ };
777
+
778
+ /**
779
+ * How long the engine waits between two attempts. `delayMs` is that wait in
780
+ * milliseconds: `'fixed'` waits it every time, `'exponential'` doubles it per
781
+ * attempt already made (`delayMs`, then `2 × delayMs`, then `4 × delayMs`).
782
+ */
783
+ declare type EffectRetryBackoff = {
784
+ kind: "fixed" | "exponential";
785
+ delayMs: number;
786
+ };
787
+
788
+ /** @inline */
789
+ declare type EffectRetryFields = {
790
+ attempts: number;
791
+ backoff?: EffectRetryBackoff | undefined;
792
+ expiryMs?: number | undefined;
793
+ };
794
+
795
+ /**
796
+ * Who runs a retry policy. `'engine'` is the only member: the engine loops
797
+ * inside the `drainEffects` call that picked the effect up, holding the claim
798
+ * across the waits.
799
+ */
800
+ declare type EffectRetryKind = "engine";
801
+
802
+ /**
803
+ * The `runtime` block on an effect node, overriding its workflow's kind.
804
+ * `timeout` is seconds and `memory` megabytes of the function that runs this
805
+ * handler, and an effect declaring either gets its own drain function instead of
806
+ * sharing the deployment's. Both are the function budget, so both are accepted
807
+ * only under `'function'`.
808
+ */
809
+ declare type EffectRuntimeBlock =
810
+ | {
811
+ kind: "function";
812
+ timeout?: number | undefined;
813
+ memory?: number | undefined;
814
+ }
815
+ | {
816
+ kind: "durableFunction";
817
+ }
818
+ | {
819
+ kind: "selfHosted";
820
+ };
688
821
 
689
822
  /**
690
823
  * The kinds a VALUE can take — scalars aligned to Sanity's names, the
@@ -732,7 +865,26 @@ declare type FieldBase<TEditable, TGroup> = {
732
865
  };
733
866
 
734
867
  /**
735
- * One declared field entry as authored and stored: name, value kind, and its scope's sourcing and editability.
868
+ * A field declaration whose location determines its scope and lifetime.
869
+ * Workflow fields initialize at start; stage and activity fields initialize
870
+ * on each stage visit. {@link FieldSource} controls initialization;
871
+ * {@link Editable} controls direct edits independently.
872
+ *
873
+ * `required: true` is valid only on workflow-scope fields with an `input`
874
+ * source. It requires a non-null value at start or spawn. On `subject`,
875
+ * `doc.ref`, and `doc.refs`, selected targets must also remain readable in the
876
+ * workflow perspective after initialization. Missing targets block normal
877
+ * actions, triggered actions, and transitions. Abort and permitted field edits remain available.
878
+ * `subject` is also
879
+ * workflow-scope-only, with at most one subject per definition. Each scope
880
+ * may declare at most one `dueDate` or `dueDatetime` field, always top-level.
881
+ *
882
+ * `types` is a nonempty list of accepted document types on `subject`,
883
+ * `doc.ref`, or `doc.refs`; omit it to accept any document type. `roles`
884
+ * constrains assignment eligibility only on `assignee` and `assignees`.
885
+ * {@link FieldShape}, {@link ChoiceOptions}, and {@link ScalarValidation}
886
+ * define the nested-shape and scalar constraints. Authoring conveniences are
887
+ * accepted by {@link AuthoringFieldEntry}.
736
888
  *
737
889
  * @interface
738
890
  */
@@ -753,7 +905,22 @@ declare type FieldEntryFields<TEditable, TGroup> = FieldBase<
753
905
  of?: FieldShape[] | undefined;
754
906
  };
755
907
 
756
- /** A field mutation targeting the supplied field-reference shape. */
908
+ /**
909
+ * A field mutation targeting a declared field. Resolved values must satisfy
910
+ * that field's shape, choices, validation, and assignment constraints.
911
+ *
912
+ * `field.setIfMissing` supports nullable fields only. If a value exists, it
913
+ * leaves the value unchanged and records no `opApplied` history event.
914
+ * `field.inc` and `field.dec` require an initialized `number` field; their
915
+ * delta defaults to `1`. Both the delta and resulting value must be finite,
916
+ * and the result must satisfy the field's validation bounds.
917
+ *
918
+ * `field.append` adds one valid list member. `field.updateWhere` accepts only
919
+ * `array` fields and merges an object into matching rows. The merge cannot
920
+ * write `_key` or `_type`, and each resulting row must satisfy its declared
921
+ * shape. `field.removeWhere` supports list fields. See {@link Op} for row
922
+ * selection and history behavior.
923
+ */
757
924
  declare type FieldMutationOp<
758
925
  TTarget extends {
759
926
  field: string;
@@ -801,8 +968,9 @@ declare type FieldMutationOp<
801
968
  };
802
969
 
803
970
  /**
804
- * A stored field mutation. `field.inc` and `field.dec` use the same names as
805
- * `@sanity/client` patches and default an omitted `value` to a delta of `1`.
971
+ * A {@link FieldMutationOp} whose target scope is explicit. Actions can write
972
+ * fields in their activity, stage, or workflow. Effect completions accept only
973
+ * workflow- or stage-scoped field operations, never activity status changes.
806
974
  */
807
975
  declare type FieldOp = FieldMutationOp<StoredFieldRef>;
808
976
 
@@ -815,12 +983,16 @@ declare type FieldReadExpr = {
815
983
  };
816
984
 
817
985
  /**
818
- * A sub-field shape used inside an `object`'s `fields` or an `array`'s `of`
819
- * lighter than {@link FieldEntry}: no `initialValue`/`editable`/`required`,
820
- * since a sub-field's value comes from the parent. An `object` kind requires
821
- * non-empty `fields` and no `of`; an `array` kind requires non-empty `of` and
822
- * no `fields`; every other kind requires neither enforced at parse, not
823
- * visible in this type.
986
+ * A nested field shape inside an object's `fields`, an array's `of`, or an
987
+ * effect's `outputs`. It has no initialization, direct editability, or required
988
+ * setting; those belong to {@link FieldEntry}.
989
+ *
990
+ * An `object` requires nonempty `fields` and no `of`. An `array` requires
991
+ * nonempty `of` and no `fields`. Other types accept neither. Sibling names
992
+ * must be unique. Use ordinary `date` and `datetime` here; `dueDate` and
993
+ * `dueDatetime` are not valid nested fields or effect outputs.
994
+ * {@link ChoiceOptions} and {@link ScalarValidation} constrain supported
995
+ * scalar types. `roles` is valid only on `assignee` and `assignees` shapes.
824
996
  */
825
997
  declare interface FieldShape {
826
998
  type: FieldValueKind;
@@ -836,11 +1008,28 @@ declare interface FieldShape {
836
1008
  }
837
1009
 
838
1010
  /**
839
- * How a field seeds its `initialValue`, once at materialisation (advisory
840
- * after the field stays freely editable). Absent means working memory: the
841
- * field starts empty and an op fills it later, spelled by omission rather
842
- * than an arm. Distinct from {@link ValueExpr}, an op's write payload; they
843
- * overlap only on the literal and field-read arms.
1011
+ * Supplies a field's `initialValue` once, when the field is initialized.
1012
+ * Omitting the source starts the field empty; an operation can fill it later.
1013
+ * The source does not grant permission to edit. Direct editing requires an
1014
+ * {@link Editable | editable} declaration.
1015
+ *
1016
+ * Distinct from {@link ValueExpr}, which supplies an operation's write value.
1017
+ * Only the literal and field-read forms are shared.
1018
+ *
1019
+ * `input` reads workflow inputs supplied at start or spawn. Stage and activity
1020
+ * input seeds receive no caller value; activity input seeds produce a deploy
1021
+ * warning. `literal` supplies a fixed value. `query` runs against the Content
1022
+ * Lake with earlier fields in the same scope available as `$fields`.
1023
+ * Reference normalization can omit unrecognized values without recording
1024
+ * `fieldQueryDiscarded`. A result that fails validation after normalization
1025
+ * uses the field's empty value (`null` or `[]`) and records that event.
1026
+ * A failed query throws.
1027
+ *
1028
+ * A `fieldRead` seed reads earlier fields in its own scope when `scope` is
1029
+ * omitted. A stage or activity seed can read workflow fields with
1030
+ * `scope: 'workflow'`. An activity seed cannot read stage fields. At workflow
1031
+ * scope, omit `scope` to read an earlier workflow field. `path` selects a
1032
+ * nested value; these reads do not load referenced documents.
844
1033
  */
845
1034
  declare type FieldSource = FieldSourceInternal;
846
1035
 
@@ -885,8 +1074,13 @@ export declare function groq(
885
1074
  ...values: unknown[]
886
1075
  ): string;
887
1076
 
888
- /** A named readiness condition. Activities accept only `'groq'`; workflow
889
- * `start.requirements` also accepts `'singleSubject'` see {@link StartRequirement}. */
1077
+ /**
1078
+ * A named GROQ readiness condition. Its name must be unique in the containing
1079
+ * requirements array. Activity requirements use instance and caller variables;
1080
+ * workflow requirements use the input and projected dataset in {@link StartBlock}.
1081
+ * Every requirement must pass before the corresponding caller action or fresh
1082
+ * standalone start can commit.
1083
+ */
890
1084
  declare type GroqRequirement = RequirementBase & {
891
1085
  type: "groq";
892
1086
  query: string;
@@ -954,15 +1148,13 @@ export declare const GUARD_PREDICATE_VARS: readonly {
954
1148
  }[];
955
1149
 
956
1150
  /**
957
- * A deploy-time value read on a guard's `match.idRefs` / `metadata`, typed
958
- * like {@link ValueExpr} (`self`/`now`/`fieldRead`, plus the guard-only
959
- * `effectsRead` for a completed effect's output). Workflow-scope only a
960
- * guard outlives any activity, so `fieldRead` here carries no `scope`.
961
- * Desugar prints the STORED string spelling the deploy resolver and guard
962
- * refresh parse (`"$self"`, `"$now"`, `"$fields.<name>[.path]"`,
963
- * `"$effects['<name>'][.path]"`); those spellings are single-line strings
964
- * matched by anchored regexes, so a line break in a path would print an
965
- * unparseable read.
1151
+ * A value read for a guard's `match.idRefs` or `metadata`, resolved when the
1152
+ * guard is created or refreshed. `fieldRead` reads workflow fields only;
1153
+ * stage and activity fields are unavailable. `effectsRead` reads a completed
1154
+ * effect's output. `self` supplies the instance's GDR URI and `now` its ISO
1155
+ * clock value.
1156
+ * Paths cannot contain line breaks, and effect names cannot contain `'`.
1157
+ * Stored {@link Guard} declarations carry string forms of these reads.
966
1158
  */
967
1159
  declare type GuardRead =
968
1160
  | {
@@ -1090,8 +1282,15 @@ declare type NotesField = FieldBase<AuthoringEditable, GroupMembership> & {
1090
1282
  type: "notes";
1091
1283
  };
1092
1284
 
1093
- /** A `field.updateWhere` / `field.removeWhere` op's `where` selects rows to
1094
- * mutate with rendered-scope GROQ (`$row`, `$params` bound) row selection, not a gate; an unevaluable row never matches. */
1285
+ /**
1286
+ * An action operation: a {@link FieldOp} or a status change on an activity in
1287
+ * the current stage.
1288
+ *
1289
+ * For `field.updateWhere` and `field.removeWhere`, `where` evaluates each row
1290
+ * as `$row`. Caller-fired actions also supply `$params`. Referenced document
1291
+ * content is not loaded for row selection, and an unevaluable row never
1292
+ * matches. An operation matching no rows still records `opApplied` history.
1293
+ */
1095
1294
  declare type Op =
1096
1295
  | FieldOp
1097
1296
  | {
@@ -1124,8 +1323,38 @@ export declare const RESERVED_CONDITION_VARS: readonly string[];
1124
1323
  */
1125
1324
  declare type RoleAliases = Record<string, string[]>;
1126
1325
 
1127
- /** Inclusive scalar bounds. String/text bounds measure character length;
1128
- * number bounds measure the numeric value. */
1326
+ /**
1327
+ * The `runtime` block on a deployment and on `defineWorkflow`. A workflow that
1328
+ * declares none inherits its deployment's kind, and a deployment that declares
1329
+ * none hosts on `'function'`. Authoring-only: the deploy strips it and stores
1330
+ * nothing.
1331
+ *
1332
+ * It is a hint to the generator and to callers, never a rule the engine
1333
+ * enforces. The engine never sees it: any engine built anywhere with a handler
1334
+ * for an effect drains that effect when it calls `drainEffects`, whatever kind
1335
+ * the node declares, so a `'selfHosted'` effect is drained by whoever registers
1336
+ * its handler, the Studio included.
1337
+ */
1338
+ declare interface RuntimeBlock {
1339
+ kind: RuntimeKind;
1340
+ }
1341
+
1342
+ /**
1343
+ * Where the generated unattended runtime hosts a workflow or an effect.
1344
+ * `'function'` is a plain Sanity Function, `'durableFunction'` a durable one,
1345
+ * and `'selfHosted'` a process you run yourself.
1346
+ */
1347
+ declare type RuntimeKind = "function" | "durableFunction" | "selfHosted";
1348
+
1349
+ /**
1350
+ * Inclusive bounds for `string`, `text`, `number`, or `progress` values.
1351
+ * String/text bounds count characters and must be non-negative integers.
1352
+ * Number bounds are finite numeric values. Progress bounds may only narrow
1353
+ * its inclusive 0–100 range.
1354
+ *
1355
+ * Supply at least one bound. When both are present, `min` must not exceed
1356
+ * `max`. Null values remain allowed unless an input is required separately.
1357
+ */
1129
1358
  declare interface ScalarValidation {
1130
1359
  min?: number | undefined;
1131
1360
  max?: number | undefined;
@@ -1141,21 +1370,28 @@ declare const SIGNAL_SEMANTICS: readonly [
1141
1370
 
1142
1371
  declare type SignalSemantic = (typeof SIGNAL_SEMANTICS)[number];
1143
1372
 
1373
+ /**
1374
+ * A start requirement that rejects a fresh start when an unfinished run of
1375
+ * this definition holds the same subject, across deployed versions.
1376
+ * The workflow must declare an input-sourced `subject` field. Names are unique
1377
+ * within the requirements array. Like other engine checks, this is advisory;
1378
+ * it is not Content Lake enforcement.
1379
+ */
1144
1380
  declare type SingleSubjectRequirement = RequirementBase & {
1145
1381
  type: "singleSubject";
1146
1382
  };
1147
1383
 
1148
1384
  /**
1149
- * A pure container — name, fields, guards, activities, transitions, no
1150
- * behaviour of its own. Activities own enter, transitions own exit and
1151
- * arrival; a stage with no transitions IS terminal (structural, nothing to
1152
- * declare or mis-declare). `guards` are lake mutation guards active while
1153
- * the stage holds, each compiling to a persisted guard document deployed on
1154
- * stage entry and retracted on exit. `editable` is a tighten-only override
1155
- * for the time the stage holds, keyed by an in-scope field name: the field's
1156
- * own `editable` is the ceiling, ANDed with the stage value at runtime, so an
1157
- * override can only NARROW never open a field the baseline left closed. An
1158
- * unlisted field inherits its baseline.
1385
+ * The fields, activities, guards, and outgoing routes for one stage visit.
1386
+ * A stage with no transitions is terminal: entering it completes the instance,
1387
+ * and it cannot declare activities. Put completion work in the source stage
1388
+ * or give the working stage an outgoing transition.
1389
+ *
1390
+ * Guards are registered on entry and retracted on exit. `editable` overrides
1391
+ * are keyed by in-scope field name and apply while the stage is current.
1392
+ * Each combines with the field's own edit condition using AND, so an override
1393
+ * can restrict editing but cannot open a field whose baseline is closed.
1394
+ * An unlisted field inherits its baseline.
1159
1395
  *
1160
1396
  * @interface
1161
1397
  */
@@ -1182,17 +1418,24 @@ declare type StageFields<TField, TActivity, TTransition, TGuard, TEditable> = {
1182
1418
  };
1183
1419
 
1184
1420
  /**
1185
- * How standalone runs of this workflow begin. `filter` is a READ-SIDE
1186
- * visibility predicate "should a start surface offer this workflow for
1187
- * this document?" evaluated by `definitionsForDocument`/applicability in
1188
- * the browse-time-pure start-filter context (`$tag`/`$definition`/`$now`
1189
- * bound; `$fields` cannot exist before inputs do, so a `$fields` read here
1190
- * is deploy-rejected). It is NOT a `startInstance` gate; the verb never
1191
- * reads it. `requirements` are named readiness checks evaluated in author
1192
- * order in the start-time context (GROQ nodes add `$fields`; `singleSubject`
1193
- * is the one-in-flight-run-per-subject rule) every node must pass before
1194
- * `startInstance` commits. Both are advisory like every engine-side check;
1195
- * the Content Lake remains the only enforcement point.
1421
+ * Discovery and readiness rules for standalone starts.
1422
+ * `filter` evaluates against a candidate document with `$tag`, `$definition`,
1423
+ * and `$now`. It controls discovery and never gates `startInstance`.
1424
+ * It cannot read `$fields` or caller variables.
1425
+ *
1426
+ * `requirements` evaluates named checks in declaration order before a fresh
1427
+ * standalone start. All must pass. Resuming an existing start and spawning
1428
+ * children do not rerun these checks. A GROQ requirement binds `$tag`,
1429
+ * `$definition`, `$now`, and `$fields`, with no candidate document root.
1430
+ * `$fields` contains supplied input values, including GDR reference envelopes;
1431
+ * it excludes computed defaults and hydrated document content.
1432
+ *
1433
+ * At both sites, `*` scans projected instances in the engine's tag. Each row
1434
+ * contains only `definition` (name), `subject` (GDR URI or null), and
1435
+ * `completedAt` (ISO timestamp or null). Completed and aborted runs are
1436
+ * included. Raw fields such as `_type`, `tag`, and `fields` are unavailable.
1437
+ * Use {@link SingleSubjectRequirement} for one unfinished run per subject.
1438
+ * These checks are advisory; the Content Lake remains the enforcement point.
1196
1439
  */
1197
1440
  declare type StartBlock = StartFields & {
1198
1441
  kind: StartKind;
@@ -1242,17 +1485,27 @@ declare const StoredFieldRefSchema: v.StrictObjectSchema<
1242
1485
  >;
1243
1486
 
1244
1487
  /**
1245
- * Fan-out declared as an action's `spawn`, read back as `$subworkflows`.
1246
- * `forEach` is GROQ producing one row per subworkflow (bound as `$row`); each
1247
- * row needs an identity the engine can adopt on re-entry (`_key` ?? `_id` ??
1248
- * GDR `id`, or the value itself for a scalar row) or the spawn fails.
1249
- * `definition` resolves by stable `name`, ordered `version desc` unless
1250
- * pinned. `with` seeds each child's initial fields; `context` delivers extra
1251
- * parent-scope values into the child's `$context`. `onExit` governs only
1252
- * still-live children when the cohort's scope stops applying: `'detach'`
1253
- * (default) lets them run to completion, `'abort'` kills them recursively —
1254
- * always an authored choice, never automatic. Whether the PARENT may move at
1255
- * all is a separate gate over `$subworkflows`.
1488
+ * Child workflows created by an action's `spawn`, exposed as `$subworkflows`.
1489
+ * `definition` selects the highest deployed version unless a version is pinned.
1490
+ *
1491
+ * `forEach` evaluates with workflow fields only and no caller variables, even
1492
+ * for a caller-fired action. Rows need unique identities: a nonempty `_key`,
1493
+ * then `_id`, then a GDR's `id`, or a scalar's string representation.
1494
+ * Missing or duplicate identities reject the spawn. Re-entry adopts matching
1495
+ * live children from the same activity, action, and definition instead of
1496
+ * duplicating them.
1497
+ *
1498
+ * `with` maps child input-field names to expressions evaluated with `$row`.
1499
+ * `context` evaluates once without `$row` and supplies the child's `$context`.
1500
+ * Both use the parent activity's field scope and the acting identity when
1501
+ * available. Neither binds `$can`, `$attributes`, or `$params`.
1502
+ * Context results must be strings, numbers, booleans, or full GDRs; null and
1503
+ * undefined omit the entry. Other objects and arrays reject the spawn.
1504
+ *
1505
+ * `onExit` governs live children when their cohort leaves scope: `detach`
1506
+ * (the default) leaves them running; `abort` stops them recursively. Aborting
1507
+ * the parent always stops its children. Parent transitions must separately
1508
+ * declare whether they wait for the cohort to settle.
1256
1509
  *
1257
1510
  * @interface
1258
1511
  */
@@ -1353,14 +1606,14 @@ declare type TodoListField = FieldBase<AuthoringEditable, GroupMembership> & {
1353
1606
  };
1354
1607
 
1355
1608
  /**
1356
- * A pure edge — `{name, when, to}` plus presentation, no ops or effects
1357
- * (structure never does; only actions do). Every transition is evaluated on
1358
- * every commit and cascade; the first truthy `when` in declaration order
1359
- * fires. No action coupling: a routing difference is written into fields by
1360
- * an action and read by the trigger — arrival work is a `when: 'true'`
1361
- * action in the destination stage, and exit work is an action in the source
1362
- * stage whose `when` repeats this transition's condition (the hop rule
1363
- * guarantees it commits before the move).
1609
+ * A one-way route to another stage, without operations or effects. Selection
1610
+ * checks `when` conditions in declaration order. The first satisfied condition
1611
+ * fires; an earlier unevaluable condition, such as GROQ null, stops selection
1612
+ * without considering later routes. A false condition permits the next route.
1613
+ *
1614
+ * Actions write routing decisions into fields; transitions read that state.
1615
+ * Source-stage triggered actions run before transition selection. Arrival work
1616
+ * belongs to a triggered action in a nonterminal destination stage.
1364
1617
  */
1365
1618
  declare type Transition = TransitionFields & {
1366
1619
  when: string;
@@ -1375,10 +1628,18 @@ declare type TransitionFields = {
1375
1628
  };
1376
1629
 
1377
1630
  /**
1378
- * An op's write payload, resolved to concrete JSON when the op applies. Each
1379
- * context-bound arm has a rendered `$`-twin in conditions (`actor`
1380
- * `$actor`, `now` `$now`, `self` `$self`), so learning one side teaches
1381
- * the other. Distinct from {@link FieldSource}, a field's seed recipe.
1631
+ * An operation's write value, resolved when the operation applies.
1632
+ * `param` reads a caller-supplied action argument; `actor` records the acting
1633
+ * identity. `now` supplies the operation's ISO timestamp, `self` its instance's
1634
+ * GDR URI, and `stage` the current stage name. `object` resolves its fields
1635
+ * recursively.
1636
+ *
1637
+ * A `fieldRead` with no scope searches activity, stage, then workflow fields.
1638
+ * An explicit scope searches only that scope. A pathless read from a subject
1639
+ * or `doc.ref` into another subject or `doc.ref` preserves the stored reference.
1640
+ * Other reads use the referenced snapshot document, or only its `_id` and
1641
+ * `_type` when it is not loaded. No additional documents are fetched.
1642
+ * Initialization uses {@link FieldSource}, whose field-read scope rules differ.
1382
1643
  */
1383
1644
  declare type ValueExpr = ValueExprInternal;
1384
1645
 
@@ -1691,44 +1952,22 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
1691
1952
  readonly [
1692
1953
  v.ArraySchema<
1693
1954
  v.CustomSchema<
1694
- {
1695
- name: string;
1696
- semantics?: Semantic[] | undefined;
1697
- title: string;
1698
- description?: string | undefined;
1699
- groups?: Group[] | undefined;
1700
- lifecycle?: WorkflowLifecycle | undefined;
1701
- start?: StartBlock | undefined;
1702
- initialStage: string;
1703
- fields?: FieldEntry[] | undefined;
1704
- stages: Stage[];
1705
- predicates?: Record<string, string> | undefined;
1706
- roleAliases?: RoleAliases | undefined;
1707
- },
1955
+ DefinedWorkflow,
1708
1956
  v.ErrorMessage<v.CustomIssue> | undefined
1709
1957
  >,
1710
1958
  undefined
1711
1959
  >,
1712
1960
  v.MinLengthAction<
1713
- {
1714
- name: string;
1715
- semantics?: Semantic[] | undefined;
1716
- title: string;
1717
- description?: string | undefined;
1718
- groups?: Group[] | undefined;
1719
- lifecycle?: WorkflowLifecycle | undefined;
1720
- start?: StartBlock | undefined;
1721
- initialStage: string;
1722
- fields?: FieldEntry[] | undefined;
1723
- stages: Stage[];
1724
- predicates?: Record<string, string> | undefined;
1725
- roleAliases?: RoleAliases | undefined;
1726
- }[],
1961
+ DefinedWorkflow[],
1727
1962
  1,
1728
1963
  "a deployment needs at least one definition"
1729
1964
  >,
1730
1965
  ]
1731
1966
  >;
1967
+ readonly runtime: v.OptionalSchema<
1968
+ v.GenericSchema<RuntimeBlock>,
1969
+ undefined
1970
+ >;
1732
1971
  },
1733
1972
  undefined
1734
1973
  >,
@@ -1778,20 +2017,8 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
1778
2017
  };
1779
2018
  }[]
1780
2019
  | undefined;
1781
- definitions: {
1782
- name: string;
1783
- semantics?: Semantic[] | undefined;
1784
- title: string;
1785
- description?: string | undefined;
1786
- groups?: Group[] | undefined;
1787
- lifecycle?: WorkflowLifecycle | undefined;
1788
- start?: StartBlock | undefined;
1789
- initialStage: string;
1790
- fields?: FieldEntry[] | undefined;
1791
- stages: Stage[];
1792
- predicates?: Record<string, string> | undefined;
1793
- roleAliases?: RoleAliases | undefined;
1794
- }[];
2020
+ definitions: DefinedWorkflow[];
2021
+ runtime?: RuntimeBlock | undefined;
1795
2022
  }[],
1796
2023
  1,
1797
2024
  "a config needs at least one deployment"
@@ -1840,20 +2067,8 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
1840
2067
  };
1841
2068
  }[]
1842
2069
  | undefined;
1843
- definitions: {
1844
- name: string;
1845
- semantics?: Semantic[] | undefined;
1846
- title: string;
1847
- description?: string | undefined;
1848
- groups?: Group[] | undefined;
1849
- lifecycle?: WorkflowLifecycle | undefined;
1850
- start?: StartBlock | undefined;
1851
- initialStage: string;
1852
- fields?: FieldEntry[] | undefined;
1853
- stages: Stage[];
1854
- predicates?: Record<string, string> | undefined;
1855
- roleAliases?: RoleAliases | undefined;
1856
- }[];
2070
+ definitions: DefinedWorkflow[];
2071
+ runtime?: RuntimeBlock | undefined;
1857
2072
  }[],
1858
2073
  (
1859
2074
  issue: v.CheckIssue<
@@ -1900,20 +2115,8 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
1900
2115
  };
1901
2116
  }[]
1902
2117
  | undefined;
1903
- definitions: {
1904
- name: string;
1905
- semantics?: Semantic[] | undefined;
1906
- title: string;
1907
- description?: string | undefined;
1908
- groups?: Group[] | undefined;
1909
- lifecycle?: WorkflowLifecycle | undefined;
1910
- start?: StartBlock | undefined;
1911
- initialStage: string;
1912
- fields?: FieldEntry[] | undefined;
1913
- stages: Stage[];
1914
- predicates?: Record<string, string> | undefined;
1915
- roleAliases?: RoleAliases | undefined;
1916
- }[];
2118
+ definitions: DefinedWorkflow[];
2119
+ runtime?: RuntimeBlock | undefined;
1917
2120
  }[]
1918
2121
  >,
1919
2122
  ) => string
@@ -1962,20 +2165,8 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
1962
2165
  };
1963
2166
  }[]
1964
2167
  | undefined;
1965
- definitions: {
1966
- name: string;
1967
- semantics?: Semantic[] | undefined;
1968
- title: string;
1969
- description?: string | undefined;
1970
- groups?: Group[] | undefined;
1971
- lifecycle?: WorkflowLifecycle | undefined;
1972
- start?: StartBlock | undefined;
1973
- initialStage: string;
1974
- fields?: FieldEntry[] | undefined;
1975
- stages: Stage[];
1976
- predicates?: Record<string, string> | undefined;
1977
- roleAliases?: RoleAliases | undefined;
1978
- }[];
2168
+ definitions: DefinedWorkflow[];
2169
+ runtime?: RuntimeBlock | undefined;
1979
2170
  }[],
1980
2171
  (
1981
2172
  issue: v.CheckIssue<
@@ -2022,20 +2213,8 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2022
2213
  };
2023
2214
  }[]
2024
2215
  | undefined;
2025
- definitions: {
2026
- name: string;
2027
- semantics?: Semantic[] | undefined;
2028
- title: string;
2029
- description?: string | undefined;
2030
- groups?: Group[] | undefined;
2031
- lifecycle?: WorkflowLifecycle | undefined;
2032
- start?: StartBlock | undefined;
2033
- initialStage: string;
2034
- fields?: FieldEntry[] | undefined;
2035
- stages: Stage[];
2036
- predicates?: Record<string, string> | undefined;
2037
- roleAliases?: RoleAliases | undefined;
2038
- }[];
2216
+ definitions: DefinedWorkflow[];
2217
+ runtime?: RuntimeBlock | undefined;
2039
2218
  }[]
2040
2219
  >,
2041
2220
  ) => string
@@ -2074,21 +2253,6 @@ declare type WorkflowDefinition = v.InferOutput<
2074
2253
  typeof WorkflowDefinitionSchema
2075
2254
  >;
2076
2255
 
2077
- /**
2078
- * Structural schema for a STORED workflow definition — primitives only,
2079
- * every reference scope resolved. Cross-field invariants (unique names,
2080
- * transition targets, effect-name uniqueness, predicate shadowing) are
2081
- * checked by `checkWorkflowInvariants` after desugar — see `defineWorkflow`.
2082
- * Carries NO `version`: a definition's version and content fingerprint are
2083
- * stamped onto the deployed document at deploy time, derived from the
2084
- * content itself, so redeploying identical content is a no-op and any
2085
- * change mints the next version.
2086
- *
2087
- * Exported (module-level, not package API) for the model-surface gate's
2088
- * coverage test and for `parseStoredDefinition` — the boundary parse for a
2089
- * definition that did not come out of `defineWorkflow` in-process; trusted
2090
- * in-process desugar output is never re-parsed.
2091
- */
2092
2256
  declare const WorkflowDefinitionSchema: v.GenericSchema<
2093
2257
  WorkflowFields<FieldEntry, Stage, StartBlock>
2094
2258
  >;
@@ -2100,10 +2264,22 @@ declare const WorkflowDefinitionSchema: v.GenericSchema<
2100
2264
  declare type WorkflowDeployment = WorkflowConfig["deployments"][number];
2101
2265
 
2102
2266
  /**
2103
- * What an author writes for one deployment: the highest reader model verified
2104
- * across runtimes sharing its workflow resource. Runtime validation compares
2105
- * it with the submitted definitions, so a dependency upgrade alone does not
2106
- * require changing the literal.
2267
+ * Author one deployment with a nonempty `definitions` array and a
2268
+ * {@link WorkflowResource}. Dataset resource IDs use `<projectId>.<dataset>`.
2269
+ *
2270
+ * `name` and `tag` must contain only ASCII lowercase letters, digits, and dashes,
2271
+ * starting with a letter or digit. Deployment names and `(workflowResource, tag)`
2272
+ * pairs must be unique across the config. Optional `resourceAliases` use the same
2273
+ * name grammar, with unique names within this deployment.
2274
+ *
2275
+ * `expectedMinReaderModel` is the highest reader model you have verified across
2276
+ * runtimes sharing the workflow resource. Supply a reviewed numeric literal.
2277
+ * Definition submission checks it against the required reader floor; upgrading
2278
+ * a dependency alone does not require changing it.
2279
+ *
2280
+ * `runtime` is the default hosting kind for this deployment's workflows, which
2281
+ * each workflow and effect may override. Omitted, its workflows host on
2282
+ * `'function'`.
2107
2283
  */
2108
2284
  declare type WorkflowDeploymentInput = Omit<
2109
2285
  WorkflowDeployment,