@sanity/workflow-engine 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/define.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as v from "valibot";
2
- import { andConditions, expandRequiredRoles, GROQ_IDENTIFIER, formatValidationError, issuesFromValibot, AuthoringWorkflowSchema, AuthoringStageSchema, AuthoringTaskSchema, AuthoringActionSchema, AuthoringTransitionSchema, AuthoringFieldEntrySchema, AuthoringOpSchema, GuardSchema, EffectSchema } from "./_chunks-es/schema.js";
2
+ import { andConditions, expandRequiredRoles, normalizeRoleAliases, GROQ_IDENTIFIER, formatValidationError, issuesFromValibot, AuthoringWorkflowSchema, AuthoringStageSchema, AuthoringActivitySchema, AuthoringActionSchema, AuthoringTransitionSchema, AuthoringFieldEntrySchema, AuthoringOpSchema, GuardSchema, EffectSchema } from "./_chunks-es/schema.js";
3
3
  function groq(strings, ...values) {
4
4
  return strings.reduce((out, part, i) => i === 0 ? part : `${out}${serializeGroqValue(values[i - 1])}${part}`, "");
5
5
  }
@@ -12,24 +12,26 @@ function serializeGroqValue(value) {
12
12
  return serialized;
13
13
  }
14
14
  function desugarWorkflow(authoring) {
15
- const ctx = {
16
- issues: [],
15
+ const issues = [];
16
+ checkReservedRoleAliasKeys(authoring.roleAliases, issues);
17
+ const roleAliases = normalizeRoleAliases(authoring.roleAliases), ctx = {
18
+ issues,
17
19
  claimFields: /* @__PURE__ */ new Map(),
18
20
  claimedFields: /* @__PURE__ */ new Set(),
19
- roleAliases: authoring.roleAliases
21
+ roleAliases
20
22
  }, workflowFields = desugarFieldEntries(authoring.fields, ["fields"], ctx), workflowLayer = layerOf(workflowFields), stages = authoring.stages.map((stage, i) => {
21
23
  const path = ["stages", i], stageFields = desugarFieldEntries(stage.fields, [...path, "fields"], ctx), stageEnv = {
22
24
  layers: [
23
25
  { scope: "stage", entries: layerOf(stageFields) },
24
26
  { scope: "workflow", entries: workflowLayer }
25
27
  ]
26
- }, tasks = (stage.tasks ?? []).map(
27
- (task, j) => desugarTask(task, [...path, "tasks", j], stageEnv, ctx)
28
+ }, activities = (stage.activities ?? []).map(
29
+ (activity, j) => desugarActivity(activity, [...path, "activities", j], stageEnv, ctx)
28
30
  ), transitions = (stage.transitions ?? []).map(
29
31
  (transition, k) => desugarTransition(transition, [...path, "transitions", k], stageEnv, ctx)
30
32
  ), editable = desugarStageEditable(
31
33
  stage.editable,
32
- editableSlotNames(workflowFields, stageFields, tasks),
34
+ editableSlotNames(workflowFields, stageFields, activities),
33
35
  [...path, "editable"],
34
36
  ctx
35
37
  );
@@ -41,7 +43,7 @@ function desugarWorkflow(authoring) {
41
43
  guards: stage.guards
42
44
  }),
43
45
  ...stageFields ? { fields: stageFields } : {},
44
- ...tasks.length > 0 ? { tasks } : {},
46
+ ...activities.length > 0 ? { activities } : {},
45
47
  ...transitions.length > 0 ? { transitions } : {},
46
48
  ...editable ? { editable } : {}
47
49
  };
@@ -49,41 +51,76 @@ function desugarWorkflow(authoring) {
49
51
  return checkUnclaimedClaimFields(ctx), { definition: {
50
52
  ...stripUndefined({
51
53
  name: authoring.name,
52
- version: authoring.version,
53
54
  title: authoring.title,
54
55
  description: authoring.description,
55
56
  role: authoring.role,
56
57
  initialStage: authoring.initialStage,
57
58
  predicates: authoring.predicates,
58
- roleAliases: authoring.roleAliases
59
+ roleAliases
59
60
  }),
60
61
  ...workflowFields ? { fields: workflowFields } : {},
61
62
  stages
62
63
  }, issues: ctx.issues };
63
64
  }
65
+ function checkReservedRoleAliasKeys(aliases, issues) {
66
+ for (const key of Object.keys(aliases ?? {}))
67
+ key.startsWith("$") && issues.push({
68
+ path: ["roleAliases", key],
69
+ message: `role alias key "${key}" uses the reserved "$" prefix \u2014 that namespace is the engine's stored spelling for the universal fulfiller. Use "*" to mean "fulfills any gate", or rename the role.`
70
+ });
71
+ }
72
+ const TODOLIST_OF = [
73
+ { type: "string", name: "label", title: "Label" },
74
+ { type: "string", name: "status", title: "Status" },
75
+ { type: "assignee", name: "assignee", title: "Assignee" },
76
+ { type: "date", name: "dueDate", title: "Due date" }
77
+ ], NOTES_OF = [
78
+ { type: "text", name: "body", title: "Body" },
79
+ { type: "actor", name: "actor", title: "Actor" },
80
+ { type: "datetime", name: "at", title: "At" }
81
+ ];
64
82
  function desugarFieldEntries(entries, path, ctx) {
65
- return !entries || entries.length === 0 ? entries === void 0 ? void 0 : [] : entries.map((entry, i) => {
66
- if (entry.type === "claim") {
67
- const desugared = {
68
- ...stripUndefined({ name: entry.name, title: entry.title, description: entry.description }),
69
- type: "value.actor",
70
- source: { type: "write" }
71
- };
72
- return ctx.claimFields.set(desugared, { name: entry.name, path: [...path, i] }), desugared;
73
- }
74
- const editable = normalizeEditable(entry.editable, [...path, i, "editable"], ctx);
75
- return {
76
- ...stripUndefined({
77
- type: entry.type,
78
- name: entry.name,
79
- title: entry.title,
80
- description: entry.description,
81
- required: entry.required,
82
- editable
83
- }),
84
- source: entry.source
85
- };
86
- });
83
+ return !entries || entries.length === 0 ? entries === void 0 ? void 0 : [] : entries.map((entry, i) => desugarFieldEntry(entry, [...path, i], ctx));
84
+ }
85
+ function desugarFieldEntry(entry, path, ctx) {
86
+ if (entry.type === "claim") return desugarClaimField(entry, path, ctx);
87
+ if (entry.type === "todoList" || entry.type === "notes") return desugarListField(entry, path, ctx);
88
+ const editable = normalizeEditable(entry.editable, [...path, "editable"], ctx);
89
+ return {
90
+ ...stripUndefined({
91
+ type: entry.type,
92
+ name: entry.name,
93
+ title: entry.title,
94
+ description: entry.description,
95
+ required: entry.required,
96
+ initialValue: entry.initialValue,
97
+ editable,
98
+ fields: entry.fields,
99
+ of: entry.of
100
+ })
101
+ };
102
+ }
103
+ function desugarClaimField(entry, path, ctx) {
104
+ const desugared = {
105
+ ...stripUndefined({ name: entry.name, title: entry.title, description: entry.description }),
106
+ type: "actor"
107
+ };
108
+ return ctx.claimFields.set(desugared, { name: entry.name, path }), desugared;
109
+ }
110
+ function desugarListField(entry, path, ctx) {
111
+ const editable = normalizeEditable(entry.editable, [...path, "editable"], ctx);
112
+ return {
113
+ ...stripUndefined({
114
+ name: entry.name,
115
+ title: entry.title,
116
+ description: entry.description,
117
+ required: entry.required,
118
+ initialValue: entry.initialValue,
119
+ editable
120
+ }),
121
+ type: "array",
122
+ of: entry.type === "todoList" ? TODOLIST_OF : NOTES_OF
123
+ };
87
124
  }
88
125
  function normalizeEditable(editable, path, ctx) {
89
126
  if (editable === void 0 || editable === !0) return editable;
@@ -100,12 +137,12 @@ function normalizeEditable(editable, path, ctx) {
100
137
  }
101
138
  return editable;
102
139
  }
103
- function editableSlotNames(workflowFields, stageFields, tasks) {
140
+ function editableSlotNames(workflowFields, stageFields, activities) {
104
141
  const names = /* @__PURE__ */ new Set(), collect = (entries) => {
105
142
  for (const entry of entries ?? []) entry.editable !== void 0 && names.add(entry.name);
106
143
  };
107
144
  collect(workflowFields), collect(stageFields);
108
- for (const task of tasks) collect(task.fields);
145
+ for (const activity of activities) collect(activity.fields);
109
146
  return names;
110
147
  }
111
148
  function desugarStageEditable(overrides, inScope, path, ctx) {
@@ -115,7 +152,7 @@ function desugarStageEditable(overrides, inScope, path, ctx) {
115
152
  if (!inScope.has(name)) {
116
153
  ctx.issues.push({
117
154
  path: [...path, name],
118
- message: `stage editable override "${name}" does not narrow an editable slot in scope \u2014 name a workflow/stage/task slot of this stage that declares \`editable\``
155
+ message: `stage editable override "${name}" does not narrow an editable slot in scope \u2014 name a workflow/stage/activity slot of this stage that declares \`editable\``
119
156
  });
120
157
  continue;
121
158
  }
@@ -127,28 +164,28 @@ function desugarStageEditable(overrides, inScope, path, ctx) {
127
164
  function layerOf(entries) {
128
165
  return new Map((entries ?? []).map((entry) => [entry.name, entry]));
129
166
  }
130
- function desugarTask(task, path, stageEnv, ctx) {
131
- const taskFields = desugarFieldEntries(task.fields, [...path, "fields"], ctx), env = {
132
- layers: [{ scope: "task", entries: layerOf(taskFields) }, ...stageEnv.layers]
133
- }, ops = desugarOps(task.ops, [...path, "ops"], env, task.name, ctx), actions = (task.actions ?? []).map(
134
- (action, a) => desugarAction(action, [...path, "actions", a], env, task.name, ctx)
135
- ), target = desugarTarget(task.target, env, [...path, "target"], ctx);
167
+ function desugarActivity(activity, path, stageEnv, ctx) {
168
+ const activityFields = desugarFieldEntries(activity.fields, [...path, "fields"], ctx), env = {
169
+ layers: [{ scope: "activity", entries: layerOf(activityFields) }, ...stageEnv.layers]
170
+ }, ops = desugarOps(activity.ops, [...path, "ops"], env, activity.name, ctx), actions = (activity.actions ?? []).map(
171
+ (action, a) => desugarAction(action, [...path, "actions", a], env, activity.name, ctx)
172
+ ), target = desugarTarget(activity.target, env, [...path, "target"], ctx);
136
173
  return {
137
174
  ...stripUndefined({
138
- name: task.name,
139
- title: task.title,
140
- description: task.description,
141
- kind: task.kind,
142
- filter: task.filter,
143
- requirements: task.requirements,
144
- completeWhen: task.completeWhen,
145
- failWhen: task.failWhen,
146
- effects: task.effects,
147
- subworkflows: task.subworkflows
175
+ name: activity.name,
176
+ title: activity.title,
177
+ description: activity.description,
178
+ kind: activity.kind,
179
+ filter: activity.filter,
180
+ requirements: activity.requirements,
181
+ completeWhen: activity.completeWhen,
182
+ failWhen: activity.failWhen,
183
+ effects: activity.effects,
184
+ subworkflows: activity.subworkflows
148
185
  }),
149
- activation: task.activation ?? "manual",
186
+ activation: activity.activation ?? "manual",
150
187
  ...target ? { target } : {},
151
- ...taskFields ? { fields: taskFields } : {},
188
+ ...activityFields ? { fields: activityFields } : {},
152
189
  ...ops ? { ops } : {},
153
190
  ...actions.length > 0 ? { actions } : {}
154
191
  };
@@ -159,14 +196,14 @@ function desugarTarget(target, env, path, ctx) {
159
196
  const ref = typeof target.field == "string" ? { field: target.field } : target.field, field = resolveRef(ref, env, [...path, "field"], ctx) ?? fallbackRef(ref), entry = entryAt(env, field);
160
197
  return entry && !TARGET_DOC_KINDS.includes(entry.type) && ctx.issues.push({
161
198
  path: [...path, "field"],
162
- message: `manual task target references "${field.field}" of kind "${entry.type}" \u2014 a deep-link target needs a document-valued entry (${TARGET_DOC_KINDS.join(", ")})`
199
+ message: `manual activity target references "${field.field}" of kind "${entry.type}" \u2014 a deep-link target needs a document-valued entry (${TARGET_DOC_KINDS.join(", ")})`
163
200
  }), { type: "field", field };
164
201
  }
165
- function desugarAction(action, path, env, taskName, ctx) {
202
+ function desugarAction(action, path, env, activityName, ctx) {
166
203
  if ("type" in action)
167
204
  return desugarClaimAction(action, path, env, ctx);
168
- const filter = andConditions([rolesCondition(action.roles, ctx.roleAliases), action.filter]), ops = desugarOps(action.ops, [...path, "ops"], env, taskName, ctx) ?? [];
169
- return action.status !== void 0 && ops.push({ type: "status.set", task: taskName, status: action.status }), {
205
+ const filter = andConditions([rolesCondition(action.roles, ctx.roleAliases), action.filter]), ops = desugarOps(action.ops, [...path, "ops"], env, activityName, ctx) ?? [];
206
+ return action.status !== void 0 && ops.push({ type: "status.set", activity: activityName, status: action.status }), {
170
207
  ...stripUndefined({
171
208
  name: action.name,
172
209
  title: action.title,
@@ -182,9 +219,9 @@ function desugarClaimAction(action, path, env, ctx) {
182
219
  const ref = typeof action.field == "string" ? { field: action.field } : action.field, resolved = resolveRef(ref, env, [...path, "field"], ctx);
183
220
  if (resolved) {
184
221
  const entry = entryAt(env, resolved);
185
- entry && entry.type !== "value.actor" && ctx.issues.push({
222
+ entry && entry.type !== "actor" && ctx.issues.push({
186
223
  path: [...path, "field"],
187
- message: `claim action "${action.name}" references "${resolved.field}" of kind "${entry.type}" \u2014 a claim pair needs an actor-valued entry (a "claim" or "value.actor" field declaration)`
224
+ message: `claim action "${action.name}" references "${resolved.field}" of kind "${entry.type}" \u2014 a claim pair needs an actor-valued entry (a "claim" or "actor" field declaration)`
188
225
  }), checkShadowedClaimTarget(action.name, ref.field, resolved, env, [...path, "field"], ctx), entry && ctx.claimedFields.add(entry);
189
226
  }
190
227
  const noSteal = `!defined($fields.${ref.field})`, filter = andConditions([
@@ -215,7 +252,7 @@ function checkUnclaimedClaimFields(ctx) {
215
252
  for (const [entry, { name, path }] of ctx.claimFields)
216
253
  ctx.claimedFields.has(entry) || ctx.issues.push({
217
254
  path,
218
- message: `claim field "${name}" is never referenced by a claim action \u2014 you announced the pattern and wrote half of it. Declare a defineAction({ type: "claim", field: "${name}" }) or use a raw value.actor entry`
255
+ message: `claim field "${name}" is never referenced by a claim action \u2014 you announced the pattern and wrote half of it. Declare a defineAction({ type: "claim", field: "${name}" }) or use a raw actor entry`
219
256
  });
220
257
  }
221
258
  function desugarTransition(transition, path, stageEnv, ctx) {
@@ -228,21 +265,21 @@ function desugarTransition(transition, path, stageEnv, ctx) {
228
265
  to: transition.to,
229
266
  effects: transition.effects
230
267
  }),
231
- filter: transition.filter ?? "$allTasksDone",
268
+ filter: transition.filter ?? "$allActivitiesDone",
232
269
  ...ops ? { ops } : {}
233
270
  };
234
271
  }
235
- function desugarOps(ops, path, env, firingTask, ctx) {
272
+ function desugarOps(ops, path, env, firingActivity, ctx) {
236
273
  if (ops)
237
- return ops.map((op, i) => desugarOp(op, [...path, i], env, firingTask, ctx));
274
+ return ops.map((op, i) => desugarOp(op, [...path, i], env, firingActivity, ctx));
238
275
  }
239
- function desugarOp(op, path, env, firingTask, ctx) {
276
+ function desugarOp(op, path, env, firingActivity, ctx) {
240
277
  if (op.type === "status.set") {
241
- const task = op.task ?? firingTask;
242
- return task === void 0 && ctx.issues.push({
243
- path: [...path, "task"],
244
- message: "status.set outside an action must name its target task"
245
- }), { type: "status.set", task: task ?? "", status: op.status };
278
+ const activity = op.activity ?? firingActivity;
279
+ return activity === void 0 && ctx.issues.push({
280
+ path: [...path, "activity"],
281
+ message: "status.set outside an action must name its target activity"
282
+ }), { type: "status.set", activity: activity ?? "", status: op.status };
246
283
  }
247
284
  if (op.type === "audit") return desugarAuditOp(op, path, env, ctx);
248
285
  const target = resolveRef(op.target, env, [...path, "target"], ctx) ?? fallbackRef(op.target);
@@ -306,14 +343,14 @@ const RESERVED_CONDITION_VARS = [
306
343
  "row",
307
344
  "now",
308
345
  "effects",
309
- "tasks",
346
+ "activities",
310
347
  "subworkflows",
311
348
  "self",
312
349
  "stage",
313
350
  "parent",
314
351
  "ancestors",
315
- "allTasksDone",
316
- "anyTaskFailed"
352
+ "allActivitiesDone",
353
+ "anyActivityFailed"
317
354
  ], PREDICATE_CALLER_VARS = ["actor", "assigned", "can"];
318
355
  function knownList(ids) {
319
356
  return [...ids].map((s) => `"${s}"`).join(", ");
@@ -331,12 +368,12 @@ function checkStages(def, issues) {
331
368
  issues
332
369
  );
333
370
  for (const [i, stage] of def.stages.entries()) {
334
- const taskNames = checkDuplicates(
335
- (stage.tasks ?? []).map((task, j) => ({
336
- name: task.name,
337
- path: ["stages", i, "tasks", j, "name"]
371
+ const activityNames = checkDuplicates(
372
+ (stage.activities ?? []).map((activity, j) => ({
373
+ name: activity.name,
374
+ path: ["stages", i, "activities", j, "name"]
338
375
  })),
339
- `task name in stage "${stage.name}"`,
376
+ `activity name in stage "${stage.name}"`,
340
377
  issues
341
378
  );
342
379
  checkDuplicates(
@@ -346,34 +383,34 @@ function checkStages(def, issues) {
346
383
  })),
347
384
  `transition name in stage "${stage.name}"`,
348
385
  issues
349
- ), checkTasks(def, i, taskNames, issues);
386
+ ), checkActivities(def, i, activityNames, issues);
350
387
  }
351
388
  return stageNames;
352
389
  }
353
- function checkTasks(def, i, taskNames, issues) {
390
+ function checkActivities(def, i, activityNames, issues) {
354
391
  const stage = def.stages[i];
355
- for (const [j, task] of (stage.tasks ?? []).entries()) {
356
- const path = ["stages", i, "tasks", j];
392
+ for (const [j, activity] of (stage.activities ?? []).entries()) {
393
+ const path = ["stages", i, "activities", j];
357
394
  checkDuplicates(
358
- (task.actions ?? []).map((action, a) => ({
395
+ (activity.actions ?? []).map((action, a) => ({
359
396
  name: action.name,
360
397
  path: [...path, "actions", a, "name"]
361
398
  })),
362
- `action name in task "${task.name}"`,
399
+ `action name in activity "${activity.name}"`,
363
400
  issues
364
- ), checkStatusSetTargets(task, taskNames, path, issues);
401
+ ), checkStatusSetTargets(activity, activityNames, path, issues);
365
402
  }
366
403
  }
367
- function checkStatusSetTargets(task, taskNames, path, issues) {
368
- checkStatusSetOps(task.ops, taskNames, [...path, "ops"], issues);
369
- for (const [a, action] of (task.actions ?? []).entries())
370
- checkStatusSetOps(action.ops, taskNames, [...path, "actions", a, "ops"], issues);
404
+ function checkStatusSetTargets(activity, activityNames, path, issues) {
405
+ checkStatusSetOps(activity.ops, activityNames, [...path, "ops"], issues);
406
+ for (const [a, action] of (activity.actions ?? []).entries())
407
+ checkStatusSetOps(action.ops, activityNames, [...path, "actions", a, "ops"], issues);
371
408
  }
372
- function checkStatusSetOps(ops, taskNames, path, issues) {
409
+ function checkStatusSetOps(ops, activityNames, path, issues) {
373
410
  for (const [o, op] of (ops ?? []).entries())
374
- op.type !== "status.set" || taskNames.has(op.task) || issues.push({
375
- path: [...path, o, "task"],
376
- message: `status.set targets task "${op.task}" which is not declared in this stage. Known tasks: ${knownList(taskNames)}`
411
+ op.type !== "status.set" || activityNames.has(op.activity) || issues.push({
412
+ path: [...path, o, "activity"],
413
+ message: `status.set targets activity "${op.activity}" which is not declared in this stage. Known activities: ${knownList(activityNames)}`
377
414
  });
378
415
  }
379
416
  function checkInitialStage(def, stageNames, issues) {
@@ -393,10 +430,14 @@ function checkTransitionTargets(def, stageNames, issues) {
393
430
  function checkEffectNames(def, issues) {
394
431
  const sites = [];
395
432
  for (const [i, stage] of def.stages.entries()) {
396
- for (const [j, task] of (stage.tasks ?? []).entries()) {
397
- collectEffects(task.effects, ["stages", i, "tasks", j, "effects"], sites);
398
- for (const [a, action] of (task.actions ?? []).entries())
399
- collectEffects(action.effects, ["stages", i, "tasks", j, "actions", a, "effects"], sites);
433
+ for (const [j, activity] of (stage.activities ?? []).entries()) {
434
+ collectEffects(activity.effects, ["stages", i, "activities", j, "effects"], sites);
435
+ for (const [a, action] of (activity.actions ?? []).entries())
436
+ collectEffects(
437
+ action.effects,
438
+ ["stages", i, "activities", j, "actions", a, "effects"],
439
+ sites
440
+ );
400
441
  }
401
442
  for (const [k, t] of (stage.transitions ?? []).entries())
402
443
  collectEffects(t.effects, ["stages", i, "transitions", k, "effects"], sites);
@@ -431,12 +472,12 @@ function fieldScopes(def) {
431
472
  path: ["stages", i, "fields"],
432
473
  label: `stage "${stage.name}" fields`
433
474
  });
434
- for (const [j, task] of (stage.tasks ?? []).entries())
475
+ for (const [j, activity] of (stage.activities ?? []).entries())
435
476
  scopes.push({
436
- entries: task.fields,
437
- scope: "task",
438
- path: ["stages", i, "tasks", j, "fields"],
439
- label: `task "${task.name}" fields`
477
+ entries: activity.fields,
478
+ scope: "activity",
479
+ path: ["stages", i, "activities", j, "fields"],
480
+ label: `activity "${activity.name}" fields`
440
481
  });
441
482
  }
442
483
  return scopes;
@@ -444,13 +485,20 @@ function fieldScopes(def) {
444
485
  function checkRequiredField(def, issues) {
445
486
  for (const { entries, scope, path, label } of fieldScopes(def))
446
487
  for (const [n, entry] of (entries ?? []).entries())
447
- entry.required === !0 && (scope !== "workflow" ? issues.push({
448
- path: [...path, n, "required"],
449
- message: `${label} entry "${entry.name}" is \`required\`, but \`required\` applies only to workflow-scope \`init\` entries \u2014 only those are caller-supplied at start/spawn`
450
- }) : entry.source.type !== "init" && issues.push({
451
- path: [...path, n, "required"],
452
- message: `field entry "${entry.name}" is \`required\` but its source is "${entry.source.type}" \u2014 \`required\` applies only to \`init\`-sourced entries (the caller fills them at start/spawn)`
453
- }));
488
+ if (entry.required === !0) {
489
+ if (scope !== "workflow")
490
+ issues.push({
491
+ path: [...path, n, "required"],
492
+ message: `${label} entry "${entry.name}" is \`required\`, but \`required\` applies only to workflow-scope \`input\` entries \u2014 only those are caller-supplied at start/spawn`
493
+ });
494
+ else if (entry.initialValue?.type !== "input") {
495
+ const seed = entry.initialValue?.type ?? "working memory (no initialValue)";
496
+ issues.push({
497
+ path: [...path, n, "required"],
498
+ message: `field entry "${entry.name}" has initialValue "${seed}" \u2014 \`required\` applies only to \`input\`-sourced entries (the caller fills them at start/spawn)`
499
+ });
500
+ }
501
+ }
454
502
  }
455
503
  function checkFieldEntryNames(def, issues) {
456
504
  for (const { entries, path, label } of fieldScopes(def))
@@ -506,34 +554,34 @@ function nonActionFilterConditionSites(def) {
506
554
  `transition "${t.name}"`,
507
555
  sites
508
556
  );
509
- for (const [j, task] of (stage.tasks ?? []).entries())
510
- collectTaskConditionSites(task, ["stages", i, "tasks", j], sites);
557
+ for (const [j, activity] of (stage.activities ?? []).entries())
558
+ collectActivityConditionSites(activity, ["stages", i, "activities", j], sites);
511
559
  }
512
560
  return sites;
513
561
  }
514
- function collectTaskConditionSites(task, path, sites) {
562
+ function collectActivityConditionSites(activity, path, sites) {
515
563
  for (const field of ["filter", "completeWhen", "failWhen"]) {
516
- const groq2 = task[field];
517
- groq2 !== void 0 && sites.push({ groq: groq2, path: [...path, field], label: `task "${task.name}".${field}` });
564
+ const groq2 = activity[field];
565
+ groq2 !== void 0 && sites.push({ groq: groq2, path: [...path, field], label: `activity "${activity.name}".${field}` });
518
566
  }
519
- collectBindingSites(task.effects, [...path, "effects"], `task "${task.name}"`, sites);
520
- for (const [a, action] of (task.actions ?? []).entries())
567
+ collectBindingSites(activity.effects, [...path, "effects"], `activity "${activity.name}"`, sites);
568
+ for (const [a, action] of (activity.actions ?? []).entries())
521
569
  collectBindingSites(
522
570
  action.effects,
523
571
  [...path, "actions", a, "effects"],
524
572
  `action "${action.name}"`,
525
573
  sites
526
574
  );
527
- collectSubworkflowSites(task, path, sites);
575
+ collectSubworkflowSites(activity, path, sites);
528
576
  }
529
- function collectSubworkflowSites(task, path, sites) {
530
- const sub = task.subworkflows;
577
+ function collectSubworkflowSites(activity, path, sites) {
578
+ const sub = activity.subworkflows;
531
579
  if (sub === void 0) return;
532
580
  const subPath = [...path, "subworkflows"];
533
581
  sites.push({
534
582
  groq: sub.forEach,
535
583
  path: [...subPath, "forEach"],
536
- label: `task "${task.name}".subworkflows.forEach`
584
+ label: `activity "${activity.name}".subworkflows.forEach`
537
585
  });
538
586
  for (const [group, record] of [
539
587
  ["with", sub.with],
@@ -543,7 +591,7 @@ function collectSubworkflowSites(task, path, sites) {
543
591
  sites.push({
544
592
  groq: groq2,
545
593
  path: [...subPath, group, key],
546
- label: `task "${task.name}".subworkflows.${group} "${key}"`
594
+ label: `activity "${activity.name}".subworkflows.${group} "${key}"`
547
595
  });
548
596
  }
549
597
  function collectBindingSites(effects, path, label, sites) {
@@ -562,12 +610,12 @@ function checkAssigneesEntries(def, issues) {
562
610
  message: "at most one assignees-kind field entry per scope \u2014 the inbox reads it by kind"
563
611
  });
564
612
  }
565
- function taskShape(task) {
613
+ function activityShape(activity) {
566
614
  return {
567
- hasActions: (task.actions ?? []).length > 0,
568
- hasEffects: (task.effects ?? []).length > 0,
569
- hasCompleteWhen: task.completeWhen !== void 0,
570
- hasSubworkflows: task.subworkflows !== void 0
615
+ hasActions: (activity.actions ?? []).length > 0,
616
+ hasEffects: (activity.effects ?? []).length > 0,
617
+ hasCompleteWhen: activity.completeWhen !== void 0,
618
+ hasSubworkflows: activity.subworkflows !== void 0
571
619
  };
572
620
  }
573
621
  const KIND_SHAPE_RULES = {
@@ -575,7 +623,7 @@ const KIND_SHAPE_RULES = {
575
623
  service: (s) => s.hasEffects ? [] : ["needs at least one effect \u2014 the automated work it performs"],
576
624
  manual: (s) => [
577
625
  s.hasActions || s.hasCompleteWhen ? void 0 : "needs a way to complete \u2014 an action to acknowledge it, or a `completeWhen` predicate to verify it (otherwise it auto-resolves on activation)",
578
- s.hasSubworkflows ? "is off-system work, not a fan-out \u2014 drop `subworkflows` or move it to its own task" : void 0
626
+ s.hasSubworkflows ? "is off-system work, not a fan-out \u2014 drop `subworkflows` or move it to its own activity" : void 0
579
627
  ].filter((m) => m !== void 0),
580
628
  receive: (s) => [
581
629
  s.hasCompleteWhen || s.hasSubworkflows ? void 0 : "needs a `completeWhen` (or `subworkflows`) condition to wait on",
@@ -587,24 +635,24 @@ const KIND_SHAPE_RULES = {
587
635
  s.hasSubworkflows ? "resolves on activation, so it cannot fan out with `subworkflows`" : void 0
588
636
  ].filter((m) => m !== void 0)
589
637
  };
590
- function checkTaskKinds(def, issues) {
638
+ function checkActivityKinds(def, issues) {
591
639
  for (const [i, stage] of def.stages.entries())
592
- for (const [j, task] of (stage.tasks ?? []).entries()) {
593
- const path = ["stages", i, "tasks", j];
594
- if (task.target !== void 0 && task.kind !== "manual" && issues.push({
640
+ for (const [j, activity] of (stage.activities ?? []).entries()) {
641
+ const path = ["stages", i, "activities", j];
642
+ if (activity.target !== void 0 && activity.kind !== "manual" && issues.push({
595
643
  path: [...path, "target"],
596
- message: `task "${task.name}" has a \`target\` but is not \`kind: "manual"\` \u2014 a target is the deep-link for off-system manual work`
597
- }), task.kind !== void 0)
598
- for (const fault of KIND_SHAPE_RULES[task.kind](taskShape(task)))
644
+ message: `activity "${activity.name}" has a \`target\` but is not \`kind: "manual"\` \u2014 a target is the deep-link for off-system manual work`
645
+ }), activity.kind !== void 0)
646
+ for (const fault of KIND_SHAPE_RULES[activity.kind](activityShape(activity)))
599
647
  issues.push({
600
648
  path: [...path, "kind"],
601
- message: `task "${task.name}" declares kind "${task.kind}" but ${fault}`
649
+ message: `activity "${activity.name}" declares kind "${activity.kind}" but ${fault}`
602
650
  });
603
651
  }
604
652
  }
605
653
  function checkWorkflowInvariants(def) {
606
654
  const issues = [], stageNames = checkStages(def, issues);
607
- return checkInitialStage(def, stageNames, issues), checkTransitionTargets(def, stageNames, issues), checkEffectNames(def, issues), checkGuardNames(def, issues), checkFieldEntryNames(def, issues), checkRequiredField(def, issues), checkPredicates(def, issues), checkCanOutsideActionFilters(def, issues), checkAssigneesEntries(def, issues), checkTaskKinds(def, issues), issues;
655
+ return checkInitialStage(def, stageNames, issues), checkTransitionTargets(def, stageNames, issues), checkEffectNames(def, issues), checkGuardNames(def, issues), checkFieldEntryNames(def, issues), checkRequiredField(def, issues), checkPredicates(def, issues), checkCanOutsideActionFilters(def, issues), checkAssigneesEntries(def, issues), checkActivityKinds(def, issues), issues;
608
656
  }
609
657
  function defineWorkflow(definition) {
610
658
  const label = labelFor("defineWorkflow", definition), parsed = parseOrThrow(AuthoringWorkflowSchema, definition, label), { definition: stored, issues: desugarIssues } = desugarWorkflow(parsed), issues = [...desugarIssues, ...checkWorkflowInvariants(stored)];
@@ -614,8 +662,8 @@ function defineWorkflow(definition) {
614
662
  function defineStage(stage) {
615
663
  return parseOrThrow(AuthoringStageSchema, stage, labelFor("defineStage", stage));
616
664
  }
617
- function defineTask(task) {
618
- return parseOrThrow(AuthoringTaskSchema, task, labelFor("defineTask", task));
665
+ function defineActivity(activity) {
666
+ return parseOrThrow(AuthoringActivitySchema, activity, labelFor("defineActivity", activity));
619
667
  }
620
668
  function defineAction(action) {
621
669
  return parseOrThrow(AuthoringActionSchema, action, labelFor("defineAction", action));
@@ -658,13 +706,13 @@ function labelFor(fn, value) {
658
706
  }
659
707
  export {
660
708
  defineAction,
709
+ defineActivity,
661
710
  defineEffect,
662
711
  defineEffectDescriptor,
663
712
  defineField,
664
713
  defineGuard,
665
714
  defineOp,
666
715
  defineStage,
667
- defineTask,
668
716
  defineTransition,
669
717
  defineWorkflow,
670
718
  groq