Skip to content

Overview

@saflib/workflows is the workflow engine for SAF — TypeScript-defined, agent-supervised routines that copy templates, run commands, prompt for edits, and validate results. Platform and product packages export workflow definitions; @saflib/workflows-cli registers and runs them via saf-workflow.

Workflows run on XState internally via step machines; you do not use XState directly. See @saflib/xstate for the thin helper package and current/planned role.

Extended narrative and examples also live on workflows.saf-demo.online.

What this package provides

ExportRole
defineWorkflow / stepDeclare a workflow (id, input, context, steps, …)
makeWorkflowMachineNest one workflow inside another as a step
Step machinesCopyStepMachine, UpdateStepMachine, PromptStepMachine, CommandStepMachine, CdStepMachine, NpmScriptStepMachine, TransformFileStepMachine
HelpersmakeLineReplace, parsePath, parsePackageName, offshoot init helpers
runWorkflow / runWorkflowCliExecute or expose workflows programmatically

Package exports: @saflib/workflows (engine) and @saflib/workflows/workflows (meta workflows including workflows/add-workflow).

Running workflows

From a package directory (must contain package.json):

bash
npm exec saf-workflow list              # workflows available here
npm exec saf-workflow kickoff <id>    # start a workflow
npm exec saf-workflow checklist <id>    # preview steps
npm exec saf-workflow dry-run         # alias for dry/script validation

Common ids look like vue/add-view, openapi/add-route, product/init, processes/spec-project. See per-package docs/workflows/ indexes (e.g. vue, openapi, sdk).

Execution modes

ModePurpose
checklistGenerate a generic step list (uses example args; no cwd side effects)
dryValidate inputs and flow without writes, commands, or prompts
scriptRun mechanical steps only — copies, commands; skips prompts and TODO checks
printEmit prompts and logs; halt at prompts for an external agent
runTool drives the agent (e.g. Cursor CLI) through each step

Use script or dry to verify wiring before print/run. UpdateStepMachine blocks progress while copied files still contain TODO markers (skippable with --skip-todos).

Authoring a workflow

  1. Add workflows/<name>.ts in your package with defineWorkflow({ id: "package/<name>", … }).
  2. Export it from workflows/index.ts (default export array + named exports).
  3. Register the package in workflows-cli/list.ts inside the workflow-cli-imports / workflow-cli-spreads areas — or run workflows/add-workflow to scaffold steps 1–3.

Typical step sequence:

  1. CopyStepMachine — scaffold from @saflib/templates with makeLineReplace(context).
  2. UpdateStepMachine — agent fills generated files (links docFiles for context).
  3. PromptStepMachine — freeform user/agent checkpoint.
  4. CommandStepMachine / NpmScriptStepMachinetypecheck, test, codegen.
  5. CdStepMachine — change cwd before steps that target another package.

Set versionControl.allowPaths so git commits stay scoped. Nested work uses makeWorkflowMachine(OtherWorkflowDefinition).

Where workflows live

AreaExamples
Platformvue/add-view, openapi/add-route, workflows/add-workflow
Product scaffoldingproduct/init
Agent planningprocesses/spec-project

Workflow definitions are normal TypeScript — test with runWorkflow(def, { mode: "checklist", … }) in package tests.