@sanity/workflow-cli 0.12.0 → 0.13.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +45 -26
  3. package/dist/commands/{abort.d.ts → editorial-workflows/abort.d.ts} +3 -2
  4. package/dist/commands/{abort.js → editorial-workflows/abort.js} +7 -6
  5. package/dist/commands/{definition → editorial-workflows/definition}/delete.d.ts +3 -2
  6. package/dist/commands/{definition → editorial-workflows/definition}/delete.js +6 -5
  7. package/dist/commands/{definition → editorial-workflows/definition}/diff.d.ts +2 -1
  8. package/dist/commands/{definition → editorial-workflows/definition}/diff.js +7 -6
  9. package/dist/commands/{definition → editorial-workflows/definition}/list.d.ts +2 -1
  10. package/dist/commands/{definition → editorial-workflows/definition}/list.js +21 -21
  11. package/dist/commands/{definition → editorial-workflows/definition}/show.d.ts +3 -2
  12. package/dist/commands/{definition → editorial-workflows/definition}/show.js +7 -6
  13. package/dist/commands/{deploy.d.ts → editorial-workflows/deploy.d.ts} +2 -1
  14. package/dist/commands/{deploy.js → editorial-workflows/deploy.js} +14 -13
  15. package/dist/commands/{diagnose.d.ts → editorial-workflows/diagnose.d.ts} +2 -1
  16. package/dist/commands/{diagnose.js → editorial-workflows/diagnose.js} +7 -6
  17. package/dist/commands/{fire-action.d.ts → editorial-workflows/fire-action.d.ts} +3 -2
  18. package/dist/commands/{fire-action.js → editorial-workflows/fire-action.js} +8 -7
  19. package/dist/commands/{list.d.ts → editorial-workflows/list.d.ts} +2 -1
  20. package/dist/commands/{list.js → editorial-workflows/list.js} +24 -24
  21. package/dist/commands/{nuke.d.ts → editorial-workflows/nuke.d.ts} +2 -1
  22. package/dist/commands/{nuke.js → editorial-workflows/nuke.js} +10 -9
  23. package/dist/commands/{reset-activity.d.ts → editorial-workflows/reset-activity.d.ts} +2 -1
  24. package/dist/commands/{reset-activity.js → editorial-workflows/reset-activity.js} +2 -1
  25. package/dist/commands/{set-stage.d.ts → editorial-workflows/set-stage.d.ts} +4 -3
  26. package/dist/commands/{set-stage.js → editorial-workflows/set-stage.js} +6 -5
  27. package/dist/commands/{show.d.ts → editorial-workflows/show.d.ts} +2 -1
  28. package/dist/commands/{show.js → editorial-workflows/show.js} +40 -26
  29. package/dist/commands/{start.d.ts → editorial-workflows/start.d.ts} +3 -2
  30. package/dist/commands/{start.js → editorial-workflows/start.js} +9 -8
  31. package/dist/commands/{tail.d.ts → editorial-workflows/tail.d.ts} +2 -1
  32. package/dist/commands/{tail.js → editorial-workflows/tail.js} +6 -5
  33. package/dist/hooks/finally/telemetry.js +2 -2
  34. package/dist/hooks/prerun/telemetry.d.ts +4 -3
  35. package/dist/lib/base-command.d.ts +4 -6
  36. package/dist/lib/base-command.js +6 -0
  37. package/dist/lib/flags.d.ts +4 -3
  38. package/dist/lib/prompt.d.ts +3 -2
  39. package/dist/lib/select-deployment.d.ts +12 -7
  40. package/dist/lib/select-deployment.js +26 -1
  41. package/dist/lib/share-definitions.d.ts +23 -28
  42. package/dist/lib/share-definitions.js +26 -38
  43. package/dist/lib/telemetry-setup.d.ts +2 -2
  44. package/dist/lib/telemetry.d.ts +18 -10
  45. package/dist/lib/telemetry.js +5 -2
  46. package/dist/lib/ui.d.ts +12 -0
  47. package/dist/lib/ui.js +9 -0
  48. package/oclif.manifest.json +93 -48
  49. package/package.json +11 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # @sanity/workflow-cli
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 58f8211: Every command's canonical oclif id now nests under the `editorial-workflows` topic, making the package mountable as a plugin of the `sanity` CLI (`sanity editorial-workflows deploy`) without colliding with host commands. The standalone surface is unchanged: the bare forms (`sanity-workflows deploy`, `sanity-workflows definition list`, …) remain as aliases of the nested ids.
8
+ - 00c089d: **BREAKING:** Require every definition deployment and workflow deployment configuration to state an `expectedMinReaderModel` literal that exactly matches the installed engine's writer capability.
9
+
10
+ Deploy and definition-diff paths now reject missing or stale acknowledgements before client access or telemetry, with a structured error and readers-first rollout guidance.
11
+
12
+ - 53661fa: Prompt interactive deploys to select a configured deployment tag when several are available and no selector flag was supplied. Render Ctrl+C prompt cancellations without a stack trace.
13
+
14
+ ### Patch Changes
15
+
16
+ - 82e4a4e: Fix definition sharing to honor its opt-out contract: deploys now share newly created definition versions by default in every environment, including CI, `DO_NOT_TRACK`, and non-TTY runs. The first interactive run shows a mandatory disclosure rather than a consent choice, every other flagless run prints a clear status block with the explicit opt-in and opt-out flags, and only `--no-share-defs` suppresses sharing for that invocation.
17
+ - 9126299: **BREAKING:** Delete persisted stage guard documents when their stage exits, and remove the lifted-record `GUARD_LIFTED_PREDICATE` and `isGuardLifted` exports.
18
+
19
+ Guard deletion now uses the observed document revision so stale exit reconciliation cannot delete a guard reactivated by a newer stage visit. Reactive guard streams contain only active persisted guards.
20
+
21
+ - Updated dependencies [239d9f6]
22
+ - Updated dependencies [3af2ca0]
23
+ - Updated dependencies [7276702]
24
+ - Updated dependencies [58f8211]
25
+ - Updated dependencies [00c089d]
26
+ - Updated dependencies [71cd58e]
27
+ - Updated dependencies [cd03973]
28
+ - Updated dependencies [d26cc1a]
29
+ - Updated dependencies [9126299]
30
+ - Updated dependencies [72018af]
31
+ - Updated dependencies [5cd8ffd]
32
+ - Updated dependencies [b82bda4]
33
+ - Updated dependencies [55a54b3]
34
+ - Updated dependencies [b82bda4]
35
+ - Updated dependencies [4490442]
36
+ - Updated dependencies [1540dce]
37
+ - @sanity/workflow-engine@0.18.0
38
+
3
39
  ## 0.12.0
4
40
 
5
41
  ### Minor Changes
package/README.md CHANGED
@@ -20,6 +20,19 @@ pnpm --filter @sanity/workflow-cli dev list --include-completed
20
20
  pnpm --filter @sanity/workflow-cli dev show wf-instance.abc123
21
21
  ```
22
22
 
23
+ The package is an [oclif](https://oclif.io) plugin: every command's canonical
24
+ id nests under the `editorial-workflows` topic
25
+ (`sanity-workflows editorial-workflows deploy`), so mounting the package into
26
+ the `sanity` CLI's plugin list surfaces the same commands as
27
+ `sanity editorial-workflows …` without its canonical ids colliding with the
28
+ host's own commands (the sanity CLI already has a `deploy`). The bare forms
29
+ used throughout this README (`deploy`, `definition list`, …) are aliases of
30
+ the nested ids and are the standalone binary's stable surface. oclif registers
31
+ plugin aliases in a host unconditionally (an id collision resolves by plugin
32
+ priority, host first), so a host mount would also surface these bare aliases
33
+ at its root — trimming or hiding them for the mounted context is part of the
34
+ host-side mount work, not something a host can configure away.
35
+
23
36
  Authenticate once with `sanity login` (the CLI reads that session token); for
24
37
  CI, set `SANITY_AUTH_TOKEN` instead. Then create a `sanity.workflow.ts` in the
25
38
  directory you run from — see [Configuration](#configuration).
@@ -46,6 +59,7 @@ import {articleReview, urlDraft} from './src/workflows.ts'
46
59
  export default defineWorkflowConfig({
47
60
  deployments: [
48
61
  {
62
+ expectedMinReaderModel: 2,
49
63
  name: 'production',
50
64
  tag: 'prod', // the environment partition the engine's docs are scoped to
51
65
  workflowResource: {type: 'dataset', id: 'acme.workflows'}, // where those docs live
@@ -63,13 +77,15 @@ export default defineWorkflowConfig({
63
77
  ```
64
78
 
65
79
  Pick a deployment with `--tag <tag>`; with a single deployment configured you
66
- can omit it, and with several configured a bare `deploy` fails asking for
67
- `--tag` or `--all-tags`. `--all-tags` deploys every deployment in the config in
68
- one run: a failure in one doesn't stop the rest — the run continues, prints a
69
- summary of what failed, and exits non-zero. The client's project + dataset are derived
70
- from the deployment's `workflowResource`, and `deploy` expands each
71
- definition's `@<handle>:` reference to the bound physical resource. An invalid
72
- config fails with a clean, path-prefixed error before the command runs.
80
+ can omit it. With several configured, a bare interactive `deploy` presents a
81
+ keyboard-driven tag selector. In CI or another non-interactive shell, it fails
82
+ asking for `--tag` or `--all-tags` instead of blocking for input. `--all-tags`
83
+ deploys every deployment in the config in one run: a failure in one doesn't
84
+ stop the rest the run continues, prints a summary of what failed, and exits
85
+ non-zero. The client's project + dataset are derived from the deployment's
86
+ `workflowResource`, and `deploy` expands each definition's `@<handle>:`
87
+ reference to the bound physical resource. An invalid config fails with a clean,
88
+ path-prefixed error before the command runs.
73
89
 
74
90
  `resourceAliases` is only for content that lives in a _different_ resource from
75
91
  `workflowResource`. A definition can reference a document in the **same**
@@ -139,7 +155,7 @@ stale compiled output.
139
155
  | `show <instance-id>` | wired — `client.getDocument` |
140
156
  | `diagnose <instance-id>` | wired — calls `workflow.diagnose`, classifies why the instance is/isn't progressing |
141
157
  | `tail <instance-id>` | wired — `client.listen()` over the instance, prints new history entries |
142
- | `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects, lifts guards) |
158
+ | `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects, removes guards) |
143
159
  | `set-stage <instance-id> --to <stage>` | wired — calls `workflow.setStage` (admin override: skips declared transitions/filters; enter lifecycle + cascade still run) |
144
160
  | `fire-action <instance-id>` | wired — `workflow.availableActions` lists actions; `workflow.fireAction` fires one |
145
161
  | `definition list` | wired — `client.fetch` over `sanity.workflow.definition` documents |
@@ -155,8 +171,9 @@ per-command trace (`Editorial Workflows CLI Command Executed` — the command id
155
171
  names of declared flags used, never their values, and a success flag) plus
156
172
  the engine's adoption events from the operations it drives. Consent is the
157
173
  account-wide status managed by `npx sanity telemetry enable|disable|status`;
158
- CI and trueish `DO_NOT_TRACK` suppress everything (except a `deploy --share-defs`,
159
- which forces that deploy's telemetry see [Definition sharing](#definition-sharing)),
174
+ CI and trueish `DO_NOT_TRACK` suppress everything (except a deploy that may share
175
+ new definitions, which forces that deploy's telemetry unless `--no-share-defs`
176
+ is passed — see [Definition sharing](#definition-sharing)),
160
177
  and a session that isn't logged in sends nothing. A one-time notice on stderr
161
178
  discloses collection on first use.
162
179
 
@@ -176,25 +193,27 @@ definition-feedback endpoint, not the telemetry pipeline; telemetry carries
176
193
  only a content-free marker (content hash plus structural counts) per shared
177
194
  definition and a per-invocation decision event.
178
195
 
179
- Sharing is **opt-out**. Pass `--share-defs` to donate without being asked, or
180
- `--no-share-defs` to decline. With neither flag, an interactive terminal is
181
- asked **once** the answer is remembered in your Sanity user config, so the
182
- prompt never repeats before anything is sent; notice always precedes the
183
- send. Every later flagless deploy then prints a one-line reminder of the
184
- current state (sharing, or not) and the flag to change it, so an ongoing
185
- donation is never silent. Unattended runs (CI, `DO_NOT_TRACK`, a non-TTY pipe)
186
- can't prompt: by default they donate nothing (opt in per run with
187
- `--share-defs`). An explicit `--share-defs` also sends that deploy's telemetry
188
- regardless of CI / `DO_NOT_TRACK` a command-line arg beats env vars;
189
- account-level `sanity telemetry disable` still applies. A failed share only
190
- warns, never failing a completed deploy.
196
+ Sharing is **opt-out in every environment**. Pass `--no-share-defs` to decline
197
+ for one invocation. With neither flag, the first interactive deploy prints a
198
+ full notice before sending and remembers that the notice was shown; every later
199
+ flagless deploy prints a status block showing that sharing is on by default and
200
+ showing runnable shell examples for the default, explicit opt-in, and opt-out
201
+ forms; the explicit flags suppress the status block. Unattended runs (CI,
202
+ `DO_NOT_TRACK`, or a non-TTY pipe) also share by default and print that status
203
+ block in their logs.
204
+ A flagless deploy or explicit `--share-defs` forces that deploy's telemetry
205
+ through the environment gate so donated definitions retain their content-free
206
+ markers; account-level `sanity telemetry disable` still applies. A failed share
207
+ only warns, never failing a completed deploy.
191
208
 
192
209
  ## Known gaps
193
210
 
194
- - **No `sanity workflow` plugin wiring yet.** The proposal targets the
195
- Sanity CLI as a plugin host. The package publishes as a standalone
196
- `sanity-workflows` binary today; plugging into `sanity` as an oclif
197
- plugin is a separate piece of work.
211
+ - **Not mounted in the `sanity` CLI yet.** The package side is mount-ready —
212
+ commands nest under the `editorial-workflows` oclif topic (see
213
+ [Run](#run)) — but the `sanity` CLI does not list this package in its
214
+ plugin array, so the commands ship only through the standalone
215
+ `sanity-workflows` binary today. The host-side mount (and what happens to
216
+ the bare aliases inside a host) is a separate piece of work.
198
217
  - **No true bypass.** `set-stage` is the engine's `setStage` admin
199
218
  override: it skips the definition's declared transitions and filters, but
200
219
  the target stage's enter lifecycle and the post-move cascade still run. A
@@ -1,7 +1,8 @@
1
1
  import { type WorkflowInstance } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../lib/base-command.ts';
3
- import { type WriteReport } from '../lib/ops-report.ts';
2
+ import { WorkflowCommand } from '../../lib/base-command.ts';
3
+ import { type WriteReport } from '../../lib/ops-report.ts';
4
4
  export default class Abort extends WorkflowCommand {
5
+ static aliases: string[];
5
6
  static description: string;
6
7
  static examples: string[];
7
8
  static args: {
@@ -1,13 +1,14 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { workflow } from '@sanity/workflow-engine';
4
- import { WorkflowCommand } from "../lib/base-command.js";
5
- import { resolveInstanceContext } from "../lib/context.js";
6
- import { tagFlags } from "../lib/flags.js";
7
- import { buildOperationArgs } from "../lib/operation-args.js";
8
- import { runWriteVerb } from "../lib/ops-report.js";
4
+ import { WorkflowCommand } from "../../lib/base-command.js";
5
+ import { resolveInstanceContext } from "../../lib/context.js";
6
+ import { tagFlags } from "../../lib/flags.js";
7
+ import { buildOperationArgs } from "../../lib/operation-args.js";
8
+ import { runWriteVerb } from "../../lib/ops-report.js";
9
9
  export default class Abort extends WorkflowCommand {
10
- static description = 'Abort an in-flight workflow instance — a hard stop: pending effects are cancelled, stage guards lifted, and the instance is marked terminal where it stands.';
10
+ static aliases = ['abort'];
11
+ static description = 'Abort an in-flight workflow instance — a hard stop: pending effects are cancelled, stage guards removed, and the instance is marked terminal where it stands.';
11
12
  static examples = [
12
13
  '<%= config.bin %> abort wf-instance.abc123',
13
14
  "<%= config.bin %> abort wf-instance.abc123 --reason 'superseded by relaunch'",
@@ -1,7 +1,8 @@
1
1
  import { type DeleteDefinitionArgs, type DeleteDefinitionResult } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../../lib/base-command.ts';
3
- import { type EngineScope } from '../../lib/operation-args.ts';
2
+ import { WorkflowCommand } from '../../../lib/base-command.ts';
3
+ import { type EngineScope } from '../../../lib/operation-args.ts';
4
4
  export default class DefinitionDelete extends WorkflowCommand {
5
+ static aliases: string[];
5
6
  static description: string;
6
7
  static examples: string[];
7
8
  static args: {
@@ -1,12 +1,13 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { workflow, } from '@sanity/workflow-engine';
4
- import { WorkflowCommand } from "../../lib/base-command.js";
5
- import { resolveContext } from "../../lib/context.js";
6
- import { tagFlags } from "../../lib/flags.js";
7
- import { baseEngineArgs } from "../../lib/operation-args.js";
8
- import { runWriteVerb } from "../../lib/ops-report.js";
4
+ import { WorkflowCommand } from "../../../lib/base-command.js";
5
+ import { resolveContext } from "../../../lib/context.js";
6
+ import { tagFlags } from "../../../lib/flags.js";
7
+ import { baseEngineArgs } from "../../../lib/operation-args.js";
8
+ import { runWriteVerb } from "../../../lib/ops-report.js";
9
9
  export default class DefinitionDelete extends WorkflowCommand {
10
+ static aliases = ['definition:delete'];
10
11
  static description = 'Delete a deployed workflow definition (every version, or one via --version). ' +
11
12
  'Refuses while non-terminal instances exist unless --cascade aborts them first — ' +
12
13
  'instances are aborted in place, never deleted.';
@@ -1,6 +1,7 @@
1
1
  import { type WorkflowDefinition } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../../lib/base-command.ts';
2
+ import { WorkflowCommand } from '../../../lib/base-command.ts';
3
3
  export default class DefinitionDiff extends WorkflowCommand {
4
+ static aliases: string[];
4
5
  static description: string;
5
6
  static examples: string[];
6
7
  static args: {
@@ -1,13 +1,14 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
2
  import { diffEntry } from '@sanity/workflow-engine';
3
3
  import ora from 'ora';
4
- import { WorkflowCommand } from "../../lib/base-command.js";
5
- import { resolveContext } from "../../lib/context.js";
6
- import { fetchDeployedDefinition, selectDefinitions, validateOrFail } from "../../lib/definitions.js";
7
- import { diffReport } from "../../lib/diff.js";
8
- import { tagFlags } from "../../lib/flags.js";
9
- import { deploymentToTarget } from "../../lib/select-deployment.js";
4
+ import { WorkflowCommand } from "../../../lib/base-command.js";
5
+ import { resolveContext } from "../../../lib/context.js";
6
+ import { fetchDeployedDefinition, selectDefinitions, validateOrFail, } from "../../../lib/definitions.js";
7
+ import { diffReport } from "../../../lib/diff.js";
8
+ import { tagFlags } from "../../../lib/flags.js";
9
+ import { deploymentToTarget } from "../../../lib/select-deployment.js";
10
10
  export default class DefinitionDiff extends WorkflowCommand {
11
+ static aliases = ['definition:diff'];
11
12
  static description = 'Diff an in-code definition against the deployed version (latest by default).';
12
13
  static examples = [
13
14
  '<%= config.bin %> definition diff productLaunch',
@@ -1,4 +1,4 @@
1
- import { WorkflowCommand } from '../../lib/base-command.ts';
1
+ import { WorkflowCommand } from '../../../lib/base-command.ts';
2
2
  interface DefinitionListFlags {
3
3
  tag?: string | undefined;
4
4
  name?: string | undefined;
@@ -22,6 +22,7 @@ export declare function buildDefinitionListQuery(flags: DefinitionListFlags): {
22
22
  params: Record<string, unknown>;
23
23
  };
24
24
  export default class DefinitionList extends WorkflowCommand {
25
+ static aliases: string[];
25
26
  static description: string;
26
27
  static examples: string[];
27
28
  static flags: {
@@ -1,11 +1,11 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, assertReadableModel, inFlightFilter, tagScopeFilter, } from '@sanity/workflow-engine';
3
3
  import logSymbols from 'log-symbols';
4
- import { WorkflowCommand } from "../../lib/base-command.js";
5
- import { resolveReadTargets } from "../../lib/context.js";
6
- import { tagFlags } from "../../lib/flags.js";
7
- import { runReadAcrossTargets } from "../../lib/read-fanout.js";
8
- import { clipToLimit, formatTable } from "../../lib/ui.js";
4
+ import { WorkflowCommand } from "../../../lib/base-command.js";
5
+ import { resolveReadTargets } from "../../../lib/context.js";
6
+ import { tagFlags } from "../../../lib/flags.js";
7
+ import { runReadAcrossTargets } from "../../../lib/read-fanout.js";
8
+ import { logClippedTable } from "../../../lib/ui.js";
9
9
  export function buildDefinitionListQuery(flags) {
10
10
  const params = { limit: flags.limit + 1 };
11
11
  const filters = [`_type == "${WORKFLOW_DEFINITION_TYPE}"`];
@@ -40,6 +40,7 @@ export function buildDefinitionListQuery(flags) {
40
40
  return { groq, params };
41
41
  }
42
42
  export default class DefinitionList extends WorkflowCommand {
43
+ static aliases = ['definition:list'];
43
44
  static description = 'List deployed workflow definitions.';
44
45
  static examples = [
45
46
  '<%= config.bin %> definition list',
@@ -70,22 +71,21 @@ export default class DefinitionList extends WorkflowCommand {
70
71
  this.log(`${logSymbols.info} no definitions found`);
71
72
  return;
72
73
  }
73
- const { rows, note } = clipToLimit(fetched, flags.limit);
74
- const lines = formatTable(['workflow', 'title', 'tag', 'stages', 'in flight', 'instances', 'created'], rows.map((r) => [
75
- `${r.name} v${r.version}`,
76
- r.title,
77
- r.tag,
78
- String(r.stageCount),
79
- String(r.inFlightCount),
80
- String(r.totalInstances),
81
- r._createdAt,
82
- ]));
83
- for (const line of lines) {
84
- this.log(line);
85
- }
86
- if (note) {
87
- this.log(note);
88
- }
74
+ logClippedTable({
75
+ rows: fetched,
76
+ limit: flags.limit,
77
+ headers: ['workflow', 'title', 'tag', 'stages', 'in flight', 'instances', 'created'],
78
+ toCells: (r) => [
79
+ `${r.name} v${r.version}`,
80
+ r.title,
81
+ r.tag,
82
+ String(r.stageCount),
83
+ String(r.inFlightCount),
84
+ String(r.totalInstances),
85
+ r._createdAt,
86
+ ],
87
+ log: (line) => this.log(line),
88
+ });
89
89
  },
90
90
  });
91
91
  if (failures.length > 0) {
@@ -1,7 +1,8 @@
1
1
  import { type DeployedDefinition, type WorkflowDefinition, type WorkflowResource } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../../lib/base-command.ts';
3
- import { type ReadTarget } from '../../lib/context.ts';
2
+ import { WorkflowCommand } from '../../../lib/base-command.ts';
3
+ import { type ReadTarget } from '../../../lib/context.ts';
4
4
  export default class DefinitionShow extends WorkflowCommand {
5
+ static aliases: string[];
5
6
  static description: string;
6
7
  static args: {
7
8
  name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -2,13 +2,14 @@ import { styleText } from 'node:util';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { assertReadableModel, isTerminalStage, } from '@sanity/workflow-engine';
4
4
  import logSymbols from 'log-symbols';
5
- import { WorkflowCommand } from "../../lib/base-command.js";
6
- import { resolveReadTargets, soleHitOrFail } from "../../lib/context.js";
7
- import { buildDefinitionShowQuery, buildDefinitionTagsQuery } from "../../lib/definitions.js";
8
- import { fail } from "../../lib/fail.js";
9
- import { tagFlags } from "../../lib/flags.js";
10
- import { formatKeyValue, resourceLabel, sectionHeader } from "../../lib/ui.js";
5
+ import { WorkflowCommand } from "../../../lib/base-command.js";
6
+ import { resolveReadTargets, soleHitOrFail } from "../../../lib/context.js";
7
+ import { buildDefinitionShowQuery, buildDefinitionTagsQuery } from "../../../lib/definitions.js";
8
+ import { fail } from "../../../lib/fail.js";
9
+ import { tagFlags } from "../../../lib/flags.js";
10
+ import { formatKeyValue, resourceLabel, sectionHeader } from "../../../lib/ui.js";
11
11
  export default class DefinitionShow extends WorkflowCommand {
12
+ static aliases = ['definition:show'];
12
13
  static description = 'Show a deployed workflow definition.';
13
14
  static args = {
14
15
  name: Args.string({ required: true, description: 'Workflow definition name.' }),
@@ -1,5 +1,5 @@
1
1
  import { type DeployDefinitionResult, type WorkflowDefinition, type WorkflowDeployment } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../lib/base-command.ts';
2
+ import { WorkflowCommand } from '../../lib/base-command.ts';
3
3
  /** A deployment paired with the definitions selected + validated for it. */
4
4
  interface DeployBatch {
5
5
  deployment: WorkflowDeployment;
@@ -11,6 +11,7 @@ interface DeployFailure {
11
11
  message: string;
12
12
  }
13
13
  export default class Deploy extends WorkflowCommand {
14
+ static aliases: string[];
14
15
  static description: string;
15
16
  static examples: string[];
16
17
  static flags: {
@@ -3,18 +3,19 @@ import { Flags } from '@oclif/core';
3
3
  import { computeDiffEntries, errorMessage, workflow, } from '@sanity/workflow-engine';
4
4
  import logSymbols from 'log-symbols';
5
5
  import ora from 'ora';
6
- import { WorkflowCommand } from "../lib/base-command.js";
7
- import { clientFor, resolveTokenOrFail } from "../lib/client.js";
8
- import { selectDefinitions, validateOrFail } from "../lib/definitions.js";
9
- import { diffReport } from "../lib/diff.js";
10
- import { fail, isAuthRejection } from "../lib/fail.js";
11
- import { tagFlags } from "../lib/flags.js";
12
- import { loadWorkflowConfig } from "../lib/load-config.js";
13
- import { deploymentToTarget, selectDeployments } from "../lib/select-deployment.js";
14
- import { shareDefinitionsAfterDeploy } from "../lib/share-definitions.js";
15
- import { cliTelemetry } from "../lib/telemetry.js";
16
- import { groupBanner } from "../lib/ui.js";
6
+ import { WorkflowCommand } from "../../lib/base-command.js";
7
+ import { clientFor, resolveTokenOrFail } from "../../lib/client.js";
8
+ import { selectDefinitions, validateOrFail } from "../../lib/definitions.js";
9
+ import { diffReport } from "../../lib/diff.js";
10
+ import { fail, isAuthRejection } from "../../lib/fail.js";
11
+ import { tagFlags } from "../../lib/flags.js";
12
+ import { loadWorkflowConfig } from "../../lib/load-config.js";
13
+ import { deploymentToTarget, selectDeployments } from "../../lib/select-deployment.js";
14
+ import { shareDefinitionsAfterDeploy } from "../../lib/share-definitions.js";
15
+ import { cliTelemetry } from "../../lib/telemetry.js";
16
+ import { groupBanner } from "../../lib/ui.js";
17
17
  export default class Deploy extends WorkflowCommand {
18
+ static aliases = ['deploy'];
18
19
  static description = 'Validate, diff, and deploy workflow definitions to the resource bound by the selected deployment.';
19
20
  static examples = [
20
21
  '<%= config.bin %> deploy --tag prod',
@@ -43,14 +44,14 @@ export default class Deploy extends WorkflowCommand {
43
44
  }),
44
45
  'share-defs': Flags.boolean({
45
46
  allowNo: true,
46
- description: 'Share the definition documents newly created by this deploy with Sanity — the full document, verbatim (structure, names, filters, effect configuration, seeded values), plus its deployment coordinates (project and dataset, or resource id); never content documents, instances, or your Sanity auth token. Opt-out: an interactive terminal is asked once (the answer is remembered), while unattended runs (CI / non-TTY / DO_NOT_TRACK) share nothing unless --share-defs is passed. Use --no-share-defs to opt out. An explicit --share-defs also sends telemetry for this deploy regardless of CI / DO_NOT_TRACK.',
47
+ description: 'Share the definition documents newly created by this deploy with Sanity — the full document, verbatim (structure, names, filters, effect configuration, seeded values), plus its deployment coordinates (project and dataset, or resource id); never content documents, instances, or your Sanity auth token. Sharing is the default in every environment, including CI / non-TTY / DO_NOT_TRACK. Use --no-share-defs to opt out.',
47
48
  }),
48
49
  };
49
50
  async run() {
50
51
  const { flags } = await this.parse(Deploy);
51
52
  validateModeFlags(flags.check, flags['dry-run']);
52
53
  const config = await loadWorkflowConfig();
53
- const batches = buildBatches(selectDeployments(config, { tag: flags.tag, allTags: flags['all-tags'] }), flags.only);
54
+ const batches = buildBatches(await selectDeployments(config, { tag: flags.tag, allTags: flags['all-tags'] }), flags.only);
54
55
  const log = (line) => this.log(line);
55
56
  if (flags.check) {
56
57
  await reconcileBatches({
@@ -1,5 +1,5 @@
1
1
  import { type Diagnosis, type DiagnoseInput, type SuggestedRemediation, type WorkflowEvaluation } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../lib/base-command.ts';
2
+ import { WorkflowCommand } from '../../lib/base-command.ts';
3
3
  /** The `--json` transitions payload: raw derived state (atom GROQ, negation,
4
4
  * pivotality, solvable requirement) — structure for scripts, never baked
5
5
  * English. Pure so the shape is a testable contract. */
@@ -32,6 +32,7 @@ export declare function renderDiagnosis({ diagnosis, input, remediations, explan
32
32
  explanations?: ReadonlyMap<string, string> | undefined;
33
33
  }): string[];
34
34
  export default class Diagnose extends WorkflowCommand {
35
+ static aliases: string[];
35
36
  static description: string;
36
37
  static examples: string[];
37
38
  static args: {
@@ -2,12 +2,12 @@ import { styleText } from 'node:util';
2
2
  import { Args } from '@oclif/core';
3
3
  import { diagnoseInputFromEvaluation, workflow, unsatisfiedTransitionSummaries, } from '@sanity/workflow-engine';
4
4
  import logSymbols from 'log-symbols';
5
- import { WorkflowCommand } from "../lib/base-command.js";
6
- import { resolveInstanceContext } from "../lib/context.js";
7
- import { fail, failureDetail } from "../lib/fail.js";
8
- import { jsonFlags, tagFlags } from "../lib/flags.js";
9
- import { baseEngineArgs } from "../lib/operation-args.js";
10
- import { formatTimestamp, sectionHeader, activityIcon } from "../lib/ui.js";
5
+ import { WorkflowCommand } from "../../lib/base-command.js";
6
+ import { resolveInstanceContext } from "../../lib/context.js";
7
+ import { fail, failureDetail } from "../../lib/fail.js";
8
+ import { jsonFlags, tagFlags } from "../../lib/flags.js";
9
+ import { baseEngineArgs } from "../../lib/operation-args.js";
10
+ import { formatTimestamp, sectionHeader, activityIcon } from "../../lib/ui.js";
11
11
  import { instanceHeader } from "./show.js";
12
12
  function formatAssignee(a) {
13
13
  return a.type === 'user' ? `user:${a.id}` : `role:${a.role}`;
@@ -212,6 +212,7 @@ export function renderDiagnosis({ diagnosis, input, remediations, explanations,
212
212
  return lines;
213
213
  }
214
214
  export default class Diagnose extends WorkflowCommand {
215
+ static aliases = ['diagnose'];
215
216
  static description = "Explain why a workflow instance is or isn't progressing, and what would unstick it.";
216
217
  static examples = [
217
218
  '<%= config.bin %> diagnose wf-instance.abc123',
@@ -1,6 +1,6 @@
1
1
  import { type AvailableAction } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../lib/base-command.ts';
3
- import { type WriteOutcome, type WriteReport } from '../lib/ops-report.ts';
2
+ import { WorkflowCommand } from '../../lib/base-command.ts';
3
+ import { type WriteOutcome, type WriteReport } from '../../lib/ops-report.ts';
4
4
  /**
5
5
  * The list-mode body: every action on the current stage's activities, marked
6
6
  * fireable or not (with the disabling reason), plus a hint showing the
@@ -30,6 +30,7 @@ export declare function fireActionReport({ result, activity, action, }: {
30
30
  action: string;
31
31
  }): WriteReport;
32
32
  export default class FireAction extends WorkflowCommand {
33
+ static aliases: string[];
33
34
  static description: string;
34
35
  static examples: string[];
35
36
  static args: {
@@ -2,13 +2,13 @@ import { styleText } from 'node:util';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { actionRendering, actionDisabledDetail, deniedGuardLabels, workflow, } from '@sanity/workflow-engine';
4
4
  import logSymbols from 'log-symbols';
5
- import { WorkflowCommand } from "../lib/base-command.js";
6
- import { resolveInstanceContext } from "../lib/context.js";
7
- import { fail, failOnThrow, failureDetail } from "../lib/fail.js";
8
- import { jsonFlags, tagFlags } from "../lib/flags.js";
9
- import { baseEngineArgs } from "../lib/operation-args.js";
10
- import { cascadeTail, opsAppliedLines, runWriteVerb, } from "../lib/ops-report.js";
11
- import { parseParams } from "../lib/params.js";
5
+ import { WorkflowCommand } from "../../lib/base-command.js";
6
+ import { resolveInstanceContext } from "../../lib/context.js";
7
+ import { fail, failOnThrow, failureDetail } from "../../lib/fail.js";
8
+ import { jsonFlags, tagFlags } from "../../lib/flags.js";
9
+ import { baseEngineArgs } from "../../lib/operation-args.js";
10
+ import { cascadeTail, opsAppliedLines, runWriteVerb, } from "../../lib/ops-report.js";
11
+ import { parseParams } from "../../lib/params.js";
12
12
  import { instanceHeader } from "./show.js";
13
13
  function reasonText(reason) {
14
14
  if (reason.kind === 'mutation-guard-denied') {
@@ -82,6 +82,7 @@ export function fireActionReport({ result, activity, action, }) {
82
82
  };
83
83
  }
84
84
  export default class FireAction extends WorkflowCommand {
85
+ static aliases = ['fire-action'];
85
86
  static description = 'Fire an action on an instance to unstick a waiting activity — the write acts as the configured token. Omit --action to list what can be fired.';
86
87
  static examples = [
87
88
  '<%= config.bin %> fire-action wf-instance.abc123',
@@ -1,5 +1,5 @@
1
1
  import { type TerminalState } from '@sanity/workflow-engine';
2
- import { WorkflowCommand } from '../lib/base-command.ts';
2
+ import { WorkflowCommand } from '../../lib/base-command.ts';
3
3
  interface InstanceRow {
4
4
  _id: string;
5
5
  definition: string;
@@ -45,6 +45,7 @@ export declare function instanceRow(r: InstanceRow): {
45
45
  lastChangedAt: string;
46
46
  };
47
47
  export default class List extends WorkflowCommand {
48
+ static aliases: string[];
48
49
  static description: string;
49
50
  static examples: string[];
50
51
  static flags: {
@@ -1,12 +1,12 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { WORKFLOW_INSTANCE_TYPE, assertReadableModel, documentPrefilter, inFlightFilter, instanceWatchesDocument, tagScopeFilter, terminalState, } from '@sanity/workflow-engine';
3
3
  import logSymbols from 'log-symbols';
4
- import { WorkflowCommand } from "../lib/base-command.js";
5
- import { resolveReadTargets } from "../lib/context.js";
6
- import { failOnThrow } from "../lib/fail.js";
7
- import { tagFlags } from "../lib/flags.js";
8
- import { runReadAcrossTargets } from "../lib/read-fanout.js";
9
- import { clipToLimit, formatAge, formatTable } from "../lib/ui.js";
4
+ import { WorkflowCommand } from "../../lib/base-command.js";
5
+ import { resolveReadTargets } from "../../lib/context.js";
6
+ import { failOnThrow } from "../../lib/fail.js";
7
+ import { tagFlags } from "../../lib/flags.js";
8
+ import { runReadAcrossTargets } from "../../lib/read-fanout.js";
9
+ import { formatAge, logClippedTable } from "../../lib/ui.js";
10
10
  export function buildListQuery(flags) {
11
11
  const filters = [`_type == "${WORKFLOW_INSTANCE_TYPE}"`];
12
12
  const params = {};
@@ -56,6 +56,7 @@ export function instanceRow(r) {
56
56
  };
57
57
  }
58
58
  export default class List extends WorkflowCommand {
59
+ static aliases = ['list'];
59
60
  static description = 'List workflow instances in the configured dataset (in-flight by default).';
60
61
  static examples = [
61
62
  '<%= config.bin %> list',
@@ -100,24 +101,23 @@ export default class List extends WorkflowCommand {
100
101
  this.log(`${logSymbols.info} no instances match`);
101
102
  return;
102
103
  }
103
- const { rows, note } = clipToLimit(fetched, flags.limit);
104
- const lines = formatTable(['instance', 'workflow', 'tag', 'stage', 'status', 'updated'], rows.map((r) => {
105
- const row = instanceRow(r);
106
- return [
107
- row._id,
108
- row.definition,
109
- row.tag,
110
- row.currentStage,
111
- row.status,
112
- formatAge(row.lastChangedAt),
113
- ];
114
- }));
115
- for (const line of lines) {
116
- this.log(line);
117
- }
118
- if (note) {
119
- this.log(note);
120
- }
104
+ logClippedTable({
105
+ rows: fetched,
106
+ limit: flags.limit,
107
+ headers: ['instance', 'workflow', 'tag', 'stage', 'status', 'updated'],
108
+ toCells: (r) => {
109
+ const row = instanceRow(r);
110
+ return [
111
+ row._id,
112
+ row.definition,
113
+ row.tag,
114
+ row.currentStage,
115
+ row.status,
116
+ formatAge(row.lastChangedAt),
117
+ ];
118
+ },
119
+ log: (line) => this.log(line),
120
+ });
121
121
  },
122
122
  });
123
123
  if (failures.length > 0) {