@sanity/workflow-engine 0.29.0 → 0.31.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 —
@@ -7063,27 +6956,40 @@ export declare interface QueryInScopeArgs extends InstanceRefArgs, QueryArgs {}
7063
6956
  export { quoted };
7064
6957
 
7065
6958
  export declare const READER_MODEL_ROLLOUT_URL =
7066
- "https://www.sanity.io/docs/editorial-workflows/prerelease";
6959
+ "https://www.sanity.io/docs/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;
7074
- readonly documentationUrl =
7075
- "https://www.sanity.io/docs/editorial-workflows/prerelease";
7076
- constructor(expectedMinReaderModel: unknown, context?: string);
6967
+ readonly engineMaxReaderModel = 8;
6968
+ readonly engineModelVersion = 8;
6969
+ readonly documentationUrl = "https://www.sanity.io/docs/workflows/prerelease";
6970
+ constructor(
6971
+ expectedMinReaderModel: unknown,
6972
+ options?: {
6973
+ requiredMinReaderModel?: number;
6974
+ context?: string;
6975
+ },
6976
+ );
7077
6977
  }
7078
6978
 
7079
6979
  /**
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
6980
+ * The single definition of the instance read discipline (model gate
6981
+ * {@link assertReadableModel} first, shape parse
6982
+ * {@link parseInstanceDocument} second), shared by the point-read funnel
7083
6983
  * above and the list-read sites that fetch instance rows in bulk.
7084
6984
  */
7085
6985
  export declare function readInstanceDoc(doc: SanityDocument): WorkflowInstance;
7086
6986
 
6987
+ /** {@link readInstanceDoc}'s preview-projection counterpart: the same
6988
+ * gate-then-parse order over an `instancePreviewsQuery` result. */
6989
+ export declare function readInstancePreviewDoc(
6990
+ doc: unknown,
6991
+ ): WorkflowInstancePreview;
6992
+
7087
6993
  /**
7088
6994
  * Whether a watched ref reads RAW — never perspective-scoped. The
7089
6995
  * instance, its ancestors, and its spawned children (all instance docs), and
@@ -7095,16 +7001,10 @@ export declare function readInstanceDoc(doc: SanityDocument): WorkflowInstance;
7095
7001
  */
7096
7002
  export declare function readsRaw(ref: { type: string }): boolean;
7097
7003
 
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
- */
7004
+ /** Whether a GROQ expression reads its ROOT document — the candidate a
7005
+ * `start.filter` binds, not an item inside a rebound scope (filters, `map`). A `^`
7006
+ * that escapes past the outermost scope lands back on the root and counts. A
7007
+ * malformed expression reads nothing here, so it returns `false`. */
7108
7008
  export declare function readsRootDocument(groq: string): boolean;
7109
7009
 
7110
7010
  /** Make a GDR pointer to a Canvas-resource doc. */
@@ -7172,15 +7072,10 @@ export declare class RefResourceUndeclaredError extends WorkflowError<"ref-resou
7172
7072
  export declare function refsOf(def: WorkflowDefinition): LogicalRef[];
7173
7073
 
7174
7074
  /**
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}.
7075
+ * GDR `type`s in a reference-kind ({@link refKindAcceptsTypes}) value that the
7076
+ * entry's declared `types` reject — empty when it conforms, no `types` are
7077
+ * declared, or the kind isn't a ref. Skips non-GDR-shaped values; the shape
7078
+ * schemas already reject those.
7184
7079
  */
7185
7080
  export declare function rejectedRefTypes(args: {
7186
7081
  entryType: string;
@@ -7246,6 +7141,11 @@ export declare type RemediationVerb =
7246
7141
  | "set-stage"
7247
7142
  | "abort";
7248
7143
 
7144
+ /** The reader model a deployment must acknowledge for its submitted definitions. */
7145
+ export declare function requiredDefinitionReaderModel(
7146
+ definitions: readonly unknown[],
7147
+ ): number;
7148
+
7249
7149
  /**
7250
7150
  * Thrown when a workflow is started (or a child spawned) without a value for
7251
7151
  * a field entry marked `required`. Mirrors {@link ActionParamsInvalidError}:
@@ -7301,14 +7201,6 @@ export declare interface RequirementDescriptor {
7301
7201
  */
7302
7202
  export declare const RESERVED_CONDITION_VARS: readonly string[];
7303
7203
 
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
7204
  declare const RESET_ACTIVITY_TARGETS: readonly ["active", "skipped"];
7313
7205
 
7314
7206
  export declare interface ResetActivityArgs extends DedupableOperationArgs {
@@ -7336,6 +7228,14 @@ export declare type ResetActivityResult =
7336
7228
  to: ResetActivityTarget;
7337
7229
  };
7338
7230
 
7231
+ /**
7232
+ * What to reset a stuck activity INTO — the two non-`failed` outcomes that
7233
+ * unstick a stage gated on it. `active` re-runs it (back in progress, so a
7234
+ * caller drives it to completion again); `skipped` bypasses it (terminal but
7235
+ * resolved, so `$allActivitiesDone` can satisfy and a gated exit transition
7236
+ * fire). `done` is deliberately absent: a reset is recovery, not a silent
7237
+ * declaration that the work succeeded.
7238
+ */
7339
7239
  export declare type ResetActivityTarget =
7340
7240
  (typeof RESET_ACTIVITY_TARGETS)[number];
7341
7241
 
@@ -7343,8 +7243,9 @@ export declare type ResetActivityTarget =
7343
7243
  * Resolve the engine's `WorkflowAccess` for a client — actor and grants
7344
7244
  * (when a path is supplied) fetched from its token in parallel and cached.
7345
7245
  * 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}.
7246
+ * without an identity. A grants-fetch failure degrades open instead: the
7247
+ * rendered `$can` stays undefined and the real Sanity write boundary still
7248
+ * enforces. Does not fetch User Attributes; see {@link resolveUserAttributes}.
7348
7249
  */
7349
7250
  export declare function resolveAccess(
7350
7251
  taggedClient: WorkflowClient,
@@ -7386,8 +7287,9 @@ export declare interface ResolveClientActorArgs {
7386
7287
  * `resolvedAt` — the lake-read time — so `resolvedAt` is provenance-driven,
7387
7288
  * not kind-specific. `object` / `array` entries carry their declared
7388
7289
  * 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.
7290
+ * ({@link refKindAcceptsTypes}) their declared accepted `types`, and
7291
+ * assignment kinds their eligible `roles` so the instance is
7292
+ * self-describing for op-time validation and rendering.
7391
7293
  */
7392
7294
  export declare type ResolvedFieldEntry = {
7393
7295
  [K in FieldKind]: {
@@ -7411,6 +7313,11 @@ export declare type ResolvedFieldEntry = {
7411
7313
  of: FieldShape[];
7412
7314
  }
7413
7315
  : Record<never, never>) &
7316
+ (K extends "assignee" | "assignees"
7317
+ ? {
7318
+ roles?: string[];
7319
+ }
7320
+ : Record<never, never>) &
7414
7321
  (K extends "doc.ref" | "doc.refs" | "subject"
7415
7322
  ? {
7416
7323
  types?: string[];
@@ -7418,14 +7325,8 @@ export declare type ResolvedFieldEntry = {
7418
7325
  : Record<never, never>);
7419
7326
  }[FieldKind];
7420
7327
 
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
- */
7328
+ /** Resolves against the OPEN stage for stage/activity scopes; `undefined`
7329
+ * when the field hasn't resolved yet (e.g. an activity field before activation). */
7429
7330
  export declare function resolveFieldEntry(
7430
7331
  instance: WorkflowInstance,
7431
7332
  site: {
@@ -7459,26 +7360,20 @@ export declare type ResourceAliases = Record<string, WorkflowResource>;
7459
7360
  * Collapse a deployment's `resourceAliases` bindings into the
7460
7361
  * {@link ResourceAliases} map (handle name → physical resource) that
7461
7362
  * `deployDefinitions` expands `@<handle>:` references against. Deploy-time
7462
- * only — the map never reaches any other verb.
7363
+ * only — the map never reaches any other verb. A duplicate binding name
7364
+ * silently overwrites here (last wins), which is why `DeploymentSchema`
7365
+ * rejects one at parse time, before this ever runs.
7463
7366
  */
7464
7367
  export declare function resourceAliasesToMap(
7465
7368
  resourceAliases: WorkflowDeployment["resourceAliases"],
7466
7369
  ): ResourceAliases;
7467
7370
 
7468
7371
  /**
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.
7372
+ * Cross-resource read routing override return a client for the parsed
7373
+ * GDR's resource, or `undefined` to let the engine route it. Serving a
7374
+ * resource also declares it on the written-ref surface, so narrowing this
7375
+ * resolver rejects refs to resources it stops serving; engine verb scopes
7376
+ * also rebind any returned client onto their own API version.
7482
7377
  */
7483
7378
  export declare type ResourceClientResolver = (
7484
7379
  parsed: ParsedGdr,
@@ -7527,38 +7422,22 @@ export declare interface ResourceSurface {
7527
7422
  * the stage and must keep its lock) or gone (leave the lock as the orphan
7528
7423
  * seam rather than silently unlocking a vanished instance — the same
7529
7424
  * over-lock direction as deploy).
7425
+ *
7426
+ * Guard revisions are observed before the live-stage gate, then only those
7427
+ * revisions are deleted: a deploy landing in between changes the revision,
7428
+ * so the delete's revision fence fails instead of deleting the active guard.
7530
7429
  */
7531
7430
  export declare function retractStageGuards(args: StageGuardArgs): Promise<void>;
7532
7431
 
7533
- export declare type RoleAliases = v.InferOutput<typeof RoleAliasesSchema>;
7534
-
7535
7432
  /**
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.
7433
+ * Roles that may fulfil each authored role. Aliases widen action gates,
7434
+ * `$assigned`, and assignment-field user eligibility by expanding the required
7435
+ * side; they never alter an actor's roles. Collective role assignees remain
7436
+ * literal ownership values and are not widened by this map. The authored `"*"`
7437
+ * key lists universal fulfillers and is normalized before persistence.
7561
7438
  */
7439
+ export declare type RoleAliases = v.InferOutput<typeof RoleAliasesSchema>;
7440
+
7562
7441
  declare const RoleAliasesSchema: v.RecordSchema<
7563
7442
  v.SchemaWithPipe<
7564
7443
  readonly [
@@ -7726,6 +7605,18 @@ export declare class SpawnContractsInvalidError extends WorkflowError<"spawn-con
7726
7605
  constructor(args: { issues: SpawnContractIssue[]; message: string });
7727
7606
  }
7728
7607
 
7608
+ /**
7609
+ * A pure container — name, fields, guards, activities, transitions, no
7610
+ * behaviour of its own. Activities own enter, transitions own exit and
7611
+ * arrival; a stage with no transitions IS terminal (structural, nothing to
7612
+ * declare or mis-declare). `guards` are lake mutation guards active while
7613
+ * the stage holds, each compiling to a persisted guard document deployed on
7614
+ * stage entry and retracted on exit. `editable` is a tighten-only override
7615
+ * for the time the stage holds, keyed by an in-scope field name: the field's
7616
+ * own `editable` is the ceiling, ANDed with the stage value at runtime, so an
7617
+ * override can only NARROW — never open a field the baseline left closed. An
7618
+ * unlisted field inherits its baseline.
7619
+ */
7729
7620
  export declare type Stage = StageFields<
7730
7621
  FieldEntry,
7731
7622
  Activity,
@@ -7863,6 +7754,19 @@ export declare const START_REQUIREMENT_VARS: readonly {
7863
7754
  description: string;
7864
7755
  }[];
7865
7756
 
7757
+ /**
7758
+ * How standalone runs of this workflow begin. `filter` is a READ-SIDE
7759
+ * visibility predicate — "should a start surface offer this workflow for
7760
+ * this document?" — evaluated by `definitionsForDocument`/applicability in
7761
+ * the browse-time-pure start-filter context (`$tag`/`$definition`/`$now`
7762
+ * bound; `$fields` cannot exist before inputs do, so a `$fields` read here
7763
+ * is deploy-rejected). It is NOT a `startInstance` gate; the verb never
7764
+ * reads it. `requirements` are named readiness checks evaluated in author
7765
+ * order in the start-time context (GROQ nodes add `$fields`; `singleSubject`
7766
+ * is the one-in-flight-run-per-subject rule) — every node must pass before
7767
+ * `startInstance` commits. Both are advisory like every engine-side check;
7768
+ * the Content Lake remains the only enforcement point.
7769
+ */
7866
7770
  export declare type StartBlock = StartFields & {
7867
7771
  kind: StartKind;
7868
7772
  };
@@ -7924,9 +7828,6 @@ export declare interface StartEvaluation {
7924
7828
  invalidInitialFields: InitialFieldIssue[];
7925
7829
  }
7926
7830
 
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
7831
  declare type StartFields = {
7931
7832
  filter?: string | undefined;
7932
7833
  requirements?: StartRequirement[] | undefined;
@@ -8092,16 +7993,12 @@ export declare class StartNotSettledError extends WorkflowError<"start-not-settl
8092
7993
  });
8093
7994
  }
8094
7995
 
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
- */
7996
+ /** 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
7997
  export declare function startRefusal(definition: {
8102
7998
  lifecycle?: WorkflowLifecycle | undefined;
8103
7999
  }): string | undefined;
8104
8000
 
8001
+ /** Every named readiness requirement accepted by workflow `start.requirements`. */
8105
8002
  export declare type StartRequirement =
8106
8003
  | GroqRequirement
8107
8004
  | SingleSubjectRequirement;
@@ -8153,15 +8050,6 @@ export declare interface StartSliceRow {
8153
8050
  completedAt: string | null;
8154
8051
  }
8155
8052
 
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
8053
  declare const StoredEditableSchema: v.UnionSchema<
8166
8054
  [
8167
8055
  v.LiteralSchema<true, undefined>,
@@ -8383,6 +8271,7 @@ declare const StoredFieldOpSchema: v.VariantSchema<
8383
8271
  undefined
8384
8272
  >;
8385
8273
 
8274
+ /** A field reference with `scope` already resolved — the form every op target carries. */
8386
8275
  export declare type StoredFieldRef = v.InferOutput<typeof StoredFieldRefSchema>;
8387
8276
 
8388
8277
  declare const StoredFieldRefSchema: v.StrictObjectSchema<
@@ -8668,6 +8557,12 @@ export declare function stripSystemFields(
8668
8557
  * its activity looking merely "active", so it wins over the activity- and
8669
8558
  * transition-level symptoms it produces. Note an active activity awaiting a human
8670
8559
  * action is NOT here — that's the healthy {@link Diagnosis} `waiting` state.
8560
+ *
8561
+ * `transition-unevaluable` is the recoverable arm: every activity resolved,
8562
+ * but an exit transition's `when` came back GROQ `null` (a referenced operand
8563
+ * is missing or unreadable), so selection halts and the cascade re-fires once
8564
+ * the operand resolves — where `no-transition-fires` means every `when` is a
8565
+ * definite `false`. It carries the undecidable transitions.
8671
8566
  */
8672
8567
  export declare type StuckCause =
8673
8568
  | {
@@ -8685,13 +8580,6 @@ export declare type StuckCause =
8685
8580
  | {
8686
8581
  kind: "no-transition-fires";
8687
8582
  }
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
8583
  | {
8696
8584
  kind: "transition-unevaluable";
8697
8585
  transitions: string[];
@@ -8721,14 +8609,9 @@ export declare interface SubjectPermissionDenial {
8721
8609
  permission: DocumentValuePermission;
8722
8610
  }
8723
8611
 
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
8612
  declare interface SubjectResourceAccess {
8727
8613
  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. */
8614
+ /** 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
8615
  actorId: string;
8733
8616
  }
8734
8617
 
@@ -8835,18 +8718,23 @@ export declare interface SubworkflowEntry {
8835
8718
  };
8836
8719
  }
8837
8720
 
8721
+ /**
8722
+ * Fan-out declared as an action's `spawn`, read back as `$subworkflows`.
8723
+ * `forEach` is GROQ producing one row per subworkflow (bound as `$row`); each
8724
+ * row needs an identity the engine can adopt on re-entry (`_key` ?? `_id` ??
8725
+ * GDR `id`, or the value itself for a scalar row) or the spawn fails.
8726
+ * `definition` resolves by stable `name`, ordered `version desc` unless
8727
+ * pinned. `with` seeds each child's initial fields; `context` delivers extra
8728
+ * parent-scope values into the child's `$context`. `onExit` governs only
8729
+ * still-live children when the cohort's scope stops applying: `'detach'`
8730
+ * (default) lets them run to completion, `'abort'` kills them recursively —
8731
+ * always an authored choice, never automatic. Whether the PARENT may move at
8732
+ * all is a separate gate over `$subworkflows`.
8733
+ */
8838
8734
  export declare type Subworkflows = v.InferOutput<typeof SubworkflowsSchema>;
8839
8735
 
8840
8736
  declare const SubworkflowsSchema: v.StrictObjectSchema<
8841
8737
  {
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
8738
  readonly forEach: v.SchemaWithPipe<
8851
8739
  readonly [
8852
8740
  v.StringSchema<undefined>,
@@ -8880,7 +8768,6 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
8880
8768
  },
8881
8769
  undefined
8882
8770
  >;
8883
- /** Initial fields for each subworkflow — entry name → GROQ over `$row` + the parent scope. */
8884
8771
  readonly with: v.OptionalSchema<
8885
8772
  v.RecordSchema<
8886
8773
  v.SchemaWithPipe<
@@ -8899,11 +8786,6 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
8899
8786
  >,
8900
8787
  undefined
8901
8788
  >;
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
8789
  readonly context: v.OptionalSchema<
8908
8790
  v.RecordSchema<
8909
8791
  v.SchemaWithPipe<
@@ -8922,16 +8804,6 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
8922
8804
  >,
8923
8805
  undefined
8924
8806
  >;
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
8807
  readonly onExit: v.OptionalSchema<
8936
8808
  v.PicklistSchema<readonly ["detach", "abort"], string>,
8937
8809
  undefined
@@ -8961,6 +8833,10 @@ export declare interface SuggestedRemediation {
8961
8833
  * recovered entries is the next `drainEffects` call's job. To kill a stuck
8962
8834
  * entry WITHOUT redispatching, report it via
8963
8835
  * `completeEffect({status: 'failed'})` instead.
8836
+ *
8837
+ * A standalone export, NOT an `Engine` verb: like the guard-lifecycle
8838
+ * helpers, this is housekeeping for admin/ops tooling, not part of the
8839
+ * editor/runtime verb surface — a drain already self-recovers via takeover.
8964
8840
  */
8965
8841
  export declare function sweepStaleClaims(args: {
8966
8842
  client: WorkflowClient;
@@ -8981,12 +8857,7 @@ export declare interface SweepStaleClaimsResult {
8981
8857
  /** Lake `identity()` sentinel for system-initiated actions. */
8982
8858
  export declare const SYSTEM_IDENTITY = "<system>";
8983
8859
 
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
- */
8860
+ /** 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
8861
  export declare function tagScopeFilter(): string;
8991
8862
 
8992
8863
  /**
@@ -9000,22 +8871,6 @@ declare type Telemetered<T> = T & {
9000
8871
  telemetry?: WorkflowTelemetryLogger;
9001
8872
  };
9002
8873
 
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
8874
  /** Mirror of `@sanity/telemetry`'s `ConsentStatus`. */
9020
8875
  export declare type TelemetryConsentStatus =
9021
8876
  | "undetermined"
@@ -9050,6 +8905,14 @@ export declare interface TelemetryIntakeClient {
9050
8905
  }) => Promise<T>;
9051
8906
  }
9052
8907
 
8908
+ /**
8909
+ * The statuses an activity can be resolved INTO — what `status.set` accepts.
8910
+ * A health axis, not a decision axis: a routine decision (decline, send back,
8911
+ * hold) resolves `done` and routes via a field write; `failed` means the work
8912
+ * genuinely could not complete. Only `done`/`skipped` satisfy
8913
+ * `$allActivitiesDone` — a `failed` activity blocks it permanently, surfacing
8914
+ * via `$anyActivityFailed`.
8915
+ */
9053
8916
  declare const TERMINAL_ACTIVITY_STATUSES: readonly [
9054
8917
  "done",
9055
8918
  "skipped",
@@ -9063,8 +8926,8 @@ export declare type TerminalActivityStatus =
9063
8926
  export declare type TerminalState = "aborted" | "completed" | "in-flight";
9064
8927
 
9065
8928
  /**
9066
- * Classify an instance by its terminal stamps. The ONE home for the
9067
- * precedence rule: aborted instances carry `completedAt` too (stamped at the
8929
+ * Classify an instance by its terminal stamps. The single definition of the
8930
+ * precedence rule: aborted instances have `completedAt` too (stamped at the
9068
8931
  * abort, so in-flight queries treat both terminals uniformly), so `abortedAt`
9069
8932
  * must be checked first — `'completed'` means completed *without* an abort.
9070
8933
  */
@@ -9080,15 +8943,8 @@ export declare function terminalState(
9080
8943
  */
9081
8944
  export declare function toBareId(id: string): string;
9082
8945
 
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
- */
8946
+ /** Ad-hoc, status-tracked work items: sugar over `array of object {label, status, assignee?, dueDate?}`; a plain checklist is that with `{label, status}` alone.
8947
+ * 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
8948
  declare type TodoListField = FieldBase<AuthoringEditable, GroupMembership> & {
9093
8949
  type: "todoList";
9094
8950
  };
@@ -9110,6 +8966,16 @@ export declare interface TodoListItem {
9110
8966
  dueDate?: string | null;
9111
8967
  }
9112
8968
 
8969
+ /**
8970
+ * A pure edge — `{name, when, to}` plus presentation, no ops or effects
8971
+ * (structure never does; only actions do). Every transition is evaluated on
8972
+ * every commit and cascade; the first truthy `when` in declaration order
8973
+ * fires. No action coupling: a routing difference is written into fields by
8974
+ * an action and read by the trigger — arrival work is a `when: 'true'`
8975
+ * action in the destination stage, and exit work is an action in the source
8976
+ * stage whose `when` repeats this transition's condition (the hop rule
8977
+ * guarantees it commits before the move).
8978
+ */
9113
8979
  export declare type Transition = TransitionFields & {
9114
8980
  when: string;
9115
8981
  };
@@ -9190,10 +9056,6 @@ export declare function unsatisfiedTransitionSummaries(
9190
9056
  summary: string;
9191
9057
  }[];
9192
9058
 
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
9059
  /** Flat key → active-value record bound as advisory `$attributes` when present. */
9198
9060
  export declare type UserAttributes = Record<string, unknown>;
9199
9061
 
@@ -9237,6 +9099,12 @@ declare interface ValidationIssue {
9237
9099
  message: string;
9238
9100
  }
9239
9101
 
9102
+ /**
9103
+ * An op's write payload, resolved to concrete JSON when the op applies. Each
9104
+ * context-bound arm has a rendered `$`-twin in conditions (`actor` ↔
9105
+ * `$actor`, `now` ↔ `$now`, `self` ↔ `$self`), so learning one side teaches
9106
+ * the other. Distinct from {@link FieldSource}, a field's seed recipe.
9107
+ */
9240
9108
  export declare type ValueExpr = ValueExprInternal;
9241
9109
 
9242
9110
  declare type ValueExprInternal =
@@ -9337,110 +9205,80 @@ export { WhatIfOutcome };
9337
9205
 
9338
9206
  export { withAssignment };
9339
9207
 
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
9208
  export declare const workflow: {
9346
9209
  /**
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.
9210
+ * Deploy a set of definitions as one call. Definitions are immutable and
9211
+ * content-addressed: the author writes no version, identical content no-ops
9212
+ * (`unchanged`), and any change mints the next version (`created`) — deploy
9213
+ * never patches a deployed version out from under the instances pinned to it.
9214
+ * The engine orders the batch itself (children before the parents that spawn
9215
+ * them). Refs may point inside the batch or at already-deployed definitions;
9216
+ * a ref resolving to neither, or a cycle, errors before any write. Input is
9217
+ * authored content or a fetched definition document the document envelope
9218
+ * (`_*` system fields, `tag`, `version`, `contentHash`) is stripped at the
9219
+ * boundary and never fingerprinted, so a fetched document redeploys as
9220
+ * `unchanged`; any other unknown key fails loud.
9368
9221
  */
9369
9222
  deployDefinitions: <T extends WorkflowDefinitionInput<T>>(
9370
9223
  rawArgs: Telemetered<DeployDefinitionsArgs<T> & EngineScopeArgs>,
9371
9224
  ) => Promise<DeployDefinitionsResult>;
9372
9225
  /**
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).
9226
+ * Remove a deployed definition (all versions, or one via `version`). Refuses
9227
+ * while non-terminal instances exist unless `cascade` aborts them first —
9228
+ * instances are never deleted, only aborted in place; see
9229
+ * {@link deleteDefinitionInternal} for the full contract (spawn-referrer
9230
+ * check, guard-doc housekeeping).
9378
9231
  */
9379
9232
  deleteDefinition: (
9380
9233
  rawArgs: Clocked<Telemetered<DeleteDefinitionArgs & EngineScopeArgs>>,
9381
9234
  ) => Promise<DeleteDefinitionResult>;
9382
9235
  /**
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.
9236
+ * Spawn a new instance from a deployed definition: pins the snapshot, seeds
9237
+ * the `context` bag, enters the initial stage with every in-scope activity
9238
+ * born active, then cascades until stable. The gates run before anything is
9239
+ * written — supplied rows must be structurally consumable, required inputs
9240
+ * must be present, then every declared start requirement is evaluated in
9241
+ * author order and all unmet nodes are reported by one
9242
+ * {@link StartNotAllowedError} (no override arg; pre-flight with
9243
+ * `evaluateStart`). `start.filter` is NOT evaluated herethat is a
9244
+ * read-side visibility rule, see `definitionsForDocument`.
9399
9245
  *
9400
9246
  * 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.
9247
+ * `instanceId` is the idempotency key across them: reusing it for the SAME
9248
+ * start RESUMES (input gates and field resolution are skipped, those values
9249
+ * were pinned at create), while reusing it for a DIFFERENT start, or for an
9250
+ * unfinished start that was aborted, throws
9251
+ * {@link ContractViolationError}. `changed` is `true` on a fresh start and
9252
+ * rev-derived on a resume; `cascaded` reports how far the instance
9253
+ * auto-advanced.
9415
9254
  */
9416
9255
  startInstance: (
9417
9256
  rawArgs: Clocked<Telemetered<StartInstanceArgs & EngineScopeArgs>>,
9418
9257
  ) => Promise<OperationResult>;
9419
9258
  /**
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.
9259
+ * Fire an action against an active activity, then cascade and propagate to
9260
+ * ancestors once it commits. The universal "something happened" call —
9261
+ * editors fire it, and runtimes fire it in response to webhooks, effect
9262
+ * completions, and timer firings; external signals never bypass it. A
9263
+ * cascade-fired (`when`) action is rejected: the cascade is its only firing
9264
+ * path.
9427
9265
  */
9428
9266
  fireAction: (
9429
9267
  rawArgs: Clocked<Telemetered<FireActionArgs & EngineScopeArgs>>,
9430
9268
  ) => Promise<OperationResult>;
9431
9269
  /**
9432
9270
  * Edit a declared-editable field directly — reassign, reschedule,
9433
- * claim-by-hand, append to a running log — through the generic edit seam,
9271
+ * claim-by-hand, append to a running log — through the generic edit seam
9434
9272
  * instead of a bespoke action per field. Soft-gates on the field's declared
9435
9273
  * editability (the same projection a UI renders), applies the edit as a
9436
- * `field.*` op (so provenance + history are stamped by the op path),
9274
+ * `field.*` op so provenance and history are stamped by the op path,
9437
9275
  * refreshes the stage's guards, then cascades — an edit to a value a
9438
9276
  * transition reads can and should move the instance. Advisory like every
9439
9277
  * engine gate.
9440
9278
  *
9441
9279
  * Each call is a discrete COMMIT (a history entry, a guard refresh, a
9442
9280
  * 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),
9281
+ * UI must bind it to a deliberate boundary (blur, Enter, Save, debounce),
9444
9282
  * never an `onChange` per keystroke.
9445
9283
  */
9446
9284
  editField: (
@@ -9448,94 +9286,87 @@ export declare const workflow: {
9448
9286
  ) => Promise<OperationResult>;
9449
9287
  /**
9450
9288
  * 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`.
9289
+ * appends an `effectHistory` entry whose `outputs` are what downstream
9290
+ * bindings and conditions read as `$effects['<name>'].<output>` the
9291
+ * start-only `context` bag is never touched. Any `ops` the handler returned
9292
+ * (`field.*`) are validated and applied in the same commit, through the op
9293
+ * applier an action's field ops use. Cascades after. A completion that
9294
+ * applies always changes state, so `changed` is `true`; a bad
9295
+ * `effectKey`/status throws instead, and a keyed retry of an
9296
+ * already-applied completion replays as `changed: false`.
9461
9297
  *
9462
9298
  * Completion is first-writer-wins — see {@link CompleteEffectArgs}. A
9463
- * completer reporting over a retrying transport (webhook redelivery,
9464
- * queue, cron) should pass `idempotencyKey`.
9299
+ * completer reporting over a retrying transport (webhook redelivery, queue,
9300
+ * cron) should pass `idempotencyKey`.
9465
9301
  */
9466
9302
  completeEffect: (
9467
9303
  rawArgs: Clocked<Telemetered<CompleteEffectArgs & EngineScopeArgs>>,
9468
9304
  ) => Promise<OperationResult>;
9469
9305
  /**
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.
9306
+ * Commit mid-dispatch field state from a running effect handler — the engine
9307
+ * verb behind `ctx.commitOps`. Gates on the dispatch's exact claim (token
9308
+ * match plus unexpired lease; a stale report throws `StaleEffectClaimError`
9309
+ * and writes nothing), validates and applies the `field.*` ops through the
9310
+ * shared op applier, records history and the mandatory idempotency key,
9311
+ * renews the claim's lease in the same compare-and-swap commit, refreshes
9312
+ * the stage's guards, then cascades — a report that satisfies a transition
9313
+ * moves the instance, by design.
9478
9314
  *
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.
9315
+ * `completeEffect` remains the authoritative final result and stays
9316
+ * claim-blind; this verb only protects the mid-dispatch write channel from
9317
+ * superseded handlers.
9482
9318
  */
9483
9319
  commitEffectOps: (
9484
9320
  rawArgs: Clocked<Telemetered<CommitEffectOpsArgs & EngineScopeArgs>>,
9485
9321
  ) => Promise<OperationResult>;
9486
9322
  /**
9487
9323
  * 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.
9324
+ * For a runtime reacting to any event that might affect the workflow but
9325
+ * isn't itself an action fire: a subject doc was patched, a sibling workflow
9326
+ * completed, the clock crossed a deadline a `when` reads. The caller doesn't
9327
+ * need to know what changed it nudges the affected instance and the engine
9328
+ * re-evaluates. `changed` reports whether the nudge wrote anything, derived
9329
+ * from the instance's `_rev` rather than `cascaded` alone, since a hop can
9330
+ * fire triggered actions without unlocking a transition.
9497
9331
  */
9498
9332
  tick: (
9499
9333
  rawArgs: Clocked<Telemetered<OperationArgs & EngineScopeArgs>>,
9500
9334
  ) => Promise<OperationResult>;
9501
9335
  /**
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).
9336
+ * Admin override — force the instance into `targetStage` regardless of
9337
+ * filters or declared transitions. ACL gating is enforced upstream by the
9338
+ * caller; this verb performs no permission pre-flight, only the mechanical
9339
+ * move. `changed: false` means the move was a no-op (already at the target,
9340
+ * or terminal).
9506
9341
  */
9507
9342
  setStage: (
9508
9343
  rawArgs: Clocked<Telemetered<SetStageArgs & EngineScopeArgs>>,
9509
9344
  ) => Promise<OperationResult>;
9510
9345
  /**
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.
9346
+ * Admin override — hard-stop an in-flight instance where it stands. No stage
9347
+ * move, no transition effects, pending effects cancelled; see
9348
+ * {@link abortAndPropagate} for the abort + ancestor-propagation contract.
9349
+ * Propagated, not cascaded — the instance is terminal, so `cascaded` is
9350
+ * always `0` and ancestor movement is reported on the ancestors, not here.
9351
+ * `changed: false` means the instance was already terminal.
9518
9352
  */
9519
9353
  abortInstance: (
9520
9354
  rawArgs: Clocked<Telemetered<AbortInstanceArgs & EngineScopeArgs>>,
9521
9355
  ) => Promise<OperationResult>;
9522
9356
  /**
9523
9357
  * 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).
9358
+ * instance's current stage. `to: 'active'` (the default) re-runs it;
9359
+ * `to: 'skipped'` is the bypass that resolves it so a `$allActivitiesDone`-gated
9360
+ * exit can fire. Cascades after the reset, so an unblocked transition fires
9361
+ * in the same call. ACL gating is enforced upstream by the caller; this verb
9362
+ * performs no permission pre-flight. `changed: false` means the reset was a
9363
+ * no-op (instance terminal, or the activity already at the target status).
9530
9364
  */
9531
9365
  resetActivity: (
9532
9366
  rawArgs: Clocked<Telemetered<ResetActivityArgs & EngineScopeArgs>>,
9533
9367
  ) => 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
- */
9368
+ /** Fetch a workflow instance by id, scoped to the engine's tag. Throws when
9369
+ * the instance doesn't exist or isn't visible to this engine. */
9539
9370
  getInstance: (
9540
9371
  rawArgs: InstanceRefArgs & EngineScopeArgs,
9541
9372
  ) => Promise<WorkflowInstance>;
@@ -9546,65 +9377,52 @@ export declare const workflow: {
9546
9377
  rawArgs: GuardsForDefinitionArgs & EngineScopeArgs,
9547
9378
  ) => Promise<MutationGuardDoc[]>;
9548
9379
  /**
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.
9380
+ * Run a caller-supplied GROQ query with the engine's tag bound as `$tag`.
9381
+ * This does NOT rewrite the query — arbitrary GROQ can't be safely
9382
+ * tag-scoped after the fact — so the CALLER MUST filter on `$tag` (e.g.
9383
+ * `tag == $tag`). To guard against accidental cross-partition reads, a query
9384
+ * that never references `$tag` is rejected before it reaches the lake. The
9385
+ * caller is responsible for type-narrowing the result.
9556
9386
  */
9557
9387
  query: <T = unknown>(rawArgs: QueryArgs & EngineScopeArgs) => Promise<T>;
9558
9388
  /**
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.
9389
+ * Snapshot-aware GROQ — runs against the same in-memory view that filters
9390
+ * see for a given instance. Hydrates the instance's snapshot (instance +
9391
+ * ancestors + every doc declared by a `doc.ref` / `subject` / `doc.refs`
9392
+ * entry in scope), then evaluates the supplied GROQ in groq-js against that
9393
+ * dataset. The caller-free rendered scope cascade gates evaluate in is
9394
+ * auto-bound the instance-derived vars with the open stage's overlay
9395
+ * merged into `$fields`, `$assigned` at its caller-free `false`, plus the
9396
+ * author's pre-evaluated `$<predicate>` booleans with ids in GDR URI form
9397
+ * to match the snapshot's keying. Pure read; never writes.
9574
9398
  */
9575
9399
  queryInScope: <T = unknown>(
9576
9400
  rawArgs: Clocked<QueryInScopeArgs & EngineScopeArgs>,
9577
9401
  ) => 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
- */
9402
+ /** Every pending effect on the instance — the same entries the runtime would
9403
+ * see, claimed and unclaimed alike. */
9582
9404
  listPendingEffects: (
9583
9405
  rawArgs: InstanceRefArgs & EngineScopeArgs,
9584
9406
  ) => 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
- */
9407
+ /** Filter the instance's pending effects: `claimed` on claim presence,
9408
+ * `names` on specific effect names. Both filters compose (AND). */
9590
9409
  findPendingEffects: (
9591
9410
  rawArgs: FindPendingEffectsArgs & EngineScopeArgs,
9592
9411
  ) => Promise<PendingEffect[]>;
9593
9412
  /**
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.
9413
+ * Project the instance from a given actor's perspective a
9414
+ * {@link WorkflowEvaluation} with per-action verdicts (`allowed` plus a
9415
+ * structured `disabledReason`). Used by UIs to render
9416
+ * disabled-with-reason buttons and by `fireAction` to gate writes through
9417
+ * the same logic. Pure read; never writes.
9600
9418
  */
9601
9419
  evaluate: (
9602
9420
  rawArgs: Clocked<EvaluateArgs & EngineScopeArgs>,
9603
9421
  ) => Promise<WorkflowEvaluation>;
9604
9422
  /**
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`
9423
+ * Diagnose why an instance is or isn't progressing. Projects the instance
9424
+ * (the same read as `evaluate`) and classifies it — terminal,
9425
+ * `progressing`, `waiting` (an action is available, so healthy), or `stuck`
9608
9426
  * with a structured cause — returning that verdict as a
9609
9427
  * {@link DiagnoseResult} alongside the evaluation it came from, so a
9610
9428
  * consumer can render the supporting evidence without a second projection.
@@ -9613,59 +9431,39 @@ export declare const workflow: {
9613
9431
  diagnose: (
9614
9432
  rawArgs: Clocked<EvaluateArgs & EngineScopeArgs>,
9615
9433
  ) => 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
- */
9434
+ /** The actions an actor could fire on the instance's current stage, each
9435
+ * flagged `allowed` with a structured `disabledReason` when not, returned
9436
+ * with the evaluation they were projected from. Pure read. */
9623
9437
  availableActions: (
9624
9438
  rawArgs: Clocked<EvaluateArgs & EngineScopeArgs>,
9625
9439
  ) => Promise<AvailableActionsResult>;
9626
9440
  /**
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.
9441
+ * Materialised spawned children of a parent instance. Walks `history` for
9442
+ * `spawned` events — the durable record, and still the one place adoption
9443
+ * and orphan events sit alongside spawns strips each `instanceRef`'s GDR
9444
+ * URI to a bare `_id`, fetches the instances, drops any not visible to this
9445
+ * engine's tag, and returns them sorted by `startedAt` ascending. Pass
9446
+ * `activity` to restrict to a single spawning activity on the parent.
9637
9447
  */
9638
9448
  children: (
9639
9449
  rawArgs: ChildrenArgs & EngineScopeArgs,
9640
9450
  ) => Promise<WorkflowInstance[]>;
9641
9451
  /**
9642
9452
  * 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
9453
+ * the reverse of an instance's subscription document set. For a
9454
+ * content-change-driven runtime holding no instances in memory: a document
9455
+ * changed, which instances should it `tick`? The watch-set covers the
9456
+ * instance itself, its ancestors, live spawned children, and the docs named
9457
+ * by `doc.ref` / `subject` / `doc.refs` / `release.ref` entries on the
9458
+ * workflow scope AND the current stage, so a hand-rolled GROQ over `fields[]`
9459
+ * gets it subtly wrong. The GROQ filter narrows candidates server-side and
9460
+ * {@link instanceWatchesDocument} rechecks each result, keeping the reverse
9657
9461
  * in lockstep with the forward set.
9658
9462
  *
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.
9463
+ * `document` must be a resource-qualified GDR URI; a bare id is rejected,
9464
+ * since it can't be resource-routed and would silently mismatch — an
9465
+ * instance watching `dataset:A:ds:doc` is never matched by a change to
9466
+ * `dataset:B:ds:doc`. Sorted by `startedAt` ascending.
9669
9467
  */
9670
9468
  instancesForDocument: (
9671
9469
  rawArgs: InstancesForDocumentArgs & EngineScopeArgs,
@@ -9674,51 +9472,46 @@ export declare const workflow: {
9674
9472
  * The startable half of {@link workflow.instancesForDocument}: every
9675
9473
  * deployed definition that APPLIES to `document` — what a start picker for
9676
9474
  * 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}.
9475
+ * visible to the engine's tag and filters it through
9476
+ * {@link applicableDefinitions}: startable ∧ the `subject`-kind entry
9477
+ * accepts the doc's `_type` ∧ `start.filter` passes, evaluated in the
9478
+ * browse-time-pure start-filter context. Start requirements never
9479
+ * participate readiness is a start-time question; pre-flight it with
9480
+ * {@link workflow.evaluateStart}.
9684
9481
  *
9685
9482
  * Takes the LOADED candidate document, not a ref — applicability evaluates
9686
9483
  * 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.
9484
+ * ALL matches (name ascending) with no engine ranking: presenting a picker
9485
+ * or auto-picking is consumer policy. Advisory like every engine-side check.
9690
9486
  */
9691
9487
  definitionsForDocument: (
9692
9488
  rawArgs: Clocked<DefinitionsForDocumentArgs & EngineScopeArgs>,
9693
9489
  ) => Promise<DeployedDefinition[]>;
9694
9490
  /**
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
9491
+ * Pre-flight the start gates for a definition plus candidate
9492
+ * `initialFields` — the read `startInstance` enforces, as a
9493
+ * {@link StartEvaluation} a surface can render: `missingRequired` mirrors
9494
+ * the input contract, while `requirements` preserves every declared node's
9495
+ * authored descriptor, outcome, and GROQ insight where applicable;
9496
+ * `allowed` / `outcome` aggregate those ordered results.
9497
+ *
9498
+ * BINDABILITY-AWARE for partial mid-form inputs: when a predicate reads an
9499
+ * entry `initialFields` doesn't supply including a `singleSubject` node's
9500
+ * implicit subject read — `outcome` is `'unevaluable'` and `unboundReads`
9501
+ * names the entries ("fill these to decide") instead of the collapsed answer
9502
+ * GROQ equality would give. That is the ONE deliberate divergence from the
9503
+ * gate, where absence is final rather than provisional. A definition
9504
+ * declaring no start requirements is vacuously allowed, exactly like the
9505
+ * verb. Pure read; advisory under races — the enforcement moment is
9711
9506
  * `startInstance` itself.
9712
9507
  */
9713
9508
  evaluateStart: (
9714
9509
  rawArgs: Clocked<EvaluateStartArgs & EngineScopeArgs>,
9715
9510
  ) => 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
- */
9511
+ /** Permission helpers — Sanity ACL grants evaluated against documents via
9512
+ * GROQ, used by `workflow.evaluate` to soft-gate actions when the caller
9513
+ * supplies grants. Deliberately namespace-only, not mirrored on `Engine`:
9514
+ * pure helpers that need none of the engine's pinned scope. */
9722
9515
  permissions: {
9723
9516
  matchesFilter: typeof matchesFilter;
9724
9517
  grantsPermissionOn: typeof grantsPermissionOn;
@@ -9737,7 +9530,7 @@ export declare const WORKFLOW_DEFINITION_TYPE = "sanity.workflow.definition";
9737
9530
  * The lake document type for a workflow instance. Single source of truth — the
9738
9531
  * {@link WorkflowInstance} `_type`, every tag-scoped query, and the create
9739
9532
  * write all derive from here, mirroring {@link WORKFLOW_DEFINITION_TYPE}.
9740
- * Engine-owned standalone documents carry the platform namespace.
9533
+ * Engine-owned standalone documents use the platform namespace.
9741
9534
  */
9742
9535
  export declare const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
9743
9536
 
@@ -9907,10 +9700,10 @@ export declare interface WorkflowClient {
9907
9700
  */
9908
9701
  withConfig?: (config: WorkflowClientConfig) => this;
9909
9702
  /**
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."
9703
+ * Optional — present on the real `@sanity/client`. Without it, ACL grant
9704
+ * discovery uses its dry-run fallback, while a definition containing
9705
+ * role-constrained assignment fields fails loudly because the engine cannot
9706
+ * read the project membership directory required to validate assignees.
9914
9707
  */
9915
9708
  request?: <T>(opts: {
9916
9709
  /** Raw URL (host + path). One of `url` / `uri` required. */
@@ -9973,6 +9766,16 @@ export declare interface WorkflowCommitOptions {
9973
9766
  tag?: string;
9974
9767
  }
9975
9768
 
9769
+ /**
9770
+ * `deployments` names must be unique (the selector deployment-targeted
9771
+ * commands resolve by), and each `(workflowResource, tag)` pair must be
9772
+ * unique — that pair is the storage partition, so two deployments sharing
9773
+ * both would fight over definition versions. `telemetry`, when set, replaces
9774
+ * the CLI's built-in Sanity-intake shell entirely: every event flows to this
9775
+ * logger unconditionally (CI and `DO_NOT_TRACK` included), and consent,
9776
+ * environment suppression, and transport become this implementation's
9777
+ * business.
9778
+ */
9976
9779
  export declare type WorkflowConfig = v.InferOutput<typeof WorkflowConfigSchema>;
9977
9780
 
9978
9781
  /**
@@ -10599,14 +10402,6 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
10599
10402
  >,
10600
10403
  ]
10601
10404
  >;
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
10405
  readonly telemetry: v.OptionalSchema<
10611
10406
  v.CustomSchema<
10612
10407
  WorkflowTelemetryLogger,
@@ -10618,6 +10413,21 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
10618
10413
  undefined
10619
10414
  >;
10620
10415
 
10416
+ /**
10417
+ * `name` is a lake-id-segment (`^[a-z0-9][a-z0-9-]*$`) that interpolates into
10418
+ * every deployed document id (`<tag>.<name>.v<version>`) — stable identity
10419
+ * that instances pin to and subworkflows resolve by. `lifecycle: 'child'`
10420
+ * marks a spawn-only definition, instantiated by a parent via an action's
10421
+ * `spawn`, never started cold from a picker (omitted ⇒ `'standalone'`,
10422
+ * startable); advisory only — consumers filter start pickers on it (see
10423
+ * {@link isStartableDefinition}), the engine does not itself refuse a
10424
+ * `startInstance` on a `'child'` definition. `start` is meaningless
10425
+ * (deploy-rejected) on a spawn-only definition; omitted, it means
10426
+ * interactive semantics with no predicates. `predicates` are nullary named
10427
+ * conditions — each `name: groq` entry is pre-evaluated and bound as the
10428
+ * boolean `$name` var; redefining a built-in var is a deploy error, never a
10429
+ * silent shadow.
10430
+ */
10621
10431
  export declare type WorkflowDefinition = v.InferOutput<
10622
10432
  typeof WorkflowDefinitionSchema
10623
10433
  >;
@@ -10690,37 +10500,37 @@ export declare type WorkflowDefinitionInput<T> = string extends keyof T
10690
10500
  * every reference scope resolved. Cross-field invariants (unique names,
10691
10501
  * transition targets, effect-name uniqueness, predicate shadowing) are
10692
10502
  * checked by `checkWorkflowInvariants` after desugar — see `defineWorkflow`.
10503
+ * Carries NO `version`: a definition's version and content fingerprint are
10504
+ * stamped onto the deployed document at deploy time, derived from the
10505
+ * content itself, so redeploying identical content is a no-op and any
10506
+ * change mints the next version.
10693
10507
  *
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.
10508
+ * Exported (module-level, not package API) for the model-surface gate's
10509
+ * coverage test and for `parseStoredDefinition` the boundary parse for a
10510
+ * definition that did not come out of `defineWorkflow` in-process; trusted
10511
+ * in-process desugar output is never re-parsed.
10700
10512
  */
10701
10513
  declare const WorkflowDefinitionSchema: v.GenericSchema<
10702
10514
  WorkflowFields<FieldEntry, Stage, StartBlock>
10703
10515
  >;
10704
10516
 
10705
10517
  /** 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}. */
10518
+ * commands that do not submit definitions can hold a missing acknowledgement.
10519
+ * Definition-submission paths compare it with their selected definitions; authors write
10520
+ * {@link WorkflowDeploymentInput}. */
10709
10521
  export declare type WorkflowDeployment = WorkflowConfig["deployments"][number];
10710
10522
 
10711
10523
  /**
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).
10524
+ * What an author writes for one deployment: the highest reader model verified
10525
+ * across runtimes sharing its workflow resource. Runtime validation compares
10526
+ * it with the submitted definitions, so a dependency upgrade alone does not
10527
+ * require changing the literal.
10718
10528
  */
10719
10529
  export declare type WorkflowDeploymentInput = Omit<
10720
10530
  WorkflowDeployment,
10721
10531
  "expectedMinReaderModel"
10722
10532
  > & {
10723
- expectedMinReaderModel: typeof DATA_MODEL_MIN_READER;
10533
+ expectedMinReaderModel: number;
10724
10534
  };
10725
10535
 
10726
10536
  export declare const WorkflowEffectCompleted: WorkflowTelemetryEvent<WorkflowEffectCompletedData>;
@@ -10874,12 +10684,6 @@ export declare interface WorkflowFieldEditedData extends InstanceScopedEventData
10874
10684
 
10875
10685
  /** Type-mirror of {@link workflowFields}, parameterised over field/stage/start. */
10876
10686
  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
10687
  name: string;
10884
10688
  semantics?: Semantic[] | undefined;
10885
10689
  title: string;
@@ -10906,8 +10710,8 @@ export declare interface WorkflowInstance extends SanityDocument {
10906
10710
  modelVersion?: number;
10907
10711
  /**
10908
10712
  * 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
10713
+ * this document. Derived from its persisted features and the retained
10714
+ * model-4 baseline, and written alongside
10911
10715
  * {@link WorkflowInstance.modelVersion}. Full persists never lower it.
10912
10716
  */
10913
10717
  minReaderModel?: number;
@@ -10933,7 +10737,7 @@ export declare interface WorkflowInstance extends SanityDocument {
10933
10737
  * can detect a deployed definition that drifted from what this instance
10934
10738
  * started on. Advisory — the engine enforces nothing; this enables detection,
10935
10739
  * not prevention. Absent when the instance was started against a definition
10936
- * deployed before content-addressing (it carried no hash to pin).
10740
+ * deployed before content-addressing (it had no hash to pin).
10937
10741
  */
10938
10742
  pinnedContentHash?: string;
10939
10743
  /** Frozen JSON snapshot of the definition at the moment the instance started. */
@@ -10982,10 +10786,10 @@ export declare interface WorkflowInstance extends SanityDocument {
10982
10786
  */
10983
10787
  stages: StageEntry[];
10984
10788
  /**
10985
- * Workflow-scope registry of every child this instance ever spawned
10789
+ * Workflow-scope registry of every child this instance ever spawned;
10986
10790
  * 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
10791
+ * `resolved` is a live child (watched, hydrated, propagating), one with
10792
+ * it is terminal, and a live row with `abortPending` is condemned — the
10989
10793
  * cascade owes it an abort. Rendered as the `$subworkflows` condition
10990
10794
  * var. Absent only on instances persisted before the registry existed.
10991
10795
  */
@@ -11015,6 +10819,63 @@ export declare interface WorkflowInstance extends SanityDocument {
11015
10819
 
11016
10820
  export declare const WorkflowInstanceAborted: WorkflowTelemetryEvent<WorkflowAdminOverrideData>;
11017
10821
 
10822
+ /**
10823
+ * The instance list projection — a reduced {@link WorkflowInstance} for
10824
+ * surfaces that render many runs at once, fetched by `instancePreviewsQuery`.
10825
+ *
10826
+ * The reduction keeps the full instance's field names and member shapes so
10827
+ * instance helpers (`terminalState`, `findOpenStageEntry`, `parentRef`, the
10828
+ * identity normalizer) read a preview unchanged; what shrinks is the content:
10829
+ * `stages` holds the open entry alone, every `fields` list keeps only the
10830
+ * identity, date, document-reference, and release-reference kinds, and the unbounded audit
10831
+ * trails are gone — `claimedEffects` and `failedEffects` hold the two facts
10832
+ * a stuck classifier reads in their place. There is deliberately no
10833
+ * `definitionSnapshot`: a consumer titles what it shows from the deployed
10834
+ * catalog, falling back to raw names.
10835
+ */
10836
+ export declare interface WorkflowInstancePreview {
10837
+ _id: string;
10838
+ _type: typeof WORKFLOW_INSTANCE_TYPE;
10839
+ /** See {@link WorkflowInstance.modelVersion}. */
10840
+ modelVersion?: number;
10841
+ /** See {@link WorkflowInstance.minReaderModel}. */
10842
+ minReaderModel?: number;
10843
+ workflowResource: WorkflowResource;
10844
+ definition: string;
10845
+ pinnedVersion: number;
10846
+ /** Identity, date, document-reference, and release-reference entries only
10847
+ * — the kinds list surfaces read. Composite (`object`/`array`) entries are
10848
+ * dropped, so identities nested inside them are invisible to a preview. */
10849
+ fields: ResolvedFieldEntry[];
10850
+ ancestors: GlobalDocumentReference[];
10851
+ perspective?: WorkflowPerspective;
10852
+ currentStage: StageName;
10853
+ /** The open stage entry alone, its activities' fields reduced like
10854
+ * {@link fields}. A completed run keeps its terminal entry open, so this
10855
+ * is empty only for an aborted run (whose entries closed in place) or
10856
+ * before the run primes. */
10857
+ stages: StageEntry[];
10858
+ /** Pending effects a drainer has claimed — the hung-automation fact. */
10859
+ claimedEffects: WorkflowInstancePreviewEffect[];
10860
+ /** Effect-history rows that reported failure — the failed-automation fact. */
10861
+ failedEffects: WorkflowInstancePreviewEffect[];
10862
+ startedAt: string;
10863
+ completedAt?: string;
10864
+ abortedAt?: string;
10865
+ }
10866
+
10867
+ /** A stalled automation as a preview reports it — the effect's machine name
10868
+ * and its display title. */
10869
+ export declare interface WorkflowInstancePreviewEffect {
10870
+ name: string;
10871
+ title?: string;
10872
+ }
10873
+
10874
+ /** The instance list projection (`instancePreviewsQuery` results). The reduced
10875
+ * members reuse the persisted document's own schemas, so a preview can
10876
+ * never admit a shape the full parse would refuse. */
10877
+ export declare const WorkflowInstancePreviewSchema: v.GenericSchema<WorkflowInstancePreview>;
10878
+
11018
10879
  /**
11019
10880
  * The persisted instance document, root to leaf. Reused verbatim by every
11020
10881
  * engine read boundary through {@link parseInstanceDocument}; the