@sanity/workflow-engine 0.26.0 → 0.28.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.
@@ -6,6 +6,41 @@ import { parse } from "groq-js";
6
6
 
7
7
  import { isDraftId, isVersionId, getPublishedId } from "@sanity/id-utils";
8
8
 
9
+ function isCascadeFired(action) {
10
+ return action.when !== void 0;
11
+ }
12
+
13
+ function deriveActivityKind(activity) {
14
+ if (activity.target !== void 0) return "manual";
15
+ const actions = activity.actions ?? [];
16
+ return actions.some(a => !isCascadeFired(a)) ? "user" : actions.some(a => (a.effects ?? []).length > 0 || a.spawn !== void 0) ? "service" : actions.length > 0 ? "receive" : "script";
17
+ }
18
+
19
+ function deriveExecutorClassification(activity) {
20
+ if (activity.target !== void 0) return "off-system";
21
+ const actions = activity.actions ?? [], cascadeFired = actions.filter(isCascadeFired).length;
22
+ return cascadeFired === actions.length ? "autonomous" : cascadeFired === 0 ? "interactive" : "hybrid";
23
+ }
24
+
25
+ function driverKind(actor) {
26
+ return actor.kind === "person" || actor.kind === "agent" ? actor.kind : "service";
27
+ }
28
+
29
+ function errorMessage(err) {
30
+ return (err instanceof Error ? err.message : String(err)).replace(/[^\P{Cc}\n\t]/gu, "");
31
+ }
32
+
33
+ function rethrowWithContext(err, context) {
34
+ throw new Error(`${context}: ${errorMessage(err)}`, {
35
+ cause: err
36
+ });
37
+ }
38
+
39
+ function andConditions(parts) {
40
+ const present = parts.filter(p => p !== void 0);
41
+ if (present.length !== 0) return present.length === 1 ? present[0] : present.map(p => `(${p})`).join(" && ");
42
+ }
43
+
9
44
  class WorkflowError extends Error {
10
45
  kind;
11
46
  constructor(kind, message, options) {
@@ -79,322 +114,6 @@ function effectNotFoundMessage(args) {
79
114
  return args.settled.status === "cancelled" ? `${base} — it was cancelled at ${args.settled.ranAt}${cause}` : `${base} — it already settled "${args.settled.status}" at ${args.settled.ranAt}${cause}`;
80
115
  }
81
116
 
82
- function errorMessage(err) {
83
- return (err instanceof Error ? err.message : String(err)).replace(/[^\P{Cc}\n\t]/gu, "");
84
- }
85
-
86
- function rethrowWithContext(err, context) {
87
- throw new Error(`${context}: ${errorMessage(err)}`, {
88
- cause: err
89
- });
90
- }
91
-
92
- const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
93
-
94
- function terminalState(instance) {
95
- return instance.abortedAt !== void 0 ? "aborted" : instance.completedAt !== void 0 ? "completed" : "in-flight";
96
- }
97
-
98
- function isUnprimed(instance) {
99
- return instance.stages.length === 0 && terminalState(instance) === "in-flight";
100
- }
101
-
102
- function parseDefinitionSnapshotValue(instance) {
103
- try {
104
- return normalizeLegacyActivityRequirements(JSON.parse(instance.definitionSnapshot));
105
- } catch (err) {
106
- rethrowWithContext(err, `Failed to parse definitionSnapshot on instance "${instance._id}"`);
107
- }
108
- }
109
-
110
- function normalizeLegacyActivityRequirements(value) {
111
- for (const stage of arrayMember(value, "stages")) for (const activity of arrayMember(stage, "activities")) normalizeLegacyRequirementMap(activity);
112
- return value;
113
- }
114
-
115
- function arrayMember(value, key) {
116
- if (typeof value != "object" || value === null) return [];
117
- const member = value[key];
118
- return Array.isArray(member) ? member : [];
119
- }
120
-
121
- function normalizeLegacyRequirementMap(value) {
122
- if (typeof value != "object" || value === null) return;
123
- const activity = value, requirements = activity.requirements;
124
- typeof requirements != "object" || requirements === null || Array.isArray(requirements) || (activity.requirements = Object.entries(requirements).map(([name, query]) => ({
125
- type: "groq",
126
- name: name,
127
- query: query
128
- })));
129
- }
130
-
131
- function parseDefinitionSnapshot(instance) {
132
- return parseDefinitionSnapshotValue(instance);
133
- }
134
-
135
- function parentRef(instance) {
136
- return instance.ancestors.at(-1);
137
- }
138
-
139
- const DATA_MODEL_VERSION = 5, DATA_MODEL_MIN_READER = 4, READER_MODEL_ROLLOUT_URL = "https://www.sanity.io/docs/editorial-workflows/prerelease";
140
-
141
- class ReaderModelAcknowledgementError extends WorkflowError {
142
- code="WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
143
- expectedMinReaderModel;
144
- engineMinReaderModel=DATA_MODEL_MIN_READER;
145
- engineModelVersion=DATA_MODEL_VERSION;
146
- documentationUrl=READER_MODEL_ROLLOUT_URL;
147
- constructor(expectedMinReaderModel, context = "Deployment") {
148
- const expected = expectedMinReaderModel === void 0 ? "missing" : String(expectedMinReaderModel);
149
- super("reader-model-acknowledgement", `${context} expected reader floor ${expected}; the installed engine requires acknowledgement ${DATA_MODEL_MIN_READER}. Do not change the acknowledgement yet: accepting ${DATA_MODEL_MIN_READER} authorizes this engine to write documents that older readers will refuse. Upgrade every Studio, CLI, MCP server, Function, and other runtime that reads engine-owned documents; verify that rollout in every environment sharing the workflow resource; then change the literal in deployment configuration and deploy the writer. Rollout guide: ${READER_MODEL_ROLLOUT_URL}`),
150
- this.name = "ReaderModelAcknowledgementError", this.expectedMinReaderModel = expectedMinReaderModel;
151
- }
152
- }
153
-
154
- function assertReaderModelAcknowledgement(expectedMinReaderModel, context) {
155
- if (typeof expectedMinReaderModel != "number" || !Number.isFinite(expectedMinReaderModel) || !Number.isInteger(expectedMinReaderModel) || expectedMinReaderModel < 0 || expectedMinReaderModel !== DATA_MODEL_MIN_READER) throw new ReaderModelAcknowledgementError(expectedMinReaderModel, context);
156
- }
157
-
158
- const DATA_MODEL_CHANGES = Object.freeze([ Object.freeze({
159
- id: "governed-model-stamps",
160
- introducedInModel: 1,
161
- minReaderModel: 0,
162
- documentTypes: Object.freeze([ "definition", "instance" ]),
163
- compatibility: "additive",
164
- applicability: "unconditional",
165
- summary: "Definition and instance documents carry model provenance and reader-floor stamps."
166
- }), Object.freeze({
167
- id: "subject-field-kind",
168
- introducedInModel: 2,
169
- minReaderModel: 0,
170
- documentTypes: Object.freeze([ "definition", "instance" ]),
171
- compatibility: "additive",
172
- applicability: "detectable",
173
- summary: "A workflow-level subject field identifies the document a workflow is about."
174
- }), Object.freeze({
175
- id: "typed-scalar-choice-lists",
176
- introducedInModel: 2,
177
- minReaderModel: 2,
178
- documentTypes: Object.freeze([ "definition", "instance" ]),
179
- compatibility: "reader-floor",
180
- applicability: "detectable",
181
- summary: "Scalar fields may constrain writes to a persisted typed choice list."
182
- }), Object.freeze({
183
- id: "action-semantics",
184
- introducedInModel: 2,
185
- minReaderModel: 0,
186
- documentTypes: Object.freeze([ "definition" ]),
187
- compatibility: "additive",
188
- applicability: "detectable",
189
- summary: "Ordinary actions may carry a closed bag of advisory workflow semantics."
190
- }), Object.freeze({
191
- id: "inclusive-scalar-bounds",
192
- introducedInModel: 2,
193
- minReaderModel: 2,
194
- documentTypes: Object.freeze([ "definition", "instance" ]),
195
- compatibility: "reader-floor",
196
- applicability: "detectable",
197
- summary: "String, text, and number values may carry persisted inclusive bounds."
198
- }), Object.freeze({
199
- id: "progress-field-kind",
200
- introducedInModel: 3,
201
- minReaderModel: 0,
202
- documentTypes: Object.freeze([ "definition", "instance" ]),
203
- compatibility: "additive",
204
- applicability: "detectable",
205
- summary: "A progress field kind carries application-defined 0–100 completion."
206
- }), Object.freeze({
207
- id: "effect-claim-tokens",
208
- introducedInModel: 3,
209
- minReaderModel: 0,
210
- documentTypes: Object.freeze([ "instance" ]),
211
- compatibility: "additive",
212
- applicability: "detectable",
213
- summary: "Pending-effect claims carry an exact-claim token gating mid-dispatch state reports."
214
- }), Object.freeze({
215
- id: "classified-principal-ids",
216
- introducedInModel: 4,
217
- minReaderModel: 4,
218
- documentTypes: Object.freeze([ "instance" ]),
219
- compatibility: "reader-floor",
220
- applicability: "unconditional",
221
- summary: "Principal ids are namespace-classified: actor and assignee writes carry the account-global user id only, and readers resolve legacy project-scoped ids through the prefix classifier at the instance read funnel."
222
- }), Object.freeze({
223
- id: "readiness-requirements",
224
- introducedInModel: 4,
225
- minReaderModel: 4,
226
- documentTypes: Object.freeze([ "definition" ]),
227
- compatibility: "reader-floor",
228
- applicability: "detectable",
229
- summary: "Start and activity readiness use named polymorphic requirement arrays."
230
- }), Object.freeze({
231
- id: "due-date-field-kinds",
232
- introducedInModel: 5,
233
- minReaderModel: 0,
234
- documentTypes: Object.freeze([ "definition", "instance" ]),
235
- compatibility: "additive",
236
- applicability: "detectable",
237
- summary: "Due-date field kinds (dueDate, dueDatetime) mark a level deadline, elevated aliases of date/datetime carrying the same stored value."
238
- }) ]);
239
-
240
- function recordOf(value) {
241
- return value !== null && typeof value == "object" && !Array.isArray(value) ? value : void 0;
242
- }
243
-
244
- function recordsAt(record, key) {
245
- const value = record[key];
246
- return Array.isArray(value) ? value.map(recordOf).filter(item => item !== void 0) : [];
247
- }
248
-
249
- function nestedFieldEntries(entries) {
250
- return entries.flatMap(entry => [ entry, ...nestedFieldEntries(recordsAt(entry, "fields")), ...nestedFieldEntries(recordsAt(entry, "of")) ]);
251
- }
252
-
253
- function parsedDefinitionSnapshot(root) {
254
- if (typeof root.definitionSnapshot == "string") return recordOf(parseDefinitionSnapshotValue({
255
- _id: typeof root._id == "string" ? root._id : "<unknown instance>",
256
- definitionSnapshot: root.definitionSnapshot
257
- }));
258
- }
259
-
260
- function persistedFieldEntries(document) {
261
- const root = recordOf(document);
262
- if (root === void 0) return [];
263
- const snapshot = parsedDefinitionSnapshot(root), roots = snapshot === void 0 ? [ root ] : [ root, snapshot ], stages = roots.flatMap(candidate => recordsAt(candidate, "stages")), activities = stages.flatMap(stage => recordsAt(stage, "activities")), actions = activities.flatMap(activity => recordsAt(activity, "actions")), effects = actions.flatMap(action => recordsAt(action, "effects"));
264
- return nestedFieldEntries([ ...roots.flatMap(candidate => recordsAt(candidate, "fields")), ...stages.flatMap(stage => recordsAt(stage, "fields")), ...activities.flatMap(activity => recordsAt(activity, "fields")), ...actions.flatMap(action => recordsAt(action, "params")), ...effects.flatMap(effect => recordsAt(effect, "outputs")) ]);
265
- }
266
-
267
- function hasChoiceList(document) {
268
- return persistedFieldEntries(document).some(entry => {
269
- const options = recordOf(entry.options);
270
- return options !== void 0 && Array.isArray(options.list);
271
- });
272
- }
273
-
274
- function hasFieldKind(document, kind) {
275
- return persistedFieldEntries(document).some(entry => entry.type === kind || entry._type === kind);
276
- }
277
-
278
- function hasActionSemantics(document) {
279
- const root = recordOf(document);
280
- return root === void 0 ? !1 : recordsAt(root, "stages").flatMap(stage => recordsAt(stage, "activities")).flatMap(activity => recordsAt(activity, "actions")).some(action => Array.isArray(action.semantics));
281
- }
282
-
283
- function hasScalarValidation(document) {
284
- return persistedFieldEntries(document).some(entry => {
285
- const validation = recordOf(entry.validation);
286
- return typeof validation?.min == "number" || typeof validation?.max == "number";
287
- });
288
- }
289
-
290
- function hasClaimTokens(document) {
291
- const root = recordOf(document);
292
- return root === void 0 ? !1 : recordsAt(root, "pendingEffects").some(entry => {
293
- const claim = recordOf(entry.claim);
294
- return claim !== void 0 && typeof claim.claimToken == "string";
295
- });
296
- }
297
-
298
- function hasReadinessRequirements(document) {
299
- const root = recordOf(document);
300
- return root === void 0 ? !1 : Array.isArray(recordOf(root.start)?.requirements) ? !0 : recordsAt(root, "stages").some(stage => recordsAt(stage, "activities").some(activity => Array.isArray(activity.requirements)));
301
- }
302
-
303
- const featureDetectors = {
304
- "governed-model-stamps": () => !0,
305
- "subject-field-kind": document => hasFieldKind(document, "subject"),
306
- "typed-scalar-choice-lists": hasChoiceList,
307
- "action-semantics": hasActionSemantics,
308
- "inclusive-scalar-bounds": hasScalarValidation,
309
- "progress-field-kind": document => hasFieldKind(document, "progress"),
310
- "effect-claim-tokens": hasClaimTokens,
311
- "classified-principal-ids": () => !0,
312
- "readiness-requirements": hasReadinessRequirements,
313
- "due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime")
314
- };
315
-
316
- function requiredModelFeatures(documentType, document) {
317
- return DATA_MODEL_CHANGES.filter(change => change.documentTypes.some(candidate => candidate === documentType) && featureDetectors[change.id](document));
318
- }
319
-
320
- function requiredReaderModel(documentType, document) {
321
- return Math.max(0, ...requiredModelFeatures(documentType, document).map(change => change.minReaderModel));
322
- }
323
-
324
- function modelStampFor(args) {
325
- return {
326
- modelVersion: DATA_MODEL_VERSION,
327
- minReaderModel: Math.max(DATA_MODEL_MIN_READER, args.storedMinReaderModel ?? 0, requiredReaderModel(args.documentType, args.document))
328
- };
329
- }
330
-
331
- function fieldTreeShape(value) {
332
- if (Array.isArray(value)) return value.map(fieldTreeShape);
333
- if (value === null) return "null";
334
- if (typeof value == "object") {
335
- const record = value;
336
- return Object.fromEntries(Object.keys(record).toSorted().map(key => [ key, fieldTreeShape(record[key]) ]));
337
- }
338
- return typeof value;
339
- }
340
-
341
- function modelVersionOf(doc) {
342
- const stamp = doc.modelVersion;
343
- return typeof stamp == "number" ? stamp : 0;
344
- }
345
-
346
- function minReaderModelOf(doc) {
347
- const floor = doc.minReaderModel;
348
- return typeof floor == "number" ? floor : modelVersionOf(doc);
349
- }
350
-
351
- class ModelVersionAheadError extends WorkflowError {
352
- documentId;
353
- documentModelVersion;
354
- requiredReaderModel;
355
- engineModelVersion;
356
- constructor(args) {
357
- 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.`),
358
- this.name = "ModelVersionAheadError", this.documentId = args.documentId, this.documentModelVersion = args.documentModelVersion,
359
- this.requiredReaderModel = args.requiredReaderModel, this.engineModelVersion = DATA_MODEL_VERSION;
360
- }
361
- }
362
-
363
- function assertReadableModel(doc) {
364
- const documentReaderModel = minReaderModelOf(doc);
365
- if (documentReaderModel > DATA_MODEL_VERSION) throw new ModelVersionAheadError({
366
- documentId: doc._id,
367
- documentModelVersion: modelVersionOf(doc),
368
- requiredReaderModel: documentReaderModel
369
- });
370
- return doc;
371
- }
372
-
373
- function isCascadeFired(action) {
374
- return action.when !== void 0;
375
- }
376
-
377
- function deriveActivityKind(activity) {
378
- if (activity.target !== void 0) return "manual";
379
- const actions = activity.actions ?? [];
380
- return actions.some(a => !isCascadeFired(a)) ? "user" : actions.some(a => (a.effects ?? []).length > 0 || a.spawn !== void 0) ? "service" : actions.length > 0 ? "receive" : "script";
381
- }
382
-
383
- function deriveExecutorClassification(activity) {
384
- if (activity.target !== void 0) return "off-system";
385
- const actions = activity.actions ?? [], cascadeFired = actions.filter(isCascadeFired).length;
386
- return cascadeFired === actions.length ? "autonomous" : cascadeFired === 0 ? "interactive" : "hybrid";
387
- }
388
-
389
- function driverKind(actor) {
390
- return actor.kind === "person" || actor.kind === "agent" ? actor.kind : "service";
391
- }
392
-
393
- function andConditions(parts) {
394
- const present = parts.filter(p => p !== void 0);
395
- if (present.length !== 0) return present.length === 1 ? present[0] : present.map(p => `(${p})`).join(" && ");
396
- }
397
-
398
117
  const KNOWN_SCHEMES = /* @__PURE__ */ new Set([ "dataset", "canvas", "media-library", "dashboard" ]), KNOWN_SCHEMES_TEXT = [ ...KNOWN_SCHEMES ].join(", ");
399
118
 
400
119
  class VersionSpecificDatasetGdrError extends Error {
@@ -4020,4 +3739,4 @@ function checkWorkflowInvariants(def) {
4020
3739
  checkStoredRolesPlacement(def, issues), checkGroups(def, issues), issues;
4021
3740
  }
4022
3741
 
4023
- export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_STATUSES, ACTOR_KINDS, ANONYMOUS_IDENTITY, ActorShape, AuthoringActionSchema, AuthoringActivitySchema, AuthoringFieldEntrySchema, AuthoringGuardSchema, AuthoringOpSchema, AuthoringStageSchema, AuthoringTransitionSchema, AuthoringWorkflowSchema, CALLER_BOUND_VARS, CONDITION_VARS, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_TRANSITION_WHEN, DOCUMENT_VALUE_PERMISSIONS, DRIVER_KINDS, DefinitionInUseError, DefinitionNotFoundError, EFFECTS_READ, EXECUTOR_CLASSIFICATIONS, EffectNotFoundError, EffectSchema, FIELD_READ, FIELD_SCOPES, FIELD_VALUE_KINDS, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GUARD_PREDICATE_VARS, GdrShape, GroupSchema, InstanceNotFoundError, IsoTimestamp, MUTATION_GUARD_ACTIONS, ModelVersionAheadError, NonEmptyString, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, RESOURCE_ALIAS_NAME_SOURCE, ReaderModelAcknowledgementError, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StoredFieldOpSchema, VersionSpecificDatasetGdrError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowConfigSchema, WorkflowError, actorFulfillsRole, andConditions, assertReadableModel, assertReaderModelAcknowledgement, checkWorkflowInvariants, choiceValueIssues, classifyPrincipalId, clientConfigFromResource, conditionEffectReads, conditionFieldReadNames, conditionParameterNames, conditionSyntaxIssues, datasetResourceParts, definitionDocId, deriveActivityKind, deriveExecutorClassification, desugarWorkflow, directoryBridgeId, driverKind, errorMessage, evaluateCondition, evaluateConditionOutcome, evaluatePredicates, extractDocumentId, fieldTreeShape, fieldValueSchemas, firstCarriedGlobalId, formatIssuePath, formatIssues, formatValidationError, gdrFromResource, gdrRef, gdrResourcePrefix, gdrUri, groq, groupMembershipNames, isBareSeedId, isCascadeFired, isGdr, isGdrUri, isGuardReadExpr, isInputSourced, isNotesEntry, isParseableInstant, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTerminalActivityStatus, isTodoListEntry, isTodoListItem, isUnevaluable, isUnprimed, labelFor, lakePrincipalId, minReaderModelOf, modelStampFor, modelVersionOf, parentRef, parseDefinitionSnapshot, parseDefinitionSnapshotValue, parseFieldValue, parseGdr, parseOrThrow, parsePersistedDoc, parseResourceGdr, parseStoredDefinition, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refTypeIssues, rejectedRefTypes, releaseDocId, releaseRef, requiredModelFeatures, requiredReaderModel, resourceAliasesToMap, resourceFromGdrUri, resourceFromParsed, resourceGdr, rethrowWithContext, runGroq, sameResource, scalarValidationIssues, schemaTreeShape, selfGdr, startKindOf, tagScopeFilter, terminalState, toBareId, toPhysicalGdr, tolerantEntries, tolerantObject, tryParseGdr, validateFieldAppendItem, validateFieldValue, validateResourceAliasName, validateTag };
3742
+ export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_STATUSES, ACTOR_KINDS, ANONYMOUS_IDENTITY, ActorShape, AuthoringActionSchema, AuthoringActivitySchema, AuthoringFieldEntrySchema, AuthoringGuardSchema, AuthoringOpSchema, AuthoringStageSchema, AuthoringTransitionSchema, AuthoringWorkflowSchema, CALLER_BOUND_VARS, CONDITION_VARS, ContractViolationError, DEFAULT_TRANSITION_WHEN, DOCUMENT_VALUE_PERMISSIONS, DRIVER_KINDS, DefinitionInUseError, DefinitionNotFoundError, EFFECTS_READ, EXECUTOR_CLASSIFICATIONS, EffectNotFoundError, EffectSchema, FIELD_READ, FIELD_SCOPES, FIELD_VALUE_KINDS, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GUARD_PREDICATE_VARS, GdrShape, GroupSchema, InstanceNotFoundError, IsoTimestamp, MUTATION_GUARD_ACTIONS, NonEmptyString, PersistedDocShapeError, RESERVED_CONDITION_VARS, RESOURCE_ALIAS_NAME_SOURCE, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StoredFieldOpSchema, VersionSpecificDatasetGdrError, WORKFLOW_DEFINITION_TYPE, WorkflowConfigSchema, WorkflowError, actorFulfillsRole, andConditions, checkWorkflowInvariants, choiceValueIssues, classifyPrincipalId, clientConfigFromResource, conditionEffectReads, conditionFieldReadNames, conditionParameterNames, conditionSyntaxIssues, datasetResourceParts, definitionDocId, deriveActivityKind, deriveExecutorClassification, desugarWorkflow, directoryBridgeId, driverKind, errorMessage, evaluateCondition, evaluateConditionOutcome, evaluatePredicates, extractDocumentId, fieldValueSchemas, firstCarriedGlobalId, formatIssuePath, formatIssues, formatValidationError, gdrFromResource, gdrRef, gdrResourcePrefix, gdrUri, groq, groupMembershipNames, isBareSeedId, isCascadeFired, isGdr, isGdrUri, isGuardReadExpr, isInputSourced, isNotesEntry, isParseableInstant, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTerminalActivityStatus, isTodoListEntry, isTodoListItem, isUnevaluable, labelFor, lakePrincipalId, parseFieldValue, parseGdr, parseOrThrow, parsePersistedDoc, parseResourceGdr, parseStoredDefinition, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refTypeIssues, rejectedRefTypes, releaseDocId, releaseRef, resourceAliasesToMap, resourceFromGdrUri, resourceFromParsed, resourceGdr, rethrowWithContext, runGroq, sameResource, scalarValidationIssues, schemaTreeShape, selfGdr, startKindOf, tagScopeFilter, toBareId, toPhysicalGdr, tolerantEntries, tolerantObject, tryParseGdr, validateFieldAppendItem, validateFieldValue, validateResourceAliasName, validateTag };
package/dist/define.cjs CHANGED
@@ -17,16 +17,11 @@ function defineWorkflow(definition) {
17
17
  }
18
18
 
19
19
  function defineWorkflowConfig(config) {
20
- const parsed = invariants.parseOrThrow({
20
+ return invariants.parseOrThrow({
21
21
  schema: invariants.WorkflowConfigSchema,
22
22
  input: config,
23
23
  label: "defineWorkflowConfig"
24
24
  });
25
- return assertDeploymentAcknowledgements(parsed), parsed;
26
- }
27
-
28
- function assertDeploymentAcknowledgements(config) {
29
- for (const [index, deployment] of config.deployments.entries()) invariants.assertReaderModelAcknowledgement(deployment.expectedMinReaderModel, `Deployment ${deployment.name || `at deployments[${index}]`}`);
30
25
  }
31
26
 
32
27
  function defineStage(stage) {
package/dist/define.d.cts CHANGED
@@ -983,6 +983,15 @@ export declare interface ConditionVar {
983
983
  */
984
984
  export declare type ConditionVarBinding = "always" | "caller" | "spawn";
985
985
 
986
+ /**
987
+ * The maximum reader floor this writer can emit. Individual documents derive
988
+ * their `minReaderModel` from the compatibility-bearing features actually
989
+ * present; a document written at {@link DATA_MODEL_VERSION} may therefore
990
+ * carry a lower floor. Raising this maximum is a declared, DATAMODEL.md-logged
991
+ * decision that requires readers-first fleet sequencing.
992
+ */
993
+ declare const DATA_MODEL_MIN_READER = 4;
994
+
986
995
  export declare function defineAction(action: AuthoringAction): AuthoringAction;
987
996
 
988
997
  export declare function defineActivity(
@@ -1043,9 +1052,18 @@ export declare function defineWorkflow(
1043
1052
  * path-prefixed error if the shape is invalid. The CLI collapses the selected
1044
1053
  * deployment's bindings via {@link resourceAliasesToMap} into the
1045
1054
  * `resourceAliases` map `deployDefinitions` expands against.
1055
+ *
1056
+ * Validates shape only — NOT the reader-floor acknowledgement. That is a
1057
+ * selected-deployment gate (`deployDefinitions`, the CLI's
1058
+ * `deploymentToTarget` / `buildBatches` / `resolveContext`, and blueprint
1059
+ * provision each assert the deployment they target), so a command that never
1060
+ * selects a deployment loads a config with a stale or missing floor on an
1061
+ * untargeted entry without failing. Authors must still acknowledge the floor
1062
+ * at compile time — each {@link WorkflowDeploymentInput} requires it; the
1063
+ * returned {@link WorkflowConfig} is the looser parsed shape.
1046
1064
  */
1047
1065
  export declare function defineWorkflowConfig(
1048
- config: WorkflowConfig,
1066
+ config: WorkflowConfigInput,
1049
1067
  ): WorkflowConfig;
1050
1068
 
1051
1069
  declare type Editable = v.InferOutput<typeof StoredEditableSchema>;
@@ -1422,11 +1440,6 @@ declare type NotesField = FieldBase<AuthoringEditable, GroupMembership> & {
1422
1440
 
1423
1441
  declare type Op = v.InferOutput<typeof StoredOpSchema>;
1424
1442
 
1425
- declare type ParsedWorkflowConfig = v.InferOutput<typeof WorkflowConfigSchema>;
1426
-
1427
- declare type ParsedWorkflowDeployment =
1428
- ParsedWorkflowConfig["deployments"][number];
1429
-
1430
1443
  declare type RequirementBase = {
1431
1444
  name: string;
1432
1445
  title?: string | undefined;
@@ -1929,8 +1942,15 @@ declare type ValueExprInternal =
1929
1942
 
1930
1943
  declare const WORKFLOW_LIFECYCLES: readonly ["standalone", "child"];
1931
1944
 
1932
- declare type WorkflowConfig = Omit<ParsedWorkflowConfig, "deployments"> & {
1933
- deployments: WorkflowDeployment[];
1945
+ declare type WorkflowConfig = v.InferOutput<typeof WorkflowConfigSchema>;
1946
+
1947
+ /**
1948
+ * What an author writes for a whole config: every deployment is a
1949
+ * {@link WorkflowDeploymentInput}. `defineWorkflowConfig` accepts this and
1950
+ * returns the looser {@link WorkflowConfig}.
1951
+ */
1952
+ declare type WorkflowConfigInput = Omit<WorkflowConfig, "deployments"> & {
1953
+ deployments: WorkflowDeploymentInput[];
1934
1954
  };
1935
1955
 
1936
1956
  declare const WorkflowConfigSchema: v.ObjectSchema<
@@ -2578,15 +2598,25 @@ declare const WorkflowDefinitionSchema: v.GenericSchema<
2578
2598
  WorkflowFields<FieldEntry, Stage, StartBlock>
2579
2599
  >;
2580
2600
 
2581
- declare type WorkflowDeployment = Omit<
2582
- ParsedWorkflowDeployment,
2601
+ /** One deployment as loaded from a config: the floor is optional/unverified so
2602
+ * a command that never selects a deployment can hold a stale or missing
2603
+ * acknowledgement. Deployment-scoped paths assert before they act; authors
2604
+ * write {@link WorkflowDeploymentInput}. */
2605
+ declare type WorkflowDeployment = WorkflowConfig["deployments"][number];
2606
+
2607
+ /**
2608
+ * What an author writes for one deployment: the current reader floor as the
2609
+ * reviewed literal. Compile-time only — omitting it or setting a wrong value
2610
+ * is a type error in the editor. Runtime parse still tolerates a stale or
2611
+ * missing floor on {@link WorkflowDeployment} so commands that never select a
2612
+ * deployment still run; deployment-scoped paths assert the selected
2613
+ * deployment (instance-id commands do not).
2614
+ */
2615
+ declare type WorkflowDeploymentInput = Omit<
2616
+ WorkflowDeployment,
2583
2617
  "expectedMinReaderModel"
2584
2618
  > & {
2585
- /**
2586
- * Reviewed numeric literal. Runtime validation owns the exact installed-floor check so a stale
2587
- * acknowledgement reaches the readers-first rollout guidance instead of becoming a type error.
2588
- */
2589
- expectedMinReaderModel: number;
2619
+ expectedMinReaderModel: typeof DATA_MODEL_MIN_READER;
2590
2620
  };
2591
2621
 
2592
2622
  /** Type-mirror of {@link workflowFields}, parameterised over field/stage/start. */
package/dist/define.d.ts CHANGED
@@ -983,6 +983,15 @@ export declare interface ConditionVar {
983
983
  */
984
984
  export declare type ConditionVarBinding = "always" | "caller" | "spawn";
985
985
 
986
+ /**
987
+ * The maximum reader floor this writer can emit. Individual documents derive
988
+ * their `minReaderModel` from the compatibility-bearing features actually
989
+ * present; a document written at {@link DATA_MODEL_VERSION} may therefore
990
+ * carry a lower floor. Raising this maximum is a declared, DATAMODEL.md-logged
991
+ * decision that requires readers-first fleet sequencing.
992
+ */
993
+ declare const DATA_MODEL_MIN_READER = 4;
994
+
986
995
  export declare function defineAction(action: AuthoringAction): AuthoringAction;
987
996
 
988
997
  export declare function defineActivity(
@@ -1043,9 +1052,18 @@ export declare function defineWorkflow(
1043
1052
  * path-prefixed error if the shape is invalid. The CLI collapses the selected
1044
1053
  * deployment's bindings via {@link resourceAliasesToMap} into the
1045
1054
  * `resourceAliases` map `deployDefinitions` expands against.
1055
+ *
1056
+ * Validates shape only — NOT the reader-floor acknowledgement. That is a
1057
+ * selected-deployment gate (`deployDefinitions`, the CLI's
1058
+ * `deploymentToTarget` / `buildBatches` / `resolveContext`, and blueprint
1059
+ * provision each assert the deployment they target), so a command that never
1060
+ * selects a deployment loads a config with a stale or missing floor on an
1061
+ * untargeted entry without failing. Authors must still acknowledge the floor
1062
+ * at compile time — each {@link WorkflowDeploymentInput} requires it; the
1063
+ * returned {@link WorkflowConfig} is the looser parsed shape.
1046
1064
  */
1047
1065
  export declare function defineWorkflowConfig(
1048
- config: WorkflowConfig,
1066
+ config: WorkflowConfigInput,
1049
1067
  ): WorkflowConfig;
1050
1068
 
1051
1069
  declare type Editable = v.InferOutput<typeof StoredEditableSchema>;
@@ -1422,11 +1440,6 @@ declare type NotesField = FieldBase<AuthoringEditable, GroupMembership> & {
1422
1440
 
1423
1441
  declare type Op = v.InferOutput<typeof StoredOpSchema>;
1424
1442
 
1425
- declare type ParsedWorkflowConfig = v.InferOutput<typeof WorkflowConfigSchema>;
1426
-
1427
- declare type ParsedWorkflowDeployment =
1428
- ParsedWorkflowConfig["deployments"][number];
1429
-
1430
1443
  declare type RequirementBase = {
1431
1444
  name: string;
1432
1445
  title?: string | undefined;
@@ -1929,8 +1942,15 @@ declare type ValueExprInternal =
1929
1942
 
1930
1943
  declare const WORKFLOW_LIFECYCLES: readonly ["standalone", "child"];
1931
1944
 
1932
- declare type WorkflowConfig = Omit<ParsedWorkflowConfig, "deployments"> & {
1933
- deployments: WorkflowDeployment[];
1945
+ declare type WorkflowConfig = v.InferOutput<typeof WorkflowConfigSchema>;
1946
+
1947
+ /**
1948
+ * What an author writes for a whole config: every deployment is a
1949
+ * {@link WorkflowDeploymentInput}. `defineWorkflowConfig` accepts this and
1950
+ * returns the looser {@link WorkflowConfig}.
1951
+ */
1952
+ declare type WorkflowConfigInput = Omit<WorkflowConfig, "deployments"> & {
1953
+ deployments: WorkflowDeploymentInput[];
1934
1954
  };
1935
1955
 
1936
1956
  declare const WorkflowConfigSchema: v.ObjectSchema<
@@ -2578,15 +2598,25 @@ declare const WorkflowDefinitionSchema: v.GenericSchema<
2578
2598
  WorkflowFields<FieldEntry, Stage, StartBlock>
2579
2599
  >;
2580
2600
 
2581
- declare type WorkflowDeployment = Omit<
2582
- ParsedWorkflowDeployment,
2601
+ /** One deployment as loaded from a config: the floor is optional/unverified so
2602
+ * a command that never selects a deployment can hold a stale or missing
2603
+ * acknowledgement. Deployment-scoped paths assert before they act; authors
2604
+ * write {@link WorkflowDeploymentInput}. */
2605
+ declare type WorkflowDeployment = WorkflowConfig["deployments"][number];
2606
+
2607
+ /**
2608
+ * What an author writes for one deployment: the current reader floor as the
2609
+ * reviewed literal. Compile-time only — omitting it or setting a wrong value
2610
+ * is a type error in the editor. Runtime parse still tolerates a stale or
2611
+ * missing floor on {@link WorkflowDeployment} so commands that never select a
2612
+ * deployment still run; deployment-scoped paths assert the selected
2613
+ * deployment (instance-id commands do not).
2614
+ */
2615
+ declare type WorkflowDeploymentInput = Omit<
2616
+ WorkflowDeployment,
2583
2617
  "expectedMinReaderModel"
2584
2618
  > & {
2585
- /**
2586
- * Reviewed numeric literal. Runtime validation owns the exact installed-floor check so a stale
2587
- * acknowledgement reaches the readers-first rollout guidance instead of becoming a type error.
2588
- */
2589
- expectedMinReaderModel: number;
2619
+ expectedMinReaderModel: typeof DATA_MODEL_MIN_READER;
2590
2620
  };
2591
2621
 
2592
2622
  /** Type-mirror of {@link workflowFields}, parameterised over field/stage/start. */
package/dist/define.js CHANGED
@@ -1,4 +1,4 @@
1
- import { parseOrThrow, desugarWorkflow, checkWorkflowInvariants, formatValidationError, WorkflowConfigSchema, assertReaderModelAcknowledgement, AuthoringWorkflowSchema, labelFor, AuthoringStageSchema, AuthoringActivitySchema, AuthoringActionSchema, AuthoringTransitionSchema, AuthoringFieldEntrySchema, AuthoringOpSchema, GroupSchema, AuthoringGuardSchema, EffectSchema } from "./_chunks-es/invariants.js";
1
+ import { parseOrThrow, desugarWorkflow, checkWorkflowInvariants, formatValidationError, AuthoringWorkflowSchema, labelFor, WorkflowConfigSchema, AuthoringStageSchema, AuthoringActivitySchema, AuthoringActionSchema, AuthoringTransitionSchema, AuthoringFieldEntrySchema, AuthoringOpSchema, GroupSchema, AuthoringGuardSchema, EffectSchema } from "./_chunks-es/invariants.js";
2
2
 
3
3
  import { CONDITION_VARS, FILTER_SCOPE_VARS, GUARD_PREDICATE_VARS, RESERVED_CONDITION_VARS, groq } from "./_chunks-es/invariants.js";
4
4
 
@@ -13,16 +13,11 @@ function defineWorkflow(definition) {
13
13
  }
14
14
 
15
15
  function defineWorkflowConfig(config) {
16
- const parsed = parseOrThrow({
16
+ return parseOrThrow({
17
17
  schema: WorkflowConfigSchema,
18
18
  input: config,
19
19
  label: "defineWorkflowConfig"
20
20
  });
21
- return assertDeploymentAcknowledgements(parsed), parsed;
22
- }
23
-
24
- function assertDeploymentAcknowledgements(config) {
25
- for (const [index, deployment] of config.deployments.entries()) assertReaderModelAcknowledgement(deployment.expectedMinReaderModel, `Deployment ${deployment.name || `at deployments[${index}]`}`);
26
21
  }
27
22
 
28
23
  function defineStage(stage) {