@osolmaz/pi-workflows 0.5.2 → 0.6.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.
- package/README.md +13 -3
- package/dist/builtins/catalog.js +1 -1
- package/dist/builtins/monitor.workflow.d.ts +25 -69
- package/dist/builtins/monitor.workflow.js +194 -123
- package/dist/builtins/monitor.workflow.js.map +1 -1
- package/dist/extension/executor.d.ts +7 -2
- package/dist/extension/executor.js +20 -14
- package/dist/extension/executor.js.map +1 -1
- package/dist/extension/index.js +56 -15
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/step-message.d.ts +24 -0
- package/dist/extension/step-message.js +106 -0
- package/dist/extension/step-message.js.map +1 -0
- package/dist/extension/widget.d.ts +4 -2
- package/dist/extension/widget.js +111 -17
- package/dist/extension/widget.js.map +1 -1
- package/dist/extension/workflow-tool.d.ts +9 -0
- package/dist/extension/workflow-tool.js +10 -0
- package/dist/extension/workflow-tool.js.map +1 -1
- package/dist/host/rpc-bridge.js +25 -11
- package/dist/host/rpc-bridge.js.map +1 -1
- package/dist/host/rpc-executor.d.ts +2 -2
- package/dist/host/rpc-executor.js +23 -12
- package/dist/host/rpc-executor.js.map +1 -1
- package/dist/viewer/cli.js +1 -1
- package/dist/viewer/cli.js.map +1 -1
- package/dist/viewer/render.js +14 -0
- package/dist/viewer/render.js.map +1 -1
- package/dist/viewer/tui.js +1 -1
- package/dist/viewer/tui.js.map +1 -1
- package/dist/workflows/engine.d.ts +6 -1
- package/dist/workflows/engine.js +88 -6
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/index.d.ts +4 -2
- package/dist/workflows/index.js +2 -0
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/progress.d.ts +34 -0
- package/dist/workflows/progress.js +268 -0
- package/dist/workflows/progress.js.map +1 -0
- package/dist/workflows/schema.js +21 -1
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/shell.d.ts +2 -2
- package/dist/workflows/shell.js +103 -25
- package/dist/workflows/shell.js.map +1 -1
- package/dist/workflows/store.d.ts +15 -2
- package/dist/workflows/store.js +44 -2
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +52 -1
- package/dist/workflows/updates.d.ts +15 -0
- package/dist/workflows/updates.js +188 -0
- package/dist/workflows/updates.js.map +1 -0
- package/docs/DESIGN_PHILOSOPHY.md +51 -0
- package/docs/MONITOR.md +282 -0
- package/docs/WORKFLOW_STEP_MESSAGES.md +141 -0
- package/docs/WORKFLOW_UPDATES.md +416 -0
- package/docs/development.md +7 -3
- package/docs/plans/2026-08-13-responsive-workflow-widget-plan.md +11 -3
- package/docs/plans/2026-08-16-workflow-updates-plan.md +494 -0
- package/docs/run-bundles.md +10 -2
- package/docs/workflows.md +57 -17
- package/package.json +1 -1
- package/src/builtins/catalog.ts +1 -1
- package/src/builtins/monitor.workflow.ts +217 -148
- package/src/extension/executor.ts +36 -14
- package/src/extension/index.ts +89 -23
- package/src/extension/step-message.ts +145 -0
- package/src/extension/widget.ts +158 -14
- package/src/extension/workflow-tool.ts +22 -0
- package/src/host/rpc-bridge.ts +37 -14
- package/src/host/rpc-executor.ts +35 -14
- package/src/viewer/cli.ts +1 -1
- package/src/viewer/render.ts +27 -0
- package/src/viewer/tui.ts +1 -1
- package/src/workflows/engine.ts +117 -4
- package/src/workflows/index.ts +32 -0
- package/src/workflows/progress.ts +326 -0
- package/src/workflows/schema.ts +23 -1
- package/src/workflows/shell.ts +109 -26
- package/src/workflows/store.ts +67 -2
- package/src/workflows/types.ts +78 -1
- package/src/workflows/updates.ts +208 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Add durable workflow updates and progress reporting
|
|
3
|
+
author: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
|
|
4
|
+
date: 2026-08-16
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Add durable workflow updates and progress reporting
|
|
8
|
+
|
|
9
|
+
This plan implements the contracts in [WORKFLOW_UPDATES.md](../WORKFLOW_UPDATES.md), [WORKFLOW_STEP_MESSAGES.md](../WORKFLOW_STEP_MESSAGES.md), and [MONITOR.md](../MONITOR.md). It follows the [design philosophy](../DESIGN_PHILOSOPHY.md): add one general update capability, keep the node set small, and build progress, presentation, and monitoring through composition.
|
|
10
|
+
|
|
11
|
+
## Outcome
|
|
12
|
+
|
|
13
|
+
Pi Workflows will let a running agent, function action, shell action, or claimed runner publish durable structured updates without completing a node. Progress will be one optional update type with shared estimation and presentation helpers.
|
|
14
|
+
|
|
15
|
+
The built-in monitor will report every accepted check, support optional progress tracks, show live timing in the widget, and deliver notifications without starting an assistant turn.
|
|
16
|
+
|
|
17
|
+
Interactive agent steps will keep their full model prompts while appearing as compact, expandable workflow cards in the conversation.
|
|
18
|
+
|
|
19
|
+
## Scope
|
|
20
|
+
|
|
21
|
+
### Pi Workflows engine
|
|
22
|
+
|
|
23
|
+
- Add public update types and the action context that publishes them.
|
|
24
|
+
- Add fenced update publication to the engine and run store.
|
|
25
|
+
- Append `update_published` trace events.
|
|
26
|
+
- Add the latest update projection to run state.
|
|
27
|
+
- Preserve update ordering and idempotency.
|
|
28
|
+
- Apply payload and key-count limits plus update rate limits.
|
|
29
|
+
- Expose update publication to claimed hosts and controllers.
|
|
30
|
+
|
|
31
|
+
### Node and tool APIs
|
|
32
|
+
|
|
33
|
+
- Add `publishUpdate()` to function-action context.
|
|
34
|
+
- Add the non-completing `workflow` tool action `update`.
|
|
35
|
+
- Add structured line parsing to shell actions.
|
|
36
|
+
- Keep compute nodes pure.
|
|
37
|
+
- Keep final node outputs as the only routing input.
|
|
38
|
+
- Keep the existing `status` action read-only and include current updates in its details.
|
|
39
|
+
|
|
40
|
+
### Progress support
|
|
41
|
+
|
|
42
|
+
- Add the `pi-workflows.progress.v1` validator and types.
|
|
43
|
+
- Add incremental reduction and conservative estimation helpers.
|
|
44
|
+
- Support independent tracks with stable keys.
|
|
45
|
+
- Support source ETA, measured ETA, confidence, stalls, resets, stale data, and unavailable estimates.
|
|
46
|
+
- Reserve `overall` for workflow-supplied aggregation.
|
|
47
|
+
- Add model-free formatters for notifications and displays.
|
|
48
|
+
|
|
49
|
+
### Presentation
|
|
50
|
+
|
|
51
|
+
- Extend the compact Pi widget with an optional bounded progress panel.
|
|
52
|
+
- Extend `piw` and the TypeScript viewer with update history and full progress details.
|
|
53
|
+
- Reuse the current widget ticker for elapsed time and countdowns.
|
|
54
|
+
- Keep observed counters fixed between updates.
|
|
55
|
+
- Deliver workflow notifications with `triggerTurn: false` while retaining them in later model context.
|
|
56
|
+
- Deliver interactive agent steps as `pi-workflows-agent-step` custom messages with `triggerTurn: true`.
|
|
57
|
+
- Show workflow, node, and status details in a compact card and the complete prompt when expanded.
|
|
58
|
+
- Use the same complete model prompt in interactive and RPC execution.
|
|
59
|
+
|
|
60
|
+
### Built-in monitor
|
|
61
|
+
|
|
62
|
+
- Replace quiet/report routes with `continue` and `stop`.
|
|
63
|
+
- Require a report after every accepted check.
|
|
64
|
+
- Remove `reportWhen`, report acknowledgement steps, and `presentationPrompt`.
|
|
65
|
+
- Add optional progress tracks to check output.
|
|
66
|
+
- Add estimate and publish stages, then schedule and report through existing nodes.
|
|
67
|
+
- Default to a 30-minute interval.
|
|
68
|
+
- Preserve the documented 1,000-check workflow safety ceiling.
|
|
69
|
+
- Keep explicit user stop as the fallback stop rule when no terminal condition is clear.
|
|
70
|
+
|
|
71
|
+
### Integration repositories
|
|
72
|
+
|
|
73
|
+
- Release the package from `osolmaz/pi-workflows`.
|
|
74
|
+
- Update the exact package pin and upstream record in `osolmaz/onurpi`.
|
|
75
|
+
- Update the source monitor skill in `osolmaz/tools`, then run its sync script.
|
|
76
|
+
|
|
77
|
+
## Non-goals
|
|
78
|
+
|
|
79
|
+
- No Pi core changes.
|
|
80
|
+
- No progress node type.
|
|
81
|
+
- No automatic aggregation of unrelated tracks.
|
|
82
|
+
- No arbitrary commands inside update data.
|
|
83
|
+
- No model-generated fallback ETA.
|
|
84
|
+
- No remote metrics service or global time-series database.
|
|
85
|
+
- No migration files, fallback formats, or dual writes for run bundles.
|
|
86
|
+
- No claim that a finite workflow is an indefinite controller.
|
|
87
|
+
- No controller-backed indefinite monitor in this release.
|
|
88
|
+
- No new workflow primitive or workflow-file option for step-message presentation.
|
|
89
|
+
- No Pi core change, private Pi API, or separate expansion state.
|
|
90
|
+
- No duplicate `sendUserMessage` fallback for new agent-step messages.
|
|
91
|
+
- No rewrite of existing Pi session entries.
|
|
92
|
+
|
|
93
|
+
## Persistent contract impact
|
|
94
|
+
|
|
95
|
+
### Run bundles
|
|
96
|
+
|
|
97
|
+
`trace.ndjson` gains `update_published` events. `state.json` gains the optional latest `updates` projection. The trace remains the source of truth.
|
|
98
|
+
|
|
99
|
+
Omission means that a run has never published an update. New runs write an empty array from their first projection. Existing bundles remain valid without migration or fallback code. The implementation keeps the current `pi-workflows.trace-event.v1` and `pi-workflows.run-state.v1` identifiers and does not add dual-write paths.
|
|
100
|
+
|
|
101
|
+
Checkpoint continuations begin with an empty update projection. Resume keeps updates because it continues the same run.
|
|
102
|
+
|
|
103
|
+
### Pi sessions
|
|
104
|
+
|
|
105
|
+
Workflow notifications remain `pi-workflows-notification` custom messages. They remain in session history and model context. Delivery sets `triggerTurn: false`, so arrival does not start a model turn.
|
|
106
|
+
|
|
107
|
+
New interactive agent-step instructions become `pi-workflows-agent-step` custom messages. Their complete prompt remains in session history and model context. Delivery sets `triggerTurn: true`, so each accepted delivery starts the required model turn. The structured message details use `pi-workflows.agent-step-message.v1`.
|
|
108
|
+
|
|
109
|
+
Existing user-message entries remain readable and are not rewritten. No private Pi entry type, Pi schema change, or separate persistent store is introduced.
|
|
110
|
+
|
|
111
|
+
### Controller storage
|
|
112
|
+
|
|
113
|
+
The controller database schema does not change for the first implementation. Controllers publish only through a claimed workflow run. Controller-native status remains in controller resources.
|
|
114
|
+
|
|
115
|
+
## Public API impact
|
|
116
|
+
|
|
117
|
+
The release adds:
|
|
118
|
+
|
|
119
|
+
- `WorkflowUpdateInput`
|
|
120
|
+
- `WorkflowUpdateRecord`
|
|
121
|
+
- `WorkflowUpdateReceipt`
|
|
122
|
+
- `WorkflowActionContext`
|
|
123
|
+
- `context.publishUpdate()`
|
|
124
|
+
- the `workflow` tool action `update`
|
|
125
|
+
- shell update parsing
|
|
126
|
+
- progress validation and estimation exports, including reduction and formatting
|
|
127
|
+
- optional agent-step presentation metadata passed to executors
|
|
128
|
+
- the versioned `WorkflowAgentStepMessageDetails` extension contract
|
|
129
|
+
|
|
130
|
+
The built-in monitor check output changes incompatibly. Existing `continue_quiet`, `continue_report`, `stop_quiet`, and `stop_report` outputs become invalid. The new values are `continue` and `stop`, and both require `report`.
|
|
131
|
+
|
|
132
|
+
The recommended release is `0.6.0`. The package is pre-1.0, previous capability releases use minor versions, and this release adds public APIs while replacing the built-in monitor contract.
|
|
133
|
+
|
|
134
|
+
## Implementation sequence
|
|
135
|
+
|
|
136
|
+
### Core update records
|
|
137
|
+
|
|
138
|
+
Files expected to change:
|
|
139
|
+
|
|
140
|
+
- `src/workflows/types.ts`
|
|
141
|
+
- `src/workflows/json.ts`
|
|
142
|
+
- `src/workflows/schema.ts`
|
|
143
|
+
- `src/workflows/store.ts`
|
|
144
|
+
- `src/workflows/engine.ts`
|
|
145
|
+
- `src/workflows/index.ts`
|
|
146
|
+
- `test/store.test.ts`
|
|
147
|
+
- `test/engine.test.ts`
|
|
148
|
+
- `test/engine-more.test.ts`
|
|
149
|
+
|
|
150
|
+
Work:
|
|
151
|
+
|
|
152
|
+
1. Add public update types and validators.
|
|
153
|
+
2. Add `updates` to new and replayed run state, and treat omission as no published updates.
|
|
154
|
+
3. Add a fenced store transition that writes `update_published` first and then replaces projections.
|
|
155
|
+
4. Fold the latest record per `(type, key)` into state, sorted by trace sequence.
|
|
156
|
+
5. Enforce payload and key limits with a token-bucket rate limit.
|
|
157
|
+
6. Add idempotent publication by source id.
|
|
158
|
+
7. Rebuild projections from trace and verify torn-tail repair.
|
|
159
|
+
8. Ensure terminal or expired attempts reject updates.
|
|
160
|
+
|
|
161
|
+
Verification:
|
|
162
|
+
|
|
163
|
+
- unit tests for valid writes and receipts
|
|
164
|
+
- ordering under concurrent publication attempts
|
|
165
|
+
- duplicate tool source id returns the first receipt
|
|
166
|
+
- claim loss blocks writes
|
|
167
|
+
- resume reconstructs the same projection
|
|
168
|
+
- continuation starts empty
|
|
169
|
+
- state and trace agree after repair
|
|
170
|
+
|
|
171
|
+
### Publishers
|
|
172
|
+
|
|
173
|
+
Files expected to change:
|
|
174
|
+
|
|
175
|
+
- `src/workflows/types.ts`
|
|
176
|
+
- `src/workflows/engine.ts`
|
|
177
|
+
- `src/workflows/shell.ts`
|
|
178
|
+
- `src/extension/workflow-tool.ts`
|
|
179
|
+
- `src/extension/index.ts`
|
|
180
|
+
- `src/host/rpc-executor.ts`
|
|
181
|
+
- `test/extension.test.ts`
|
|
182
|
+
- `test/workflow-args.test.ts`
|
|
183
|
+
- `test/e2e/workflow.e2e.test.ts`
|
|
184
|
+
|
|
185
|
+
Work:
|
|
186
|
+
|
|
187
|
+
1. Give function actions `WorkflowActionContext`.
|
|
188
|
+
2. Connect `publishUpdate()` to the current run, node, attempt, claim fence, and cancellation signal.
|
|
189
|
+
3. Add the `workflow` tool `update` variant.
|
|
190
|
+
4. Use the Pi tool call id as the agent-update source id.
|
|
191
|
+
5. Keep the step open after a successful update.
|
|
192
|
+
6. Reject mismatched and expired step contracts.
|
|
193
|
+
7. Add shell stream selection, line framing, parser execution, and publication backpressure.
|
|
194
|
+
8. Terminate shell actions on parser or publication failure.
|
|
195
|
+
9. Expose the same claimed-run operation to the standalone host and controller scheduler boundary.
|
|
196
|
+
10. Include the current update projection in `status` details.
|
|
197
|
+
|
|
198
|
+
Verification:
|
|
199
|
+
|
|
200
|
+
- an agent publishes several updates and submits once
|
|
201
|
+
- function action publication is durable before the promise resolves
|
|
202
|
+
- shell stdout and stderr parsing works with partial chunks and a final unterminated line
|
|
203
|
+
- malformed or oversized lines and invalid UTF-8 fail safely
|
|
204
|
+
- update data cannot change shell execution
|
|
205
|
+
- a tool update does not trigger an assistant turn
|
|
206
|
+
|
|
207
|
+
### Progress profile
|
|
208
|
+
|
|
209
|
+
Expected new or changed files:
|
|
210
|
+
|
|
211
|
+
- `src/workflows/progress.ts`
|
|
212
|
+
- `src/workflows/index.ts`
|
|
213
|
+
- `test/progress.test.ts`
|
|
214
|
+
|
|
215
|
+
Work:
|
|
216
|
+
|
|
217
|
+
1. Add strict `pi-workflows.progress.v1` validation.
|
|
218
|
+
2. Add a reducer keyed by run and track key.
|
|
219
|
+
3. Split estimation epochs after phase or unit changes, total or counter changes, and terminal-state resets.
|
|
220
|
+
4. Keep the latest eight usable intervals.
|
|
221
|
+
5. Calculate median rate, percentile range, confidence, remaining work, sample age, and stall duration.
|
|
222
|
+
6. Prefer fresh source ETA and label its basis.
|
|
223
|
+
7. Pause measured ETA for waiting or blocked tracks.
|
|
224
|
+
8. Return a reason whenever ETA is unavailable.
|
|
225
|
+
9. Add bounded plain-text formatting.
|
|
226
|
+
|
|
227
|
+
Verification fixtures must cover:
|
|
228
|
+
|
|
229
|
+
- no counts
|
|
230
|
+
- completed without total
|
|
231
|
+
- two-sample low-confidence ETA
|
|
232
|
+
- stable high-confidence samples
|
|
233
|
+
- bursty and zero-rate intervals
|
|
234
|
+
- counter rollback
|
|
235
|
+
- changed phase, unit, or total
|
|
236
|
+
- source ETA
|
|
237
|
+
- stale source facts
|
|
238
|
+
- waiting, blocked, failed, cancelled, and completed tracks
|
|
239
|
+
- several unrelated tracks
|
|
240
|
+
- explicit `overall`
|
|
241
|
+
|
|
242
|
+
### Update presentation
|
|
243
|
+
|
|
244
|
+
Files expected to change:
|
|
245
|
+
|
|
246
|
+
- `src/extension/widget.ts`
|
|
247
|
+
- `src/extension/index.ts`
|
|
248
|
+
- `src/viewer/render.ts`
|
|
249
|
+
- `src/viewer/tui.ts`
|
|
250
|
+
- `src/viewer/watch.ts`
|
|
251
|
+
- `tui/src/`
|
|
252
|
+
- `test/widget.test.ts`
|
|
253
|
+
- viewer tests and Rust fixtures
|
|
254
|
+
|
|
255
|
+
Work:
|
|
256
|
+
|
|
257
|
+
1. Add a pure progress view model under the workflow or render layer without importing Pi.
|
|
258
|
+
2. Keep the graph visible and fit the optional panel inside the 10-line Pi limit.
|
|
259
|
+
3. Prioritize `overall`, failures, blocked tracks, and active tracks.
|
|
260
|
+
4. Preserve manual scrolling and active-node following.
|
|
261
|
+
5. Recalculate elapsed values from `now` without changing state.
|
|
262
|
+
6. Show expired ETA as awaiting a new sample.
|
|
263
|
+
7. Add update and estimate inspection to both viewers.
|
|
264
|
+
8. Keep TypeScript and Rust rendering behavior in parity.
|
|
265
|
+
9. Make notifications explicitly non-triggering while retaining custom messages in context.
|
|
266
|
+
|
|
267
|
+
Verification:
|
|
268
|
+
|
|
269
|
+
- zero progress leaves current rendering unchanged
|
|
270
|
+
- one and many tracks fit at narrow widths
|
|
271
|
+
- timers advance without persisted writes
|
|
272
|
+
- completed counters remain fixed
|
|
273
|
+
- renderer output contains no assistant-trigger request
|
|
274
|
+
- replay at every trace position shows the correct update projection
|
|
275
|
+
|
|
276
|
+
### Agent-step message presentation
|
|
277
|
+
|
|
278
|
+
Files expected to change:
|
|
279
|
+
|
|
280
|
+
- `src/workflows/types.ts`
|
|
281
|
+
- `src/workflows/engine.ts`
|
|
282
|
+
- `src/extension/executor.ts`
|
|
283
|
+
- `src/extension/index.ts`
|
|
284
|
+
- `src/extension/` message-renderer module
|
|
285
|
+
- `src/host/rpc-executor.ts`
|
|
286
|
+
- `test/executor.test.ts`
|
|
287
|
+
- `test/extension.test.ts`
|
|
288
|
+
- `test/e2e/workflow.e2e.test.ts`
|
|
289
|
+
|
|
290
|
+
Work:
|
|
291
|
+
|
|
292
|
+
1. Keep one pure formatter for the complete model prompt.
|
|
293
|
+
2. Add optional run-title and status-detail presentation data to `AgentStepRequest` without importing Pi into the workflow layer.
|
|
294
|
+
3. Pass the prompt, contract, presentation data, delivery kind, and streaming state through `PromptDelivery`.
|
|
295
|
+
4. Replace interactive `sendUserMessage` delivery with a `pi-workflows-agent-step` custom message.
|
|
296
|
+
5. Set `triggerTurn: true` and select `steer` or `followUp` from the current streaming state.
|
|
297
|
+
6. Register a renderer that reads versioned message details instead of parsing prompt text.
|
|
298
|
+
7. Show a bounded workflow and node summary when collapsed.
|
|
299
|
+
8. Show exact ids, expected output, and the complete prompt when expanded.
|
|
300
|
+
9. Send reminders and repeated resume instructions through the same message type with their delivery kind.
|
|
301
|
+
10. Keep RPC delivery on the same complete prompt and preserve run-bundle prompt recording.
|
|
302
|
+
11. Remove the interactive `sendUserMessage` path without adding a duplicate fallback.
|
|
303
|
+
|
|
304
|
+
Verification:
|
|
305
|
+
|
|
306
|
+
- interactive and RPC model prompts match
|
|
307
|
+
- one step delivery starts one model turn
|
|
308
|
+
- collapsed and expanded rendering work at narrow widths
|
|
309
|
+
- reminders and resumed deliveries preserve the active attempt
|
|
310
|
+
- timed-out, cancelled, and stale attempts remain invalid
|
|
311
|
+
- replay restores the custom message and structured details
|
|
312
|
+
- notification delivery still does not start a model turn
|
|
313
|
+
- no duplicate user message appears
|
|
314
|
+
|
|
315
|
+
### Built-in monitor contract
|
|
316
|
+
|
|
317
|
+
Files expected to change:
|
|
318
|
+
|
|
319
|
+
- `src/builtins/monitor.workflow.ts`
|
|
320
|
+
- `src/builtins/catalog.ts`
|
|
321
|
+
- `test/monitor-workflow.test.ts`
|
|
322
|
+
- `test/e2e/workflow.e2e.test.ts`
|
|
323
|
+
|
|
324
|
+
Work:
|
|
325
|
+
|
|
326
|
+
1. Make `everyMinutes` optional with default 30.
|
|
327
|
+
2. Remove `reportWhen`.
|
|
328
|
+
3. Replace the route enum and validation.
|
|
329
|
+
4. Require reports for `continue` and `stop`.
|
|
330
|
+
5. Add optional strict progress tracks.
|
|
331
|
+
6. Add estimate and publish-progress stages, then decide, schedule, and report stages.
|
|
332
|
+
7. Publish `monitor.schedule` before each sleep.
|
|
333
|
+
8. Notify once for every accepted check.
|
|
334
|
+
9. Report before stopping on route or check limit.
|
|
335
|
+
10. Remove report acknowledgement and presentation behavior.
|
|
336
|
+
11. Update the built-in catalog revision.
|
|
337
|
+
12. Keep the 1,000-check safety ceiling and disclose it in prompts and docs.
|
|
338
|
+
|
|
339
|
+
Verification:
|
|
340
|
+
|
|
341
|
+
- first check is immediate
|
|
342
|
+
- normal interval starts after the report is queued
|
|
343
|
+
- every accepted check queues exactly one notification
|
|
344
|
+
- quiet routes and missing reports fail validation
|
|
345
|
+
- stop report arrives before completion
|
|
346
|
+
- safety-limit report arrives before completion
|
|
347
|
+
- cancellation does not fabricate a report
|
|
348
|
+
- progress is optional
|
|
349
|
+
- several tracks publish independently
|
|
350
|
+
- notification arrival does not start an assistant turn
|
|
351
|
+
|
|
352
|
+
### Canonical documentation
|
|
353
|
+
|
|
354
|
+
Update:
|
|
355
|
+
|
|
356
|
+
- `README.md`
|
|
357
|
+
- `docs/workflows.md`
|
|
358
|
+
- `docs/run-bundles.md`
|
|
359
|
+
- `docs/development.md`
|
|
360
|
+
- `docs/WORKFLOW_UPDATES.md`
|
|
361
|
+
- `docs/WORKFLOW_STEP_MESSAGES.md`
|
|
362
|
+
- `docs/MONITOR.md`
|
|
363
|
+
- examples that teach agent, action, shell, notify, or monitor behavior
|
|
364
|
+
|
|
365
|
+
The shipped docs must describe actual field names and limits along with lifecycle and error behavior. Remove accepted-design warnings only after implementation matches the specifications.
|
|
366
|
+
|
|
367
|
+
### Release and integration
|
|
368
|
+
|
|
369
|
+
1. Confirm no old active built-in monitor depends on the previous catalog revision.
|
|
370
|
+
2. Run every required repository check.
|
|
371
|
+
3. Commit coherent implementation slices with Conventional Commits.
|
|
372
|
+
4. Prepare release `0.6.0` through the repository's GitHub Release publication flow.
|
|
373
|
+
5. Verify npm package contents and the published exact version.
|
|
374
|
+
6. Pull `osolmaz/onurpi` with `git pull --ff-only`.
|
|
375
|
+
7. Update `packages/workflows/package.json`, lock data, tests, and `UPSTREAM.md` to the immutable release.
|
|
376
|
+
8. Run the OnurPi wrapper checks and a real Pi smoke test after `/reload`.
|
|
377
|
+
9. Pull `osolmaz/tools`, update `agents/skills/monitor/SKILL.md`, and run `agents/sync-skills.py monitor`.
|
|
378
|
+
10. Verify the installed Pi skill matches the source copy.
|
|
379
|
+
11. Commit and push each owned repository under its own rules.
|
|
380
|
+
|
|
381
|
+
## Test matrix
|
|
382
|
+
|
|
383
|
+
### Unit
|
|
384
|
+
|
|
385
|
+
- schemas and unknown fields
|
|
386
|
+
- update projection and replay
|
|
387
|
+
- claim fencing and idempotency
|
|
388
|
+
- rate limits and size limits
|
|
389
|
+
- progress epochs and estimates
|
|
390
|
+
- monitor validation and routing
|
|
391
|
+
- widget and viewer formatting
|
|
392
|
+
|
|
393
|
+
### Integration
|
|
394
|
+
|
|
395
|
+
- action to trace to state to widget
|
|
396
|
+
- agent tool update followed by submit
|
|
397
|
+
- shell stream to update publication
|
|
398
|
+
- host park and resume
|
|
399
|
+
- notification outbox delivery to the origin session
|
|
400
|
+
- `status` with current updates
|
|
401
|
+
|
|
402
|
+
### End to end
|
|
403
|
+
|
|
404
|
+
Use the real installed Pi runtime without a real model or destructive target:
|
|
405
|
+
|
|
406
|
+
1. Start a fixture workflow with a scripted action that publishes progress.
|
|
407
|
+
2. Observe progress in the in-Pi widget and `piw`.
|
|
408
|
+
3. Verify the run trace and state projection.
|
|
409
|
+
4. Start a short monitor fixture.
|
|
410
|
+
5. Verify one custom notification per check.
|
|
411
|
+
6. Verify no assistant turn starts from notification delivery.
|
|
412
|
+
7. Start an interactive agent step and verify one compact custom message and one model turn.
|
|
413
|
+
8. Expand the message and verify the full prompt and exact contract ids.
|
|
414
|
+
9. Compare the provider-facing interactive prompt with the RPC prompt.
|
|
415
|
+
10. Cancel during sleep and verify terminal state.
|
|
416
|
+
11. Restart Pi and verify durable display and replay.
|
|
417
|
+
|
|
418
|
+
## Required commands
|
|
419
|
+
|
|
420
|
+
Run in `osolmaz/pi-workflows` before release:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
npm run check
|
|
424
|
+
npm run test:e2e
|
|
425
|
+
npx slophammer-ts@latest dry .
|
|
426
|
+
npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
|
|
427
|
+
git diff --check
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Run documentation checks:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
npx -y @simpledoc/simpledoc check
|
|
434
|
+
npx oxfmt --check README.md docs
|
|
435
|
+
python3 ~/.pi/agent/skills/kill-ai-smell/check.py docs/WORKFLOW_UPDATES.md
|
|
436
|
+
python3 ~/.pi/agent/skills/kill-ai-smell/check.py docs/WORKFLOW_STEP_MESSAGES.md
|
|
437
|
+
python3 ~/.pi/agent/skills/kill-ai-smell/check.py docs/MONITOR.md
|
|
438
|
+
python3 ~/.pi/agent/skills/kill-ai-smell/check.py docs/plans/2026-08-16-workflow-updates-plan.md
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Run package and real-Pi checks again after updating OnurPi. Run the tools skill sync in dry-run mode before applying it.
|
|
442
|
+
|
|
443
|
+
## Acceptance criteria
|
|
444
|
+
|
|
445
|
+
- The public update API works from agent and action nodes.
|
|
446
|
+
- Shell updates use only workflow-author code and fixed execution settings.
|
|
447
|
+
- Every accepted update is ordered and fenced, with durable bounded storage and replay.
|
|
448
|
+
- Final outputs remain the only routing input.
|
|
449
|
+
- Workflows without updates preserve their current behavior and display.
|
|
450
|
+
- Progress is optional and supports several stable tracks.
|
|
451
|
+
- ETA is source-based or measured from facts and never invented by a model.
|
|
452
|
+
- Widget clocks update without a model call or per-tick write.
|
|
453
|
+
- Notifications remain in context and never start an assistant turn.
|
|
454
|
+
- Agent-step prompts remain complete for the model and appear as compact, expandable workflow cards.
|
|
455
|
+
- Interactive and RPC execution use the same model prompt.
|
|
456
|
+
- The built-in monitor reports every accepted check and has no quiet path.
|
|
457
|
+
- The monitor discloses its finite safety ceiling.
|
|
458
|
+
- TypeScript and Rust viewers agree on replayed progress.
|
|
459
|
+
- All required checks pass in Pi Workflows and OnurPi.
|
|
460
|
+
- The published package, OnurPi pin, monitor skill source, and installed Pi copy agree.
|
|
461
|
+
|
|
462
|
+
## Risks and controls
|
|
463
|
+
|
|
464
|
+
### Trace growth
|
|
465
|
+
|
|
466
|
+
High-rate updates can grow bundles quickly. Payload and rate limits apply alongside burst and current-key limits. Shell parsing applies backpressure.
|
|
467
|
+
|
|
468
|
+
### Misleading ETA
|
|
469
|
+
|
|
470
|
+
The estimator uses observed facts, short rolling history, explicit confidence, and unavailable reasons. It never advances observed counters between samples.
|
|
471
|
+
|
|
472
|
+
### Hidden behavior
|
|
473
|
+
|
|
474
|
+
Updates cannot route, execute, or notify. The graph retains control of completion, side effects, and user messages.
|
|
475
|
+
|
|
476
|
+
### Duplicate notifications
|
|
477
|
+
|
|
478
|
+
Update idempotency and the existing notification occurrence index remain separate. Each monitor check reaches one notify node once.
|
|
479
|
+
|
|
480
|
+
### Prompt and display drift
|
|
481
|
+
|
|
482
|
+
The renderer reads structured details, while one formatter produces the complete model prompt for interactive and RPC execution. Tests compare provider-facing content and verify that expansion shows the recorded prompt. The renderer never rebuilds instructions from display fields.
|
|
483
|
+
|
|
484
|
+
### Upgrade interruption
|
|
485
|
+
|
|
486
|
+
The built-in monitor revision change can block resume of an old active monitor even though old bundles remain valid. Inventory active monitors before release and do not install the new built-in over work that still needs the old revision.
|
|
487
|
+
|
|
488
|
+
### Rollback
|
|
489
|
+
|
|
490
|
+
Before any run publishes an update, rollback is an exact dependency pin to `0.5.3`. After update-bearing bundles exist, preserve them and keep the new reader available. Do not delete or rewrite bundles to force an old runtime to read fields it does not support.
|
|
491
|
+
|
|
492
|
+
## Follow-up boundary
|
|
493
|
+
|
|
494
|
+
A truly indefinite monitor belongs in the controller runtime. This plan keeps the finite workflow safety ceiling and does not hide it behind a huge number or automatic restart. A later controller resource may use the same update and progress contracts alongside the notification and viewer contracts.
|
package/docs/run-bundles.md
CHANGED
|
@@ -210,7 +210,8 @@ The full run projection (`WorkflowRunState` in
|
|
|
210
210
|
"input": { "task": "fix the flaky test" },
|
|
211
211
|
"outputs": {},
|
|
212
212
|
"results": {},
|
|
213
|
-
"steps": []
|
|
213
|
+
"steps": [],
|
|
214
|
+
"updates": []
|
|
214
215
|
}
|
|
215
216
|
```
|
|
216
217
|
|
|
@@ -235,6 +236,10 @@ The full run projection (`WorkflowRunState` in
|
|
|
235
236
|
- Per-node data lives in `outputs` (the accepted output of each finished node,
|
|
236
237
|
latest attempt wins on loops) and `results` (the full result record of the
|
|
237
238
|
latest attempt, including outcome and timing).
|
|
239
|
+
- `updates` contains the latest durable record for each `(type, key)` pair,
|
|
240
|
+
sorted by trace sequence. New runs start with an empty array. Older bundles
|
|
241
|
+
can omit it. Resume keeps it; checkpoint continuation starts a new empty
|
|
242
|
+
projection. The trace keeps the complete update history.
|
|
238
243
|
- `steps` is the ordered history, one record per node attempt:
|
|
239
244
|
|
|
240
245
|
```json
|
|
@@ -289,7 +294,10 @@ One event per line, monotonically sequenced per run, schema
|
|
|
289
294
|
}
|
|
290
295
|
```
|
|
291
296
|
|
|
292
|
-
`scope` is one of `run`, `node`, `agent`, `action`, or `session`.
|
|
297
|
+
`scope` is one of `run`, `node`, `agent`, `action`, or `session`.
|
|
298
|
+
A node-scoped `update_published` event carries the runtime update ID, type, key, and data;
|
|
299
|
+
its event sequence and timestamp are the update sequence and timestamp. See
|
|
300
|
+
[WORKFLOW_UPDATES.md](WORKFLOW_UPDATES.md) for the full contract. `nodeId` and
|
|
293
301
|
`attemptId` are present on node-scoped and agent-scoped events. Consumers must
|
|
294
302
|
ignore unknown event types and unknown payload fields so new ones can be added
|
|
295
303
|
within the same schema version.
|
package/docs/workflows.md
CHANGED
|
@@ -90,6 +90,9 @@ Long-running compute, action, and checkpoint callbacks should observe
|
|
|
90
90
|
steps). When the node times out or the run is cancelled, the engine stops
|
|
91
91
|
waiting immediately, but only cooperative callbacks stop doing work.
|
|
92
92
|
|
|
93
|
+
Function actions receive `WorkflowActionContext`, which adds
|
|
94
|
+
`publishUpdate(update)`. Other callbacks keep the read-only node context.
|
|
95
|
+
|
|
93
96
|
## Durable runs, parking, and resume
|
|
94
97
|
|
|
95
98
|
Every interactive `/workflow` run is tracked in the project run queue (see
|
|
@@ -218,6 +221,32 @@ commands cannot exhaust memory. Both action forms record a receipt (command,
|
|
|
218
221
|
exit code, duration) in the step record for auditability, including when the
|
|
219
222
|
command fails.
|
|
220
223
|
|
|
224
|
+
A function action can publish a durable update without completing the node:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
action({
|
|
228
|
+
run: async ({ publishUpdate }) => {
|
|
229
|
+
await publishUpdate({
|
|
230
|
+
type: "progress",
|
|
231
|
+
key: "overall",
|
|
232
|
+
data: {
|
|
233
|
+
schema: "pi-workflows.progress.v1",
|
|
234
|
+
status: "running",
|
|
235
|
+
completed: 40,
|
|
236
|
+
total: 100,
|
|
237
|
+
unit: "rows",
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
A shell action can parse complete lines from stdout or stderr and return one
|
|
245
|
+
or more updates through `updates.parseLine`. Parsing applies backpressure and
|
|
246
|
+
keeps normal output capture. Lines and update data are each limited to 64 KiB.
|
|
247
|
+
See [WORKFLOW_UPDATES.md](WORKFLOW_UPDATES.md) for the envelope, progress
|
|
248
|
+
schema, limits, estimation, and error rules.
|
|
249
|
+
|
|
221
250
|
### checkpoint
|
|
222
251
|
|
|
223
252
|
Ends the run in a `waiting` state for human review. The checkpoint bundle is
|
|
@@ -294,13 +323,15 @@ The model sees one `workflow` tool. Its `action` field supports:
|
|
|
294
323
|
- `status` for the active run or a supplied run ID.
|
|
295
324
|
- `pause`, `resume`, and `cancel` for the active run.
|
|
296
325
|
- `answer` with checkpoint input and an optional run ID.
|
|
326
|
+
- `update` for a non-completing update from the current agent attempt.
|
|
297
327
|
- `submit` for the current workflow step contract.
|
|
298
328
|
|
|
299
329
|
A model-started run is queued until the model's current turn settles. The first
|
|
300
330
|
workflow prompt then starts a new turn. This keeps the requesting turn outside
|
|
301
331
|
the workflow's first attempt and prevents an early missing-submission reminder.
|
|
302
332
|
The normal extension offers all actions. The headless RPC bridge offers only
|
|
303
|
-
`submit`, so a workflow child cannot recursively control other
|
|
333
|
+
`update` and `submit`, so a workflow child cannot recursively control other
|
|
334
|
+
runs.
|
|
304
335
|
|
|
305
336
|
### Built-in monitor
|
|
306
337
|
|
|
@@ -310,24 +341,23 @@ one looping workflow run. Its input is:
|
|
|
310
341
|
```json
|
|
311
342
|
{
|
|
312
343
|
"task": "Check pull request 123",
|
|
313
|
-
"
|
|
314
|
-
"reportWhen": "Checks fail or the state changes materially",
|
|
315
|
-
"stopWhen": "The pull request is merged or closed",
|
|
316
|
-
"maxChecks": 1000,
|
|
317
|
-
"checkTimeoutMinutes": 60
|
|
344
|
+
"stopWhen": "The pull request is merged or closed"
|
|
318
345
|
}
|
|
319
346
|
```
|
|
320
347
|
|
|
321
|
-
The first check runs immediately.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
348
|
+
The first check runs immediately. `everyMinutes` defaults to 30. Each accepted
|
|
349
|
+
check must provide one concise report and choose `continue` or `stop`. The
|
|
350
|
+
runtime queues that report as a workflow notification with `triggerTurn:
|
|
351
|
+
false`, so it does not cause an assistant reply. A check can also provide
|
|
352
|
+
independent progress tracks. Pi Workflows validates the counts and calculates
|
|
353
|
+
rates, confidence, and ETA without a model.
|
|
325
354
|
|
|
326
|
-
Intervals must be whole minutes from 1 through 1,440. `
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
355
|
+
Intervals must be whole minutes from 1 through 1,440. When `stopWhen` is
|
|
356
|
+
omitted, the monitor stops only after an explicit user request. `maxChecks`
|
|
357
|
+
defaults to the disclosed safety ceiling of 1,000 and cannot exceed it. Callers
|
|
358
|
+
omit `maxChecks` unless the user requests a fixed count. `checkTimeoutMinutes`
|
|
359
|
+
is from 5 through 1,440 and defaults to the larger of 60 and `everyMinutes`.
|
|
360
|
+
See [MONITOR.md](MONITOR.md) for the check and progress schemas.
|
|
331
361
|
|
|
332
362
|
The interval uses the existing shell action to launch the current Node
|
|
333
363
|
executable with a timer. This works on every platform supported by Pi. The node
|
|
@@ -360,8 +390,18 @@ results. Submissions are rejected (with a reason the model sees) when no step
|
|
|
360
390
|
is pending, the step id is wrong, the attempt id belongs to an earlier attempt
|
|
361
391
|
of the same node (loops revisit node ids, so each attempt gets a fresh id), or
|
|
362
392
|
`validate` throws.
|
|
363
|
-
Acceptance resolves the step and the engine advances
|
|
364
|
-
arrives as a
|
|
393
|
+
Acceptance resolves the step and the engine advances. In an interactive Pi
|
|
394
|
+
session, each agent prompt arrives as a `pi-workflows-agent-step` custom message
|
|
395
|
+
with `triggerTurn: true`. The model receives the complete prompt, while the
|
|
396
|
+
conversation shows a compact workflow and node card. Expanding tool output with
|
|
397
|
+
Ctrl+O shows the exact contract and full prompt. Reminders and resumed prompts
|
|
398
|
+
use the same card and keep the active attempt id.
|
|
399
|
+
|
|
400
|
+
Headless RPC execution receives the same complete prompt without TUI metadata.
|
|
401
|
+
Workflow notifications use a separate message type with `triggerTurn: false`,
|
|
402
|
+
so a notification does not start an assistant response. See
|
|
403
|
+
[WORKFLOW_STEP_MESSAGES.md](WORKFLOW_STEP_MESSAGES.md) for the message contract
|
|
404
|
+
and renderer rules.
|
|
365
405
|
|
|
366
406
|
## Result presentation
|
|
367
407
|
|
package/package.json
CHANGED
package/src/builtins/catalog.ts
CHANGED