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
| Export | Role |
|---|---|
defineWorkflow / step | Declare a workflow (id, input, context, steps, …) |
makeWorkflowMachine | Nest one workflow inside another as a step |
| Step machines | CopyStepMachine, UpdateStepMachine, PromptStepMachine, CommandStepMachine, CdStepMachine, NpmScriptStepMachine, TransformFileStepMachine |
| Helpers | makeLineReplace, parsePath, parsePackageName, offshoot init helpers |
runWorkflow / runWorkflowCli | Execute 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):
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 validationCommon 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
| Mode | Purpose |
|---|---|
checklist | Generate a generic step list (uses example args; no cwd side effects) |
dry | Validate inputs and flow without writes, commands, or prompts |
script | Run mechanical steps only — copies, commands; skips prompts and TODO checks |
print | Emit prompts and logs; halt at prompts for an external agent |
run | Tool 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
- Add
workflows/<name>.tsin your package withdefineWorkflow({ id: "package/<name>", … }). - Export it from
workflows/index.ts(default export array + named exports). - Register the package in
workflows-cli/list.tsinside theworkflow-cli-imports/workflow-cli-spreadsareas — or run workflows/add-workflow to scaffold steps 1–3.
Typical step sequence:
CopyStepMachine— scaffold from@saflib/templateswithmakeLineReplace(context).UpdateStepMachine— agent fills generated files (linksdocFilesfor context).PromptStepMachine— freeform user/agent checkpoint.CommandStepMachine/NpmScriptStepMachine—typecheck,test, codegen.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
| Area | Examples |
|---|---|
| Platform | vue/add-view, openapi/add-route, workflows/add-workflow |
| Product scaffolding | product/init |
| Agent planning | processes/spec-project |
Workflow definitions are normal TypeScript — test with runWorkflow(def, { mode: "checklist", … }) in package tests.