@bastani/atomic 0.8.4-0 → 0.8.5-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 (245) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +24 -23
  3. package/dist/builtin/intercom/README.md +5 -5
  4. package/dist/builtin/intercom/index.ts +1 -1
  5. package/dist/builtin/intercom/package.json +1 -1
  6. package/dist/builtin/intercom/ui/compose.ts +19 -1
  7. package/dist/builtin/intercom/ui/session-list.ts +19 -1
  8. package/dist/builtin/mcp/README.md +3 -3
  9. package/dist/builtin/mcp/commands.ts +1 -1
  10. package/dist/builtin/mcp/host-html-template.ts +1 -1
  11. package/dist/builtin/mcp/mcp-panel.ts +14 -14
  12. package/dist/builtin/mcp/mcp-setup-panel.ts +4 -4
  13. package/dist/builtin/mcp/package.json +1 -1
  14. package/dist/builtin/mcp/tool-result-renderer.ts +1 -1
  15. package/dist/builtin/subagents/README.md +3 -3
  16. package/dist/builtin/subagents/package.json +1 -1
  17. package/dist/builtin/subagents/src/tui/render.ts +1844 -1062
  18. package/dist/builtin/web-access/README.md +1 -1
  19. package/dist/builtin/web-access/curator-page.ts +2 -2
  20. package/dist/builtin/web-access/index.ts +1 -1
  21. package/dist/builtin/web-access/package.json +1 -1
  22. package/dist/builtin/workflows/README.md +34 -7
  23. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +23 -4
  24. package/dist/builtin/workflows/builtin/ralph.ts +1 -1
  25. package/dist/builtin/workflows/package.json +1 -1
  26. package/dist/builtin/workflows/skills/workflow/SKILL.md +75 -16
  27. package/dist/builtin/workflows/skills/workflow/references/running-workflows.md +34 -11
  28. package/dist/builtin/workflows/skills/workflow/references/sdk-authoring.md +111 -20
  29. package/dist/builtin/workflows/src/extension/discovery.ts +32 -4
  30. package/dist/builtin/workflows/src/extension/index.ts +347 -63
  31. package/dist/builtin/workflows/src/extension/render-call.ts +3 -1
  32. package/dist/builtin/workflows/src/extension/render-result.ts +7 -0
  33. package/dist/builtin/workflows/src/extension/runtime.ts +4 -2
  34. package/dist/builtin/workflows/src/extension/wiring.ts +32 -8
  35. package/dist/builtin/workflows/src/extension/workflow-schema.ts +36 -14
  36. package/dist/builtin/workflows/src/runs/background/runner.ts +2 -2
  37. package/dist/builtin/workflows/src/runs/background/status.ts +89 -0
  38. package/dist/builtin/workflows/src/runs/foreground/executor.ts +338 -78
  39. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +2 -0
  40. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +55 -7
  41. package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +146 -10
  42. package/dist/builtin/workflows/src/shared/store.ts +29 -0
  43. package/dist/builtin/workflows/src/shared/types.ts +25 -4
  44. package/dist/builtin/workflows/src/tui/graph-canvas.ts +69 -2
  45. package/dist/builtin/workflows/src/tui/graph-view.ts +97 -182
  46. package/dist/builtin/workflows/src/tui/header.ts +36 -20
  47. package/dist/builtin/workflows/src/tui/inline-form-card.ts +129 -46
  48. package/dist/builtin/workflows/src/tui/inline-form-editor.ts +111 -36
  49. package/dist/builtin/workflows/src/tui/inputs-picker.ts +311 -91
  50. package/dist/builtin/workflows/src/tui/layout.ts +1 -1
  51. package/dist/builtin/workflows/src/tui/node-card.ts +66 -37
  52. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +20 -6
  53. package/dist/builtin/workflows/src/tui/prompt-card.ts +262 -85
  54. package/dist/builtin/workflows/src/tui/run-detail.ts +50 -31
  55. package/dist/builtin/workflows/src/tui/session-confirm.ts +21 -14
  56. package/dist/builtin/workflows/src/tui/session-picker.ts +35 -26
  57. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +531 -960
  58. package/dist/builtin/workflows/src/tui/status-helpers.ts +6 -0
  59. package/dist/builtin/workflows/src/tui/status-list.ts +8 -4
  60. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +7 -2
  61. package/dist/builtin/workflows/src/tui/switcher.ts +55 -25
  62. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +33 -1
  63. package/dist/builtin/workflows/src/tui/workflow-list.ts +10 -6
  64. package/dist/cli/args.d.ts.map +1 -1
  65. package/dist/cli/args.js +1 -1
  66. package/dist/cli/args.js.map +1 -1
  67. package/dist/config.d.ts.map +1 -1
  68. package/dist/config.js +20 -6
  69. package/dist/config.js.map +1 -1
  70. package/dist/core/agent-session-services.d.ts +3 -3
  71. package/dist/core/agent-session-services.d.ts.map +1 -1
  72. package/dist/core/agent-session-services.js.map +1 -1
  73. package/dist/core/agent-session.d.ts +7 -7
  74. package/dist/core/agent-session.d.ts.map +1 -1
  75. package/dist/core/agent-session.js.map +1 -1
  76. package/dist/core/compaction/branch-summarization.d.ts +2 -2
  77. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  78. package/dist/core/compaction/branch-summarization.js.map +1 -1
  79. package/dist/core/compaction/compaction.d.ts +3 -3
  80. package/dist/core/compaction/compaction.d.ts.map +1 -1
  81. package/dist/core/compaction/compaction.js.map +1 -1
  82. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  83. package/dist/core/export-html/tool-renderer.js.map +1 -1
  84. package/dist/core/extensions/loader.d.ts +3 -2
  85. package/dist/core/extensions/loader.d.ts.map +1 -1
  86. package/dist/core/extensions/loader.js +24 -12
  87. package/dist/core/extensions/loader.js.map +1 -1
  88. package/dist/core/extensions/runner.d.ts.map +1 -1
  89. package/dist/core/extensions/runner.js +6 -0
  90. package/dist/core/extensions/runner.js.map +1 -1
  91. package/dist/core/extensions/types.d.ts +28 -17
  92. package/dist/core/extensions/types.d.ts.map +1 -1
  93. package/dist/core/extensions/types.js.map +1 -1
  94. package/dist/core/package-manager.d.ts +1 -0
  95. package/dist/core/package-manager.d.ts.map +1 -1
  96. package/dist/core/package-manager.js +65 -28
  97. package/dist/core/package-manager.js.map +1 -1
  98. package/dist/core/resource-loader.d.ts.map +1 -1
  99. package/dist/core/resource-loader.js +13 -5
  100. package/dist/core/resource-loader.js.map +1 -1
  101. package/dist/core/sdk.d.ts +3 -3
  102. package/dist/core/sdk.d.ts.map +1 -1
  103. package/dist/core/sdk.js.map +1 -1
  104. package/dist/core/session-manager.d.ts.map +1 -1
  105. package/dist/core/session-manager.js +1 -1
  106. package/dist/core/session-manager.js.map +1 -1
  107. package/dist/core/settings-manager.d.ts +2 -0
  108. package/dist/core/settings-manager.d.ts.map +1 -1
  109. package/dist/core/settings-manager.js.map +1 -1
  110. package/dist/core/slash-commands.d.ts.map +1 -1
  111. package/dist/core/slash-commands.js +1 -1
  112. package/dist/core/slash-commands.js.map +1 -1
  113. package/dist/core/system-prompt.d.ts.map +1 -1
  114. package/dist/core/system-prompt.js +5 -3
  115. package/dist/core/system-prompt.js.map +1 -1
  116. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts +1 -1
  117. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts.map +1 -1
  118. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js +1 -1
  119. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js.map +1 -1
  120. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts +8 -8
  121. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts.map +1 -1
  122. package/dist/core/tools/ask-user-question/view/dialog-builder.js +6 -6
  123. package/dist/core/tools/ask-user-question/view/dialog-builder.js.map +1 -1
  124. package/dist/core/tools/bash.d.ts.map +1 -1
  125. package/dist/core/tools/bash.js +1 -1
  126. package/dist/core/tools/bash.js.map +1 -1
  127. package/dist/core/tools/find.d.ts.map +1 -1
  128. package/dist/core/tools/find.js +1 -1
  129. package/dist/core/tools/find.js.map +1 -1
  130. package/dist/core/tools/grep.d.ts.map +1 -1
  131. package/dist/core/tools/grep.js +7 -4
  132. package/dist/core/tools/grep.js.map +1 -1
  133. package/dist/core/tools/index.d.ts +3 -2
  134. package/dist/core/tools/index.d.ts.map +1 -1
  135. package/dist/core/tools/index.js.map +1 -1
  136. package/dist/core/tools/ls.d.ts.map +1 -1
  137. package/dist/core/tools/ls.js +3 -2
  138. package/dist/core/tools/ls.js.map +1 -1
  139. package/dist/core/tools/read.d.ts.map +1 -1
  140. package/dist/core/tools/read.js +2 -2
  141. package/dist/core/tools/read.js.map +1 -1
  142. package/dist/core/tools/render-utils.d.ts +2 -1
  143. package/dist/core/tools/render-utils.d.ts.map +1 -1
  144. package/dist/core/tools/render-utils.js.map +1 -1
  145. package/dist/core/tools/todos.d.ts.map +1 -1
  146. package/dist/core/tools/todos.js +1 -1
  147. package/dist/core/tools/todos.js.map +1 -1
  148. package/dist/core/tools/tool-definition-wrapper.d.ts +4 -3
  149. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  150. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  151. package/dist/core/tools/write.d.ts.map +1 -1
  152. package/dist/core/tools/write.js +1 -1
  153. package/dist/core/tools/write.js.map +1 -1
  154. package/dist/index.d.ts +2 -1
  155. package/dist/index.d.ts.map +1 -1
  156. package/dist/index.js +2 -1
  157. package/dist/index.js.map +1 -1
  158. package/dist/main.d.ts.map +1 -1
  159. package/dist/main.js +2 -2
  160. package/dist/main.js.map +1 -1
  161. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  162. package/dist/modes/interactive/components/assistant-message.js +3 -3
  163. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  164. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  165. package/dist/modes/interactive/components/bash-execution.js +3 -3
  166. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  167. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  168. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  169. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  170. package/dist/modes/interactive/components/chat-message-renderer.d.ts +2 -1
  171. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  172. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  173. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  175. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  176. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  177. package/dist/modes/interactive/components/config-selector.js +1 -1
  178. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  179. package/dist/modes/interactive/components/custom-editor.d.ts +3 -0
  180. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  181. package/dist/modes/interactive/components/custom-editor.js +13 -3
  182. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  183. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  184. package/dist/modes/interactive/components/footer.js +1 -1
  185. package/dist/modes/interactive/components/footer.js.map +1 -1
  186. package/dist/modes/interactive/components/index.d.ts +2 -1
  187. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  188. package/dist/modes/interactive/components/index.js +2 -1
  189. package/dist/modes/interactive/components/index.js.map +1 -1
  190. package/dist/modes/interactive/components/keybinding-hints.d.ts +1 -0
  191. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  192. package/dist/modes/interactive/components/keybinding-hints.js +47 -5
  193. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  194. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  195. package/dist/modes/interactive/components/login-dialog.js +5 -5
  196. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  197. package/dist/modes/interactive/components/model-selector.d.ts +3 -3
  198. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  199. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  200. package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
  201. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  202. package/dist/modes/interactive/components/scoped-models-selector.js +7 -7
  203. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  204. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  205. package/dist/modes/interactive/components/session-selector.js +8 -8
  206. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  207. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  208. package/dist/modes/interactive/components/settings-selector.js +3 -3
  209. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  210. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  211. package/dist/modes/interactive/components/skill-invocation-message.js +2 -2
  212. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  213. package/dist/modes/interactive/components/tool-execution.d.ts +10 -12
  214. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  215. package/dist/modes/interactive/components/tool-execution.js +3 -3
  216. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  217. package/dist/modes/interactive/components/working-status.d.ts +25 -0
  218. package/dist/modes/interactive/components/working-status.d.ts.map +1 -0
  219. package/dist/modes/interactive/components/working-status.js +28 -0
  220. package/dist/modes/interactive/components/working-status.js.map +1 -0
  221. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  222. package/dist/modes/interactive/interactive-mode.js +8 -7
  223. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  224. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  225. package/dist/modes/rpc/rpc-mode.js +8 -0
  226. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  227. package/dist/modes/rpc/rpc-types.d.ts +5 -5
  228. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  229. package/dist/modes/rpc/rpc-types.js.map +1 -1
  230. package/dist/utils/tools-manager.d.ts.map +1 -1
  231. package/dist/utils/tools-manager.js.map +1 -1
  232. package/docs/development.md +2 -2
  233. package/docs/extensions.md +7 -7
  234. package/docs/packages.md +11 -8
  235. package/docs/quickstart.md +2 -2
  236. package/docs/rpc.md +1 -1
  237. package/docs/sdk.md +14 -11
  238. package/docs/session-format.md +1 -1
  239. package/docs/sessions.md +10 -10
  240. package/docs/settings.md +1 -1
  241. package/docs/terminal-setup.md +9 -9
  242. package/docs/tmux.md +10 -10
  243. package/docs/tui.md +2 -2
  244. package/docs/usage.md +9 -9
  245. package/package.json +6 -1
@@ -4,12 +4,51 @@ 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/Atomic discovers workflows from these user-facing locations:
7
+ Atomic/pi discovers workflows from these user-facing locations, in this override order:
8
8
 
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.
12
- - Package-provided: a pi package can expose bundled workflow directories through `package.json` under `pi.builtin`.
9
+ 1. Configured project files from `.atomic/extensions/workflow/config.json` (`workflows.<name>.path`). Legacy `.pi/...` config paths are also considered.
10
+ 2. Project-local files in `.atomic/workflows/*.{ts,js,mjs,cjs}`. Legacy `.pi/workflows/` is also checked.
11
+ 3. Configured global files from `~/.atomic/agent/extensions/workflow/config.json`. Legacy `~/.pi/...` config paths are also considered.
12
+ 4. User-global files in `~/.atomic/agent/workflows/*.{ts,js,mjs,cjs}`. Legacy `~/.pi/agent/workflows/` is also checked.
13
+ 5. Package-provided files from installed Atomic/pi packages.
14
+ 6. Bundled workflows shipped with `@bastani/workflows`.
15
+
16
+ A workflow module may export one default workflow definition and/or named workflow definitions; discovery checks the default export first, then named exports.
17
+
18
+ Configured workflow paths live in extension config. Project config relative paths resolve from the project root; global config relative paths resolve under the user agent directory (`<home>/.atomic/agent`). Project entries override global entries with the same key.
19
+
20
+ ```json
21
+ {
22
+ "workflows": {
23
+ "team": { "path": "./workflows/team.ts" }
24
+ },
25
+ "defaultConcurrency": 4,
26
+ "maxDepth": 4,
27
+ "persistRuns": true,
28
+ "statusFile": false,
29
+ "resumeInFlight": "ask"
30
+ }
31
+ ```
32
+
33
+ Runtime config defaults are `defaultConcurrency: 4`, `maxDepth: 4`, `persistRuns: true`, `statusFile: false`, and `resumeInFlight: "ask"`. Invalid JSON or invalid shapes produce `CONFIG_INVALID` diagnostics; missing config files are ignored. When `statusFile` is enabled, the derived status file defaults under `.atomic/workflows/status.json` for the project.
34
+
35
+ Package-provided workflows can be exposed either explicitly through host package metadata or implicitly through a conventional directory:
36
+
37
+ ```json
38
+ {
39
+ "name": "my-atomic-workflows",
40
+ "keywords": ["pi-package"],
41
+ "atomic": {
42
+ "extensions": ["./src/index.ts"],
43
+ "workflows": ["./workflows"]
44
+ }
45
+ }
46
+ ```
47
+
48
+ - For new Atomic package examples, prefer app-name keys such as `atomic.workflows` and `atomic.extensions` when supported by the host.
49
+ - `pi.workflows` and `pi.extensions` remain supported for pi compatibility and existing first-party package metadata.
50
+ - If no manifest declares workflows, conventional `workflows/` is auto-discovered. Singular `workflow/` is also accepted.
51
+ - App-level config similarly prefers `<appName>Config` (for example `atomicConfig`) where available; legacy `piConfig` is still read as a shim.
13
52
 
14
53
  In a normal consumer project, import from the package:
15
54
 
@@ -42,7 +81,7 @@ export default defineWorkflow("my-workflow")
42
81
  const reviews = await ctx.parallel([
43
82
  { name: "quality", prompt: "Inspect quality risks using this context: {previous}", previous: scout },
44
83
  { name: "runtime", prompt: "Inspect runtime concerns using this context: {previous}", previous: scout },
45
- ]);
84
+ ], { concurrency: 2 });
46
85
 
47
86
  const final = await ctx.task("synthesis", {
48
87
  prompt: "Synthesize findings and recommend next steps.",
@@ -65,6 +104,19 @@ export default defineWorkflow("my-workflow")
65
104
  - `.run(fn)` defines the workflow body.
66
105
  - `.compile()` returns the workflow definition for discovery.
67
106
 
107
+ ## Anti-pattern: no-stage workflows
108
+
109
+ Do not create workflows whose `run` body only executes deterministic code and returns a value without creating a tracked workflow stage. That shape defeats the purpose of the workflow runtime: there is no graph node to inspect, attach to, interrupt, resume, or render.
110
+
111
+ Discovery rejects no-stage workflows with an `INVALID_DEFINITION` diagnostic because the workflow graph would be empty (`cachedLayout.length === 0`). To be valid, the run body must call at least one of:
112
+
113
+ - `ctx.task()`
114
+ - `ctx.chain()`
115
+ - `ctx.parallel()`
116
+ - `ctx.stage()`
117
+
118
+ If the entire job is deterministic TypeScript with no LLM/session interaction, use a script, custom tool, or extension command instead of a workflow. If deterministic code prepares or post-processes LLM work, keep that code in `.run()` or helpers, but pair it with a nearby tracked stage.
119
+
68
120
  ## Inputs
69
121
 
70
122
  Supported input schema types are:
@@ -80,21 +132,23 @@ All schemas support `description` and `required`. Prefer explicit descriptions b
80
132
 
81
133
  `ctx.inputs` contains resolved inputs.
82
134
 
83
- Prefer high-level primitives:
135
+ Prefer high-level primitives for most workflows because they create tracked graph nodes, provide consistent handoff semantics, and keep definitions easier to read:
84
136
 
85
- - `ctx.task(name, options)` — one tracked stage + prompt, returns `WorkflowTaskResult`.
86
- - `ctx.parallel(steps, options?)` — run independent task steps together; keep authored fan-outs intentionally bounded.
87
- - `ctx.chain(steps, options?)` — run dependent task steps sequentially.
88
- - `ctx.ui` — human-in-the-loop primitives when a run needs user input.
137
+ - `ctx.task(name, options)` — use for one LLM/session task with workflow tracking. This is the default choice for a single stage.
138
+ - `ctx.chain(steps, options?)` — use for dependent sequential tasks where each step consumes previous output.
139
+ - `ctx.parallel(steps, options?)` — use for independent branches that can run concurrently; supports shared task/session defaults plus `concurrency` and `failFast`.
140
+ - `ctx.ui` — use for human-in-the-loop decisions during the workflow run.
89
141
 
90
- Use `ctx.stage(name, options?)` only when you need lower-level session control. `StageContext` supports:
142
+ Advanced users and advanced use cases can use `ctx.stage(name, options?)` for finer-grained session control. Reach for it when `ctx.task` is too coarse and you need direct control over the underlying stage session. `StageContext` supports:
91
143
 
92
144
  - `prompt(text, options?)`, `complete(text, options?)`
93
- - `steer`, `followUp`, `subscribe`
145
+ - `steer(text)`, `followUp(text)`, `subscribe(listener)`
94
146
  - session metadata: `sessionId`, `sessionFile`
95
147
  - model/thinking controls: `setModel`, `setThinkingLevel`, `cycleModel`, `cycleThinkingLevel`
96
148
  - state access: `agent`, `model`, `thinkingLevel`, `messages`, `isStreaming`
97
- - tree navigation, compaction, and abort
149
+ - in-session tree navigation: `navigateTree(targetId, { summarize?, customInstructions?, replaceInstructions?, label? })`
150
+ - compaction controls: `compact(customInstructions?)`, `abortCompaction()`
151
+ - current operation abort: `abort()`
98
152
 
99
153
  ## Human-in-the-loop UI
100
154
 
@@ -113,10 +167,11 @@ Common task/stage options include:
113
167
 
114
168
  - `prompt` or `task`
115
169
  - `previous` for handoff context; `{previous}` placeholder inserts it, otherwise context is appended
116
- - `context: "fresh" | "fork"`
117
- - `model`, `fallbackModels`, `thinkingLevel`
118
- - `output`, `outputMode`, `reads`, `progress`, `worktree`, `maxOutput`, `artifacts`, `sessionDir`, `cwd`
119
- - `mcp: { allow?: string[], deny?: string[] }`
170
+ - `context: "fresh" | "fork"`, `forkFromSessionFile`
171
+ - `model`, `fallbackModels`, `thinkingLevel`, `scopedModels`, `modelRegistry`
172
+ - `tools`, `noTools`, `customTools`, `mcp: { allow?: string[], deny?: string[] }`
173
+ - `output`, `outputMode`, `reads`, `worktree`, `maxOutput`, `artifacts`, `sessionDir`, `cwd`, `agentDir`
174
+ - advanced SDK seams when explicitly supplied by host code: `authStorage`, `resourceLoader`, `sessionManager`, `settingsManager`, `sessionStartEvent`
120
175
 
121
176
  `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
177
 
@@ -137,13 +192,18 @@ Use `createRegistry()` when code needs to group definitions explicitly:
137
192
  ```ts
138
193
  import { createRegistry, defineWorkflow } from "@bastani/workflows";
139
194
 
140
- const alpha = defineWorkflow("alpha").run(async () => ({})).compile();
195
+ const alpha = defineWorkflow("alpha")
196
+ .run(async (ctx) => {
197
+ const result = await ctx.task("alpha", { prompt: "Run alpha." });
198
+ return { text: result.text };
199
+ })
200
+ .compile();
141
201
  const registry = createRegistry().register(alpha);
142
202
  registry.names();
143
203
  registry.get("alpha");
144
204
  ```
145
205
 
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:
206
+ `@bastani/workflows` is an Atomic/pi package extension. The host loads extension metadata from supported package manifest keys (new app-name keys where available plus pi-compatible metadata used by existing packages). The extension registers the `workflow` tool, `/workflow` command, renderers, widgets, and lifecycle hooks. Use these user-facing surfaces:
147
207
 
148
208
  - `/workflow <name> key=value ...` inside pi.
149
209
  - The `workflow` tool for LLM-driven orchestration and direct one-off runs.
@@ -160,10 +220,41 @@ const definition = {
160
220
  inputs: {
161
221
  prompt: "map workflow sdk",
162
222
  max_partitions: 1,
223
+ max_concurrency: 4,
163
224
  },
164
225
  } as const;
165
226
 
166
227
  const options: WorkflowOptions = {};
167
228
 
168
229
  await runWorkflow(definition, options);
230
+
231
+ await runWorkflow({
232
+ mode: "parallel",
233
+ task: "Audit auth changes",
234
+ tasks: [
235
+ { name: "security", task: "Review security risks" },
236
+ { name: "runtime", task: "Review runtime risks" },
237
+ ],
238
+ concurrency: 2,
239
+ reads: ["research/context.md"],
240
+ output: "research/auth-audit.md",
241
+ outputMode: "inline",
242
+ maxOutput: { lines: 2000 },
243
+ artifacts: true,
244
+ });
245
+
246
+ await runWorkflow({
247
+ mode: "chain",
248
+ task: "Plan a safe release",
249
+ chainName: "release-plan",
250
+ chainDir: ".atomic/workflows/runs/release-plan",
251
+ chain: [
252
+ { name: "research", task: "Research release constraints for {task}" },
253
+ { name: "plan", task: "Create a release plan from {previous}" },
254
+ ],
255
+ });
169
256
  ```
257
+
258
+ The programmatic definition object mirrors the workflow tool for `mode: "workflow"` / `"named"`, `"single"`, `"parallel"`, and `"chain"` runs, including direct options and stage/session options. Direct chains support `chainName` for status/artifact grouping and `chainDir` as a shared directory for relative reads, outputs, and worktree diffs.
259
+
260
+ Workflow stage sessions follow Atomic SDK directory defaults: resource discovery starts from `.atomic` locations (`~/.atomic/agent`, `<cwd>/.atomic`) and also considers legacy `.pi` locations where the SDK supports multiple config directories. Passing `agentDir` on a stage/task is an explicit user override; passing `resourceLoader` makes that loader responsible for discovery, while `cwd`/`agentDir` still affect session naming and tool path resolution.
@@ -12,7 +12,8 @@
12
12
  * 2. project-local — {cwd}/.atomic/workflows/*.{ts,js,mjs,cjs}
13
13
  * 3. settings-global — paths listed in config.globalWorkflows
14
14
  * 4. user-global — {homeDir}/.atomic/agent/workflows/*.{ts,js,mjs,cjs}
15
- * 5. bundledshipped workflows (skipped when includeBundled=false)
15
+ * 5. packageworkflow files supplied by Atomic/pi packages
16
+ * 6. bundled — shipped workflows (skipped when includeBundled=false)
16
17
  *
17
18
  * Usage:
18
19
  * // Full discovery (all sources):
@@ -39,13 +40,15 @@ import * as bundledManifest from "../../builtin/index.js";
39
40
  * user-global — found in {homeDir}/.atomic/agent/workflows/
40
41
  * settings-project — listed in DiscoveryConfig.projectWorkflows
41
42
  * settings-global — listed in DiscoveryConfig.globalWorkflows
43
+ * package — supplied by Atomic/pi package workflow resources
42
44
  */
43
45
  export type DiscoveryKind =
44
46
  | "bundled"
45
47
  | "project-local"
46
48
  | "user-global"
47
49
  | "settings-project"
48
- | "settings-global";
50
+ | "settings-global"
51
+ | "package";
49
52
 
50
53
  /** Identifies the origin of a discovered workflow definition. */
51
54
  export interface DiscoverySource {
@@ -121,6 +124,8 @@ export interface DiscoveryOptions {
121
124
  homeDir: string;
122
125
  /** Optional extra paths from project/global config. */
123
126
  config?: DiscoveryConfig;
127
+ /** Workflow files supplied by installed Atomic/pi packages. */
128
+ packageWorkflowPaths?: string[] | Record<string, string>;
124
129
  /** When false, bundled workflows are excluded. Default: true */
125
130
  includeBundled?: boolean;
126
131
  }
@@ -143,6 +148,15 @@ export interface DiscoveryResult {
143
148
  * Validate a candidate value as a WorkflowDefinition.
144
149
  * Returns null when valid, or a human-readable rejection reason string.
145
150
  */
151
+ function workflowRunCreatesStage(run: WorkflowDefinition["run"]): boolean {
152
+ // Discovery must not execute workflow bodies: run functions are arbitrary
153
+ // user code and may perform I/O before the first stage. Use a conservative
154
+ // static guard instead so obvious no-stage definitions are rejected before
155
+ // they can register and render an empty graph.
156
+ const source = Function.prototype.toString.call(run);
157
+ return /\.\s*(?:stage|task|chain|parallel)\s*\(/.test(source);
158
+ }
159
+
146
160
  function validateDefinition(value: unknown): string | null {
147
161
  if (value === null || typeof value !== "object") {
148
162
  return "export is not an object";
@@ -161,6 +175,9 @@ function validateDefinition(value: unknown): string | null {
161
175
  if (typeof d["run"] !== "function") {
162
176
  return "run must be a function";
163
177
  }
178
+ if (!workflowRunCreatesStage(d["run"] as WorkflowDefinition["run"])) {
179
+ return "run must create at least one workflow stage via ctx.stage(), ctx.task(), ctx.chain(), or ctx.parallel(); otherwise the workflow graph is empty (cachedLayout.length === 0)";
180
+ }
164
181
  return null;
165
182
  }
166
183
 
@@ -367,7 +384,8 @@ async function loadFromPaths(
367
384
  * 2. project-local — {cwd}/.atomic/workflows/*.{ts,js,mjs,cjs}
368
385
  * 3. settings-global — config.globalWorkflows paths
369
386
  * 4. user-global — {homeDir}/.atomic/agent/workflows/*.{ts,js,mjs,cjs}
370
- * 5. bundledshipped workflows (omitted when includeBundled=false)
387
+ * 5. packagepackage-supplied workflow files
388
+ * 6. bundled — shipped workflows (omitted when includeBundled=false)
371
389
  */
372
390
  export async function discoverWorkflows(
373
391
  options?: Partial<DiscoveryOptions>,
@@ -375,6 +393,7 @@ export async function discoverWorkflows(
375
393
  const cwd = options?.cwd ?? process.cwd();
376
394
  const homeDir = options?.homeDir ?? (await defaultHomeDir());
377
395
  const config = options?.config;
396
+ const packageWorkflowPaths = options?.packageWorkflowPaths;
378
397
  const includeBundled = options?.includeBundled !== false;
379
398
 
380
399
  const diagnostics: DiscoveryDiagnostic[] = [];
@@ -429,7 +448,16 @@ export async function discoverWorkflows(
429
448
  registry = applyBatch(candidates, registry, sources, diagnostics);
430
449
  }
431
450
 
432
- // 5. bundled
451
+ // 5. package workflows
452
+ if (packageWorkflowPaths !== undefined) {
453
+ const hasEntries = Array.isArray(packageWorkflowPaths) ? packageWorkflowPaths.length > 0 : Object.keys(packageWorkflowPaths).length > 0;
454
+ if (hasEntries) {
455
+ const candidates = await loadFromPaths(packageWorkflowPaths, "package", cwd, diagnostics);
456
+ registry = applyBatch(candidates, registry, sources, diagnostics);
457
+ }
458
+ }
459
+
460
+ // 6. bundled
433
461
  if (includeBundled) {
434
462
  const bundledResult = discoverBundledManifest();
435
463
  // Merge bundled: only register names not already present (lower precedence)