@sanity/workflow-engine 0.29.0 → 0.30.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/index.d.cts CHANGED
@@ -57,6 +57,12 @@ export declare function acceptsDocumentType(
57
57
  documentType: string,
58
58
  ): boolean;
59
59
 
60
+ /** A parsed deployment after its reader-model acknowledgement has been
61
+ * validated against the definitions a command will submit. */
62
+ export declare type AcknowledgedWorkflowDeployment = WorkflowDeployment & {
63
+ expectedMinReaderModel: number;
64
+ };
65
+
60
66
  /**
61
67
  * The URL path a resource's ACL is served at — where the engine fetches an
62
68
  * actor's grants for that resource (and the canonical encoding of the shape
@@ -79,6 +85,21 @@ export declare function aclPathForResource(
79
85
  res: WorkflowResource,
80
86
  ): string | undefined;
81
87
 
88
+ /**
89
+ * A stored action. `semantics` is engine-owned advisory meaning, independent
90
+ * of execution and presentation — an array so the vocabulary can grow without
91
+ * reshaping this field. `when`'s presence makes the action CASCADE-FIRED: the
92
+ * engine fires it the moment the condition turns true, at most once per stage
93
+ * visit, and it is never invocable via `fireAction`; absent, the action must
94
+ * be invoked via `fireAction` by any caller holding a token (fire-on-entry is
95
+ * `when: 'true'`). `filter` is existence with GROQ semantics — a non-matching
96
+ * action might as well not exist (invisible to UI and LLMs, never merely
97
+ * disabled); on a `when` action it composes: `filter` scopes whether the
98
+ * automation exists, `when` is its firing trigger. `roles` is kept VERBATIM
99
+ * only when cascade-fired (the pin on which identities may execute the
100
+ * trigger); a fireAction-fired action's `roles` folds into `filter` at
101
+ * desugar instead.
102
+ */
82
103
  export declare type Action = ActionFields<Op, string[]> & {
83
104
  roles?: string[] | undefined;
84
105
  };
@@ -184,14 +205,14 @@ declare type ActionFields<TOp, TGroup> = {
184
205
 
185
206
  export declare type ActionName = string;
186
207
 
187
- export declare type ActionParam = v.InferOutput<typeof ActionParamSchema>;
188
-
189
208
  /**
190
- * Caller-supplied params declared on an action. The engine validates
191
- * incoming `params` against this list before running ops or queuing
192
- * effects: missing required params ActionParamsInvalidError, action
193
- * does not commit. Resolved values feed `ValueExpr.param` lookups.
209
+ * Caller-supplied params declared on an action, validated before running ops
210
+ * or queuing effects: a missing required param throws
211
+ * `ActionParamsInvalidError` and the action does not commit. Resolved values
212
+ * feed `ValueExpr.param` lookups.
194
213
  */
214
+ export declare type ActionParam = v.InferOutput<typeof ActionParamSchema>;
215
+
195
216
  declare const ActionParamSchema: v.SchemaWithPipe<
196
217
  readonly [
197
218
  v.StrictObjectSchema<
@@ -363,17 +384,26 @@ export declare function actionRendering(action: {
363
384
 
364
385
  export declare type ActionSemantic = DecisionSemantic | Semantic;
365
386
 
366
- /** The fireable-action verdict for one action on an activity — its `allowed`
367
- * state, structured `disabledReason`, and declared params, tagged with the
368
- * owning activity. The per-action atom both projections share:
369
- * {@link availableActions} flattens it across a stage's activities; a consumer
370
- * that keeps per-activity nesting (e.g. the MCP) maps it over an activity's actions
371
- * directly, so the verdict shape has a single source. */
387
+ /** The per-action verdict shape shared by every projection: {@link availableActions} flattens it, a per-activity consumer (e.g. the MCP) maps it directly both must stay on this one builder. */
372
388
  export declare function actionVerdict(
373
389
  activity: ActivityEvaluation,
374
390
  action: ActionEvaluation,
375
391
  ): AvailableAction;
376
392
 
393
+ /**
394
+ * A unit of work carrying no payload of its own — every op, effect, and
395
+ * spawn lives on an action; an activity contributes scoped `fields`
396
+ * (resolved at stage entry), existence (`filter`), advisory readiness
397
+ * (`requirements`), and the off-system marker (`target`, a BPMN Manual Task
398
+ * deep-link, render-only and never gating). All in-scope activities are
399
+ * ACTIVE from stage entry until an action's terminal `status` resolves them —
400
+ * there is no activation moment. `filter` is existence with GROQ semantics,
401
+ * evaluated once against the stage's entry state: a definite `false`
402
+ * excludes the activity from UI, LLMs, and `$allActivitiesDone`.
403
+ * `requirements` are readiness gates orthogonal to `filter` — an unmet one
404
+ * keeps the activity visible but disables its actions with a
405
+ * `requirements-unmet` verdict; distinct from ACL and guards.
406
+ */
377
407
  export declare type Activity = ActivityFields<
378
408
  FieldEntry,
379
409
  Action,
@@ -410,6 +440,12 @@ export declare const ACTIVITY_KIND_DISPLAY: {
410
440
  };
411
441
  };
412
442
 
443
+ /**
444
+ * BPMN-aligned classification of an activity by its EXECUTOR. Purely
445
+ * advisory and always DERIVED from the activity's shape (`target` marks
446
+ * off-system manual work, action shapes decide the rest) — it changes no
447
+ * gating or runtime.
448
+ */
413
449
  export declare const ACTIVITY_KINDS: readonly [
414
450
  "user",
415
451
  "service",
@@ -419,14 +455,10 @@ export declare const ACTIVITY_KINDS: readonly [
419
455
  ];
420
456
 
421
457
  /**
422
- * Leaf vocabularies that both the authoring schema and the engine address by
423
- * name. Some exported types also include grammar-validated open values that
424
- * cannot be enumerated by a const array.
425
- *
426
- * This module imports nothing. It is the schema-free foundation that
427
- * `../define/schema.ts` reads its value constants from, which is what keeps
428
- * the type model and the valibot schema free of an import cycle: the value edge
429
- * `schema.ts → enums.ts` terminates here.
458
+ * An activity is `active` from stage entry (or `skipped` when its `filter`
459
+ * excluded it) until a terminal status resolves it there is no pre-active
460
+ * state. The authored action `status:` sugar (and the `status.set` op it
461
+ * desugars to) is constrained to {@link TerminalActivityStatus}.
430
462
  */
431
463
  declare const ACTIVITY_STATUSES: readonly [
432
464
  "active",
@@ -594,8 +626,24 @@ export declare interface Actor {
594
626
  onBehalfOf?: string;
595
627
  }
596
628
 
629
+ /**
630
+ * WHO is acting: a human, an LLM, or automated machinery. The `system` kind
631
+ * covers both the engine's own housekeeping and external services;
632
+ * {@link DriverKind} splits that for the audit-trail glyph.
633
+ */
597
634
  export declare const ACTOR_KINDS: readonly ["person", "agent", "system"];
598
635
 
636
+ /** Runtime counterpart of {@link expandRequiredRoles}; both expand only the required side. */
637
+ export declare function actorFulfillsRole({
638
+ actorRoles,
639
+ required,
640
+ aliases,
641
+ }: {
642
+ actorRoles: readonly string[] | undefined;
643
+ required: string;
644
+ aliases: RoleAliases | undefined;
645
+ }): boolean;
646
+
599
647
  export declare type ActorKind = (typeof ACTOR_KINDS)[number];
600
648
 
601
649
  export declare type ActorResolution<User> =
@@ -653,16 +701,9 @@ export declare function applicableDefinitions<
653
701
  }): Promise<T[]>;
654
702
 
655
703
  /**
656
- * The data-model gate every engine read of an engine-owned document passes
657
- * through point reads, list queries, projections, and snapshot hydration's
658
- * raw reads (the structural exceptionsexistence-only probes and lake-side
659
- * GROQ filters — are declared in DATAMODEL.md). Throws
660
- * {@link ModelVersionAheadError} only when the document's
661
- * {@link minReaderModelOf reader floor} is ahead of
662
- * {@link DATA_MODEL_VERSION}; a doc stamped by a NEWER model whose changes
663
- * were additive keeps its old floor and reads fine — mixed-version fleets
664
- * interoperate across additive evolution. A missing stamp is model 0 and
665
- * always readable.
704
+ * Throws {@link ModelVersionAheadError} only when the document's reader floor exceeds
705
+ * {@link DATA_MODEL_VERSION}. A doc from a NEWER engine whose changes were purely additive
706
+ * keeps its old (lower) floor and still reads fine — only reader-floor-raising changes block a read.
666
707
  */
667
708
  export declare function assertReadableModel<
668
709
  T extends {
@@ -672,8 +713,11 @@ export declare function assertReadableModel<
672
713
 
673
714
  export declare function assertReaderModelAcknowledgement(
674
715
  expectedMinReaderModel: unknown,
675
- context?: string,
676
- ): asserts expectedMinReaderModel is typeof DATA_MODEL_MIN_READER;
716
+ options: {
717
+ requiredMinReaderModel: number;
718
+ context?: string;
719
+ },
720
+ ): asserts expectedMinReaderModel is number;
677
721
 
678
722
  /**
679
723
  * One member of an `assignees`-kind entry's value — and the value of the
@@ -721,6 +765,18 @@ export declare const AUTHORING_DISPLAY: {
721
765
  };
722
766
  };
723
767
 
768
+ /**
769
+ * The stored action fields plus two authoring sugars, or the
770
+ * {@link ClaimAction} pair-half. `roles`: on a fireAction-fired action (no
771
+ * `when`) it desugars into a `count($actor.roles[@ in [...]]) > 0` condition
772
+ * ANDed with `filter`; on a CASCADE-FIRED action it stores VERBATIM instead —
773
+ * the pin on which identities may execute the trigger, since folding it into
774
+ * `filter` would make the action's existence depend on whose token cascades.
775
+ * `roleAliases` widens the membership either way. `status` compiles to a
776
+ * `status.set` op on the firing activity, appended AFTER the authored ops —
777
+ * deliberately never implied, so a forgotten `status` is a visible stall
778
+ * rather than a silently completed action.
779
+ */
724
780
  export declare type AuthoringAction = AuthoringRawAction | ClaimAction;
725
781
 
726
782
  export declare type AuthoringActivity = ActivityFields<
@@ -730,16 +786,16 @@ export declare type AuthoringActivity = ActivityFields<
730
786
  GroupMembership
731
787
  >;
732
788
 
733
- export declare type AuthoringEditable = v.InferOutput<
734
- typeof AuthoringEditableSchema
735
- >;
736
-
737
789
  /**
738
790
  * Authoring editability adds the `role[]` convenience: a non-empty role list
739
791
  * desugars to the same `count($actor.roles[@ in [...]]) > 0` membership
740
792
  * predicate `action.roles` produces. `true` opens the field to anyone in its
741
793
  * window; a bare string is a raw predicate.
742
794
  */
795
+ export declare type AuthoringEditable = v.InferOutput<
796
+ typeof AuthoringEditableSchema
797
+ >;
798
+
743
799
  declare const AuthoringEditableSchema: v.UnionSchema<
744
800
  [
745
801
  v.LiteralSchema<true, undefined>,
@@ -768,6 +824,8 @@ export declare type AuthoringFieldEntry =
768
824
  | TodoListField
769
825
  | NotesField;
770
826
 
827
+ /** A field reference with `scope` optional; desugar resolves it lexically
828
+ * (activity → stage → workflow) into {@link StoredFieldRef}. */
771
829
  declare type AuthoringFieldRef = v.InferOutput<typeof AuthoringFieldRefSchema>;
772
830
 
773
831
  declare const AuthoringFieldRefSchema: v.StrictObjectSchema<
@@ -786,15 +844,12 @@ declare const AuthoringFieldRefSchema: v.StrictObjectSchema<
786
844
  undefined
787
845
  >;
788
846
 
847
+ /** {@link Guard}'s contract as authored: `match.idRefs` and `metadata` carry
848
+ * typed {@link GuardRead} values that deploy resolves to bare ones. */
789
849
  export declare type AuthoringGuard = v.InferOutput<typeof AuthoringGuardSchema>;
790
850
 
791
851
  declare const AuthoringGuardSchema: v.StrictObjectSchema<
792
852
  {
793
- /**
794
- * Lake-id-segment grammar (`^[a-z0-9][a-z0-9-]*$`, deploy-enforced): the
795
- * guard's lake `_id` derives from `(instanceId, name)` at stage entry.
796
- * Unique per definition.
797
- */
798
853
  name: v.SchemaWithPipe<
799
854
  readonly [
800
855
  v.StringSchema<undefined>,
@@ -805,7 +860,6 @@ declare const AuthoringGuardSchema: v.StrictObjectSchema<
805
860
  description: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
806
861
  match: v.StrictObjectSchema<
807
862
  {
808
- /** Subject `_type`(s); empty matches any type. */
809
863
  types: v.OptionalSchema<
810
864
  v.ArraySchema<
811
865
  v.SchemaWithPipe<
@@ -818,7 +872,6 @@ declare const AuthoringGuardSchema: v.StrictObjectSchema<
818
872
  >,
819
873
  undefined
820
874
  >;
821
- /** Target docs as field reads (or the instance itself), resolved at deploy to bare ids + the resource. */
822
875
  idRefs: v.OptionalSchema<
823
876
  v.ArraySchema<
824
877
  v.VariantSchema<
@@ -921,7 +974,6 @@ declare const AuthoringGuardSchema: v.StrictObjectSchema<
921
974
  >,
922
975
  undefined
923
976
  >;
924
- /** Glob id patterns (bare, resource-local). */
925
977
  idPatterns: v.OptionalSchema<
926
978
  v.ArraySchema<
927
979
  v.SchemaWithPipe<
@@ -953,22 +1005,7 @@ declare const AuthoringGuardSchema: v.StrictObjectSchema<
953
1005
  },
954
1006
  undefined
955
1007
  >;
956
- /**
957
- * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
958
- * reading the `before()`/`after()` natives, `mutation`, `guard`, and
959
- * `identity()`. Bare ids/fields only. Polarity: a result of strictly
960
- * `true` ALLOWS the matched mutation; anything else (false, null, an
961
- * evaluation error) DENIES. Omitted or empty means UNCONDITIONAL DENY.
962
- */
963
1008
  predicate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
964
- /**
965
- * Projected workflow fields the predicate reads as `guard.metadata.*` —
966
- * the only bridge from the lake eval context (which cannot see `$fields`)
967
- * to workflow fields. Each value is a deploy-time read — a typed
968
- * {@link GuardRead} when authoring, the printed string spelling once
969
- * stored — resolved into a bare value at deploy and re-synced by the
970
- * post-field-op guard refresh.
971
- */
972
1009
  metadata: v.OptionalSchema<
973
1010
  v.RecordSchema<
974
1011
  v.SchemaWithPipe<
@@ -1078,6 +1115,8 @@ declare const AuthoringGuardSchema: v.StrictObjectSchema<
1078
1115
  undefined
1079
1116
  >;
1080
1117
 
1118
+ /** Like {@link ManualTarget}, but the `field` variant also accepts a bare
1119
+ * field name; desugar normalises it into {@link AuthoringFieldRef}. */
1081
1120
  export declare type AuthoringManualTarget = v.InferOutput<
1082
1121
  typeof AuthoringManualTargetSchema
1083
1122
  >;
@@ -1137,6 +1176,9 @@ declare const AuthoringManualTargetSchema: v.VariantSchema<
1137
1176
  undefined
1138
1177
  >;
1139
1178
 
1179
+ /** Like {@link Op}, plus: `status.set`'s `activity` is optional (desugar fills
1180
+ * the firing activity), and the `audit` sugar — a stamped append merging
1181
+ * `actor`/`at` {@link ValueExpr} fields into its own value. */
1140
1182
  export declare type AuthoringOp = v.InferOutput<typeof AuthoringOpSchema>;
1141
1183
 
1142
1184
  declare const AuthoringOpSchema: v.VariantSchema<
@@ -1432,27 +1474,6 @@ declare const AuthoringOpSchema: v.VariantSchema<
1432
1474
  undefined
1433
1475
  >;
1434
1476
 
1435
- /**
1436
- * Authoring action — the stored fields plus two field sugars with one
1437
- * defined expansion each:
1438
- *
1439
- * - `roles` — on a fireAction-fired action (no `when`) it desugars to a
1440
- * `count($actor.roles[@ in [...]]) > 0` membership condition ANDed with
1441
- * the authored `filter` (for a caller, "not yours to fire" and "doesn't
1442
- * exist for you" are the same advisory answer). On a CASCADE-FIRED
1443
- * action it stores VERBATIM — the pin on which identities may execute
1444
- * the trigger; folding it into `filter` would make the action's
1445
- * existence depend on whose token happens to cascade. The definition's
1446
- * `roleAliases` ({@link RoleAliasesSchema}) widen the membership either
1447
- * way.
1448
- * - `status` → a `status.set` op on the firing activity, appended **after**
1449
- * the authored ops (deliberately never implied: a forgotten explicit
1450
- * `status` is a visible stall, an implied default silently completes
1451
- * claim-like actions). Status is the health axis: a decision action
1452
- * (decline, send back) resolves `done` and writes the decision into a
1453
- * field the transition trigger reads — `failed` is for work that
1454
- * genuinely could not complete.
1455
- */
1456
1477
  declare type AuthoringRawAction = ActionFields<AuthoringOp, GroupMembership> & {
1457
1478
  roles?: string[] | undefined;
1458
1479
  status?: TerminalActivityStatus | undefined;
@@ -1580,31 +1601,21 @@ export declare interface AvailableAction {
1580
1601
  params: ActionParam[];
1581
1602
  }
1582
1603
 
1583
- /** Flatten an evaluation's current-stage activities into the actions the actor
1584
- * could fire, each carrying whether it's allowed (and why not). A
1585
- * filter-scoped-out activity does not exist for this visit, so its actions
1586
- * never list — the same {@link ActivityEvaluation.scopedOut} split every
1587
- * other surface applies. */
1604
+ /** Excludes a `scopedOut` activity's actions, matching the same split every other surface applies to filter-scoped-out activities. */
1588
1605
  export declare function availableActions(
1589
1606
  activities: ActivityEvaluation[],
1590
1607
  ): AvailableAction[];
1591
1608
 
1592
- /** The `workflow.availableActions` result the projected actions plus the
1593
- * evaluation they came from, so a consumer can read the instance/stage
1594
- * context without a second projection. */
1609
+ /** Pairs the projected actions with the evaluation they came from, so a consumer reads instance/stage context without a second call. */
1595
1610
  export declare interface AvailableActionsResult {
1596
1611
  evaluation: WorkflowEvaluation;
1597
1612
  actions: AvailableAction[];
1598
1613
  }
1599
1614
 
1600
- /**
1601
- * Type each caller-supplied name→value against the workflow's declared field
1602
- * entries — the engine takes typed {@link InitialFieldValue}s, and a value's
1603
- * type IS its declared entry's kind. Only `input`-sourced entries read caller
1604
- * values, so anything else fails here, naming the fields that ARE settable.
1605
- * The engine repeats this structural validation at its contract boundary;
1606
- * value validation also stays there.
1607
- */
1615
+ /** Builds the start payload's field rows from caller values: accepts only
1616
+ * declared `input`-sourced entries and throws on an unknown or non-input
1617
+ * name. Structural validation only — the engine repeats value-kind
1618
+ * validation at its own start boundary, not here. */
1608
1619
  export declare function buildInitialFields({
1609
1620
  declared,
1610
1621
  values,
@@ -1614,18 +1625,8 @@ export declare function buildInitialFields({
1614
1625
  }): InitialFieldValue[];
1615
1626
 
1616
1627
  /**
1617
- * Build a snapshot from a set of loaded docs. Pure transform.
1618
- *
1619
- * For each `LoadedDoc { doc, resource }`:
1620
- * - The doc's `_id` is rewritten to `gdrFromResource(resource, _id)`.
1621
- * - Every nested `_ref` value (recursively, through objects and arrays)
1622
- * is rewritten the same way: bare ref → URI in the parent's resource.
1623
- * Already-qualified `_ref` URIs (containing `:`) are left alone.
1624
- *
1625
- * Plain string fields, numbers, booleans — anything that isn't an
1626
- * object with a `_ref` field — pass through untouched. The rewriter is
1627
- * structural, not schema-aware: only the `_ref` field on an object is
1628
- * treated as a Sanity reference. Everything else is user data.
1628
+ * Rewrites each doc's `_id` and every nested `_ref` field to GDR URI form,
1629
+ * recursing through objects/arrays; already-URI `_ref`s pass through unchanged.
1629
1630
  */
1630
1631
  export declare function buildSnapshot(args: {
1631
1632
  docs: LoadedDoc[];
@@ -1678,14 +1679,8 @@ export declare interface ChoiceOptions {
1678
1679
 
1679
1680
  export declare type ChoiceValue = string | number;
1680
1681
 
1681
- /**
1682
- * The action half of the mirrored claim pair. `field` references an
1683
- * author-declared actor-valued entry (the pair's other half), resolved
1684
- * lexically. Expansion, strictly within this action: a no-steal
1685
- * `!defined($fields.<field>)` filter ANDed with `roles`/`filter`, plus a
1686
- * `field.set` ← actor op. `ops` and `status` are reserved (the expansion
1687
- * owns them) — strictObject rejects them as unknown keys.
1688
- */
1682
+ /** The action half of the mirrored claim pair: `field` names the actor-valued entry this action claims, resolved lexically, and the expansion
1683
+ * adds a no-steal `!defined($fields.<field>)` filter ANDed with `roles`/`filter` plus a `field.set` actor op. `ops`/`status` are reserved (strictObject rejects them). */
1689
1684
  declare type ClaimAction = {
1690
1685
  type: "claim";
1691
1686
  name: string;
@@ -1699,12 +1694,8 @@ declare type ClaimAction = {
1699
1694
  effects?: Effect[] | undefined;
1700
1695
  };
1701
1696
 
1702
- /**
1703
- * Authoring fields accept the raw entries plus the `claim` sugar type the
1704
- * field half of the mirrored claim pair. Expansion: an `actor` working-
1705
- * memory field (no `initialValue`; the claim action's op fills it), strictly
1706
- * within this entry.
1707
- */
1697
+ /** The field half of the mirrored claim pair, expanding strictly within this entry: an `actor`
1698
+ * working-memory field with no `initialValue` the paired {@link ClaimAction}'s op fills it. */
1708
1699
  declare type ClaimField = {
1709
1700
  type: "claim";
1710
1701
  name: string;
@@ -1771,14 +1762,9 @@ export declare interface ClientProjectUser {
1771
1762
  readonly email?: string;
1772
1763
  readonly imageUrl?: string | null;
1773
1764
  /**
1774
- * Which identity provider the person signs in with (`google`, `github`, or a
1775
- * `saml-<name>` deployment)display only.
1776
- *
1777
- * Both spellings are declared because the two project-user endpoints
1778
- * disagree: the project-hosted `/users/<id>` the adapters read answers
1779
- * `provider`, while the management `/projects/<id>/users/<id>` answers
1780
- * `loginProvider`. Read them through {@link userLoginProvider} rather than
1781
- * picking one.
1765
+ * Display only. Both spellings exist because the two project-user
1766
+ * endpoints disagree on which they answer read through
1767
+ * {@link userLoginProvider} rather than picking one.
1782
1768
  */
1783
1769
  readonly provider?: string;
1784
1770
  readonly loginProvider?: string;
@@ -1876,10 +1862,7 @@ export declare interface CompiledQuery {
1876
1862
  params: Record<string, string | string[]>;
1877
1863
  }
1878
1864
 
1879
- /** Assemble a persisted guard doc from resolved pieces. Deliberately carries
1880
- * NO engine data-model stamp: the guard doc format is the lake's forthcoming
1881
- * contract, not ours to grow fields on — its versioning event is the
1882
- * {@link GUARD_DOC_TYPE} cutover itself (see DATAMODEL.md). */
1865
+ /** Deliberately carries NO engine data-model stamp: the guard doc format is the lake's forthcoming contract, not ours to grow fields on (see DATAMODEL.md). */
1883
1866
  export declare function compileGuard(args: CompileGuardArgs): MutationGuardDoc;
1884
1867
 
1885
1868
  declare interface CompileGuardArgs extends MutationGuardBody {
@@ -2033,10 +2016,23 @@ export declare class ConcurrentFireActionError extends WorkflowError<"concurrent
2033
2016
  export declare type Condition = string;
2034
2017
 
2035
2018
  /**
2036
- * Every variable the engine binds for conditions, in one place. The
2037
- * deploy-time shadow check ({@link RESERVED_CONDITION_VARS}) and the docs on
2038
- * {@link Condition} derive from this list — extend it here when the engine
2039
- * grows a binding, never in a comment elsewhere.
2019
+ * Every variable the engine binds for the RENDERED condition scope (every
2020
+ * condition site: transition `when`s, activity filters, action
2021
+ * `when`s/filters, effect bindings, `spawn` reads, where-op `where`s,
2022
+ * editability predicates, author predicates) the deploy-time shadow check
2023
+ * ({@link RESERVED_CONDITION_VARS}) and the docs on {@link Condition} derive
2024
+ * from this list; extend it here when the engine grows a binding, never in
2025
+ * a comment elsewhere.
2026
+ *
2027
+ * Three other GROQ contexts read a definition and do NOT share this
2028
+ * inventory: cascade gates (transition/activity/cascade-action gates, which
2029
+ * must resolve identically regardless of caller — only the `'always'`-bound
2030
+ * subset carries values, {@link FILTER_SCOPE_VARS}); the start contexts
2031
+ * (`start.filter` is browse-time-pure over a candidate document,
2032
+ * {@link START_FILTER_VARS}; a start `groq` requirement binds `$fields`
2033
+ * instead, {@link START_REQUIREMENT_VARS}); and lake guard predicates, which
2034
+ * are not conditions at all — delta-mode GROQ over a mutation, binding
2035
+ * {@link GUARD_PREDICATE_VARS} instead.
2040
2036
  */
2041
2037
  export declare const CONDITION_VARS: readonly ConditionVar[];
2042
2038
 
@@ -2048,13 +2044,10 @@ export { ConditionClause };
2048
2044
 
2049
2045
  export { ConditionDescription };
2050
2046
 
2051
- /**
2052
- * Every STATIC `$fields.<name>` (or `$fields['<name>']` groq-js normalises
2053
- * both to `AccessAttribute`) read in a condition, from the AST. Dynamic access
2054
- * (`$fields[$var]`) carries no static name and is not collected. A malformed
2055
- * condition reads nothing here ({@link conditionSyntaxIssues} owns the parse
2056
- * error).
2057
- */
2047
+ /** Static `$fields.<name>` / `$fields['<name>']` reads (both normalise to the
2048
+ * same AST node); `$fields[$var]` dynamic access has no static name and is skipped.
2049
+ * A malformed condition reads nothing here rather than throwing the deploy-time
2050
+ * syntax check owns the parse error. */
2058
2051
  export declare function conditionFieldReadNames(
2059
2052
  groq: string,
2060
2053
  ): ReadonlySet<string>;
@@ -2090,43 +2083,6 @@ export declare interface ConditionVar {
2090
2083
  label: string;
2091
2084
  }
2092
2085
 
2093
- /**
2094
- * The condition-variable inventory — the single source of truth for every
2095
- * `$var` the engine binds when it evaluates a {@link Condition}.
2096
- *
2097
- * Four evaluation contexts read a definition's GROQ:
2098
- *
2099
- * 1. **Rendered condition scope** — every condition site in a definition
2100
- * (transition `when`s, activity filters, action `when`s/filters, effect
2101
- * bindings, `spawn` reads, where-op `where`s, editability predicates,
2102
- * author predicates). {@link CONDITION_VARS} is its inventory; each
2103
- * entry's `binding` says when the var actually holds a value. The
2104
- * where-op context is the one closed subset — its bound set is statically
2105
- * fixed and deploy-enforced (see the op-where scope's param-name list in
2106
- * the op applier).
2107
- * 2. **Cascade gates** — transition `when`s, activity filters, and a
2108
- * cascade-fired action's `when`/`filter` must resolve identically no
2109
- * matter whose token drives the cascade, so only the `'always'`-bound
2110
- * subset carries values there ({@link FILTER_SCOPE_VARS}). Caller-bound
2111
- * vars fail closed — `$assigned` binds its caller-free constant `false`,
2112
- * the rest evaluate to `undefined` — and deploy rejects them at these
2113
- * sites; a cascade-fired action's per-token gate is `roles`, never its
2114
- * conditions.
2115
- * 3. **The start contexts** — a definition's `start.filter` and start GROQ
2116
- * requirements evaluate against a CANDIDATE (no instance exists yet):
2117
- * `*[...]` reads the engine-owned `{definition, subject, completedAt}`
2118
- * projection of the tag's instances and none of the rendered
2119
- * condition vars exist. The two split on what a surface can know:
2120
- * `filter` is browse-time-pure (candidate document as root,
2121
- * {@link START_FILTER_VARS} — no `$fields`, which cannot exist before
2122
- * inputs do), a `groq` requirement is the start-time readiness predicate
2123
- * ({@link START_REQUIREMENT_VARS} — `$fields` bound, never a root).
2124
- * 4. **Guard predicates** — NOT conditions. A lake mutation guard's
2125
- * `predicate` is groq-js **delta-mode** GROQ over a document mutation:
2126
- * `before()`/`after()`/`identity()` are dialect natives, and the wire
2127
- * format binds the identifiers in {@link GUARD_PREDICATE_VARS}. None of
2128
- * the condition vars exist there.
2129
- */
2130
2086
  /**
2131
2087
  * When a condition var holds a value:
2132
2088
  *
@@ -2264,11 +2220,7 @@ export declare type ContextEntry =
2264
2220
  value: string;
2265
2221
  };
2266
2222
 
2267
- /**
2268
- * Render the instance's `context` bag as the `$context` map — the
2269
- * start-time seed plus a parent's spawn handoff. `json` entries decode to
2270
- * their object form.
2271
- */
2223
+ /** `$context`: the context bag as a map by name; `json` entries decode to their object form. */
2272
2224
  export declare function contextMap(
2273
2225
  instance: Pick<WorkflowInstance, "context">,
2274
2226
  ): Record<string, unknown>;
@@ -2379,11 +2331,7 @@ export declare function createTelemetryIntake(args: {
2379
2331
  /** A define-time validated `custom.<camelCaseMeaning>` value. */
2380
2332
  export declare type CustomSemantic = `custom.${string}`;
2381
2333
 
2382
- /**
2383
- * The append-only, machine-readable counterpart of the model log in
2384
- * `DATAMODEL.md`. It records compatibility decisions; the prose log retains
2385
- * the reasoning, absent-value semantics, and old-writer round-trip proof.
2386
- */
2334
+ /** Append-only, machine-readable counterpart of the model log in DATAMODEL.md, which keeps the full reasoning. */
2387
2335
  export declare const DATA_MODEL_CHANGES: readonly [
2388
2336
  Readonly<{
2389
2337
  id: "governed-model-stamps";
@@ -2502,14 +2450,24 @@ export declare const DATA_MODEL_CHANGES: readonly [
2502
2450
  applicability: "unconditional";
2503
2451
  summary: string;
2504
2452
  }>,
2453
+ Readonly<{
2454
+ id: "role-constrained-assignment-fields";
2455
+ introducedInModel: 8;
2456
+ minReaderModel: 8;
2457
+ documentTypes: readonly ["definition", "instance"];
2458
+ compatibility: "reader-floor";
2459
+ applicability: "detectable";
2460
+ summary: "Assignee fields may restrict newly assigned users and collective roles by role.";
2461
+ }>,
2505
2462
  ];
2506
2463
 
2464
+ /** The maximum reader floor this writer can emit for a detectable feature. */
2465
+ export declare const DATA_MODEL_MAX_READER = 8;
2466
+
2507
2467
  /**
2508
- * The maximum reader floor this writer can emit. Individual documents derive
2509
- * their `minReaderModel` from the compatibility-bearing features actually
2510
- * present; a document written at {@link DATA_MODEL_VERSION} may therefore
2511
- * carry a lower floor. Raising this maximum is a declared, DATAMODEL.md-logged
2512
- * decision that requires readers-first fleet sequencing.
2468
+ * The unconditional model-4 reader floor for every engine-owned document.
2469
+ * Detectable features may raise an individual document through
2470
+ * {@link DATA_MODEL_MAX_READER}.
2513
2471
  */
2514
2472
  export declare const DATA_MODEL_MIN_READER = 4;
2515
2473
 
@@ -2522,11 +2480,11 @@ export declare const DATA_MODEL_MIN_READER = 4;
2522
2480
  * honestly record whichever engine last shaped a doc.
2523
2481
  *
2524
2482
  * Bump on every declared shape change (additive included). Bumping does NOT
2525
- * by itself lock out older engines — that is {@link DATA_MODEL_MIN_READER}'s
2526
- * job. Declare every bump in `DATAMODEL.md`; the model-surface snapshot test
2527
- * keeps undeclared drift red.
2483
+ * by itself lock out older engines — that is the document's derived
2484
+ * `minReaderModel` floor. Declare every bump in `DATAMODEL.md`; the model-surface snapshot test
2485
+ * fails on undeclared drift.
2528
2486
  */
2529
- export declare const DATA_MODEL_VERSION = 7;
2487
+ export declare const DATA_MODEL_VERSION = 8;
2530
2488
 
2531
2489
  export declare interface DataModelChange {
2532
2490
  readonly id: string;
@@ -2689,23 +2647,9 @@ export declare class DefinitionInUseError extends WorkflowError<"definition-in-u
2689
2647
  }
2690
2648
 
2691
2649
  /**
2692
- * Pure GROQ builders for deployed workflow definitions. Composes the doc-type
2693
- * constant and the tag-scope predicate so the engine's internal lookups and the
2694
- * CLI share one definition of "tag-scoped, latest-or-pinned
2695
- * `workflow.definition`" instead of hand-writing the query at each call site.
2696
- *
2697
- * The tag enumerations are the deliberate exception: they span partitions, for a
2698
- * caller holding a resource but no tag yet.
2699
- */
2700
- /**
2701
- * GROQ resolving a single deployed {@link WORKFLOW_DEFINITION_TYPE} visible to
2702
- * the caller's tag. With {@link explicit} the query pins `$version`; otherwise
2703
- * it returns the highest deployed version.
2704
- *
2705
- * Params: `$definition`, `$tag`, plus `$version` when {@link explicit}.
2706
- *
2707
- * @param explicit - whether the caller wants a specific version (`$version`)
2708
- * rather than the latest.
2650
+ * GROQ resolving a single deployed {@link WORKFLOW_DEFINITION_TYPE} for the
2651
+ * caller's tag pinned to `$version` when {@link explicit}, else the highest
2652
+ * deployed version. Params: `$definition`, `$tag`, plus `$version` when explicit.
2709
2653
  */
2710
2654
  export declare function definitionLookupGroq(explicit: boolean): string;
2711
2655
 
@@ -2862,10 +2806,9 @@ export declare interface DeployDefinitionsArgs<
2862
2806
  T extends WorkflowDefinitionInput<T> = WorkflowDefinition,
2863
2807
  > {
2864
2808
  /**
2865
- * Reviewed numeric literal acknowledging the installed writer's maximum reader-floor capability.
2866
- * The deploy gate checks the exact installed value and links the readers-first rollout; do not
2867
- * import {@link DATA_MODEL_MIN_READER}, because that would auto-advance this acknowledgement on
2868
- * upgrade.
2809
+ * Highest reader model verified across runtimes sharing the workflow resource. The deploy gate
2810
+ * compares this reviewed numeric literal with the submitted definitions; do not import
2811
+ * either exported reader constant, because a dependency upgrade must not change it automatically.
2869
2812
  */
2870
2813
  expectedMinReaderModel: number;
2871
2814
  /**
@@ -2911,8 +2854,8 @@ export declare type DeployedDefinition = WorkflowDefinition & {
2911
2854
  /** Engine data-model stamp (see {@link DATA_MODEL_VERSION}) — absent on
2912
2855
  * documents deployed before the stamp existed (model 0). */
2913
2856
  modelVersion?: number;
2914
- /** Reader floor (see {@link DATA_MODEL_MIN_READER}) the oldest engine
2915
- * data model that can safely interpret this document. */
2857
+ /** The oldest engine data model that can safely interpret this document,
2858
+ * derived from its persisted features and the retained model-4 baseline. */
2916
2859
  minReaderModel?: number;
2917
2860
  };
2918
2861
 
@@ -2938,45 +2881,32 @@ export declare function deployedTagsGroq(): string;
2938
2881
  */
2939
2882
  export declare function deployStageGuards(args: StageGuardArgs): Promise<void>;
2940
2883
 
2941
- /** Where a definition deploys: the engine tag it partitions under, the
2942
- * workflow resource it belongs to, and the resource-alias bindings to expand
2943
- * references against. Structurally what `deployDefinitions` receives, minus the
2944
- * definitions themselves — carrying `resourceAliases` here is what keeps a diff
2945
- * fingerprinting the same physical content `deployDefinitions` would. */
2884
+ /** Structurally what `deployDefinitions` receives, minus the definitions; carrying `resourceAliases` here keeps a diff's fingerprint matching what deploy would produce. */
2946
2885
  export declare interface DeployTarget {
2947
- /** Reviewed numeric literal, checked against the exact installed floor before client access. */
2886
+ /** Highest reader model verified across runtimes sharing this workflow resource. */
2948
2887
  expectedMinReaderModel: number;
2949
2888
  tag: string;
2950
2889
  workflowResource: WorkflowResource;
2951
2890
  resourceAliases?: ResourceAliases;
2952
2891
  }
2953
2892
 
2954
- /**
2955
- * Classify an activity from its shape, BPMN-aligned: `target` marks off-system
2956
- * work (`manual`); otherwise any fireAction-fired action means a person (or
2957
- * robot caller) acts on it (`user`); otherwise cascade-fired effects make it a
2958
- * `service` step; otherwise cascade-fired status flips make it a `receive`
2959
- * wait; anything left is an inline `script` step.
2960
- */
2893
+ /** Classifies an activity from its shape: `target` marks off-system work
2894
+ * (`manual`), the one bit action shapes alone can't otherwise show. Then:
2895
+ * any caller-fireable action `user`; effects or spawns → `service`;
2896
+ * cascade-only actions `receive`; no actions at all `script`. */
2961
2897
  export declare function deriveActivityKind(activity: Activity): ActivityKind;
2962
2898
 
2963
2899
  export declare interface DeriveAutonomyOptions {
2964
2900
  /** Child definitions for `spawn` recursion, by definition `name` — the
2965
- * deploy batch or previously deployed set. An unresolvable child reports
2901
+ * deploy batch or the already-deployed set. An unresolvable child reports
2966
2902
  * `conditional` with an unresolved wait. */
2967
2903
  children?: ReadonlyMap<string, WorkflowDefinition>;
2968
2904
  }
2969
2905
 
2970
- /**
2971
- * Who, if anyone, fires the activity's actions derived ahead-of-time from
2972
- * the activity's shape alone: `off-system` when `target` is present; else
2973
- * `autonomous` (every action cascade-fired no caller fires anything),
2974
- * `interactive` (only fireAction-fired actions), or `hybrid` (mixed). An
2975
- * actionless activity classifies `autonomous` vacuously (deploy's
2976
- * terminal-reachability invariant rejects it anyway). Shape-only: whether
2977
- * the activity actually RESOLVES without a caller is the causal question
2978
- * `deriveWorkflowAutonomy` answers.
2979
- */
2906
+ /** Who fires the activity's actions, from shape alone — a separate causal
2907
+ * check decides whether it actually resolves without a caller. A `target`
2908
+ * is `off-system`; all-cascade actions are `autonomous`, none are
2909
+ * `interactive`, a mix is `hybrid`. */
2980
2910
  export declare function deriveExecutorClassification(
2981
2911
  activity: Activity,
2982
2912
  ): ExecutorClassification;
@@ -3158,6 +3088,18 @@ export declare interface DiagnoseResult {
3158
3088
  remediations: SuggestedRemediation[];
3159
3089
  }
3160
3090
 
3091
+ /**
3092
+ * How an in-flight instance reads right now. `waiting` and `blocked` are both
3093
+ * HEALTHY, not stuck: `waiting` means an active activity has an available
3094
+ * action and advances when someone acts — how long a workflow is "allowed" to
3095
+ * wait is workflow- and team-specific, not this classifier's call — while
3096
+ * `blocked` means an active activity's declared requirements aren't all met
3097
+ * yet, and flips to `waiting` once they hold (typically a sibling activity
3098
+ * completing, or content landing). `completed` and `aborted` carry
3099
+ * `liveChildren` when spawned work is still running: a parent finishing while
3100
+ * detached children run is legal — detach means detach — but a consumer
3101
+ * should surface it loudly.
3102
+ */
3161
3103
  export declare type Diagnosis =
3162
3104
  | {
3163
3105
  state: "progressing";
@@ -3205,16 +3147,11 @@ export declare interface DiffEntry {
3205
3147
  }
3206
3148
 
3207
3149
  /**
3208
- * Compare one local definition against the latest deployed version of its
3209
- * name (or its absence), classifying it via the engine's own content-addressed
3210
- * planner ({@link planDefinitionDeploy}). Create-only: a content change is a
3211
- * NEW version, never an in-place update so there is no `update` verdict.
3212
- * Pure the caller owns the fetch. `def` passes the same boundary parse as
3213
- * deploy ({@link parseDefinitionInput}): a fetched document's envelope is
3214
- * stripped and unknown keys fail loud, so diff and deploy accept and reject
3215
- * the same input shape. Deploy's further checks (GROQ + invariants via
3216
- * `validateDefinition`, batch ordering) stay the caller's job, as they always
3217
- * were.
3150
+ * Classifies `def` against the latest deployed version of its name via
3151
+ * {@link planDefinitionDeploy} a content change is always a new version,
3152
+ * never an in-place update. `def` passes the same boundary parse deploy uses
3153
+ * ({@link parseDefinitionInput}), so diff and deploy accept and reject the
3154
+ * same input shape.
3218
3155
  */
3219
3156
  export declare function diffEntry<T extends WorkflowDefinitionInput<T>>({
3220
3157
  def: rawDef,
@@ -3324,20 +3261,11 @@ export declare function displayDescription(
3324
3261
  ): string | undefined;
3325
3262
 
3326
3263
  /**
3327
- * Display metadata for the discriminator literals the engine persists
3328
- * (history entries, field-entry kinds, ops, effects-context entry
3329
- * kinds, document and effect-queue types). Each entry exposes
3330
- *
3331
- * - `title` — short label for chips, badges, headings
3332
- * - `description` — longer prose for tooltips / inspector panes
3333
- *
3334
- * UIs that render an instance audit log should NEVER show
3335
- * `transitionFired` raw — they look it up here and
3336
- * render `"Transition fired"` instead.
3337
- *
3338
- * Each family map is checked (`satisfies`) against the canonical union
3339
- * for that family, so adding or removing a discriminator in the engine
3340
- * fails tsc here until the display entry follows.
3264
+ * Display strings for one persisted discriminator: `title` is a short label
3265
+ * for chips, badges, and headings, `description` longer prose for tooltips and
3266
+ * inspector panes. A UI rendering an instance audit log looks the raw
3267
+ * discriminator up here instead of showing it — `transitionFired` reads as
3268
+ * "Transition fired".
3341
3269
  */
3342
3270
  export declare interface DisplayMetadata {
3343
3271
  readonly title: string;
@@ -3350,6 +3278,7 @@ export declare interface DisplayMetadata {
3350
3278
  */
3351
3279
  export declare function displayTitle(typeKey: string | undefined): string;
3352
3280
 
3281
+ /** Document-value permissions. Grants ({@link Grant} in ./authorization.ts) compose most-permissive-wins. */
3353
3282
  declare const DOCUMENT_VALUE_PERMISSIONS: readonly ["create", "read", "update"];
3354
3283
 
3355
3284
  /**
@@ -3484,6 +3413,13 @@ export declare const DRIVER_KIND_DISPLAY: {
3484
3413
  };
3485
3414
  };
3486
3415
 
3416
+ /**
3417
+ * What KIND of actor drove an action, recorded on the `actionFired` history
3418
+ * entry for the audit-trail "who did this?" glyph. Distinct from
3419
+ * {@link ActivityKind} (the intended execution lane) — any driver can fire
3420
+ * any kind. New entries stamp `'person'`; `'agent'`/`'service'`/`'engine'`
3421
+ * remain as read vocabulary for stored entries.
3422
+ */
3487
3423
  export declare const DRIVER_KINDS: readonly [
3488
3424
  "person",
3489
3425
  "agent",
@@ -3493,21 +3429,19 @@ export declare const DRIVER_KINDS: readonly [
3493
3429
 
3494
3430
  export declare type DriverKind = (typeof DRIVER_KINDS)[number];
3495
3431
 
3496
- /**
3497
- * Classify the actor that drove an action for the audit-trail glyph. `person`
3498
- * and `agent` pass through from {@link Actor.kind}; `system` maps to
3499
- * `service`. Today every token identity resolves as a person (`/users/me`
3500
- * carries no kind), so new entries stamp `person` and the `agent`/`service`/
3501
- * `engine` values are read vocabulary for stored entries — a service's
3502
- * environment lives on the entry's `executionContext`, and agent delegation
3503
- * is a future designed feature, not an actor kind the engine can mint.
3504
- *
3505
- * Advisory and only as trustworthy as the {@link Actor} it reads — actor
3506
- * identity is itself advisory in this engine (the lake/token is authoritative),
3507
- * so this is a best-effort glyph, never an authorization signal.
3508
- */
3432
+ /** Actor-kind glyph for the audit trail — advisory only, never an
3433
+ * authorization signal. */
3509
3434
  export declare function driverKind(actor: Actor): DriverKind;
3510
3435
 
3436
+ /**
3437
+ * Declared editability of a field — the generic edit seam's gate. Default
3438
+ * (absent) is NOT editable: a field is op-only engine working memory unless the
3439
+ * modeler opens it. The stored form is `true` (editable by anyone within the
3440
+ * field's scope window) or an EDIT CONDITION — rendered-scope GROQ (`$actor`,
3441
+ * `$can`, `$attributes`, `$fields`, `$assigned`), checked like an action filter
3442
+ * to decide who-may-edit. ADVISORY like every engine gate — it disables the
3443
+ * inline field and explains; a {@link Guard} declares the intended write-lock.
3444
+ */
3511
3445
  export declare type Editable = v.InferOutput<typeof StoredEditableSchema>;
3512
3446
 
3513
3447
  /**
@@ -3525,6 +3459,10 @@ export declare interface EditableFieldEvaluation {
3525
3459
  type: FieldKind;
3526
3460
  title?: string;
3527
3461
  validation?: ScalarValidation;
3462
+ /** Eligible assignment roles for `assignee` / `assignees`; absent means unconstrained. */
3463
+ roles?: string[];
3464
+ /** The definition aliases used to interpret {@link EditableFieldEvaluation.roles}. */
3465
+ roleAliases?: RoleAliases;
3528
3466
  /** Current resolved value; `undefined` until the field is first resolved. */
3529
3467
  value: unknown;
3530
3468
  /** Whether THIS actor may edit the field right now (window + predicate + guard). */
@@ -3637,6 +3575,18 @@ export declare interface EditFieldTarget {
3637
3575
 
3638
3576
  export declare type EditMode = "set" | "append" | "unset";
3639
3577
 
3578
+ /**
3579
+ * A registered effect: `name` is its only identity (unique per definition,
3580
+ * read downstream as `$effects.<name>`) — the host app registers a handler
3581
+ * against it 1:1, and the stored definition never references code.
3582
+ * `bindings` are GROQ reads over the rendered scope, resolved to concrete
3583
+ * JSON at queue time; `input` is static config passed through verbatim.
3584
+ * `outputs` (typed {@link FieldShape}s) is a STRICT allowlist: at completion
3585
+ * an undeclared output key, or a value that doesn't fit its shape, fails the
3586
+ * completion and nothing is stored. Omitting `outputs` is an EMPTY allowlist,
3587
+ * so ANY returned output is rejected and fails the completion — the bound is
3588
+ * universal, not opt-in.
3589
+ */
3640
3590
  export declare type Effect = v.InferOutput<typeof EffectSchema>;
3641
3591
 
3642
3592
  /** Total commits one dispatch may make — the runaway-handler bound: without
@@ -3660,8 +3610,10 @@ declare const EFFECT_RUN_STATUSES: readonly ["done", "failed", "cancelled"];
3660
3610
 
3661
3611
  /**
3662
3612
  * A `ctx.commitOps` / `ctx.setProgress` call hit one of the dispatch's
3663
- * bounds. Thrown synchronously at the call site see the module doc for why
3664
- * a rejection would be invisible to exactly the caller the bound exists for.
3613
+ * bounds. Thrown synchronously at the call site, not as a promise rejection:
3614
+ * a tight loop that forgot to `await` dies on its own stack at the bound
3615
+ * instead of spraying unhandled rejections invisible to the caller the bound
3616
+ * exists for.
3665
3617
  */
3666
3618
  export declare class EffectCommitQueueOverflowError extends WorkflowError<"effect-commit-queue-overflow"> {
3667
3619
  readonly effectKey: string;
@@ -3682,11 +3634,29 @@ export declare type EffectCompletionStatus = Exclude<
3682
3634
  "cancelled"
3683
3635
  >;
3684
3636
 
3637
+ /**
3638
+ * External effect handler — invoked at drain time with resolved `params` and
3639
+ * a context. Returning `outputs` records them on the run's `effectHistory`
3640
+ * row, read downstream as `$effects['<name>'].<output>`. Returning `ops`
3641
+ * applies the state half of the effect in the completion commit (`field.*`
3642
+ * only, never `status.set`) — every returned op must explicitly set
3643
+ * `target.scope`, since completion ops have no authoring location to infer
3644
+ * one from. Throwing marks the effect failed, with no `ops`.
3645
+ *
3646
+ * Delivery is at-least-once: a handler MAY run more than once for the same
3647
+ * effect (a dispatch dying after its side effect but before commit, or a
3648
+ * lease expiring mid-dispatch and being taken over). Completion is
3649
+ * first-writer-wins — the losing run's completion is reported as `lost`.
3650
+ * Write handlers to tolerate this: check `effectHistory[]` for a row keyed
3651
+ * by `ctx.effectKey` before irreversible work, and derive external
3652
+ * identifiers from `ctx.effectKey` so the receiving system can dedupe.
3653
+ *
3654
+ * The `bivarianceHack` indirection keeps this readable from the non-generic
3655
+ * `Engine` surface; only the typed drain invokes handlers.
3656
+ */
3685
3657
  export declare type EffectHandler<
3686
3658
  Client extends WorkflowClient = WorkflowClient,
3687
3659
  > = {
3688
- /** Bivariant so a concretely typed handler registry remains readable from
3689
- * the non-generic Engine surface; only the typed drain invokes handlers. */
3690
3660
  bivarianceHack(
3691
3661
  params: Record<string, unknown>,
3692
3662
  ctx: EffectHandlerContext<Client>,
@@ -3696,97 +3666,21 @@ export declare type EffectHandler<
3696
3666
  } | void>;
3697
3667
  }["bivarianceHack"];
3698
3668
 
3699
- /**
3700
- * External effect handler — invoked at drain time with the resolved
3701
- * `params` and a context. Returning `outputs` records them on the run's
3702
- * `effectHistory` row, where downstream bindings and conditions read them
3703
- * as `$effects['<effect name>'].<output>`.
3704
- * Returning `ops` applies the state half of the effect in the completion
3705
- * commit — `field.*` computed from the real result, run through the same op
3706
- * applier as an action's field ops (so a created doc's ref enters `$fields`, or
3707
- * a screened outcome lands in a field the activity/stage gate reads). Effects
3708
- * report results as field state, never by flipping an activity status, so `ops`
3709
- * excludes `status.set`. Unlike definition-authored field ops, completion ops
3710
- * have no authoring location from which to infer a target scope: every returned
3711
- * op must explicitly set `target.scope` to `'workflow'` or `'stage'`. Throwing
3712
- * marks the effect as failed (and returns no `ops`).
3713
- *
3714
- * **Delivery is at-least-once — a handler MAY run more than once for the
3715
- * same effect.** Two overlaps produce a double-run: the dispatching process
3716
- * dies after the handler's side effect but before `completeEffect` commits,
3717
- * and a slow dispatch outliving its claim's lease (the engine's
3718
- * `effectLeaseMs`, default 5 minutes) — an expired claim is taken over by
3719
- * the next drain, or force-released by `sweepStaleClaims`, and redispatched
3720
- * while the original handler may still be running. Completion is
3721
- * first-writer-wins: the losing drainer's dispatch already ran, its
3722
- * completion is reported as `lost`.
3723
- *
3724
- * Write handlers to tolerate that: before irreversible work, check
3725
- * `effectHistory[]` for a row with this run's `ctx.effectKey` (the stable
3726
- * `_key` an entry keeps from queue to history) and skip work a prior run
3727
- * already completed; derive external-system identifiers from `ctx.effectKey`
3728
- * so the receiving system can dedupe the overlap the ledger can't see.
3729
- */
3730
3669
  declare type EffectHandlerContext<Client extends WorkflowClient> = {
3731
- /**
3732
- * A concrete sibling of the client supplied to `createEngine`, bound to the
3733
- * workflow resource with the same namespaces and credentials. Untagged
3734
- * handler requests on its workflow-client surface carry the `workflow.effect`
3735
- * request tag by default. A concrete client's explicit tags compose beneath
3736
- * that prefix. On the structural fallback for minimal clients, pass-through
3737
- * namespaces are not stamped and core builders expose the engine's minimal
3738
- * workflow-client surface.
3739
- */
3670
+ /** A concrete sibling of the `createEngine` client, bound to the workflow resource with the
3671
+ * same credentials; untagged handler requests carry the `workflow.effect` tag by default. */
3740
3672
  client: Client;
3741
- /**
3742
- * Resolve the client bound to a subject doc's own resource. A handler
3743
- * patches the SUBJECT (which may live in a different Sanity resource
3744
- * than the instance — split-dataset GDR deploys); the drainer's
3745
- * `completeEffect` writes the INSTANCE through {@link client}. One
3746
- * client can't address both, so a handler that patches a foreign
3747
- * subject must route its write here.
3748
- *
3749
- * Pass the subject's GDR — the URI a binding like `$fields.subject._id`
3750
- * resolves to (the hydrated doc's `_id`), or a full
3751
- * {@link GlobalDocumentReference}. Returns the `resourceClients` client
3752
- * for that resource when one is mapped, {@link client} for the workflow
3753
- * resource itself, and a sibling derived from {@link client}'s
3754
- * credentials otherwise. Returned clients preserve their concrete APIs and
3755
- * apply the same default effect request tag.
3756
- * Throws if `ref` isn't a GDR — a bare id can't
3757
- * be routed, so failing loud beats silently patching the wrong dataset.
3758
- */
3673
+ /** Resolve the client for a subject doc's own resource: a handler patching a foreign subject
3674
+ * routes its write here {@link client} addresses the instance's. Throws on a bare id. */
3759
3675
  clientFor: (ref: GdrUri | GlobalDocumentReference) => WorkflowClient;
3760
3676
  instanceId: string;
3761
3677
  effectKey: string;
3762
3678
  log: (message: string, extra?: Record<string, unknown>) => void;
3763
- /**
3764
- * Commit mid-dispatch field state as a real engine transaction
3765
- * validated like completion ops (`field.*` only, never `status.set`),
3766
- * gated on THIS dispatch's exact claim (a stale/superseded claim
3767
- * rejects before writing), history + idempotency recorded, guards
3768
- * refreshed, cascade run, and the claim's lease renewed in the same
3769
- * commit. Calls enqueue synchronously into a bounded per-dispatch FIFO
3770
- * and execute strictly in call order, one at a time — forgetting to
3771
- * `await` cannot create same-handler write races, and overflow (or the
3772
- * per-dispatch commit cap) throws synchronously at the call site.
3773
- * Await each call anyway: that is where errors surface promptly and
3774
- * engine commit latency paces the reporter. `idempotencyKey` is
3775
- * required — the engine does not assume a supplied op is idempotent.
3776
- * An accepted-but-unawaited commit that fails still fails the effect
3777
- * at settlement; the final completion always waits for this queue to
3778
- * drain. Never coalesced.
3779
- */
3679
+ /** Mid-dispatch `field.*` commit gated on THIS dispatch's exact claim — a superseded claim
3680
+ * writes nothing. Runs in call order, never coalesced; `idempotencyKey` is required. */
3780
3681
  commitOps: (req: CommitOpsRequest) => Promise<void>;
3781
- /**
3782
- * Report absolute progresssugar over {@link commitOps} that
3783
- * `field.set`s a number (a `progress` field's 0–100 contract is
3784
- * enforced by the engine at commit). A bare string targets a
3785
- * workflow-scope field; pass `{scope: 'stage', field}` for stage
3786
- * scope. Unlike `commitOps`, PENDING sets to the same field coalesce
3787
- * (latest value wins, one commit), so a tight reporting loop is safe
3788
- * by construction; idempotency keys are engine-derived.
3789
- */
3682
+ /** Absolute progress, sugar over {@link commitOps}: `field.set`s a number (0–100, enforced at
3683
+ * commit). Unlike `commitOps`, pending sets to one field coalesce latest value wins. */
3790
3684
  setProgress: (target: ProgressTarget, value: number) => Promise<void>;
3791
3685
  };
3792
3686
 
@@ -3885,12 +3779,7 @@ export declare class EffectOutputsInvalidError extends WorkflowError<"effect-out
3885
3779
  constructor(args: { effect: string; issues: string[] });
3886
3780
  }
3887
3781
 
3888
- /**
3889
- * Render completed effects' outputs as the `$effects` map — each effect's
3890
- * LATEST completed run with outputs wins, by name, across the whole
3891
- * history (outputs are workflow-scope handler results; the per-visit
3892
- * signal is `$effectStatus`).
3893
- */
3782
+ /** `$effects`: each effect name → its LATEST completed run's outputs across the whole history. */
3894
3783
  export declare function effectOutputsMap(
3895
3784
  instance: Pick<WorkflowInstance, "effectHistory">,
3896
3785
  ): Record<string, unknown>;
@@ -3910,7 +3799,6 @@ declare const EffectSchema: v.StrictObjectSchema<
3910
3799
  v.StringSchema<undefined>,
3911
3800
  undefined
3912
3801
  >;
3913
- /** GROQ reads over the rendered scope, resolved to concrete JSON at queue time. */
3914
3802
  readonly bindings: v.OptionalSchema<
3915
3803
  v.RecordSchema<
3916
3804
  v.StringSchema<undefined>,
@@ -3924,28 +3812,10 @@ declare const EffectSchema: v.StrictObjectSchema<
3924
3812
  >,
3925
3813
  undefined
3926
3814
  >;
3927
- /** Static config, passed through to the handler verbatim. */
3928
3815
  readonly input: v.OptionalSchema<
3929
3816
  v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>,
3930
3817
  undefined
3931
3818
  >;
3932
- /**
3933
- * The outputs this effect is allowed to produce, as typed {@link FieldShape}s
3934
- * (each `name` is an output key, read downstream as `$effects['<name>'].<key>`;
3935
- * an `array` output is an array of objects shaped by `of`).
3936
- *
3937
- * A STRICT allowlist: at completion the handler's returned `outputs` are
3938
- * validated against these shapes and an undeclared key — or a value that
3939
- * doesn't fit its shape — fails the completion (nothing is stored). Omitting
3940
- * `outputs` is an EMPTY allowlist: the effect produces nothing, so any returned
3941
- * output is rejected — the bound is universal, not opt-in.
3942
- * Why strict: outputs land on the instance document's `effectHistory`, so
3943
- * the allowlist keeps it bounded — a handler can't accidentally spread a
3944
- * whole API response
3945
- * into the instance — and the declared shapes let tooling (e.g. the simulator's
3946
- * drain UI) suggest an effect's exact output keys. Declaring outputs also
3947
- * powers the advisory deploy-time producer/consumer lint.
3948
- */
3949
3819
  readonly outputs: v.OptionalSchema<
3950
3820
  v.ArraySchema<v.GenericSchema<FieldShape>, undefined>,
3951
3821
  undefined
@@ -3983,6 +3853,10 @@ export declare interface Engine {
3983
3853
  deployDefinitions: <T extends WorkflowDefinitionInput<T>>(
3984
3854
  args: DeployDefinitionsArgs<T>,
3985
3855
  ) => Promise<DeployDefinitionsResult>;
3856
+ /** Starts an instance. `start.filter` is never a gate here — applicability
3857
+ * belongs to `definitionsForDocument`, and an inapplicable definition
3858
+ * starts without complaint. `instanceId` is the idempotency key: reusing
3859
+ * it for the same start resumes; a different start throws. */
3986
3860
  startInstance: (args: StartInstanceArgs) => Promise<OperationResult>;
3987
3861
  fireAction: (args: FireActionArgs) => Promise<OperationResult>;
3988
3862
  /** Edit a declared-editable field directly (the generic edit seam):
@@ -4199,17 +4073,9 @@ export declare function entryDocRefs(
4199
4073
  entries: unknown,
4200
4074
  ): GlobalDocumentReference[];
4201
4075
 
4202
- /**
4203
- * Pure error helpers no client, no I/O. The one home for the engine's
4204
- * "coerce an unknown caught value" + "rethrow with context" idioms, so the
4205
- * message shape and cause-chaining can't drift across call sites.
4206
- */
4207
- /**
4208
- * A human-readable message for an unknown caught value: `.message` for an
4209
- * {@link Error}, otherwise `String(value)`. Strips control characters
4210
- * (keeping newlines and tabs) so server-derived error text can't smuggle
4211
- * terminal escape sequences into consumer output.
4212
- */
4076
+ /** The value's message — `Error.message`, else `String(value)` — with
4077
+ * control characters stripped so server-derived error text can't smuggle
4078
+ * terminal escape sequences into consumer output. */
4213
4079
  export declare function errorMessage(err: unknown): string;
4214
4080
 
4215
4081
  export declare interface EvaluateArgs {
@@ -4352,16 +4218,16 @@ export declare function evaluateStartFilter(args: {
4352
4218
 
4353
4219
  /**
4354
4220
  * Well-known {@link ExecutionContext.kind} values. The field is a free
4355
- * string — these are the shipped vocabulary, not a closed set.
4221
+ * string — these are the shipped vocabulary, not a closed set. `interactive`
4222
+ * is the generic human-session fallback when `studio`/`sdkApp` don't apply;
4223
+ * `server` is a proxy acting with a user's token; `drainer` is an
4224
+ * effect-drain runtime.
4356
4225
  */
4357
4226
  export declare const EXECUTION_KINDS: {
4358
- /** A human-facing session (generic — prefer `studio`/`sdkApp` when known). */
4359
4227
  readonly interactive: "interactive";
4360
- /** A server process acting with a user's token (e.g. a publish proxy). */
4361
4228
  readonly server: "server";
4362
4229
  readonly cli: "cli";
4363
4230
  readonly mcp: "mcp";
4364
- /** An effect-drain runtime. */
4365
4231
  readonly drainer: "drainer";
4366
4232
  readonly script: "script";
4367
4233
  readonly test: "test";
@@ -4370,23 +4236,11 @@ export declare const EXECUTION_KINDS: {
4370
4236
  };
4371
4237
 
4372
4238
  /**
4373
- * Execution context advisory "via what" provenance, stamped on every
4374
- * history entry alongside the actor's "who".
4375
- *
4376
- * Identity is always the token behind the client (`/users/me`); the
4377
- * execution context records the ENVIRONMENT that drove the commit: a
4378
- * studio session, the CLI, an MCP host, a server proxy acting with a
4379
- * user's token. It is self-asserted advisory metadata, configured once at
4380
- * `createEngine` — never per call — and never an authorization input.
4381
- *
4382
- * The `runtime` half is always inferred at construction (best-effort,
4383
- * zero dependencies); the declared `{kind, id}` half is optional. An
4384
- * unlabeled `runtime: "node"` is itself a signal (a script or proxy that
4385
- * didn't declare itself), and a declared/inferred mismatch (`kind:
4386
- * "studio"` on `runtime: "node"`) surfaces SSR passes or lying labels
4387
- * for free.
4388
- */
4389
- /** The stored stamp — `runtime` is always present, the declared half optional. */
4239
+ * The stored stamp: self-asserted advisory provenance — "via what", distinct
4240
+ * from the actor's "who". Configured once at `createEngine`, never per call,
4241
+ * and never an authorization input. `runtime` is always present; the declared
4242
+ * half is optional.
4243
+ */
4390
4244
  export declare interface ExecutionContext {
4391
4245
  /** Inferred JavaScript runtime: `browser` | `node` | `worker` | `edge` | `deno` | `bun` | `unknown`. */
4392
4246
  runtime: string;
@@ -4419,6 +4273,13 @@ export declare const EXECUTOR_CLASSIFICATION_DISPLAY: {
4419
4273
  };
4420
4274
  };
4421
4275
 
4276
+ /**
4277
+ * Who, if anyone, fires an activity's actions, derived ahead-of-time from
4278
+ * the activity's shape alone: `'autonomous'` = every action is cascade-fired
4279
+ * (no caller fires anything); `'interactive'` = only fireAction-fired
4280
+ * actions; `'off-system'` = `target` present; `'hybrid'` = mixed. Advisory,
4281
+ * rendered on insight/evaluation nodes — never gating.
4282
+ */
4422
4283
  export declare const EXECUTOR_CLASSIFICATIONS: readonly [
4423
4284
  "autonomous",
4424
4285
  "interactive",
@@ -4492,17 +4353,7 @@ export declare function explainStartRequirement(args: {
4492
4353
  */
4493
4354
  export declare function extractDocumentId(gdrUriString: string): string;
4494
4355
 
4495
- /**
4496
- * Convenience: fetch the grants for a given resource via the supplied
4497
- * client:
4498
- *
4499
- * GET <resourcePath> → Grant[]
4500
- *
4501
- * `resourcePath` is caller-supplied so the same helper works for
4502
- * project ACLs (`/projects/<id>/datasets/<dataset>/acl`) and for a
4503
- * dedicated workflow-collaboration resource. The client must support
4504
- * the `request<T>({url})` method `@sanity/client` exposes.
4505
- */
4356
+ /** `resourcePath` is caller-supplied so this works for both project ACLs and a dedicated workflow-collaboration resource. */
4506
4357
  declare function fetchGrants(args: {
4507
4358
  client: {
4508
4359
  request: <T>(opts: {
@@ -4598,13 +4449,21 @@ export declare const FIELD_KIND_DISPLAY: {
4598
4449
  };
4599
4450
  };
4600
4451
 
4452
+ /**
4453
+ * The three field scopes a field entry can live in. Also the
4454
+ * group-declaration levels: a `groups` array lives at exactly these three
4455
+ * nodes, so `DefinitionGroupSite.level` reuses this vocabulary.
4456
+ */
4601
4457
  declare const FIELD_SCOPES: readonly ["workflow", "stage", "activity"];
4602
4458
 
4603
4459
  /**
4604
4460
  * The kinds a VALUE can take — scalars aligned to Sanity's names, the
4605
4461
  * reference kinds, the actor/assignee identities, and the two compositional
4606
4462
  * kinds (`object` with named `fields`, `array` of objects shaped by `of`).
4607
- * This is also the set a nested {@link FieldShape} sub-field may use.
4463
+ * This is also the set a nested {@link FieldShape} sub-field may use. Kinds
4464
+ * are bare (unique within their union); namespacing lives only on
4465
+ * engine-owned lake document `_type`s ({@link WORKFLOW_DEFINITION_TYPE}, the
4466
+ * instance type).
4608
4467
  *
4609
4468
  * Exported (module-level, not package API) for the model-surface gate's
4610
4469
  * enum-value coverage test.
@@ -4650,6 +4509,7 @@ export declare interface FieldDescription {
4650
4509
  proposals: InsightPhrase[];
4651
4510
  }
4652
4511
 
4512
+ /** One declared field entry as authored and stored: name, value kind, and its scope's sourcing and editability. */
4653
4513
  export declare type FieldEntry = FieldEntryFields<Editable, string[]>;
4654
4514
 
4655
4515
  /** Type-mirror of {@link fieldEntryFields}: a raw field entry of the given
@@ -4662,6 +4522,8 @@ declare type FieldEntryFields<TEditable, TGroup> = FieldBase<
4662
4522
  options?: ChoiceOptions | undefined;
4663
4523
  validation?: ScalarValidation | undefined;
4664
4524
  types?: string[] | undefined;
4525
+ /** Non-empty assignment eligibility constraint. User roles apply aliases; collective roles match literally. */
4526
+ roles?: string[] | undefined;
4665
4527
  fields?: FieldShape[] | undefined;
4666
4528
  of?: FieldShape[] | undefined;
4667
4529
  };
@@ -4715,6 +4577,14 @@ declare type FieldReadExpr = {
4715
4577
 
4716
4578
  export declare type FieldScope = (typeof FIELD_SCOPES)[number];
4717
4579
 
4580
+ /**
4581
+ * A sub-field shape used inside an `object`'s `fields` or an `array`'s `of` —
4582
+ * lighter than {@link FieldEntry}: no `initialValue`/`editable`/`required`,
4583
+ * since a sub-field's value comes from the parent. An `object` kind requires
4584
+ * non-empty `fields` and no `of`; an `array` kind requires non-empty `of` and
4585
+ * no `fields`; every other kind requires neither — enforced at parse, not
4586
+ * visible in this type.
4587
+ */
4718
4588
  export declare interface FieldShape {
4719
4589
  type: FieldValueKind;
4720
4590
  name: string;
@@ -4722,10 +4592,19 @@ export declare interface FieldShape {
4722
4592
  description?: string | undefined;
4723
4593
  options?: ChoiceOptions | undefined;
4724
4594
  validation?: ScalarValidation | undefined;
4595
+ /** Non-empty assignment eligibility constraint. User roles apply aliases; collective roles match literally. */
4596
+ roles?: string[] | undefined;
4725
4597
  fields?: FieldShape[] | undefined;
4726
4598
  of?: FieldShape[] | undefined;
4727
4599
  }
4728
4600
 
4601
+ /**
4602
+ * How a field seeds its `initialValue`, once at materialisation (advisory
4603
+ * after — the field stays freely editable). Absent means working memory: the
4604
+ * field starts empty and an op fills it later, spelled by omission rather
4605
+ * than an arm. Distinct from {@link ValueExpr}, an op's write payload; they
4606
+ * overlap only on the literal and field-read arms.
4607
+ */
4729
4608
  export declare type FieldSource = FieldSourceInternal;
4730
4609
 
4731
4610
  declare type FieldSourceInternal =
@@ -4740,12 +4619,9 @@ declare type FieldSourceInternal =
4740
4619
  | FieldReadExpr;
4741
4620
 
4742
4621
  /**
4743
- * The field tree of a persisted value every leaf replaced by its type name
4744
- * (`null` kept distinct from `object`), object keys sorted by UTF-16 code
4745
- * unit (locale-independent, so the pinned ledgers canonicalise identically
4746
- * on every machine), arrays element-wise so discriminated variants stay
4747
- * visible. The comparison form the model-surface gates pin per model
4748
- * version, and the form ops tooling can diff a live document against.
4622
+ * Every leaf replaced by its type name (`null` distinct from `object`); keys sorted by
4623
+ * UTF-16 code unit, not locale collation, so the shape canonicalises identically on every
4624
+ * machine.
4749
4625
  */
4750
4626
  export declare function fieldTreeShape(value: unknown): unknown;
4751
4627
 
@@ -4806,6 +4682,7 @@ export declare class FieldValueShapeError extends WorkflowError<"field-value-sha
4806
4682
  */
4807
4683
  export declare const FILTER_SCOPE_VARS: readonly string[];
4808
4684
 
4685
+ /** Returns `undefined`, never throws, for an activity an instance's pinned snapshot names but the definition has since renamed or removed. */
4809
4686
  export declare function findActivityNode(args: {
4810
4687
  activityName: string;
4811
4688
  definition: WorkflowDefinition | undefined;
@@ -4852,6 +4729,7 @@ export declare interface FindPendingEffectsArgs extends InstanceRefArgs {
4852
4729
  names?: string[];
4853
4730
  }
4854
4731
 
4732
+ /** Returns `undefined`, never throws, for a stage an instance's pinned snapshot names but the definition has since renamed or removed. */
4855
4733
  export declare function findStageNode(args: {
4856
4734
  definition: WorkflowDefinition | undefined;
4857
4735
  stageName: string;
@@ -5012,6 +4890,11 @@ export declare interface GlobalDocumentReference<
5012
4890
  type: TType;
5013
4891
  }
5014
4892
 
4893
+ /**
4894
+ * Filters are GROQ strings evaluated through groq-js with the document as
4895
+ * the dataset and the caller's principal id as `identity()`. Grants compose
4896
+ * most-permissive-wins.
4897
+ */
5015
4898
  export declare interface Grant {
5016
4899
  filter: string;
5017
4900
  permissions: DocumentValuePermission[];
@@ -5033,12 +4916,22 @@ declare function grantsPermissionOn(args: {
5033
4916
  userId?: string;
5034
4917
  }): Promise<boolean>;
5035
4918
 
4919
+ /** A named readiness condition. Activities accept only `'groq'`; workflow
4920
+ * `start.requirements` also accepts `'singleSubject'` — see {@link StartRequirement}. */
5036
4921
  export declare type GroqRequirement = RequirementBase & {
5037
4922
  type: "groq";
5038
4923
  query: string;
5039
4924
  };
5040
4925
 
5041
- /** Type-mirror of {@link GroupSchema} — one declared group. */
4926
+ /**
4927
+ * A declared "what belongs together" tag: the workflow root, a stage, or an
4928
+ * activity declares named groups, and field entries, activities, and actions
4929
+ * opt in via `group`. Purely advisory — the engine stores and validates names
4930
+ * (unique per level, every reference resolves) and never acts on them; a
4931
+ * consumer decides what a group means for its medium. The same name declared
4932
+ * at several levels is intentional nesting, addressed per level; the engine
4933
+ * never merges them.
4934
+ */
5042
4935
  export declare type Group = {
5043
4936
  name: string;
5044
4937
  title?: string | undefined;
@@ -5064,6 +4957,14 @@ export declare const GROUP_KIND_DISPLAY: {
5064
4957
  };
5065
4958
  };
5066
4959
 
4960
+ /**
4961
+ * Advisory classification of a declared {@link Group} by its informational
4962
+ * ROLE, never a rendering treatment: `'core'` marks content central to
4963
+ * understanding the workflow (condensed views include these first);
4964
+ * `'details'` marks depth on demand. Unset = a plain group. Consumers
4965
+ * reading a definition as data MUST treat an unknown kind as unset — growing
4966
+ * this list is an engine version bump, like every stored enum.
4967
+ */
5067
4968
  export declare const GROUP_KINDS: readonly ["core", "details"];
5068
4969
 
5069
4970
  export declare type GroupKind = (typeof GROUP_KINDS)[number];
@@ -5116,6 +5017,27 @@ export declare function groupSitesOf(
5116
5017
  definition: WorkflowDefinition,
5117
5018
  ): DefinitionGroupSite[];
5118
5019
 
5020
+ /**
5021
+ * A lake mutation guard. A FOREIGN CONTRACT mirrored 1:1: `match`,
5022
+ * `predicate`, and `metadata` are the content lake's persisted guard-document
5023
+ * API, not engine-invented surface — the stored form keeps the lake's
5024
+ * vocabulary verbatim. The engine adds exactly two things: `name` (a
5025
+ * lake-id-segment, `^[a-z0-9][a-z0-9-]*$`, unique per definition — the lake
5026
+ * `_id` derives from `(instanceId, name)` at stage entry) and the deploy-time
5027
+ * read VALUES on `match.idRefs` / `metadata` (a typed {@link GuardRead} when
5028
+ * authoring, resolved to bare values at deploy). `match` selects mutations by
5029
+ * `types` (empty matches any), `idRefs` (field reads resolved to bare ids),
5030
+ * `idPatterns` (bare glob ids), and `actions` (at least one). `predicate` is
5031
+ * lake GROQ in a distinct delta-mode eval context (`before()`/`after()`,
5032
+ * `mutation`, `guard`, `identity()`, bare ids/fields only): strictly `true`
5033
+ * ALLOWS the mutation; anything else — false, null, an evaluation error, or
5034
+ * an omitted/empty predicate — DENIES. `metadata` is the only bridge from
5035
+ * that eval context (which cannot see `$fields`) to workflow fields, read as
5036
+ * `guard.metadata.*` and re-synced by the post-field-op guard refresh. The
5037
+ * lake does not enforce the guard document type yet: a deployed guard denies
5038
+ * optimistically engine-side, and the lake ACL is the only hard gate until
5039
+ * guard enforcement ships.
5040
+ */
5119
5041
  export declare type Guard = v.InferOutput<typeof GuardSchema>;
5120
5042
 
5121
5043
  /**
@@ -5173,6 +5095,17 @@ export declare function guardMatches({
5173
5095
  action: MutationGuardAction;
5174
5096
  }): boolean;
5175
5097
 
5098
+ /**
5099
+ * A deploy-time value read on a guard's `match.idRefs` / `metadata`, typed
5100
+ * like {@link ValueExpr} (`self`/`now`/`fieldRead`, plus the guard-only
5101
+ * `effectsRead` for a completed effect's output). Workflow-scope only — a
5102
+ * guard outlives any activity, so `fieldRead` here carries no `scope`.
5103
+ * Desugar prints the STORED string spelling the deploy resolver and guard
5104
+ * refresh parse (`"$self"`, `"$now"`, `"$fields.<name>[.path]"`,
5105
+ * `"$effects['<name>'][.path]"`); those spellings are single-line strings
5106
+ * matched by anchored regexes, so a line break in a path would print an
5107
+ * unparseable read.
5108
+ */
5176
5109
  export declare type GuardRead = v.InferOutput<typeof GuardReadSchema>;
5177
5110
 
5178
5111
  declare const GuardReadSchema: v.VariantSchema<
@@ -5254,14 +5187,8 @@ declare const GuardReadSchema: v.VariantSchema<
5254
5187
  undefined
5255
5188
  >;
5256
5189
 
5257
- /** Stored guards carry the printed string reads (the deploy resolver's input). */
5258
5190
  declare const GuardSchema: v.StrictObjectSchema<
5259
5191
  {
5260
- /**
5261
- * Lake-id-segment grammar (`^[a-z0-9][a-z0-9-]*$`, deploy-enforced): the
5262
- * guard's lake `_id` derives from `(instanceId, name)` at stage entry.
5263
- * Unique per definition.
5264
- */
5265
5192
  name: v.SchemaWithPipe<
5266
5193
  readonly [
5267
5194
  v.StringSchema<undefined>,
@@ -5272,7 +5199,6 @@ declare const GuardSchema: v.StrictObjectSchema<
5272
5199
  description: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
5273
5200
  match: v.StrictObjectSchema<
5274
5201
  {
5275
- /** Subject `_type`(s); empty matches any type. */
5276
5202
  types: v.OptionalSchema<
5277
5203
  v.ArraySchema<
5278
5204
  v.SchemaWithPipe<
@@ -5285,7 +5211,6 @@ declare const GuardSchema: v.StrictObjectSchema<
5285
5211
  >,
5286
5212
  undefined
5287
5213
  >;
5288
- /** Target docs as field reads (or the instance itself), resolved at deploy to bare ids + the resource. */
5289
5214
  idRefs: v.OptionalSchema<
5290
5215
  v.ArraySchema<
5291
5216
  v.SchemaWithPipe<
@@ -5298,7 +5223,6 @@ declare const GuardSchema: v.StrictObjectSchema<
5298
5223
  >,
5299
5224
  undefined
5300
5225
  >;
5301
- /** Glob id patterns (bare, resource-local). */
5302
5226
  idPatterns: v.OptionalSchema<
5303
5227
  v.ArraySchema<
5304
5228
  v.SchemaWithPipe<
@@ -5330,22 +5254,7 @@ declare const GuardSchema: v.StrictObjectSchema<
5330
5254
  },
5331
5255
  undefined
5332
5256
  >;
5333
- /**
5334
- * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
5335
- * reading the `before()`/`after()` natives, `mutation`, `guard`, and
5336
- * `identity()`. Bare ids/fields only. Polarity: a result of strictly
5337
- * `true` ALLOWS the matched mutation; anything else (false, null, an
5338
- * evaluation error) DENIES. Omitted or empty means UNCONDITIONAL DENY.
5339
- */
5340
5257
  predicate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
5341
- /**
5342
- * Projected workflow fields the predicate reads as `guard.metadata.*` —
5343
- * the only bridge from the lake eval context (which cannot see `$fields`)
5344
- * to workflow fields. Each value is a deploy-time read — a typed
5345
- * {@link GuardRead} when authoring, the printed string spelling once
5346
- * stored — resolved into a bare value at deploy and re-synced by the
5347
- * post-field-op guard refresh.
5348
- */
5349
5258
  metadata: v.OptionalSchema<
5350
5259
  v.RecordSchema<
5351
5260
  v.SchemaWithPipe<
@@ -5495,6 +5404,15 @@ export declare const HISTORY_DISPLAY: {
5495
5404
  };
5496
5405
  };
5497
5406
 
5407
+ /**
5408
+ * One appended audit row. Every `actor` stamp on one is token-resolved
5409
+ * advisory provenance, never authenticated identity — the lake's own document
5410
+ * history is the authenticated ground truth.
5411
+ *
5412
+ * On the three stage-movement arms, `via` discriminates a condition-driven
5413
+ * transition (`'transition'`, the default when absent) from an admin override
5414
+ * (`'setStage'`), and the `reason` beside it is that override's free text.
5415
+ */
5498
5416
  export declare type HistoryEntry = HistoryEvent & {
5499
5417
  /**
5500
5418
  * The execution environment that committed this entry — inferred
@@ -5514,10 +5432,7 @@ declare type HistoryEvent =
5514
5432
  stage: StageName;
5515
5433
  fromStage?: StageName;
5516
5434
  transition?: string;
5517
- /** Discriminates filtered transitions ("transition", default) from
5518
- * admin overrides ("setStage"). */
5519
5435
  via?: "transition" | "setStage";
5520
- /** Admin-supplied free-text on setStage. */
5521
5436
  reason?: string;
5522
5437
  actor?: Actor;
5523
5438
  }
@@ -5550,17 +5465,9 @@ declare type HistoryEvent =
5550
5465
  activity: ActivityName;
5551
5466
  action: ActionName;
5552
5467
  actor?: Actor;
5553
- /**
5554
- * What KIND of driver fired the action, derived from {@link actor} at
5555
- * fire time (see `../activity-kind.ts`) — the audit-trail glyph's
5556
- * person/agent/service/engine axis. Absent when no actor was supplied.
5557
- */
5558
5468
  driverKind?: DriverKind;
5559
- /**
5560
- * The engine fired this action in a cascade (its `when` turned true) —
5561
- * {@link actor} is the cascading token that happened to execute it,
5562
- * not a caller who invoked `fireAction`.
5563
- */
5469
+ /** The engine fired this action in a cascade: `actor` is the cascading token that
5470
+ * executed it, not a caller who invoked `fireAction`. */
5564
5471
  triggered?: true;
5565
5472
  }
5566
5473
  | {
@@ -5583,9 +5490,6 @@ declare type HistoryEvent =
5583
5490
  origin: EffectOrigin;
5584
5491
  }
5585
5492
  | {
5586
- /** A queued effect settled — a reported completion (`done`/`failed`),
5587
- * or an abort cancelling it before dispatch (`cancelled`). One entry
5588
- * per `effectHistory` row, sharing its `effectKey`. */
5589
5493
  _key: string;
5590
5494
  _type: "effectCompleted";
5591
5495
  at: string;
@@ -5602,12 +5506,9 @@ declare type HistoryEvent =
5602
5506
  at: string;
5603
5507
  effectKey: string;
5604
5508
  effect: EffectName;
5605
- /** The expired claim that was released — who abandoned it and when. */
5606
5509
  claim: PendingEffectClaim;
5607
- /** How the stale claim was recovered: a drain taking it over for
5608
- * redispatch, or `sweepStaleClaims` force-releasing it. */
5510
+ /** `drain-takeover` = a drain redispatched it; `sweep` = `sweepStaleClaims` released it. */
5609
5511
  via: "drain-takeover" | "sweep";
5610
- /** The drainer/sweeper that released it. */
5611
5512
  actor?: Actor;
5612
5513
  }
5613
5514
  | {
@@ -5615,12 +5516,6 @@ declare type HistoryEvent =
5615
5516
  _type: "spawned";
5616
5517
  at: string;
5617
5518
  activity: ActivityName;
5618
- /**
5619
- * GDR pointer at the spawned child workflow instance. Stored as
5620
- * the typed `{id, type}` envelope — same shape every other GDR
5621
- * field in the engine uses (`ancestors[]`, the subworkflow registry,
5622
- * any `doc.ref` field entry). The `id` is the full GDR URI.
5623
- */
5624
5519
  instanceRef: GlobalDocumentReference;
5625
5520
  /** Identity of the `forEach` row that produced this child. */
5626
5521
  rowKey?: string;
@@ -5632,8 +5527,6 @@ declare type HistoryEvent =
5632
5527
  at: string;
5633
5528
  stage: StageName;
5634
5529
  activity: ActivityName;
5635
- /** The live child re-bound to the entering stage's cohort instead of
5636
- * being duplicated — its `forEach` row was rediscovered on re-entry. */
5637
5530
  instanceRef: GlobalDocumentReference;
5638
5531
  rowKey: string;
5639
5532
  }
@@ -5642,8 +5535,6 @@ declare type HistoryEvent =
5642
5535
  _type: "subworkflowResolved";
5643
5536
  at: string;
5644
5537
  activity: ActivityName;
5645
- /** The child observed terminal; its registry row now carries the
5646
- * terminal cache. */
5647
5538
  instanceRef: GlobalDocumentReference;
5648
5539
  status: "done" | "aborted";
5649
5540
  }
@@ -5651,9 +5542,8 @@ declare type HistoryEvent =
5651
5542
  _key: string;
5652
5543
  _type: "subworkflowOrphaned";
5653
5544
  at: string;
5654
- /** A child that names this instance in its `ancestors` reached terminal,
5655
- * but no registry row matches it — its completion cannot drive any
5656
- * gate. Loud audit record of a propagation dead-end. */
5545
+ /** A child naming this instance in its `ancestors` reached terminal, but no registry
5546
+ * row matches it — its completion cannot drive any gate. A loud dead-end record. */
5657
5547
  instanceRef: GlobalDocumentReference;
5658
5548
  detail: string;
5659
5549
  }
@@ -5661,9 +5551,7 @@ declare type HistoryEvent =
5661
5551
  _key: string;
5662
5552
  _type: "aborted";
5663
5553
  at: string;
5664
- /** The stage the instance was on when it was hard-stopped. */
5665
5554
  stage: StageName;
5666
- /** Admin-supplied free-text reason for the abort. */
5667
5555
  reason?: string;
5668
5556
  actor?: Actor;
5669
5557
  }
@@ -5672,27 +5560,17 @@ declare type HistoryEvent =
5672
5560
  _type: "opApplied";
5673
5561
  at: string;
5674
5562
  stage: StageName;
5675
- /** The boundary that ran the op. For an action fire (caller- or
5676
- * cascade-fired), `activity` + `action` are set; for a direct edit
5677
- * (the edit seam), `edit` is set and `activity` carries the field's activity when
5678
- * the edited field is activity-scope; for an effect's completion ops,
5679
- * `effect` names the effect. */
5563
+ /** The op's boundary: an action fire sets `activity` + `action`; an edit sets `edit`
5564
+ * (plus `activity` for an activity-scope field); completion ops set `effect`. */
5680
5565
  activity?: ActivityName;
5681
5566
  action?: ActionName;
5682
- /** Set when the op was a direct edit through the edit seam (`editField`),
5683
- * not an action. */
5684
5567
  edit?: true;
5685
- /** Set when the op came from an effect handler's completion (the state
5686
- * half of an effect); names the effect. */
5687
5568
  effect?: EffectName;
5688
- /** The op's `type` (e.g. `field.set`). */
5689
5569
  opType: string;
5690
- /** Field reference the op targeted (omitted for `status.set`). */
5691
5570
  target?: {
5692
5571
  scope: FieldScope;
5693
5572
  field: string;
5694
5573
  };
5695
- /** Concrete resolved params the op acted on. Captured for audit. */
5696
5574
  resolved?: Record<string, unknown>;
5697
5575
  actor?: Actor;
5698
5576
  }
@@ -5700,30 +5578,18 @@ declare type HistoryEvent =
5700
5578
  _key: string;
5701
5579
  _type: "fieldQueryDiscarded";
5702
5580
  at: string;
5703
- /** Scope of the field whose `initialValue: {type:'query'}` result was dropped. */
5704
5581
  scope: FieldScope;
5705
- /** The field entry name. */
5706
5582
  field: string;
5707
- /** Why the lake result was discarded — the shape mismatch against the
5708
- * declared kind. The field falls back to its default (null / []). */
5709
5583
  detail: string;
5710
5584
  };
5711
5585
 
5712
5586
  export { humanize };
5713
5587
 
5714
- /**
5715
- * The in-memory groq-js dataset filters evaluate against. Built once
5716
- * per cascade entry (in the shell), passed through to `evaluateFilter`
5717
- * (in the core) for every filter check.
5718
- */
5588
+ /** The in-memory groq-js dataset the engine's filters evaluate against. */
5719
5589
  export declare interface HydratedSnapshot {
5720
- /** All hydrated docs, keyed by GDR URI as `_id`. */
5590
+ /** Hydrated docs, keyed by GDR URI as `_id`. */
5721
5591
  docs: SanityDocument[];
5722
- /**
5723
- * The set of GDR URIs present in `docs`. Helpful for tests and shells
5724
- * that want to assert "is this doc in scope?" — the core eval pipeline
5725
- * itself doesn't read it.
5726
- */
5592
+ /** Existence-check helper; the core eval pipeline itself doesn't read it. */
5727
5593
  knownIds: Set<string>;
5728
5594
  }
5729
5595
 
@@ -5846,6 +5712,17 @@ export declare type InsightSite =
5846
5712
  activity?: string;
5847
5713
  };
5848
5714
 
5715
+ /**
5716
+ * The tag's instance partition as a listen filter — the one shared change
5717
+ * feed a preview store keeps itself fresh from (an event names the touched
5718
+ * instance; the store refetches that preview alone). Deliberately unfiltered
5719
+ * beyond the tag: one upstream listener serves every view, whatever each is
5720
+ * filtered to.
5721
+ */
5722
+ export declare function instanceChangesQuery(args: {
5723
+ tag: string;
5724
+ }): CompiledQuery;
5725
+
5849
5726
  /**
5850
5727
  * Mint the Sanity document `_id` for a workflow instance — a fresh
5851
5728
  * {@link randomKey} suffix, so every instance (root or spawned child) gets a
@@ -5885,6 +5762,17 @@ export declare class InstanceNotFoundError extends WorkflowError<"instance-not-f
5885
5762
  constructor(args: { instanceId: string; detail?: string });
5886
5763
  }
5887
5764
 
5765
+ /**
5766
+ * The preview projection over the same instances {@link instancesQuery}
5767
+ * matches — a `WorkflowInstancePreview` each, kilobytes lighter than the full
5768
+ * document (no snapshot, no audit trails), for surfaces that render many runs
5769
+ * at once. Parse results through `readInstancePreviewDoc`.
5770
+ */
5771
+ export declare function instancePreviewsQuery(args: {
5772
+ tag: string;
5773
+ filter?: InstancesQueryFilter;
5774
+ }): CompiledQuery;
5775
+
5888
5776
  /** Args for the verbs that address an instance without further input. */
5889
5777
  export declare interface InstanceRefArgs {
5890
5778
  instanceId: string;
@@ -6021,10 +5909,10 @@ export declare interface InstancesQueryFilter {
6021
5909
  document?: GdrUri;
6022
5910
  /**
6023
5911
  * The multi-document form of {@link InstancesQueryFilter.document}: one
6024
- * predicate matching instances that reference ANY of the given docs,
5912
+ * predicate matching instances that reference any of the given docs,
6025
5913
  * for consumers discovering instances across many open documents at once.
6026
5914
  * Merged with `document` when both are set. Callers may defensively recheck
6027
- * with {@link instanceWatchesDocument}. A DEFINED-but-EMPTY
5915
+ * with {@link instanceWatchesDocument}. A defined but empty
6028
5916
  * array matches nothing (the GROQ-natural reading of membership in an
6029
5917
  * empty set) — omit the field for the unconstrained every-in-flight read.
6030
5918
  */
@@ -6034,7 +5922,7 @@ export declare interface InstancesQueryFilter {
6034
5922
  * a consumer tracking freshly-started instances (not yet referencing any
6035
5923
  * registered doc) sees them in the same live read. Bare ids only: an
6036
5924
  * instance's `_id` is never a GDR URI, so a URI here is a caller bug and
6037
- * is rejected. A DEFINED-but-EMPTY array matches nothing, exactly like
5925
+ * is rejected. A defined but empty array matches nothing, exactly like
6038
5926
  * {@link InstancesQueryFilter.documents}.
6039
5927
  */
6040
5928
  ids?: readonly string[];
@@ -6045,13 +5933,25 @@ export declare interface InstancesQueryFilter {
6045
5933
  /** Include completed/aborted instances (default: in-flight only). */
6046
5934
  includeCompleted?: boolean;
6047
5935
  /**
6048
- * Cap the read to the NEWEST `limit` instances — the query flips to
5936
+ * Cap the read to the newest `limit` instances — the query flips to
6049
5937
  * `startedAt desc` and slices, so a bounded consumer (a dashboard over an
6050
5938
  * unbounded dataset) reads the most recent rows instead of the oldest.
6051
5939
  * Unlimited reads keep the ascending order adapters index by. Must be a
6052
5940
  * positive integer.
6053
5941
  */
6054
5942
  limit?: number;
5943
+ /**
5944
+ * Keyset cursor into the newest-first order: only instances strictly older
5945
+ * than this position. Pass the last row of the previous page, and the next
5946
+ * `limit` rows continue where it ended. A cursor rather than an offset, so
5947
+ * rows starting or concluding between pages can't shift what a page holds.
5948
+ * Requires `limit`: pages only exist in the newest-first sliced read.
5949
+ */
5950
+ before?: {
5951
+ /** The `_id` tiebreak for rows sharing `startedAt`. */
5952
+ id: string;
5953
+ startedAt: string;
5954
+ };
6055
5955
  }
6056
5956
 
6057
5957
  /**
@@ -6071,9 +5971,8 @@ export declare function instanceWatchesDocument(
6071
5971
  document: GdrUri,
6072
5972
  ): boolean;
6073
5973
 
6074
- /** The trigger split: a `when` action is cascade-fired; without one it is
6075
- * fireAction-fired. The single spelling of that test — structural over
6076
- * `when` so authoring and stored shapes both qualify. */
5974
+ /** The canonical cascade-fired test: structural on `when`, so both authored
5975
+ * and stored shapes qualify. */
6077
5976
  export declare function isCascadeFired(action: {
6078
5977
  when?: string | undefined;
6079
5978
  }): boolean;
@@ -6145,7 +6044,8 @@ export declare function isInputSourced(
6145
6044
  * apart from other array kinds (e.g. the `todoList` sugar's
6146
6045
  * `{label, status}`). Accepts both vocabularies — a deployed definition
6147
6046
  * entry (`type`) and a resolved instance entry (`_type`) — so start-time
6148
- * and runtime surfaces share one verdict.
6047
+ * and runtime surfaces share one verdict. Resolved-entry overload last, as
6048
+ * on {@link isTodoListEntry}.
6149
6049
  */
6150
6050
  export declare function isNotesEntry(entry: FieldEntry): entry is FieldEntry & {
6151
6051
  type: "array";
@@ -6246,7 +6146,9 @@ export declare function isTerminalStage(stage: Stage): boolean;
6246
6146
  * `status` rows, which tells a todo list apart from other array kinds (e.g.
6247
6147
  * the `notes` sugar's `{body, actor, at}`). Accepts both vocabularies —
6248
6148
  * a deployed definition entry (`type`) and a resolved instance entry
6249
- * (`_type`) — so start-time and runtime surfaces share one verdict.
6149
+ * (`_type`) — so start-time and runtime surfaces share one verdict. The
6150
+ * resolved-entry overload comes last: contextual typing reads an overloaded
6151
+ * argument's FINAL signature, which `.filter(isTodoListEntry)` needs.
6250
6152
  */
6251
6153
  export declare function isTodoListEntry(
6252
6154
  entry: FieldEntry,
@@ -6275,31 +6177,23 @@ export declare function isTodoListItem(row: unknown): row is TodoListItem;
6275
6177
  * did not. The shape is legal and resumable — `startInstance` with the same
6276
6178
  * `instanceId` completes the outstanding commits. Readers should present it
6277
6179
  * as an incomplete start, never as a normal run sitting at its initial
6278
- * stage. Terminal instances are excluded: an aborted never-primed husk
6180
+ * stage. Terminal instances are excluded: an aborted never-primed instance
6279
6181
  * reads as aborted, not as still-resumable.
6280
6182
  */
6281
6183
  export declare function isUnprimed(
6282
6184
  instance: Pick<WorkflowInstance, "stages" | "completedAt" | "abortedAt">,
6283
6185
  ): boolean;
6284
6186
 
6285
- /**
6286
- * Deterministic id so deploy/retract are query-free and idempotent. Derived
6287
- * from the guard's authored `name` — an author-controlled handle that stays
6288
- * stable when guards are reordered or inserted (a positional index would
6289
- * silently shift).
6290
- */
6187
+ /** Deterministic id (from the guard's authored `name`) so deploy/retract are query-free and idempotent; a positional index would silently shift if guards are reordered. */
6291
6188
  export declare function lakeGuardId(args: {
6292
6189
  instanceDocId: string;
6293
6190
  guardName: string;
6294
6191
  }): string;
6295
6192
 
6296
6193
  /**
6297
- * The id a lake-facing check binds for an actor: the resource-local
6298
- * principal id when the namespaces diverge, otherwise the actor's own
6299
- * (account-global) id. Every advisory that must agree with the lake's
6300
- * `identity()` — guard previews and pre-flights, the anchor ACL's `$can`
6301
- * grant filters — resolves through this one rule; binding `actor.id`
6302
- * directly at a lake edge reintroduces the divergent-identity mismatch.
6194
+ * The one rule every lake-facing identity check (guard previews/pre-flights, `$can` grant filters)
6195
+ * must resolve through to agree with the lake's own `identity()`; binding `actor.id` directly at a
6196
+ * lake edge reintroduces the divergent-identity mismatch.
6303
6197
  */
6304
6198
  export declare function lakePrincipalId(args: {
6305
6199
  actor: {
@@ -6359,11 +6253,6 @@ declare type LiteralExpr = {
6359
6253
  value: unknown;
6360
6254
  };
6361
6255
 
6362
- /**
6363
- * One loaded doc plus the resource it came from. The shell builds
6364
- * this list by routing reads to the right client for each doc, then
6365
- * hands it to `buildSnapshot`.
6366
- */
6367
6256
  export declare interface LoadedDoc {
6368
6257
  doc: SanityDocument;
6369
6258
  resource: WorkflowResource;
@@ -6380,18 +6269,17 @@ export declare interface LogicalRef {
6380
6269
  version?: number | "latest";
6381
6270
  }
6382
6271
 
6272
+ /**
6273
+ * Off-system deep-link target — render-only metadata whose presence marks an
6274
+ * activity as off-system (BPMN Manual Task). Either a static URL, or a field
6275
+ * reference whose resolved document the consumer opens; deploy checks the
6276
+ * `field` variant points at a doc-valued entry.
6277
+ */
6383
6278
  export declare type ManualTarget = v.InferOutput<
6384
6279
  typeof StoredManualTargetSchema
6385
6280
  >;
6386
6281
 
6387
- /**
6388
- * Evaluate a grant's GROQ filter against a single document with the
6389
- * supplied identity. Returns true iff the document survives the filter.
6390
- *
6391
- * The implementation parses `*[<filter>]` once per filter string,
6392
- * evaluates against a singleton dataset, and asks the result for its
6393
- * length — `length === 1` means the doc passed.
6394
- */
6282
+ /** Returns true iff `document` survives `filter`'s GROQ predicate under the supplied identity. */
6395
6283
  declare function matchesFilter(args: {
6396
6284
  document: {
6397
6285
  _id?: string;
@@ -6405,10 +6293,9 @@ declare function matchesFilter(args: {
6405
6293
  export { MAX_COUNTERFACTUAL_INDEX };
6406
6294
 
6407
6295
  /**
6408
- * The oldest engine model that can safely read a persisted engine document.
6409
- * The engine always writes the stamp pair, so a `modelVersion`
6410
- * with no `minReaderModel` is malformed foreign data — read conservatively:
6411
- * the stamp itself is the floor. A doc with neither is model 0 (floor 0).
6296
+ * The engine always writes both stamps together, so a bare `modelVersion` with no
6297
+ * `minReaderModel` is malformed foreign data; that case reads the version itself as the
6298
+ * floor (conservative fallback).
6412
6299
  */
6413
6300
  export declare function minReaderModelOf(doc: object): number;
6414
6301
 
@@ -6467,11 +6354,9 @@ export declare function missingRequiredInputs(args: {
6467
6354
  }[];
6468
6355
 
6469
6356
  /**
6470
- * A persisted engine document requires a NEWER reader than this engine: its
6471
- * `minReaderModel` floor is above {@link DATA_MODEL_VERSION}. Reading it
6472
- * could silently misinterpret whatever the newer model reshaped, so every
6473
- * engine read path fails hard instead. The remediation is always the same:
6474
- * upgrade `@sanity/workflow-engine`.
6357
+ * Thrown when a document's reader floor exceeds {@link DATA_MODEL_VERSION} reading it
6358
+ * could silently misinterpret a newer model's reshape, so the read fails hard instead.
6359
+ * Fix: upgrade `@sanity/workflow-engine`.
6475
6360
  */
6476
6361
  export declare class ModelVersionAheadError extends WorkflowError<"model-version-ahead"> {
6477
6362
  readonly documentId: string;
@@ -6485,13 +6370,10 @@ export declare class ModelVersionAheadError extends WorkflowError<"model-version
6485
6370
  });
6486
6371
  }
6487
6372
 
6488
- /** The data model a persisted engine document conforms to. A document with no
6489
- * stamp was last written before governance existed — model 0. Reads the
6490
- * stamp structurally (persisted docs reach the gate as typed docs,
6491
- * projections, and raw snapshot reads alike); a non-number stamp is foreign
6492
- * data the engine never wrote and also reads as model 0. */
6373
+ /** A document with no stamp, or a non-number stamp (foreign data this engine never wrote), reads as model 0. */
6493
6374
  export declare function modelVersionOf(doc: object): number;
6494
6375
 
6376
+ /** The lake operations a guard can gate — see the guard types in ./authorization.ts. */
6495
6377
  declare const MUTATION_GUARD_ACTIONS: readonly [
6496
6378
  "create",
6497
6379
  "update",
@@ -6537,7 +6419,8 @@ export declare type MutationGuardAction =
6537
6419
  * compile inputs, so the field set lives in one place.
6538
6420
  */
6539
6421
  export declare interface MutationGuardBody {
6540
- /** Engine-layer: the single datasource this guard belongs to. */
6422
+ /** The single datasource this guard belongs to — the engine spans
6423
+ * datasources and must record which one, since the lake is per-datasource and infers the resource from storage. */
6541
6424
  resourceType: string;
6542
6425
  resourceId: string;
6543
6426
  /**
@@ -6608,6 +6491,13 @@ export declare class MutationGuardDeniedError extends WorkflowError<"mutation-gu
6608
6491
  export declare interface MutationGuardDoc extends MutationGuardBody {
6609
6492
  _id: string;
6610
6493
  _type: typeof GUARD_DOC_TYPE;
6494
+ /**
6495
+ * Deliberately NO engine data-model stamp (`modelVersion`/`minReaderModel`)
6496
+ * — this doc format is the lake's forthcoming contract, and the engine
6497
+ * must not grow fields on a shape it doesn't own. Assigned by the lake on
6498
+ * write — never sent on create (an empty-string value fails datetime
6499
+ * validation).
6500
+ */
6611
6501
  _rev?: string;
6612
6502
  _createdAt?: string;
6613
6503
  _updatedAt?: string;
@@ -6651,15 +6541,14 @@ export declare interface NoteItem {
6651
6541
  at?: string | null;
6652
6542
  }
6653
6543
 
6654
- /**
6655
- * `notes` an append-only audit/comment log. Sugar over `array of object
6656
- * { body, actor, at }` (the `actor`/`at` sub-fields match the `audit` op's
6657
- * stamp names, so it pairs with it). Never a stored kind.
6658
- */
6544
+ /** An append-only audit/comment log: sugar over `array of object {body, actor, at}` — the `actor`/`at`
6545
+ * names match the `audit` op's stamp fields, so it pairs with it. Never a stored kind. */
6659
6546
  declare type NotesField = FieldBase<AuthoringEditable, GroupMembership> & {
6660
6547
  type: "notes";
6661
6548
  };
6662
6549
 
6550
+ /** A `field.updateWhere` / `field.removeWhere` op's `where` selects rows to
6551
+ * mutate with rendered-scope GROQ (`$row`, `$params` bound) — row selection, not a gate; an unevaluable row never matches. */
6663
6552
  export declare type Op = v.InferOutput<typeof StoredOpSchema>;
6664
6553
 
6665
6554
  /**
@@ -6804,22 +6693,26 @@ export declare interface ParsedGdr {
6804
6693
  export declare function parseGdr(uri: string): ParsedGdr;
6805
6694
 
6806
6695
  /**
6807
- * Parse a fetched guard document, failing hard with a
6808
- * {@link PersistedDocShapeError} naming the document and every offending
6809
- * field. No model-version gate: the guard doc carries no stamp by design —
6810
- * its `_type` cutover is its versioning event.
6696
+ * Throws {@link PersistedDocShapeError} on shape mismatch. Unlike other
6697
+ * persisted docs, this doc carries no model-version stamp to gate on.
6811
6698
  */
6812
6699
  export declare function parseGuardDocument(doc: unknown): MutationGuardDoc;
6813
6700
 
6814
6701
  /**
6815
6702
  * Parse a fetched `sanity.workflow.instance` document, failing hard with a
6816
6703
  * {@link PersistedDocShapeError} naming the document and every offending
6817
- * field. The caller's model-version gate (`assertReadableModel`) comes
6818
- * FIRST a doc from beyond the reader floor is a governed
6704
+ * field. The caller's model-version gate (`assertReadableModel`) must run
6705
+ * first: a doc from beyond the reader floor is a governed
6819
6706
  * `ModelVersionAheadError`, not a shape error.
6820
6707
  */
6821
6708
  export declare function parseInstanceDocument(doc: unknown): WorkflowInstance;
6822
6709
 
6710
+ /** {@link parseInstanceDocument}'s row-projection counterpart, with the same
6711
+ * gate-first contract. */
6712
+ export declare function parseInstancePreviewDocument(
6713
+ doc: unknown,
6714
+ ): WorkflowInstancePreview;
6715
+
6823
6716
  /**
6824
6717
  * Parse a resource-shaped GDR (`<type>:<id>`, no document part) into the
6825
6718
  * {@link WorkflowResource} it names. The one grammar for resource addresses —
@@ -7065,25 +6958,39 @@ export { quoted };
7065
6958
  export declare const READER_MODEL_ROLLOUT_URL =
7066
6959
  "https://www.sanity.io/docs/editorial-workflows/prerelease";
7067
6960
 
7068
- /** A producer has not explicitly acknowledged this engine's writer capability. */
6961
+ /** A producer has not acknowledged the floor required by its submitted definitions. */
7069
6962
  export declare class ReaderModelAcknowledgementError extends WorkflowError<"reader-model-acknowledgement"> {
7070
6963
  readonly code = "WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
7071
6964
  readonly expectedMinReaderModel: unknown;
6965
+ readonly requiredMinReaderModel: number;
7072
6966
  readonly engineMinReaderModel = 4;
7073
- readonly engineModelVersion = 7;
6967
+ readonly engineMaxReaderModel = 8;
6968
+ readonly engineModelVersion = 8;
7074
6969
  readonly documentationUrl =
7075
6970
  "https://www.sanity.io/docs/editorial-workflows/prerelease";
7076
- constructor(expectedMinReaderModel: unknown, context?: string);
6971
+ constructor(
6972
+ expectedMinReaderModel: unknown,
6973
+ options?: {
6974
+ requiredMinReaderModel?: number;
6975
+ context?: string;
6976
+ },
6977
+ );
7077
6978
  }
7078
6979
 
7079
6980
  /**
7080
- * The one spelling of the instance read discipline model gate
7081
- * ({@link assertReadableModel}) first, shape parse
7082
- * ({@link parseInstanceDocument}) second shared by the point-read funnel
6981
+ * The single definition of the instance read discipline (model gate
6982
+ * {@link assertReadableModel} first, shape parse
6983
+ * {@link parseInstanceDocument} second), shared by the point-read funnel
7083
6984
  * above and the list-read sites that fetch instance rows in bulk.
7084
6985
  */
7085
6986
  export declare function readInstanceDoc(doc: SanityDocument): WorkflowInstance;
7086
6987
 
6988
+ /** {@link readInstanceDoc}'s preview-projection counterpart: the same
6989
+ * gate-then-parse order over an `instancePreviewsQuery` result. */
6990
+ export declare function readInstancePreviewDoc(
6991
+ doc: unknown,
6992
+ ): WorkflowInstancePreview;
6993
+
7087
6994
  /**
7088
6995
  * Whether a watched ref reads RAW — never perspective-scoped. The
7089
6996
  * instance, its ancestors, and its spawned children (all instance docs), and
@@ -7095,16 +7002,10 @@ export declare function readInstanceDoc(doc: SanityDocument): WorkflowInstance;
7095
7002
  */
7096
7003
  export declare function readsRaw(ref: { type: string }): boolean;
7097
7004
 
7098
- /**
7099
- * Whether a GROQ expression reads its ROOT document the candidate document
7100
- * a `start.filter` binds as root. A bare attribute access (`_type == 'task'`)
7101
- * or `@` in the OUTER scope reads the root; the same inside a construct that
7102
- * rebinds the implicit `this` per element (`*[...]` filters, projections,
7103
- * `map`/pipe traversals) addresses THOSE items, so it doesn't. `^` (Parent)
7104
- * climbs scopes — one that escapes past the outermost scope lands back on the
7105
- * root and counts, wherever it is nested. A malformed expression reads
7106
- * nothing here ({@link conditionSyntaxIssues} owns the parse error).
7107
- */
7005
+ /** Whether a GROQ expression reads its ROOT document — the candidate a
7006
+ * `start.filter` binds, not an item inside a rebound scope (filters, `map`). A `^`
7007
+ * that escapes past the outermost scope lands back on the root and counts. A
7008
+ * malformed expression reads nothing here, so it returns `false`. */
7108
7009
  export declare function readsRootDocument(groq: string): boolean;
7109
7010
 
7110
7011
  /** Make a GDR pointer to a Canvas-resource doc. */
@@ -7172,15 +7073,10 @@ export declare class RefResourceUndeclaredError extends WorkflowError<"ref-resou
7172
7073
  export declare function refsOf(def: WorkflowDefinition): LogicalRef[];
7173
7074
 
7174
7075
  /**
7175
- * The GDR `type`s in a reference-kind ({@link refKindAcceptsTypes}) value
7176
- * that the entry's declared accepted `types` reject — empty when the value
7177
- * conforms, the entry declares no `types`, or the kind isn't a ref. A GDR's
7178
- * `type` names the target document's schema type, so this is the
7179
- * declared-target-type contract. Skips anything that isn't GDR-shaped — the
7180
- * shape schemas scream about those. Boundaries that need their own error
7181
- * framing (the spawn `with` projection gates its remediation hint on the
7182
- * generic `"document"` type being among the rejects) read this; everything
7183
- * else goes through {@link refTypeIssues} / {@link checkFieldValue}.
7076
+ * GDR `type`s in a reference-kind ({@link refKindAcceptsTypes}) value that the
7077
+ * entry's declared `types` reject — empty when it conforms, no `types` are
7078
+ * declared, or the kind isn't a ref. Skips non-GDR-shaped values; the shape
7079
+ * schemas already reject those.
7184
7080
  */
7185
7081
  export declare function rejectedRefTypes(args: {
7186
7082
  entryType: string;
@@ -7246,6 +7142,11 @@ export declare type RemediationVerb =
7246
7142
  | "set-stage"
7247
7143
  | "abort";
7248
7144
 
7145
+ /** The reader model a deployment must acknowledge for its submitted definitions. */
7146
+ export declare function requiredDefinitionReaderModel(
7147
+ definitions: readonly unknown[],
7148
+ ): number;
7149
+
7249
7150
  /**
7250
7151
  * Thrown when a workflow is started (or a child spawned) without a value for
7251
7152
  * a field entry marked `required`. Mirrors {@link ActionParamsInvalidError}:
@@ -7301,14 +7202,6 @@ export declare interface RequirementDescriptor {
7301
7202
  */
7302
7203
  export declare const RESERVED_CONDITION_VARS: readonly string[];
7303
7204
 
7304
- /**
7305
- * What to reset a stuck activity INTO — the two non-`failed` outcomes that
7306
- * unstick a stage gated on it. `active` re-runs it (back in progress, so a
7307
- * caller drives it to completion again); `skipped` bypasses it (terminal but
7308
- * resolved, so `$allActivitiesDone` can satisfy and a gated exit transition
7309
- * fire). `done` is deliberately absent: a reset is recovery, not a silent
7310
- * declaration that the work succeeded.
7311
- */
7312
7205
  declare const RESET_ACTIVITY_TARGETS: readonly ["active", "skipped"];
7313
7206
 
7314
7207
  export declare interface ResetActivityArgs extends DedupableOperationArgs {
@@ -7336,6 +7229,14 @@ export declare type ResetActivityResult =
7336
7229
  to: ResetActivityTarget;
7337
7230
  };
7338
7231
 
7232
+ /**
7233
+ * What to reset a stuck activity INTO — the two non-`failed` outcomes that
7234
+ * unstick a stage gated on it. `active` re-runs it (back in progress, so a
7235
+ * caller drives it to completion again); `skipped` bypasses it (terminal but
7236
+ * resolved, so `$allActivitiesDone` can satisfy and a gated exit transition
7237
+ * fire). `done` is deliberately absent: a reset is recovery, not a silent
7238
+ * declaration that the work succeeded.
7239
+ */
7339
7240
  export declare type ResetActivityTarget =
7340
7241
  (typeof RESET_ACTIVITY_TARGETS)[number];
7341
7242
 
@@ -7343,8 +7244,9 @@ export declare type ResetActivityTarget =
7343
7244
  * Resolve the engine's `WorkflowAccess` for a client — actor and grants
7344
7245
  * (when a path is supplied) fetched from its token in parallel and cached.
7345
7246
  * Throws if the client can't yield an actor — the engine refuses to operate
7346
- * without an identity. Does **not** fetch User Attributes; see
7347
- * {@link resolveUserAttributes}.
7247
+ * without an identity. A grants-fetch failure degrades open instead: the
7248
+ * rendered `$can` stays undefined and the real Sanity write boundary still
7249
+ * enforces. Does not fetch User Attributes; see {@link resolveUserAttributes}.
7348
7250
  */
7349
7251
  export declare function resolveAccess(
7350
7252
  taggedClient: WorkflowClient,
@@ -7386,8 +7288,9 @@ export declare interface ResolveClientActorArgs {
7386
7288
  * `resolvedAt` — the lake-read time — so `resolvedAt` is provenance-driven,
7387
7289
  * not kind-specific. `object` / `array` entries carry their declared
7388
7290
  * sub-field shape (`fields` / `of`) — and the reference kinds
7389
- * ({@link refKindAcceptsTypes}) their declared accepted `types` — so the
7390
- * instance is self-describing for op-time validation and rendering.
7291
+ * ({@link refKindAcceptsTypes}) their declared accepted `types`, and
7292
+ * assignment kinds their eligible `roles` so the instance is
7293
+ * self-describing for op-time validation and rendering.
7391
7294
  */
7392
7295
  export declare type ResolvedFieldEntry = {
7393
7296
  [K in FieldKind]: {
@@ -7411,6 +7314,11 @@ export declare type ResolvedFieldEntry = {
7411
7314
  of: FieldShape[];
7412
7315
  }
7413
7316
  : Record<never, never>) &
7317
+ (K extends "assignee" | "assignees"
7318
+ ? {
7319
+ roles?: string[];
7320
+ }
7321
+ : Record<never, never>) &
7414
7322
  (K extends "doc.ref" | "doc.refs" | "subject"
7415
7323
  ? {
7416
7324
  types?: string[];
@@ -7418,14 +7326,8 @@ export declare type ResolvedFieldEntry = {
7418
7326
  : Record<never, never>);
7419
7327
  }[FieldKind];
7420
7328
 
7421
- /**
7422
- * The resolved entry a field site names, read from the instance's runtime
7423
- * `fields[]` at the site's scope — the instance copy that carries what an
7424
- * evaluation doesn't (the declared `of`/`fields` shape). Stage- and
7425
- * activity-scope sites resolve against the OPEN stage. `undefined` when the
7426
- * field hasn't been resolved yet (e.g. an activity-scope field before its
7427
- * activity activated).
7428
- */
7329
+ /** Resolves against the OPEN stage for stage/activity scopes; `undefined`
7330
+ * when the field hasn't resolved yet (e.g. an activity field before activation). */
7429
7331
  export declare function resolveFieldEntry(
7430
7332
  instance: WorkflowInstance,
7431
7333
  site: {
@@ -7459,26 +7361,20 @@ export declare type ResourceAliases = Record<string, WorkflowResource>;
7459
7361
  * Collapse a deployment's `resourceAliases` bindings into the
7460
7362
  * {@link ResourceAliases} map (handle name → physical resource) that
7461
7363
  * `deployDefinitions` expands `@<handle>:` references against. Deploy-time
7462
- * only — the map never reaches any other verb.
7364
+ * only — the map never reaches any other verb. A duplicate binding name
7365
+ * silently overwrites here (last wins), which is why `DeploymentSchema`
7366
+ * rejects one at parse time, before this ever runs.
7463
7367
  */
7464
7368
  export declare function resourceAliasesToMap(
7465
7369
  resourceAliases: WorkflowDeployment["resourceAliases"],
7466
7370
  ): ResourceAliases;
7467
7371
 
7468
7372
  /**
7469
- * Routing override for cross-resource reads (subject + ancestor docs that
7470
- * live in a different Sanity resource than the workflow). Called with a
7471
- * parsed GDR; return a client for that resource, or `undefined` to let the
7472
- * engine route it its own client for the workflow resource, a derived
7473
- * sibling ({@link WorkflowClient.withConfig}) for anything else.
7474
- *
7475
- * Serving a resource also DECLARES it on the written-ref surface: the write
7476
- * boundaries probe this resolver per ref, so narrowing a resolver rejects
7477
- * refs to the resources it stops serving.
7478
- *
7479
- * Engine-owned verb scopes rebind resolved clients onto
7480
- * `ENGINE_API_VERSION`. Effect handlers derive request-tagged siblings from
7481
- * resolver clients so their concrete APIs remain available and attributed.
7373
+ * Cross-resource read routing override return a client for the parsed
7374
+ * GDR's resource, or `undefined` to let the engine route it. Serving a
7375
+ * resource also declares it on the written-ref surface, so narrowing this
7376
+ * resolver rejects refs to resources it stops serving; engine verb scopes
7377
+ * also rebind any returned client onto their own API version.
7482
7378
  */
7483
7379
  export declare type ResourceClientResolver = (
7484
7380
  parsed: ParsedGdr,
@@ -7527,38 +7423,22 @@ export declare interface ResourceSurface {
7527
7423
  * the stage and must keep its lock) or gone (leave the lock as the orphan
7528
7424
  * seam rather than silently unlocking a vanished instance — the same
7529
7425
  * over-lock direction as deploy).
7426
+ *
7427
+ * Guard revisions are observed before the live-stage gate, then only those
7428
+ * revisions are deleted: a deploy landing in between changes the revision,
7429
+ * so the delete's revision fence fails instead of deleting the active guard.
7530
7430
  */
7531
7431
  export declare function retractStageGuards(args: StageGuardArgs): Promise<void>;
7532
7432
 
7533
- export declare type RoleAliases = v.InferOutput<typeof RoleAliasesSchema>;
7534
-
7535
7433
  /**
7536
- * Role aliasing the "can be fulfilled by" map, an authoring convenience.
7537
- * A `roles` gate (or an `assignees` entry) names the role the author writes;
7538
- * but the SAME capability is often carried by different role names depending
7539
- * on how a given project deploys its Content Lake roles, and several roles may
7540
- * legitimately do the job. Rather than enumerate every equivalent role inline
7541
- * in each gate — or fork the definition per deployment — declare once here
7542
- * which other roles also fulfill it.
7543
- *
7544
- * Each key is a role a gate/assignee names; its value lists the roles that
7545
- * also satisfy it. The reserved key `"*"` lists roles that fulfill ANY gate
7546
- * (e.g. `"*": ["administrator"]` — whatever this deployment's broad role is).
7547
- * `"*"` is the spelling authors write; it is rewritten to a lake-safe stored
7548
- * key before the definition is persisted, since the Content Lake rejects `"*"`
7549
- * as a document attribute name (see {@link normalizeRoleAliases}).
7550
- *
7551
- * Applied as an in-place expansion of the REQUIRED side, never the actor's
7552
- * roles: the `roles` gate bakes the expanded membership into its desugared
7553
- * GROQ at define time; `$assigned` expands the assignee's role at match time
7554
- * (see {@link expandRequiredRoles}). Carried into the stored definition for
7555
- * that runtime half.
7556
- *
7557
- * Advisory, like every engine gate — an alias only predicts what the
7558
- * deployment's Content Lake ACLs already allow, it never grants access. An
7559
- * alias the lake won't honor makes the gate predict "allowed" for a write the
7560
- * lake then rejects, so keep it true to what's actually deployed.
7434
+ * Roles that may fulfil each authored role. Aliases widen action gates,
7435
+ * `$assigned`, and assignment-field user eligibility by expanding the required
7436
+ * side; they never alter an actor's roles. Collective role assignees remain
7437
+ * literal ownership values and are not widened by this map. The authored `"*"`
7438
+ * key lists universal fulfillers and is normalized before persistence.
7561
7439
  */
7440
+ export declare type RoleAliases = v.InferOutput<typeof RoleAliasesSchema>;
7441
+
7562
7442
  declare const RoleAliasesSchema: v.RecordSchema<
7563
7443
  v.SchemaWithPipe<
7564
7444
  readonly [
@@ -7726,6 +7606,18 @@ export declare class SpawnContractsInvalidError extends WorkflowError<"spawn-con
7726
7606
  constructor(args: { issues: SpawnContractIssue[]; message: string });
7727
7607
  }
7728
7608
 
7609
+ /**
7610
+ * A pure container — name, fields, guards, activities, transitions, no
7611
+ * behaviour of its own. Activities own enter, transitions own exit and
7612
+ * arrival; a stage with no transitions IS terminal (structural, nothing to
7613
+ * declare or mis-declare). `guards` are lake mutation guards active while
7614
+ * the stage holds, each compiling to a persisted guard document deployed on
7615
+ * stage entry and retracted on exit. `editable` is a tighten-only override
7616
+ * for the time the stage holds, keyed by an in-scope field name: the field's
7617
+ * own `editable` is the ceiling, ANDed with the stage value at runtime, so an
7618
+ * override can only NARROW — never open a field the baseline left closed. An
7619
+ * unlisted field inherits its baseline.
7620
+ */
7729
7621
  export declare type Stage = StageFields<
7730
7622
  FieldEntry,
7731
7623
  Activity,
@@ -7863,6 +7755,19 @@ export declare const START_REQUIREMENT_VARS: readonly {
7863
7755
  description: string;
7864
7756
  }[];
7865
7757
 
7758
+ /**
7759
+ * How standalone runs of this workflow begin. `filter` is a READ-SIDE
7760
+ * visibility predicate — "should a start surface offer this workflow for
7761
+ * this document?" — evaluated by `definitionsForDocument`/applicability in
7762
+ * the browse-time-pure start-filter context (`$tag`/`$definition`/`$now`
7763
+ * bound; `$fields` cannot exist before inputs do, so a `$fields` read here
7764
+ * is deploy-rejected). It is NOT a `startInstance` gate; the verb never
7765
+ * reads it. `requirements` are named readiness checks evaluated in author
7766
+ * order in the start-time context (GROQ nodes add `$fields`; `singleSubject`
7767
+ * is the one-in-flight-run-per-subject rule) — every node must pass before
7768
+ * `startInstance` commits. Both are advisory like every engine-side check;
7769
+ * the Content Lake remains the only enforcement point.
7770
+ */
7866
7771
  export declare type StartBlock = StartFields & {
7867
7772
  kind: StartKind;
7868
7773
  };
@@ -7924,9 +7829,6 @@ export declare interface StartEvaluation {
7924
7829
  invalidInitialFields: InitialFieldIssue[];
7925
7830
  }
7926
7831
 
7927
- /** Type-mirror of {@link startFields}: how standalone runs of this workflow
7928
- * begin. Stored requires `kind` (desugar fills the `'interactive'` default);
7929
- * authoring may omit it — so each variant declares it. */
7930
7832
  declare type StartFields = {
7931
7833
  filter?: string | undefined;
7932
7834
  requirements?: StartRequirement[] | undefined;
@@ -8092,16 +7994,12 @@ export declare class StartNotSettledError extends WorkflowError<"start-not-settl
8092
7994
  });
8093
7995
  }
8094
7996
 
8095
- /**
8096
- * Why a definition can't be started standalone, or `undefined` when it can.
8097
- * Advisory — the engine itself does not refuse ({@link isStartableDefinition})
8098
- * — but a start surface has no way to supply the parent context a spawn-only
8099
- * child expects, so it fails fast with this message instead.
8100
- */
7997
+ /** Advisory only, per {@link isStartableDefinition} — a start surface has no parent context to give a spawn-only child, so it rejects fast with this message instead. */
8101
7998
  export declare function startRefusal(definition: {
8102
7999
  lifecycle?: WorkflowLifecycle | undefined;
8103
8000
  }): string | undefined;
8104
8001
 
8002
+ /** Every named readiness requirement accepted by workflow `start.requirements`. */
8105
8003
  export declare type StartRequirement =
8106
8004
  | GroqRequirement
8107
8005
  | SingleSubjectRequirement;
@@ -8153,15 +8051,6 @@ export declare interface StartSliceRow {
8153
8051
  completedAt: string | null;
8154
8052
  }
8155
8053
 
8156
- /**
8157
- * Declared editability of a field — the generic edit seam's gate. Default
8158
- * (absent) is NOT editable: a field is op-only engine working memory unless the
8159
- * modeler opens it. The stored form is `true` (editable by anyone within the
8160
- * field's scope window) or an EDIT CONDITION — rendered-scope GROQ (`$actor`,
8161
- * `$can`, `$attributes`, `$fields`, `$assigned`), checked like an action filter
8162
- * to decide who-may-edit. ADVISORY like every engine gate — it disables the
8163
- * inline field and explains; a {@link Guard} declares the intended write-lock.
8164
- */
8165
8054
  declare const StoredEditableSchema: v.UnionSchema<
8166
8055
  [
8167
8056
  v.LiteralSchema<true, undefined>,
@@ -8383,6 +8272,7 @@ declare const StoredFieldOpSchema: v.VariantSchema<
8383
8272
  undefined
8384
8273
  >;
8385
8274
 
8275
+ /** A field reference with `scope` already resolved — the form every op target carries. */
8386
8276
  export declare type StoredFieldRef = v.InferOutput<typeof StoredFieldRefSchema>;
8387
8277
 
8388
8278
  declare const StoredFieldRefSchema: v.StrictObjectSchema<
@@ -8668,6 +8558,12 @@ export declare function stripSystemFields(
8668
8558
  * its activity looking merely "active", so it wins over the activity- and
8669
8559
  * transition-level symptoms it produces. Note an active activity awaiting a human
8670
8560
  * action is NOT here — that's the healthy {@link Diagnosis} `waiting` state.
8561
+ *
8562
+ * `transition-unevaluable` is the recoverable arm: every activity resolved,
8563
+ * but an exit transition's `when` came back GROQ `null` (a referenced operand
8564
+ * is missing or unreadable), so selection halts and the cascade re-fires once
8565
+ * the operand resolves — where `no-transition-fires` means every `when` is a
8566
+ * definite `false`. It carries the undecidable transitions.
8671
8567
  */
8672
8568
  export declare type StuckCause =
8673
8569
  | {
@@ -8685,13 +8581,6 @@ export declare type StuckCause =
8685
8581
  | {
8686
8582
  kind: "no-transition-fires";
8687
8583
  }
8688
- /**
8689
- * Every activity resolved, but an exit transition's `when` is *unevaluable*
8690
- * (GROQ `null` — a referenced operand is missing/unreadable), so selection
8691
- * halts. Unlike {@link StuckCause} `no-transition-fires` this is recoverable:
8692
- * the cascade re-fires once the operand resolves (e.g. the subject is
8693
- * published or the field is filled). Carries the undecidable transitions.
8694
- */
8695
8584
  | {
8696
8585
  kind: "transition-unevaluable";
8697
8586
  transitions: string[];
@@ -8721,14 +8610,9 @@ export declare interface SubjectPermissionDenial {
8721
8610
  permission: DocumentValuePermission;
8722
8611
  }
8723
8612
 
8724
- /** One foreign resource's forecast inputs: the actor's grants there, and the
8725
- * actor's principal id in THAT resource's own identity namespace. */
8726
8613
  declare interface SubjectResourceAccess {
8727
8614
  grants: Grant[];
8728
- /** What that resource's lake `identity()` returns for the acting token
8729
- * resolved through the resource's own routed client, so a dataset
8730
- * resource contributes the actor's per-project user id and an org-level
8731
- * resource the account-global id. */
8615
+ /** The actor's principal id in this resource's own namespace: per-project user id for a dataset resource, account-global id for an org-level one. */
8732
8616
  actorId: string;
8733
8617
  }
8734
8618
 
@@ -8835,18 +8719,23 @@ export declare interface SubworkflowEntry {
8835
8719
  };
8836
8720
  }
8837
8721
 
8722
+ /**
8723
+ * Fan-out declared as an action's `spawn`, read back as `$subworkflows`.
8724
+ * `forEach` is GROQ producing one row per subworkflow (bound as `$row`); each
8725
+ * row needs an identity the engine can adopt on re-entry (`_key` ?? `_id` ??
8726
+ * GDR `id`, or the value itself for a scalar row) or the spawn fails.
8727
+ * `definition` resolves by stable `name`, ordered `version desc` unless
8728
+ * pinned. `with` seeds each child's initial fields; `context` delivers extra
8729
+ * parent-scope values into the child's `$context`. `onExit` governs only
8730
+ * still-live children when the cohort's scope stops applying: `'detach'`
8731
+ * (default) lets them run to completion, `'abort'` kills them recursively —
8732
+ * always an authored choice, never automatic. Whether the PARENT may move at
8733
+ * all is a separate gate over `$subworkflows`.
8734
+ */
8838
8735
  export declare type Subworkflows = v.InferOutput<typeof SubworkflowsSchema>;
8839
8736
 
8840
8737
  declare const SubworkflowsSchema: v.StrictObjectSchema<
8841
8738
  {
8842
- /**
8843
- * GROQ producing one row per subworkflow; each row binds as `$row`. Every
8844
- * row must carry an identity the engine can adopt against on re-entry:
8845
- * `_key` ?? `_id` ?? GDR `id` for object rows (a GDR value — `{id, type}`
8846
- * with a GDR-URI `id`, the rows a `doc.refs` field stores — keys on its
8847
- * `id`; mint a `_key` in the projection for synthetic rows), the value
8848
- * itself for scalar rows. A row without an identity fails the spawn.
8849
- */
8850
8739
  readonly forEach: v.SchemaWithPipe<
8851
8740
  readonly [
8852
8741
  v.StringSchema<undefined>,
@@ -8880,7 +8769,6 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
8880
8769
  },
8881
8770
  undefined
8882
8771
  >;
8883
- /** Initial fields for each subworkflow — entry name → GROQ over `$row` + the parent scope. */
8884
8772
  readonly with: v.OptionalSchema<
8885
8773
  v.RecordSchema<
8886
8774
  v.SchemaWithPipe<
@@ -8899,11 +8787,6 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
8899
8787
  >,
8900
8788
  undefined
8901
8789
  >;
8902
- /**
8903
- * Extra values evaluated in the parent's rendered scope at spawn time and
8904
- * delivered into each subworkflow's `$context` bag — the parent→child
8905
- * handoff.
8906
- */
8907
8790
  readonly context: v.OptionalSchema<
8908
8791
  v.RecordSchema<
8909
8792
  v.SchemaWithPipe<
@@ -8922,16 +8805,6 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
8922
8805
  >,
8923
8806
  undefined
8924
8807
  >;
8925
- /**
8926
- * What happens to still-live children when their cohort's scope stops
8927
- * applying — the spawning stage exits, or a re-fire's `forEach` no longer
8928
- * discovers their row. `'detach'` (the default) lets them run to
8929
- * completion outside the gate; `'abort'` kills them (recursively). The
8930
- * engine never destroys in-flight work implicitly — `'abort'` is always
8931
- * an authored choice. Note this governs only the CHILDREN's fate; whether
8932
- * the parent may move at all is what gates (conditions over
8933
- * `$subworkflows`) decide.
8934
- */
8935
8808
  readonly onExit: v.OptionalSchema<
8936
8809
  v.PicklistSchema<readonly ["detach", "abort"], string>,
8937
8810
  undefined
@@ -8961,6 +8834,10 @@ export declare interface SuggestedRemediation {
8961
8834
  * recovered entries is the next `drainEffects` call's job. To kill a stuck
8962
8835
  * entry WITHOUT redispatching, report it via
8963
8836
  * `completeEffect({status: 'failed'})` instead.
8837
+ *
8838
+ * A standalone export, NOT an `Engine` verb: like the guard-lifecycle
8839
+ * helpers, this is housekeeping for admin/ops tooling, not part of the
8840
+ * editor/runtime verb surface — a drain already self-recovers via takeover.
8964
8841
  */
8965
8842
  export declare function sweepStaleClaims(args: {
8966
8843
  client: WorkflowClient;
@@ -8981,12 +8858,7 @@ export declare interface SweepStaleClaimsResult {
8981
8858
  /** Lake `identity()` sentinel for system-initiated actions. */
8982
8859
  export declare const SYSTEM_IDENTITY = "<system>";
8983
8860
 
8984
- /**
8985
- * The engine's read-partition invariant as a GROQ predicate: a document is
8986
- * visible when its `tag` equals the caller's `$tag` param. The single
8987
- * definition of "tag-scoped" shared by the engine's internal lookups, the
8988
- * `workflow.query` guard, and the CLI/MCP read helpers.
8989
- */
8861
+ /** Single source of the tag-scope GROQ predicate; the engine's lookups, `workflow.query`, and CLI/MCP reads all call this instead of hand-rolling the filter. */
8990
8862
  export declare function tagScopeFilter(): string;
8991
8863
 
8992
8864
  /**
@@ -9000,22 +8872,6 @@ declare type Telemetered<T> = T & {
9000
8872
  telemetry?: WorkflowTelemetryLogger;
9001
8873
  };
9002
8874
 
9003
- /**
9004
- * The standard Sanity-intake recipe every workflow app shell shares —
9005
- * consent from `GET /intake/telemetry-status`, transport via
9006
- * `POST /intake/batch` `{projectId, batch}`, and the request tags that
9007
- * keep shell telemetry traffic identifiable in request logs. The shells
9008
- * (App SDK provider, MCP server, CLI) each own their store and
9009
- * environment gates; this module is the one home for the recipe those
9010
- * stores run on, so a change to an endpoint, body shape, or tag lands
9011
- * everywhere at once.
9012
- *
9013
- * Like the event vocabulary (`engine.telemetry.ts`), this module keeps
9014
- * the engine free of a runtime `@sanity/telemetry` dependency: the
9015
- * result is a structural mirror of that package's batched-store options,
9016
- * so a shell passes it straight to `createBatchedStore`. Drift against
9017
- * the real package is pinned by a type-level test (dev dependency).
9018
- */
9019
8875
  /** Mirror of `@sanity/telemetry`'s `ConsentStatus`. */
9020
8876
  export declare type TelemetryConsentStatus =
9021
8877
  | "undetermined"
@@ -9050,6 +8906,14 @@ export declare interface TelemetryIntakeClient {
9050
8906
  }) => Promise<T>;
9051
8907
  }
9052
8908
 
8909
+ /**
8910
+ * The statuses an activity can be resolved INTO — what `status.set` accepts.
8911
+ * A health axis, not a decision axis: a routine decision (decline, send back,
8912
+ * hold) resolves `done` and routes via a field write; `failed` means the work
8913
+ * genuinely could not complete. Only `done`/`skipped` satisfy
8914
+ * `$allActivitiesDone` — a `failed` activity blocks it permanently, surfacing
8915
+ * via `$anyActivityFailed`.
8916
+ */
9053
8917
  declare const TERMINAL_ACTIVITY_STATUSES: readonly [
9054
8918
  "done",
9055
8919
  "skipped",
@@ -9063,8 +8927,8 @@ export declare type TerminalActivityStatus =
9063
8927
  export declare type TerminalState = "aborted" | "completed" | "in-flight";
9064
8928
 
9065
8929
  /**
9066
- * Classify an instance by its terminal stamps. The ONE home for the
9067
- * precedence rule: aborted instances carry `completedAt` too (stamped at the
8930
+ * Classify an instance by its terminal stamps. The single definition of the
8931
+ * precedence rule: aborted instances have `completedAt` too (stamped at the
9068
8932
  * abort, so in-flight queries treat both terminals uniformly), so `abortedAt`
9069
8933
  * must be checked first — `'completed'` means completed *without* an abort.
9070
8934
  */
@@ -9080,15 +8944,8 @@ export declare function terminalState(
9080
8944
  */
9081
8945
  export declare function toBareId(id: string): string;
9082
8946
 
9083
- /**
9084
- * `todoList` ad-hoc, status-tracked work items. Sugar over `array of object
9085
- * { label, status, assignee?, dueDate? }`; a plain checklist is this used with
9086
- * `{label, status}` only (open ↔ done). Never a stored kind.
9087
- *
9088
- * The `dueDate` column is a `date` NAMED `dueDate`, not the {@link
9089
- * FieldValueMap.dueDate} kind — that kind reserves one deadline slot per level,
9090
- * and a repeating row has nothing to reserve.
9091
- */
8947
+ /** Ad-hoc, status-tracked work items: sugar over `array of object {label, status, assignee?, dueDate?}`; a plain checklist is that with `{label, status}` alone.
8948
+ * Its `dueDate` is a `date` column named `dueDate`, not the elevated `dueDate` kind, which reserves one deadline slot per level. Never a stored kind. */
9092
8949
  declare type TodoListField = FieldBase<AuthoringEditable, GroupMembership> & {
9093
8950
  type: "todoList";
9094
8951
  };
@@ -9110,6 +8967,16 @@ export declare interface TodoListItem {
9110
8967
  dueDate?: string | null;
9111
8968
  }
9112
8969
 
8970
+ /**
8971
+ * A pure edge — `{name, when, to}` plus presentation, no ops or effects
8972
+ * (structure never does; only actions do). Every transition is evaluated on
8973
+ * every commit and cascade; the first truthy `when` in declaration order
8974
+ * fires. No action coupling: a routing difference is written into fields by
8975
+ * an action and read by the trigger — arrival work is a `when: 'true'`
8976
+ * action in the destination stage, and exit work is an action in the source
8977
+ * stage whose `when` repeats this transition's condition (the hop rule
8978
+ * guarantees it commits before the move).
8979
+ */
9113
8980
  export declare type Transition = TransitionFields & {
9114
8981
  when: string;
9115
8982
  };
@@ -9190,10 +9057,6 @@ export declare function unsatisfiedTransitionSummaries(
9190
9057
  summary: string;
9191
9058
  }[];
9192
9059
 
9193
- /**
9194
- * Normalize Management API user-attribute payloads into the `$attributes`
9195
- * bag. Fetch/caching stays in access resolution; this module is I/O-free.
9196
- */
9197
9060
  /** Flat key → active-value record bound as advisory `$attributes` when present. */
9198
9061
  export declare type UserAttributes = Record<string, unknown>;
9199
9062
 
@@ -9237,6 +9100,12 @@ declare interface ValidationIssue {
9237
9100
  message: string;
9238
9101
  }
9239
9102
 
9103
+ /**
9104
+ * An op's write payload, resolved to concrete JSON when the op applies. Each
9105
+ * context-bound arm has a rendered `$`-twin in conditions (`actor` ↔
9106
+ * `$actor`, `now` ↔ `$now`, `self` ↔ `$self`), so learning one side teaches
9107
+ * the other. Distinct from {@link FieldSource}, a field's seed recipe.
9108
+ */
9240
9109
  export declare type ValueExpr = ValueExprInternal;
9241
9110
 
9242
9111
  declare type ValueExprInternal =
@@ -9337,110 +9206,80 @@ export { WhatIfOutcome };
9337
9206
 
9338
9207
  export { withAssignment };
9339
9208
 
9340
- /**
9341
- * The workflow verbs, bound as one object — write path, admin
9342
- * overrides, pure reads, and permission helpers. The module doc above
9343
- * describes the model.
9344
- */
9345
9209
  export declare const workflow: {
9346
9210
  /**
9347
- * Deploy a set of workflow definitions as one call. Definitions are
9348
- * immutable and content-addressed: the author writes no version, and each
9349
- * deploy compares a definition's content fingerprint to the latest version
9350
- * already deployed under its name. Identical content is a no-op
9351
- * (`unchanged`); any change mints the next version (`created`) deploy
9352
- * never patches a deployed version, so a definition can't change out from
9353
- * under the instances pinned to it. `startInstance` picks the highest
9354
- * version by default. The engine figures out the dependency order itself
9355
- * (children before parents that spawn them via `action.spawn.definition`)
9356
- * and reports a per-definition outcome (`created` / `unchanged`).
9357
- *
9358
- * Refs may point inside the batch OR at already-deployed definitions
9359
- * in the lake — both are valid. A ref pointing at neither errors with
9360
- * a clear message naming the missing target.
9361
- *
9362
- * Cycles in the dependency graph error before any write happens.
9363
- *
9364
- * Input is authored content or a fetched definition document — the document
9365
- * envelope (`_*` system fields, `tag`, `version`, `contentHash`) is stripped
9366
- * at the boundary, never fingerprinted, so a fetched document redeploys as
9367
- * `unchanged`. Any other unknown key fails loud.
9211
+ * Deploy a set of definitions as one call. Definitions are immutable and
9212
+ * content-addressed: the author writes no version, identical content no-ops
9213
+ * (`unchanged`), and any change mints the next version (`created`) — deploy
9214
+ * never patches a deployed version out from under the instances pinned to it.
9215
+ * The engine orders the batch itself (children before the parents that spawn
9216
+ * them). Refs may point inside the batch or at already-deployed definitions;
9217
+ * a ref resolving to neither, or a cycle, errors before any write. Input is
9218
+ * authored content or a fetched definition document the document envelope
9219
+ * (`_*` system fields, `tag`, `version`, `contentHash`) is stripped at the
9220
+ * boundary and never fingerprinted, so a fetched document redeploys as
9221
+ * `unchanged`; any other unknown key fails loud.
9368
9222
  */
9369
9223
  deployDefinitions: <T extends WorkflowDefinitionInput<T>>(
9370
9224
  rawArgs: Telemetered<DeployDefinitionsArgs<T> & EngineScopeArgs>,
9371
9225
  ) => Promise<DeployDefinitionsResult>;
9372
9226
  /**
9373
- * Remove a deployed workflow definition (all versions, or one via
9374
- * `version`). Refuses while non-terminal instances exist unless
9375
- * `cascade` aborts them first — instances are never deleted, only
9376
- * aborted in place; see {@link deleteDefinitionInternal} for the
9377
- * full contract (spawn-referrer check, guard-doc housekeeping).
9227
+ * Remove a deployed definition (all versions, or one via `version`). Refuses
9228
+ * while non-terminal instances exist unless `cascade` aborts them first —
9229
+ * instances are never deleted, only aborted in place; see
9230
+ * {@link deleteDefinitionInternal} for the full contract (spawn-referrer
9231
+ * check, guard-doc housekeeping).
9378
9232
  */
9379
9233
  deleteDefinition: (
9380
9234
  rawArgs: Clocked<Telemetered<DeleteDefinitionArgs & EngineScopeArgs>>,
9381
9235
  ) => Promise<DeleteDefinitionResult>;
9382
9236
  /**
9383
- * Spawn a new workflow instance from a deployed definition.
9384
- *
9385
- * The gates run before anything is written, in order: supplied rows must be
9386
- * structurally consumable, required inputs must be present
9387
- * ({@link RequiredFieldNotProvidedError}), then every declared start
9388
- * requirement is evaluated in author order. All unmet `groq` and
9389
- * `singleSubject` nodes are reported by one {@link StartNotAllowedError}
9390
- * (there is no override argpre-flight with `evaluateStart`).
9391
- * Per-value SHAPE validation fires during field resolution, after the
9392
- * verdict but still before any write. It does NOT evaluate `start.filter`:
9393
- * that is a read-side visibility rule (see `definitionsForDocument`).
9394
- *
9395
- * Pins the snapshot at start-time, seeds the `context` bag, and enters
9396
- * the initial stage — fields resolve and every in-scope activity is
9397
- * born active. Then cascades until stable, so the initial stage's
9398
- * `when: 'true'` triggers have fired by the time this returns.
9237
+ * Spawn a new instance from a deployed definition: pins the snapshot, seeds
9238
+ * the `context` bag, enters the initial stage with every in-scope activity
9239
+ * born active, then cascades until stable. The gates run before anything is
9240
+ * written — supplied rows must be structurally consumable, required inputs
9241
+ * must be present, then every declared start requirement is evaluated in
9242
+ * author order and all unmet nodes are reported by one
9243
+ * {@link StartNotAllowedError} (no override arg; pre-flight with
9244
+ * `evaluateStart`). `start.filter` is NOT evaluated herethat is a
9245
+ * read-side visibility rule, see `definitionsForDocument`.
9399
9246
  *
9400
9247
  * Start is three commits — create, prime, first cascade — and a supplied
9401
- * `instanceId` is its idempotency key across them. When that id already
9402
- * exists under this tag for the same start, the call RESUMES: input gates
9403
- * and field resolution are skipped (those values were pinned at create)
9404
- * and the outstanding commits run — the retry path for a start that
9405
- * failed after its create landed (see `isUnprimed`). Reusing an id for a
9406
- * DIFFERENT start (definition or explicit version mismatch) or for an
9407
- * unfinished start that was aborted (a discarded start) — throws
9408
- * {@link ContractViolationError}. The mid-sequence failures are typed and
9409
- * carry the retry id: a prime failure after the create committed throws
9410
- * `StartNotPrimedError` (failed but resumable), and a cascade failure
9411
- * after a successful prime throws `StartNotSettledError` — the run exists
9412
- * by then and must not be reported as a failed start. `changed` is `true`
9413
- * on a fresh start and rev-derived on a resume; `cascaded` reports how far
9414
- * the instance auto-advanced.
9248
+ * `instanceId` is the idempotency key across them: reusing it for the SAME
9249
+ * start RESUMES (input gates and field resolution are skipped, those values
9250
+ * were pinned at create), while reusing it for a DIFFERENT start, or for an
9251
+ * unfinished start that was aborted, throws
9252
+ * {@link ContractViolationError}. `changed` is `true` on a fresh start and
9253
+ * rev-derived on a resume; `cascaded` reports how far the instance
9254
+ * auto-advanced.
9415
9255
  */
9416
9256
  startInstance: (
9417
9257
  rawArgs: Clocked<Telemetered<StartInstanceArgs & EngineScopeArgs>>,
9418
9258
  ) => Promise<OperationResult>;
9419
9259
  /**
9420
- * Fire an action against an active activity. Cascades and propagates to
9421
- * ancestors after the action commits. A cascade-fired (`when`) action is
9422
- * rejected the cascade is its only firing path.
9423
- *
9424
- * This is the universal "something happened" call. Editors fire it.
9425
- * Runtimes fire it in response to webhooks, effect completions, and
9426
- * timer firings. External signals never bypass this.
9260
+ * Fire an action against an active activity, then cascade and propagate to
9261
+ * ancestors once it commits. The universal "something happened" call —
9262
+ * editors fire it, and runtimes fire it in response to webhooks, effect
9263
+ * completions, and timer firings; external signals never bypass it. A
9264
+ * cascade-fired (`when`) action is rejected: the cascade is its only firing
9265
+ * path.
9427
9266
  */
9428
9267
  fireAction: (
9429
9268
  rawArgs: Clocked<Telemetered<FireActionArgs & EngineScopeArgs>>,
9430
9269
  ) => Promise<OperationResult>;
9431
9270
  /**
9432
9271
  * Edit a declared-editable field directly — reassign, reschedule,
9433
- * claim-by-hand, append to a running log — through the generic edit seam,
9272
+ * claim-by-hand, append to a running log — through the generic edit seam
9434
9273
  * instead of a bespoke action per field. Soft-gates on the field's declared
9435
9274
  * editability (the same projection a UI renders), applies the edit as a
9436
- * `field.*` op (so provenance + history are stamped by the op path),
9275
+ * `field.*` op so provenance and history are stamped by the op path,
9437
9276
  * refreshes the stage's guards, then cascades — an edit to a value a
9438
9277
  * transition reads can and should move the instance. Advisory like every
9439
9278
  * engine gate.
9440
9279
  *
9441
9280
  * Each call is a discrete COMMIT (a history entry, a guard refresh, a
9442
9281
  * cascade, an `ifRevisionId` write), not a draft patch — so an inline-field
9443
- * UI must bind it to a deliberate boundary (blur / Enter / Save / debounce),
9282
+ * UI must bind it to a deliberate boundary (blur, Enter, Save, debounce),
9444
9283
  * never an `onChange` per keystroke.
9445
9284
  */
9446
9285
  editField: (
@@ -9448,94 +9287,87 @@ export declare const workflow: {
9448
9287
  ) => Promise<OperationResult>;
9449
9288
  /**
9450
9289
  * Report a queued effect's outcome. Drains it from `pendingEffects` and
9451
- * appends an `effectHistory` entry whose `outputs` (when supplied on a
9452
- * successful run) are what downstream effect bindings and conditions
9453
- * read as `$effects['<name>'].<output>` the start-only `context` bag
9454
- * is never touched. Any `ops` the handler returned (`field.*`) are
9455
- * validated and applied to the instance in the same commit, through the
9456
- * same op applier an action's field ops use. Cascades after. A completion
9457
- * that applies always changes state (the effect drains + history is
9458
- * appended), so `changed` is `true` — a bad `effectKey`/status throws
9459
- * instead, and a keyed retry of an already-applied completion replays as
9460
- * `changed: false`.
9290
+ * appends an `effectHistory` entry whose `outputs` are what downstream
9291
+ * bindings and conditions read as `$effects['<name>'].<output>` the
9292
+ * start-only `context` bag is never touched. Any `ops` the handler returned
9293
+ * (`field.*`) are validated and applied in the same commit, through the op
9294
+ * applier an action's field ops use. Cascades after. A completion that
9295
+ * applies always changes state, so `changed` is `true`; a bad
9296
+ * `effectKey`/status throws instead, and a keyed retry of an
9297
+ * already-applied completion replays as `changed: false`.
9461
9298
  *
9462
9299
  * Completion is first-writer-wins — see {@link CompleteEffectArgs}. A
9463
- * completer reporting over a retrying transport (webhook redelivery,
9464
- * queue, cron) should pass `idempotencyKey`.
9300
+ * completer reporting over a retrying transport (webhook redelivery, queue,
9301
+ * cron) should pass `idempotencyKey`.
9465
9302
  */
9466
9303
  completeEffect: (
9467
9304
  rawArgs: Clocked<Telemetered<CompleteEffectArgs & EngineScopeArgs>>,
9468
9305
  ) => Promise<OperationResult>;
9469
9306
  /**
9470
- * Commit mid-dispatch field state from a running effect handler — the
9471
- * engine verb behind `ctx.commitOps`. Gates on the dispatch's exact claim
9472
- * (token match + unexpired lease; a stale report throws
9473
- * `StaleEffectClaimError` and writes nothing), validates and applies the
9474
- * `field.*` ops through the shared op applier, records history and the
9475
- * mandatory idempotency key, renews the claim's lease in the same
9476
- * compare-and-swap commit, refreshes the stage's guards, then cascades —
9477
- * a report that satisfies a transition moves the instance, by design.
9307
+ * Commit mid-dispatch field state from a running effect handler — the engine
9308
+ * verb behind `ctx.commitOps`. Gates on the dispatch's exact claim (token
9309
+ * match plus unexpired lease; a stale report throws `StaleEffectClaimError`
9310
+ * and writes nothing), validates and applies the `field.*` ops through the
9311
+ * shared op applier, records history and the mandatory idempotency key,
9312
+ * renews the claim's lease in the same compare-and-swap commit, refreshes
9313
+ * the stage's guards, then cascades — a report that satisfies a transition
9314
+ * moves the instance, by design.
9478
9315
  *
9479
- * Completion (`completeEffect`) remains the authoritative final result
9480
- * and stays claim-blind; this verb only protects the mid-dispatch write
9481
- * channel from superseded handlers.
9316
+ * `completeEffect` remains the authoritative final result and stays
9317
+ * claim-blind; this verb only protects the mid-dispatch write channel from
9318
+ * superseded handlers.
9482
9319
  */
9483
9320
  commitEffectOps: (
9484
9321
  rawArgs: Clocked<Telemetered<CommitEffectOpsArgs & EngineScopeArgs>>,
9485
9322
  ) => Promise<OperationResult>;
9486
9323
  /**
9487
9324
  * Run the cascade until stable — triggered actions fire, transitions move.
9488
- *
9489
- * Used by the runtime after any event that might affect the workflow
9490
- * but isn't itself an action fire: a subject doc was patched, a sibling
9491
- * workflow completed, the clock crossed a deadline a `when` reads, etc.
9492
- * The runtime doesn't need to know what changed — it just nudges
9493
- * affected instances and the engine re-evaluates. `changed` reports
9494
- * whether the nudge wrote anything: a fired transition, but also a
9495
- * hop that fired triggered actions without unlocking a transition yet —
9496
- * so it's derived from the instance's `_rev`, not from `cascaded` alone.
9325
+ * For a runtime reacting to any event that might affect the workflow but
9326
+ * isn't itself an action fire: a subject doc was patched, a sibling workflow
9327
+ * completed, the clock crossed a deadline a `when` reads. The caller doesn't
9328
+ * need to know what changed it nudges the affected instance and the engine
9329
+ * re-evaluates. `changed` reports whether the nudge wrote anything, derived
9330
+ * from the instance's `_rev` rather than `cascaded` alone, since a hop can
9331
+ * fire triggered actions without unlocking a transition.
9497
9332
  */
9498
9333
  tick: (
9499
9334
  rawArgs: Clocked<Telemetered<OperationArgs & EngineScopeArgs>>,
9500
9335
  ) => Promise<OperationResult>;
9501
9336
  /**
9502
- * Admin override — force the instance into `targetStage` regardless
9503
- * of filters or declared transitions. ACL gating should be enforced
9504
- * upstream; this verb performs the mechanical move. `changed: false`
9505
- * means the move was a no-op (already at the target / terminal).
9337
+ * Admin override — force the instance into `targetStage` regardless of
9338
+ * filters or declared transitions. ACL gating is enforced upstream by the
9339
+ * caller; this verb performs no permission pre-flight, only the mechanical
9340
+ * move. `changed: false` means the move was a no-op (already at the target,
9341
+ * or terminal).
9506
9342
  */
9507
9343
  setStage: (
9508
9344
  rawArgs: Clocked<Telemetered<SetStageArgs & EngineScopeArgs>>,
9509
9345
  ) => Promise<OperationResult>;
9510
9346
  /**
9511
- * Admin override — hard-stop an in-flight instance where it stands.
9512
- * No stage move, no transition effects, pending effects cancelled;
9513
- * see {@link abortAndPropagate} for the abort + ancestor-propagation
9514
- * contract (propagated, not cascaded — the instance is terminal, so
9515
- * `cascaded` is always `0`; ancestor movement is reported on the
9516
- * ancestors, not here). `changed: false` means the instance was
9517
- * already terminal.
9347
+ * Admin override — hard-stop an in-flight instance where it stands. No stage
9348
+ * move, no transition effects, pending effects cancelled; see
9349
+ * {@link abortAndPropagate} for the abort + ancestor-propagation contract.
9350
+ * Propagated, not cascaded — the instance is terminal, so `cascaded` is
9351
+ * always `0` and ancestor movement is reported on the ancestors, not here.
9352
+ * `changed: false` means the instance was already terminal.
9518
9353
  */
9519
9354
  abortInstance: (
9520
9355
  rawArgs: Clocked<Telemetered<AbortInstanceArgs & EngineScopeArgs>>,
9521
9356
  ) => Promise<OperationResult>;
9522
9357
  /**
9523
9358
  * Admin override — reset a failed (or otherwise terminal) activity in the
9524
- * instance's current stage: `to: 'active'` re-runs it, `to: 'skipped'`
9525
- * (the bypass) resolves it so a `$allActivitiesDone`-gated exit can fire.
9526
- * Defaults to `active`. Cascades after the reset, so an unblocked
9527
- * transition fires in the same call. ACL gating should be enforced
9528
- * upstream. `changed: false` means the reset was a no-op (instance
9529
- * terminal, or the activity already at the target status).
9359
+ * instance's current stage. `to: 'active'` (the default) re-runs it;
9360
+ * `to: 'skipped'` is the bypass that resolves it so a `$allActivitiesDone`-gated
9361
+ * exit can fire. Cascades after the reset, so an unblocked transition fires
9362
+ * in the same call. ACL gating is enforced upstream by the caller; this verb
9363
+ * performs no permission pre-flight. `changed: false` means the reset was a
9364
+ * no-op (instance terminal, or the activity already at the target status).
9530
9365
  */
9531
9366
  resetActivity: (
9532
9367
  rawArgs: Clocked<Telemetered<ResetActivityArgs & EngineScopeArgs>>,
9533
9368
  ) => Promise<OperationResult>;
9534
- /**
9535
- * Fetch a workflow instance by id, scoped to the engine's tag.
9536
- * Throws when the instance doesn't exist or isn't visible to this
9537
- * engine.
9538
- */
9369
+ /** Fetch a workflow instance by id, scoped to the engine's tag. Throws when
9370
+ * the instance doesn't exist or isn't visible to this engine. */
9539
9371
  getInstance: (
9540
9372
  rawArgs: InstanceRefArgs & EngineScopeArgs,
9541
9373
  ) => Promise<WorkflowInstance>;
@@ -9546,65 +9378,52 @@ export declare const workflow: {
9546
9378
  rawArgs: GuardsForDefinitionArgs & EngineScopeArgs,
9547
9379
  ) => Promise<MutationGuardDoc[]>;
9548
9380
  /**
9549
- * Run a caller-supplied GROQ query with the engine's tag bound as
9550
- * `$tag`. This does NOT rewrite the query — arbitrary GROQ
9551
- * can't be safely tag-scoped after the fact — so the CALLER MUST
9552
- * filter on `$tag` (e.g. `tag == $tag`). To guard against accidental
9553
- * cross-partition reads, a query that never references `$tag` is
9554
- * rejected before it reaches the lake. Caller is responsible for type
9555
- * narrowing the result.
9381
+ * Run a caller-supplied GROQ query with the engine's tag bound as `$tag`.
9382
+ * This does NOT rewrite the query — arbitrary GROQ can't be safely
9383
+ * tag-scoped after the fact — so the CALLER MUST filter on `$tag` (e.g.
9384
+ * `tag == $tag`). To guard against accidental cross-partition reads, a query
9385
+ * that never references `$tag` is rejected before it reaches the lake. The
9386
+ * caller is responsible for type-narrowing the result.
9556
9387
  */
9557
9388
  query: <T = unknown>(rawArgs: QueryArgs & EngineScopeArgs) => Promise<T>;
9558
9389
  /**
9559
- * Snapshot-aware GROQ — runs against the same in-memory view that
9560
- * filters see for a given instance.
9561
- *
9562
- * Hydrates the instance's snapshot (instance + ancestors + every doc
9563
- * declared by a `doc.ref` / `subject` / `doc.refs` entry in scope), then
9564
- * evaluates the supplied GROQ in groq-js against that dataset. The
9565
- * caller-free rendered scope cascade gates evaluate in is auto-bound
9566
- * the instance-derived vars ({@link FILTER_SCOPE_VARS}) with the open
9567
- * stage's overlay merged into `$fields`, `$assigned` at its caller-free
9568
- * `false`, plus the author's pre-evaluated `$<predicate>` booleans —
9569
- * ids in GDR URI form to match the snapshot's keying.
9570
- *
9571
- * Use when an external consumer (a UI, a debug pane, a test) wants
9572
- * to ask "what does the engine see for this workflow right now?"
9573
- * without re-implementing hydration. Pure read — never writes.
9390
+ * Snapshot-aware GROQ — runs against the same in-memory view that filters
9391
+ * see for a given instance. Hydrates the instance's snapshot (instance +
9392
+ * ancestors + every doc declared by a `doc.ref` / `subject` / `doc.refs`
9393
+ * entry in scope), then evaluates the supplied GROQ in groq-js against that
9394
+ * dataset. The caller-free rendered scope cascade gates evaluate in is
9395
+ * auto-bound the instance-derived vars with the open stage's overlay
9396
+ * merged into `$fields`, `$assigned` at its caller-free `false`, plus the
9397
+ * author's pre-evaluated `$<predicate>` booleans with ids in GDR URI form
9398
+ * to match the snapshot's keying. Pure read; never writes.
9574
9399
  */
9575
9400
  queryInScope: <T = unknown>(
9576
9401
  rawArgs: Clocked<QueryInScopeArgs & EngineScopeArgs>,
9577
9402
  ) => Promise<T>;
9578
- /**
9579
- * List every pending effect on the instance. Returns the same entries
9580
- * the runtime would see — claimed and unclaimed alike.
9581
- */
9403
+ /** Every pending effect on the instance — the same entries the runtime would
9404
+ * see, claimed and unclaimed alike. */
9582
9405
  listPendingEffects: (
9583
9406
  rawArgs: InstanceRefArgs & EngineScopeArgs,
9584
9407
  ) => Promise<PendingEffect[]>;
9585
- /**
9586
- * Filter pending effects on the instance by criteria. `claimed`
9587
- * filters on claim presence; `names` restricts to specific effect
9588
- * names. Both filters compose (AND).
9589
- */
9408
+ /** Filter the instance's pending effects: `claimed` on claim presence,
9409
+ * `names` on specific effect names. Both filters compose (AND). */
9590
9410
  findPendingEffects: (
9591
9411
  rawArgs: FindPendingEffectsArgs & EngineScopeArgs,
9592
9412
  ) => Promise<PendingEffect[]>;
9593
9413
  /**
9594
- * Project the instance from a given actor's perspective. Returns a
9595
- * `WorkflowEvaluation` with per-action verdicts (`allowed` + a
9596
- * structured `disabledReason`). Pure read; never writes.
9597
- *
9598
- * Used by UIs to render disabled-with-reason buttons and by
9599
- * `fireAction` to gate writes via the same logic.
9414
+ * Project the instance from a given actor's perspective a
9415
+ * {@link WorkflowEvaluation} with per-action verdicts (`allowed` plus a
9416
+ * structured `disabledReason`). Used by UIs to render
9417
+ * disabled-with-reason buttons and by `fireAction` to gate writes through
9418
+ * the same logic. Pure read; never writes.
9600
9419
  */
9601
9420
  evaluate: (
9602
9421
  rawArgs: Clocked<EvaluateArgs & EngineScopeArgs>,
9603
9422
  ) => Promise<WorkflowEvaluation>;
9604
9423
  /**
9605
- * Diagnose why an instance is or isn't progressing. Projects the
9606
- * instance (the same read as `evaluate`) and classifies it — terminal,
9607
- * `progressing`, `waiting` (an action is available healthy), or `stuck`
9424
+ * Diagnose why an instance is or isn't progressing. Projects the instance
9425
+ * (the same read as `evaluate`) and classifies it — terminal,
9426
+ * `progressing`, `waiting` (an action is available, so healthy), or `stuck`
9608
9427
  * with a structured cause — returning that verdict as a
9609
9428
  * {@link DiagnoseResult} alongside the evaluation it came from, so a
9610
9429
  * consumer can render the supporting evidence without a second projection.
@@ -9613,59 +9432,39 @@ export declare const workflow: {
9613
9432
  diagnose: (
9614
9433
  rawArgs: Clocked<EvaluateArgs & EngineScopeArgs>,
9615
9434
  ) => Promise<DiagnoseResult>;
9616
- /**
9617
- * List the actions an actor could fire on an instance's current stage,
9618
- * each flagged `allowed` (with a structured `disabledReason` when not).
9619
- * Projects the instance from the actor's perspective and flattens its
9620
- * activities' actions. Returns the evaluation alongside the actions so a
9621
- * consumer can read the instance/stage context. Pure read.
9622
- */
9435
+ /** The actions an actor could fire on the instance's current stage, each
9436
+ * flagged `allowed` with a structured `disabledReason` when not, returned
9437
+ * with the evaluation they were projected from. Pure read. */
9623
9438
  availableActions: (
9624
9439
  rawArgs: Clocked<EvaluateArgs & EngineScopeArgs>,
9625
9440
  ) => Promise<AvailableActionsResult>;
9626
9441
  /**
9627
- * Materialised spawned children of a parent instance.
9628
- *
9629
- * Walks `history` for `spawned` eventsthe durable
9630
- * record predating the workflow-scope subworkflow registry, and still the
9631
- * one place adoption/orphan events sit alongside spawns. Strips
9632
- * the GDR URI on each `instanceRef` to a bare `_id`, fetches the
9633
- * instances, drops any that aren't visible to this engine's tag, and
9634
- * returns them sorted by `startedAt` ascending.
9635
- *
9636
- * Pass `activity` to restrict to a single spawning activity on the parent.
9442
+ * Materialised spawned children of a parent instance. Walks `history` for
9443
+ * `spawned` events — the durable record, and still the one place adoption
9444
+ * and orphan events sit alongside spawns strips each `instanceRef`'s GDR
9445
+ * URI to a bare `_id`, fetches the instances, drops any not visible to this
9446
+ * engine's tag, and returns them sorted by `startedAt` ascending. Pass
9447
+ * `activity` to restrict to a single spawning activity on the parent.
9637
9448
  */
9638
9449
  children: (
9639
9450
  rawArgs: ChildrenArgs & EngineScopeArgs,
9640
9451
  ) => Promise<WorkflowInstance[]>;
9641
9452
  /**
9642
9453
  * Every in-flight instance whose reactive watch-set includes `document` —
9643
- * the reverse of {@link subscriptionDocumentsForInstance}.
9644
- *
9645
- * For a non-reactive, content-change-driven runtime (a Sanity Function, an
9646
- * Inngest/durable worker, any server) that holds no instances in memory: a
9647
- * document changed; which instances should it `tick`? The watch-set covers
9648
- * the instance itself, its ancestors, live spawned children, and the docs named by
9649
- * `doc.ref` / `subject` / `doc.refs` / `release.ref` field entries on the
9650
- * workflow scope
9651
- * **and the current stage** — so a hand-rolled GROQ over `fields[]` gets it
9652
- * subtly wrong (misses stage-scope refs, `release.ref`, ancestors, and children).
9653
- *
9654
- * The GROQ filter narrows candidates server-side (in-flight, tag-scoped,
9655
- * matching workflow/open-stage refs); {@link instanceWatchesDocument},
9656
- * derived from `collectWatchRefs`, rechecks the result so the reverse stays
9454
+ * the reverse of an instance's subscription document set. For a
9455
+ * content-change-driven runtime holding no instances in memory: a document
9456
+ * changed, which instances should it `tick`? The watch-set covers the
9457
+ * instance itself, its ancestors, live spawned children, and the docs named
9458
+ * by `doc.ref` / `subject` / `doc.refs` / `release.ref` entries on the
9459
+ * workflow scope AND the current stage, so a hand-rolled GROQ over `fields[]`
9460
+ * gets it subtly wrong. The GROQ filter narrows candidates server-side and
9461
+ * {@link instanceWatchesDocument} rechecks each result, keeping the reverse
9657
9462
  * in lockstep with the forward set.
9658
9463
  *
9659
- * Single-resource: instances always live in the engine's own resource, so
9660
- * this reads one client (unlike {@link guardsForInstance}, whose guard docs
9661
- * are scattered across the watched resources). "Routed by resource" applies
9662
- * to the **subject**: a cross-dataset doc is matched by its full,
9663
- * resource-qualified GDR URI, never its bare id, so an instance watching
9664
- * `dataset:A:ds:doc` is not matched by a change to `dataset:B:ds:doc`.
9665
- *
9666
- * `document` must be a resource-qualified GDR URI; a bare id is rejected
9667
- * (it can't be resource-routed and would silently mismatch). Sorted by
9668
- * `startedAt` ascending.
9464
+ * `document` must be a resource-qualified GDR URI; a bare id is rejected,
9465
+ * since it can't be resource-routed and would silently mismatch — an
9466
+ * instance watching `dataset:A:ds:doc` is never matched by a change to
9467
+ * `dataset:B:ds:doc`. Sorted by `startedAt` ascending.
9669
9468
  */
9670
9469
  instancesForDocument: (
9671
9470
  rawArgs: InstancesForDocumentArgs & EngineScopeArgs,
@@ -9674,51 +9473,46 @@ export declare const workflow: {
9674
9473
  * The startable half of {@link workflow.instancesForDocument}: every
9675
9474
  * deployed definition that APPLIES to `document` — what a start picker for
9676
9475
  * it should offer. Loads the latest deployed version of each definition
9677
- * visible to the engine's tag and filters it through the derivation
9678
- * ({@link applicableDefinitions}): startable ∧ the `subject`-kind entry
9679
- * accepts the doc's `_type` ∧ `start.filter` passes evaluated in the
9680
- * browse-time-pure start-filter context with `$tag`/`$definition`/`$now`
9681
- * bound and the tag's projected start slice (completed included) backing dataset
9682
- * reads. Start requirements never participate — readiness is a start-time
9683
- * question; pre-flight it with {@link workflow.evaluateStart}.
9476
+ * visible to the engine's tag and filters it through
9477
+ * {@link applicableDefinitions}: startable ∧ the `subject`-kind entry
9478
+ * accepts the doc's `_type` ∧ `start.filter` passes, evaluated in the
9479
+ * browse-time-pure start-filter context. Start requirements never
9480
+ * participate readiness is a start-time question; pre-flight it with
9481
+ * {@link workflow.evaluateStart}.
9684
9482
  *
9685
9483
  * Takes the LOADED candidate document, not a ref — applicability evaluates
9686
9484
  * its content under whatever perspective the caller read it with. Surfaces
9687
- * ALL matches (name ascending), no engine
9688
- * ranking — presenting a picker or auto-picking is consumer policy.
9689
- * Advisory like every engine-side check.
9485
+ * ALL matches (name ascending) with no engine ranking: presenting a picker
9486
+ * or auto-picking is consumer policy. Advisory like every engine-side check.
9690
9487
  */
9691
9488
  definitionsForDocument: (
9692
9489
  rawArgs: Clocked<DefinitionsForDocumentArgs & EngineScopeArgs>,
9693
9490
  ) => Promise<DeployedDefinition[]>;
9694
9491
  /**
9695
- * Pre-flight the start gates for a definition + candidate `initialFields` —
9696
- * the read `startInstance` enforces, as a {@link StartEvaluation} a surface
9697
- * can render: `missingRequired` mirrors the input contract
9698
- * ({@link RequiredFieldNotProvidedError}'s rows), while `requirements`
9699
- * preserves every declared node's authored descriptor, outcome, and GROQ
9700
- * insight when applicable. `allowed` / `outcome` aggregate those ordered
9701
- * results. BINDABILITY-AWARE for partial mid-form inputs: when a predicate
9702
- * reads an entry `initialFields` doesn't supply including a
9703
- * `singleSubject` node's implicit subject read `outcome` is
9704
- * `'unevaluable'` and `unboundReads` names the entries ("fill these to
9705
- * decide") instead of the collapsed answer GROQ equality would give —
9706
- * this is the ONE deliberate divergence from the gate, where absence is
9707
- * final, not provisional (a rule like `!defined($fields.rush)` genuinely
9708
- * passes there when `rush` is absent). A definition declaring no start
9709
- * requirements is vacuously allowed, exactly like
9710
- * the verb. Pure read; advisory under races — the enforcement moment is
9492
+ * Pre-flight the start gates for a definition plus candidate
9493
+ * `initialFields` — the read `startInstance` enforces, as a
9494
+ * {@link StartEvaluation} a surface can render: `missingRequired` mirrors
9495
+ * the input contract, while `requirements` preserves every declared node's
9496
+ * authored descriptor, outcome, and GROQ insight where applicable;
9497
+ * `allowed` / `outcome` aggregate those ordered results.
9498
+ *
9499
+ * BINDABILITY-AWARE for partial mid-form inputs: when a predicate reads an
9500
+ * entry `initialFields` doesn't supply including a `singleSubject` node's
9501
+ * implicit subject read — `outcome` is `'unevaluable'` and `unboundReads`
9502
+ * names the entries ("fill these to decide") instead of the collapsed answer
9503
+ * GROQ equality would give. That is the ONE deliberate divergence from the
9504
+ * gate, where absence is final rather than provisional. A definition
9505
+ * declaring no start requirements is vacuously allowed, exactly like the
9506
+ * verb. Pure read; advisory under races — the enforcement moment is
9711
9507
  * `startInstance` itself.
9712
9508
  */
9713
9509
  evaluateStart: (
9714
9510
  rawArgs: Clocked<EvaluateStartArgs & EngineScopeArgs>,
9715
9511
  ) => Promise<StartEvaluation>;
9716
- /**
9717
- * Permission helpers Sanity ACL grants evaluated against documents
9718
- * via GROQ. Used by `workflow.evaluate` to soft-gate actions when the
9719
- * caller supplies grants. Deliberately namespace-only (not mirrored on
9720
- * `Engine`): pure helpers that need none of the engine's pinned scope.
9721
- */
9512
+ /** Permission helpers — Sanity ACL grants evaluated against documents via
9513
+ * GROQ, used by `workflow.evaluate` to soft-gate actions when the caller
9514
+ * supplies grants. Deliberately namespace-only, not mirrored on `Engine`:
9515
+ * pure helpers that need none of the engine's pinned scope. */
9722
9516
  permissions: {
9723
9517
  matchesFilter: typeof matchesFilter;
9724
9518
  grantsPermissionOn: typeof grantsPermissionOn;
@@ -9737,7 +9531,7 @@ export declare const WORKFLOW_DEFINITION_TYPE = "sanity.workflow.definition";
9737
9531
  * The lake document type for a workflow instance. Single source of truth — the
9738
9532
  * {@link WorkflowInstance} `_type`, every tag-scoped query, and the create
9739
9533
  * write all derive from here, mirroring {@link WORKFLOW_DEFINITION_TYPE}.
9740
- * Engine-owned standalone documents carry the platform namespace.
9534
+ * Engine-owned standalone documents use the platform namespace.
9741
9535
  */
9742
9536
  export declare const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
9743
9537
 
@@ -9907,10 +9701,10 @@ export declare interface WorkflowClient {
9907
9701
  */
9908
9702
  withConfig?: (config: WorkflowClientConfig) => this;
9909
9703
  /**
9910
- * Optional — present on the real `@sanity/client`, absent on the
9911
- * in-memory test client. The engine probes for it when auto-resolving
9912
- * ACL grants from an endpoint; absence is the package's signal for
9913
- * "dry-run mode, don't try to fetch real grants."
9704
+ * Optional — present on the real `@sanity/client`. Without it, ACL grant
9705
+ * discovery uses its dry-run fallback, while a definition containing
9706
+ * role-constrained assignment fields fails loudly because the engine cannot
9707
+ * read the project membership directory required to validate assignees.
9914
9708
  */
9915
9709
  request?: <T>(opts: {
9916
9710
  /** Raw URL (host + path). One of `url` / `uri` required. */
@@ -9973,6 +9767,16 @@ export declare interface WorkflowCommitOptions {
9973
9767
  tag?: string;
9974
9768
  }
9975
9769
 
9770
+ /**
9771
+ * `deployments` names must be unique (the selector deployment-targeted
9772
+ * commands resolve by), and each `(workflowResource, tag)` pair must be
9773
+ * unique — that pair is the storage partition, so two deployments sharing
9774
+ * both would fight over definition versions. `telemetry`, when set, replaces
9775
+ * the CLI's built-in Sanity-intake shell entirely: every event flows to this
9776
+ * logger unconditionally (CI and `DO_NOT_TRACK` included), and consent,
9777
+ * environment suppression, and transport become this implementation's
9778
+ * business.
9779
+ */
9976
9780
  export declare type WorkflowConfig = v.InferOutput<typeof WorkflowConfigSchema>;
9977
9781
 
9978
9782
  /**
@@ -10599,14 +10403,6 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
10599
10403
  >,
10600
10404
  ]
10601
10405
  >;
10602
- /**
10603
- * Custom telemetry destination for the CLI. When set, the CLI's built-in
10604
- * Sanity-intake shell is not constructed and none of its policy applies:
10605
- * every event — the command trace and the engine vocabulary — flows to
10606
- * this logger unconditionally (CI and `DO_NOT_TRACK` environments
10607
- * included). Consent, environment suppression, transport, and destination
10608
- * are wholly this implementation's business.
10609
- */
10610
10406
  readonly telemetry: v.OptionalSchema<
10611
10407
  v.CustomSchema<
10612
10408
  WorkflowTelemetryLogger,
@@ -10618,6 +10414,21 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
10618
10414
  undefined
10619
10415
  >;
10620
10416
 
10417
+ /**
10418
+ * `name` is a lake-id-segment (`^[a-z0-9][a-z0-9-]*$`) that interpolates into
10419
+ * every deployed document id (`<tag>.<name>.v<version>`) — stable identity
10420
+ * that instances pin to and subworkflows resolve by. `lifecycle: 'child'`
10421
+ * marks a spawn-only definition, instantiated by a parent via an action's
10422
+ * `spawn`, never started cold from a picker (omitted ⇒ `'standalone'`,
10423
+ * startable); advisory only — consumers filter start pickers on it (see
10424
+ * {@link isStartableDefinition}), the engine does not itself refuse a
10425
+ * `startInstance` on a `'child'` definition. `start` is meaningless
10426
+ * (deploy-rejected) on a spawn-only definition; omitted, it means
10427
+ * interactive semantics with no predicates. `predicates` are nullary named
10428
+ * conditions — each `name: groq` entry is pre-evaluated and bound as the
10429
+ * boolean `$name` var; redefining a built-in var is a deploy error, never a
10430
+ * silent shadow.
10431
+ */
10621
10432
  export declare type WorkflowDefinition = v.InferOutput<
10622
10433
  typeof WorkflowDefinitionSchema
10623
10434
  >;
@@ -10690,37 +10501,37 @@ export declare type WorkflowDefinitionInput<T> = string extends keyof T
10690
10501
  * every reference scope resolved. Cross-field invariants (unique names,
10691
10502
  * transition targets, effect-name uniqueness, predicate shadowing) are
10692
10503
  * checked by `checkWorkflowInvariants` after desugar — see `defineWorkflow`.
10504
+ * Carries NO `version`: a definition's version and content fingerprint are
10505
+ * stamped onto the deployed document at deploy time, derived from the
10506
+ * content itself, so redeploying identical content is a no-op and any
10507
+ * change mints the next version.
10693
10508
  *
10694
- * Carries NO `version` the author never writes one. A definition's version
10695
- * (and its content fingerprint) are stamped onto the deployed *document* at
10696
- * deploy time, derived from the content itself; see `DeployedDefinition` and
10697
- * `planDefinitionDeploy` in `api/deploy.ts`. The author's content is the sole
10698
- * source of identity: redeploying identical content is a no-op, any change
10699
- * mints the next version.
10509
+ * Exported (module-level, not package API) for the model-surface gate's
10510
+ * coverage test and for `parseStoredDefinition` the boundary parse for a
10511
+ * definition that did not come out of `defineWorkflow` in-process; trusted
10512
+ * in-process desugar output is never re-parsed.
10700
10513
  */
10701
10514
  declare const WorkflowDefinitionSchema: v.GenericSchema<
10702
10515
  WorkflowFields<FieldEntry, Stage, StartBlock>
10703
10516
  >;
10704
10517
 
10705
10518
  /** One deployment as loaded from a config: the floor is optional/unverified so
10706
- * a command that never selects a deployment can hold a stale or missing
10707
- * acknowledgement. Deployment-scoped paths assert before they act; authors
10708
- * write {@link WorkflowDeploymentInput}. */
10519
+ * commands that do not submit definitions can hold a missing acknowledgement.
10520
+ * Definition-submission paths compare it with their selected definitions; authors write
10521
+ * {@link WorkflowDeploymentInput}. */
10709
10522
  export declare type WorkflowDeployment = WorkflowConfig["deployments"][number];
10710
10523
 
10711
10524
  /**
10712
- * What an author writes for one deployment: the current reader floor as the
10713
- * reviewed literal. Compile-time only omitting it or setting a wrong value
10714
- * is a type error in the editor. Runtime parse still tolerates a stale or
10715
- * missing floor on {@link WorkflowDeployment} so commands that never select a
10716
- * deployment still run; deployment-scoped paths assert the selected
10717
- * deployment (instance-id commands do not).
10525
+ * What an author writes for one deployment: the highest reader model verified
10526
+ * across runtimes sharing its workflow resource. Runtime validation compares
10527
+ * it with the submitted definitions, so a dependency upgrade alone does not
10528
+ * require changing the literal.
10718
10529
  */
10719
10530
  export declare type WorkflowDeploymentInput = Omit<
10720
10531
  WorkflowDeployment,
10721
10532
  "expectedMinReaderModel"
10722
10533
  > & {
10723
- expectedMinReaderModel: typeof DATA_MODEL_MIN_READER;
10534
+ expectedMinReaderModel: number;
10724
10535
  };
10725
10536
 
10726
10537
  export declare const WorkflowEffectCompleted: WorkflowTelemetryEvent<WorkflowEffectCompletedData>;
@@ -10874,12 +10685,6 @@ export declare interface WorkflowFieldEditedData extends InstanceScopedEventData
10874
10685
 
10875
10686
  /** Type-mirror of {@link workflowFields}, parameterised over field/stage/start. */
10876
10687
  declare type WorkflowFields<TField, TStage, TStart> = {
10877
- /**
10878
- * Lake-id-segment grammar (`^[a-z0-9][a-z0-9-]*$`, deploy-enforced): the
10879
- * name interpolates into every deployed document id
10880
- * (`<tag>.<name>.v<version>`). Stable identity — instances pin to it,
10881
- * subworkflows resolve by it.
10882
- */
10883
10688
  name: string;
10884
10689
  semantics?: Semantic[] | undefined;
10885
10690
  title: string;
@@ -10906,8 +10711,8 @@ export declare interface WorkflowInstance extends SanityDocument {
10906
10711
  modelVersion?: number;
10907
10712
  /**
10908
10713
  * Reader floor — the oldest engine data model that can safely interpret
10909
- * this document. No lower than the writer's unconditional
10910
- * {@link DATA_MODEL_MIN_READER}, and written alongside
10714
+ * this document. Derived from its persisted features and the retained
10715
+ * model-4 baseline, and written alongside
10911
10716
  * {@link WorkflowInstance.modelVersion}. Full persists never lower it.
10912
10717
  */
10913
10718
  minReaderModel?: number;
@@ -10933,7 +10738,7 @@ export declare interface WorkflowInstance extends SanityDocument {
10933
10738
  * can detect a deployed definition that drifted from what this instance
10934
10739
  * started on. Advisory — the engine enforces nothing; this enables detection,
10935
10740
  * not prevention. Absent when the instance was started against a definition
10936
- * deployed before content-addressing (it carried no hash to pin).
10741
+ * deployed before content-addressing (it had no hash to pin).
10937
10742
  */
10938
10743
  pinnedContentHash?: string;
10939
10744
  /** Frozen JSON snapshot of the definition at the moment the instance started. */
@@ -10982,10 +10787,10 @@ export declare interface WorkflowInstance extends SanityDocument {
10982
10787
  */
10983
10788
  stages: StageEntry[];
10984
10789
  /**
10985
- * Workflow-scope registry of every child this instance ever spawned
10790
+ * Workflow-scope registry of every child this instance ever spawned;
10986
10791
  * see {@link SubworkflowEntry}. Rows are never deleted; a row without
10987
- * `resolved` is a LIVE child (watched, hydrated, propagating), one with
10988
- * it is terminal, and a live row with `abortPending` is CONDEMNED — the
10792
+ * `resolved` is a live child (watched, hydrated, propagating), one with
10793
+ * it is terminal, and a live row with `abortPending` is condemned — the
10989
10794
  * cascade owes it an abort. Rendered as the `$subworkflows` condition
10990
10795
  * var. Absent only on instances persisted before the registry existed.
10991
10796
  */
@@ -11015,6 +10820,63 @@ export declare interface WorkflowInstance extends SanityDocument {
11015
10820
 
11016
10821
  export declare const WorkflowInstanceAborted: WorkflowTelemetryEvent<WorkflowAdminOverrideData>;
11017
10822
 
10823
+ /**
10824
+ * The instance list projection — a reduced {@link WorkflowInstance} for
10825
+ * surfaces that render many runs at once, fetched by `instancePreviewsQuery`.
10826
+ *
10827
+ * The reduction keeps the full instance's field names and member shapes so
10828
+ * instance helpers (`terminalState`, `findOpenStageEntry`, `parentRef`, the
10829
+ * identity normalizer) read a preview unchanged; what shrinks is the content:
10830
+ * `stages` holds the open entry alone, every `fields` list keeps only the
10831
+ * identity, date, document-reference, and release-reference kinds, and the unbounded audit
10832
+ * trails are gone — `claimedEffects` and `failedEffects` hold the two facts
10833
+ * a stuck classifier reads in their place. There is deliberately no
10834
+ * `definitionSnapshot`: a consumer titles what it shows from the deployed
10835
+ * catalog, falling back to raw names.
10836
+ */
10837
+ export declare interface WorkflowInstancePreview {
10838
+ _id: string;
10839
+ _type: typeof WORKFLOW_INSTANCE_TYPE;
10840
+ /** See {@link WorkflowInstance.modelVersion}. */
10841
+ modelVersion?: number;
10842
+ /** See {@link WorkflowInstance.minReaderModel}. */
10843
+ minReaderModel?: number;
10844
+ workflowResource: WorkflowResource;
10845
+ definition: string;
10846
+ pinnedVersion: number;
10847
+ /** Identity, date, document-reference, and release-reference entries only
10848
+ * — the kinds list surfaces read. Composite (`object`/`array`) entries are
10849
+ * dropped, so identities nested inside them are invisible to a preview. */
10850
+ fields: ResolvedFieldEntry[];
10851
+ ancestors: GlobalDocumentReference[];
10852
+ perspective?: WorkflowPerspective;
10853
+ currentStage: StageName;
10854
+ /** The open stage entry alone, its activities' fields reduced like
10855
+ * {@link fields}. A completed run keeps its terminal entry open, so this
10856
+ * is empty only for an aborted run (whose entries closed in place) or
10857
+ * before the run primes. */
10858
+ stages: StageEntry[];
10859
+ /** Pending effects a drainer has claimed — the hung-automation fact. */
10860
+ claimedEffects: WorkflowInstancePreviewEffect[];
10861
+ /** Effect-history rows that reported failure — the failed-automation fact. */
10862
+ failedEffects: WorkflowInstancePreviewEffect[];
10863
+ startedAt: string;
10864
+ completedAt?: string;
10865
+ abortedAt?: string;
10866
+ }
10867
+
10868
+ /** A stalled automation as a preview reports it — the effect's machine name
10869
+ * and its display title. */
10870
+ export declare interface WorkflowInstancePreviewEffect {
10871
+ name: string;
10872
+ title?: string;
10873
+ }
10874
+
10875
+ /** The instance list projection (`instancePreviewsQuery` results). The reduced
10876
+ * members reuse the persisted document's own schemas, so a preview can
10877
+ * never admit a shape the full parse would refuse. */
10878
+ export declare const WorkflowInstancePreviewSchema: v.GenericSchema<WorkflowInstancePreview>;
10879
+
11018
10880
  /**
11019
10881
  * The persisted instance document, root to leaf. Reused verbatim by every
11020
10882
  * engine read boundary through {@link parseInstanceDocument}; the