@osolmaz/pi-workflows 0.12.0 → 0.13.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 +56 -31
- package/dist/builtins/autodoc.workflow.d.ts +4 -4
- package/dist/builtins/autoimplement.workflow.d.ts +797 -142
- package/dist/builtins/autoimplement.workflow.js +17 -105
- package/dist/builtins/autoimplement.workflow.js.map +1 -1
- package/dist/builtins/autoplan.workflow.d.ts +126 -13
- package/dist/builtins/autoplan.workflow.js +200 -29
- package/dist/builtins/autoplan.workflow.js.map +1 -1
- package/dist/builtins/catalog.js +7 -5
- package/dist/builtins/catalog.js.map +1 -1
- package/dist/builtins/index.d.ts +4 -2
- package/dist/builtins/index.js +3 -1
- package/dist/builtins/index.js.map +1 -1
- package/dist/builtins/monitor.workflow.d.ts +56 -23
- package/dist/builtins/monitor.workflow.js +508 -329
- package/dist/builtins/monitor.workflow.js.map +1 -1
- package/dist/builtins/pi-agent-group.d.ts +72 -0
- package/dist/builtins/pi-agent-group.js +1087 -0
- package/dist/builtins/pi-agent-group.js.map +1 -0
- package/dist/builtins/plain-summary.workflow.d.ts +32 -0
- package/dist/builtins/plain-summary.workflow.js +134 -0
- package/dist/builtins/plain-summary.workflow.js.map +1 -0
- package/dist/builtins/plan-approval.workflow.d.ts +39 -5
- package/dist/builtins/plan-approval.workflow.js +92 -14
- package/dist/builtins/plan-approval.workflow.js.map +1 -1
- package/dist/builtins/plan-change.workflow.d.ts +449 -0
- package/dist/builtins/plan-change.workflow.js +256 -0
- package/dist/builtins/plan-change.workflow.js.map +1 -0
- package/dist/builtins/plan-presentation.js +2 -2
- package/dist/builtins/plan-presentation.js.map +1 -1
- package/dist/builtins/sanity-check.workflow.d.ts +50 -6
- package/dist/builtins/sanity-check.workflow.js +150 -28
- package/dist/builtins/sanity-check.workflow.js.map +1 -1
- package/dist/controllers/effects.d.ts +3 -2
- package/dist/controllers/effects.js +8 -1
- package/dist/controllers/effects.js.map +1 -1
- package/dist/controllers/index.d.ts +1 -1
- package/dist/controllers/index.js +1 -1
- package/dist/controllers/index.js.map +1 -1
- package/dist/controllers/manager.d.ts +1 -0
- package/dist/controllers/manager.js +41 -17
- package/dist/controllers/manager.js.map +1 -1
- package/dist/controllers/sqlite.d.ts +107 -85
- package/dist/controllers/sqlite.js +1611 -1486
- package/dist/controllers/sqlite.js.map +1 -1
- package/dist/controllers/store.d.ts +9 -8
- package/dist/controllers/store.js +1 -31
- package/dist/controllers/store.js.map +1 -1
- package/dist/controllers/types.d.ts +3 -0
- package/dist/controllers/workflow-engine-scheduler.d.ts +1 -1
- package/dist/controllers/workflow-engine-scheduler.js +3 -5
- package/dist/controllers/workflow-engine-scheduler.js.map +1 -1
- package/dist/controllers/workflows.d.ts +2 -2
- package/dist/controllers/workflows.js +11 -10
- package/dist/controllers/workflows.js.map +1 -1
- package/dist/extension/controller-host.js +2 -2
- package/dist/extension/controller-host.js.map +1 -1
- package/dist/extension/decision-channels.d.ts +4 -2
- package/dist/extension/decision-channels.js +333 -146
- package/dist/extension/decision-channels.js.map +1 -1
- package/dist/extension/executor.d.ts +9 -2
- package/dist/extension/executor.js +89 -2
- package/dist/extension/executor.js.map +1 -1
- package/dist/extension/herdr-viewer.d.ts +0 -1
- package/dist/extension/herdr-viewer.js +0 -4
- package/dist/extension/herdr-viewer.js.map +1 -1
- package/dist/extension/index.js +209 -127
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/recorder.d.ts +3 -10
- package/dist/extension/recorder.js +13 -22
- package/dist/extension/recorder.js.map +1 -1
- package/dist/extension/session-events.d.ts +2 -2
- package/dist/extension/step-message.d.ts +7 -2
- package/dist/extension/step-message.js +94 -2
- package/dist/extension/step-message.js.map +1 -1
- package/dist/extension/widget.js +29 -3
- package/dist/extension/widget.js.map +1 -1
- package/dist/host/rpc-executor.d.ts +3 -0
- package/dist/host/rpc-executor.js +2 -0
- package/dist/host/rpc-executor.js.map +1 -1
- package/dist/host/runner.d.ts +3 -6
- package/dist/host/runner.js +83 -32
- package/dist/host/runner.js.map +1 -1
- package/dist/render/graph-render.js +15 -10
- package/dist/render/graph-render.js.map +1 -1
- package/dist/state/database.d.ts +35 -0
- package/dist/state/database.js +287 -0
- package/dist/state/database.js.map +1 -0
- package/dist/state/index.d.ts +4 -0
- package/dist/state/index.js +5 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/json.d.ts +6 -0
- package/dist/state/json.js +38 -0
- package/dist/state/json.js.map +1 -0
- package/dist/state/mutation.d.ts +57 -0
- package/dist/state/mutation.js +255 -0
- package/dist/state/mutation.js.map +1 -0
- package/dist/state/schema.d.ts +6 -0
- package/dist/state/schema.js +473 -0
- package/dist/state/schema.js.map +1 -0
- package/dist/viewer/cli.d.ts +2 -2
- package/dist/viewer/cli.js +142 -122
- package/dist/viewer/cli.js.map +1 -1
- package/dist/viewer/render.d.ts +4 -4
- package/dist/viewer/render.js +9 -23
- package/dist/viewer/render.js.map +1 -1
- package/dist/viewer/session-reducer.d.ts +1 -1
- package/dist/viewer/session-reducer.js +1 -1
- package/dist/viewer/tui.d.ts +3 -3
- package/dist/viewer/tui.js +15 -13
- package/dist/viewer/tui.js.map +1 -1
- package/dist/viewer/watch.d.ts +2 -5
- package/dist/viewer/watch.js +13 -13
- package/dist/viewer/watch.js.map +1 -1
- package/dist/workflows/catalog.js +7 -2
- package/dist/workflows/catalog.js.map +1 -1
- package/dist/workflows/composition.js +20 -2
- package/dist/workflows/composition.js.map +1 -1
- package/dist/workflows/decision-presentation.d.ts +1 -1
- package/dist/workflows/decision-presentation.js +51 -38
- package/dist/workflows/decision-presentation.js.map +1 -1
- package/dist/workflows/definition.d.ts +6 -2
- package/dist/workflows/definition.js +17 -0
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/engine.d.ts +7 -7
- package/dist/workflows/engine.js +196 -115
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/errors.d.ts +16 -3
- package/dist/workflows/errors.js +18 -3
- package/dist/workflows/errors.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +45 -8
- package/dist/workflows/human-decision.js +641 -274
- package/dist/workflows/human-decision.js.map +1 -1
- package/dist/workflows/index.d.ts +5 -6
- package/dist/workflows/index.js +4 -5
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/progress.d.ts +1 -0
- package/dist/workflows/progress.js +15 -3
- package/dist/workflows/progress.js.map +1 -1
- package/dist/workflows/schema.js +27 -1
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/store.d.ts +83 -103
- package/dist/workflows/store.js +907 -951
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +88 -126
- package/docs/CONTROLLERS.md +10 -8
- package/docs/DEFERRED_TURNS.md +2 -2
- package/docs/DESIGN_PHILOSOPHY.md +4 -2
- package/docs/HUMAN_DECISIONS.md +36 -47
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +14 -24
- package/docs/MONITOR.md +179 -237
- package/docs/SQLITE_STATE.md +219 -0
- package/docs/WORKFLOW_COMPOSITION.md +27 -26
- package/docs/WORKFLOW_STEP_MESSAGES.md +20 -18
- package/docs/WORKFLOW_UPDATES.md +10 -9
- package/docs/development.md +9 -9
- package/docs/live-replay-protocol.md +28 -37
- package/docs/plans/2026-08-16-workflow-updates-plan.md +1 -1
- package/docs/plans/2026-08-19-human-decision-gates-plan.md +1 -1
- package/docs/plans/2026-08-21-autoimplement-timeout-fallback-plan.md +1 -1
- package/docs/plans/2026-08-21-plan-change-approval-policy-plan.md +322 -0
- package/docs/plans/2026-08-21-sanity-check-plan.md +217 -95
- package/docs/plans/2026-08-22-goal-finishing-monitor-plan.md +200 -0
- package/docs/plans/2026-08-23-assistant-agent-completion-plan.md +701 -0
- package/docs/plans/2026-08-23-sqlite-state-plan.md +970 -0
- package/docs/plans/replayable-run-bundles-implementation-plan.md +2 -2
- package/docs/plans/session-event-replay-implementation-plan.md +1 -1
- package/docs/plans/tui-viewer-implementation-plan.md +1 -1
- package/docs/session-event-journal.md +63 -434
- package/docs/tui-viewer.md +13 -15
- package/docs/workflows.md +127 -53
- package/examples/workflows/approved-plan.workflow.ts +19 -46
- package/examples/workflows/plain-summary.workflow.ts +1 -0
- package/herdr-plugin.toml +1 -1
- package/package.json +7 -7
- package/plugins/herdr/viewer.mjs +1 -11
- package/schemas/human-decision-accepted-v1.schema.json +15 -3
- package/schemas/human-decision-continuation-v1.schema.json +10 -1
- package/schemas/human-decision-delivery-v1.schema.json +8 -0
- package/schemas/human-decision-receipt-v1.schema.json +8 -0
- package/schemas/human-decision-request-v1.schema.json +24 -4
- package/skills/autoimplement/SKILL.md +27 -0
- package/skills/autoplan/SKILL.md +5 -4
- package/skills/monitor/SKILL.md +91 -135
- package/skills/pi-workflows/SKILL.md +9 -8
- package/skills/sanity-check/SKILL.md +44 -0
- package/src/builtins/autoimplement.workflow.ts +19 -118
- package/src/builtins/autoplan.workflow.ts +290 -40
- package/src/builtins/catalog.ts +7 -5
- package/src/builtins/index.ts +18 -1
- package/src/builtins/monitor.workflow.ts +673 -382
- package/src/builtins/pi-agent-group.ts +1407 -0
- package/src/builtins/plain-summary.workflow.ts +185 -0
- package/src/builtins/plan-approval.workflow.ts +157 -24
- package/src/builtins/plan-change.workflow.ts +321 -0
- package/src/builtins/plan-presentation.ts +2 -2
- package/src/builtins/sanity-check.workflow.ts +248 -48
- package/src/controllers/effects.ts +7 -0
- package/src/controllers/index.ts +0 -6
- package/src/controllers/manager.ts +72 -32
- package/src/controllers/sqlite.ts +2420 -1948
- package/src/controllers/store.ts +17 -38
- package/src/controllers/types.ts +3 -0
- package/src/controllers/workflow-engine-scheduler.ts +4 -8
- package/src/controllers/workflows.ts +45 -21
- package/src/extension/controller-host.ts +1 -2
- package/src/extension/decision-channels.ts +456 -203
- package/src/extension/executor.ts +105 -2
- package/src/extension/herdr-viewer.ts +0 -5
- package/src/extension/index.ts +251 -151
- package/src/extension/recorder.ts +13 -22
- package/src/extension/session-events.ts +2 -2
- package/src/extension/step-message.ts +106 -4
- package/src/extension/widget.ts +32 -5
- package/src/host/rpc-executor.ts +4 -0
- package/src/host/runner.ts +93 -41
- package/src/render/graph-render.ts +12 -6
- package/src/state/database.ts +375 -0
- package/src/state/index.ts +29 -0
- package/src/state/json.ts +42 -0
- package/src/state/mutation.ts +435 -0
- package/src/state/schema.ts +475 -0
- package/src/viewer/cli.ts +151 -144
- package/src/viewer/render.ts +19 -30
- package/src/viewer/session-reducer.ts +1 -1
- package/src/viewer/tui.ts +18 -17
- package/src/viewer/watch.ts +13 -17
- package/src/workflows/catalog.ts +7 -2
- package/src/workflows/composition.ts +21 -3
- package/src/workflows/decision-presentation.ts +56 -43
- package/src/workflows/definition.ts +36 -3
- package/src/workflows/engine.ts +228 -130
- package/src/workflows/errors.ts +27 -3
- package/src/workflows/human-decision.ts +921 -349
- package/src/workflows/index.ts +20 -30
- package/src/workflows/progress.ts +18 -3
- package/src/workflows/schema.ts +36 -1
- package/src/workflows/store.ts +1300 -1163
- package/src/workflows/types.ts +100 -137
- package/dist/builtins/sanity-check-session.d.ts +0 -17
- package/dist/builtins/sanity-check-session.js +0 -168
- package/dist/builtins/sanity-check-session.js.map +0 -1
- package/dist/workflows/artifacts.d.ts +0 -40
- package/dist/workflows/artifacts.js +0 -155
- package/dist/workflows/artifacts.js.map +0 -1
- package/dist/workflows/migrate-sources.d.ts +0 -42
- package/dist/workflows/migrate-sources.js +0 -133
- package/dist/workflows/migrate-sources.js.map +0 -1
- package/docs/run-bundles.md +0 -481
- package/schemas/human-decision-accepted-v2.schema.json +0 -50
- package/schemas/human-decision-delivery-v2.schema.json +0 -36
- package/schemas/human-decision-receipt-v2.schema.json +0 -39
- package/schemas/human-decision-request-v2.schema.json +0 -69
- package/schemas/human-decision-resolution-v2.schema.json +0 -27
- package/src/builtins/sanity-check-session.ts +0 -205
- package/src/workflows/artifacts.ts +0 -188
- package/src/workflows/migrate-sources.ts +0 -178
package/docs/workflows.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
This document is the authoring reference for pi-workflows definitions. It
|
|
4
4
|
covers the file format, every node type, edge routing, the step contract the
|
|
5
|
-
model sees, and how runs behave at runtime. For
|
|
6
|
-
[
|
|
5
|
+
model sees, and how runs behave at runtime. For durable state, see
|
|
6
|
+
[SQLITE_STATE.md](SQLITE_STATE.md).
|
|
7
7
|
|
|
8
8
|
## Workflow files
|
|
9
9
|
|
|
@@ -15,8 +15,8 @@ Files are discovered by suffix (`.workflow.ts`, `.workflow.js`, `.workflow.mts`,
|
|
|
15
15
|
2. `~/.pi/agent/workflows/` globally
|
|
16
16
|
3. Workflows built into Pi Workflows
|
|
17
17
|
|
|
18
|
-
Pi Workflows includes built-in `
|
|
19
|
-
`plan-approval`, `sanity-check`, and `monitor` workflows. `autoplan` is the current name for the
|
|
18
|
+
Pi Workflows includes built-in `plain-summary`, `autoplan`, `autodoc`,
|
|
19
|
+
`autoimplement`, `plan-approval`, `sanity-check`, and `monitor` workflows. `autoplan` is the current name for the
|
|
20
20
|
planning workflow that was first released as `autodevise`; the old command and
|
|
21
21
|
export are not retained. A project or global file named `monitor.workflow.ts`
|
|
22
22
|
replaces the built-in monitor. The package registers each built-in in
|
|
@@ -105,11 +105,11 @@ Function actions receive `WorkflowActionContext`, which adds
|
|
|
105
105
|
|
|
106
106
|
Every interactive `/workflow` run is tracked in the project run queue (see
|
|
107
107
|
[CONTROLLERS.md](CONTROLLERS.md) for the store). The session that starts a run
|
|
108
|
-
claims it and owns it while it executes; every
|
|
108
|
+
claims it and owns it while it executes; every owner-only SQLite write proves the claim
|
|
109
109
|
first (write fencing).
|
|
110
110
|
|
|
111
111
|
Closing the Pi session mid-run no longer cancels the run. The engine **parks**:
|
|
112
|
-
it stops without a terminal event, releases the claim, and leaves the
|
|
112
|
+
it stops without a terminal event, releases the claim, and leaves the run
|
|
113
113
|
resumable. When a runner is available again (a reopened Pi session or the
|
|
114
114
|
standalone host), the run **resumes** at the node it stopped on. Completed
|
|
115
115
|
nodes replay from the recorded state; only the interrupted node and everything
|
|
@@ -124,9 +124,11 @@ pi-workflows host --project /path/to/project
|
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
The host claims parked runs, resumes them, and reconciles durable controllers.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
Agent nodes that submit through the workflow tool execute in headless
|
|
128
|
+
`pi --mode rpc` children that load a small bridge extension. An agent node with
|
|
129
|
+
`expectedOutput: assistantMessage()` parks before prompting and waits for the
|
|
130
|
+
origin Pi session because its result must be a visible assistant message. A
|
|
131
|
+
detached run without an origin session fails clearly. The host is a foreground process: start it in a terminal and
|
|
130
132
|
stop it with Ctrl-C. A second host for the same project refuses to start, and
|
|
131
133
|
a host that dies has its orphaned children reaped by the next one. While the host works, reports enter a durable outbox addressed to the Pi
|
|
132
134
|
session that started the run. They remain pending while that session is closed
|
|
@@ -136,8 +138,9 @@ and never enter another conversation in the same project.
|
|
|
136
138
|
|
|
137
139
|
### agent
|
|
138
140
|
|
|
139
|
-
Sends a prompt
|
|
140
|
-
|
|
141
|
+
Sends a prompt to the model. `expectedOutput` selects one of two output forms.
|
|
142
|
+
|
|
143
|
+
The existing string form waits for a `workflow submit` call:
|
|
141
144
|
|
|
142
145
|
```typescript
|
|
143
146
|
agent({
|
|
@@ -152,14 +155,28 @@ agent({
|
|
|
152
155
|
});
|
|
153
156
|
```
|
|
154
157
|
|
|
155
|
-
The
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
158
|
+
The assistant-message form waits for one normal visible response and uses its
|
|
159
|
+
exact text as the node output:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
agent({
|
|
163
|
+
prompt: ({ outputs }) => `Explain this plainly: ${JSON.stringify(outputs.review)}`,
|
|
164
|
+
expectedOutput: assistantMessage(),
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`assistantMessage()` has no default character limit. Authors can opt in with
|
|
169
|
+
`assistantMessage({ maxChars: 2_000 })`. It cannot be combined with `validate`
|
|
170
|
+
because an invalid response is already visible and must not be retried.
|
|
171
|
+
|
|
172
|
+
For submitted output, the engine appends the existing workflow-tool contract.
|
|
173
|
+
The output passes through tolerant JSON normalization and then `validate`.
|
|
174
|
+
Rejected submissions can retry in the same step. If the model settles without
|
|
175
|
+
submitting, the extension nudges it twice by default and then fails the step.
|
|
176
|
+
For assistant-message output, the engine appends a normal-response contract,
|
|
177
|
+
waits for `agent_settled`, rejects empty, failed, aborted, or tool-only results,
|
|
178
|
+
and never suppresses the visible text. Timeout and cancellation abort either
|
|
179
|
+
form's active Pi turn.
|
|
163
180
|
|
|
164
181
|
`timeoutMs` can be a finite positive number, `null`, or a function of the normal
|
|
165
182
|
node context that returns either value. Omit it to use the 15-minute engine
|
|
@@ -259,10 +276,10 @@ schema, limits, estimation, and error rules.
|
|
|
259
276
|
|
|
260
277
|
### checkpoint
|
|
261
278
|
|
|
262
|
-
Ends the run in a `waiting` state for human review. The checkpoint
|
|
279
|
+
Ends the run in a `waiting` state for human review. The checkpoint run is
|
|
263
280
|
terminal, so no process keeps running while the run waits. The human answers
|
|
264
281
|
with `/workflow answer <json>` (or plain text), which starts a **continuation
|
|
265
|
-
run**: a new run with its own
|
|
282
|
+
run**: a new run with its own state and events, linked to the checkpointed run
|
|
266
283
|
through `parentRunId`. The continuation receives the answer as its input,
|
|
267
284
|
carries forward every output the parent produced (including the checkpoint's),
|
|
268
285
|
and continues routing along the checkpoint's outgoing edge. Outgoing edges
|
|
@@ -291,6 +308,10 @@ const choices = defineHumanChoices({
|
|
|
291
308
|
humanDecision({
|
|
292
309
|
audience: "operator",
|
|
293
310
|
choices,
|
|
311
|
+
onTimeout: {
|
|
312
|
+
afterMs: 10 * 60_000,
|
|
313
|
+
response: { choice: "continue" },
|
|
314
|
+
},
|
|
294
315
|
request: ({ outputs }) => ({
|
|
295
316
|
title: "Approve plan",
|
|
296
317
|
subject: outputs.plan,
|
|
@@ -303,7 +324,7 @@ humanDecision({
|
|
|
303
324
|
});
|
|
304
325
|
```
|
|
305
326
|
|
|
306
|
-
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, and
|
|
327
|
+
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, recovery applies the validated response with `timeout` provenance. 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. Existing `body` requests remain a legacy compatibility form and use deterministic readable formatting.
|
|
307
328
|
|
|
308
329
|
The model-facing workflow tool cannot answer a protected human decision. Pi interactive UI and configured external channels use a host-owned answer path. Ordinary checkpoints keep the existing `/workflow answer` behavior.
|
|
309
330
|
|
|
@@ -413,11 +434,33 @@ The normal extension offers all actions. The headless RPC bridge offers only
|
|
|
413
434
|
`update` and `submit`, so a workflow child cannot recursively control other
|
|
414
435
|
runs.
|
|
415
436
|
|
|
437
|
+
### Built-in plain summary
|
|
438
|
+
|
|
439
|
+
The built-in `plain-summary` workflow turns supplied structured data into one
|
|
440
|
+
short normal assistant message. Its input has `source`, `purpose`, optional
|
|
441
|
+
`mustInclude`, optional `maxChars`, optional `maxSentences`, and `format` set to
|
|
442
|
+
`paragraphs`, `bullets`, or `mixed`. The workflow defaults to 2,000 characters,
|
|
443
|
+
five sentences, and mixed format. These are workflow-specific limits;
|
|
444
|
+
`assistantMessage()` itself has no default limit.
|
|
445
|
+
|
|
446
|
+
The summarizer uses only the supplied source, treats instructions inside that
|
|
447
|
+
source as data, keeps required points, and returns the same text as its
|
|
448
|
+
`completed` result. The source enters the normal model prompt and Pi session,
|
|
449
|
+
so callers must pass only data that is suitable for that conversation. It has no notify node or final presentation prompt, so
|
|
450
|
+
including it in another workflow produces one readable assistant response
|
|
451
|
+
before the parent continues.
|
|
452
|
+
|
|
416
453
|
### Built-in planning and implementation
|
|
417
454
|
|
|
418
|
-
The built-in `autoplan` workflow
|
|
455
|
+
The built-in `autoplan` workflow records two through four practical candidates,
|
|
456
|
+
describes the ideal separately, chooses one option, records a rejection reason
|
|
457
|
+
for every other explicit option, and writes a detailed plan. It then includes
|
|
458
|
+
`plain-summary` to show the chosen plan, its main steps, and the rejected options
|
|
459
|
+
in one short assistant message. The detailed records remain in the run bundle. The standalone `autodoc` workflow finds an already selected plan, records it in canonical documentation, verifies those documents, and never devises or implements. The built-in `autoimplement` workflow finds a clear existing plan from explicit input, conversation context, or referenced canonical documents. It blocks when no clear plan exists. An explicit plan bypasses autodoc only when a current-document receipt carries its matching plan digest; otherwise autodoc inspects and adopts or updates the canonical documents. Later invalidating evidence returns to `autoplan` followed by `autodoc`.
|
|
419
460
|
|
|
420
|
-
The built-in `plan-approval` workflow offers
|
|
461
|
+
The built-in `plan-approval` workflow offers `continue`, `stop`, and exact-text `replan` exits. Its shared policy uses `auto`, `required`, or `skip` mode. Omitted policy defaults to `auto`: ask audience `operator`, then continue with the exact plan after 10 minutes without an answer. Required mode waits for a human. Skip mode creates no decision. Stop and replan always require a human answer.
|
|
462
|
+
|
|
463
|
+
The internal plan-change workflow composes Autoplan, Autodoc, plan approval, and bounded replanning. Autoimplement and Monitor use it whenever they create or change a plan. Existing supplied or discovered plans bypass the gate. A plan selected by Monitor enters Autoimplement without another decision for the same digest.
|
|
421
464
|
|
|
422
465
|
Autoimplement runs independent commands through bounded command batches. A batch is an ordinary function action that calls the public `runCommandBatch` helper. Each command has a stable ID, executable, arguments, absolute working directory, timeout, and output limit. Results stay separate and return in input order. One command uses the same path with concurrency one.
|
|
423
466
|
|
|
@@ -436,7 +479,7 @@ Autoimplement uses batches for pi-reviewer, pending CI watches, and local verifi
|
|
|
436
479
|
|
|
437
480
|
Autoimplement inspects every pull request before it waits for CI. It accepts only supported pending `gh pr checks --watch` or `gh run watch` descriptors and binds each one to the validated pull request as `gh pr checks <PR URL> --watch`. Repository and pull-request overrides are rejected. One watch lasts at most five minutes. A failed or timed-out watch affects only its pull request. When checks remain pending, the model runs more useful local tests before checking CI again. Autoimplement does not invent an ETA.
|
|
438
481
|
|
|
439
|
-
The action abort signal stops active command process groups and prevents queued commands from starting. Accepted outputs use
|
|
482
|
+
The action abort signal stops active command process groups and prevents queued commands from starting. Accepted outputs use immutable events and content-addressed blobs. An interrupted unaccepted batch runs again because batch commands are read-only or isolated local checks. Progress updates contain metadata only and never control routing. Truncated reviewer or CI output cannot count as clean. See [Run independent commands in bounded batches](plans/2026-08-20-bounded-command-batches-plan.md) for the complete contract and implementation plan.
|
|
440
483
|
|
|
441
484
|
A model-generated blocker from implementation or a safe later stage does not end autoimplement by itself. A separate blocker-challenge agent checks the task, approved plan, current result, evidence, scope, authority, earlier attempts, and practical alternatives. It confirms a blocker only when the blocker exists now, is outside the granted authority, has no safe path forward, has an empty next action, and includes concrete evidence and checked alternatives. A rejected blocker must name the next practical action and routes through the existing redesign workflow before implementation and verification continue.
|
|
442
485
|
|
|
@@ -453,44 +496,69 @@ The built-in `sanity-check` workflow reviews a pull request or local contributio
|
|
|
453
496
|
}
|
|
454
497
|
```
|
|
455
498
|
|
|
456
|
-
Serial mode is the default. It runs one
|
|
499
|
+
Serial mode is the default. It runs one review session for all four review areas, then one verification session. Parallel mode runs four focused review sessions at the same time, then one verification session. Serial mode uses two model sessions. Parallel mode uses five. When `baseRef` is omitted, the workflow tries the remote default branch, the current branch upstream, and the first parent, then uses `HEAD` for a working-tree-only review.
|
|
500
|
+
|
|
501
|
+
The workflow collects pull request intent and repository diff evidence before model review. It bounds evidence and review results before prompt construction and marks truncated input. Every review must cite evidence and give the strongest case for accepting the current design. The verification session removes unsupported claims, requires exact file and symbol references, resolves supported conflicts, and returns `keep`, `simplify`, `refactor`, `drop`, or `needs_evidence`.
|
|
502
|
+
|
|
503
|
+
Sanity Check revision 4 creates child sessions directly through the documented Pi SDK. A private built-in runner uses `createAgentSession` with `SessionManager.inMemory`, one independent context per child, and only the verified built-in `read`, `grep`, `find`, and `ls` tools. Child sessions load no skills, prompt templates, themes, or context files. They create no Pi session file.
|
|
504
|
+
|
|
505
|
+
The parent Pi process keeps its normal configured extensions enabled. The child runner resolves enabled user extension paths, excludes Pi Workflows and project extensions by default, and preflights the remaining paths without creating a session. It admits only the extension that registers the exact configured provider, plus any behavior extension on an explicit private allowlist. It rejects competing provider owners, workflow tools or commands, and extensions that replace a built-in read-only tool. The admitted paths are frozen for the group, and each child loads only those explicit paths without a second discovery pass.
|
|
506
|
+
|
|
507
|
+
Each child owns a separate `ModelRuntime`, provider instance, extension runtime, resource loader, and in-memory session. The runner loads validated model and ordinary credential snapshots into per-child in-memory stores without writing them back. A provider extension uses its existing provider-owned credential store in place; Pi Workflows does not copy, print, migrate, or persist those credentials.
|
|
508
|
+
|
|
509
|
+
A complete explicit provider, model, and thinking override wins. Otherwise, the runner uses the configured process defaults. It passes the exact cached model and thinking level to the child, then verifies the actual provider, model, thinking level, authentication, extension state, active tools, and tool sources before prompting. A missing or different dispatch is terminal. The runner never silently falls back to OpenRouter, Kimi, a local model, or another provider or model. It does not promise to inherit a model selected temporarily in the origin Pi TUI.
|
|
457
510
|
|
|
458
|
-
|
|
511
|
+
Children do not receive the `workflow` tool, workflow commands, parent run identifiers, update channels, or workflow callbacks. Prompts that invoke extension slash commands are rejected. The parent Sanity Check action remains the only workflow owner. These controls block normal child model and extension bindings from inspecting or changing workflow state. Extensions still run as trusted code in the parent Node process, so this is not an OS sandbox against direct filesystem or network access.
|
|
459
512
|
|
|
460
|
-
|
|
513
|
+
Only bounded final assistant text and safe operational facts leave a live child session. Pi Workflows does not persist child prompts, reasoning, intermediate messages, tool arguments, tool results, message history, credentials, or extension-private state. Timeout and cancellation abort and settle active work before the runner disposes the session, shuts down extensions, and releases provider resources.
|
|
514
|
+
|
|
515
|
+
The workflow publishes aggregate and per-agent `pi-workflows.progress.v1` tracks under `agents/review/*` and `agents/verification/*`. Progress contains role, the verified actual model when known, state, elapsed facts, and safe phases such as `thinking` or `tool: read`. The Pi widget shows the aggregate plus failed and active children within its ten-line limit. `piw` shows every durable child track and its samples. Both views use existing progress records, so no child workflow run or new persisted schema is needed.
|
|
516
|
+
|
|
517
|
+
Serial mode still uses two child sessions, and parallel mode still uses five. Review prompts, review areas, strict result validation, verdicts, and progress stay unchanged. After verification, an assistant-message agent shows the full bounded report verbatim. A mismatch stops before summary generation. The graph then includes `plain-summary`, which shows a short plain-language explanation with the verdict and the most important next action. The detailed response always settles before the summary starts. A final compute node returns the original strict result, so presentation cannot change the verdict. Sanity Check uses no final notification or root `presentationPrompt`.
|
|
518
|
+
|
|
519
|
+
The CLI, JSON or RPC stream, temporary prompt file, standard-output cap, subprocess fallback, shared child runtime, and blanket child-extension ban are not retained. See [the Sanity Check plan](plans/2026-08-21-sanity-check-plan.md) for the selected implementation and test boundaries.
|
|
461
520
|
|
|
462
521
|
### Built-in monitor
|
|
463
522
|
|
|
464
|
-
The built-in `monitor` workflow turns a plain request
|
|
465
|
-
one looping workflow run.
|
|
523
|
+
The built-in `monitor` workflow turns a plain request to finish and monitor an
|
|
524
|
+
authorized goal into one looping workflow run. It accepts only `task`,
|
|
525
|
+
`stopWhen`, `everyMinutes`, and `maxChecks`:
|
|
466
526
|
|
|
467
527
|
```json
|
|
468
528
|
{
|
|
469
|
-
"task": "
|
|
470
|
-
"stopWhen": "The pull request is merged or
|
|
471
|
-
"
|
|
472
|
-
"authorized": true,
|
|
473
|
-
"scope": "the current repository"
|
|
474
|
-
}
|
|
529
|
+
"task": "Finish pull request 123 within the recorded repository and delivery authority.",
|
|
530
|
+
"stopWhen": "The pull request is merged or safe continuation is blocked.",
|
|
531
|
+
"everyMinutes": 30
|
|
475
532
|
}
|
|
476
533
|
```
|
|
477
534
|
|
|
478
|
-
The first
|
|
535
|
+
The first `observe` step runs immediately and is read-only. It inspects the real
|
|
536
|
+
target with normal tools and chooses `wait`, `act`, or `stop`. `wait` means that
|
|
537
|
+
useful target work is moving or an external event must finish. `act` states one
|
|
538
|
+
safe action that existing authority permits. `stop` means that the goal is
|
|
539
|
+
complete or cannot continue safely.
|
|
479
540
|
|
|
480
|
-
`
|
|
541
|
+
An `advance` or `recover` action runs directly in a separate normal-tools step.
|
|
542
|
+
A `repair` action composes the shared plan-change workflow and Autoimplement.
|
|
543
|
+
Monitor observes again immediately after every action. It stops instead of
|
|
544
|
+
repeating a completed repair when the same stable failure and target state
|
|
545
|
+
return. The timer is reachable only from `wait`.
|
|
546
|
+
|
|
547
|
+
`everyMinutes` defaults to 30. Every accepted observation provides one concise
|
|
548
|
+
report that separates Monitor state, goal state, and target work state. The
|
|
481
549
|
runtime queues that report as a workflow notification with `triggerTurn:
|
|
482
|
-
false`, so it does not cause an assistant reply.
|
|
483
|
-
independent progress tracks. The regular Pi model
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
550
|
+
false`, so it does not cause an assistant reply. An observation can also provide
|
|
551
|
+
independent progress tracks. The regular Pi model observes the target and
|
|
552
|
+
submits those facts. Pi Workflows validates counts and calculates rates,
|
|
553
|
+
confidence, and ETA deterministically. The target does not need a Pi Workflows
|
|
554
|
+
dependency or reporting protocol.
|
|
487
555
|
|
|
488
556
|
Intervals must be whole minutes from 1 through 1,440. When `stopWhen` is
|
|
489
557
|
omitted, the monitor stops only after an explicit user request. `maxChecks`
|
|
490
|
-
defaults to the disclosed safety
|
|
491
|
-
omit `maxChecks` unless the user requests a fixed count.
|
|
492
|
-
|
|
493
|
-
|
|
558
|
+
defaults to the disclosed observation safety limit of 1,000 and cannot exceed
|
|
559
|
+
it. Callers omit `maxChecks` unless the user requests a fixed count. Unknown
|
|
560
|
+
fields fail before a run is created. See [MONITOR.md](MONITOR.md) for the
|
|
561
|
+
observation, action, and progress schemas.
|
|
494
562
|
|
|
495
563
|
The interval uses the existing shell action to launch the current Node
|
|
496
564
|
executable with a timer. This works on every platform supported by Pi. The node
|
|
@@ -539,8 +607,8 @@ and [Deferred workflow turns](DEFERRED_TURNS.md) for the successor-turn contract
|
|
|
539
607
|
|
|
540
608
|
## Result presentation
|
|
541
609
|
|
|
542
|
-
Workflow nodes produce structured
|
|
543
|
-
person should see a normal prose response after the run, add
|
|
610
|
+
Workflow nodes normally produce structured values for routing and persistence.
|
|
611
|
+
When a person should see a normal prose response only after the root run, add
|
|
544
612
|
`presentationPrompt` at the top level:
|
|
545
613
|
|
|
546
614
|
```typescript
|
|
@@ -568,8 +636,14 @@ or normal user turn starts; stale presentations are discarded. Once a presentati
|
|
|
568
636
|
been queued, another workflow cannot start until that assistant response
|
|
569
637
|
settles, so results cannot interleave.
|
|
570
638
|
|
|
639
|
+
An agent with `expectedOutput: assistantMessage()` is different. Its visible
|
|
640
|
+
assistant response is the node output, can appear before later nodes, and also
|
|
641
|
+
works inside an included workflow. A root `presentationPrompt` would add a
|
|
642
|
+
second response, so workflows that end with assistant-message output normally
|
|
643
|
+
omit it.
|
|
644
|
+
|
|
571
645
|
Presentation is outside the workflow graph: it cannot route to another node,
|
|
572
|
-
change the run status, or alter the run
|
|
646
|
+
change the run status, or alter the SQLite run state. If prompt generation or message
|
|
573
647
|
delivery fails, the extension reports a warning and leaves the finished run
|
|
574
648
|
unchanged. Opting in adds one hidden custom message and one assistant response
|
|
575
649
|
to the normal Pi session; it adds no other persistent data and uses no Pi
|
|
@@ -578,7 +652,7 @@ internals.
|
|
|
578
652
|
## Runtime behavior
|
|
579
653
|
|
|
580
654
|
Runs execute one node at a time. Every transition is persisted to the run
|
|
581
|
-
|
|
655
|
+
database transaction before the engine moves on, which is what makes the live viewer
|
|
582
656
|
possible. Defaults worth knowing:
|
|
583
657
|
|
|
584
658
|
- Node timeout is 15 minutes unless the node sets `timeoutMs` to a positive
|
|
@@ -597,7 +671,7 @@ possible. Defaults worth knowing:
|
|
|
597
671
|
`/workflow resume` re-delivers the pending step prompt.
|
|
598
672
|
- A model-started workflow is persisted as `queued` with its final run ID before the start tool
|
|
599
673
|
returns. Activation waits for the initiating agent turn to settle, then moves through `starting`
|
|
600
|
-
and `running`. `workflow status` and `workflow cancel` accept the run ID before a run
|
|
674
|
+
and `running`. `workflow status` and `workflow cancel` accept the run ID before a SQLite run state
|
|
601
675
|
exists.
|
|
602
676
|
- If deferred activation fails, the queue stores a bounded safe error, releases the session
|
|
603
677
|
reservation, and creates one deferred-turn intent for the initiating session. A workflow that
|
|
@@ -637,7 +711,7 @@ if (run.state !== "succeeded") {
|
|
|
637
711
|
}
|
|
638
712
|
```
|
|
639
713
|
|
|
640
|
-
Child workflow completion queues the parent resource again. A running child left by a stopped host is recorded as a failed run
|
|
714
|
+
Child workflow completion queues the parent resource again. A running child left by a stopped host is recorded as a failed SQLite run state with a `run_interrupted` event. The controller treats that child attempt as interrupted, and the next parent reconciliation starts another immutable attempt. Consequential external mutations should use the controller effect API so uncertain results are observed before retry.
|
|
641
715
|
|
|
642
716
|
See [CONTROLLERS.md](CONTROLLERS.md) for controller definitions and the full recovery contract.
|
|
643
717
|
|
|
@@ -1,58 +1,31 @@
|
|
|
1
|
-
import { compute, defineWorkflow, includeWorkflow
|
|
2
|
-
import
|
|
3
|
-
import autoplan from "../../src/builtins/autoplan.workflow.js";
|
|
4
|
-
import planApproval from "../../src/builtins/plan-approval.workflow.js";
|
|
1
|
+
import { compute, defineWorkflow, includeWorkflow } from "@osolmaz/pi-workflows";
|
|
2
|
+
import planChange from "../../src/builtins/plan-change.workflow.js";
|
|
5
3
|
|
|
6
4
|
export default defineWorkflow({
|
|
7
5
|
name: "approved-plan-example",
|
|
8
|
-
startAt: "
|
|
9
|
-
maxSteps:
|
|
6
|
+
startAt: "start",
|
|
7
|
+
maxSteps: 100,
|
|
10
8
|
includes: {
|
|
11
|
-
|
|
12
|
-
input: ({ input
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
| undefined;
|
|
17
|
-
return {
|
|
18
|
-
problem: (input as { task: string }).task,
|
|
19
|
-
...(prior?.exit === "ready" ? { previousPlan: prior.output?.plan } : {}),
|
|
20
|
-
...(answer?.exit === "replan" ? { newEvidence: answer.output?.instructions } : {}),
|
|
21
|
-
};
|
|
22
|
-
},
|
|
23
|
-
}),
|
|
24
|
-
documentation: includeWorkflow(autodoc, {
|
|
25
|
-
input: ({ input, outputs }) => {
|
|
26
|
-
const result = includedResult(autoplan, outputs.design);
|
|
27
|
-
if (result.exit !== "ready") throw new Error("design is not ready");
|
|
28
|
-
return { task: (input as { task: string }).task, plan: result.output.plan };
|
|
29
|
-
},
|
|
30
|
-
}),
|
|
31
|
-
approval: includeWorkflow(planApproval, {
|
|
32
|
-
input: ({ input, outputs }) => {
|
|
33
|
-
const result = includedResult(autodoc, outputs.documentation);
|
|
34
|
-
if (result.exit !== "ready") throw new Error("documentation is not ready");
|
|
35
|
-
return {
|
|
36
|
-
task: (input as { task: string }).task,
|
|
37
|
-
plan: result.output.plan,
|
|
38
|
-
planDigest: result.output.planDigest,
|
|
9
|
+
planChange: includeWorkflow(planChange, {
|
|
10
|
+
input: ({ input }) => ({
|
|
11
|
+
task: (input as { task: string }).task,
|
|
12
|
+
approval: {
|
|
13
|
+
mode: "auto" as const,
|
|
39
14
|
audience: "operator",
|
|
40
|
-
|
|
41
|
-
|
|
15
|
+
timeoutMinutes: 10,
|
|
16
|
+
maxReplans: 3,
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
42
19
|
}),
|
|
43
20
|
},
|
|
44
21
|
nodes: {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
blocked: compute({ run: ({ outputs }) => ({ status: "blocked", outputs }) }),
|
|
22
|
+
start: compute({ run: () => ({ route: "plan" }) }),
|
|
23
|
+
done: compute({ run: ({ outputs }) => ({ status: "ready", plan: outputs.planChange }) }),
|
|
24
|
+
blocked: compute({ run: ({ outputs }) => ({ status: "blocked", plan: outputs.planChange }) }),
|
|
48
25
|
},
|
|
49
26
|
edges: [
|
|
50
|
-
{ from: "
|
|
51
|
-
{ from: "
|
|
52
|
-
{ from: "
|
|
53
|
-
{ from: "documentation.blocked", to: "blocked" },
|
|
54
|
-
{ from: "approval.continue", to: "done" },
|
|
55
|
-
{ from: "approval.stop", to: "stopped" },
|
|
56
|
-
{ from: "approval.replan", to: "design" },
|
|
27
|
+
{ from: "start", to: "planChange" },
|
|
28
|
+
{ from: "planChange.ready", to: "done" },
|
|
29
|
+
{ from: "planChange.blocked", to: "blocked" },
|
|
57
30
|
],
|
|
58
31
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { plainSummaryWorkflow as default } from "@osolmaz/pi-workflows/builtins";
|
package/herdr-plugin.toml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osolmaz/pi-workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Workflow and controller runtime with a live terminal viewer for the pi coding agent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
"jiti": "^2.7.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@earendil-works/pi-ai": "
|
|
73
|
-
"@earendil-works/pi-coding-agent": "
|
|
74
|
-
"@earendil-works/pi-tui": "
|
|
72
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
73
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
74
|
+
"@earendil-works/pi-tui": "0.84.2",
|
|
75
75
|
"@types/better-sqlite3": "^7.6.13",
|
|
76
76
|
"@types/node": "^26.1.1",
|
|
77
77
|
"@vitest/coverage-istanbul": "^4.1.10",
|
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
"vitest": "^4.1.10"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
|
-
"@earendil-works/pi-ai": "
|
|
87
|
-
"@earendil-works/pi-coding-agent": "
|
|
88
|
-
"@earendil-works/pi-tui": "
|
|
86
|
+
"@earendil-works/pi-ai": ">=0.84.2 <0.85.0",
|
|
87
|
+
"@earendil-works/pi-coding-agent": ">=0.84.2 <0.85.0",
|
|
88
|
+
"@earendil-works/pi-tui": ">=0.84.2 <0.85.0",
|
|
89
89
|
"typebox": "*"
|
|
90
90
|
},
|
|
91
91
|
"engines": {
|
package/plugins/herdr/viewer.mjs
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { spawn, spawnSync } from "node:child_process";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import path from "node:path";
|
|
6
4
|
|
|
7
5
|
const runId = process.env.PI_WORKFLOWS_RUN_ID ?? "";
|
|
8
|
-
const runDir = process.env.PI_WORKFLOWS_RUN_DIR ?? "";
|
|
9
6
|
|
|
10
7
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/u.test(runId)) {
|
|
11
8
|
fail("PI_WORKFLOWS_RUN_ID is missing or invalid.");
|
|
12
9
|
}
|
|
13
|
-
if (!path.isAbsolute(runDir) || path.basename(runDir) !== runId) {
|
|
14
|
-
fail("PI_WORKFLOWS_RUN_DIR must be the absolute bundle directory for the selected run.");
|
|
15
|
-
}
|
|
16
|
-
if (!fs.existsSync(path.join(runDir, "manifest.json"))) {
|
|
17
|
-
fail(`Workflow bundle not found: ${runDir}`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
10
|
const paneId = process.env.HERDR_PANE_ID ?? "";
|
|
21
11
|
if (!/^[A-Za-z0-9]+:p[A-Za-z0-9]+$/u.test(paneId)) {
|
|
22
12
|
fail("HERDR_PANE_ID is missing or invalid.");
|
|
@@ -33,7 +23,7 @@ if (labeled.status !== 0) {
|
|
|
33
23
|
fail(`Could not label the Herdr viewer pane: ${bounded(labeled.stderr) || "unknown error"}`);
|
|
34
24
|
}
|
|
35
25
|
|
|
36
|
-
const viewer = spawn("piw", [
|
|
26
|
+
const viewer = spawn("piw", [runId], { stdio: "inherit" });
|
|
37
27
|
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
38
28
|
process.on(signal, () => viewer.kill(signal));
|
|
39
29
|
}
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
"schema",
|
|
9
9
|
"decisionId",
|
|
10
10
|
"requestDigest",
|
|
11
|
+
"subjectDigest",
|
|
12
|
+
"presentationDigest",
|
|
13
|
+
"revision",
|
|
11
14
|
"response",
|
|
12
|
-
"
|
|
13
|
-
"idempotencyKey",
|
|
15
|
+
"provenance",
|
|
14
16
|
"acceptedAt",
|
|
15
17
|
"answerDigest"
|
|
16
18
|
],
|
|
@@ -18,6 +20,9 @@
|
|
|
18
20
|
"schema": { "const": "pi-workflows.human-decision-accepted.v1" },
|
|
19
21
|
"decisionId": { "type": "string" },
|
|
20
22
|
"requestDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
23
|
+
"subjectDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
24
|
+
"presentationDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
25
|
+
"revision": { "type": "integer", "minimum": 1 },
|
|
21
26
|
"response": {
|
|
22
27
|
"type": "object",
|
|
23
28
|
"additionalProperties": false,
|
|
@@ -27,6 +32,7 @@
|
|
|
27
32
|
"input": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
28
33
|
}
|
|
29
34
|
},
|
|
35
|
+
"provenance": { "enum": ["human", "timeout"] },
|
|
30
36
|
"source": {
|
|
31
37
|
"type": "object",
|
|
32
38
|
"additionalProperties": false,
|
|
@@ -40,5 +46,11 @@
|
|
|
40
46
|
"idempotencyKey": { "type": "string" },
|
|
41
47
|
"acceptedAt": { "type": "string", "format": "date-time" },
|
|
42
48
|
"answerDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }
|
|
43
|
-
}
|
|
49
|
+
},
|
|
50
|
+
"allOf": [
|
|
51
|
+
{
|
|
52
|
+
"if": { "properties": { "provenance": { "const": "human" } } },
|
|
53
|
+
"then": { "required": ["source", "idempotencyKey"] }
|
|
54
|
+
}
|
|
55
|
+
]
|
|
44
56
|
}
|
|
@@ -4,11 +4,20 @@
|
|
|
4
4
|
"title": "pi-workflows human decision continuation v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"schema",
|
|
9
|
+
"decisionId",
|
|
10
|
+
"requestDigest",
|
|
11
|
+
"provenance",
|
|
12
|
+
"parentRunId",
|
|
13
|
+
"runId",
|
|
14
|
+
"createdAt"
|
|
15
|
+
],
|
|
8
16
|
"properties": {
|
|
9
17
|
"schema": { "const": "pi-workflows.human-decision-continuation.v1" },
|
|
10
18
|
"decisionId": { "type": "string" },
|
|
11
19
|
"requestDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
20
|
+
"provenance": { "enum": ["human", "timeout"] },
|
|
12
21
|
"parentRunId": { "type": "string" },
|
|
13
22
|
"runId": { "type": "string" },
|
|
14
23
|
"createdAt": { "type": "string", "format": "date-time" }
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
"attemptId",
|
|
10
10
|
"decisionId",
|
|
11
11
|
"requestDigest",
|
|
12
|
+
"presentationDigest",
|
|
12
13
|
"channel",
|
|
14
|
+
"phase",
|
|
13
15
|
"state",
|
|
14
16
|
"createdAt"
|
|
15
17
|
],
|
|
@@ -18,10 +20,16 @@
|
|
|
18
20
|
"attemptId": { "type": "string" },
|
|
19
21
|
"decisionId": { "type": "string" },
|
|
20
22
|
"requestDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
23
|
+
"presentationDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
21
24
|
"channel": { "type": "string" },
|
|
25
|
+
"phase": { "enum": ["intent", "part", "complete"] },
|
|
22
26
|
"state": { "enum": ["intent", "confirmed", "failed", "unknown"] },
|
|
23
27
|
"createdAt": { "type": "string", "format": "date-time" },
|
|
24
28
|
"finishedAt": { "type": "string", "format": "date-time" },
|
|
29
|
+
"recipientIndex": { "type": "integer", "minimum": 1 },
|
|
30
|
+
"partIndex": { "type": "integer", "minimum": 1 },
|
|
31
|
+
"partCount": { "type": "integer", "minimum": 1, "maximum": 20 },
|
|
32
|
+
"contentDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
25
33
|
"messageCount": { "type": "integer", "minimum": 0 },
|
|
26
34
|
"errorCode": { "type": "string" }
|
|
27
35
|
}
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
"schema",
|
|
9
9
|
"decisionId",
|
|
10
10
|
"requestDigest",
|
|
11
|
+
"subjectDigest",
|
|
12
|
+
"presentationDigest",
|
|
13
|
+
"revision",
|
|
11
14
|
"nodeId",
|
|
12
15
|
"response",
|
|
16
|
+
"provenance",
|
|
13
17
|
"acceptedAt",
|
|
14
18
|
"answerDigest"
|
|
15
19
|
],
|
|
@@ -17,6 +21,9 @@
|
|
|
17
21
|
"schema": { "const": "pi-workflows.human-decision-receipt.v1" },
|
|
18
22
|
"decisionId": { "type": "string" },
|
|
19
23
|
"requestDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
24
|
+
"subjectDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
25
|
+
"presentationDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
26
|
+
"revision": { "type": "integer", "minimum": 1 },
|
|
20
27
|
"nodeId": { "type": "string" },
|
|
21
28
|
"response": {
|
|
22
29
|
"type": "object",
|
|
@@ -27,6 +34,7 @@
|
|
|
27
34
|
"input": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
28
35
|
}
|
|
29
36
|
},
|
|
37
|
+
"provenance": { "enum": ["human", "timeout"] },
|
|
30
38
|
"acceptedAt": { "type": "string", "format": "date-time" },
|
|
31
39
|
"answerDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }
|
|
32
40
|
}
|