@osolmaz/pi-workflows 0.13.3 → 0.14.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 (48) hide show
  1. package/README.md +136 -118
  2. package/dist/builtins/autoimplement.workflow.d.ts +12 -12
  3. package/dist/builtins/autoplan.workflow.d.ts +3 -3
  4. package/dist/builtins/autoplan.workflow.js +44 -35
  5. package/dist/builtins/autoplan.workflow.js.map +1 -1
  6. package/dist/builtins/catalog.js +1 -1
  7. package/dist/builtins/plan-change.workflow.d.ts +6 -6
  8. package/dist/controllers/index.d.ts +1 -1
  9. package/dist/controllers/index.js.map +1 -1
  10. package/dist/controllers/sqlite.d.ts +34 -31
  11. package/dist/controllers/sqlite.js +116 -77
  12. package/dist/controllers/sqlite.js.map +1 -1
  13. package/dist/extension/index.js +721 -202
  14. package/dist/extension/index.js.map +1 -1
  15. package/dist/extension/restart-policy.d.ts +38 -0
  16. package/dist/extension/restart-policy.js +116 -0
  17. package/dist/extension/restart-policy.js.map +1 -0
  18. package/dist/extension/terminal-decision.d.ts +51 -0
  19. package/dist/extension/terminal-decision.js +110 -0
  20. package/dist/extension/terminal-decision.js.map +1 -0
  21. package/dist/state/prune.js +36 -10
  22. package/dist/state/prune.js.map +1 -1
  23. package/dist/workflows/tool-input.d.ts +4 -0
  24. package/dist/workflows/tool-input.js +6 -1
  25. package/dist/workflows/tool-input.js.map +1 -1
  26. package/docs/2026-08-25-workflow-follow-ups.md +8 -6
  27. package/docs/DEFERRED_TURNS.md +39 -26
  28. package/docs/HUMAN_DECISIONS.md +12 -4
  29. package/docs/SQLITE_STATE.md +24 -0
  30. package/docs/WORKFLOW_COMPOSITION.md +1 -1
  31. package/docs/plans/2026-08-19-human-decision-gates-plan.md +34 -8
  32. package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +357 -0
  33. package/docs/workflows.md +85 -29
  34. package/herdr-plugin.toml +1 -1
  35. package/package.json +1 -1
  36. package/skills/autodoc/SKILL.md +1 -1
  37. package/skills/autoimplement/SKILL.md +1 -1
  38. package/skills/autoplan/SKILL.md +6 -6
  39. package/skills/pi-workflows/SKILL.md +2 -0
  40. package/src/builtins/autoplan.workflow.ts +45 -37
  41. package/src/builtins/catalog.ts +1 -1
  42. package/src/controllers/index.ts +3 -0
  43. package/src/controllers/sqlite.ts +226 -155
  44. package/src/extension/index.ts +881 -220
  45. package/src/extension/restart-policy.ts +163 -0
  46. package/src/extension/terminal-decision.ts +172 -0
  47. package/src/state/prune.ts +35 -9
  48. package/src/workflows/tool-input.ts +9 -1
package/README.md CHANGED
@@ -4,25 +4,17 @@
4
4
  <img src="assets/cover.svg" alt="pi-workflows: a representative multi-step workflow graph with plan, implement, verify, review, a fix loop, and a clean finish" width="880">
5
5
  </p>
6
6
 
7
- pi-workflows is a workflow extension for the [pi coding agent](https://pi.dev).
7
+ pi-workflows is a workflow extension for the [Pi coding agent](https://pi.dev).
8
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
9
+ them at any point in a Pi conversation with `/workflow`, and watch them run
10
10
  live in a standalone terminal viewer.
11
11
 
12
- The workflow model is a port of [openclaw/acpx](https://github.com/openclaw/acpx)
13
- flows into pi itself. Agent steps run inside your current pi conversation, so
14
- the model keeps everything it already knows from the discussion. A submitted
15
- agent calls the JSON `workflow` tool with structured output. An assistant agent
16
- writes a normal visible response that becomes the node output. See the [design
17
- philosophy](docs/DESIGN_PHILOSOPHY.md) for the principles behind the engine and
18
- its public parts. Running steps can publish durable [workflow
19
- updates](docs/WORKFLOW_UPDATES.md), including progress counts and ETA data.
20
- Agent instructions use compact [workflow step
21
- messages](docs/WORKFLOW_STEP_MESSAGES.md). Workflows can expose [settings that
22
- change during a run](docs/2026-08-25-workflow-settings.md) and queue [normal
23
- follow-up work after completion](docs/2026-08-25-workflow-follow-ups.md). The
24
- built-in [monitor](docs/MONITOR.md) reports every check without starting an
25
- extra assistant turn.
12
+ Agent steps run inside your current Pi conversation, so the model keeps
13
+ everything it already knows from the discussion. A submitted agent step
14
+ returns structured output through the JSON `workflow` tool, while an
15
+ assistant step writes a normal visible response that becomes the node
16
+ output. The [design philosophy](docs/DESIGN_PHILOSOPHY.md) explains the
17
+ principles behind the engine and its public parts.
26
18
 
27
19
  ## Install
28
20
 
@@ -70,7 +62,7 @@ Set `"skills": []` to disable all bundled skills while keeping the extension.
70
62
  Set `"extensions": []` to keep the skills without loading the extension.
71
63
 
72
64
  Install the interactive terminal viewer separately from crates.io. The crate
73
- is named `pi-workflows`; its command is `piw`:
65
+ is named `pi-workflows` and installs the `piw` command:
74
66
 
75
67
  ```bash
76
68
  cargo install pi-workflows
@@ -88,35 +80,10 @@ All live workflow and controller state uses one local database:
88
80
  ```
89
81
 
90
82
  Runs, decisions, queues, claims, controllers, session capture, notifications,
91
- channel transport state, effects, and large text values share that database.
92
- Reads are read-only. Every write checks its actor, expected revision, and owner
93
- lease when required. See [SQLite state](docs/SQLITE_STATE.md).
94
-
95
- ## Herdr integration
96
-
97
- pi-workflows also ships as a [Herdr](https://herdr.dev) plugin. After installing
98
- `piw` and pi-workflows, synchronize the bundled plugin:
99
-
100
- ```bash
101
- pi-workflows herdr sync
102
- ```
103
-
104
- Run the same command after a pi-workflows update. It finds the package that
105
- provides the running CLI and repairs a Herdr link when npm moved that package.
106
- `pi-workflows herdr setup` remains an alias for existing installations. Use
107
- `--json` for versioned machine-readable output. The [Herdr plugin sync
108
- plan](docs/plans/2026-08-20-herdr-plugin-sync-plan.md) defines update and
109
- recovery behavior.
110
-
111
- When Pi runs inside Herdr, a workflow widget shows `Ctrl+Shift+R piw`. When the widget has hidden rows, this call to action shares the existing scroll-controls line instead of taking another line.
112
- The shortcut opens the exact SQLite run state and lets you choose a split, tab, or new
113
- workspace. `/piw` opens the same menu, and `/piw right`, `/piw below`, `/piw
114
- left`, `/piw above`, `/piw tab`, or `/piw workspace` selects a placement
115
- directly. If a viewer for that run already exists, pi-workflows focuses it
116
- instead of opening a duplicate.
117
-
118
- The plugin uses Herdr's public pane APIs and runs no service or polling loop. It
119
- is also available through the [Herdr plugin marketplace](https://herdr.dev/plugins/).
83
+ channel transport state, effects, and large text values all live there.
84
+ Viewers open the database read-only, and every write checks its actor,
85
+ expected revision, and owner lease when required. See
86
+ [SQLite state](docs/SQLITE_STATE.md).
120
87
 
121
88
  ## Quick start
122
89
 
@@ -141,37 +108,38 @@ export default defineWorkflow({
141
108
  });
142
109
  ```
143
110
 
144
- Then, from any pi conversation:
111
+ Then, from any Pi conversation:
145
112
 
146
113
  ```
147
114
  /workflow echo summarize this repository
148
115
  ```
149
116
 
150
- A model-started workflow is saved before the tool reports it as queued. The returned run ID works
151
- with `workflow status` and `workflow cancel` before execution starts. pi-workflows waits for the
152
- current agent turn to settle before activation. If activation fails, it saves the failure and sends
153
- one follow-up turn so the model can correct the cause and start a new run.
154
-
155
117
  `/workflow` with no arguments lists discovered workflows. `/workflow pause`
156
- lets the current step finish and then holds the run before the next node. This
157
- is useful when you want to interject in the conversation mid-workflow.
158
- `/workflow resume` continues it. Pressing escape to interrupt a turn
159
- pauses the workflow automatically, so the run never nudges the model while
160
- you have taken the conversation back; `/workflow resume` re-delivers the
161
- pending step prompt. `/workflow cancel` stops the active run; if the last run
162
- already ended (for example parked at a checkpoint), it clears the leftover
163
- widget instead. Trailing text becomes `{ task: "..." }`; pass arbitrary input
164
- with `--input-json {"key": "value"}`. The names `answer`, `cancel`, `list`, `pause`, `resume`, and `status` are
165
- reserved and rejected as workflow names.
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.
129
+
130
+ A workflow can also expose [settings that change during a
131
+ run](docs/2026-08-25-workflow-settings.md) and queue [normal follow-up work
132
+ after completion](docs/2026-08-25-workflow-follow-ups.md).
166
133
 
167
134
  While a run is on screen, the footer status bar shows a compact
168
135
  `wf <name> [status] <node>` indicator alongside the widget.
169
136
 
170
- `presentationPrompt` is optional. When present, pi-workflows uses it after the
171
- structured run ends to request one normal, human-readable assistant response.
172
- Without it, pi-workflows does not request a separate final response. If the
173
- model writes text after submitting its last agent step, that text stays visible.
174
- Shell-only and machine-consumed workflows remain model-free.
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.
175
143
 
176
144
  Use `expectedOutput: assistantMessage()` when a normal assistant response must
177
145
  be a node inside the graph rather than a presentation after the run. Its exact
@@ -179,7 +147,7 @@ visible text becomes the node output after the turn settles. The helper has no
179
147
  default character limit; a workflow can set one explicitly with
180
148
  `assistantMessage({ maxChars: 2_000 })`.
181
149
 
182
- ## Compose workflows
150
+ ## Workflow composition
183
151
 
184
152
  A workflow can import another workflow and connect its named exits without copying its nodes:
185
153
 
@@ -208,25 +176,50 @@ export default defineWorkflow({
208
176
  });
209
177
  ```
210
178
 
211
- Direct imports check child input and exit names in TypeScript. Names and paths remain available for dynamic discovery. Nested children share one run, trace, pause state, and cancellation state. See [Workflow composition](docs/WORKFLOW_COMPOSITION.md) for the complete contract.
179
+ Direct imports check child input and exit names in TypeScript, while names and
180
+ paths remain available for dynamic discovery. Nested children share one run,
181
+ trace, pause state, and cancellation state. See
182
+ [Workflow composition](docs/WORKFLOW_COMPOSITION.md) for the complete contract.
212
183
 
213
184
  ## Agent-managed workflows
214
185
 
215
- The model can use the same `workflow` tool to list, start, inspect, pause,
216
- resume, cancel, and answer workflows. Submitted-step contracts use the tool's
217
- `submit` action. Assistant-step contracts require a normal assistant response
218
- instead. Slash commands and model actions share one lifecycle implementation.
219
-
220
- pi-workflows includes a `monitor` workflow for plain-language requests such as:
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.
206
+
207
+ pi-workflows includes a [monitor](docs/MONITOR.md) workflow for plain-language
208
+ requests such as:
221
209
 
222
210
  > Monitor PR 123 every 30 minutes. Report failed checks. Stop when it is merged or closed.
223
211
 
224
212
  The monitor checks immediately, reports only the states requested by the user,
225
213
  waits with a normal shell action, and loops until its stop condition or check
226
- limit. Its input supports `task`, `everyMinutes`, `stopWhen`, `maxChecks`, and
227
- an optional `checkTimeoutMinutes`.
214
+ limit. Every check is reported without starting an extra assistant turn. Its
215
+ input supports `task`, `everyMinutes`, `stopWhen`, `maxChecks`, and an
216
+ optional `checkTimeoutMinutes`.
228
217
 
229
- Monitor is observation-only by default. An explicit `repair` policy authorizes its composed `autoplan` and `autoimplement` path. The monitor checks the target again after repair and stops when the same issue and target evidence return without progress. Project and global workflows can replace the built-in `monitor` by using the same file name.
218
+ Monitor is observation-only by default. An explicit `repair` policy authorizes
219
+ its composed `autoplan` and `autoimplement` path. The monitor checks the
220
+ target again after repair and stops when the same issue and target evidence
221
+ return without progress. Project and global workflows can replace the built-in
222
+ `monitor` by using the same file name.
230
223
 
231
224
  A monitor occupies the session's one active workflow slot. If its Pi runner
232
225
  stops during the shell wait, the run parks and repeats that wait node when a
@@ -241,9 +234,9 @@ resolve the gap. The ideal can win when it is feasible, but work outside the
241
234
  current authority cannot block a valid practical solution. The workflow keeps
242
235
  the detailed implementation plan and shows one short assistant response with
243
236
  the selected plan and a gist of every rejected option. `autoplan` replaces the
244
- earlier `autodevise` name; the old command and export are not retained.
237
+ earlier `autodevise` name, and the old command and export are not retained.
245
238
 
246
- ## Watching a run
239
+ ## Viewers
247
240
 
248
241
  Runs persist in `~/.pi/agent/workflows/state.sqlite` as they execute. The
249
242
  viewer reads that database and re-renders on every state change:
@@ -255,27 +248,17 @@ pi-workflows runs # plain list of recent runs
255
248
  pi-workflows view --once # print a snapshot and exit (good for scripts)
256
249
  ```
257
250
 
258
- The run detail view draws the workflow as a boxed graph, like the acpx replay
259
- viewer. Included nodes use hierarchical labels such as `implementation › redesign › plan`. Every card has a centered step-name header and a divider above its
260
- structured metadata. Border characters keep the graph background, the body
261
- surface begins inside the border, and the header interior uses a separate
262
- surface. Node type, status, attempts, and timing use compact symbol rows; start
263
- and terminal markers sit outside the card. Node types have distinct
264
- semantic colors, active cards use a heavy border, branches carry their case
265
- labels, the taken path is highlighted, and loops route through a gutter on the
266
- right back into their target from above. `←/→` scrubs
267
- backwards and forwards through the recorded steps and re-derives every node's
268
- status as of that step, with the selected step's full output shown below;
269
- scrubbing to the end snaps back to following the run live.
270
-
271
- The Rust `piw` viewer under `tui/` adds a Catppuccin interface, selectable
272
- themes, centered active-node following, draggable browser and inspector sizes,
273
- detailed trace and conversation inspection, temporal replay, and reconnecting
274
- remote viewing. Full cards have one fixed graph-wide size, so streaming,
275
- selection, timer ticks, and replay never move nodes or edges. Live conversation
276
- capture shows text, thinking, tool calls, and tool execution as they happen,
277
- then reconciles settled messages to verbatim Pi entries. See
278
- [the piw guide](docs/tui-viewer.md).
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.
279
262
 
280
263
  ```
281
264
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
@@ -289,23 +272,56 @@ then reconciles settled messages to verbatim Pi entries. See
289
272
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
290
273
  ```
291
274
 
292
- Inside pi, a compact widget above the editor shows one line per workflow node.
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
282
+ [the piw guide](docs/tui-viewer.md).
283
+
284
+ Inside Pi, a compact widget above the editor shows one line per workflow node.
293
285
  The first glyph is the node status. The second glyph is the node type: `●`
294
286
  agent, `ƒ` compute, `!` notification, `$` shell action, `*` function action, or
295
287
  `◆` checkpoint. Repeated visits, runtime details, and timing appear on the same
296
288
  line when they apply. Pi's current theme highlights the full active-node line,
297
289
  while status glyphs keep every state readable without color. Long workflows are
298
- windowed around the active node.
299
- Scroll the list with `shift+↑` / `shift+↓`; it snaps back to following the
300
- active node whenever the workflow advances a step. Use `piw` when you need the
301
- full boxed graph and its edges.
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.
293
+
294
+ ## Herdr integration
295
+
296
+ pi-workflows also ships as a [Herdr](https://herdr.dev) plugin. After installing
297
+ `piw` and pi-workflows, synchronize the bundled plugin:
298
+
299
+ ```bash
300
+ pi-workflows herdr sync
301
+ ```
302
+
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.
307
+
308
+ When Pi runs inside Herdr, the workflow widget shows a `Ctrl+Shift+R piw`
309
+ shortcut. The shortcut opens the exact SQLite run state and lets you choose a
310
+ split, tab, or new workspace. `/piw` opens the same menu, and `/piw right`,
311
+ `/piw below`, `/piw left`, `/piw above`, `/piw tab`, or `/piw workspace`
312
+ selects a placement directly. If a viewer for that run already exists,
313
+ pi-workflows focuses it instead of opening a duplicate.
314
+
315
+ The plugin uses Herdr's public pane APIs and runs no service or polling loop. It
316
+ is also available through the [Herdr plugin marketplace](https://herdr.dev/plugins/).
302
317
 
303
318
  ## Node types
304
319
 
305
320
  A workflow is a graph of named nodes with exactly one entry point. Each node
306
321
  finishes with an output, and edges decide what runs next.
307
322
 
308
- An `agent` node sends a prompt into the pi conversation. By default, it waits
323
+ An `agent` node sends a prompt into the Pi conversation as a compact
324
+ [workflow step message](docs/WORKFLOW_STEP_MESSAGES.md). By default, it waits
309
325
  for structured output through the `workflow` tool. With
310
326
  `expectedOutput: assistantMessage()`, it waits for a normal visible assistant
311
327
  response and uses the exact text as its output. A `compute` node runs a pure
@@ -317,6 +333,9 @@ state so a human can pick it up. On top of `agent`, the `decision` helper asks
317
333
  the model to pick from a fixed set of choices and validates the answer, and
318
334
  `decisionEdge` routes on the result with compile-time case checking.
319
335
 
336
+ Running steps can publish durable [workflow updates](docs/WORKFLOW_UPDATES.md),
337
+ including progress counts and ETA data.
338
+
320
339
  See [docs/workflows.md](docs/workflows.md) for the full authoring reference
321
340
  and [docs/SQLITE_STATE.md](docs/SQLITE_STATE.md) for the on-disk run format.
322
341
 
@@ -352,7 +371,7 @@ The standalone CLI provides read-only views with `pi-workflows controllers` and
352
371
 
353
372
  ## Always-on workflows
354
373
 
355
- 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. 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.
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.
356
375
 
357
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.
358
377
 
@@ -362,7 +381,7 @@ For runs that must continue while Pi is closed, keep the standalone host running
362
381
  pi-workflows host --project /path/to/project
363
382
  ```
364
383
 
365
- 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. It is a foreground process 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.
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.
366
385
 
367
386
  ## Examples
368
387
 
@@ -373,8 +392,7 @@ workflow examples. Copy any of them into `.pi/workflows/` to use them:
373
392
  - `branch` classifies a task with a `decision` and routes to either a
374
393
  continue lane or a clarification checkpoint.
375
394
  - `shell` runs a runtime-owned shell command and parses its output, with no
376
- agent step at all. Shell and function actions can publish durable progress
377
- while they run.
395
+ agent step at all.
378
396
  - `two-turn` chains three agent steps that build on each other's outputs in
379
397
  the same conversation.
380
398
  - `plain-summary` turns structured source data into one visible assistant
@@ -387,9 +405,9 @@ workflow examples. Copy any of them into `.pi/workflows/` to use them:
387
405
  worktree before mutation, documents it when needed, and verifies the current
388
406
  change against eligible base-branch failures. It writes and runs the exact
389
407
  pi-reviewer command, tracks P0 through P2, handles PR comments and CI, and
390
- finalizes the PR. P0 and P1 fixes require another review. P2-only work is
391
- verified without another reviewer round. A five-minute CI wait routes to
392
- additional useful local testing. New evidence can route through autoplan
408
+ finalizes the PR. P0 and P1 fixes require another review, while P2-only work
409
+ is verified without another reviewer round. A five-minute CI wait routes to
410
+ additional useful local testing, and new evidence can route through autoplan
393
411
  and autodoc before implementation resumes.
394
412
  - `human-decision` shows a reusable verified-human gate with a structured
395
413
  machine subject, a separate readable operator presentation, plain choices,
@@ -397,11 +415,11 @@ workflow examples. Copy any of them into `.pi/workflows/` to use them:
397
415
  - `approved-plan` includes the shared plan-change workflow, which composes
398
416
  autoplan, autodoc, the configurable plan decision, and bounded replanning.
399
417
  - `autoresearch` runs an iterative feature-search loop in the style of
400
- [karpathy/autoresearch](https://github.com/karpathy/autoresearch): setup
418
+ [karpathy/autoresearch](https://github.com/karpathy/autoresearch). Setup
401
419
  creates a frozen evaluation harness, one editable feature file, and a
402
- journal; each loop iteration runs one generation of experiments and
403
- journals every result; an assess decision keeps looping until a kept
404
- result plateaus or a diverse generation all fails, then conclusions are
420
+ journal. Each loop iteration then runs one generation of experiments and
421
+ journals every result, and an assess decision keeps looping until a kept
422
+ result plateaus or a diverse generation all fails. Conclusions are
405
423
  written before the winner is promoted out of the loop directory.
406
424
 
407
425
  The controller example at `examples/controllers/pull-request.controller.ts`
@@ -443,9 +443,9 @@ export declare const autoimplementWorkflow: import("../workflows/types.js").Work
443
443
  nodes: {
444
444
  readonly captureIntent: import("../workflows/types.js").SubmittedAgentNodeDefinition;
445
445
  readonly frame: import("../workflows/types.js").SubmittedAgentNodeDefinition;
446
- readonly propose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
447
- readonly ideal: import("../workflows/types.js").SubmittedAgentNodeDefinition;
448
- readonly choose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
446
+ readonly solutions: import("../workflows/types.js").SubmittedAgentNodeDefinition;
447
+ readonly holyGrail: import("../workflows/types.js").SubmittedAgentNodeDefinition;
448
+ readonly select: import("../workflows/types.js").SubmittedAgentNodeDefinition;
449
449
  readonly plan: import("../workflows/types.js").SubmittedAgentNodeDefinition;
450
450
  readonly blocked: import("../workflows/types.js").ComputeNodeDefinition;
451
451
  readonly finalize: import("../workflows/types.js").ComputeNodeDefinition;
@@ -820,9 +820,9 @@ export declare const autoimplementWorkflow: import("../workflows/types.js").Work
820
820
  nodes: {
821
821
  readonly captureIntent: import("../workflows/types.js").SubmittedAgentNodeDefinition;
822
822
  readonly frame: import("../workflows/types.js").SubmittedAgentNodeDefinition;
823
- readonly propose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
824
- readonly ideal: import("../workflows/types.js").SubmittedAgentNodeDefinition;
825
- readonly choose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
823
+ readonly solutions: import("../workflows/types.js").SubmittedAgentNodeDefinition;
824
+ readonly holyGrail: import("../workflows/types.js").SubmittedAgentNodeDefinition;
825
+ readonly select: import("../workflows/types.js").SubmittedAgentNodeDefinition;
826
826
  readonly plan: import("../workflows/types.js").SubmittedAgentNodeDefinition;
827
827
  readonly blocked: import("../workflows/types.js").ComputeNodeDefinition;
828
828
  readonly finalize: import("../workflows/types.js").ComputeNodeDefinition;
@@ -1548,9 +1548,9 @@ export declare const autoimplementWorkflow: import("../workflows/types.js").Work
1548
1548
  nodes: {
1549
1549
  readonly captureIntent: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1550
1550
  readonly frame: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1551
- readonly propose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1552
- readonly ideal: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1553
- readonly choose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1551
+ readonly solutions: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1552
+ readonly holyGrail: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1553
+ readonly select: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1554
1554
  readonly plan: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1555
1555
  readonly blocked: import("../workflows/types.js").ComputeNodeDefinition;
1556
1556
  readonly finalize: import("../workflows/types.js").ComputeNodeDefinition;
@@ -1925,9 +1925,9 @@ export declare const autoimplementWorkflow: import("../workflows/types.js").Work
1925
1925
  nodes: {
1926
1926
  readonly captureIntent: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1927
1927
  readonly frame: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1928
- readonly propose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1929
- readonly ideal: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1930
- readonly choose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1928
+ readonly solutions: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1929
+ readonly holyGrail: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1930
+ readonly select: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1931
1931
  readonly plan: import("../workflows/types.js").SubmittedAgentNodeDefinition;
1932
1932
  readonly blocked: import("../workflows/types.js").ComputeNodeDefinition;
1933
1933
  readonly finalize: import("../workflows/types.js").ComputeNodeDefinition;
@@ -118,9 +118,9 @@ export declare const autoplanWorkflow: import("../workflows/types.js").WorkflowD
118
118
  nodes: {
119
119
  readonly captureIntent: import("../workflows/types.js").SubmittedAgentNodeDefinition;
120
120
  readonly frame: import("../workflows/types.js").SubmittedAgentNodeDefinition;
121
- readonly propose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
122
- readonly ideal: import("../workflows/types.js").SubmittedAgentNodeDefinition;
123
- readonly choose: import("../workflows/types.js").SubmittedAgentNodeDefinition;
121
+ readonly solutions: import("../workflows/types.js").SubmittedAgentNodeDefinition;
122
+ readonly holyGrail: import("../workflows/types.js").SubmittedAgentNodeDefinition;
123
+ readonly select: import("../workflows/types.js").SubmittedAgentNodeDefinition;
124
124
  readonly plan: import("../workflows/types.js").SubmittedAgentNodeDefinition;
125
125
  readonly blocked: import("../workflows/types.js").ComputeNodeDefinition;
126
126
  readonly finalize: import("../workflows/types.js").ComputeNodeDefinition;