@bastani/atomic 0.8.1 → 0.8.2

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 (149) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/builtin/intercom/config.ts +3 -4
  3. package/dist/builtin/intercom/index.ts +6 -6
  4. package/dist/builtin/intercom/package.json +1 -1
  5. package/dist/builtin/mcp/agent-dir.ts +11 -2
  6. package/dist/builtin/mcp/cli.js +12 -6
  7. package/dist/builtin/mcp/config.ts +31 -22
  8. package/dist/builtin/mcp/package.json +1 -1
  9. package/dist/builtin/subagents/package.json +1 -1
  10. package/dist/builtin/subagents/src/agents/agents.ts +63 -23
  11. package/dist/builtin/subagents/src/agents/skills.ts +21 -21
  12. package/dist/builtin/subagents/src/extension/index.ts +9 -8
  13. package/dist/builtin/subagents/src/runs/shared/run-history.ts +13 -10
  14. package/dist/builtin/subagents/src/runs/shared/subagent-prompt-runtime.ts +3 -3
  15. package/dist/builtin/subagents/src/shared/artifacts.ts +18 -17
  16. package/dist/builtin/subagents/src/shared/types.ts +4 -4
  17. package/dist/builtin/web-access/config-paths.ts +11 -0
  18. package/dist/builtin/web-access/exa.ts +3 -2
  19. package/dist/builtin/web-access/gemini-api.ts +2 -1
  20. package/dist/builtin/web-access/gemini-search.ts +2 -1
  21. package/dist/builtin/web-access/gemini-web-config.ts +2 -1
  22. package/dist/builtin/web-access/github-extract.ts +2 -1
  23. package/dist/builtin/web-access/index.ts +11 -8
  24. package/dist/builtin/web-access/package.json +1 -1
  25. package/dist/builtin/web-access/perplexity.ts +2 -1
  26. package/dist/builtin/web-access/video-extract.ts +2 -1
  27. package/dist/builtin/web-access/youtube-extract.ts +2 -1
  28. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +4 -0
  29. package/dist/builtin/workflows/builtin/open-claude-design.ts +39 -22
  30. package/dist/builtin/workflows/builtin/ralph.ts +7 -0
  31. package/dist/builtin/workflows/package.json +1 -1
  32. package/dist/builtin/workflows/skills/workflow/SKILL.md +28 -20
  33. package/dist/builtin/workflows/skills/workflow/references/design-checklist.md +8 -4
  34. package/dist/builtin/workflows/skills/workflow/references/running-workflows.md +52 -23
  35. package/dist/builtin/workflows/skills/workflow/references/sdk-authoring.md +41 -12
  36. package/dist/builtin/workflows/src/extension/config-loader.ts +13 -14
  37. package/dist/builtin/workflows/src/extension/discovery.ts +4 -6
  38. package/dist/builtin/workflows/src/extension/index.ts +675 -524
  39. package/dist/builtin/workflows/src/extension/runtime.ts +40 -16
  40. package/dist/builtin/workflows/src/extension/wiring.ts +3 -0
  41. package/dist/builtin/workflows/src/extension/workflow-schema.ts +43 -33
  42. package/dist/builtin/workflows/src/runs/foreground/executor.ts +34 -10
  43. package/dist/builtin/workflows/src/shared/types.ts +1 -5
  44. package/dist/builtin/workflows/src/tui/graph-view.ts +245 -75
  45. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +23 -0
  46. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +259 -149
  47. package/dist/builtin/workflows/src/tui/status-helpers.ts +3 -3
  48. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +99 -10
  49. package/dist/builtin/workflows/src/tui/switcher.ts +4 -5
  50. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +29 -0
  51. package/dist/cli/args.d.ts.map +1 -1
  52. package/dist/cli/args.js +11 -8
  53. package/dist/cli/args.js.map +1 -1
  54. package/dist/config.d.ts +21 -0
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +59 -4
  57. package/dist/config.js.map +1 -1
  58. package/dist/core/agent-session.d.ts +1 -1
  59. package/dist/core/agent-session.d.ts.map +1 -1
  60. package/dist/core/agent-session.js +2 -2
  61. package/dist/core/agent-session.js.map +1 -1
  62. package/dist/core/auth-storage.d.ts +3 -1
  63. package/dist/core/auth-storage.d.ts.map +1 -1
  64. package/dist/core/auth-storage.js +31 -8
  65. package/dist/core/auth-storage.js.map +1 -1
  66. package/dist/core/extensions/runner.d.ts.map +1 -1
  67. package/dist/core/extensions/runner.js +9 -0
  68. package/dist/core/extensions/runner.js.map +1 -1
  69. package/dist/core/extensions/types.d.ts +11 -0
  70. package/dist/core/extensions/types.d.ts.map +1 -1
  71. package/dist/core/extensions/types.js.map +1 -1
  72. package/dist/core/model-registry.d.ts +3 -2
  73. package/dist/core/model-registry.d.ts.map +1 -1
  74. package/dist/core/model-registry.js +25 -8
  75. package/dist/core/model-registry.js.map +1 -1
  76. package/dist/core/package-manager.d.ts +3 -0
  77. package/dist/core/package-manager.d.ts.map +1 -1
  78. package/dist/core/package-manager.js +97 -58
  79. package/dist/core/package-manager.js.map +1 -1
  80. package/dist/core/resource-loader.d.ts +1 -0
  81. package/dist/core/resource-loader.d.ts.map +1 -1
  82. package/dist/core/resource-loader.js +37 -36
  83. package/dist/core/resource-loader.js.map +1 -1
  84. package/dist/core/sdk.d.ts +5 -4
  85. package/dist/core/sdk.d.ts.map +1 -1
  86. package/dist/core/sdk.js +2 -2
  87. package/dist/core/sdk.js.map +1 -1
  88. package/dist/core/settings-manager.d.ts +7 -1
  89. package/dist/core/settings-manager.d.ts.map +1 -1
  90. package/dist/core/settings-manager.js +29 -8
  91. package/dist/core/settings-manager.js.map +1 -1
  92. package/dist/core/system-prompt.d.ts +1 -1
  93. package/dist/core/system-prompt.d.ts.map +1 -1
  94. package/dist/core/system-prompt.js.map +1 -1
  95. package/dist/core/telemetry.d.ts.map +1 -1
  96. package/dist/core/telemetry.js +2 -2
  97. package/dist/core/telemetry.js.map +1 -1
  98. package/dist/core/timings.d.ts.map +1 -1
  99. package/dist/core/timings.js +2 -2
  100. package/dist/core/timings.js.map +1 -1
  101. package/dist/core/tools/index.d.ts +1 -0
  102. package/dist/core/tools/index.d.ts.map +1 -1
  103. package/dist/core/tools/index.js +8 -0
  104. package/dist/core/tools/index.js.map +1 -1
  105. package/dist/core/tools/todos.d.ts.map +1 -1
  106. package/dist/core/tools/todos.js +3 -3
  107. package/dist/core/tools/todos.js.map +1 -1
  108. package/dist/index.d.ts +2 -2
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +2 -2
  111. package/dist/index.js.map +1 -1
  112. package/dist/main.d.ts.map +1 -1
  113. package/dist/main.js +6 -6
  114. package/dist/main.js.map +1 -1
  115. package/dist/modes/interactive/components/atomic-banner.d.ts +4 -0
  116. package/dist/modes/interactive/components/atomic-banner.d.ts.map +1 -0
  117. package/dist/modes/interactive/components/atomic-banner.js +34 -0
  118. package/dist/modes/interactive/components/atomic-banner.js.map +1 -0
  119. package/dist/modes/interactive/components/chat-message-renderer.d.ts +99 -0
  120. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -0
  121. package/dist/modes/interactive/components/chat-message-renderer.js +450 -0
  122. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -0
  123. package/dist/modes/interactive/components/chat-transcript.d.ts +69 -0
  124. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -0
  125. package/dist/modes/interactive/components/chat-transcript.js +183 -0
  126. package/dist/modes/interactive/components/chat-transcript.js.map +1 -0
  127. package/dist/modes/interactive/components/footer.d.ts +16 -4
  128. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  129. package/dist/modes/interactive/components/footer.js +110 -137
  130. package/dist/modes/interactive/components/footer.js.map +1 -1
  131. package/dist/modes/interactive/components/index.d.ts +2 -0
  132. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  133. package/dist/modes/interactive/components/index.js +2 -0
  134. package/dist/modes/interactive/components/index.js.map +1 -1
  135. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  136. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  137. package/dist/modes/interactive/interactive-mode.js +192 -137
  138. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  139. package/dist/modes/interactive/theme/catppuccin-mocha.json +5 -5
  140. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  141. package/dist/modes/rpc/rpc-mode.js +11 -0
  142. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  143. package/dist/utils/tools-manager.d.ts.map +1 -1
  144. package/dist/utils/tools-manager.js +2 -2
  145. package/dist/utils/tools-manager.js.map +1 -1
  146. package/dist/utils/version-check.d.ts.map +1 -1
  147. package/dist/utils/version-check.js +2 -2
  148. package/dist/utils/version-check.js.map +1 -1
  149. package/package.json +1 -1
@@ -1,17 +1,17 @@
1
1
  ---
2
2
  name: workflow
3
- description: Create, run, inspect, and improve pi/atomic workflows. Use whenever the user wants a reusable multi-stage automation, DAG or staged agent pipeline, workflow definition, defineWorkflow file, ctx.task/ctx.parallel/ctx.chain/ctx.stage orchestration, /workflow run/status/resume help, custom workflow discovery, or context-engineered multi-session process.
3
+ description: Create, run, inspect, and improve pi/atomic workflows. Use whenever the user wants reusable multi-stage automation, a DAG or staged agent pipeline, workflow definitions with defineWorkflow, ctx.task/ctx.parallel/ctx.chain/ctx.stage/ctx.ui orchestration, workflow tool calls, /workflow list/inputs/connect/attach/pause/resume/status help, custom workflow discovery, model fallback chains, or context-engineered multi-session processes.
4
4
  ---
5
5
 
6
6
  # Workflow Skill
7
7
 
8
- You help users create and operate pi/atomic workflows. A workflow is a reusable TypeScript definition that orchestrates named stages, parallel branches, handoffs, artifacts, user-input prompts, status UI, and resumable runs through pi's workflow extension.
8
+ You help users create and operate pi/atomic workflows. A workflow is a reusable TypeScript definition that orchestrates named stages, parallel branches, handoffs, artifacts, human-in-the-loop prompts, live graph/status UI, attachable stage chats, model fallback chains, and resumable background runs through pi's workflow extension.
9
9
 
10
10
  This skill is for people using workflows. Default to helping users author workflow definitions and run them through pi. Only discuss package implementation details if the user explicitly asks to modify the `@bastani/workflows` package itself.
11
11
 
12
12
  Use this skill for two user journeys:
13
13
 
14
- 1. **Run or inspect an existing workflow** — use the workflow tool or `/workflow` surface. Load `references/running-workflows.md`.
14
+ 1. **Run, inspect, attach to, pause, or resume an existing workflow** — use the workflow tool or `/workflow` surface. Load `references/running-workflows.md`.
15
15
  2. **Create or edit a workflow definition** — design the information flow, then author a `defineWorkflow(...).run(...).compile()` TypeScript file. Load `references/sdk-authoring.md` and `references/design-checklist.md`.
16
16
 
17
17
  ## Reference Files
@@ -20,8 +20,8 @@ Load references on demand. Keep this file lean; put details in references.
20
20
 
21
21
  | File | Load when |
22
22
  | --- | --- |
23
- | `references/sdk-authoring.md` | Creating/editing workflow definition files, inputs, `ctx.task`, `ctx.parallel`, `ctx.chain`, `ctx.stage`, or programmatic runner usage. |
24
- | `references/running-workflows.md` | Running, monitoring, interrupting, resuming, or inspecting workflows. |
23
+ | `references/sdk-authoring.md` | Creating/editing workflow definition files, inputs, `ctx.task`, `ctx.parallel`, `ctx.chain`, `ctx.stage`, `ctx.ui`, model fallbacks, registries, or programmatic runner usage. |
24
+ | `references/running-workflows.md` | Running, monitoring, connecting/attaching, pausing, interrupting, resuming, or inspecting workflows. |
25
25
  | `references/design-checklist.md` | Before implementing or shipping any non-trivial workflow. |
26
26
  | `references/context-engineering.md` | Any multi-stage or multi-agent workflow; routes to copied context-engineering references. |
27
27
  | `references/context-engineering/context-fundamentals.md` | Prompt/context basics, token budgeting, prompt placement, progressive disclosure. |
@@ -42,9 +42,9 @@ Load references on demand. Keep this file lean; put details in references.
42
42
 
43
43
  Classify the user's ask before acting:
44
44
 
45
- - **Run**: "run workflow X", "kick off ralph", "is it done?", "resume", "interrupt", "status", "what inputs does it need?" → load `references/running-workflows.md`; list/inspect first if needed; execute rather than merely printing commands when tools allow.
46
- - **Author**: "create a workflow", "turn this process into a workflow", "add a stage", "make a reusable workflow", "defineWorkflow", "ctx.parallel", "workflow schema" → load `references/sdk-authoring.md`; design before coding.
47
- - **Design/architecture**: "make this workflow robust", "multi-agent pipeline", "context handoff", "review/fix loop" → load `references/design-checklist.md` and `references/context-engineering.md` before writing code.
45
+ - **Run**: "run workflow X", "kick off ralph", "is it done?", "resume", "interrupt", "pause", "attach", "status", "what inputs does it need?" → load `references/running-workflows.md`; list/inspect first if needed; execute rather than merely printing commands when tools allow.
46
+ - **Author**: "create a workflow", "turn this process into a workflow", "add a stage", "make a reusable workflow", "defineWorkflow", "ctx.parallel", "ctx.ui", "workflow schema" → load `references/sdk-authoring.md`; design before coding.
47
+ - **Design/architecture**: "make this workflow robust", "multi-agent pipeline", "context handoff", "review/fix loop", "fallback models", "human approval gate" → load `references/design-checklist.md` and `references/context-engineering.md` before writing code.
48
48
 
49
49
  ## Running Existing Workflows
50
50
 
@@ -52,8 +52,9 @@ Inspect before running unfamiliar named workflows:
52
52
 
53
53
  ```ts
54
54
  workflow({ action: "list" })
55
+ workflow({ action: "get", workflow: "deep-research-codebase" })
55
56
  workflow({ action: "inputs", workflow: "deep-research-codebase" })
56
- workflow({ workflow: "deep-research-codebase", inputs: { prompt: "map workflow runtime" } })
57
+ workflow({ action: "run", workflow: "deep-research-codebase", inputs: { prompt: "map workflow runtime" } })
57
58
  ```
58
59
 
59
60
  Slash equivalents:
@@ -61,13 +62,18 @@ Slash equivalents:
61
62
  ```text
62
63
  /workflow list
63
64
  /workflow inputs deep-research-codebase
65
+ /workflow deep-research-codebase --help
64
66
  /workflow deep-research-codebase prompt="map src" max_partitions=2
67
+ /workflow connect <run-id>
68
+ /workflow attach <run-id> <stage-id-or-name>
69
+ /workflow pause <run-id> [stage-id-or-name]
65
70
  /workflow status --all
66
71
  /workflow status <run-id>
67
- /workflow resume <run-id>
72
+ /workflow interrupt <run-id|--all>
73
+ /workflow resume <run-id> [stage-id-or-name] [message]
68
74
  ```
69
75
 
70
- Named workflow dispatch is background-oriented: expect a run id and then monitor status/attention states.
76
+ Named workflow dispatch is always background-oriented: expect a run id, then monitor status/attention states. Press F2 or run `/workflow connect <run-id>` to open the live graph viewer. HIL prompts from `ctx.ui.input/confirm/select/editor` appear in that workflow UI, not as modal chat dialogs.
71
77
 
72
78
  ## Direct Workflow-Native Orchestration
73
79
 
@@ -129,8 +135,9 @@ Task options mirror pi session options plus workflow-owned fields such as `outpu
129
135
 
130
136
  For user-authored workflows, place definitions where pi discovers them:
131
137
 
132
- - Project-local: `.atomic/workflows/*.ts` inside the current project.
133
- - User-global: `~/.atomic/agent/workflows/*.ts` for workflows available across projects.
138
+ - Project-local: `.atomic/workflows/*.{ts,js,mjs,cjs}` inside the current project. Legacy `.pi/workflows/` is also checked for compatibility.
139
+ - User-global: `~/.atomic/agent/workflows/*.{ts,js,mjs,cjs}` for workflows available across projects. Legacy `~/.pi/agent/workflows/` is also checked.
140
+ - Configured directories: `.atomic/extensions/workflow/config.json` or `~/.atomic/agent/extensions/workflow/config.json` may add named `workflows.<name>.path` entries; legacy `.pi/...` config paths are also considered.
134
141
  - Package workflows: a pi package can expose bundled workflow directories through `package.json` under `pi.builtin`.
135
142
 
136
143
  If an existing project has workflow examples, inspect those first for import style and naming conventions. In a normal consumer project, import from the package:
@@ -169,7 +176,7 @@ export default defineWorkflow("explain-file")
169
176
  .input("path", { type: "text", required: true, description: "File path to explain." })
170
177
  .run(async (ctx) => {
171
178
  const explanation = await ctx.task("explain", {
172
- task: `Read ${ctx.inputs.path} and explain purpose, risks, and key symbols.`,
179
+ prompt: `Read ${String(ctx.inputs.path)} and explain purpose, risks, and key symbols.`,
173
180
  context: "fresh",
174
181
  });
175
182
 
@@ -186,7 +193,7 @@ Builder rules:
186
193
  - `.run(async (ctx) => ({ ... }))` defines the workflow body.
187
194
  - `.compile()` returns the workflow definition for discovery.
188
195
 
189
- Input types: `text`, `string`, `number`, `boolean`, `select`. All support `description` and `required`; defaults are type-specific; `select` requires `choices`.
196
+ Input types: `text`, `string`, `number`, `boolean`, `select`. All support `description` and `required`; defaults are type-specific; `select` requires `choices`. Runtime validation rejects unknown keys, missing required values, type mismatches, and select values outside `choices`.
190
197
 
191
198
  ### 4. Pick the right primitive
192
199
 
@@ -196,7 +203,7 @@ Input types: `text`, `string`, `number`, `boolean`, `select`. All support `descr
196
203
  | Independent branches | `ctx.parallel(steps, { task? })` |
197
204
  | Dependent stages | `ctx.chain(steps, { task? })` |
198
205
  | Low-level session controls | `ctx.stage(name, options)` then `stage.prompt/complete` |
199
- | User interaction during run | `ctx.ui` primitives |
206
+ | User interaction during run | `ctx.ui.input/confirm/select/editor` |
200
207
  | Pure computation / file I/O / parsing | Plain TypeScript in `.run()` or helpers |
201
208
 
202
209
  Use `previous` plus `{previous}` for context handoff. If no placeholder is present, the runtime appends context. Chain defaults: first missing task uses `{task}`, later missing tasks use `{previous}`, and missing tasks inside chain-parallel groups use `{previous}`.
@@ -220,8 +227,9 @@ Prefer concise structured returns and durable artifacts over dumping full transc
220
227
 
221
228
  Use these supported workflow surfaces:
222
229
 
223
- - `/workflow <name> key=value ...` for interactive pi use.
224
- - The `workflow` tool for LLM-initiated orchestration.
230
+ - `/workflow <name> key=value ...` for interactive pi use; omit required args to open the input picker when the TUI is available.
231
+ - `/workflow connect|attach|pause|interrupt|resume|status|inputs` for live control and inspection.
232
+ - The `workflow` tool for LLM-initiated orchestration and direct one-off task/parallel/chain runs.
225
233
  - `runWorkflow(definition)` for explicit library/script usage.
226
234
 
227
235
  Programmatic runner example:
@@ -245,10 +253,10 @@ await runWorkflow(definition, options);
245
253
 
246
254
  ## Safety and Compatibility Rules
247
255
 
248
- - Do not fabricate workflow names or inputs; list/inspect first.
256
+ - Do not fabricate workflow names or inputs; list/inspect first with `list`, `get`, or `inputs`.
249
257
  - Do not use legacy workflow tool fields such as `agent`, `stage`, or run-control `name`.
250
258
  - Do not expect workflow-tool `create`, `update`, or `delete`; reusable definitions are code-authored.
251
- - Use `/workflow` slash commands for named runs, inspection, status, and diagnostics.
259
+ - Use `/workflow` slash commands for named runs, input picker/help, graph attach, pause/resume, status, and diagnostics.
252
260
  - Prefer `ctx.task`, `ctx.parallel`, and `ctx.chain`; drop to `ctx.stage` only for lower-level controls.
253
261
  - Keep stage names user-readable because they appear in workflow status/UI.
254
262
  - Put deterministic code outside standalone stages.
@@ -13,7 +13,8 @@ Use this before implementing or shipping a non-trivial workflow.
13
13
 
14
14
  - Declare every user-provided value as an input.
15
15
  - Pick the narrowest schema type: `text`, `string`, `number`, `boolean`, or `select`.
16
- - Add useful descriptions; set defaults only when safe.
16
+ - Add useful descriptions because `/workflow inputs`, `--help`, and the input picker show them.
17
+ - Set defaults only when safe; remember runtime validation rejects unknown keys, missing required values, wrong types, and invalid `select` choices.
17
18
  - Validate risky input combinations before starting expensive stages.
18
19
 
19
20
  ## 3. Stage decomposition
@@ -26,7 +27,7 @@ For each planned stage, write:
26
27
  - input context required
27
28
  - output artifact/result shape
28
29
  - model/thinking/tool/MCP needs
29
- - failure mode and retry/fallback behavior
30
+ - failure mode and retry/fallback behavior, including whether `fallbackModels` is appropriate
30
31
 
31
32
  Avoid stages that only do filesystem, parsing, git, or formatting work.
32
33
 
@@ -58,7 +59,8 @@ Load `context-engineering.md` and relevant detailed references. At minimum consi
58
59
 
59
60
  - Use `ctx.chain` for dependent steps.
60
61
  - Use `ctx.parallel` for independent branches.
61
- - Use `concurrency` limits for large fan-outs.
62
+ - Use `ctx.ui.input/confirm/select/editor` for real human decisions or missing information during a run.
63
+ - Use direct-mode `concurrency` limits when available; for authored `ctx.parallel(...)`, keep fan-outs intentionally bounded because the high-level primitive currently runs its steps together.
62
64
  - Use `failFast` deliberately where available.
63
65
  - Use loops only with clear bounds and termination criteria.
64
66
  - Use `fallbackModels` for critical expensive stages when model availability is uncertain.
@@ -68,7 +70,8 @@ Load `context-engineering.md` and relevant detailed references. At minimum consi
68
70
  - Name stages so they make sense in workflow UI/status.
69
71
  - Return a compact structured output at the end.
70
72
  - Save important artifacts with stable paths.
71
- - Surface HIL/attention states promptly.
73
+ - Surface HIL/attention states promptly and tell users to open F2 or `/workflow connect <run-id>` when input is needed.
74
+ - Make attachable stage names clear enough for `/workflow attach <run-id> <stage>`.
72
75
  - Include enough progress and output for resumed/inspected runs.
73
76
 
74
77
  ## 8. Final sanity pass
@@ -77,3 +80,4 @@ Load `context-engineering.md` and relevant detailed references. At minimum consi
77
80
  - Confirm every required input is declared and described.
78
81
  - Confirm every stage name is user-readable in `/workflow status` and the graph UI.
79
82
  - Confirm the workflow uses a supported surface: `/workflow`, the `workflow` tool, or explicit `runWorkflow(...)` objects.
83
+ - Confirm any required live controls are represented accurately: `connect`/`attach`/`pause` are slash/TUI controls; tool controls cover status/interrupt/resume.
@@ -1,22 +1,27 @@
1
1
  # Running and Inspecting Pi Workflows
2
2
 
3
- Use this when the user asks to run, start, kick off, monitor, interrupt, resume, attach to, or inspect a workflow.
3
+ Use this when the user asks to run, start, kick off, monitor, connect to, attach to, pause, interrupt, resume, or inspect a workflow.
4
4
 
5
5
  ## Discover first
6
6
 
7
- For named workflows, do not guess the schema:
7
+ For named workflows, do not guess names or schemas:
8
8
 
9
9
  ```ts
10
10
  workflow({ action: "list" })
11
+ workflow({ action: "get", workflow: "<name>" })
11
12
  workflow({ action: "inputs", workflow: "<name>" })
12
13
  ```
13
14
 
14
15
  If required inputs are missing and cannot be inferred, ask the user with `ask_user_question` or a concise free-form question.
15
16
 
16
- ## Run
17
+ ## Run named workflows
17
18
 
18
19
  ```ts
19
- workflow({ workflow: "deep-research-codebase", inputs: { prompt: "map workflow dispatch" } })
20
+ workflow({
21
+ action: "run",
22
+ workflow: "deep-research-codebase",
23
+ inputs: { prompt: "map workflow dispatch" },
24
+ })
20
25
  ```
21
26
 
22
27
  Slash equivalent:
@@ -25,62 +30,84 @@ Slash equivalent:
25
30
  /workflow deep-research-codebase prompt="map workflow dispatch"
26
31
  ```
27
32
 
28
- Named workflow dispatch is background-oriented: expect a run id and then monitor status.
33
+ Input overrides are bare `key=value` tokens. Values are JSON-parsed when possible, so `count=3`, `flag=true`, and `prompt="multi word value"` preserve useful types. A whole input object can also be passed as one JSON token.
34
+
35
+ Named workflow dispatch is always background-oriented: expect a run id and then monitor status. Press F2 or use `/workflow connect <run-id>` to attach to the graph viewer. If the TUI is available and required inputs are missing, `/workflow <name>` opens an input picker unless the user passes `--no-picker`.
36
+
37
+ ## Slash command surface
38
+
39
+ ```text
40
+ /workflow list
41
+ /workflow inputs <name>
42
+ /workflow <name> --help
43
+ /workflow <name> [key=value ...]
44
+ /workflow connect [run-id]
45
+ /workflow attach [run-id] [stage-id-or-name]
46
+ /workflow pause [run-id] [stage-id-or-name]
47
+ /workflow status [run-id]
48
+ /workflow status --all
49
+ /workflow interrupt <run-id|--all>
50
+ /workflow resume <run-id> [stage-id-or-name] [message]
51
+ ```
52
+
53
+ Use `connect` for the orchestrator graph. Use `attach` when the user wants to open a chat pane for a specific stage. Use `pause`/`resume` for live paused work; `resume` on a non-paused run reopens the saved snapshot/overlay.
54
+
55
+ Human-in-the-loop prompts from `ctx.ui.input`, `ctx.ui.confirm`, `ctx.ui.select`, and `ctx.ui.editor` surface in the workflow UI/graph viewer, not as ordinary chat modals.
29
56
 
30
57
  ## Direct runs
31
58
 
32
- Use direct workflow-native orchestration for one-off tracked work:
59
+ Use direct workflow-native orchestration for one-off tracked work that does not need a reusable workflow file.
60
+
61
+ Single tracked task:
33
62
 
34
63
  ```ts
35
64
  workflow({
36
65
  task: { name: "review", task: "Review this patch for API risks." },
37
66
  async: true,
38
- intercom: { delivery: "result" }
67
+ intercom: { delivery: "result" },
39
68
  })
40
69
  ```
41
70
 
42
- Parallel:
71
+ Parallel fan-out:
43
72
 
44
73
  ```ts
45
74
  workflow({
46
75
  tasks: [
47
76
  { name: "docs", task: "Review documentation gaps" },
48
- { name: "risks", task: "Review operational risks" }
77
+ { name: "risks", task: "Review operational risks" },
49
78
  ],
50
79
  concurrency: 2,
51
- outputMode: "file-only"
80
+ outputMode: "file-only",
81
+ async: true,
52
82
  })
53
83
  ```
54
84
 
55
- Chain:
85
+ Dependent chain:
56
86
 
57
87
  ```ts
58
88
  workflow({
59
89
  task: "Design the workflow SDK migration",
60
90
  chain: [
61
91
  { name: "research", task: "Research {task}" },
62
- { name: "plan", task: "Plan from {previous}" }
63
- ]
92
+ { name: "plan", task: "Plan from {previous}" },
93
+ ],
94
+ async: true,
64
95
  })
65
96
  ```
66
97
 
67
- ## Monitor/control
98
+ Direct mode supports top-level/default options and per-task options such as `context`, `model`, `fallbackModels`, `thinkingLevel`, `mcp`, `output`, `reads`, `progress`, `worktree`, `maxOutput`, `artifacts`, `sessionDir`, and `cwd`. For large fan-outs, prefer `outputMode: "file-only"`.
99
+
100
+ ## Monitor/control with the workflow tool
68
101
 
69
102
  ```ts
70
103
  workflow({ action: "status" })
71
104
  workflow({ action: "status", runId: "<id>" })
72
105
  workflow({ action: "interrupt", runId: "<id>" })
106
+ workflow({ action: "interrupt", runId: "--all" })
73
107
  workflow({ action: "resume", runId: "<id>" })
74
108
  ```
75
109
 
76
- Slash equivalents:
77
-
78
- ```text
79
- /workflow status --all
80
- /workflow status <id>
81
- /workflow interrupt <id>
82
- /workflow resume <id>
83
- ```
110
+ The LLM-callable tool exposes status/interrupt/resume controls. Use slash commands for graph connect, stage attach, and pause because those are interactive TUI surfaces.
84
111
 
85
112
  When a run needs user input or attention, surface that to the user instead of polling silently.
86
113
 
@@ -92,7 +119,7 @@ For async direct runs, request result delivery when available:
92
119
  workflow({
93
120
  tasks: [{ name: "reviewer", task: "Review the patch" }],
94
121
  async: true,
95
- intercom: { delivery: "result" }
122
+ intercom: { delivery: "result" },
96
123
  })
97
124
  ```
98
125
 
@@ -101,7 +128,9 @@ Treat intercom payloads as user-visible workflow output.
101
128
  ## Common mistakes
102
129
 
103
130
  - Do not fabricate workflow names; list first.
131
+ - Do not guess input keys; inspect with `inputs` or `get` first.
104
132
  - Do not call `create`, `update`, or `delete` on the workflow tool; definitions are code-authored.
105
133
  - Do not use legacy tool fields like `agent`, `stage`, or run-control `name`.
134
+ - Do not expect named workflow runs to block the chat turn; they are background tasks.
106
135
  - Prefer `outputMode: "file-only"` for large fan-outs.
107
136
  - Use status/resume controls for run lifecycle; inspect workflow output and artifacts for behavior.
@@ -4,10 +4,11 @@ Use this when creating or editing user-facing workflow definition files for `@ba
4
4
 
5
5
  ## Where workflow files live
6
6
 
7
- Pi discovers workflows from these user-facing locations:
7
+ Pi/Atomic discovers workflows from these user-facing locations:
8
8
 
9
- - Project-local: `.atomic/workflows/*.ts` inside a project.
10
- - User-global: `~/.atomic/agent/workflows/*.ts` for workflows shared across projects.
9
+ - Project-local: `.atomic/workflows/*.{ts,js,mjs,cjs}` inside a project. Legacy `.pi/workflows/` is also checked for compatibility.
10
+ - User-global: `~/.atomic/agent/workflows/*.{ts,js,mjs,cjs}` for workflows shared across projects. Legacy `~/.pi/agent/workflows/` is also checked.
11
+ - Configured directories: `.atomic/extensions/workflow/config.json` or `~/.atomic/agent/extensions/workflow/config.json` can add `workflows.<name>.path` entries; legacy `.pi/...` config paths are also considered.
11
12
  - Package-provided: a pi package can expose bundled workflow directories through `package.json` under `pi.builtin`.
12
13
 
13
14
  In a normal consumer project, import from the package:
@@ -31,18 +32,20 @@ export default defineWorkflow("my-workflow")
31
32
  description: "Task or question for the workflow.",
32
33
  })
33
34
  .run(async (ctx) => {
35
+ const prompt = String(ctx.inputs.prompt);
36
+
34
37
  const scout = await ctx.task("scout", {
35
- task: `Map the relevant context for: ${ctx.inputs.prompt}`,
38
+ prompt: `Map the relevant context for: ${prompt}`,
36
39
  context: "fresh",
37
40
  });
38
41
 
39
42
  const reviews = await ctx.parallel([
40
- { name: "quality", task: "Inspect quality risks using this context: {previous}", previous: scout },
41
- { name: "runtime", task: "Inspect runtime concerns using this context: {previous}", previous: scout },
43
+ { name: "quality", prompt: "Inspect quality risks using this context: {previous}", previous: scout },
44
+ { name: "runtime", prompt: "Inspect runtime concerns using this context: {previous}", previous: scout },
42
45
  ]);
43
46
 
44
47
  const final = await ctx.task("synthesis", {
45
- task: "Synthesize findings and recommend next steps.",
48
+ prompt: "Synthesize findings and recommend next steps.",
46
49
  previous: reviews,
47
50
  });
48
51
 
@@ -51,6 +54,8 @@ export default defineWorkflow("my-workflow")
51
54
  .compile();
52
55
  ```
53
56
 
57
+ `prompt` and `task` are aliases for task text. Prefer `prompt` inside authored workflow files because it mirrors the lower-level `stage.prompt(...)`; `task` remains useful in direct tool calls and chain examples.
58
+
54
59
  ## Builder facts
55
60
 
56
61
  - `defineWorkflow(name)` requires a non-empty string name.
@@ -69,7 +74,7 @@ Supported input schema types are:
69
74
  - `boolean`: optional `default: boolean`
70
75
  - `select`: required `choices: string[]`, optional `default: string`
71
76
 
72
- All schemas support `description` and `required`. Prefer explicit descriptions because `/workflow inputs <name>` and the input picker show them to the user.
77
+ All schemas support `description` and `required`. Prefer explicit descriptions because `/workflow inputs <name>`, `/workflow <name> --help`, and the input picker show them to the user. Runtime validation rejects unknown keys, missing required values, type mismatches, and select values outside `choices`; it does not coerce strings like `"3"` to numbers.
73
78
 
74
79
  ## Run context
75
80
 
@@ -78,9 +83,9 @@ All schemas support `description` and `required`. Prefer explicit descriptions b
78
83
  Prefer high-level primitives:
79
84
 
80
85
  - `ctx.task(name, options)` — one tracked stage + prompt, returns `WorkflowTaskResult`.
81
- - `ctx.parallel(steps, options?)` — run independent task steps concurrently.
86
+ - `ctx.parallel(steps, options?)` — run independent task steps together; keep authored fan-outs intentionally bounded.
82
87
  - `ctx.chain(steps, options?)` — run dependent task steps sequentially.
83
- - `ctx.ui` — user interaction primitives when a run needs human input.
88
+ - `ctx.ui` — human-in-the-loop primitives when a run needs user input.
84
89
 
85
90
  Use `ctx.stage(name, options?)` only when you need lower-level session control. `StageContext` supports:
86
91
 
@@ -91,6 +96,17 @@ Use `ctx.stage(name, options?)` only when you need lower-level session control.
91
96
  - state access: `agent`, `model`, `thinkingLevel`, `messages`, `isStreaming`
92
97
  - tree navigation, compaction, and abort
93
98
 
99
+ ## Human-in-the-loop UI
100
+
101
+ `ctx.ui` supports:
102
+
103
+ - `input(prompt): Promise<string>`
104
+ - `confirm(message): Promise<boolean>`
105
+ - `select(message, options): Promise<T>`
106
+ - `editor(initial?): Promise<string>`
107
+
108
+ These suspend the workflow until the user responds. In interactive pi/Atomic, prompts appear in the workflow graph/input UI opened by F2 or `/workflow connect <run-id>`, not as modal chat dialogs. Always make the surrounding stage/output clear enough that the user knows what decision they are making.
109
+
94
110
  ## Task/session options
95
111
 
96
112
  Common task/stage options include:
@@ -102,6 +118,8 @@ Common task/stage options include:
102
118
  - `output`, `outputMode`, `reads`, `progress`, `worktree`, `maxOutput`, `artifacts`, `sessionDir`, `cwd`
103
119
  - `mcp: { allow?: string[], deny?: string[] }`
104
120
 
121
+ `fallbackModels` retries transient provider/model failures with the primary `model` first, then each fallback, then the current pi-selected model when available. It is for rate limits, quota/auth/provider outages, unavailable models, network timeouts, and 5xx errors — not workflow-code errors, tool failures, validation failures, or cancellations. Use provider-qualified IDs when bare IDs would be ambiguous.
122
+
105
123
  Chain defaults:
106
124
 
107
125
  - first missing task uses `{task}` from chain options/root direct task
@@ -112,12 +130,23 @@ Chain defaults:
112
130
 
113
131
  A stage should correspond to an LLM/session interaction. Put pure deterministic work directly in `.run()` or helper functions, not in a standalone stage. Examples: parsing, filesystem writes, JSON validation, git queries, and formatting. Pair deterministic parsing/validation with a nearby LLM call when it is part of that stage's output handling.
114
132
 
115
- ## Execution model
133
+ ## Registries and programmatic execution
134
+
135
+ Use `createRegistry()` when code needs to group definitions explicitly:
136
+
137
+ ```ts
138
+ import { createRegistry, defineWorkflow } from "@bastani/workflows";
139
+
140
+ const alpha = defineWorkflow("alpha").run(async () => ({})).compile();
141
+ const registry = createRegistry().register(alpha);
142
+ registry.names();
143
+ registry.get("alpha");
144
+ ```
116
145
 
117
146
  `@bastani/workflows` is a pi package/extension. Pi loads the extension from the package manifest; the extension registers the `workflow` tool, `/workflow` command, renderers, widgets, and lifecycle hooks. Use these user-facing surfaces:
118
147
 
119
148
  - `/workflow <name> key=value ...` inside pi.
120
- - The `workflow` tool for LLM-driven orchestration.
149
+ - The `workflow` tool for LLM-driven orchestration and direct one-off runs.
121
150
  - `runWorkflow(definition)` for explicit library/script usage.
122
151
 
123
152
  Programmatic runner example:
@@ -18,7 +18,7 @@
18
18
 
19
19
  import { join, isAbsolute } from "node:path";
20
20
  import { homedir } from "node:os";
21
- import { CONFIG_DIR_NAME } from "@bastani/atomic";
21
+ import { CONFIG_DIR_NAME, CONFIG_DIR_NAMES, getProjectConfigPaths } from "@bastani/atomic";
22
22
 
23
23
  // ---------------------------------------------------------------------------
24
24
  // Public types
@@ -439,37 +439,36 @@ export async function loadWorkflowConfig(
439
439
 
440
440
  const diagnostics: ConfigDiagnostic[] = [];
441
441
 
442
- // Global config path
443
- const globalPath = join(home, CONFIG_DIR_NAME, "agent", "extensions", "workflow", "config.json");
442
+ // Global config paths (primary Atomic first, then legacy pi)
443
+ const globalCandidates = CONFIG_DIR_NAMES.map((name) => join(home, name, "agent", "extensions", "workflow", "config.json"));
444
444
 
445
- // Project-local config
446
- const projectCandidates: string[] = [
447
- join(projectRoot, CONFIG_DIR_NAME, "extensions", "workflow", "config.json"),
448
- ];
445
+ // Project-local config paths (primary Atomic first, then legacy pi)
446
+ const projectCandidates: string[] = getProjectConfigPaths(projectRoot, "extensions", "workflow", "config.json");
449
447
 
450
- // Load global config
448
+ // Load global config (primary overrides legacy)
451
449
  let globalConfig: WorkflowExtensionConfig | null = null;
452
- {
450
+ for (let i = globalCandidates.length - 1; i >= 0; i--) {
451
+ const globalPath = globalCandidates[i]!;
453
452
  const outcome = await loadConfigFile(globalPath);
454
453
  if (outcome.kind === "error") {
455
454
  diagnostics.push(outcome.diagnostic);
456
455
  } else if (outcome.kind === "ok") {
457
- globalConfig = outcome.parsed;
456
+ globalConfig = globalConfig ? mergeConfigs(globalConfig, outcome.parsed) : outcome.parsed;
458
457
  }
459
458
  // "missing" → silently skip
460
459
  }
461
460
 
462
- // Load first existing project-local config
461
+ // Load project-local configs (primary overrides legacy)
463
462
  let projectConfig: WorkflowExtensionConfig | null = null;
464
- for (const candidatePath of projectCandidates) {
463
+ for (let i = projectCandidates.length - 1; i >= 0; i--) {
464
+ const candidatePath = projectCandidates[i]!;
465
465
  const outcome = await loadConfigFile(candidatePath);
466
466
  if (outcome.kind === "missing") continue;
467
467
  if (outcome.kind === "error") {
468
468
  diagnostics.push(outcome.diagnostic);
469
469
  } else {
470
- projectConfig = outcome.parsed;
470
+ projectConfig = projectConfig ? mergeConfigs(projectConfig, outcome.parsed) : outcome.parsed;
471
471
  }
472
- break; // Only first existing candidate
473
472
  }
474
473
 
475
474
  // Merge: start from global, apply project override
@@ -21,7 +21,7 @@
21
21
 
22
22
  import { readdir, stat } from "node:fs/promises";
23
23
  import { join, resolve, extname, isAbsolute } from "node:path";
24
- import { CONFIG_DIR_NAME } from "@bastani/atomic";
24
+ import { CONFIG_DIR_NAMES, getProjectConfigPaths } from "@bastani/atomic";
25
25
  import type { WorkflowDefinition } from "../shared/types.js";
26
26
  import { createRegistry } from "../workflows/registry.js";
27
27
  import type { WorkflowRegistry } from "../workflows/registry.js";
@@ -408,8 +408,7 @@ export async function discoverWorkflows(
408
408
  }
409
409
 
410
410
  // 2. project-local
411
- {
412
- const dir = join(cwd, CONFIG_DIR_NAME, "workflows");
411
+ for (const dir of getProjectConfigPaths(cwd, "workflows").reverse()) {
413
412
  const candidates = await loadFromDir(dir, "project-local", diagnostics);
414
413
  registry = applyBatch(candidates, registry, sources, diagnostics);
415
414
  }
@@ -424,9 +423,8 @@ export async function discoverWorkflows(
424
423
  }
425
424
  }
426
425
 
427
- // 4. user-global — canonical Atomic path: ~/.atomic/agent/workflows/
428
- {
429
- const dir = join(homeDir, CONFIG_DIR_NAME, "agent", "workflows");
426
+ // 4. user-global — canonical Atomic path plus legacy pi path
427
+ for (const dir of CONFIG_DIR_NAMES.map((name) => join(homeDir, name, "agent", "workflows")).reverse()) {
430
428
  const candidates = await loadFromDir(dir, "user-global", diagnostics);
431
429
  registry = applyBatch(candidates, registry, sources, diagnostics);
432
430
  }