@sanity/workflow-engine 0.17.0 → 0.18.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.js CHANGED
@@ -1,12 +1,12 @@
1
- import { rethrowWithContext, andConditions, deriveActivityKind, CALLER_BOUND_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, conditionParameterNames, START_FILTER_VARS, START_ALLOWED_VARS, gdrFromResource, selfGdr, isGdr, actorFulfillsRole, toBareId, WorkflowError, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, errorMessage, validateFieldValue, validateFieldAppendItem, evaluateCondition, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, conditionEffectReads, EFFECTS_READ, datasetResourceParts, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, isCascadeFired, runGroq, parseGdr, isGdrUri, gdrRef, isInputSourced, checkFieldValue, toPhysicalGdr, isBareSeedId, tolerantEntries, NonEmptyString, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, InstanceNotFoundError, evaluateConditionOutcome, FIELD_READ, MUTATION_GUARD_ACTIONS, resourceGdr, resourceFromGdrUri, refTypeIssues, rejectedRefTypes, DOCUMENT_VALUE_PERMISSIONS, deriveExecutorClassification, validateTag, driverKind, EffectNotFoundError, extractDocumentId, parseStoredDefinition, labelFor, DefinitionNotFoundError, definitionDocId, validateResourceAliasName, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, DefinitionInUseError, FieldValueShapeError, isParseableInstant, groupMembershipNames } from "./_chunks-es/invariants.js";
1
+ import { terminalState, andConditions, deriveActivityKind, parseDefinitionSnapshot, CALLER_BOUND_VARS, START_ALLOWED_VARS, CONDITION_VARS, SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, rethrowWithContext, conditionParameterNames, isGdr, WORKFLOW_INSTANCE_TYPE, START_FILTER_VARS, gdrFromResource, selfGdr, isSingleDocRefKind, parentRef, actorFulfillsRole, toBareId, WorkflowError, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, errorMessage, validateFieldValue, validateFieldAppendItem, evaluateCondition, isSingleDocRefEntry, choiceValueIssues, scalarValidationIssues, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, conditionEffectReads, EFFECTS_READ, datasetResourceParts, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, isCascadeFired, runGroq, parseGdr, isGdrUri, gdrRef, isInputSourced, checkFieldValue, toPhysicalGdr, isBareSeedId, tolerantEntries, NonEmptyString, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, assertReadableModel, InstanceNotFoundError, modelStampFor, evaluateConditionOutcome, FIELD_READ, MUTATION_GUARD_ACTIONS, resourceGdr, minReaderModelOf, resourceFromGdrUri, refTypeIssues, rejectedRefTypes, DOCUMENT_VALUE_PERMISSIONS, deriveExecutorClassification, validateTag, driverKind, EffectNotFoundError, extractDocumentId, parseStoredDefinition, validateResourceAliasName, labelFor, DefinitionNotFoundError, definitionDocId, SpawnContractsInvalidError, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, isUnprimed, DefinitionInUseError, assertReaderModelAcknowledgement, FieldValueShapeError, isParseableInstant, groupMembershipNames } from "./_chunks-es/invariants.js";
2
2
 
3
- import { ACTIVITY_KINDS, ACTOR_KINDS, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, PersistedDocShapeError, RESERVED_CONDITION_VARS, clientConfigFromResource, gdrUri, isNotesEntry, isTodoListEntry, isTodoListItem, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refMediaLibrary, releaseDocId, releaseRef, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
3
+ import { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTOR_KINDS, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, ModelVersionAheadError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, clientConfigFromResource, fieldTreeShape, gdrUri, isNotesEntry, isTodoListEntry, isTodoListItem, modelVersionOf, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, releaseDocId, releaseRef, requiredModelFeatures, requiredReaderModel, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
4
4
 
5
5
  import { atomNode, dedupeBy, analyzeCondition, atomReadsDataset, checklistLines as checklistLines$1, phrase, quoted, listAnd, describeAtom as describeAtom$1, describeCondition as describeCondition$1, guillemets, formatValue, humanize, listOr, scopeReadOf, describeRead, explainCondition, dedupeReads, whatIfCondition, MAX_COUNTERFACTUAL_INDEX } from "@sanity/groq-condition-describe";
6
6
 
7
7
  import { MAX_COUNTERFACTUAL_INDEX as MAX_COUNTERFACTUAL_INDEX2, analyzeCondition as analyzeCondition2, atomReadsDataset as atomReadsDataset2, explainCondition as explainCondition2, formatRead, guillemets as guillemets2, humanize as humanize2, isComparisonOp, quoted as quoted2, sentenceCase, whatIfCondition as whatIfCondition2, withAssignment } from "@sanity/groq-condition-describe";
8
8
 
9
- import { parse, evaluate } from "groq-js";
9
+ import { evaluate, parse } from "groq-js";
10
10
 
11
11
  import * as v from "valibot";
12
12
 
@@ -41,28 +41,6 @@ function findCurrentActivityEntry(host, activityName) {
41
41
  return findOpenStageEntry(host)?.activities.find(a => a.name === activityName);
42
42
  }
43
43
 
44
- const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
45
-
46
- function terminalState(instance) {
47
- return instance.abortedAt !== void 0 ? "aborted" : instance.completedAt !== void 0 ? "completed" : "in-flight";
48
- }
49
-
50
- function isUnprimed(instance) {
51
- return instance.stages.length === 0 && terminalState(instance) === "in-flight";
52
- }
53
-
54
- function parseDefinitionSnapshot(instance) {
55
- try {
56
- return JSON.parse(instance.definitionSnapshot);
57
- } catch (err) {
58
- rethrowWithContext(err, `Failed to parse definitionSnapshot on instance "${instance._id}"`);
59
- }
60
- }
61
-
62
- function parentRef(instance) {
63
- return instance.ancestors.at(-1);
64
- }
65
-
66
44
  function effectiveEditable(baseline, override) {
67
45
  if (baseline === void 0) return;
68
46
  if (override === void 0) return baseline;
@@ -102,6 +80,9 @@ function resolveFieldSite(site, stage) {
102
80
  ...site.entry.title !== void 0 ? {
103
81
  title: site.entry.title
104
82
  } : {},
83
+ ...site.entry.validation !== void 0 ? {
84
+ validation: site.entry.validation
85
+ } : {},
105
86
  ref: {
106
87
  scope: site.scope,
107
88
  field: site.entry.name
@@ -189,14 +170,8 @@ function editDisabledReason(args) {
189
170
  kind: "not-editable"
190
171
  };
191
172
  if (!window.open) {
192
- const terminal = terminalState(instance);
193
- return terminal === "aborted" && instance.abortedAt !== void 0 ? {
194
- kind: "instance-aborted",
195
- abortedAt: instance.abortedAt
196
- } : terminal === "completed" && instance.completedAt !== void 0 ? {
197
- kind: "instance-completed",
198
- completedAt: instance.completedAt
199
- } : {
173
+ const terminalReason = instanceTerminalReason(instance);
174
+ return terminalReason !== void 0 ? terminalReason : {
200
175
  kind: "edit-window-closed",
201
176
  detail: window.detail ?? "closed"
202
177
  };
@@ -208,6 +183,18 @@ function editDisabledReason(args) {
208
183
  };
209
184
  }
210
185
 
186
+ function instanceTerminalReason(instance) {
187
+ const terminal = terminalState(instance);
188
+ if (terminal === "aborted" && instance.abortedAt !== void 0) return {
189
+ kind: "instance-aborted",
190
+ abortedAt: instance.abortedAt
191
+ };
192
+ if (terminal === "completed" && instance.completedAt !== void 0) return {
193
+ kind: "instance-completed",
194
+ completedAt: instance.completedAt
195
+ };
196
+ }
197
+
211
198
  function defineWorkflowEvent(options) {
212
199
  return {
213
200
  type: "log",
@@ -847,13 +834,13 @@ const checklistLines = checklistLines$1;
847
834
  function toGroqDescribeContext(ctx) {
848
835
  return {
849
836
  renderRead: read => renderWorkflowRead(read, ctx),
850
- renderRequirement: workflowRequirement,
837
+ renderRequirement: requirement => workflowRequirement(requirement, ctx),
851
838
  atomPatterns: [ rolesGateText, claimGateText ],
852
839
  nowParam: "now"
853
840
  };
854
841
  }
855
842
 
856
- const VAR_LABELS = new Map(CONDITION_VARS.map(entry => [ entry.name, entry.label ]));
843
+ const VAR_LABELS = new Map([ ...START_ALLOWED_VARS, ...CONDITION_VARS ].map(entry => [ entry.name, entry.label ]));
857
844
 
858
845
  function renderWorkflowRead(read, ctx) {
859
846
  if (read.variable === "fields" && typeof read.path[0] == "string") {
@@ -893,7 +880,7 @@ function renderWorkflowRead(read, ctx) {
893
880
  });
894
881
  }
895
882
 
896
- function workflowRequirement(requirement) {
883
+ function workflowRequirement(requirement, ctx) {
897
884
  const {target: target} = requirement, clause = clauseVarRequirement(requirement);
898
885
  if (clause !== void 0) return clause;
899
886
  if (target.variable === "assigned" && target.path.length === 0) {
@@ -906,7 +893,7 @@ function workflowRequirement(requirement) {
906
893
  text: "you must not be assigned to this activity"
907
894
  });
908
895
  }
909
- if (target.variable === "effectStatus" && typeof target.path[0] == "string") return effectStatusPhrase(requirement, target.path[0]);
896
+ return effectStatusPhrase(requirement, ctx);
910
897
  }
911
898
 
912
899
  function clauseVarRequirement(requirement) {
@@ -926,28 +913,40 @@ function clauseVarRequirement(requirement) {
926
913
  params: {},
927
914
  text: "no activity in this stage may have failed"
928
915
  });
916
+ if (target.variable === SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR) return kind === "truthy" ? phrase("requirement.subject-has-in-flight-instance", {
917
+ params: {},
918
+ text: "the subject must already have an in-flight workflow"
919
+ }) : phrase("requirement.subject-has-no-in-flight-instance", {
920
+ params: {},
921
+ text: "the subject must not already have an in-flight workflow"
922
+ });
929
923
  }
930
924
  }
931
925
 
932
- function effectStatusPhrase(requirement, effect) {
933
- const name = `the ${quoted(effect)} automation`;
926
+ function effectStatusPhrase(requirement, ctx) {
927
+ const {target: target} = requirement;
928
+ if (target.variable !== "effectStatus" || typeof target.path[0] != "string") return;
929
+ const effect = target.path[0], title = effectTitleOf(effect, ctx), name = `the ${quoted(title)} automation`;
934
930
  if (requirement.kind === "equals" && requirement.value === "done") return phrase("requirement.effect-done", {
935
931
  params: {
936
- effect: effect
932
+ effect: effect,
933
+ title: title
937
934
  },
938
- text: `${name} must have completed`
935
+ text: `${name} must have succeeded`
939
936
  });
940
937
  if (requirement.kind === "equals" && requirement.value === "failed") return phrase("requirement.effect-failed", {
941
938
  params: {
942
- effect: effect
939
+ effect: effect,
940
+ title: title
943
941
  },
944
942
  text: `${name} must have failed`
945
943
  });
946
944
  if (requirement.kind === "defined") return phrase("requirement.effect-settled", {
947
945
  params: {
948
- effect: effect
946
+ effect: effect,
947
+ title: title
949
948
  },
950
- text: `${name} must have settled`
949
+ text: `${name} must have finished`
951
950
  });
952
951
  }
953
952
 
@@ -1235,12 +1234,16 @@ const WAIT_TEXTS = {
1235
1234
  },
1236
1235
  text: `waits on editor content matching ${quoted(wait.condition)}`
1237
1236
  }),
1238
- effect: wait => phrase("autonomy-wait.effect", {
1239
- params: {
1240
- effect: wait.effect
1241
- },
1242
- text: `waits on the ${quoted(wait.effect)} automation`
1243
- }),
1237
+ effect: (wait, ctx) => {
1238
+ const title = effectTitleOf(wait.effect, ctx);
1239
+ return phrase("autonomy-wait.effect", {
1240
+ params: {
1241
+ effect: wait.effect,
1242
+ title: title
1243
+ },
1244
+ text: `waits on the ${quoted(title)} automation`
1245
+ });
1246
+ },
1244
1247
  "start-input": (wait, ctx) => {
1245
1248
  const title = fieldTitleOf({
1246
1249
  path: [ wait.field ]
@@ -1353,6 +1356,10 @@ function actionTitle(site, ctx) {
1353
1356
  return ctx.definition.stages.flatMap(stage => stage.activities ?? []).filter(activity => activity.name === site.activity).flatMap(activity => activity.actions ?? []).find(candidate => candidate.name === site.action)?.title ?? humanize(site.action);
1354
1357
  }
1355
1358
 
1359
+ function effectTitleOf(name, ctx) {
1360
+ return findEffect(ctx.definition, name)?.title ?? name;
1361
+ }
1362
+
1356
1363
  function conditionSitesOf(definition) {
1357
1364
  const sites = [];
1358
1365
  for (const [predicate, condition] of Object.entries(definition.predicates ?? {})) sites.push({
@@ -1480,25 +1487,17 @@ async function applicableDefinitions(args) {
1480
1487
  }
1481
1488
 
1482
1489
  async function evaluateStartFilter(args) {
1483
- const {filter: filter, definition: definition, document: document, scope: scope} = args;
1484
- let parsed;
1485
- try {
1486
- parsed = {
1487
- tree: parse(filter),
1488
- needsDataset: analyzeCondition(filter).readsDataset
1489
- };
1490
- } catch (err) {
1491
- rethrowNamingDefinition({
1492
- err: err,
1493
- definition: definition,
1494
- key: "filter"
1495
- });
1496
- }
1497
- let dataset = [];
1498
- if (parsed.needsDataset) {
1499
- if (scope?.fetchDataset === void 0) return !1;
1500
- dataset = await scope.fetchDataset();
1501
- }
1490
+ const {filter: filter, definition: definition, document: document, scope: scope} = args, parsed = parseStartFilter({
1491
+ filter: filter,
1492
+ definition: definition
1493
+ });
1494
+ assertFilterSubject({
1495
+ readsSubject: parsed.readsSubject,
1496
+ definition: definition,
1497
+ scope: scope
1498
+ });
1499
+ const dataset = await filterDataset(parsed.needsDataset, scope);
1500
+ if (dataset === void 0) return !1;
1502
1501
  try {
1503
1502
  const result = await (await evaluate(parsed.tree, {
1504
1503
  ...document !== void 0 ? {
@@ -1507,7 +1506,8 @@ async function evaluateStartFilter(args) {
1507
1506
  dataset: dataset,
1508
1507
  params: startContextParams({
1509
1508
  definition: definition,
1510
- scope: scope
1509
+ scope: scope,
1510
+ dataset: dataset
1511
1511
  })
1512
1512
  })).get();
1513
1513
  return isUnevaluable(result) ? !1 : !!result;
@@ -1520,11 +1520,38 @@ async function evaluateStartFilter(args) {
1520
1520
  }
1521
1521
  }
1522
1522
 
1523
+ function parseStartFilter(args) {
1524
+ const {filter: filter, definition: definition} = args;
1525
+ try {
1526
+ const readsSubject = readsSubjectHasInFlightInstance(filter);
1527
+ return {
1528
+ tree: parse(filter),
1529
+ needsDataset: analyzeCondition(filter).readsDataset || readsSubject,
1530
+ readsSubject: readsSubject
1531
+ };
1532
+ } catch (err) {
1533
+ rethrowNamingDefinition({
1534
+ err: err,
1535
+ definition: definition,
1536
+ key: "filter"
1537
+ });
1538
+ }
1539
+ }
1540
+
1541
+ function assertFilterSubject(args) {
1542
+ if (!(!args.readsSubject || args.scope?.subject !== void 0)) throw new ContractViolationError(`start.filter on definition "${args.definition.name ?? "<unnamed>"}" reads $${SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR}, but the caller supplied no resource-qualified \`scope.subject\` — a loaded document alone cannot identify its project and dataset.`);
1543
+ }
1544
+
1545
+ async function filterDataset(needsDataset, scope) {
1546
+ if (!needsDataset) return [];
1547
+ if (scope?.fetchDataset !== void 0) return scope.fetchDataset();
1548
+ }
1549
+
1523
1550
  async function explainStartAllowed(args) {
1524
1551
  const {allowed: allowed, definition: definition, fields: fields, scope: scope} = args;
1525
1552
  let needsDataset;
1526
1553
  try {
1527
- needsDataset = analyzeCondition(allowed).readsDataset;
1554
+ needsDataset = analyzeCondition(allowed).readsDataset || readsSubjectHasInFlightInstance(allowed);
1528
1555
  } catch (err) {
1529
1556
  rethrowNamingDefinition({
1530
1557
  err: err,
@@ -1544,7 +1571,8 @@ async function explainStartAllowed(args) {
1544
1571
  params: startContextParams({
1545
1572
  definition: definition,
1546
1573
  scope: scope,
1547
- fields: fields
1574
+ fields: fields,
1575
+ dataset: dataset
1548
1576
  })
1549
1577
  });
1550
1578
  } catch (err) {
@@ -1560,11 +1588,23 @@ function unboundAllowedReads(allowed, fields) {
1560
1588
  return [ ...conditionFieldReadNames(allowed) ].filter(name => !Object.hasOwn(fields, name));
1561
1589
  }
1562
1590
 
1591
+ function unboundAllowedReadsWithSubject(args) {
1592
+ const {allowed: allowed, fields: fields, definition: definition} = args, subjectField = (definition.fields ?? []).find(isSubjectEntry)?.name, reads = unboundAllowedReads(allowed, fields);
1593
+ return subjectField !== void 0 && readsSubjectHasInFlightInstance(allowed) && !Object.hasOwn(fields, subjectField) && !reads.includes(subjectField) && reads.push(subjectField),
1594
+ reads;
1595
+ }
1596
+
1563
1597
  function rethrowNamingDefinition({err: err, definition: definition, key: key}) {
1564
- rethrowWithContext(err, `start.${key} on definition "${definition.name ?? "<unnamed>"}" failed to evaluate (deploy validation rejects this was the definition written around it?)`);
1598
+ rethrowWithContext(err, `start.${key} on definition "${definition.name ?? "<unnamed>"}" failed to evaluate (check the predicate and its evaluation inputs)`);
1565
1599
  }
1566
1600
 
1567
- function startContextParams({definition: definition, scope: scope, fields: fields}) {
1601
+ function startContextParams({definition: definition, scope: scope, fields: fields, dataset: dataset}) {
1602
+ const subject = fields === void 0 ? scope?.subject : startSubject(definition, fields) ?? scope?.subject, params = baseStartParams(definition, scope);
1603
+ return fields !== void 0 && (params.fields = fields), subject !== void 0 && (params[SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR] = subjectHasInFlightInstance(dataset, subject)),
1604
+ params;
1605
+ }
1606
+
1607
+ function baseStartParams(definition, scope) {
1568
1608
  return {
1569
1609
  ...definition.name !== void 0 ? {
1570
1610
  definition: definition.name
@@ -1574,13 +1614,33 @@ function startContextParams({definition: definition, scope: scope, fields: field
1574
1614
  } : {},
1575
1615
  ...scope?.now !== void 0 ? {
1576
1616
  now: scope.now
1577
- } : {},
1578
- ...fields !== void 0 ? {
1579
- fields: fields
1580
1617
  } : {}
1581
1618
  };
1582
1619
  }
1583
1620
 
1621
+ function readsSubjectHasInFlightInstance(groq) {
1622
+ return conditionParameterNames(groq).has(SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR);
1623
+ }
1624
+
1625
+ function startSubject(definition, fields) {
1626
+ const subjectEntry = (definition.fields ?? []).find(isSubjectEntry);
1627
+ if (subjectEntry === void 0) return;
1628
+ const value = fields[subjectEntry.name];
1629
+ return isGdr(value) ? value.id : void 0;
1630
+ }
1631
+
1632
+ function subjectHasInFlightInstance(dataset, subject) {
1633
+ return dataset.some(row => {
1634
+ if (typeof row != "object" || row === null) return !1;
1635
+ const instance = row;
1636
+ return instance._type !== WORKFLOW_INSTANCE_TYPE || instance.completedAt !== void 0 || !Array.isArray(instance.fields) ? !1 : instance.fields.some(entry => {
1637
+ if (typeof entry != "object" || entry === null) return !1;
1638
+ const field = entry;
1639
+ return field._type === "subject" && isGdr(field.value) && field.value.id === subject;
1640
+ });
1641
+ });
1642
+ }
1643
+
1584
1644
  async function evaluateDeclaredStartFilter(args) {
1585
1645
  const {definition: definition, document: document, scope: scope} = args, filter = definition.start?.filter;
1586
1646
  return filter === void 0 ? !0 : evaluateStartFilter({
@@ -1716,9 +1776,9 @@ function overlayInstanceInSnapshot(snapshot, instance) {
1716
1776
 
1717
1777
  function resolveFieldRead(args) {
1718
1778
  const {kind: kind, value: value, path: path, snapshot: snapshot, targetKind: targetKind} = args;
1719
- if (kind === "doc.ref") {
1779
+ if (isSingleDocRefKind(kind)) {
1720
1780
  if (!isGdr(value)) return null;
1721
- if (path === void 0 && targetKind === "doc.ref") return value;
1781
+ if (path === void 0 && targetKind !== void 0 && isSingleDocRefKind(targetKind)) return value;
1722
1782
  const base = derefBase(value, snapshot);
1723
1783
  return path === void 0 ? base : walkDocPath(base, path);
1724
1784
  }
@@ -1891,7 +1951,7 @@ function instanceDocId(tag) {
1891
1951
 
1892
1952
  function mapFieldRefValues(args) {
1893
1953
  const {entryType: entryType, value: value, fields: fields, of: of, mapRef: mapRef} = args;
1894
- return value == null ? value : entryType === "doc.ref" || entryType === "release.ref" ? mapRef(value) : entryType === "doc.refs" ? mapItems(value, mapRef) : entryType === "object" ? mapRowRefValues({
1954
+ return value == null ? value : isSingleDocRefKind(entryType) || entryType === "release.ref" ? mapRef(value) : entryType === "doc.refs" ? mapItems(value, mapRef) : entryType === "object" ? mapRowRefValues({
1895
1955
  row: value,
1896
1956
  shapes: fields ?? [],
1897
1957
  mapRef: mapRef
@@ -2097,6 +2157,27 @@ class RequiredFieldNotProvidedError extends WorkflowError {
2097
2157
  }
2098
2158
  }
2099
2159
 
2160
+ class InitialFieldsInvalidError extends WorkflowError {
2161
+ definition;
2162
+ issues;
2163
+ constructor(args) {
2164
+ const where = args.definition === void 0 ? "" : ` for workflow "${args.definition}"`, lines = args.issues.map(formatInitialFieldIssue).join(`\n`);
2165
+ super("initial-fields-invalid", `Initial fields${where} contain rows the engine cannot consume:\n${lines}\nRemove or correct every listed row before retrying.`),
2166
+ this.name = "InitialFieldsInvalidError", args.definition !== void 0 && (this.definition = args.definition),
2167
+ this.issues = args.issues;
2168
+ }
2169
+ }
2170
+
2171
+ function formatInitialFieldIssue(issue) {
2172
+ const row = ` - row ${issue.index}: ${issue.name} (${issue.type})`;
2173
+ if (issue.reason === "duplicate") return `${row} duplicates rows ${issue.duplicateIndexes.join(", ")}`;
2174
+ if (issue.reason === "undeclared") return `${row} is not declared by the workflow`;
2175
+ if (issue.reason === "wrong-kind") return `${row} has the wrong kind; expected ${issue.expectedTypes.join(" or ")}`;
2176
+ if (issue.reason === "not-input") return `${row} is ${issue.source}-sourced, not caller-input-sourced`;
2177
+ const scope = issue.scope === "activity" ? `activity "${issue.activity}" in stage "${issue.stage}"` : `stage "${issue.stage}"`;
2178
+ return `${row} targets ${scope}, not workflow scope (declared as ${issue.declaredType})`;
2179
+ }
2180
+
2100
2181
  class WorkflowStateDivergedError extends WorkflowError {
2101
2182
  instanceId;
2102
2183
  guardError;
@@ -2220,10 +2301,28 @@ function validateActionParams({action: action, activityName: activityName, calle
2220
2301
  });
2221
2302
  continue;
2222
2303
  }
2223
- present && (checkParamType(value, decl) || issues.push({
2304
+ if (!present) continue;
2305
+ if (!checkParamType(value, decl)) {
2306
+ issues.push({
2307
+ param: decl.name,
2308
+ reason: `expected type=${decl.type}, got ${typeof value}`
2309
+ });
2310
+ continue;
2311
+ }
2312
+ const choiceIssues = choiceValueIssues(decl.options, value);
2313
+ choiceIssues !== void 0 && issues.push({
2224
2314
  param: decl.name,
2225
- reason: `expected type=${decl.type}, got ${typeof value}`
2226
- }));
2315
+ reason: choiceIssues.join("; ")
2316
+ });
2317
+ const validationIssues = scalarValidationIssues({
2318
+ entryType: decl.type,
2319
+ validation: decl.validation,
2320
+ value: value
2321
+ });
2322
+ validationIssues !== void 0 && issues.push({
2323
+ param: decl.name,
2324
+ reason: validationIssues.join("; ")
2325
+ });
2227
2326
  }
2228
2327
  if (issues.length > 0) throw new ActionParamsInvalidError({
2229
2328
  action: action.name,
@@ -2333,7 +2432,10 @@ function validateEffectOps(ops, effectName) {
2333
2432
  const result = v.safeParse(v.array(StoredFieldOpSchema), ops);
2334
2433
  if (!result.success) throw new EffectOpsInvalidError({
2335
2434
  effect: effectName,
2336
- issues: formatIssues(result.issues)
2435
+ issues: formatIssues(result.issues, issue => {
2436
+ const path = issue.path;
2437
+ return issue.input === void 0 && path?.at(-2)?.key === "target" && path.at(-1)?.key === "scope" ? "Effect completion field ops require target.scope: 'workflow' | 'stage'." : issue.message;
2438
+ })
2337
2439
  });
2338
2440
  const activityScoped = result.output.find(op => op.target.scope === "activity");
2339
2441
  if (activityScoped !== void 0) throw new EffectOpsInvalidError({
@@ -2414,9 +2516,16 @@ function entryShape(entry) {
2414
2516
  fields: entry.fields
2415
2517
  } : entry._type === "array" ? {
2416
2518
  of: entry.of
2417
- } : entry._type === "doc.ref" || entry._type === "doc.refs" ? entry.types !== void 0 ? {
2519
+ } : isSingleDocRefEntry(entry) || entry._type === "doc.refs" ? entry.types !== void 0 ? {
2418
2520
  types: entry.types
2419
- } : {} : {};
2521
+ } : {} : {
2522
+ ...entry.options !== void 0 ? {
2523
+ options: entry.options
2524
+ } : {},
2525
+ ...entry.validation !== void 0 ? {
2526
+ validation: entry.validation
2527
+ } : {}
2528
+ };
2420
2529
  }
2421
2530
 
2422
2531
  function entrySlot(entry) {
@@ -2655,10 +2764,12 @@ function resolveOpValue(args) {
2655
2764
  }
2656
2765
 
2657
2766
  function readEntryFromMutation(ctx, src) {
2658
- const scopes = src.scope !== void 0 ? [ src.scope ] : [ "stage", "workflow" ], stageEntry = findOpenStageEntry(ctx.mutation);
2767
+ const scopes = src.scope !== void 0 ? [ src.scope ] : [ "activity", "stage", "workflow" ], stageEntry = findOpenStageEntry(ctx.mutation);
2659
2768
  for (const scope of scopes) {
2660
- const entry = (scope === "workflow" ? ctx.mutation.fields : stageEntry?.fields)?.find(s => s.name === src.field);
2661
- if (entry !== void 0 && entry.value !== void 0) return entry;
2769
+ let host;
2770
+ scope === "workflow" ? host = ctx.mutation.fields : scope === "stage" ? host = stageEntry?.fields : host = findCurrentActivityEntry(ctx.mutation, ctx.activityName)?.fields;
2771
+ const entry = host?.find(s => s.name === src.field);
2772
+ if (entry !== void 0) return entry;
2662
2773
  }
2663
2774
  }
2664
2775
 
@@ -3099,53 +3210,6 @@ async function assertInstanceWriteAllowed(args) {
3099
3210
  });
3100
3211
  }
3101
3212
 
3102
- const DATA_MODEL_VERSION = 1, DATA_MODEL_MIN_READER = 0, MODEL_STAMP = {
3103
- modelVersion: DATA_MODEL_VERSION,
3104
- minReaderModel: DATA_MODEL_MIN_READER
3105
- };
3106
-
3107
- function fieldTreeShape(value) {
3108
- if (Array.isArray(value)) return value.map(fieldTreeShape);
3109
- if (value === null) return "null";
3110
- if (typeof value == "object") {
3111
- const record = value;
3112
- return Object.fromEntries(Object.keys(record).toSorted().map(key => [ key, fieldTreeShape(record[key]) ]));
3113
- }
3114
- return typeof value;
3115
- }
3116
-
3117
- function modelVersionOf(doc) {
3118
- const stamp = doc.modelVersion;
3119
- return typeof stamp == "number" ? stamp : 0;
3120
- }
3121
-
3122
- function minReaderModelOf(doc) {
3123
- const floor = doc.minReaderModel;
3124
- return typeof floor == "number" ? floor : modelVersionOf(doc);
3125
- }
3126
-
3127
- class ModelVersionAheadError extends WorkflowError {
3128
- documentId;
3129
- documentModelVersion;
3130
- requiredReaderModel;
3131
- engineModelVersion;
3132
- constructor(args) {
3133
- super("model-version-ahead", `Document "${args.documentId}" was written by engine data model ${args.documentModelVersion} and requires a reader at model ${args.requiredReaderModel} or newer; this engine reads up to model ${DATA_MODEL_VERSION}. Upgrade @sanity/workflow-engine to a version that understands it.`),
3134
- this.name = "ModelVersionAheadError", this.documentId = args.documentId, this.documentModelVersion = args.documentModelVersion,
3135
- this.requiredReaderModel = args.requiredReaderModel, this.engineModelVersion = DATA_MODEL_VERSION;
3136
- }
3137
- }
3138
-
3139
- function assertReadableModel(doc) {
3140
- const requiredReaderModel = minReaderModelOf(doc);
3141
- if (requiredReaderModel > DATA_MODEL_VERSION) throw new ModelVersionAheadError({
3142
- documentId: doc._id,
3143
- documentModelVersion: modelVersionOf(doc),
3144
- requiredReaderModel: requiredReaderModel
3145
- });
3146
- return doc;
3147
- }
3148
-
3149
3213
  async function renderConditionScope(source, opts) {
3150
3214
  const {instance: instance, definition: definition, snapshot: snapshot, now: now} = source, base = buildParams({
3151
3215
  instance: instance,
@@ -3519,7 +3583,7 @@ function instanceWatchesDocument(instance, document) {
3519
3583
  }
3520
3584
 
3521
3585
  function entryDocRefs(entries) {
3522
- return fieldEntries(entries).flatMap(entry => entry._type === "doc.ref" ? isGdr(entry.value) ? [ entry.value ] : [] : entry._type === "doc.refs" ? Array.isArray(entry.value) ? entry.value.filter(isGdr) : [] : []);
3586
+ return fieldEntries(entries).flatMap(entry => typeof entry._type == "string" && isSingleDocRefKind(entry._type) ? isGdr(entry.value) ? [ entry.value ] : [] : entry._type === "doc.refs" ? Array.isArray(entry.value) ? entry.value.filter(isGdr) : [] : []);
3523
3587
  }
3524
3588
 
3525
3589
  function entryReleaseRefs(entries) {
@@ -3527,7 +3591,7 @@ function entryReleaseRefs(entries) {
3527
3591
  }
3528
3592
 
3529
3593
  function entrySubjectRefs(entries) {
3530
- return fieldEntries(entries).flatMap(entry => (entry._type === "doc.ref" || entry._type === "release.ref") && isGdr(entry.value) ? [ entry.value ] : []);
3594
+ return fieldEntries(entries).flatMap(entry => (typeof entry._type == "string" && isSingleDocRefKind(entry._type) || entry._type === "release.ref") && isGdr(entry.value) ? [ entry.value ] : []);
3531
3595
  }
3532
3596
 
3533
3597
  function fieldEntries(entries) {
@@ -3550,7 +3614,13 @@ function perspectiveFromReleaseValue(value) {
3550
3614
 
3551
3615
  async function resolveDeclaredFields(args) {
3552
3616
  const {entryDefs: entryDefs, initialFields: initialFields, ctx: ctx, randomKey: randomKey2} = args;
3553
- if (entryDefs === void 0 || entryDefs.length === 0) return [];
3617
+ if (assertInitialFieldsConsumable({
3618
+ workflowFields: entryDefs ?? [],
3619
+ initialFields: initialFields,
3620
+ ...ctx.definitionName !== void 0 ? {
3621
+ definitionName: ctx.definitionName
3622
+ } : {}
3623
+ }), entryDefs === void 0 || entryDefs.length === 0) return [];
3554
3624
  assertRequiredInputProvided({
3555
3625
  entryDefs: entryDefs,
3556
3626
  initialFields: initialFields,
@@ -3572,6 +3642,83 @@ async function resolveDeclaredFields(args) {
3572
3642
  return out;
3573
3643
  }
3574
3644
 
3645
+ function initialFieldIssues(args) {
3646
+ const duplicateIndexes = /* @__PURE__ */ new Map;
3647
+ return args.initialFields.forEach((field, index) => {
3648
+ const key = `${field.name}\0${field.type}`, indexes = duplicateIndexes.get(key) ?? [];
3649
+ indexes.push(index), duplicateIndexes.set(key, indexes);
3650
+ }), args.initialFields.flatMap((field, index) => {
3651
+ const issues = [], indexes = duplicateIndexes.get(`${field.name}\0${field.type}`) ?? [];
3652
+ indexes.length > 1 && issues.push({
3653
+ index: index,
3654
+ name: field.name,
3655
+ type: field.type,
3656
+ reason: "duplicate",
3657
+ duplicateIndexes: indexes.filter(candidate => candidate !== index)
3658
+ });
3659
+ const workflowMatches = args.workflowFields.filter(entry => entry.name === field.name);
3660
+ if (workflowMatches.length > 0) {
3661
+ const exact = workflowMatches.find(entry => entry.type === field.type);
3662
+ return exact === void 0 ? issues.push({
3663
+ index: index,
3664
+ name: field.name,
3665
+ type: field.type,
3666
+ reason: "wrong-kind",
3667
+ expectedTypes: [ ...new Set(workflowMatches.map(entry => entry.type)) ]
3668
+ }) : exact.initialValue?.type !== "input" && issues.push({
3669
+ index: index,
3670
+ name: field.name,
3671
+ type: field.type,
3672
+ reason: "not-input",
3673
+ source: exact.initialValue?.type ?? "working-memory"
3674
+ }), issues;
3675
+ }
3676
+ const scoped = findNonWorkflowDeclaration(args.stages ?? [], field.name);
3677
+ return scoped !== void 0 ? issues.push({
3678
+ index: index,
3679
+ name: field.name,
3680
+ type: field.type,
3681
+ reason: "invalid-scope",
3682
+ ...scoped
3683
+ }) : issues.push({
3684
+ index: index,
3685
+ name: field.name,
3686
+ type: field.type,
3687
+ reason: "undeclared"
3688
+ }), issues;
3689
+ });
3690
+ }
3691
+
3692
+ function findNonWorkflowDeclaration(stages, name) {
3693
+ for (const stage of stages) {
3694
+ const stageField = stage.fields?.find(entry => entry.name === name);
3695
+ if (stageField !== void 0) return {
3696
+ scope: "stage",
3697
+ stage: stage.name,
3698
+ declaredType: stageField.type
3699
+ };
3700
+ for (const activity of stage.activities ?? []) {
3701
+ const activityField = activity.fields?.find(entry => entry.name === name);
3702
+ if (activityField !== void 0) return {
3703
+ scope: "activity",
3704
+ stage: stage.name,
3705
+ activity: activity.name,
3706
+ declaredType: activityField.type
3707
+ };
3708
+ }
3709
+ }
3710
+ }
3711
+
3712
+ function assertInitialFieldsConsumable(args) {
3713
+ const issues = initialFieldIssues(args);
3714
+ if (issues.length !== 0) throw new InitialFieldsInvalidError({
3715
+ ...args.definitionName !== void 0 ? {
3716
+ definition: args.definitionName
3717
+ } : {},
3718
+ issues: issues
3719
+ });
3720
+ }
3721
+
3575
3722
  function missingRequiredInputs(args) {
3576
3723
  return args.entryDefs.filter(entry => entry.required === !0 && isInputSourced(entry)).filter(entry => {
3577
3724
  const match = suppliedFieldFor(entry, args.initialFields);
@@ -3711,6 +3858,12 @@ function buildResolvedEntry({entry: entry, value: value, _key: _key, now: now})
3711
3858
  ...entry.description !== void 0 ? {
3712
3859
  description: entry.description
3713
3860
  } : {},
3861
+ ...entry.options !== void 0 ? {
3862
+ options: entry.options
3863
+ } : {},
3864
+ ...entry.validation !== void 0 ? {
3865
+ validation: entry.validation
3866
+ } : {},
3714
3867
  value: value,
3715
3868
  ...entry.initialValue?.type === "query" ? {
3716
3869
  resolvedAt: now
@@ -3740,7 +3893,9 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
3740
3893
  value: value,
3741
3894
  types: entry.types,
3742
3895
  fields: entry.fields,
3743
- of: entry.of
3896
+ of: entry.of,
3897
+ options: entry.options,
3898
+ validation: entry.validation
3744
3899
  });
3745
3900
  return issues !== void 0 ? (ctx.recordDiscard?.({
3746
3901
  field: entry.name,
@@ -3763,7 +3918,9 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
3763
3918
  value: value,
3764
3919
  types: entry.types,
3765
3920
  fields: entry.fields,
3766
- of: entry.of
3921
+ of: entry.of,
3922
+ options: entry.options,
3923
+ validation: entry.validation
3767
3924
  }), entry.initialValue?.type === "input" && ctx.inputProvenance !== "definition" && assertRefsWithinSurface({
3768
3925
  entryType: entry.type,
3769
3926
  entryName: entry.name,
@@ -3786,8 +3943,8 @@ function fieldMapFromResolved(entries) {
3786
3943
  }
3787
3944
 
3788
3945
  function assertInputValueShape(entry, value) {
3789
- if (entry.type === "doc.ref") {
3790
- assertGdrShape(value, `field entry "${entry.name}" (doc.ref)`);
3946
+ if (isSingleDocRefKind(entry.type)) {
3947
+ assertGdrShape(value, `field entry "${entry.name}" (${entry.type})`);
3791
3948
  return;
3792
3949
  }
3793
3950
  if (entry.type === "release.ref") {
@@ -3810,7 +3967,7 @@ function assertGdrShape(value, context) {
3810
3967
  }
3811
3968
 
3812
3969
  function normalizeQueryResult({entryType: entryType, raw: raw, workflowResource: workflowResource}) {
3813
- return raw == null ? raw : entryType === "doc.ref" ? coerceToGdr(raw, workflowResource) : entryType === "doc.refs" ? Array.isArray(raw) ? raw.map(item => coerceToGdr(item, workflowResource)).filter(v2 => v2 !== null) : [] : raw;
3970
+ return raw == null ? raw : isSingleDocRefKind(entryType) ? coerceToGdr(raw, workflowResource) : entryType === "doc.refs" ? Array.isArray(raw) ? raw.map(item => coerceToGdr(item, workflowResource)).filter(v2 => v2 !== null) : [] : raw;
3814
3971
  }
3815
3972
 
3816
3973
  function coerceGdrShape(raw, workflowResource) {
@@ -3841,11 +3998,21 @@ function coerceToGdr(raw, workflowResource) {
3841
3998
  } : null;
3842
3999
  }
3843
4000
 
3844
- const EFFECT_RUN_STATUSES = [ "done", "failed", "cancelled" ], NonEmpty = NonEmptyString, UnknownRecord = v.record(v.string(), v.unknown()), PersistedFieldShapeSchema = v.lazy(() => v.looseObject(tolerantEntries()({
4001
+ const EFFECT_RUN_STATUSES = [ "done", "failed", "cancelled" ], NonEmpty = NonEmptyString, UnknownRecord = v.record(v.string(), v.unknown()), PersistedChoiceOptionsSchema = v.looseObject({
4002
+ list: v.array(v.looseObject({
4003
+ title: v.string(),
4004
+ value: v.union([ v.string(), v.number() ])
4005
+ }))
4006
+ }), PersistedScalarValidationSchema = v.looseObject({
4007
+ min: v.optional(v.number()),
4008
+ max: v.optional(v.number())
4009
+ }), PersistedFieldShapeSchema = v.lazy(() => v.looseObject(tolerantEntries()({
3845
4010
  type: v.picklist(FIELD_VALUE_KINDS),
3846
4011
  name: NonEmpty,
3847
4012
  title: v.optional(v.string()),
3848
4013
  description: v.optional(v.string()),
4014
+ options: v.optional(PersistedChoiceOptionsSchema),
4015
+ validation: v.optional(PersistedScalarValidationSchema),
3849
4016
  fields: v.optional(v.array(PersistedFieldShapeSchema)),
3850
4017
  of: v.optional(v.array(PersistedFieldShapeSchema))
3851
4018
  }))), ExecutionContextSchema = tolerantObject()({
@@ -3875,6 +4042,8 @@ function fieldArm(kind, value) {
3875
4042
  name: NonEmpty,
3876
4043
  title: v.exactOptional(v.string()),
3877
4044
  description: v.exactOptional(v.string()),
4045
+ options: v.exactOptional(PersistedChoiceOptionsSchema),
4046
+ validation: v.exactOptional(PersistedScalarValidationSchema),
3878
4047
  value: value,
3879
4048
  resolvedAt: v.exactOptional(IsoTimestamp)
3880
4049
  };
@@ -3886,6 +4055,9 @@ const OptionalRefTypes = v.exactOptional(v.array(v.string())), ResolvedFieldEntr
3886
4055
  })), v.looseObject(tolerantEntries()({
3887
4056
  ...fieldArm("doc.refs", fieldValueSchemas["doc.refs"]),
3888
4057
  types: OptionalRefTypes
4058
+ })), v.looseObject(tolerantEntries()({
4059
+ ...fieldArm("subject", fieldValueSchemas.subject),
4060
+ types: OptionalRefTypes
3889
4061
  })), v.looseObject(tolerantEntries()(fieldArm("release.ref", fieldValueSchemas["release.ref"]))), v.looseObject(tolerantEntries()(fieldArm("string", fieldValueSchemas.string))), v.looseObject(tolerantEntries()(fieldArm("text", fieldValueSchemas.text))), v.looseObject(tolerantEntries()(fieldArm("number", fieldValueSchemas.number))), v.looseObject(tolerantEntries()(fieldArm("boolean", fieldValueSchemas.boolean))), v.looseObject(tolerantEntries()(fieldArm("date", fieldValueSchemas.date))), v.looseObject(tolerantEntries()(fieldArm("datetime", fieldValueSchemas.datetime))), v.looseObject(tolerantEntries()(fieldArm("url", fieldValueSchemas.url))), v.looseObject(tolerantEntries()(fieldArm("actor", fieldValueSchemas.actor))), v.looseObject(tolerantEntries()(fieldArm("assignee", fieldValueSchemas.assignee))), v.looseObject(tolerantEntries()(fieldArm("assignees", fieldValueSchemas.assignees))), v.looseObject(tolerantEntries()({
3890
4062
  ...fieldArm("object", v.union([ v.null(), UnknownRecord ])),
3891
4063
  fields: v.array(PersistedFieldShapeSchema)
@@ -4211,14 +4383,12 @@ function buildInstanceBase(args) {
4211
4383
  ...actor !== void 0 ? {
4212
4384
  actor: actor
4213
4385
  } : {}
4214
- }, ...args.extraHistory ?? [] ], history = executionContext !== void 0 ? stampHistoryEntries(entries, executionContext) : entries;
4215
- return {
4386
+ }, ...args.extraHistory ?? [] ], history = executionContext !== void 0 ? stampHistoryEntries(entries, executionContext) : entries, body = {
4216
4387
  _id: id,
4217
4388
  _type: WORKFLOW_INSTANCE_TYPE,
4218
4389
  _rev: "",
4219
4390
  _createdAt: now,
4220
4391
  _updatedAt: now,
4221
- ...MODEL_STAMP,
4222
4392
  tag: args.tag,
4223
4393
  workflowResource: args.workflowResource,
4224
4394
  definition: args.definitionName,
@@ -4242,6 +4412,13 @@ function buildInstanceBase(args) {
4242
4412
  startedAt: now,
4243
4413
  lastChangedAt: now
4244
4414
  };
4415
+ return {
4416
+ ...body,
4417
+ ...modelStampFor({
4418
+ documentType: "instance",
4419
+ document: body
4420
+ })
4421
+ };
4245
4422
  }
4246
4423
 
4247
4424
  async function hydrateSnapshot(args) {
@@ -4922,11 +5099,7 @@ function dedupById(guards) {
4922
5099
  return [ ...new Map(guards.map(g => [ g._id, g ])).values() ].sort((a, b) => a._id.localeCompare(b._id));
4923
5100
  }
4924
5101
 
4925
- const GUARD_OWNER = "robot:workflow-engine", GUARD_LIFTED_PREDICATE = "true";
4926
-
4927
- function isGuardLifted(guard) {
4928
- return guard.predicate === GUARD_LIFTED_PREDICATE;
4929
- }
5102
+ const GUARD_OWNER = "robot:workflow-engine";
4930
5103
 
4931
5104
  function resolveGuardRoute(guard, ctx) {
4932
5105
  const targets = resolveIdRefTargets(guard.match.idRefs, ctx);
@@ -5054,15 +5227,30 @@ async function deployStageGuards(args) {
5054
5227
  }
5055
5228
 
5056
5229
  async function retractStageGuards(args) {
5230
+ const observed = [];
5231
+ for (const {client: client, guardId: guardId} of resolvedStageGuardRoutes(args)) {
5232
+ const guard = await client.getDocument(guardId, {
5233
+ tag: REQUEST_TAG.guardRetract
5234
+ });
5235
+ if (guard) {
5236
+ if (guard._rev === void 0) throw new Error(`Cannot retract guard ${guardId}: persisted document has no revision`);
5237
+ observed.push({
5238
+ client: client,
5239
+ guardId: guardId,
5240
+ predicate: guard.predicate,
5241
+ revision: guard._rev
5242
+ });
5243
+ }
5244
+ }
5057
5245
  const live = await committedInstance(args);
5058
- if (live !== void 0 && !(live.currentStage === args.stageName && live.abortedAt === void 0)) for (const {client: client, guardId: guardId} of resolvedStageGuardRoutes(args)) await client.getDocument(guardId, {
5059
- tag: REQUEST_TAG.guardRetract
5060
- }) && await client.patch(guardId).set({
5061
- predicate: GUARD_LIFTED_PREDICATE
5062
- }).commit({
5063
- ...SYNC_COMMIT,
5064
- tag: REQUEST_TAG.guardRetract
5065
- });
5246
+ if (live !== void 0 && !(live.currentStage === args.stageName && live.abortedAt === void 0)) for (const {client: client, guardId: guardId, predicate: predicate, revision: revision} of observed) {
5247
+ const revisionCheck = client.patch(guardId).set({
5248
+ predicate: predicate
5249
+ }).ifRevisionId(revision);
5250
+ await client.transaction().patch(revisionCheck).delete(guardId).commit({
5251
+ tag: REQUEST_TAG.guardRetract
5252
+ });
5253
+ }
5066
5254
  }
5067
5255
 
5068
5256
  async function deleteOrphanedDefinitionGuards(args) {
@@ -5592,7 +5780,7 @@ async function resolveContextHandoff({ctx: ctx, sub: sub, parentScope: parentSco
5592
5780
  }
5593
5781
 
5594
5782
  function canonicaliseSpawnValue({kind: kind, value: value, cx: cx}) {
5595
- return kind === "doc.ref" ? coerceSpawnGdr(value, cx) : kind === "doc.refs" && Array.isArray(value) ? value.map(v2 => coerceSpawnGdr(v2, cx)).filter(v2 => v2 !== null) : value;
5783
+ return isSingleDocRefKind(kind) ? coerceSpawnGdr(value, cx) : kind === "doc.refs" && Array.isArray(value) ? value.map(v2 => coerceSpawnGdr(v2, cx)).filter(v2 => v2 !== null) : value;
5596
5784
  }
5597
5785
 
5598
5786
  function assertBareIdRootsCorrectly(id, cx) {
@@ -6318,6 +6506,9 @@ async function evaluateEditableFields(args) {
6318
6506
  ...site.title !== void 0 ? {
6319
6507
  title: site.title
6320
6508
  } : {},
6509
+ ...site.validation !== void 0 ? {
6510
+ validation: site.validation
6511
+ } : {},
6321
6512
  value: value,
6322
6513
  editable: reason === void 0,
6323
6514
  ...reason !== void 0 ? {
@@ -6543,7 +6734,7 @@ function triggeredActionVerdict({action: action, when: when, insights: insights}
6543
6734
  },
6544
6735
  ...insights
6545
6736
  }) : {
6546
- action: action,
6737
+ ...actionEvaluationIdentity(action),
6547
6738
  allowed: !1,
6548
6739
  triggered: !0,
6549
6740
  disabledReason: {
@@ -6589,12 +6780,21 @@ function fireableActionVerdict({args: args, insights: insights}) {
6589
6780
  },
6590
6781
  ...insights
6591
6782
  }) : {
6592
- action: action,
6783
+ ...actionEvaluationIdentity(action),
6593
6784
  allowed: !0,
6594
6785
  ...insights
6595
6786
  };
6596
6787
  }
6597
6788
 
6789
+ function actionEvaluationIdentity(action) {
6790
+ return {
6791
+ action: action,
6792
+ ...action.semantics !== void 0 ? {
6793
+ semantics: action.semantics
6794
+ } : {}
6795
+ };
6796
+ }
6797
+
6598
6798
  async function instanceGuardReason({instance: instance, actor: actor, guards: guards}) {
6599
6799
  if (guards === void 0 || guards.length === 0) return;
6600
6800
  const denied = await instanceWriteDenials({
@@ -6609,15 +6809,8 @@ async function instanceGuardReason({instance: instance, actor: actor, guards: gu
6609
6809
  }
6610
6810
 
6611
6811
  function lifecycleReason({instance: instance, status: status, stageHasExits: stageHasExits}) {
6612
- const terminal = terminalState(instance);
6613
- if (terminal === "aborted" && instance.abortedAt !== void 0) return {
6614
- kind: "instance-aborted",
6615
- abortedAt: instance.abortedAt
6616
- };
6617
- if (terminal === "completed" && instance.completedAt !== void 0) return {
6618
- kind: "instance-completed",
6619
- completedAt: instance.completedAt
6620
- };
6812
+ const terminalReason = instanceTerminalReason(instance);
6813
+ if (terminalReason !== void 0) return terminalReason;
6621
6814
  if (!stageHasExits) return {
6622
6815
  kind: "stage-terminal",
6623
6816
  stage: instance.currentStage
@@ -6630,7 +6823,7 @@ function lifecycleReason({instance: instance, status: status, stageHasExits: sta
6630
6823
 
6631
6824
  function disabled(args) {
6632
6825
  return {
6633
- action: args.action,
6826
+ ...actionEvaluationIdentity(args.action),
6634
6827
  allowed: !1,
6635
6828
  disabledReason: args.reason,
6636
6829
  ...args.insight !== void 0 ? {
@@ -7441,9 +7634,7 @@ function startMutation(instance) {
7441
7634
  }
7442
7635
 
7443
7636
  function instanceStateFields(src) {
7444
- const fields = {
7445
- modelVersion: DATA_MODEL_VERSION,
7446
- minReaderModel: Math.max(src.minReaderModel, DATA_MODEL_MIN_READER),
7637
+ const state = {
7447
7638
  currentStage: src.currentStage,
7448
7639
  fields: src.fields,
7449
7640
  stages: src.stages,
@@ -7452,10 +7643,22 @@ function instanceStateFields(src) {
7452
7643
  effectHistory: src.effectHistory,
7453
7644
  context: src.context,
7454
7645
  history: src.history,
7455
- processedRequests: src.processedRequests ?? []
7646
+ processedRequests: src.processedRequests ?? [],
7647
+ ...src.completedAt !== void 0 ? {
7648
+ completedAt: src.completedAt
7649
+ } : {},
7650
+ ...src.abortedAt !== void 0 ? {
7651
+ abortedAt: src.abortedAt
7652
+ } : {}
7653
+ };
7654
+ return {
7655
+ ...modelStampFor({
7656
+ documentType: "instance",
7657
+ document: state,
7658
+ storedMinReaderModel: src.minReaderModel
7659
+ }),
7660
+ ...state
7456
7661
  };
7457
- return src.completedAt !== void 0 && (fields.completedAt = src.completedAt), src.abortedAt !== void 0 && (fields.abortedAt = src.abortedAt),
7458
- fields;
7459
7662
  }
7460
7663
 
7461
7664
  function liveViewContext(ctx, mutation) {
@@ -7667,16 +7870,7 @@ function validateEffectOutputs(args) {
7667
7870
  issues.push(`"${key}" is not a declared output`);
7668
7871
  continue;
7669
7872
  }
7670
- const shapeIssues = checkFieldValue({
7671
- entryType: shape.type,
7672
- value: value,
7673
- ...shape.fields !== void 0 ? {
7674
- fields: shape.fields
7675
- } : {},
7676
- ...shape.of !== void 0 ? {
7677
- of: shape.of
7678
- } : {}
7679
- });
7873
+ const shapeIssues = effectOutputIssues(shape, value);
7680
7874
  shapeIssues !== void 0 && issues.push(...shapeIssues.map(i => `"${key}": ${i}`));
7681
7875
  }
7682
7876
  if (issues.length > 0) throw new EffectOutputsInvalidError({
@@ -7685,6 +7879,25 @@ function validateEffectOutputs(args) {
7685
7879
  });
7686
7880
  }
7687
7881
 
7882
+ function effectOutputIssues(shape, value) {
7883
+ return checkFieldValue({
7884
+ entryType: shape.type,
7885
+ value: value,
7886
+ ...shape.fields !== void 0 ? {
7887
+ fields: shape.fields
7888
+ } : {},
7889
+ ...shape.of !== void 0 ? {
7890
+ of: shape.of
7891
+ } : {},
7892
+ ...shape.options !== void 0 ? {
7893
+ options: shape.options
7894
+ } : {},
7895
+ ...shape.validation !== void 0 ? {
7896
+ validation: shape.validation
7897
+ } : {}
7898
+ });
7899
+ }
7900
+
7688
7901
  function requirePendingEffect(instance, effectKey) {
7689
7902
  const pending = instance.pendingEffects.find(e => e._key === effectKey);
7690
7903
  if (pending !== void 0) return pending;
@@ -7905,7 +8118,7 @@ async function sortByDependencies({client: client, definitions: definitions, tag
7905
8118
  byName.set(def.name, def);
7906
8119
  }
7907
8120
  const findInBatch = ref => findRefInBatch(byName, ref);
7908
- return await assertCrossBatchRefsDeployed({
8121
+ return await assertSpawnContracts({
7909
8122
  client: client,
7910
8123
  definitions: definitions,
7911
8124
  ctx: {
@@ -7921,31 +8134,76 @@ function findRefInBatch(byName, ref) {
7921
8134
  if (typeof ref.version != "number") return byName.get(ref.name);
7922
8135
  }
7923
8136
 
7924
- async function assertCrossBatchRefsDeployed({client: client, definitions: definitions, ctx: ctx}) {
7925
- const missing = [];
7926
- for (const def of definitions) for (const ref of refsOf(def)) {
7927
- if (ctx.findInBatch(ref) !== void 0) continue;
7928
- const label = await resolveDeployedRefLabel({
8137
+ async function assertSpawnContracts({client: client, definitions: definitions, ctx: ctx}) {
8138
+ const missing = [], invalidHandoffs = [];
8139
+ for (const def of definitions) for (const spawn of spawnSitesOf(def)) {
8140
+ const ref = logicalRefOf(spawn.definition), child = ctx.findInBatch(ref) ?? await resolveDeployedRef({
7929
8141
  client: client,
7930
8142
  ref: ref,
7931
8143
  tag: ctx.tag
7932
8144
  });
7933
- label !== void 0 && missing.push({
7934
- from: def.name,
7935
- ref: label
7936
- });
8145
+ if (child === void 0) {
8146
+ missing.push({
8147
+ reason: "unresolved-definition",
8148
+ from: def.name,
8149
+ ref: logicalRefLabel(ref)
8150
+ });
8151
+ continue;
8152
+ }
8153
+ for (const field of Object.keys(spawn.with ?? {})) {
8154
+ const entry = (child.fields ?? []).find(candidate => candidate.name === field);
8155
+ entry === void 0 ? invalidHandoffs.push({
8156
+ reason: "unconsumable-field",
8157
+ from: def.name,
8158
+ child: child.name,
8159
+ field: field,
8160
+ detail: "the child declares no workflow field with that name"
8161
+ }) : isInputSourced(entry) || invalidHandoffs.push({
8162
+ reason: "unconsumable-field",
8163
+ from: def.name,
8164
+ child: child.name,
8165
+ field: field,
8166
+ detail: `the child field is ${entry.initialValue?.type ?? "working-memory"}-sourced, not input-sourced`
8167
+ });
8168
+ }
7937
8169
  }
7938
- if (missing.length === 0) return;
7939
- const lines = missing.map(m => ` - ${m.from} → ${m.ref} (neither in batch nor deployed)`);
7940
- throw new Error(`workflow.deployDefinitions: ${missing.length} unresolved reference${missing.length === 1 ? "" : "s"}:\n` + lines.join(`\n`));
8170
+ if (missing.length === 0 && invalidHandoffs.length === 0) return;
8171
+ if (invalidHandoffs.length === 0) {
8172
+ const lines2 = missing.map(issue => ` - ${issue.from} ${issue.ref} (neither in batch nor deployed)`);
8173
+ throw new Error(`workflow.deployDefinitions: ${missing.length} unresolved reference${missing.length === 1 ? "" : "s"}:\n` + lines2.join(`\n`));
8174
+ }
8175
+ const issues = [ ...missing, ...invalidHandoffs ], lines = [ ...missing.map(m => ` - ${m.from} → ${m.ref} (neither in batch nor deployed)`), ...invalidHandoffs.map(issue => ` - ${issue.from} → ${issue.child}: spawn.with["${issue.field}"] cannot be consumed — ${issue.detail}`) ], count = lines.length;
8176
+ throw new SpawnContractsInvalidError({
8177
+ issues: issues,
8178
+ message: `workflow.deployDefinitions: ${count} invalid spawn contract${count === 1 ? "" : "s"}:\n` + lines.join(`\n`)
8179
+ });
7941
8180
  }
7942
8181
 
7943
- async function resolveDeployedRefLabel({client: client, ref: ref, tag: tag}) {
8182
+ async function resolveDeployedRef({client: client, ref: ref, tag: tag}) {
7944
8183
  const wantsExplicit = typeof ref.version == "number", params = {
7945
8184
  definition: ref.name,
7946
8185
  tag: tag
7947
8186
  };
7948
- if (wantsExplicit && (params.version = ref.version), !await client.fetch(definitionLookupGroq(wantsExplicit), params)) return wantsExplicit ? `${ref.name} v${ref.version}` : ref.name;
8187
+ wantsExplicit && (params.version = ref.version);
8188
+ const doc = await client.fetch(definitionLookupGroq(wantsExplicit), params);
8189
+ if (doc) return parseDefinitionInput(doc, `workflow.deployDefinitions child "${logicalRefLabel(ref)}"`);
8190
+ }
8191
+
8192
+ function logicalRefLabel(ref) {
8193
+ return typeof ref.version == "number" ? `${ref.name} v${ref.version}` : ref.name;
8194
+ }
8195
+
8196
+ function logicalRefOf(ref) {
8197
+ return {
8198
+ name: ref.name,
8199
+ ...ref.version !== void 0 ? {
8200
+ version: ref.version
8201
+ } : {}
8202
+ };
8203
+ }
8204
+
8205
+ function spawnSitesOf(def) {
8206
+ return def.stages.flatMap(stage => stage.activities ?? []).flatMap(activity => activity.actions ?? []).flatMap(action => action.spawn === void 0 ? [] : [ action.spawn ]);
7949
8207
  }
7950
8208
 
7951
8209
  function topoSortDefinitions(definitions, ctx) {
@@ -7965,12 +8223,7 @@ function topoSortDefinitions(definitions, ctx) {
7965
8223
  }
7966
8224
 
7967
8225
  function refsOf(def) {
7968
- return def.stages.flatMap(stage => stage.activities ?? []).flatMap(activity => activity.actions ?? []).flatMap(action => action.spawn === void 0 ? [] : [ action.spawn.definition ]).map(ref => ({
7969
- name: ref.name,
7970
- ...ref.version !== void 0 ? {
7971
- version: ref.version
7972
- } : {}
7973
- }));
8226
+ return spawnSitesOf(def).map(spawn => logicalRefOf(spawn.definition));
7974
8227
  }
7975
8228
 
7976
8229
  function hashDefinitionContent(def) {
@@ -7993,7 +8246,10 @@ function planDefinitionDeploy({def: def, latest: latest, target: target}) {
7993
8246
  tag: target.tag,
7994
8247
  version: version,
7995
8248
  contentHash: contentHash,
7996
- ...MODEL_STAMP
8249
+ ...modelStampFor({
8250
+ documentType: "definition",
8251
+ document: expanded
8252
+ })
7997
8253
  };
7998
8254
  return {
7999
8255
  status: unchanged ? "unchanged" : "create",
@@ -8836,6 +9092,7 @@ async function fetchStartSlice(args) {
8836
9092
 
8837
9093
  const workflow = {
8838
9094
  deployDefinitions: async rawArgs => {
9095
+ assertReaderModelAcknowledgement(rawArgs.expectedMinReaderModel);
8839
9096
  const args = taggedScope(rawArgs, REQUEST_TAG.deploy), {client: client, tag: tag, resourceAliases: resourceAliases} = args;
8840
9097
  validateTag(tag);
8841
9098
  const definitions = args.definitions.map(def => parseDefinitionInput(def, "workflow.deployDefinitions"));
@@ -8908,8 +9165,8 @@ const workflow = {
8908
9165
  }), result;
8909
9166
  },
8910
9167
  startInstance: async rawArgs => {
8911
- const args = taggedScope(rawArgs, REQUEST_TAG.start), {client: client, tag: tag, workflowResource: workflowResource, definition: definitionName, version: version, initialFields: initialFields, ancestors: ancestors, context: context, instanceId: instanceId, perspective: perspective, executionContext: executionContext} = args, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = await resolveOperationContext(args), clock = args.clock ?? wallClock, seedFields = initialFields ?? [], existing = instanceId !== void 0 ? await getInstanceDocument(client, instanceId) : void 0;
8912
- if (existing !== void 0 && existing.tag === tag) return resumeStart({
9168
+ const args = taggedScope(rawArgs, REQUEST_TAG.start), {client: client, tag: tag, definition: definitionName, version: version, initialFields: initialFields, instanceId: instanceId, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = operationContext, clock = args.clock ?? wallClock, seedFields = initialFields ?? [], existing = instanceId !== void 0 ? await getInstanceDocument(client, instanceId) : void 0;
9169
+ return existing !== void 0 && existing.tag === tag ? resumeStart({
8913
9170
  client: client,
8914
9171
  tag: tag,
8915
9172
  existing: existing,
@@ -8926,105 +9183,12 @@ const workflow = {
8926
9183
  ...args.telemetry !== void 0 ? {
8927
9184
  telemetry: args.telemetry
8928
9185
  } : {}
8929
- });
8930
- const definition = await loadDefinition({
8931
- client: client,
8932
- definition: definitionName,
8933
- version: version,
8934
- tag: tag
8935
- }), id = instanceId ?? instanceDocId(tag);
8936
- if (definition.stages.find(s => s.name === definition.initialStage) === void 0) throw new Error(`Initial stage "${definition.initialStage}" missing in ${definitionName} v${definition.version}`);
8937
- const now = clock();
8938
- if (assertRequiredInputProvided({
8939
- entryDefs: definition.fields ?? [],
8940
- initialFields: seedFields,
8941
- definitionName: definition.name
8942
- }), definition.start?.allowed !== void 0) {
8943
- const insight = await startAllowedInsight({
8944
- client: client,
8945
- tag: tag,
8946
- definition: definition,
8947
- allowed: definition.start.allowed,
8948
- initialFields: seedFields,
8949
- now: now
8950
- });
8951
- if (insight.outcome !== "satisfied") throw new StartNotAllowedError({
8952
- definition: definition.name,
8953
- insight: insight
8954
- });
8955
- }
8956
- const contextEntries = context ? toContextEntries(context) : [], fieldDiscards = [], resolvedFields = await resolveDeclaredFields({
8957
- entryDefs: definition.fields ?? [],
8958
- initialFields: seedFields,
8959
- ctx: {
8960
- client: client,
8961
- now: now,
8962
- selfId: id,
8963
- tag: tag,
8964
- workflowResource: workflowResource,
8965
- definitionName: definition.name,
8966
- refSurface: refSurface,
8967
- ...perspective !== void 0 ? {
8968
- perspective: perspective
8969
- } : {},
8970
- recordDiscard: recordFieldDiscards({
8971
- target: fieldDiscards,
8972
- scope: "workflow",
8973
- at: now
8974
- })
8975
- },
8976
- randomKey: randomKey
8977
- }), effectivePerspective = perspective ?? derivePerspectiveFromFields(resolvedFields), base = buildInstanceBase({
8978
- id: id,
8979
- now: now,
8980
- tag: tag,
8981
- workflowResource: workflowResource,
8982
- definitionName: definition.name,
8983
- pinnedVersion: definition.version,
8984
- pinnedContentHash: definition.contentHash,
8985
- definition: definition,
8986
- fields: resolvedFields,
8987
- context: contextEntries,
8988
- ancestors: ancestors ?? [],
8989
- perspective: effectivePerspective,
8990
- initialStage: definition.initialStage,
8991
- actor: actor,
8992
- executionContext: resolveExecutionContext(executionContext),
8993
- ...fieldDiscards.length > 0 ? {
8994
- extraHistory: fieldDiscards
8995
- } : {}
8996
- });
8997
- await client.create(base, SYNC_COMMIT);
8998
- const cascaded = await settleStart({
8999
- client: client,
9000
- tag: tag,
9001
- instanceId: id,
9002
- actor: actor,
9003
- clientForGdr: clientForGdr,
9004
- refSurface: refSurface,
9186
+ }) : startFreshInstance({
9187
+ args: args,
9188
+ operationContext: operationContext,
9005
9189
  clock: clock,
9006
- ...executionContext !== void 0 ? {
9007
- executionContext: executionContext
9008
- } : {},
9009
- ...args.telemetry !== void 0 ? {
9010
- telemetry: args.telemetry
9011
- } : {},
9012
- emitStarted: () => resolveTelemetry(args.telemetry).log(WorkflowInstanceStarted, instanceStartedData({
9013
- definition: definition,
9014
- instanceId: id,
9015
- initialFieldCount: seedFields.length,
9016
- viaSpawn: !1
9017
- }))
9190
+ seedFields: seedFields
9018
9191
  });
9019
- return {
9020
- instance: await reload({
9021
- client: client,
9022
- instanceId: id,
9023
- tag: tag
9024
- }),
9025
- cascaded: cascaded,
9026
- changed: !0
9027
- };
9028
9192
  },
9029
9193
  fireAction: async rawArgs => {
9030
9194
  const args = taggedScope(rawArgs, REQUEST_TAG.fireAction), {client: client, tag: tag, workflowResource: workflowResource, instanceId: instanceId, activity: activity, action: action, params: params, idempotent: idempotent, resourceClients: resourceClients, grantsFromPath: grantsFromPath, executionContext: executionContext} = args;
@@ -9510,7 +9674,7 @@ const workflow = {
9510
9674
  return (await client.fetch(query, params)).map(readInstanceDoc).filter(instance => instanceWatchesDocument(instance, document));
9511
9675
  },
9512
9676
  definitionsForDocument: async rawArgs => {
9513
- const args = taggedScope(rawArgs, REQUEST_TAG.definitionsForDocument), {client: client, tag: tag, document: document} = args;
9677
+ const args = taggedScope(rawArgs, REQUEST_TAG.definitionsForDocument), {client: client, tag: tag, document: document, subject: subject} = args;
9514
9678
  validateTag(tag);
9515
9679
  const clock = args.clock ?? wallClock, deployed = (await client.fetch(definitionsListGroq("desc"), {
9516
9680
  tag: tag
@@ -9522,6 +9686,9 @@ const workflow = {
9522
9686
  scope: {
9523
9687
  tag: tag,
9524
9688
  now: clock(),
9689
+ ...subject !== void 0 ? {
9690
+ subject: subject
9691
+ } : {},
9525
9692
  fetchDataset: () => slice ??= fetchStartSlice({
9526
9693
  client: client,
9527
9694
  tag: tag
@@ -9537,20 +9704,29 @@ const workflow = {
9537
9704
  definition: definitionName,
9538
9705
  version: version,
9539
9706
  tag: tag
9707
+ }), invalidInitialFields = initialFieldIssues({
9708
+ workflowFields: definition.fields ?? [],
9709
+ stages: definition.stages,
9710
+ initialFields: initialFields ?? []
9540
9711
  }), missingRequired = missingRequiredInputs({
9541
9712
  entryDefs: definition.fields ?? [],
9542
9713
  initialFields: initialFields ?? []
9543
9714
  }), allowed = definition.start?.allowed;
9544
9715
  if (allowed === void 0) return {
9545
- allowed: !0,
9716
+ allowed: invalidInitialFields.length === 0,
9546
9717
  outcome: "satisfied",
9547
9718
  unboundReads: [],
9548
- missingRequired: missingRequired
9719
+ missingRequired: missingRequired,
9720
+ invalidInitialFields: invalidInitialFields
9549
9721
  };
9550
- const unboundReads = unboundAllowedReads(allowed, startFieldsParam({
9551
- entryDefs: definition.fields ?? [],
9552
- initialFields: initialFields ?? []
9553
- })), insight = await startAllowedInsight({
9722
+ const unboundReads = unboundAllowedReadsWithSubject({
9723
+ allowed: allowed,
9724
+ fields: startFieldsParam({
9725
+ entryDefs: definition.fields ?? [],
9726
+ initialFields: initialFields ?? []
9727
+ }),
9728
+ definition: definition
9729
+ }), insight = await startAllowedInsight({
9554
9730
  client: client,
9555
9731
  tag: tag,
9556
9732
  definition: definition,
@@ -9559,11 +9735,12 @@ const workflow = {
9559
9735
  now: clock()
9560
9736
  }), provisional = unboundReads.length > 0;
9561
9737
  return {
9562
- allowed: !provisional && insight.outcome === "satisfied",
9738
+ allowed: invalidInitialFields.length === 0 && !provisional && insight.outcome === "satisfied",
9563
9739
  outcome: provisional ? "unevaluable" : insight.outcome,
9564
9740
  insight: insight,
9565
9741
  unboundReads: unboundReads,
9566
- missingRequired: missingRequired
9742
+ missingRequired: missingRequired,
9743
+ invalidInitialFields: invalidInitialFields
9567
9744
  };
9568
9745
  },
9569
9746
  permissions: {
@@ -9593,6 +9770,239 @@ async function startAllowedInsight(args) {
9593
9770
  });
9594
9771
  }
9595
9772
 
9773
+ async function startFreshInstance(args) {
9774
+ const {args: startArgs, operationContext: operationContext, clock: clock, seedFields: seedFields} = args, {client: client, tag: tag, workflowResource: workflowResource, definition: definitionName, version: version, ancestors: ancestors, context: context, instanceId: instanceId, perspective: perspective, executionContext: executionContext} = startArgs, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = operationContext, definition = await loadDefinition({
9775
+ client: client,
9776
+ definition: definitionName,
9777
+ version: version,
9778
+ tag: tag
9779
+ }), id = instanceId ?? instanceDocId(tag);
9780
+ assertInitialStageExists(definition);
9781
+ const now = clock();
9782
+ await assertStartInputs({
9783
+ client: client,
9784
+ tag: tag,
9785
+ definition: definition,
9786
+ initialFields: seedFields,
9787
+ now: now
9788
+ });
9789
+ const {resolvedFields: resolvedFields, fieldDiscards: fieldDiscards} = await resolveStartFields({
9790
+ client: client,
9791
+ tag: tag,
9792
+ workflowResource: workflowResource,
9793
+ definition: definition,
9794
+ initialFields: seedFields,
9795
+ id: id,
9796
+ now: now,
9797
+ refSurface: refSurface,
9798
+ ...perspective !== void 0 ? {
9799
+ perspective: perspective
9800
+ } : {}
9801
+ }), base = buildInstanceBase({
9802
+ id: id,
9803
+ now: now,
9804
+ tag: tag,
9805
+ workflowResource: workflowResource,
9806
+ definitionName: definition.name,
9807
+ pinnedVersion: definition.version,
9808
+ pinnedContentHash: definition.contentHash,
9809
+ definition: definition,
9810
+ fields: resolvedFields,
9811
+ context: context ? toContextEntries(context) : [],
9812
+ ancestors: ancestors ?? [],
9813
+ perspective: perspective ?? derivePerspectiveFromFields(resolvedFields),
9814
+ initialStage: definition.initialStage,
9815
+ actor: actor,
9816
+ executionContext: resolveExecutionContext(executionContext),
9817
+ ...fieldDiscards.length > 0 ? {
9818
+ extraHistory: fieldDiscards
9819
+ } : {}
9820
+ });
9821
+ await client.create(base, SYNC_COMMIT);
9822
+ const cascaded = await settleStart({
9823
+ client: client,
9824
+ tag: tag,
9825
+ instanceId: id,
9826
+ actor: actor,
9827
+ clientForGdr: clientForGdr,
9828
+ refSurface: refSurface,
9829
+ clock: clock,
9830
+ ...executionContext !== void 0 ? {
9831
+ executionContext: executionContext
9832
+ } : {},
9833
+ ...startArgs.telemetry !== void 0 ? {
9834
+ telemetry: startArgs.telemetry
9835
+ } : {},
9836
+ emitStarted: () => resolveTelemetry(startArgs.telemetry).log(WorkflowInstanceStarted, instanceStartedData({
9837
+ definition: definition,
9838
+ instanceId: id,
9839
+ initialFieldCount: seedFields.length,
9840
+ viaSpawn: !1
9841
+ }))
9842
+ });
9843
+ return {
9844
+ instance: await reload({
9845
+ client: client,
9846
+ instanceId: id,
9847
+ tag: tag
9848
+ }),
9849
+ cascaded: cascaded,
9850
+ changed: !0
9851
+ };
9852
+ }
9853
+
9854
+ function assertInitialStageExists(definition) {
9855
+ if (!definition.stages.some(stage => stage.name === definition.initialStage)) throw new Error(`Initial stage "${definition.initialStage}" missing in ${definition.name} v${definition.version}`);
9856
+ }
9857
+
9858
+ async function assertStartInputs(args) {
9859
+ const {client: client, tag: tag, definition: definition, initialFields: initialFields, now: now} = args;
9860
+ assertInitialFieldsConsumable({
9861
+ workflowFields: definition.fields ?? [],
9862
+ stages: definition.stages,
9863
+ initialFields: initialFields,
9864
+ definitionName: definition.name
9865
+ }), assertRequiredInputProvided({
9866
+ entryDefs: definition.fields ?? [],
9867
+ initialFields: initialFields,
9868
+ definitionName: definition.name
9869
+ });
9870
+ const allowed = definition.start?.allowed;
9871
+ if (allowed === void 0) return;
9872
+ const insight = await startAllowedInsight({
9873
+ client: client,
9874
+ tag: tag,
9875
+ definition: definition,
9876
+ allowed: allowed,
9877
+ initialFields: initialFields,
9878
+ now: now
9879
+ });
9880
+ if (insight.outcome !== "satisfied") throw new StartNotAllowedError({
9881
+ definition: definition.name,
9882
+ insight: insight
9883
+ });
9884
+ }
9885
+
9886
+ async function resolveStartFields(args) {
9887
+ const {client: client, tag: tag, workflowResource: workflowResource, definition: definition, initialFields: initialFields, id: id, now: now, refSurface: refSurface, perspective: perspective} = args, fieldDiscards = [];
9888
+ return {
9889
+ resolvedFields: await resolveDeclaredFields({
9890
+ entryDefs: definition.fields ?? [],
9891
+ initialFields: initialFields,
9892
+ ctx: {
9893
+ client: client,
9894
+ now: now,
9895
+ selfId: id,
9896
+ tag: tag,
9897
+ workflowResource: workflowResource,
9898
+ definitionName: definition.name,
9899
+ refSurface: refSurface,
9900
+ ...perspective !== void 0 ? {
9901
+ perspective: perspective
9902
+ } : {},
9903
+ recordDiscard: recordFieldDiscards({
9904
+ target: fieldDiscards,
9905
+ scope: "workflow",
9906
+ at: now
9907
+ })
9908
+ },
9909
+ randomKey: randomKey
9910
+ }),
9911
+ fieldDiscards: fieldDiscards
9912
+ };
9913
+ }
9914
+
9915
+ function isRecord(value) {
9916
+ return typeof value == "object" && value !== null && !Array.isArray(value);
9917
+ }
9918
+
9919
+ function isClientProjectUser(value) {
9920
+ return isRecord(value) && typeof value.id == "string" && (value.displayName === void 0 || typeof value.displayName == "string") && (value.email === void 0 || typeof value.email == "string") && (value.imageUrl === void 0 || value.imageUrl === null || typeof value.imageUrl == "string");
9921
+ }
9922
+
9923
+ function objectProperty(value, property) {
9924
+ if (!isRecord(value)) return;
9925
+ const propertyValue = value[property];
9926
+ return typeof propertyValue == "object" && propertyValue !== null ? propertyValue : void 0;
9927
+ }
9928
+
9929
+ function stringProperty(value, property) {
9930
+ const propertyValue = Reflect.get(value, property);
9931
+ return typeof propertyValue == "string" ? propertyValue : void 0;
9932
+ }
9933
+
9934
+ function apiErrorType(error) {
9935
+ const response = objectProperty(error, "response"), body = objectProperty(response, "body");
9936
+ if (!body) return;
9937
+ const nestedError = objectProperty(body, "error");
9938
+ return (nestedError ? stringProperty(nestedError, "type") : void 0) ?? stringProperty(body, "type");
9939
+ }
9940
+
9941
+ function isProjectUserNotFoundError(error) {
9942
+ return apiErrorType(error) === "projectUserNotFoundError";
9943
+ }
9944
+
9945
+ function clientProjectUserDirectory(client, projectId) {
9946
+ return {
9947
+ findById: async id => {
9948
+ if (!client.request) return {
9949
+ status: "inaccessible",
9950
+ cause: new Error("Project-user resolution requires WorkflowClient.request")
9951
+ };
9952
+ try {
9953
+ const response = await client.request({
9954
+ uri: `/projects/${encodeURIComponent(projectId)}/users/${encodeURIComponent(id)}`
9955
+ }), candidate = Array.isArray(response) ? response[0] : response;
9956
+ return candidate == null ? {
9957
+ status: "missing"
9958
+ } : isClientProjectUser(candidate) ? {
9959
+ status: "resolved",
9960
+ user: candidate
9961
+ } : {
9962
+ status: "inaccessible",
9963
+ cause: new Error("Project-user response had an invalid shape")
9964
+ };
9965
+ } catch (cause) {
9966
+ return isProjectUserNotFoundError(cause) ? {
9967
+ status: "missing"
9968
+ } : {
9969
+ status: "inaccessible",
9970
+ cause: cause
9971
+ };
9972
+ }
9973
+ }
9974
+ };
9975
+ }
9976
+
9977
+ function resolveClientActor(client, args) {
9978
+ return resolveActor(clientProjectUserDirectory(client, args.projectId), args.actor);
9979
+ }
9980
+
9981
+ async function resolveActor(directory, actor) {
9982
+ if (actor.kind !== "person") return {
9983
+ status: "not-person",
9984
+ actor: actor
9985
+ };
9986
+ const personActor = {
9987
+ ...actor,
9988
+ kind: "person"
9989
+ }, lookup = await directory.findById(personActor.id);
9990
+ return lookup.status === "resolved" ? {
9991
+ status: "resolved",
9992
+ actor: personActor,
9993
+ user: lookup.user
9994
+ } : lookup.status === "inaccessible" ? {
9995
+ status: "inaccessible",
9996
+ actor: personActor,
9997
+ ...lookup.cause === void 0 ? {} : {
9998
+ cause: lookup.cause
9999
+ }
10000
+ } : {
10001
+ status: "missing",
10002
+ actor: personActor
10003
+ };
10004
+ }
10005
+
9596
10006
  const DEFAULT_EFFECT_LEASE_MS = 300 * 1e3;
9597
10007
 
9598
10008
  function isClaimExpired(claim, now) {
@@ -9735,11 +10145,11 @@ function isCancelledCompletion(data) {
9735
10145
  }
9736
10146
 
9737
10147
  async function drainEffectsInternal(args) {
9738
- const {tag: tag, workflowResource: workflowResource, instanceId: instanceId, effectHandlers: effectHandlers, missingHandler: missingHandler, logger: logger} = args, cascadeTelemetry = drainCascadeTelemetry(args.telemetry), {client: client, resourceClients: resourceClients} = taggedScope(args, REQUEST_TAG.drain), leaseMs = args.leaseMs ?? DEFAULT_EFFECT_LEASE_MS, clock = args.clock ?? wallClock, routeGdr = buildClientForGdr({
9739
- client: client,
10148
+ const {tag: tag, workflowResource: workflowResource, instanceId: instanceId, effectHandlers: effectHandlers, missingHandler: missingHandler, logger: logger, handlerClient: handlerClient, handlerResourceClients: handlerResourceClients} = args, cascadeTelemetry = drainCascadeTelemetry(args.telemetry), {client: client, resourceClients: resourceClients} = taggedScope(args, REQUEST_TAG.drain), leaseMs = args.leaseMs ?? DEFAULT_EFFECT_LEASE_MS, clock = args.clock ?? wallClock, routeGdr = buildClientForGdr({
10149
+ client: handlerClient,
9740
10150
  workflowResource: workflowResource,
9741
- resourceClients: resourceClients
9742
- }), clientFor = ref => withRequestTag(routeGdr(parseGdr(typeof ref == "string" ? ref : ref.id)), REQUEST_TAG.effect), {actor: drainerActor} = await resolveAccess(client), executionContext = args.executionContext;
10151
+ resourceClients: handlerResourceClients
10152
+ }), clientFor = ref => routeGdr(parseGdr(typeof ref == "string" ? ref : ref.id)), {actor: drainerActor} = await resolveAccess(client), executionContext = args.executionContext;
9743
10153
  validateTag(tag);
9744
10154
  const log = logger("drainEffects"), buckets = {
9745
10155
  drained: [],
@@ -9785,6 +10195,7 @@ async function drainEffectsInternal(args) {
9785
10195
  handler: handler,
9786
10196
  candidate: candidate,
9787
10197
  client: client,
10198
+ handlerClient: handlerClient,
9788
10199
  tag: tag,
9789
10200
  workflowResource: workflowResource,
9790
10201
  ...resourceClients !== void 0 ? {
@@ -9810,11 +10221,11 @@ function findClaimableCandidate({instance: instance, now: now, skippedKeys: skip
9810
10221
  }
9811
10222
 
9812
10223
  async function dispatchAndReport(args) {
9813
- const {handler: handler, candidate: candidate, client: client, tag: tag, workflowResource: workflowResource, resourceClients: resourceClients, instanceId: instanceId, clientFor: clientFor, logger: logger, log: log, executionContext: executionContext, telemetry: telemetry, clock: clock} = args, {outputs: outputs, ops: ops, dispatchError: dispatchError} = await dispatchEffect({
10224
+ const {handler: handler, candidate: candidate, client: client, handlerClient: handlerClient, tag: tag, workflowResource: workflowResource, resourceClients: resourceClients, instanceId: instanceId, clientFor: clientFor, logger: logger, log: log, executionContext: executionContext, telemetry: telemetry, clock: clock} = args, {outputs: outputs, ops: ops, dispatchError: dispatchError} = await dispatchEffect({
9814
10225
  handler: handler,
9815
10226
  candidate: candidate,
9816
10227
  ctx: {
9817
- client: client,
10228
+ client: handlerClient,
9818
10229
  clientFor: clientFor,
9819
10230
  instanceId: instanceId,
9820
10231
  logger: logger
@@ -9920,7 +10331,7 @@ async function claimPendingEffect({client: client, instance: instance, candidate
9920
10331
  async function dispatchEffect({handler: handler, candidate: candidate, ctx: ctx}) {
9921
10332
  try {
9922
10333
  const result = await handler(candidate.params, {
9923
- client: withRequestTag(ctx.client, REQUEST_TAG.effect),
10334
+ client: ctx.client,
9924
10335
  clientFor: ctx.clientFor,
9925
10336
  instanceId: ctx.instanceId,
9926
10337
  effectKey: candidate._key,
@@ -10414,6 +10825,7 @@ function createEngine(args) {
10414
10825
  missingHandler: missingHandler,
10415
10826
  logger: logger,
10416
10827
  telemetry: telemetry,
10828
+ resolveActor: rest => resolveClientActor(client, rest),
10417
10829
  deployDefinitions: async rest => {
10418
10830
  const result = await workflow.deployDefinitions(withScope(rest));
10419
10831
  return logDeployWarnings(result, logger), result;
@@ -10454,6 +10866,10 @@ function createEngine(args) {
10454
10866
  drainEffects: async ({instanceId: instanceId}) => {
10455
10867
  const result = await drainEffectsInternal({
10456
10868
  client: client,
10869
+ handlerClient: args.client,
10870
+ ...args.resourceClients !== void 0 ? {
10871
+ handlerResourceClients: args.resourceClients
10872
+ } : {},
10457
10873
  tag: tag,
10458
10874
  workflowResource: workflowResource,
10459
10875
  ...optionalScope,
@@ -10650,6 +11066,7 @@ function attributeMember({member: member, group: group, chain: chain}) {
10650
11066
  }
10651
11067
 
10652
11068
  function diffEntry({def: rawDef, latestRaw: latestRaw, target: target}) {
11069
+ assertReaderModelAcknowledgement(target.expectedMinReaderModel);
10653
11070
  const def = parseDefinitionInput(rawDef, "diffEntry"), plan = planDefinitionDeploy({
10654
11071
  def: def,
10655
11072
  latest: asLatest(latestRaw),
@@ -10681,6 +11098,7 @@ function asLatest(raw) {
10681
11098
  }
10682
11099
 
10683
11100
  async function computeDiffEntries({client: client, defs: defs, target: target}) {
11101
+ assertReaderModelAcknowledgement(target.expectedMinReaderModel);
10684
11102
  const entries = [];
10685
11103
  for (const rawDef of defs) {
10686
11104
  const def = parseDefinitionInput(rawDef, "computeDiffEntries"), latest = await loadLatestDeployed({
@@ -10702,7 +11120,7 @@ function buildInitialFields({declared: declared, values: values}) {
10702
11120
  return Object.entries(values).map(([name, value]) => {
10703
11121
  const entry = declared.find(f => f.name === name);
10704
11122
  if (entry === void 0) throw new Error(settable.length > 0 ? `workflow declares no field "${name}" — input fields: ${settableNames}` : `workflow declares no field "${name}" — it declares no input fields at all`);
10705
- if (entry.initialValue?.type !== "input") throw new Error(`field "${name}" is not input-sourced the engine would silently ignore the value. ` + (settable.length > 0 ? `Input fields: ${settableNames}` : "This workflow has no input fields."));
11123
+ if (entry.initialValue?.type !== "input") throw new Error(`field "${name}" is not input-sourced and cannot accept a start value. ` + (settable.length > 0 ? `Input fields: ${settableNames}` : "This workflow has no input fields."));
10706
11124
  return {
10707
11125
  type: entry.type,
10708
11126
  name: name,
@@ -10766,7 +11184,7 @@ const HISTORY_DISPLAY = {
10766
11184
  },
10767
11185
  aborted: {
10768
11186
  title: "Instance aborted",
10769
- description: "An admin hard-stopped the instance — pending effects cancelled, stage guards lifted, abortedAt + completedAt stamped."
11187
+ description: "An admin hard-stopped the instance — pending effects cancelled, stage guards removed, abortedAt + completedAt stamped."
10770
11188
  },
10771
11189
  opApplied: {
10772
11190
  title: "Op applied",
@@ -10802,6 +11220,10 @@ const HISTORY_DISPLAY = {
10802
11220
  title: "Document references",
10803
11221
  description: "Ordered list of GDR pointers — multi-doc selection."
10804
11222
  },
11223
+ subject: {
11224
+ title: "Subject document",
11225
+ description: "Single GDR pointer at THE document the workflow is about — same value as a document reference, elevated so surfaces identify the subject by kind."
11226
+ },
10805
11227
  "release.ref": {
10806
11228
  title: "Content Release reference",
10807
11229
  description: "GDR pointer at a Content Release system doc, carrying the release name the engine derives the instance's read perspective from."
@@ -10980,4 +11402,4 @@ function displayDescription(typeKey) {
10980
11402
  if (typeKey) return DISPLAY[typeKey]?.description;
10981
11403
  }
10982
11404
 
10983
- export { ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_LIFTED_PREDICATE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, OP_DISPLAY, PartialGuardDeployError, PersistedDocShapeError, RESERVED_CONDITION_VARS, RefResourceUndeclaredError, RequiredFieldNotProvidedError, START_ALLOWED_VARS, START_FILTER_VARS, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, clientConfigFromResource, compileGuard, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, explainCondition2 as explainCondition, explainStartAllowed, extractDocumentId, fieldTreeShape, findCurrentActivityEntry, findOpenStageEntry, formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hashDefinitionContent, humanize2 as humanize, inFlightFilter, instanceDocId, instanceGuardQuery, instanceWatchesDocument, instancesQuery, isCascadeFired, isClaimExpired, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isGuardLifted, isNotesEntry, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseGdr, parseGuardDocument, parseInstanceDocument, parseResourceGdr, processShellUserProperties, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refMediaLibrary, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, resolveAccess, resolveFieldEntry$1 as resolveFieldEntry, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, schemaTreeShape, sentenceCase, silentLogger, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundAllowedReads, unsatisfiedTransitionSummaries, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };
11405
+ export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, OP_DISPLAY, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, START_ALLOWED_VARS, START_FILTER_VARS, SpawnContractsInvalidError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, clientConfigFromResource, clientProjectUserDirectory, compileGuard, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, expandResourceAliases, explainCondition2 as explainCondition, explainStartAllowed, extractDocumentId, fieldTreeShape, findCurrentActivityEntry, findOpenStageEntry, formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hashDefinitionContent, humanize2 as humanize, inFlightFilter, initialFieldIssues, instanceDocId, instanceGuardQuery, instanceWatchesDocument, instancesQuery, isCascadeFired, isClaimExpired, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseGdr, parseGuardDocument, parseInstanceDocument, parseResourceGdr, processShellUserProperties, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundAllowedReads, unsatisfiedTransitionSummaries, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };