@sanity/workflow-cli 0.7.1 → 0.8.1

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/README.md CHANGED
@@ -4,7 +4,7 @@ Command-line tool for deploying, inspecting, and administering Sanity workflow
4
4
  definitions and instances.
5
5
 
6
6
  > [!WARNING]
7
- > Early access, restricted. `retry-task` and `set-stage` are still stubs —
7
+ > Early access, restricted. `retry-activity` and `set-stage` are still stubs —
8
8
  > they print their parsed input and exit non-zero. The "wired" commands below
9
9
  > talk to a real Sanity dataset using `SANITY_*` env vars.
10
10
 
@@ -75,25 +75,25 @@ built or standalone CLI instead resolves the package's compiled `dist`.
75
75
 
76
76
  ## Command status
77
77
 
78
- | Command | Status |
79
- | ------------------------------------------ | ----------------------------------------------------------------------------------------- |
80
- | `deploy` | wired — calls `workflow.deployDefinitions` over the `WORKFLOW_DEFS` module |
81
- | `deploy --check` | wired — runs `validateDefinition` over the local batch + a duplicate-id check |
82
- | `deploy --dry-run` | wired — fetches existing docs and renders a coloured JSON diff per change |
83
- | `deploy --only <id>` | wired — filters deploy/check/dry-run to one `definition` |
84
- | `list` | wired — `client.fetch` over `workflow.instance` documents |
85
- | `show <instance-id>` | wired — `client.getDocument` |
86
- | `diagnose <instance-id>` | wired — one `workflow.evaluate` call, classifies why the instance is/isn't progressing |
87
- | `tail <instance-id>` | wired — `client.listen()` over the instance, prints new history entries |
88
- | `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects, lifts guards) |
89
- | `retry-task <instance-id> <task-id>` | stub |
90
- | `move-stage <instance-id> --to <stage-id>` | wired — calls `workflow.setStage` (runs guards + onEnter effects) |
91
- | `fire-action <instance-id>` | wired — `workflow.evaluate` lists actions; `workflow.fireAction` fires one |
92
- | `set-stage <instance-id> --to <stage-id>` | stub (engine has no guard-bypass path yet) |
93
- | `definition list` | wired — `client.fetch` over `workflow.definition` documents |
94
- | `definition show <id>` | wired — `client.fetch`, latest version unless `--version` |
95
- | `definition diff <id>` | wired — diffs the in-code definition against the deployed latest (`--version` to pin) |
96
- | `definition delete <name>` | wired — calls `workflow.deleteDefinition` (refuses on live instances unless `--cascade`) |
78
+ | Command | Status |
79
+ | -------------------------------------------- | ----------------------------------------------------------------------------------------- |
80
+ | `deploy` | wired — calls `workflow.deployDefinitions` over the `WORKFLOW_DEFS` module |
81
+ | `deploy --check` | wired — runs `validateDefinition` over the local batch + a duplicate-id check |
82
+ | `deploy --dry-run` | wired — fetches existing docs and renders a coloured JSON diff per change |
83
+ | `deploy --only <id>` | wired — filters deploy/check/dry-run to one `definition` |
84
+ | `list` | wired — `client.fetch` over `workflow.instance` documents |
85
+ | `show <instance-id>` | wired — `client.getDocument` |
86
+ | `diagnose <instance-id>` | wired — one `workflow.evaluate` call, classifies why the instance is/isn't progressing |
87
+ | `tail <instance-id>` | wired — `client.listen()` over the instance, prints new history entries |
88
+ | `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects, lifts guards) |
89
+ | `retry-activity <instance-id> <activity-id>` | stub |
90
+ | `move-stage <instance-id> --to <stage-id>` | wired — calls `workflow.setStage` (runs guards + onEnter effects) |
91
+ | `fire-action <instance-id>` | wired — `workflow.evaluate` lists actions; `workflow.fireAction` fires one |
92
+ | `set-stage <instance-id> --to <stage-id>` | stub (engine has no guard-bypass path yet) |
93
+ | `definition list` | wired — `client.fetch` over `workflow.definition` documents |
94
+ | `definition show <id>` | wired — `client.fetch`, latest version unless `--version` |
95
+ | `definition diff <id>` | wired — diffs the in-code definition against the deployed latest (`--version` to pin) |
96
+ | `definition delete <name>` | wired — calls `workflow.deleteDefinition` (refuses on live instances unless `--cascade`) |
97
97
 
98
98
  ## Known gaps
99
99
 
@@ -28,7 +28,7 @@ export default class Abort extends Command {
28
28
  try {
29
29
  const result = await workflow.abortInstance({
30
30
  client,
31
- ...buildOperationArgs(config, args.instanceId, flags.reason),
31
+ ...buildOperationArgs({ config, instanceId: args.instanceId, reason: flags.reason }),
32
32
  });
33
33
  const report = abortReport(result);
34
34
  if (!report.fired) {
@@ -21,10 +21,14 @@ export default class DefinitionDelete extends Command {
21
21
  * engine's optionals reject an explicit `undefined` under
22
22
  * `exactOptionalPropertyTypes`.
23
23
  */
24
- export declare function buildDeleteArgs(config: WorkflowConfig, name: string, flags: {
25
- version?: number | undefined;
26
- cascade: boolean;
27
- reason?: string | undefined;
24
+ export declare function buildDeleteArgs({ config, name, flags, }: {
25
+ config: WorkflowConfig;
26
+ name: string;
27
+ flags: {
28
+ version?: number | undefined;
29
+ cascade: boolean;
30
+ reason?: string | undefined;
31
+ };
28
32
  }): Omit<DeleteDefinitionArgs, 'client'>;
29
33
  /** What the spinner names: the workflow, or one pinned version of it. */
30
34
  export declare function deleteTargetLabel(args: Pick<DeleteDefinitionArgs, 'definition' | 'version'>): string;
@@ -36,7 +36,7 @@ export default class DefinitionDelete extends Command {
36
36
  const { args, flags } = await this.parse(DefinitionDelete);
37
37
  const config = loadWorkflowConfig(flags.tag);
38
38
  const client = loadClient();
39
- const deleteArgs = buildDeleteArgs(config, args.name, flags);
39
+ const deleteArgs = buildDeleteArgs({ config, name: args.name, flags });
40
40
  const spinner = ora(`Deleting definition ${deleteTargetLabel(deleteArgs)}…`).start();
41
41
  try {
42
42
  const result = await workflow.deleteDefinition({ client, ...deleteArgs });
@@ -55,7 +55,7 @@ export default class DefinitionDelete extends Command {
55
55
  * engine's optionals reject an explicit `undefined` under
56
56
  * `exactOptionalPropertyTypes`.
57
57
  */
58
- export function buildDeleteArgs(config, name, flags) {
58
+ export function buildDeleteArgs({ config, name, flags, }) {
59
59
  return {
60
60
  ...baseEngineArgs(config),
61
61
  definition: name,
@@ -29,14 +29,19 @@ export default class DefinitionDiff extends Command {
29
29
  const spinner = ora(`Diffing ${args.definition} against deployed…`).start();
30
30
  let deployed;
31
31
  try {
32
- deployed = await fetchDeployedDefinition(client, args.definition, config, flags.version);
33
- spinner.succeed(`Diffed ${args.definition} v${def.version}`);
32
+ deployed = await fetchDeployedDefinition({
33
+ client,
34
+ name: args.definition,
35
+ config,
36
+ version: flags.version,
37
+ });
38
+ spinner.succeed(`Diffed ${args.definition}`);
34
39
  }
35
40
  catch (error) {
36
41
  spinner.fail('Diff failed');
37
42
  throw error;
38
43
  }
39
- for (const line of diffReport([diffEntry(def, deployed, config)]))
44
+ for (const line of diffReport([diffEntry({ def, latestRaw: deployed, target: config })]))
40
45
  this.log(line);
41
46
  }
42
47
  }
@@ -47,7 +52,7 @@ export default class DefinitionDiff extends Command {
47
52
  * superseded — latest unless pinned via `version`. An absent latest is a
48
53
  * legitimate "create" diff, but an absent *pinned* version is an error.
49
54
  */
50
- async function fetchDeployedDefinition(client, name, config, version) {
55
+ async function fetchDeployedDefinition({ client, name, config, version, }) {
51
56
  const { groq, params } = buildDefinitionShowQuery({ name, tag: config.tag, version });
52
57
  const deployed = await client.fetch(groq, params);
53
58
  if (deployed === null && version !== undefined) {
@@ -2,7 +2,7 @@ import { Command } from '@oclif/core';
2
2
  import { type WorkflowRole } from '@sanity/workflow-engine';
3
3
  interface DefinitionListFlags {
4
4
  tag?: string | undefined;
5
- 'workflow-id'?: string | undefined;
5
+ 'workflow-name'?: string | undefined;
6
6
  limit: number;
7
7
  }
8
8
  export interface DefinitionListRow {
@@ -24,7 +24,7 @@ export default class DefinitionList extends Command {
24
24
  static examples: string[];
25
25
  static flags: {
26
26
  limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
27
- 'workflow-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
27
+ 'workflow-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
28
28
  tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
29
29
  };
30
30
  run(): Promise<void>;
@@ -21,8 +21,8 @@ export function buildDefinitionListQuery(flags) {
21
21
  params.tag = flags.tag;
22
22
  filters.push(tagScopeFilter());
23
23
  }
24
- if (flags['workflow-id']) {
25
- params.name = flags['workflow-id'];
24
+ if (flags['workflow-name']) {
25
+ params.name = flags['workflow-name'];
26
26
  filters.push('name == $name');
27
27
  }
28
28
  const instanceMatch = instanceFilters.join(' && ');
@@ -50,7 +50,7 @@ export default class DefinitionList extends Command {
50
50
  description: 'The maximum number of definitions to return.',
51
51
  default: 100,
52
52
  }),
53
- 'workflow-id': Flags.string({
53
+ 'workflow-name': Flags.string({
54
54
  description: 'Filter to a single workflow definition name (e.g. product-launch)',
55
55
  }),
56
56
  };
@@ -24,10 +24,12 @@ export default class DefinitionShow extends Command {
24
24
  * title, then the human title, description, and deploy `tag` as aligned
25
25
  * detail rows. `tag` is deployment metadata (the partition), not part of the
26
26
  * authored definition, so it's passed separately and omitted when unknown. */
27
- export declare function definitionHeader(def: WorkflowDefinition, tag?: string): string;
27
+ export declare function definitionHeader(def: WorkflowDefinition & {
28
+ version: number;
29
+ }, tag?: string): string;
28
30
  /**
29
- * The body lines for `definition show`: every stage with its tasks and each
30
- * task's actions. Pure so it can be asserted without driving the oclif command.
31
+ * The body lines for `definition show`: every stage with its activities and each
32
+ * activity's actions. Pure so it can be asserted without driving the oclif command.
31
33
  */
32
34
  export declare function describeDefinition(def: WorkflowDefinition): string[];
33
35
  export {};
@@ -36,8 +36,8 @@ export default class DefinitionShow extends Command {
36
36
  version: flags.version,
37
37
  });
38
38
  const client = loadClient();
39
- // The authored {@link WorkflowDefinition} carries no `tag` — it's the
40
- // partition the document was deployed into, stamped on the stored doc.
39
+ // A deployed document: the authored {@link WorkflowDefinition} plus the
40
+ // deploy-stamped envelope (`version`, `contentHash`, `tag`).
41
41
  const def = await client.fetch(groq, params);
42
42
  if (!def) {
43
43
  const at = flags.version ? `v${flags.version}` : 'latest';
@@ -57,11 +57,15 @@ const HEADER_PAD = 11; // "Description" — the longest label in the block
57
57
  * authored definition, so it's passed separately and omitted when unknown. */
58
58
  export function definitionHeader(def, tag) {
59
59
  const rows = [
60
- formatKeyValue('Title', def.title, { padTo: HEADER_PAD }),
61
- formatKeyValue('Description', def.description ?? styleText('dim', '—'), { padTo: HEADER_PAD }),
60
+ formatKeyValue({ key: 'Title', value: def.title, padTo: HEADER_PAD }),
61
+ formatKeyValue({
62
+ key: 'Description',
63
+ value: def.description ?? styleText('dim', '—'),
64
+ padTo: HEADER_PAD,
65
+ }),
62
66
  ];
63
67
  if (tag !== undefined) {
64
- rows.push(formatKeyValue('Tag', tag, { padTo: HEADER_PAD }));
68
+ rows.push(formatKeyValue({ key: 'Tag', value: tag, padTo: HEADER_PAD }));
65
69
  }
66
70
  return [styleText('bold', `${def.name} v${def.version}`), ...rows].join('\n');
67
71
  }
@@ -71,24 +75,24 @@ function actionLine(action) {
71
75
  const status = statusOp ? styleText('dim', ` → ${statusOp.status}`) : '';
72
76
  return ` · ${action.name}${status}`;
73
77
  }
74
- /** A `- task` line followed by one line per action it exposes. */
75
- function taskBlock(task) {
76
- const title = task.title ? styleText('dim', ` — ${task.title}`) : '';
77
- return [` - ${task.name}${title}`, ...(task.actions ?? []).map(actionLine)];
78
+ /** A `- activity` line followed by one line per action it exposes. */
79
+ function activityBlock(activity) {
80
+ const title = activity.title ? styleText('dim', ` — ${activity.title}`) : '';
81
+ return [` - ${activity.name}${title}`, ...(activity.actions ?? []).map(actionLine)];
78
82
  }
79
- /** A `• stage` line (with initial/terminal markers) followed by its task blocks. */
83
+ /** A `• stage` line (with initial/terminal markers) followed by its activity blocks. */
80
84
  function stageBlock(stage, initialStage) {
81
85
  const title = stage.title ? styleText('dim', ` — ${stage.title}`) : '';
82
86
  const terminal = isTerminalStage(stage) ? styleText('dim', ' (terminal)') : '';
83
87
  const initial = stage.name === initialStage ? styleText('cyan', ' [initial]') : '';
84
88
  return [
85
89
  ` • ${stage.name}${title}${terminal}${initial}`,
86
- ...(stage.tasks ?? []).flatMap(taskBlock),
90
+ ...(stage.activities ?? []).flatMap(activityBlock),
87
91
  ];
88
92
  }
89
93
  /**
90
- * The body lines for `definition show`: every stage with its tasks and each
91
- * task's actions. Pure so it can be asserted without driving the oclif command.
94
+ * The body lines for `definition show`: every stage with its activities and each
95
+ * activity's actions. Pure so it can be asserted without driving the oclif command.
92
96
  */
93
97
  export function describeDefinition(def) {
94
98
  return [
@@ -41,12 +41,12 @@ export default class Deploy extends Command {
41
41
  }
42
42
  const client = loadClient();
43
43
  if (flags['dry-run']) {
44
- await this.runDryRun(client, selected, config);
44
+ await this.runDryRun({ client, defs: selected, config });
45
45
  return;
46
46
  }
47
- await this.executeDeploy(client, selected, config);
47
+ await this.executeDeploy({ client, defs: selected, config });
48
48
  }
49
- async executeDeploy(client, defs, config) {
49
+ async executeDeploy({ client, defs, config, }) {
50
50
  const spinner = ora(`Deploying ${defs.length} definition(s)…`).start();
51
51
  try {
52
52
  const { results } = await workflow.deployDefinitions({
@@ -64,10 +64,10 @@ export default class Deploy extends Command {
64
64
  throw error;
65
65
  }
66
66
  }
67
- async runDryRun(client, defs, config) {
67
+ async runDryRun({ client, defs, config, }) {
68
68
  const spinner = ora(`Diffing ${defs.length} definition(s) against dataset…`).start();
69
69
  try {
70
- const entries = await computeDiffEntries(client, defs, config);
70
+ const entries = await computeDiffEntries({ client, defs, target: config });
71
71
  spinner.succeed(`Diffed ${defs.length} definition(s)`);
72
72
  for (const line of diffReport(entries))
73
73
  this.log(line);
@@ -88,7 +88,6 @@ export function validateModeFlags(check, dryRun) {
88
88
  export function deployResultLines(results) {
89
89
  const symbols = {
90
90
  created: logSymbols.success,
91
- updated: logSymbols.info,
92
91
  };
93
92
  return results.map((r) => {
94
93
  const symbol = symbols[r.status] ?? logSymbols.warning;
@@ -1,14 +1,18 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import { type Diagnosis, type DiagnoseInput, type SuggestedRemediation } from '@sanity/workflow-engine';
3
3
  /**
4
- * The diagnosis body: the verdict line, the current stage's tasks +
4
+ * The diagnosis body: the verdict line, the current stage's activities +
5
5
  * transitions as evidence (for any in-flight state), and the cause block with
6
6
  * the engine's suggested fix when stuck. Pure so every verdict permutation is
7
7
  * assertable without driving a live evaluation. Takes the engine's
8
8
  * {@link SuggestedRemediation}s rather than re-deriving them, so the rendered
9
9
  * fix block and the `--json` output stay one computation.
10
10
  */
11
- export declare function renderDiagnosis(diagnosis: Diagnosis, input: DiagnoseInput, remediations: SuggestedRemediation[]): string[];
11
+ export declare function renderDiagnosis({ diagnosis, input, remediations, }: {
12
+ diagnosis: Diagnosis;
13
+ input: DiagnoseInput;
14
+ remediations: SuggestedRemediation[];
15
+ }): string[];
12
16
  export default class Diagnose extends Command {
13
17
  static description: string;
14
18
  static examples: string[];
@@ -6,25 +6,28 @@ import { loadClient } from "../lib/client.js";
6
6
  import { loadWorkflowConfig } from "../lib/config.js";
7
7
  import { fail } from "../lib/fail.js";
8
8
  import { tagFlags } from "../lib/flags.js";
9
- import { formatTimestamp, sectionHeader, taskIcon } from "../lib/ui.js";
9
+ import { formatTimestamp, sectionHeader, activityIcon } from "../lib/ui.js";
10
10
  import { instanceHeader } from "./show.js";
11
11
  function formatAssignee(a) {
12
12
  return a.type === 'user' ? `user:${a.id}` : `role:${a.role}`;
13
13
  }
14
- function taskLine(t, assignees) {
14
+ function activityLine(t, assignees) {
15
15
  const who = assignees.length > 0
16
16
  ? styleText('dim', ` assigned → ${assignees.map(formatAssignee).join(', ')}`)
17
17
  : '';
18
- return ` ${taskIcon[t.status]} ${t.task.name} ${styleText('dim', `[${t.status}]`)}${who}`;
18
+ return ` ${activityIcon[t.status]} ${t.activity.name} ${styleText('dim', `[${t.status}]`)}${who}`;
19
19
  }
20
20
  function transitionLine(tr) {
21
21
  const mark = tr.filterSatisfied ? styleText('green', 'ready') : styleText('red', 'false');
22
22
  return ` → ${tr.transition.to} ${styleText('dim', tr.transition.filter ?? 'true')} ${mark}`;
23
23
  }
24
24
  function currentStageLines(input) {
25
- const lines = [`${sectionHeader('Stage')} ${input.instance.currentStage}`, sectionHeader('Tasks')];
26
- for (const t of input.tasks) {
27
- lines.push(taskLine(t, input.assignees[t.task.name] ?? []));
25
+ const lines = [
26
+ `${sectionHeader('Stage')} ${input.instance.currentStage}`,
27
+ sectionHeader('Activities'),
28
+ ];
29
+ for (const t of input.activities) {
30
+ lines.push(activityLine(t, input.assignees[t.activity.name] ?? []));
28
31
  }
29
32
  if (input.transitions.length > 0) {
30
33
  lines.push('', sectionHeader('Exit transitions'));
@@ -37,14 +40,14 @@ function currentStageLines(input) {
37
40
  function failedEffectDetail(effect) {
38
41
  const ran = effect.durationMs !== undefined ? ` (after ${effect.durationMs}ms)` : '';
39
42
  return {
40
- headline: `a failed effect is blocking task '${effect.origin.name}'`,
43
+ headline: `a failed effect is blocking activity '${effect.origin.name}'`,
41
44
  why: [
42
45
  styleText('red', `${logSymbols.error} failed effect: ${effect.name}`),
43
- ` queued by task '${effect.origin.name}', failed ${formatTimestamp(effect.ranAt)}${ran}`,
46
+ ` queued by activity '${effect.origin.name}', failed ${formatTimestamp(effect.ranAt)}${ran}`,
44
47
  ...(effect.error !== undefined ? [` error: ${effect.error.message}`] : []),
45
48
  '',
46
- `Task '${effect.origin.name}' is waiting on this effect. It failed against an`,
47
- `external system, so the task never completes and the stage can't advance.`,
49
+ `Activity '${effect.origin.name}' is waiting on this effect. It failed against an`,
50
+ `external system, so the activity never completes and the stage can't advance.`,
48
51
  ],
49
52
  };
50
53
  }
@@ -58,12 +61,12 @@ function hungEffectDetail(effect) {
58
61
  ],
59
62
  };
60
63
  }
61
- function failedTaskDetail(task) {
64
+ function failedActivityDetail(activity) {
62
65
  return {
63
- headline: `task '${task}' failed`,
66
+ headline: `activity '${activity}' failed`,
64
67
  why: [
65
- styleText('red', `${logSymbols.error} task '${task}' is in a terminal failed state.`),
66
- `Any exit transition gated on '${task}' being done can never fire.`,
68
+ styleText('red', `${logSymbols.error} activity '${activity}' is in a terminal failed state.`),
69
+ `Any exit transition gated on '${activity}' being done can never fire.`,
67
70
  ],
68
71
  };
69
72
  }
@@ -76,31 +79,31 @@ function waitingLines(w) {
76
79
  ? `assigned to ${w.assignees.map(formatAssignee).join(', ')}`
77
80
  : 'unassigned — anyone with permission can act';
78
81
  return [
79
- `${logSymbols.info} task '${w.task}' is active (${who}),`,
82
+ `${logSymbols.info} activity '${w.activity}' is active (${who}),`,
80
83
  `waiting for action: ${w.actions.join(' or ')}. This is the normal in-flight`,
81
84
  `state — it advances when someone acts.`,
82
85
  ];
83
86
  }
84
87
  function blockedHeadline(b) {
85
88
  const who = b.assignees.length > 0 ? ` for ${b.assignees.map(formatAssignee).join(', ')}` : '';
86
- return `task '${b.task}'${who} is not yet ready — unmet requirement(s): ${b.requirements.join(', ')}`;
89
+ return `activity '${b.activity}'${who} is not yet ready — unmet requirement(s): ${b.requirements.join(', ')}`;
87
90
  }
88
91
  function blockedLines(b) {
89
92
  const who = b.assignees.length > 0
90
93
  ? `assigned to ${b.assignees.map(formatAssignee).join(', ')}`
91
94
  : 'unassigned';
92
95
  return [
93
- `${logSymbols.info} task '${b.task}' is visible but not yet executable (${who}).`,
96
+ `${logSymbols.info} activity '${b.activity}' is visible but not yet executable (${who}).`,
94
97
  `Unmet requirement(s): ${b.requirements.join(', ')}. It can't be acted on until`,
95
98
  `those preconditions are met — check what would satisfy them (a prerequisite`,
96
- `task completing, required content landing). It will not advance on its own.`,
99
+ `activity completing, required content landing). It will not advance on its own.`,
97
100
  ];
98
101
  }
99
102
  function noTransitionDetail() {
100
103
  return {
101
104
  headline: `no exit transition's filter is satisfied`,
102
105
  why: [
103
- `${logSymbols.info} every task is resolved, but no exit transition's filter is true.`,
106
+ `${logSymbols.info} every activity is resolved, but no exit transition's filter is true.`,
104
107
  `Likely a routing state value a filter reads never got written.`,
105
108
  ],
106
109
  };
@@ -114,7 +117,7 @@ function transitionUnevaluableDetail(transitions) {
114
117
  return {
115
118
  headline: `an exit transition's filter could not be evaluated`,
116
119
  why: [
117
- `${logSymbols.info} every task is resolved, but ${transitions.join(', ')} reads an operand`,
120
+ `${logSymbols.info} every activity is resolved, but ${transitions.join(', ')} reads an operand`,
118
121
  `that is missing or unreadable (GROQ null), so routing is held rather than`,
119
122
  `falling through. Make the data the filter reads readable — publish the`,
120
123
  `subject (or fill the field) — and the instance advances on its own; no`,
@@ -125,7 +128,7 @@ function transitionUnevaluableDetail(transitions) {
125
128
  const REMEDIATION_LABEL = {
126
129
  'retry-effect': 'retry-effect',
127
130
  'drain-effects': 're-run the effect drainer',
128
- 'reset-task': 'reset-task',
131
+ 'reset-activity': 'reset-activity',
129
132
  'set-stage': 'move-stage',
130
133
  abort: 'abort',
131
134
  };
@@ -142,8 +145,8 @@ function causeDetail(cause) {
142
145
  return failedEffectDetail(cause.effect);
143
146
  case 'hung-effect':
144
147
  return hungEffectDetail(cause.effect);
145
- case 'failed-task':
146
- return failedTaskDetail(cause.task);
148
+ case 'failed-activity':
149
+ return failedActivityDetail(cause.activity);
147
150
  case 'no-transition-fires':
148
151
  return noTransitionDetail();
149
152
  case 'transition-unevaluable':
@@ -169,14 +172,14 @@ function statusLine(diagnosis) {
169
172
  }
170
173
  }
171
174
  /**
172
- * The diagnosis body: the verdict line, the current stage's tasks +
175
+ * The diagnosis body: the verdict line, the current stage's activities +
173
176
  * transitions as evidence (for any in-flight state), and the cause block with
174
177
  * the engine's suggested fix when stuck. Pure so every verdict permutation is
175
178
  * assertable without driving a live evaluation. Takes the engine's
176
179
  * {@link SuggestedRemediation}s rather than re-deriving them, so the rendered
177
180
  * fix block and the `--json` output stay one computation.
178
181
  */
179
- export function renderDiagnosis(diagnosis, input, remediations) {
182
+ export function renderDiagnosis({ diagnosis, input, remediations, }) {
180
183
  const lines = [statusLine(diagnosis)];
181
184
  const inFlight = diagnosis.state === 'progressing' ||
182
185
  diagnosis.state === 'waiting' ||
@@ -232,7 +235,7 @@ export default class Diagnose extends Command {
232
235
  workflowResource: config.workflowResource,
233
236
  instanceId: args.instanceId,
234
237
  // Token-auth CLI can't hit /users/me; pin the same system actor the
235
- // write verbs use. Transition filters and task status are actor-
238
+ // write verbs use. Transition filters and activity status are actor-
236
239
  // independent. A requirement that reads $actor/$assigned/$can is the
237
240
  // exception — it's evaluated against this system actor, so a `blocked`
238
241
  // verdict on such a requirement reflects the engine's view, not a
@@ -252,7 +255,7 @@ export default class Diagnose extends Command {
252
255
  }
253
256
  this.log(instanceHeader(evaluation.instance));
254
257
  this.log('');
255
- for (const line of renderDiagnosis(diagnosis, input, remediations)) {
258
+ for (const line of renderDiagnosis({ diagnosis, input, remediations })) {
256
259
  this.log(line);
257
260
  }
258
261
  }
@@ -9,12 +9,16 @@ import { type RanOp } from '../lib/ops-report.ts';
9
9
  */
10
10
  export declare function parseParams(pairs: string[]): Record<string, unknown>;
11
11
  /**
12
- * The list-mode body: every action on the current stage's tasks, marked
12
+ * The list-mode body: every action on the current stage's activities, marked
13
13
  * fireable or not (with the disabling reason), plus a hint showing the
14
14
  * flags to fire one. Pure so the populated/empty permutations assert
15
15
  * without a live evaluation.
16
16
  */
17
- export declare function renderAvailableActions(actions: AvailableAction[], stage: string, instanceId: string): string[];
17
+ export declare function renderAvailableActions({ actions, stage, instanceId, }: {
18
+ actions: AvailableAction[];
19
+ stage: string;
20
+ instanceId: string;
21
+ }): string[];
18
22
  interface FireOutcome {
19
23
  fired: boolean;
20
24
  cascaded: number;
@@ -27,7 +31,7 @@ interface FireOutcome {
27
31
  * {@link fireActionReport}. Pure so its shape is asserted directly. */
28
32
  export declare function fireResultJson(result: FireOutcome, ids: {
29
33
  instanceId: string;
30
- task: string;
34
+ activity: string;
31
35
  action: string;
32
36
  }): Record<string, unknown>;
33
37
  export interface FireActionReport {
@@ -40,7 +44,11 @@ export interface FireActionReport {
40
44
  * the fired / no-op / cascaded / ops permutations assert without a live
41
45
  * fire.
42
46
  */
43
- export declare function fireActionReport(result: FireOutcome, task: string, action: string): FireActionReport;
47
+ export declare function fireActionReport({ result, activity, action, }: {
48
+ result: FireOutcome;
49
+ activity: string;
50
+ action: string;
51
+ }): FireActionReport;
44
52
  export default class FireAction extends Command {
45
53
  static description: string;
46
54
  static examples: string[];
@@ -48,7 +56,7 @@ export default class FireAction extends Command {
48
56
  instanceId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
49
57
  };
50
58
  static flags: {
51
- task: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
59
+ activity: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
52
60
  action: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
53
61
  param: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
54
62
  as: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;