@osolmaz/pi-workflows 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -2
- package/dist/channels/adapter-entry.d.ts +3 -0
- package/dist/channels/adapter-entry.js +203 -0
- package/dist/channels/adapter-entry.js.map +1 -0
- package/dist/channels/config.d.ts +43 -0
- package/dist/channels/config.js +234 -0
- package/dist/channels/config.js.map +1 -0
- package/dist/channels/protocol.d.ts +94 -0
- package/dist/channels/protocol.js +219 -0
- package/dist/channels/protocol.js.map +1 -0
- package/dist/channels/telegram.d.ts +46 -0
- package/dist/channels/telegram.js +285 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/client/client.d.ts +1 -0
- package/dist/client/client.js +5 -1
- package/dist/client/client.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/protocol.d.ts +1 -1
- package/dist/client/protocol.js +11 -5
- package/dist/client/protocol.js.map +1 -1
- package/dist/client/view.d.ts +48 -16
- package/dist/client/view.js +1 -0
- package/dist/client/view.js.map +1 -1
- package/dist/controllers/index.d.ts +1 -1
- package/dist/controllers/index.js.map +1 -1
- package/dist/controllers/sqlite.d.ts +20 -165
- package/dist/controllers/sqlite.js +178 -436
- package/dist/controllers/sqlite.js.map +1 -1
- package/dist/extension/index.d.ts +23 -2
- package/dist/extension/index.js +637 -534
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/recorder.d.ts +95 -0
- package/dist/extension/recorder.js +530 -0
- package/dist/extension/recorder.js.map +1 -0
- package/dist/extension/remote-recorder-store.d.ts +25 -0
- package/dist/extension/remote-recorder-store.js +81 -0
- package/dist/extension/remote-recorder-store.js.map +1 -0
- package/dist/extension/session-events.d.ts +134 -0
- package/dist/extension/session-events.js +60 -0
- package/dist/extension/session-events.js.map +1 -0
- package/dist/extension/session-view.d.ts +2 -0
- package/dist/extension/session-view.js +60 -2
- package/dist/extension/session-view.js.map +1 -1
- package/dist/extension/step-message.d.ts +6 -4
- package/dist/extension/step-message.js +12 -6
- package/dist/extension/step-message.js.map +1 -1
- package/dist/extension/widget.d.ts +2 -2
- package/dist/extension/widget.js +28 -18
- package/dist/extension/widget.js.map +1 -1
- package/dist/extension/workflow-message-coordinator.d.ts +28 -0
- package/dist/extension/workflow-message-coordinator.js +346 -0
- package/dist/extension/workflow-message-coordinator.js.map +1 -0
- package/dist/host/channel-effects.d.ts +72 -0
- package/dist/host/channel-effects.js +271 -0
- package/dist/host/channel-effects.js.map +1 -0
- package/dist/host/channel-supervisor.d.ts +21 -0
- package/dist/host/channel-supervisor.js +54 -0
- package/dist/host/channel-supervisor.js.map +1 -0
- package/dist/host/runner.d.ts +50 -8
- package/dist/host/runner.js +1632 -341
- package/dist/host/runner.js.map +1 -1
- package/dist/host/state.d.ts +19 -16
- package/dist/host/state.js +251 -63
- package/dist/host/state.js.map +1 -1
- package/dist/host/view.d.ts +19 -9
- package/dist/host/view.js +227 -119
- package/dist/host/view.js.map +1 -1
- package/dist/host/worker-entry.d.ts +4 -1
- package/dist/host/worker-entry.js +23 -24
- package/dist/host/worker-entry.js.map +1 -1
- package/dist/host/worker-protocol.d.ts +15 -0
- package/dist/host/worker-protocol.js.map +1 -1
- package/dist/state/prune.js +3 -25
- package/dist/state/prune.js.map +1 -1
- package/dist/state/schema.js +76 -97
- package/dist/state/schema.js.map +1 -1
- package/dist/state/workflow-messages.d.ts +98 -0
- package/dist/state/workflow-messages.js +366 -0
- package/dist/state/workflow-messages.js.map +1 -0
- package/dist/viewer/render.js +1 -1
- package/dist/viewer/render.js.map +1 -1
- package/dist/viewer/tui.d.ts +1 -1
- package/dist/viewer/tui.js +65 -8
- package/dist/viewer/tui.js.map +1 -1
- package/dist/workflows/composition.js +0 -4
- package/dist/workflows/composition.js.map +1 -1
- package/dist/workflows/definition.js +0 -8
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/engine.js +4 -5
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +2 -0
- package/dist/workflows/human-decision.js +8 -2
- package/dist/workflows/human-decision.js.map +1 -1
- package/dist/workflows/index.d.ts +1 -1
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/settings.d.ts +1 -8
- package/dist/workflows/settings.js.map +1 -1
- package/dist/workflows/store.d.ts +20 -19
- package/dist/workflows/store.js +163 -354
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/tool-input.d.ts +21 -0
- package/dist/workflows/tool-input.js +23 -1
- package/dist/workflows/tool-input.js.map +1 -1
- package/dist/workflows/types.d.ts +6 -8
- package/dist/workflows/workflow-message-content.d.ts +38 -0
- package/dist/workflows/workflow-message-content.js +157 -0
- package/dist/workflows/workflow-message-content.js.map +1 -0
- package/docs/2026-08-18-herdr-piw-plan.md +2 -1
- package/docs/2026-08-20-durable-workflow-launch-plan.md +1 -1
- package/docs/2026-08-25-workflow-follow-ups.md +26 -50
- package/docs/2026-08-30-out-of-process-workflow-host-plan.md +3 -3
- package/docs/2026-09-01-restore-session-delivery-controls-plan.md +4 -0
- package/docs/2026-09-01-unified-workflow-client-plan.md +5 -1
- package/docs/2026-09-02-installed-live-e2e-plan.md +15 -1
- package/docs/2026-09-02-unify-workflow-messages-plan.md +562 -0
- package/docs/2026-09-04-workflow-run-state-plan.md +363 -0
- package/docs/DEFERRED_TURNS.md +66 -294
- package/docs/HUMAN_DECISIONS.md +29 -30
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +4 -11
- package/docs/SQLITE_STATE.md +25 -17
- package/docs/WORKFLOW_HOST.md +105 -31
- package/docs/WORKFLOW_STEP_MESSAGES.md +166 -75
- package/docs/live-replay-protocol.md +8 -4
- package/docs/tui-viewer.md +3 -1
- package/docs/workflows.md +44 -28
- package/herdr-plugin.toml +1 -1
- package/package.json +1 -1
- package/plugins/herdr/viewer.mjs +14 -5
- package/src/channels/adapter-entry.ts +220 -0
- package/src/channels/config.ts +296 -0
- package/src/channels/protocol.ts +333 -0
- package/src/channels/telegram.ts +335 -0
- package/src/client/client.ts +6 -2
- package/src/client/index.ts +2 -1
- package/src/client/protocol.ts +11 -5
- package/src/client/view.ts +51 -18
- package/src/controllers/index.ts +0 -1
- package/src/controllers/sqlite.ts +247 -845
- package/src/extension/index.ts +712 -647
- package/src/extension/recorder.ts +687 -0
- package/src/extension/remote-recorder-store.ts +126 -0
- package/src/extension/session-events.ts +119 -0
- package/src/extension/session-view.ts +86 -3
- package/src/extension/step-message.ts +19 -9
- package/src/extension/widget.ts +37 -17
- package/src/extension/workflow-message-coordinator.ts +398 -0
- package/src/host/channel-effects.ts +465 -0
- package/src/host/channel-supervisor.ts +73 -0
- package/src/host/runner.ts +2163 -525
- package/src/host/state.ts +333 -94
- package/src/host/view.ts +254 -122
- package/src/host/worker-entry.ts +38 -30
- package/src/host/worker-protocol.ts +11 -0
- package/src/state/prune.ts +3 -31
- package/src/state/schema.ts +76 -97
- package/src/state/workflow-messages.ts +599 -0
- package/src/viewer/render.ts +1 -5
- package/src/viewer/tui.ts +71 -6
- package/src/workflows/composition.ts +0 -5
- package/src/workflows/definition.ts +0 -8
- package/src/workflows/engine.ts +4 -6
- package/src/workflows/human-decision.ts +18 -2
- package/src/workflows/index.ts +0 -1
- package/src/workflows/schema.ts +0 -6
- package/src/workflows/settings.ts +1 -20
- package/src/workflows/store.ts +237 -489
- package/src/workflows/tool-input.ts +36 -1
- package/src/workflows/types.ts +6 -8
- package/src/workflows/workflow-message-content.ts +197 -0
- package/dist/extension/decision-channels.d.ts +0 -134
- package/dist/extension/decision-channels.js +0 -1307
- package/dist/extension/decision-channels.js.map +0 -1
- package/src/extension/decision-channels.ts +0 -1826
|
@@ -1,25 +1,67 @@
|
|
|
1
|
-
# Workflow
|
|
1
|
+
# Workflow messages in Pi
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Status: this is the implemented workflow-message contract. [Unify workflow messages and restore hosted behavior](2026-09-02-unify-workflow-messages-plan.md) records the approved design and implementation plan.
|
|
4
4
|
|
|
5
5
|
## Goal
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Pi Workflows must add several kinds of content to an origin Pi conversation. These include interactive step prompts, protected human decisions, passive notifications, terminal results, and follow-up prompts. Initial, reminder, and resumed prompts are one step-message kind with different display reasons.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The host saves all of them as workflow messages. One extension component sends them through documented Pi APIs. Feature records continue to own workflow results, answers, settings, and timeouts.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The model receives complete instructions when a workflow message starts a turn. The user sees a compact card for structured workflow content and can expand it.
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Workflow message contract
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
A workflow message is content that Pi Workflows requires Pi to add to one conversation. It does not mean every message in that conversation.
|
|
16
16
|
|
|
17
|
-
The message
|
|
17
|
+
The message kinds are:
|
|
18
|
+
|
|
19
|
+
| Kind | Pi behavior | Purpose |
|
|
20
|
+
| -------------- | ----------------------------------------------- | ------------------------------------------------ |
|
|
21
|
+
| `step` | Custom message that starts a model turn | Initial, reminder, or resumed interactive prompt |
|
|
22
|
+
| `decision` | Custom message that does not start a model turn | Protected choice for a person |
|
|
23
|
+
| `notification` | Custom message that does not start a model turn | Passive workflow notice |
|
|
24
|
+
| `terminal` | Custom message that starts a model turn | Final result and safe recovery choice |
|
|
25
|
+
| `followUp` | Custom message that starts normal work | Work saved for after successful completion |
|
|
26
|
+
|
|
27
|
+
The host stores one `WorkflowMessage` record before Pi can send it:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
type WorkflowMessage = {
|
|
31
|
+
schema: "pi-workflows.workflow-message.v1";
|
|
32
|
+
workflowMessageId: string;
|
|
33
|
+
runId: string;
|
|
34
|
+
targetSessionId: string;
|
|
35
|
+
kind: "step" | "decision" | "notification" | "terminal" | "followUp";
|
|
36
|
+
sourceId: string;
|
|
37
|
+
contentDigest: string;
|
|
38
|
+
order: number;
|
|
39
|
+
status: "pending" | "sent" | "cancelled";
|
|
40
|
+
piSessionEntryId: string | null;
|
|
41
|
+
createdAt: string;
|
|
42
|
+
updatedAt: string;
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The exact Pi content and custom display details remain in the content-addressed value store. `contentDigest` binds the record to those bytes. `sourceId` links the message to the feature record that created it.
|
|
47
|
+
|
|
48
|
+
`kind` determines the custom renderer, whether a model turn starts, and the host eligibility rule. The host does not store duplicate flags or message-to-message pointers for those facts.
|
|
49
|
+
|
|
50
|
+
`order` is the acceptance order for one origin session. The host marks one pending item as next in the origin-session view. An earlier ineligible or cancelled item does not block unrelated eligible work.
|
|
51
|
+
|
|
52
|
+
A source lifecycle transaction can change `pending` to `cancelled`. Active-branch evidence changes `pending` or `cancelled` to `sent`; evidence wins because Pi already contains the entry. `sent` is terminal. A pending message can be new or uncertain after a process stopped, so the coordinator always checks the active branch before sending it.
|
|
53
|
+
|
|
54
|
+
Workflow message IDs and internal send state are not included in provider-facing prompt content. The hidden custom-message details contain only the stable workflow message ID needed for branch recovery.
|
|
55
|
+
|
|
56
|
+
## Agent step card
|
|
57
|
+
|
|
58
|
+
Every step message uses the custom type `pi-workflows-step`:
|
|
18
59
|
|
|
19
60
|
```ts
|
|
20
61
|
export type WorkflowAgentStepMessageDetails = {
|
|
21
62
|
schema: "pi-workflows.agent-step-message.v1";
|
|
22
|
-
|
|
63
|
+
workflowMessageId: string;
|
|
64
|
+
reason: "initial" | "reminder" | "resumed";
|
|
23
65
|
contract: AgentStepContract;
|
|
24
66
|
presentation?: {
|
|
25
67
|
runTitle?: string;
|
|
@@ -29,124 +71,173 @@ export type WorkflowAgentStepMessageDetails = {
|
|
|
29
71
|
|
|
30
72
|
pi.sendMessage(
|
|
31
73
|
{
|
|
32
|
-
customType: "pi-workflows-
|
|
74
|
+
customType: "pi-workflows-step",
|
|
33
75
|
content: completeModelPrompt,
|
|
34
76
|
display: true,
|
|
35
77
|
details,
|
|
36
78
|
},
|
|
37
|
-
{
|
|
38
|
-
triggerTurn: true,
|
|
39
|
-
},
|
|
79
|
+
{ triggerTurn: true },
|
|
40
80
|
);
|
|
41
81
|
```
|
|
42
82
|
|
|
43
|
-
`content` is the complete prompt
|
|
44
|
-
|
|
45
|
-
`details` contains structured display data. The renderer reads this object directly and never parses the prompt text. `AgentStepContract` remains the source of every identity field, the completion form, the submitted output description, and any explicit assistant character limit.
|
|
46
|
-
|
|
47
|
-
`kind` distinguishes the first delivery from a reminder or a resume that must repeat the instructions. An ordinary resume that can continue without another prompt does not create a message.
|
|
48
|
-
|
|
49
|
-
## Session delivery
|
|
50
|
-
|
|
51
|
-
One shared coordinator delivers step prompts, protected decisions, notifications, and final workflow results. It does not claim or send a new message while Pi is busy or another message is pending. It checks these conditions again after the asynchronous host claim and immediately before the synchronous send. The coordinator remembers the stable delivery ID and exact claim expiry before that final check. If Pi became busy, a later poll can use that same claim while it remains live. Before it sends retained work, it revalidates the exact claim and durable resource through the host, then checks Pi and the lease again. Cancelled, paused, or replaced work is discarded. An expired unused claim is also discarded.
|
|
83
|
+
`content` is the complete provider-facing prompt. It includes the task, workflow identity, attempt identity, output form, and completion rules.
|
|
52
84
|
|
|
53
|
-
|
|
85
|
+
The renderer reads `details` and does not parse the prompt. It shows a compact summary by default and the complete prompt when expanded. If the renderer is unavailable, Pi still retains the custom message and its content.
|
|
54
86
|
|
|
55
|
-
|
|
87
|
+
Submitted agent steps call the `workflow` tool. Assistant-message steps reply normally. Both forms keep the existing `agent` node and use `expectedOutput` to select the completion form.
|
|
56
88
|
|
|
57
89
|
## Engine boundary
|
|
58
90
|
|
|
59
|
-
The workflow engine remains independent of Pi. It
|
|
91
|
+
The workflow engine remains independent of Pi. It produces an `AgentStepRequest` with a complete prompt and structured contract. One pure formatter builds the same provider-facing prompt for interactive and RPC execution. The extension does not shorten or rebuild it from display fields.
|
|
60
92
|
|
|
61
|
-
|
|
93
|
+
When a workflow has live settings, the formatter adds the settings scope, change number, bounded current value, allowed model paths, and exact `change-settings` action. It also adds the `queue-follow-up` and `remove-follow-up` actions. Actor identity is not model input. The extension derives it from the documented tool call.
|
|
62
94
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Before the step contract, the formatter adds the active settings scope, change number, bounded current value, allowed model paths, and exact `change-settings` action when that scope declares settings. It also shows the `queue-follow-up` and `remove-follow-up` actions. Actor identity is never part of model input. The extension derives it from the documented tool call.
|
|
95
|
+
An assistant-message step parks for its origin Pi session. A detached run without an approved origin session fails before it creates that message.
|
|
66
96
|
|
|
67
97
|
## Compact display
|
|
68
98
|
|
|
69
|
-
|
|
99
|
+
A collapsed step card shows only the workflow identity and current work. For example:
|
|
70
100
|
|
|
71
101
|
```text
|
|
72
102
|
▶ monitor › check
|
|
73
103
|
Checking the monitored target
|
|
74
104
|
```
|
|
75
105
|
|
|
76
|
-
A reminder or resumed
|
|
106
|
+
A reminder or resumed prompt adds a short label:
|
|
77
107
|
|
|
78
108
|
```text
|
|
79
109
|
↻ monitor › check · reminder
|
|
80
110
|
Checking the monitored target
|
|
81
111
|
```
|
|
82
112
|
|
|
83
|
-
The card uses the run title when it is more useful than the workflow name. It omits missing
|
|
113
|
+
The card uses the run title when it is more useful than the workflow name. It omits missing detail and clips or wraps long text to the terminal width.
|
|
84
114
|
|
|
85
|
-
The expanded card shows
|
|
115
|
+
The expanded card shows the workflow name, run title, run ID, node ID, attempt ID, step reason, completion form, expected output, optional character limit, and complete model prompt. Expansion uses Pi's standard custom-message state and keys. Pi Workflows does not store another expansion setting.
|
|
86
116
|
|
|
87
|
-
-
|
|
88
|
-
- run id
|
|
89
|
-
- node id
|
|
90
|
-
- attempt id
|
|
91
|
-
- delivery kind
|
|
92
|
-
- completion form
|
|
93
|
-
- expected output and optional character limit
|
|
94
|
-
- full model prompt
|
|
117
|
+
Notifications keep the custom type `pi-workflows-notification` and use `triggerTurn: false`. Decisions and terminal results use their approved structured renderers. The message kind fixes each send policy; the coordinator cannot change it at run time.
|
|
95
118
|
|
|
96
|
-
|
|
119
|
+
## One sender
|
|
97
120
|
|
|
98
|
-
|
|
121
|
+
The extension has one `WorkflowMessageCoordinator` for all message kinds. The host keeps one active coordinator connection and process-local epoch for each origin session. A replacement connection fences the old one, so two Pi processes cannot send for the same session.
|
|
99
122
|
|
|
100
|
-
The
|
|
123
|
+
The coordinator follows this sequence:
|
|
101
124
|
|
|
102
|
-
|
|
125
|
+
1. After every host connection, wait for the complete origin-session view and report the active branch before any send or turn report.
|
|
126
|
+
2. Wait until the host view names the next eligible pending message, Pi is idle, and Pi has no queued user input.
|
|
127
|
+
3. Save the message ID in the coordinator's queued map.
|
|
128
|
+
4. Search the active Pi branch for the same hidden message ID and report a matching entry.
|
|
129
|
+
5. Recheck synchronously that Pi is idle, has no pending input, the message is absent, and this connection still owns the active session epoch.
|
|
130
|
+
6. Call `pi.sendMessage()` with no `await` between that final check and call.
|
|
131
|
+
7. Wait until the new Pi entry is visible.
|
|
132
|
+
8. Report the active branch so the host saves its Pi entry ID and marks the message `sent`.
|
|
103
133
|
|
|
104
|
-
|
|
134
|
+
The coordinator sends only one workflow message at a time. A poll can find work, but it cannot send an ID already in its queued map.
|
|
105
135
|
|
|
106
|
-
|
|
136
|
+
Pi can emit `agent_start` before the host saves the new Pi entry ID. The coordinator keeps that start and any matching end in its in-memory session map. It first marks the workflow message `sent`, then reports the saved turn events in order. It does not drop a turn event while host confirmation is in progress.
|
|
107
137
|
|
|
108
|
-
|
|
138
|
+
A visible active-branch entry with the hidden ID is `sent`, even if the source lifecycle cancelled the message before the evidence arrived. Active-branch absence is usable only when the branch has no matching ID, Pi is idle, and Pi has no pending messages in the same observation. If Pi or the extension disappears after the send call, the message stays `pending`; reconnect reports the branch before another send. These rules do not prove cross-branch absence or exactly-once model execution.
|
|
109
139
|
|
|
110
|
-
|
|
140
|
+
After Pi, the extension, or the host restarts, branch reporting runs before any new send. It re-creates a message of the source's own kind only when the active branch has no entry for that source. A pending interaction gets one `step` with reason `resumed`; a pending decision gets one `decision`. Old incompatible workflow state is not reinterpreted.
|
|
111
141
|
|
|
112
|
-
##
|
|
142
|
+
## Model-turn status
|
|
113
143
|
|
|
114
|
-
|
|
144
|
+
`agent_start` has no message payload. The extension binds it through the current origin-session view. Turn binding ignores branch membership; only branch reporting and re-presentation inspect the active branch:
|
|
115
145
|
|
|
116
|
-
|
|
146
|
+
- the latest sent step is open while its interaction remains pending and its run is not paused;
|
|
147
|
+
- a terminal or follow-up message is open only until its first turn ends;
|
|
148
|
+
- decisions and notifications never open a turn.
|
|
117
149
|
|
|
118
|
-
|
|
150
|
+
A start against a closed message is rejected. Follow-up turns are reported for ordering but do not show the completed workflow as `running`.
|
|
119
151
|
|
|
120
|
-
|
|
152
|
+
The extension creates one workflow turn ID at `agent_start` and keeps it through the matching `agent_end` and host reconnect. It buffers starts and ends until the session view and message receipt are ready.
|
|
121
153
|
|
|
122
|
-
|
|
154
|
+
At `agent_end`, it derives `completed`, `aborted`, or `error` from the documented assistant messages. It reads response-entry evidence from `ctx.sessionManager.getBranch()`; the entry ID can be null. The host saves one immutable end result. A repeated report adopts it, and a stale turn ID cannot clear newer activity. A supervised worker can continue after accepted tool output while that Pi turn is still open. This normal continuation leaves the session capture recording until `agent_end`; it does not mark the capture as interrupted.
|
|
123
155
|
|
|
124
|
-
|
|
156
|
+
The host applies the end and its workflow consequence in one transaction. An aborted turn sets the run pause and cancels the request's pending step messages; the interaction derives its paused state from the run. Resuming that submitted-output step atomically clears the pause, increments the interaction revision, and creates one new step message with reason `resumed`. That message starts a fresh Pi model turn. A protected decision does not start a model turn, so its revision and decision message do not change when its run resumes. A completed, recoverably failed, or proved-lost turn increments `unproductiveTurnEnds` only when the submitted-output step is pending, not paused, and has no accepted or validating submission. Values one and two create one step message with reason `reminder`; a value above two fails the attempt. A partial unique index enforces at most one pending step message for the request, regardless of reason. Acceptance, pause, cancel, timeout, and branch re-presentation cancel all pending step messages. A cancelled message did not start a turn and does not increment the counter.
|
|
125
157
|
|
|
126
|
-
|
|
158
|
+
There is no activity heartbeat, refresh lease, or sequence counter. The host shows `running` from the matching start until the matching end. Host startup never marks a Pi turn lost. On `session_start`, only an idle-session branch report can close an open sent message with synthetic stop reason `lost`. Polling and time alone cannot create a reminder.
|
|
127
159
|
|
|
128
|
-
##
|
|
160
|
+
## Feature ownership
|
|
161
|
+
|
|
162
|
+
The workflow message stores only Pi send facts. Other records remain authoritative:
|
|
163
|
+
|
|
164
|
+
- interactive requests own step contracts, attempts, deadlines, validation, model submissions, and `unproductiveTurnEnds`;
|
|
165
|
+
- human decisions own choices, verified answers, expiry, and continuation;
|
|
166
|
+
- terminal runs own outcomes, reasons, restart lineage, and results;
|
|
167
|
+
- notification nodes own their node results;
|
|
168
|
+
- follow-up records own prompt source and authority;
|
|
169
|
+
- settings records own current values and accepted changes.
|
|
170
|
+
|
|
171
|
+
Submitted-output steps can use reminders. Assistant-message steps do not send a reminder after a visible response. An interrupted assistant-message step keeps its attempt ID and adopts a matching completed response from the active branch. A stale attempt or another branch remains invalid.
|
|
172
|
+
|
|
173
|
+
Each source event creates its workflow message in the same SQLite transaction. The message cannot exist without its source fact, and a source fact cannot require a Pi message without the matching record.
|
|
174
|
+
|
|
175
|
+
## Restored behavior
|
|
176
|
+
|
|
177
|
+
The shared contract supports these features without separate send paths:
|
|
129
178
|
|
|
130
|
-
|
|
179
|
+
- at most two reminder-reason step messages after model turns end without a valid submission;
|
|
180
|
+
- one resumed-reason step message after a presented paused step resumes;
|
|
181
|
+
- one terminal result and recovery turn for the final outcome of each interactive continuation chain;
|
|
182
|
+
- safe restart with lineage, a limit of three, and repeated-failure protection;
|
|
183
|
+
- ordered follow-up prompts after successful completion, terminal turn end, and release of later workflow reservations;
|
|
184
|
+
- protected decisions in Pi and approved external channels;
|
|
185
|
+
- passive notifications that do not start model turns;
|
|
186
|
+
- terminal result retention while its message is pending or its first turn is open, and then for 60 seconds after that turn ends, in the widget and `piw`;
|
|
187
|
+
- conversation recording linked to workflow attempts.
|
|
131
188
|
|
|
132
|
-
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
189
|
+
A terminal or follow-up message does not reopen the completed workflow. A slash-looking follow-up remains plain model input because `pi.sendMessage()` does not dispatch extension commands or expand prompt templates. External effects remain idempotent or explicitly ambiguous.
|
|
190
|
+
|
|
191
|
+
## Session recording
|
|
192
|
+
|
|
193
|
+
The extension records workflow-related Pi events through a batched host client operation. It uses documented Pi events and does not read or edit Pi session files.
|
|
194
|
+
|
|
195
|
+
The host deduplicates settled entries by Pi entry ID. It links attempts to their prompt, response, first, and last entries. A recording failure does not fail workflow execution.
|
|
196
|
+
|
|
197
|
+
## Public API boundary
|
|
198
|
+
|
|
199
|
+
The extension uses documented `pi.sendMessage()`, `pi.registerMessageRenderer()`, session lifecycle events, agent lifecycle events, widgets, status, commands, shortcuts, and session IDs.
|
|
200
|
+
|
|
201
|
+
This design does not change Pi core, use private Pi APIs, or change Pi session schemas. It does not add another database or runtime.
|
|
202
|
+
|
|
203
|
+
## Validation and tests
|
|
145
204
|
|
|
146
|
-
|
|
205
|
+
Tests must prove:
|
|
206
|
+
|
|
207
|
+
- every message kind uses the one coordinator;
|
|
208
|
+
- one workflow message ID creates at most one confirmed Pi entry and one automatic model turn;
|
|
209
|
+
- a later manual turn uses a new workflow turn ID without creating another Pi entry;
|
|
210
|
+
- two Pi processes that open one session cannot both send because one process-local coordinator epoch is active;
|
|
211
|
+
- restart recovery reports the branch and adopts an existing entry before it sends;
|
|
212
|
+
- branch absence is usable only when Pi is idle and has no pending input;
|
|
213
|
+
- a crash after send leaves the message pending and cannot cause a resend before branch reporting;
|
|
214
|
+
- messages remain in saved order without message-pointer deadlocks;
|
|
215
|
+
- an early `agent_start` and `agent_end` wait for the message receipt and session view, then apply in order;
|
|
216
|
+
- every matching model turn shows `running` for its full duration;
|
|
217
|
+
- normal worker continuation leaves the active session capture open until the matching turn ends;
|
|
218
|
+
- stale turn-end reports and starts against closed messages are rejected;
|
|
219
|
+
- a manual turn cancels pending step messages that it supersedes;
|
|
220
|
+
- a turn cannot bind to an interaction whose run is paused;
|
|
221
|
+
- aborted turns pause without incrementing the unproductive-turn counter;
|
|
222
|
+
- resuming an aborted step creates one new resumed message and one fresh model turn;
|
|
223
|
+
- resuming a protected decision keeps its answer revision and does not create a duplicate decision message;
|
|
224
|
+
- host restart does not close a live Pi turn, while an idle-session branch report can close an unended turn as lost;
|
|
225
|
+
- two reminder-reason steps are sent at most once and the next unproductive turn fails;
|
|
226
|
+
- initial, reminder, and resumed prompts use the same step kind and differ only by reason;
|
|
227
|
+
- terminal and follow-up messages each start only at their durable boundary;
|
|
228
|
+
- a branch switch creates one resumed-reason step only when that branch has no entry for the interaction;
|
|
229
|
+
- a missing protected decision creates another decision message, not a step;
|
|
230
|
+
- branch evidence changes a cancelled message to sent;
|
|
231
|
+
- a follow-up-started workflow blocks the next follow-up through its session reservation;
|
|
232
|
+
- notifications and protected decisions do not start model turns;
|
|
233
|
+
- the provider receives the complete step prompt but no workflow message ID or internal send state;
|
|
234
|
+
- collapsed and expanded cards remain safe and complete;
|
|
235
|
+
- session recording adopts each settled Pi entry once.
|
|
236
|
+
|
|
237
|
+
The real Pi end-to-end test must use a clean Pi home with only the packed pi-workflows extension. It must accept any provider and model supported by base Pi. `openai` and `openai-codex` are separate providers.
|
|
147
238
|
|
|
148
239
|
## Security
|
|
149
240
|
|
|
150
|
-
Workflow prompts and expected-output descriptions
|
|
241
|
+
Workflow prompts and expected-output descriptions can contain untrusted text. Renderers treat them as text, wrap them safely, and do not interpret workflow control sequences or markup.
|
|
151
242
|
|
|
152
|
-
Collapsed cards
|
|
243
|
+
Collapsed cards hide full prompts from the normal conversation view. Expanded cards and Pi session files still contain the full content, so normal session privacy rules apply. Credentials, internal send state, and internal message IDs do not enter provider-facing content.
|
|
@@ -78,7 +78,9 @@ Only the host computes this status. A parked queue is not a pause. `paused` requ
|
|
|
78
78
|
|
|
79
79
|
The run list uses the same display object. The host sends it as revision-bound `pi-workflows.run-list-page.v1` pages. Each page reads only lightweight run status and source facts. It does not load input, launch options, steps, trace, or session history. TypeScript and Rust clients collect all pages for one revision before they replace the visible list. If the revision changes, they discard the partial list and start from the next subscription event.
|
|
80
80
|
|
|
81
|
-
An origin-session subscription returns `pi-workflows.session-view.v1
|
|
81
|
+
An origin-session subscription returns `pi-workflows.session-view.v1`. It contains the active run view first. When no run is active, it keeps the most recent terminal run while its terminal workflow message is pending or its first model turn is open, and then for 60 seconds after that turn ends. The same response contains an ordered byte-bounded window of all nonterminal workflow messages and open sent messages needed for recovery, their complete count, and the next eligible pending message only for the active coordinator epoch.
|
|
82
|
+
|
|
83
|
+
The Pi extension assembles the complete run revision and workflow-message content before it updates the widget or coordinator. After every host connection, it reports the active branch before it sends a workflow message or reports a model turn. The report can name only message IDs from the complete session-view window. The extension always uses the exact run ID from that view. It does not select the latest run separately. An idle session does not create empty commands.
|
|
82
84
|
|
|
83
85
|
A snapshot page contains at most 256 items and also has a byte budget. `view.page` returns another byte-bounded window that contains the requested cursor. Page responses use `pi-workflows.run-page.v1` and echo the requested cursor and run-view revision. A client applies a page only when both still match its current request and snapshot. A step-centered trace request selects the exact stored attempt first and uses its node only when that attempt has no trace event. Large workflow topology has bounded node, edge, graph-step, and transition projections plus durable content references for the complete original definition and complete graph history. TypeScript clients assemble every run-history page for that revision and hydrate the complete definition and all referenced content before they emit a complete non-interactive view or update the Pi widget. TypeScript and Rust use the same verified content loader for complete graph steps and transitions. Rust also requests, verifies, and decodes the complete referenced definition before it builds the graph layout. A session-event page also carries the replay checkpoint for the exact sequence before its first item, so reducing the page does not lose earlier active messages or tool calls. The checkpoint can itself be a durable content reference. TypeScript hydrates it with the run view, and Rust requests and resolves it before replay.
|
|
84
86
|
|
|
@@ -90,13 +92,15 @@ Large prompt, output, event, settings, follow-up, and update values use a conten
|
|
|
90
92
|
|
|
91
93
|
A client keeps one persistent connection and records its desired run-list, run, and origin-session subscriptions. A request to watch a run that does not exist returns `notFound` and does not install a subscription. TypeScript and Rust clients show that response instead of waiting for a snapshot. Explicit `piw <runId>` mode keeps that run selected even when the run list contains a newer run. After reconnection, the client sends accepted subscriptions again with its run revision. The host sends a bounded snapshot when the client needs one. The protocol also supports retained revision patches. Unsubscribing sends the subscription ID to the host for every subscription kind, so no unused snapshot work remains on a live connection.
|
|
92
94
|
|
|
93
|
-
A slow or disconnected client cannot stop the host, another client, claim renewal, or workflow execution. The host waits for socket drain before it publishes another snapshot to that connection. Polling coalesces while the connection is blocked, so the socket buffer cannot grow by one snapshot on every poll. When a connection closes, the host removes its subscriptions and
|
|
95
|
+
A slow or disconnected client cannot stop the host, another client, claim renewal, or workflow execution. The host waits for socket drain before it publishes another snapshot to that connection. Polling coalesces while the connection is blocked, so the socket buffer cannot grow by one snapshot on every poll. When a connection closes, the host removes its subscriptions and active coordinator epoch. It does not infer that an open model turn ended.
|
|
94
96
|
|
|
95
97
|
## Origin-session activity
|
|
96
98
|
|
|
97
|
-
The Pi extension
|
|
99
|
+
The Pi extension uses `workflowTurn.report` to record `started` and `ended` for the exact workflow message, workflow turn, run, and origin session. There is no refresh, activity lease, heartbeat, or sequence counter. A started turn keeps the host-produced display status `running` until the matching end is accepted. A stale end cannot clear a newer turn.
|
|
100
|
+
|
|
101
|
+
The host accepts a start only for an open sent workflow message in that origin session. A step message is open while its interaction remains pending and its run is not paused. A terminal or follow-up message is open until its first turn ends. Decisions and notifications never open model turns. Turn binding does not inspect branch membership because documented `agent_start` has no message payload; branch reporting owns entry adoption and branch-specific re-presentation.
|
|
98
102
|
|
|
99
|
-
|
|
103
|
+
If the workflow message or session view is still loading, the extension buffers the matching start and end and reports them in order after the message is confirmed `sent`. Activity changes display only. It does not grant workflow authority, renew a run claim, or settle an interaction. Host startup does not close an open Pi turn. Only a later idle-session active-branch report can close a proved-lost turn.
|
|
100
104
|
|
|
101
105
|
## Commands and uncertain results
|
|
102
106
|
|
package/docs/tui-viewer.md
CHANGED
|
@@ -11,9 +11,11 @@ The viewer uses the [incremental and virtualized viewer design](plans/2026-08-28
|
|
|
11
11
|
|
|
12
12
|
The run browser subscribes to small host-owned metadata views. It does not load trace, step, session, settings, or follow-up payloads. The host publishes a new bounded view only when its content changes.
|
|
13
13
|
|
|
14
|
+
Each live view keeps the host's `display` value separate from the durable workflow `state`. The run browser, current-run status, timeline, and latest graph use `display` directly. During an origin-session model turn, the latest graph presents the durable `waitingOn` node as running. Replay continues to use durable state and recorded history. `piw` does not calculate another live status.
|
|
15
|
+
|
|
14
16
|
The selected run contains bounded pages. Step, trace, session-entry, session-event, settings, follow-up, and update pages have both a row limit and a byte budget. Replay can jump to any position. The viewer loads the page that contains that position and keeps only the current windows. A session-event page includes the replay checkpoint immediately before its first event. A compact graph projection keeps the latest attempt for each node and the taken transitions up to the replay point.
|
|
15
17
|
|
|
16
|
-
Large values use host content references. `piw` fetches
|
|
18
|
+
Large values use host content references. `piw` fetches workflow definitions, graph history, and complete host display reasons before it publishes the related live view. It fetches other large details when the user opens them. It verifies the byte count and SHA-256 digest before it shows the complete text or JSON value. Page and content requests run outside input and drawing through the shared client protocol. A newer page selection replaces the previous request, including when the user returns to an earlier page. A failed first read leaves the run browser usable. A failed refresh keeps the last good view and marks it stale.
|
|
17
19
|
|
|
18
20
|
## Install
|
|
19
21
|
|
package/docs/workflows.md
CHANGED
|
@@ -147,9 +147,11 @@ provisional. A new supervised worker loads the workflow and runs its `validate`
|
|
|
147
147
|
function before the host accepts the submission. A validation error leaves the
|
|
148
148
|
same request pending and returns the error to the model. Closing Pi leaves that
|
|
149
149
|
request pending; reopening the same session adopts the existing session entry
|
|
150
|
-
or presents it once.
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
or presents it once. Step prompts, protected decisions, notifications, terminal
|
|
151
|
+
results, and follow-ups use the host-owned `workflow_messages` table and one
|
|
152
|
+
extension sender. Initial, reminder, and resumed prompts are the same step-message
|
|
153
|
+
kind with different display reasons. A terminal workflow message becomes eligible only after
|
|
154
|
+
the terminal outcome is committed. A controller child without an origin session can use a supervised
|
|
153
155
|
headless `pi --mode rpc` child for structured agent steps.
|
|
154
156
|
|
|
155
157
|
Pause stops the worker and parks at the last durable boundary. Resume takes a
|
|
@@ -200,15 +202,19 @@ the client stops waiting but does not cancel the durable host command. A retry
|
|
|
200
202
|
uses a new transport request ID with the same durable submission identity and
|
|
201
203
|
adopts the stored result. Rejected submissions return
|
|
202
204
|
the validation error and can retry in the same step. If the model settles
|
|
203
|
-
without submitting, the
|
|
204
|
-
|
|
205
|
+
without submitting, the host increments the request's unproductive-turn counter
|
|
206
|
+
and can create at most two step messages with reason `reminder`. The next
|
|
207
|
+
unproductive turn fails the step. The timeout remains active during each
|
|
208
|
+
reported model turn, and cancellation remains active throughout. For assistant-message output, the engine appends a normal-response contract,
|
|
205
209
|
waits for `agent_settled`, rejects empty, failed, aborted, or tool-only results,
|
|
206
210
|
and never suppresses the visible text. Timeout and cancellation abort either
|
|
207
211
|
form's active Pi turn.
|
|
208
212
|
|
|
209
213
|
`timeoutMs` can be a finite positive number, `null`, or a function of the normal
|
|
210
214
|
node context that returns either value. Omit it to use the 15-minute engine
|
|
211
|
-
default.
|
|
215
|
+
default. The limit counts active node execution. For an origin-session agent
|
|
216
|
+
node, it counts reported model-turn time from an active connected Pi session.
|
|
217
|
+
It excludes message delivery, waiting, paused time, disconnects, and host downtime. Set it to `null` to disable only this deadline; cancellation,
|
|
212
218
|
parking, claim loss, shutdown, and the node's abort signal still work. A timeout
|
|
213
219
|
function can use prepared outputs to select a policy for this run. It has 30
|
|
214
220
|
seconds to return. Computed timeout functions are runtime code, so definition
|
|
@@ -317,7 +323,10 @@ keeps normal output capture. Lines and update data are each limited to 64 KiB.
|
|
|
317
323
|
See [WORKFLOW_UPDATES.md](WORKFLOW_UPDATES.md) for the envelope, progress
|
|
318
324
|
schema, limits, estimation, and error rules.
|
|
319
325
|
|
|
320
|
-
The host reserves the effect before it lets the action run.
|
|
326
|
+
The host reserves the effect before it lets the action run. The engine creates
|
|
327
|
+
the internal key from the run ID, effect type, full compiled node path, and node
|
|
328
|
+
visit number. Workflow code does not supply that key. Two included workflows
|
|
329
|
+
can use the same local node name without sharing an effect. A repeated key with
|
|
321
330
|
the same request adopts the durable record; the same key with another request
|
|
322
331
|
is a conflict. A normal caught error settles the attempt as rejected. After an
|
|
323
332
|
uncertain process exit, an idempotent effect returns to pending for retry, while
|
|
@@ -373,7 +382,7 @@ humanDecision({
|
|
|
373
382
|
});
|
|
374
383
|
```
|
|
375
384
|
|
|
376
|
-
The waiting run stores a versioned request and asks every channel configured for the logical audience. The structured `subject` remains machine data. Channels receive only the normalized `presentation`, title, choices, input prompts, and any deadline policy. The first valid verified human answer wins. When `onTimeout` is present and no human answer wins before the saved deadline, the host takes a control claim on the waiting parent and atomically applies the validated response with `timeout` provenance, closes the interaction, and reserves the continuation. This policy can continue without a configured channel. A continuation preserves the original workflow input and exposes the resolved response as the checkpoint output. `humanDecisionEdge()` provides exhaustive routing for the choices.
|
|
385
|
+
The waiting run stores a versioned request and asks every channel configured for the logical audience. The structured `subject` remains machine data. Channels receive only the normalized `presentation`, title, choices, input prompts, and any deadline policy. The first valid verified human answer wins. When `onTimeout` is present and no human answer wins before the saved deadline, the host takes a control claim on the waiting parent and atomically applies the validated response with `timeout` provenance, closes the interaction, and reserves the continuation. This policy can continue without a configured channel. A continuation preserves the original workflow input and exposes the resolved response as the checkpoint output. `humanDecisionEdge()` provides exhaustive routing for the choices. The removed `body` request form is invalid under the alpha hard cut.
|
|
377
386
|
|
|
378
387
|
The model-facing workflow tool cannot answer a protected human decision. The origin Pi session displays the request without starting a model turn. A person uses `/workflow answer` to send the answer through the host-owned path. Ordinary checkpoints can also use the model-facing `answer` action.
|
|
379
388
|
|
|
@@ -480,18 +489,19 @@ The model sees one `workflow` tool. Its `action` field supports:
|
|
|
480
489
|
A direct user request to continue or resume the active workflow maps to
|
|
481
490
|
`resume` immediately. The model does not call `status` instead of `resume` or
|
|
482
491
|
use it as a prerequisite. An already active run adopts the resume request. A
|
|
483
|
-
|
|
484
|
-
worker. Other paused or parked work gets a new claim generation and worker.
|
|
492
|
+
pending interaction on a paused run remains the same durable request and resumes
|
|
493
|
+
without a worker. Other paused or parked work gets a new claim generation and worker.
|
|
485
494
|
With no resumable run, the host rejects the request.
|
|
486
495
|
|
|
487
496
|
The origin Pi session shows its active run in the workflow widget. `Shift+Up`
|
|
488
|
-
and `Shift+Down` scroll it.
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
497
|
+
and `Shift+Down` scroll it. A sent step message is open only while its
|
|
498
|
+
interaction is pending and its run is not paused. Because public `agent_start`
|
|
499
|
+
has no message payload, any model turn that starts in that state is workflow
|
|
500
|
+
work. If Escape ends that turn with Pi's public `aborted` stop reason, one
|
|
501
|
+
turn-end report atomically sets the run pause and cancels the interaction's
|
|
502
|
+
pending step messages. A turn that starts while the run is paused does not bind
|
|
503
|
+
to the workflow. The paused run does not accept updates, submissions, or
|
|
504
|
+
decision answers until `resume`.
|
|
495
505
|
|
|
496
506
|
`status` reports the durable queue projection. A host command succeeds only
|
|
497
507
|
after its transaction commits. The protocol stores request fingerprints and
|
|
@@ -684,18 +694,16 @@ is pending, the step id is wrong, the attempt id belongs to an earlier attempt
|
|
|
684
694
|
of the same node (loops revisit node ids, so each attempt gets a fresh id), or
|
|
685
695
|
`validate` throws.
|
|
686
696
|
Acceptance resolves the step and the engine advances. In an interactive Pi
|
|
687
|
-
session, each agent prompt arrives as a `pi-workflows-
|
|
697
|
+
session, each agent prompt arrives as a `pi-workflows-step` custom message
|
|
688
698
|
with `triggerTurn: true`. The model receives the complete prompt, while the
|
|
689
699
|
conversation shows a compact workflow and node card. Expanding tool output with
|
|
690
|
-
Ctrl+O shows the exact contract and full prompt.
|
|
691
|
-
use the same card and keep the active attempt id.
|
|
700
|
+
Ctrl+O shows the exact contract and full prompt. Step messages with reason `reminder` or `resumed` use the same card and keep the active attempt ID.
|
|
692
701
|
|
|
693
702
|
Headless RPC execution receives the same complete prompt without TUI metadata.
|
|
694
|
-
Workflow notifications use a
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
[
|
|
698
|
-
and [Deferred workflow turns](DEFERRED_TURNS.md) for the successor-turn contract.
|
|
703
|
+
Workflow notifications use a custom message with `triggerTurn: false`, so a
|
|
704
|
+
notification does not start an assistant response. Step prompts, decisions, notifications, terminal results, and follow-ups use the same saved workflow-message contract and extension coordinator. Initial, reminder, and resumed prompts use the same step kind. See
|
|
705
|
+
[Workflow messages in Pi](WORKFLOW_STEP_MESSAGES.md) and the approved
|
|
706
|
+
[workflow-message restoration plan](2026-09-02-unify-workflow-messages-plan.md).
|
|
699
707
|
|
|
700
708
|
## Visible responses
|
|
701
709
|
|
|
@@ -712,7 +720,7 @@ returns its stored receipt.
|
|
|
712
720
|
|
|
713
721
|
A headless controller child cannot produce a visible assistant message without
|
|
714
722
|
an approved origin-session binding. Use structured agent output for detached
|
|
715
|
-
work.
|
|
723
|
+
work. A final continuation-chain outcome creates its own terminal workflow message through the shared coordinator only after the outcome is durable.
|
|
716
724
|
|
|
717
725
|
## Runtime behavior
|
|
718
726
|
|
|
@@ -724,14 +732,19 @@ possible. Defaults worth knowing:
|
|
|
724
732
|
number or context callback. A timed-out node has outcome `timed_out` and can
|
|
725
733
|
be routed with `$result.outcome`. A timed-out agent node also aborts its Pi
|
|
726
734
|
turn, and late output for that attempt is rejected. Interactive runs save the
|
|
727
|
-
resolved
|
|
728
|
-
|
|
735
|
+
resolved deadline before they park. The host advances it only during a
|
|
736
|
+
reported model turn from an active connected origin session. Message delivery,
|
|
737
|
+
waiting, pauses, disconnects, and host downtime do not consume the limit. This
|
|
738
|
+
active-time budget survives host restart.
|
|
729
739
|
- `maxSteps` (workflow-level, default 100) bounds loops built from cycles in
|
|
730
740
|
the graph.
|
|
731
741
|
- `/workflow pause` atomically parks the run with `paused: true`, stores the
|
|
732
742
|
receipt, and fences the worker before process-group shutdown. `/workflow
|
|
733
743
|
resume` takes a new generation and reruns only work after the last durable
|
|
734
744
|
boundary.
|
|
745
|
+
- The host tells each worker to `start`, `resume`, `continue`, or `restart`.
|
|
746
|
+
A checkpoint continuation names its waiting parent. A restart begins at the
|
|
747
|
+
workflow start and does not reuse checkpoint continuation rules.
|
|
735
748
|
- Resuming an active run adopts the existing work. Duplicate start, control,
|
|
736
749
|
update, and submission messages return their stored receipts.
|
|
737
750
|
- A start is committed as `queued` with its final run ID before the command
|
|
@@ -746,6 +759,9 @@ resume` takes a new generation and reruns only work after the last durable
|
|
|
746
759
|
same transaction. Claim loss does not write a failed run event.
|
|
747
760
|
- An uncommitted pure or idempotent node can run again after a worker crash. An
|
|
748
761
|
uncertain manual effect parks as ambiguous and never retries automatically.
|
|
762
|
+
If a ready worker exits before the saved run revision advances, the host parks
|
|
763
|
+
the run with `workerNoProgress`. The scheduler does not claim it again until
|
|
764
|
+
an operator explicitly resumes or cancels it.
|
|
749
765
|
- Host status reports safe counts and timestamps. It does not report session
|
|
750
766
|
IDs, project paths, prompts, payloads, tokens, process IDs, or credentials.
|
|
751
767
|
|
package/herdr-plugin.toml
CHANGED