@osolmaz/pi-workflows 0.14.0 → 0.15.1

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 (235) hide show
  1. package/README.md +78 -110
  2. package/dist/builtins/autoimplement.workflow.js +3 -1
  3. package/dist/builtins/autoimplement.workflow.js.map +1 -1
  4. package/dist/builtins/change-verification.workflow.js +7 -2
  5. package/dist/builtins/change-verification.workflow.js.map +1 -1
  6. package/dist/builtins/metadata.d.ts +22 -0
  7. package/dist/builtins/metadata.js +10 -0
  8. package/dist/builtins/metadata.js.map +1 -0
  9. package/dist/builtins/monitor.workflow.js +4 -1
  10. package/dist/builtins/monitor.workflow.js.map +1 -1
  11. package/dist/builtins/sanity-check.workflow.js +4 -1
  12. package/dist/builtins/sanity-check.workflow.js.map +1 -1
  13. package/dist/builtins/workspace-preparation.workflow.js +3 -1
  14. package/dist/builtins/workspace-preparation.workflow.js.map +1 -1
  15. package/dist/controllers/index.d.ts +0 -1
  16. package/dist/controllers/index.js +0 -1
  17. package/dist/controllers/index.js.map +1 -1
  18. package/dist/controllers/sqlite.d.ts +51 -0
  19. package/dist/controllers/sqlite.js +433 -57
  20. package/dist/controllers/sqlite.js.map +1 -1
  21. package/dist/controllers/store.d.ts +1 -0
  22. package/dist/extension/controller-command.d.ts +22 -0
  23. package/dist/extension/controller-command.js +32 -0
  24. package/dist/extension/controller-command.js.map +1 -0
  25. package/dist/extension/index.d.ts +2 -9
  26. package/dist/extension/index.js +876 -3447
  27. package/dist/extension/index.js.map +1 -1
  28. package/dist/extension/message-card.d.ts +13 -0
  29. package/dist/extension/message-card.js +46 -0
  30. package/dist/extension/message-card.js.map +1 -0
  31. package/dist/extension/step-message.d.ts +5 -6
  32. package/dist/extension/step-message.js +41 -52
  33. package/dist/extension/step-message.js.map +1 -1
  34. package/dist/host/child-worker-supervisor.d.ts +50 -0
  35. package/dist/host/child-worker-supervisor.js +159 -0
  36. package/dist/host/child-worker-supervisor.js.map +1 -0
  37. package/dist/host/client.d.ts +48 -0
  38. package/dist/host/client.js +216 -0
  39. package/dist/host/client.js.map +1 -0
  40. package/dist/host/controller-worker-entry.d.ts +2 -0
  41. package/dist/host/controller-worker-entry.js +244 -0
  42. package/dist/host/controller-worker-entry.js.map +1 -0
  43. package/dist/host/controller-worker-protocol.d.ts +36 -0
  44. package/dist/host/controller-worker-protocol.js +49 -0
  45. package/dist/host/controller-worker-protocol.js.map +1 -0
  46. package/dist/host/controller-worker-supervisor.d.ts +21 -0
  47. package/dist/host/controller-worker-supervisor.js +54 -0
  48. package/dist/host/controller-worker-supervisor.js.map +1 -0
  49. package/dist/host/host-entry.d.ts +2 -0
  50. package/dist/host/host-entry.js +23 -0
  51. package/dist/host/host-entry.js.map +1 -0
  52. package/dist/host/processes.d.ts +17 -12
  53. package/dist/host/processes.js +154 -50
  54. package/dist/host/processes.js.map +1 -1
  55. package/dist/host/protocol.d.ts +38 -0
  56. package/dist/host/protocol.js +156 -0
  57. package/dist/host/protocol.js.map +1 -0
  58. package/dist/host/resolver-entry.d.ts +49 -0
  59. package/dist/host/resolver-entry.js +149 -0
  60. package/dist/host/resolver-entry.js.map +1 -0
  61. package/dist/host/rpc-executor.d.ts +14 -3
  62. package/dist/host/rpc-executor.js +63 -30
  63. package/dist/host/rpc-executor.js.map +1 -1
  64. package/dist/host/runner.d.ts +95 -29
  65. package/dist/host/runner.js +2311 -348
  66. package/dist/host/runner.js.map +1 -1
  67. package/dist/host/state.d.ts +174 -0
  68. package/dist/host/state.js +689 -0
  69. package/dist/host/state.js.map +1 -0
  70. package/dist/host/worker-entry.d.ts +10 -0
  71. package/dist/host/worker-entry.js +446 -0
  72. package/dist/host/worker-entry.js.map +1 -0
  73. package/dist/host/worker-protocol.d.ts +31 -0
  74. package/dist/host/worker-protocol.js +122 -0
  75. package/dist/host/worker-protocol.js.map +1 -0
  76. package/dist/host/worker-store.d.ts +80 -0
  77. package/dist/host/worker-store.js +91 -0
  78. package/dist/host/worker-store.js.map +1 -0
  79. package/dist/host/worker-supervisor.d.ts +22 -0
  80. package/dist/host/worker-supervisor.js +54 -0
  81. package/dist/host/worker-supervisor.js.map +1 -0
  82. package/dist/render/canvas.d.ts +2 -1
  83. package/dist/render/canvas.js +40 -15
  84. package/dist/render/canvas.js.map +1 -1
  85. package/dist/render/graph-render.d.ts +7 -3
  86. package/dist/render/graph-render.js +125 -74
  87. package/dist/render/graph-render.js.map +1 -1
  88. package/dist/state/database.js +3 -1
  89. package/dist/state/database.js.map +1 -1
  90. package/dist/state/index.d.ts +1 -0
  91. package/dist/state/index.js +1 -0
  92. package/dist/state/index.js.map +1 -1
  93. package/dist/state/schema.d.ts +1 -1
  94. package/dist/state/schema.js +171 -3
  95. package/dist/state/schema.js.map +1 -1
  96. package/dist/state/viewer.d.ts +46 -0
  97. package/dist/state/viewer.js +249 -0
  98. package/dist/state/viewer.js.map +1 -0
  99. package/dist/viewer/cli.d.ts +1 -1
  100. package/dist/viewer/cli.js +47 -18
  101. package/dist/viewer/cli.js.map +1 -1
  102. package/dist/workflows/composition.js +25 -2
  103. package/dist/workflows/composition.js.map +1 -1
  104. package/dist/workflows/definition.d.ts +3 -1
  105. package/dist/workflows/definition.js +25 -0
  106. package/dist/workflows/definition.js.map +1 -1
  107. package/dist/workflows/engine.d.ts +1 -0
  108. package/dist/workflows/engine.js +157 -42
  109. package/dist/workflows/engine.js.map +1 -1
  110. package/dist/workflows/errors.d.ts +3 -1
  111. package/dist/workflows/errors.js +4 -7
  112. package/dist/workflows/errors.js.map +1 -1
  113. package/dist/workflows/human-decision.d.ts +3 -0
  114. package/dist/workflows/human-decision.js +31 -0
  115. package/dist/workflows/human-decision.js.map +1 -1
  116. package/dist/workflows/index.d.ts +1 -1
  117. package/dist/workflows/index.js +1 -1
  118. package/dist/workflows/index.js.map +1 -1
  119. package/dist/workflows/schema.js +17 -6
  120. package/dist/workflows/schema.js.map +1 -1
  121. package/dist/{viewer → workflows}/session-reducer.d.ts +3 -1
  122. package/dist/{viewer → workflows}/session-reducer.js +4 -0
  123. package/dist/workflows/session-reducer.js.map +1 -0
  124. package/dist/workflows/store.d.ts +87 -1
  125. package/dist/workflows/store.js +892 -93
  126. package/dist/workflows/store.js.map +1 -1
  127. package/dist/workflows/tool-input.d.ts +0 -26
  128. package/dist/workflows/tool-input.js +2 -50
  129. package/dist/workflows/tool-input.js.map +1 -1
  130. package/dist/workflows/types.d.ts +36 -4
  131. package/docs/2026-08-30-out-of-process-workflow-host-plan.md +353 -0
  132. package/docs/CONTROLLERS.md +11 -11
  133. package/docs/DEFERRED_TURNS.md +23 -2
  134. package/docs/SQLITE_STATE.md +41 -31
  135. package/docs/WORKFLOW_HOST.md +452 -0
  136. package/docs/development.md +46 -30
  137. package/docs/live-replay-protocol.md +129 -100
  138. package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +42 -0
  139. package/docs/plans/2026-08-28-piw-incremental-viewer-plan.md +293 -0
  140. package/docs/plans/piw-viewer-experience-implementation-plan.md +11 -1
  141. package/docs/plans/tui-viewer-implementation-plan.md +5 -0
  142. package/docs/tui-viewer.md +18 -3
  143. package/docs/workflows.md +162 -210
  144. package/examples/workflows/command-batch.workflow.ts +2 -0
  145. package/examples/workflows/shell.workflow.ts +2 -1
  146. package/herdr-plugin.toml +1 -1
  147. package/package.json +1 -1
  148. package/src/builtins/autoimplement.workflow.ts +3 -0
  149. package/src/builtins/change-verification.workflow.ts +7 -2
  150. package/src/builtins/metadata.ts +9 -0
  151. package/src/builtins/monitor.workflow.ts +4 -0
  152. package/src/builtins/sanity-check.workflow.ts +4 -0
  153. package/src/builtins/workspace-preparation.workflow.ts +3 -1
  154. package/src/controllers/index.ts +0 -5
  155. package/src/controllers/sqlite.ts +709 -76
  156. package/src/controllers/store.ts +1 -0
  157. package/src/extension/controller-command.ts +45 -0
  158. package/src/extension/index.ts +944 -4163
  159. package/src/extension/message-card.ts +61 -0
  160. package/src/extension/step-message.ts +58 -63
  161. package/src/host/child-worker-supervisor.ts +183 -0
  162. package/src/host/client.ts +293 -0
  163. package/src/host/controller-worker-entry.ts +311 -0
  164. package/src/host/controller-worker-protocol.ts +104 -0
  165. package/src/host/controller-worker-supervisor.ts +79 -0
  166. package/src/host/host-entry.ts +23 -0
  167. package/src/host/processes.ts +171 -54
  168. package/src/host/protocol.ts +196 -0
  169. package/src/host/resolver-entry.ts +241 -0
  170. package/src/host/rpc-executor.ts +76 -34
  171. package/src/host/runner.ts +2813 -422
  172. package/src/host/state.ts +1160 -0
  173. package/src/host/worker-entry.ts +533 -0
  174. package/src/host/worker-protocol.ts +165 -0
  175. package/src/host/worker-store.ts +229 -0
  176. package/src/host/worker-supervisor.ts +74 -0
  177. package/src/render/canvas.ts +44 -10
  178. package/src/render/graph-render.ts +145 -90
  179. package/src/state/database.ts +2 -1
  180. package/src/state/index.ts +14 -0
  181. package/src/state/schema.ts +171 -3
  182. package/src/state/viewer.ts +356 -0
  183. package/src/viewer/cli.ts +49 -17
  184. package/src/workflows/composition.ts +36 -2
  185. package/src/workflows/definition.ts +32 -0
  186. package/src/workflows/engine.ts +157 -54
  187. package/src/workflows/errors.ts +11 -2
  188. package/src/workflows/human-decision.ts +49 -0
  189. package/src/workflows/index.ts +2 -0
  190. package/src/workflows/schema.ts +19 -6
  191. package/src/{viewer → workflows}/session-reducer.ts +11 -1
  192. package/src/workflows/store.ts +1316 -108
  193. package/src/workflows/tool-input.ts +3 -69
  194. package/src/workflows/types.ts +32 -4
  195. package/dist/controllers/workflow-engine-scheduler.d.ts +0 -29
  196. package/dist/controllers/workflow-engine-scheduler.js +0 -175
  197. package/dist/controllers/workflow-engine-scheduler.js.map +0 -1
  198. package/dist/extension/controller-host.d.ts +0 -48
  199. package/dist/extension/controller-host.js +0 -110
  200. package/dist/extension/controller-host.js.map +0 -1
  201. package/dist/extension/deferred-turn-coordinator.d.ts +0 -32
  202. package/dist/extension/deferred-turn-coordinator.js +0 -143
  203. package/dist/extension/deferred-turn-coordinator.js.map +0 -1
  204. package/dist/extension/deferred-turn.d.ts +0 -44
  205. package/dist/extension/deferred-turn.js +0 -110
  206. package/dist/extension/deferred-turn.js.map +0 -1
  207. package/dist/extension/executor.d.ts +0 -86
  208. package/dist/extension/executor.js +0 -311
  209. package/dist/extension/executor.js.map +0 -1
  210. package/dist/extension/follow-up-coordinator.d.ts +0 -27
  211. package/dist/extension/follow-up-coordinator.js +0 -131
  212. package/dist/extension/follow-up-coordinator.js.map +0 -1
  213. package/dist/extension/recorder.d.ts +0 -84
  214. package/dist/extension/recorder.js +0 -528
  215. package/dist/extension/recorder.js.map +0 -1
  216. package/dist/extension/restart-policy.d.ts +0 -38
  217. package/dist/extension/restart-policy.js +0 -116
  218. package/dist/extension/restart-policy.js.map +0 -1
  219. package/dist/extension/session-events.d.ts +0 -133
  220. package/dist/extension/session-events.js +0 -61
  221. package/dist/extension/session-events.js.map +0 -1
  222. package/dist/extension/terminal-decision.d.ts +0 -51
  223. package/dist/extension/terminal-decision.js +0 -110
  224. package/dist/extension/terminal-decision.js.map +0 -1
  225. package/dist/viewer/session-reducer.js.map +0 -1
  226. package/src/controllers/workflow-engine-scheduler.ts +0 -246
  227. package/src/extension/controller-host.ts +0 -167
  228. package/src/extension/deferred-turn-coordinator.ts +0 -171
  229. package/src/extension/deferred-turn.ts +0 -166
  230. package/src/extension/executor.ts +0 -411
  231. package/src/extension/follow-up-coordinator.ts +0 -151
  232. package/src/extension/recorder.ts +0 -655
  233. package/src/extension/restart-policy.ts +0 -163
  234. package/src/extension/session-events.ts +0 -121
  235. package/src/extension/terminal-decision.ts +0 -172
package/README.md CHANGED
@@ -5,9 +5,9 @@
5
5
  </p>
6
6
 
7
7
  pi-workflows is a workflow extension for the [Pi coding agent](https://pi.dev).
8
- It lets you define multi-step agent workflows as TypeScript graphs, trigger
9
- them at any point in a Pi conversation with `/workflow`, and watch them run
10
- live in a standalone terminal viewer.
8
+ It lets you define multi-step agent workflows as TypeScript graphs and trigger
9
+ them at any point in a Pi conversation with `/workflow`. A standalone terminal
10
+ viewer shows each run live.
11
11
 
12
12
  Agent steps run inside your current Pi conversation, so the model keeps
13
13
  everything it already knows from the discussion. A submitted agent step
@@ -41,7 +41,7 @@ The Pi package includes the extension and six optional skills:
41
41
  - `autoplan` selects the best practical solution and writes an implementation plan.
42
42
  - `autodoc` records an existing plan in canonical documentation.
43
43
  - `autoimplement` implements an existing plan and verifies the result.
44
- - `sanity-check` reviews whether a contribution is necessary, focused, and well supported.
44
+ - `sanity-check` reviews whether a contribution is necessary, and whether it is focused and well supported.
45
45
 
46
46
  Pi discovers these skills when it loads the package. Use `pi config` to disable
47
47
  the extension, all bundled skills, or one skill independently. The equivalent
@@ -96,7 +96,6 @@ import { agent, defineWorkflow } from "@osolmaz/pi-workflows";
96
96
 
97
97
  export default defineWorkflow({
98
98
  name: "echo",
99
- presentationPrompt: "Give the user the concise reply from the workflow result.",
100
99
  startAt: "reply",
101
100
  nodes: {
102
101
  reply: agent({
@@ -115,32 +114,20 @@ Then, from any Pi conversation:
115
114
  ```
116
115
 
117
116
  `/workflow` with no arguments lists discovered workflows. `/workflow pause`
118
- lets the current step finish and then holds the run before the next node,
119
- which is useful when you want to interject in the conversation mid-workflow.
120
- `/workflow resume` continues it. Pressing escape to interrupt a turn pauses
121
- the workflow automatically, so the run never nudges the model while you have
122
- taken the conversation back. `/workflow resume` then re-delivers the pending
123
- step prompt. `/workflow cancel` stops the active run. If the last run already
124
- ended (for example parked at a checkpoint), it clears the leftover widget
125
- instead. Trailing text becomes `{ task: "..." }`, and `--input-json
126
- {"key": "value"}` passes arbitrary input. The names `answer`, `cancel`,
127
- `list`, `pause`, `resume`, and `status` are reserved and rejected as workflow
128
- names.
117
+ stops the worker and parks the run at its last durable boundary. `/workflow
118
+ resume` starts a new worker generation from that boundary. `/workflow cancel`
119
+ stops the active run; `/workflow cancel <run-id>` can also cancel a named stale
120
+ run when no live owner holds it. A checkpoint waits until `/workflow answer
121
+ <json-or-text>` supplies its input.
122
+
123
+ Trailing text becomes `{ task: "..." }`, and `--input-json {"key": "value"}`
124
+ passes arbitrary input. The names `answer`, `cancel`, `list`, `pause`, `resume`,
125
+ and `status` are reserved and rejected as workflow names.
129
126
 
130
127
  A workflow can also expose [settings that change during a
131
128
  run](docs/2026-08-25-workflow-settings.md) and queue [normal follow-up work
132
129
  after completion](docs/2026-08-25-workflow-follow-ups.md).
133
130
 
134
- While a run is on screen, the footer status bar shows a compact
135
- `wf <name> [status] <node>` indicator alongside the widget.
136
-
137
- `presentationPrompt` is optional. After each top-level interactive run ends,
138
- pi-workflows gives the model one normal terminal decision turn with the exact
139
- stored input, result, terminal reason, and restart history. A presentation
140
- prompt adds instructions for the human-readable response. Presentation and
141
- factual fallback share one durable turn intent, so only one decision turn is
142
- sent. Waiting checkpoints and controller child runs do not create this turn.
143
-
144
131
  Use `expectedOutput: assistantMessage()` when a normal assistant response must
145
132
  be a node inside the graph rather than a presentation after the run. Its exact
146
133
  visible text becomes the node output after the turn settles. The helper has no
@@ -183,26 +170,18 @@ trace, pause state, and cancellation state. See
183
170
 
184
171
  ## Agent-managed workflows
185
172
 
186
- The model can use the same `workflow` tool to list, start, restart, inspect,
187
- pause, resume, cancel, and answer workflows. `restart` takes a terminal run ID,
188
- reuses its exact workflow reference and input, and creates a new immutable run.
189
- Submitted-step contracts use the tool's
190
- `submit` action, while assistant-step contracts require a normal assistant
191
- response instead. Slash commands and model actions share one lifecycle
192
- implementation.
193
-
194
- A model-started workflow is saved before the tool reports it as queued, so the
195
- returned run ID works with `workflow status` and `workflow cancel` before
196
- execution starts. pi-workflows waits for the current agent turn to settle
197
- before activation. A terminal decision turn can reserve at most one restart,
198
- Monitor run, or other workflow start. Activation waits for that turn to settle.
199
- If activation fails, pi-workflows saves the failure and sends one decision turn
200
- so the model can correct the cause safely.
201
-
202
- Restart is never automatic. Explicit cancellation is not restartable through
203
- the shortcut. A chain permits at most three restarts and rejects a repeated
204
- terminal fingerprint. Pi Workflows uses Pi's current conversation for the
205
- continuation decision and does not capture or persist an original user message.
173
+ The model can use the `workflow` tool to list, start, inspect, pause, resume,
174
+ cancel, and answer ordinary checkpoints. It cannot answer a protected human
175
+ decision. A person must answer that request through `/workflow answer` in the
176
+ origin Pi session. The model uses `update` for durable progress from the current
177
+ attempt and `submit` for structured step output. Assistant-message steps require
178
+ a normal visible assistant response instead. The extension sends all lifecycle
179
+ mutations to the host and reports success only after the host commits them.
180
+
181
+ A model-started workflow is saved before the tool reports it as accepted, so
182
+ the returned run ID works with `workflow status` and `workflow cancel`
183
+ immediately. Duplicate host commands and step submissions adopt their stored
184
+ receipts instead of repeating a committed transition.
206
185
 
207
186
  pi-workflows includes a [monitor](docs/MONITOR.md) workflow for plain-language
208
187
  requests such as:
@@ -221,14 +200,15 @@ target again after repair and stops when the same issue and target evidence
221
200
  return without progress. Project and global workflows can replace the built-in
222
201
  `monitor` by using the same file name.
223
202
 
224
- A monitor occupies the session's one active workflow slot. If its Pi runner
225
- stops during the shell wait, the run parks and repeats that wait node when a
226
- runner resumes it.
203
+ A monitor occupies the session's one active workflow slot. If its worker or the
204
+ host stops during the shell wait, the run parks and repeats that idempotent wait
205
+ node when the host resumes it.
227
206
 
228
- Because the workflow runs in your current conversation, you can have a long
229
- discussion first and then trigger a workflow that builds on it. The
230
- `autoplan` example does exactly that. It frames the problem and scope, devises
231
- an elegant production-ready solution, and compares it with the holy grail. It
207
+ Because interactive agent steps run in the origin conversation, you can have a
208
+ long discussion first and then trigger a workflow that builds on it. The
209
+ `autoplan` example does exactly that. It frames the problem and scope, then
210
+ devises an elegant production-ready solution and compares it with the holy
211
+ grail. It
232
212
  then selects the best practical in-scope solution without asking the user to
233
213
  resolve the gap. The ideal can win when it is feasible, but work outside the
234
214
  current authority cannot block a valid practical solution. The workflow keeps
@@ -248,48 +228,18 @@ pi-workflows runs # plain list of recent runs
248
228
  pi-workflows view --once # print a snapshot and exit (good for scripts)
249
229
  ```
250
230
 
251
- The run detail view draws the workflow as a boxed graph, like the replay
252
- viewer in [openclaw/acpx](https://github.com/openclaw/acpx), whose flows the
253
- pi-workflows workflow model was originally ported from. Included nodes use
254
- hierarchical labels such as `implementation › redesign › plan`, and each card
255
- shows its step name plus node type, status, attempts, and timing in compact
256
- symbol rows. Node types have distinct semantic colors, active cards use a
257
- heavy border, branches carry their case labels, the taken path is highlighted,
258
- and loops route through a gutter on the right back into their target from
259
- above. `←/→` scrubs backwards and forwards through the recorded steps and
260
- re-derives every node's status as of that step, with the selected step's full
261
- output shown below. Scrubbing to the end snaps back to following the run live.
231
+ The run detail view draws the workflow as a boxed graph. `←/→` replays the
232
+ recorded steps with each step's full output, and scrubbing to the end snaps
233
+ back to following the run live.
262
234
 
263
- ```
264
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
265
- ┃ review ┃
266
- ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
267
- ┃ ● agent ◐ running ┃
268
- ┃ ↻ 2 ◷ 12s ┃
269
- ┃ ◇ clean ┃
270
- ┃ ◇ issues_found ┃
271
- ┃ … reviewing implementation ┃
272
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
273
- ```
274
-
275
- The Rust `piw` viewer under `tui/` adds a Catppuccin interface, selectable
276
- themes, centered active-node following, draggable browser and inspector sizes,
277
- detailed trace and conversation inspection, temporal replay, and reconnecting
278
- remote viewing. Cards have one fixed graph-wide size, so streaming, selection,
279
- timer ticks, and replay never move nodes or edges. Live conversation capture
280
- shows text, thinking, tool calls, and tool execution as they happen, then
281
- reconciles settled messages to verbatim Pi entries. See
235
+ The Rust `piw` viewer under `tui/` is the full interactive terminal UI, with
236
+ selectable themes, detailed trace and conversation inspection, temporal
237
+ replay, and reconnecting remote viewing. See
282
238
  [the piw guide](docs/tui-viewer.md).
283
239
 
284
- Inside Pi, a compact widget above the editor shows one line per workflow node.
285
- The first glyph is the node status. The second glyph is the node type: `●`
286
- agent, `ƒ` compute, `!` notification, `$` shell action, `*` function action, or
287
- `◆` checkpoint. Repeated visits, runtime details, and timing appear on the same
288
- line when they apply. Pi's current theme highlights the full active-node line,
289
- while status glyphs keep every state readable without color. Long workflows are
290
- windowed around the active node. Scroll the list with `shift+↑` / `shift+↓`.
291
- It snaps back to following the active node whenever the workflow advances a
292
- step. Use `piw` when you need the full boxed graph and its edges.
240
+ Inside Pi, a compact widget above the editor shows one line per workflow node,
241
+ with glyphs for node status and type. Scroll it with `shift+↑` / `shift+↓`.
242
+ Use `piw` when you need the full boxed graph and its edges.
293
243
 
294
244
  ## Herdr integration
295
245
 
@@ -300,10 +250,8 @@ pi-workflows also ships as a [Herdr](https://herdr.dev) plugin. After installing
300
250
  pi-workflows herdr sync
301
251
  ```
302
252
 
303
- Run the same command after a pi-workflows update. It finds the package that
304
- provides the running CLI and repairs a Herdr link when npm moved that package.
305
- `pi-workflows herdr setup` remains an alias for existing installations. Use
306
- `--json` for versioned machine-readable output.
253
+ Run the same command after a pi-workflows update. `pi-workflows herdr setup`
254
+ remains an alias for existing installations.
307
255
 
308
256
  When Pi runs inside Herdr, the workflow widget shows a `Ctrl+Shift+R piw`
309
257
  shortcut. The shortcut opens the exact SQLite run state and lets you choose a
@@ -320,16 +268,16 @@ is also available through the [Herdr plugin marketplace](https://herdr.dev/plugi
320
268
  A workflow is a graph of named nodes with exactly one entry point. Each node
321
269
  finishes with an output, and edges decide what runs next.
322
270
 
323
- An `agent` node sends a prompt into the Pi conversation as a compact
271
+ An `agent` node sends a prompt into the origin Pi conversation as a compact
324
272
  [workflow step message](docs/WORKFLOW_STEP_MESSAGES.md). By default, it waits
325
273
  for structured output through the `workflow` tool. With
326
274
  `expectedOutput: assistantMessage()`, it waits for a normal visible assistant
327
275
  response and uses the exact text as its output. A `compute` node runs a pure
328
276
  TypeScript function. A `notify` node writes a durable message for the Pi
329
- session that started the run. An `action` node performs a side effect, either a
330
- TypeScript function (`action({ run })`) or a runtime-owned shell command
331
- (`shell({ exec, parse })`). A `checkpoint` node ends the run in a `waiting`
332
- state so a human can pick it up. On top of `agent`, the `decision` helper asks
277
+ session that started the run. An `action` or `shell` node must declare an
278
+ `idempotentEffect(...)` or `manualEffect(...)` recovery contract before it can
279
+ perform a side effect. A `checkpoint` node ends the run in a `waiting` state so
280
+ a human can pick it up. On top of `agent`, the `decision` helper asks
333
281
  the model to pick from a fixed set of choices and validates the answer, and
334
282
  `decisionEdge` routes on the result with compile-time case checking.
335
283
 
@@ -341,7 +289,7 @@ and [docs/SQLITE_STATE.md](docs/SQLITE_STATE.md) for the on-disk run format.
341
289
 
342
290
  ## Controllers
343
291
 
344
- Controllers keep long-running automation aligned with current external state. They store desired state in `spec`, report observed state through conditions and `status`, and reconcile a deduplicated resource key whenever an event or retry makes it ready.
292
+ Controllers keep long-running automation aligned with current external state. They store desired state in `spec` and report observed state through conditions and `status`, then reconcile a deduplicated resource key whenever an event or retry makes it ready.
345
293
 
346
294
  Put `*.controller.ts` files in `.pi/controllers/` or `~/.pi/agent/controllers/`. Import the API from `@osolmaz/pi-workflows/controllers`:
347
295
 
@@ -367,21 +315,36 @@ Apply and inspect resources from Pi:
367
315
  /controller reconcile example item-1
368
316
  ```
369
317
 
370
- The standalone CLI provides read-only views with `pi-workflows controllers` and `pi-workflows controller <controller> <key>`. See [docs/CONTROLLERS.md](docs/CONTROLLERS.md) for reconciliation, queue, effect, and child workflow semantics.
318
+ The extension resolves controller initialization in a child process, then sends the declarative resource to the global host. Controller reconciliation also runs in supervised children. The standalone CLI provides read-only views with `pi-workflows controllers` and `pi-workflows controller <controller> <key>`. See [docs/CONTROLLERS.md](docs/CONTROLLERS.md) for reconciliation, queue, effect, and child workflow semantics.
371
319
 
372
320
  ## Always-on workflows
373
321
 
374
- Runs do not depend on the Pi window. Every `/workflow` run is claimed through a durable queue, so closing Pi mid-run **parks** the run instead of cancelling it. Another interactive session cannot claim it. Reopening the exact session that started the run resumes it, and a standalone host can also resume it without changing where reports go. A checkpointed run waits durably until you answer it with `/workflow answer <json>`, which continues the graph in a linked run.
322
+ Every workflow enters one durable global queue. The extension starts the
323
+ package-owned host on demand. Closing Pi does not stop a compute, action, or
324
+ shell node. When a run reaches an interactive agent, assistant-message, or
325
+ human-decision step, the host parks it and saves a request for the origin Pi
326
+ session. Reopening that session presents the same request once. A protected
327
+ human decision does not start a model turn; a person answers it with
328
+ `/workflow answer`.
375
329
 
376
- Workflow reports use a durable session-addressed outbox. A report waits while its starting session is closed and is delivered only to that session when it opens again. Runs in the same database do not broadcast messages to each other's conversations.
330
+ The host also reconciles controllers. Controller child workflows without an
331
+ origin session can use headless `pi --mode rpc` agent steps. A child that needs
332
+ a visible assistant response must have an origin-session binding.
377
333
 
378
- For runs that must continue while Pi is closed, keep the standalone host running:
334
+ Use the CLI to inspect or control the on-demand process:
379
335
 
380
336
  ```bash
381
- pi-workflows host --project /path/to/project
337
+ pi-workflows host start
338
+ pi-workflows host status
339
+ pi-workflows host stop
340
+ pi-workflows host run # stay attached; stop with Ctrl-C
382
341
  ```
383
342
 
384
- The host claims parked runs and reconciles controllers without a Pi session. Conversation nodes execute in headless `pi --mode rpc` children that expose the same `workflow` tool contract. The host runs in the foreground, so stop it with Ctrl-C. A crashed host's leftovers are reaped by the next one. See [docs/workflows.md](docs/workflows.md#durable-runs-parking-and-resume) for the model and [docs/SQLITE_STATE.md](docs/SQLITE_STATE.md) for the on-disk rules.
343
+ These commands manage one host for the complete user database, not one host per
344
+ project. They do not install an operating-system service. A new host reaps exact
345
+ orphan process identities and resumes safe work from committed state. See
346
+ [docs/workflows.md](docs/workflows.md#durable-runs-parking-and-resume) and
347
+ [docs/WORKFLOW_HOST.md](docs/WORKFLOW_HOST.md).
385
348
 
386
349
  ## Examples
387
350
 
@@ -404,8 +367,8 @@ workflow examples. Copy any of them into `.pi/workflows/` to use them:
404
367
  - `autoimplement` finds a clear existing plan, prepares a safe branch or
405
368
  worktree before mutation, documents it when needed, and verifies the current
406
369
  change against eligible base-branch failures. It writes and runs the exact
407
- pi-reviewer command, tracks P0 through P2, handles PR comments and CI, and
408
- finalizes the PR. P0 and P1 fixes require another review, while P2-only work
370
+ pi-reviewer command and tracks P0 through P2 findings, then handles PR
371
+ comments and CI and finalizes the PR. P0 and P1 fixes require another review, while P2-only work
409
372
  is verified without another reviewer round. A five-minute CI wait routes to
410
373
  additional useful local testing, and new evidence can route through autoplan
411
374
  and autodoc before implementation resumes.
@@ -426,6 +389,11 @@ The controller example at `examples/controllers/pull-request.controller.ts`
426
389
  shows child repair work and check polling. It also uses expected-head guards
427
390
  and recoverable merge effects.
428
391
 
392
+ ## Origins
393
+
394
+ The workflow model was originally ported from
395
+ [openclaw/acpx](https://github.com/openclaw/acpx) flows.
396
+
429
397
  ## License
430
398
 
431
399
  [MIT](LICENSE)
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { runCommandBatch, } from "../workflows/command-batch.js";
3
- import { action, agent, compute, defineWorkflow, includeWorkflow, includedResult, } from "../workflows/definition.js";
3
+ import { action, agent, compute, defineWorkflow, includeWorkflow, includedResult, manualEffect, } from "../workflows/definition.js";
4
4
  import { digest } from "../workflows/human-decision.js";
5
5
  import { allowSettingsPath, workflowSettings } from "../workflows/settings.js";
6
6
  import autodocWorkflow, {} from "./autodoc.workflow.js";
@@ -1413,6 +1413,7 @@ export const autoimplementWorkflow = defineWorkflow({
1413
1413
  run: selectReviewCommands,
1414
1414
  }),
1415
1415
  runReview: action({
1416
+ effect: manualEffect("pi-workflows.autoimplement.review"),
1416
1417
  statusDetail: "running pi-reviewer commands",
1417
1418
  timeoutMs: (context) => {
1418
1419
  const selected = latestOutput(context, ["selectReviewCommands"]);
@@ -1517,6 +1518,7 @@ export const autoimplementWorkflow = defineWorkflow({
1517
1518
  validate: parseCiInspectionForPublished,
1518
1519
  }),
1519
1520
  trackCi: action({
1521
+ effect: manualEffect("pi-workflows.autoimplement.track-ci"),
1520
1522
  statusDetail: "tracking pending CI commands",
1521
1523
  timeoutMs: (context) => {
1522
1524
  const inspected = latestOutput(context, ["inspectCi"]);