@osolmaz/pi-workflows 0.11.2 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -10
- package/dist/builtins/autoimplement-command-batches.d.ts +52 -0
- package/dist/builtins/autoimplement-command-batches.js +258 -0
- package/dist/builtins/autoimplement-command-batches.js.map +1 -0
- package/dist/builtins/autoimplement.workflow.d.ts +509 -124
- package/dist/builtins/autoimplement.workflow.js +884 -327
- package/dist/builtins/autoimplement.workflow.js.map +1 -1
- package/dist/builtins/catalog.js +5 -3
- package/dist/builtins/catalog.js.map +1 -1
- package/dist/builtins/index.d.ts +4 -1
- package/dist/builtins/index.js +3 -1
- package/dist/builtins/index.js.map +1 -1
- package/dist/builtins/monitor.workflow.d.ts +2 -4
- package/dist/builtins/monitor.workflow.js +26 -128
- 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/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 +301 -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 +85 -0
- package/dist/builtins/sanity-check.workflow.js +482 -0
- package/dist/builtins/sanity-check.workflow.js.map +1 -0
- package/dist/controllers/sqlite.d.ts +90 -2
- package/dist/controllers/sqlite.js +380 -5
- package/dist/controllers/sqlite.js.map +1 -1
- package/dist/extension/decision-channels.d.ts +2 -2
- package/dist/extension/decision-channels.js +29 -35
- package/dist/extension/decision-channels.js.map +1 -1
- package/dist/extension/deferred-turn-coordinator.d.ts +32 -0
- package/dist/extension/deferred-turn-coordinator.js +143 -0
- package/dist/extension/deferred-turn-coordinator.js.map +1 -0
- package/dist/extension/deferred-turn.d.ts +44 -0
- package/dist/extension/deferred-turn.js +110 -0
- package/dist/extension/deferred-turn.js.map +1 -0
- package/dist/extension/index.js +348 -80
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/session-events.d.ts +2 -2
- package/dist/extension/step-message.d.ts +1 -0
- package/dist/extension/step-message.js.map +1 -1
- package/dist/extension/widget.js +23 -3
- package/dist/extension/widget.js.map +1 -1
- package/dist/herdr/setup.js +4 -4
- package/dist/render/graph-render.js +1 -2
- package/dist/render/graph-render.js.map +1 -1
- package/dist/viewer/render.js +7 -6
- package/dist/viewer/render.js.map +1 -1
- package/dist/workflows/catalog.js +7 -2
- package/dist/workflows/catalog.js.map +1 -1
- package/dist/workflows/command-batch.d.ts +38 -0
- package/dist/workflows/command-batch.js +176 -0
- package/dist/workflows/command-batch.js.map +1 -0
- package/dist/workflows/composition.js +8 -0
- 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/engine.d.ts +2 -2
- package/dist/workflows/engine.js +22 -17
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/errors.d.ts +13 -0
- package/dist/workflows/errors.js +15 -0
- package/dist/workflows/errors.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +16 -4
- package/dist/workflows/human-decision.js +175 -72
- package/dist/workflows/human-decision.js.map +1 -1
- package/dist/workflows/index.d.ts +3 -2
- package/dist/workflows/index.js +2 -1
- 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 +12 -1
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/shell.d.ts +4 -0
- package/dist/workflows/shell.js +6 -0
- package/dist/workflows/shell.js.map +1 -1
- package/dist/workflows/store.js +8 -1
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +37 -48
- package/docs/2026-08-18-herdr-piw-plan.md +1 -1
- package/docs/2026-08-20-durable-workflow-launch-plan.md +19 -23
- package/docs/CONTROLLERS.md +2 -2
- package/docs/DEFERRED_TURNS.md +298 -0
- package/docs/DESIGN_PHILOSOPHY.md +1 -1
- package/docs/HUMAN_DECISIONS.md +30 -40
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +17 -27
- package/docs/MONITOR.md +7 -13
- package/docs/WORKFLOW_COMPOSITION.md +10 -9
- package/docs/WORKFLOW_STEP_MESSAGES.md +5 -5
- package/docs/WORKFLOW_UPDATES.md +28 -5
- package/docs/plans/2026-08-04-controller-runtime-plan.md +1 -1
- package/docs/plans/2026-08-05-always-on-workflows-plan.md +1 -1
- package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +9 -9
- package/docs/plans/2026-08-13-built-in-workflow-catalog-plan.md +1 -1
- package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
- package/docs/plans/2026-08-16-workflow-updates-plan.md +3 -3
- package/docs/plans/2026-08-17-bundled-skills-plan.md +6 -6
- package/docs/plans/2026-08-19-human-decision-gates-plan.md +5 -5
- package/docs/plans/2026-08-19-human-decision-presentations-plan.md +1 -1
- package/docs/plans/2026-08-19-provider-compatible-workflow-tool-schema-plan.md +1 -1
- package/docs/plans/2026-08-19-workflow-composition-plan.md +6 -6
- package/docs/plans/2026-08-20-autoimplement-blocker-challenge-plan.md +3 -3
- package/docs/plans/2026-08-20-bounded-command-batches-plan.md +206 -0
- package/docs/plans/2026-08-20-herdr-plugin-sync-plan.md +9 -9
- package/docs/plans/2026-08-21-autoimplement-timeout-fallback-plan.md +242 -0
- package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +324 -0
- package/docs/plans/2026-08-21-plan-change-approval-policy-plan.md +322 -0
- package/docs/plans/2026-08-21-sanity-check-plan.md +283 -0
- package/docs/run-bundles.md +8 -6
- package/docs/workflows.md +85 -22
- package/examples/workflows/approved-plan.workflow.ts +19 -46
- package/examples/workflows/command-batch.workflow.ts +50 -0
- package/examples/workflows/sanity-check.workflow.ts +1 -0
- package/herdr-plugin.toml +3 -3
- package/package.json +7 -7
- package/schemas/decision-presentation-v1.schema.json +1 -1
- package/schemas/human-decision-accepted-v1.schema.json +16 -4
- package/schemas/human-decision-answer-attempt-v1.schema.json +1 -1
- package/schemas/human-decision-cancellation-v1.schema.json +1 -1
- package/schemas/human-decision-continuation-v1.schema.json +11 -2
- package/schemas/human-decision-delivery-v1.schema.json +9 -1
- package/schemas/human-decision-receipt-v1.schema.json +9 -1
- package/schemas/human-decision-request-v1.schema.json +25 -5
- package/schemas/human-decision-resolution-v1.schema.json +1 -1
- package/schemas/human-decision-settlement-v1.schema.json +1 -1
- package/skills/autodoc/SKILL.md +33 -2
- package/skills/autoimplement/SKILL.md +93 -12
- package/skills/autoplan/SKILL.md +26 -2
- package/skills/monitor/SKILL.md +66 -24
- package/skills/pi-workflows/SKILL.md +21 -6
- package/skills/sanity-check/SKILL.md +44 -0
- package/src/builtins/autoimplement-command-batches.ts +364 -0
- package/src/builtins/autoimplement.workflow.ts +1075 -370
- package/src/builtins/catalog.ts +5 -3
- package/src/builtins/index.ts +24 -0
- package/src/builtins/monitor.workflow.ts +27 -150
- package/src/builtins/pi-agent-group.ts +1407 -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 +769 -0
- package/src/controllers/sqlite.ts +580 -7
- package/src/extension/decision-channels.ts +36 -66
- package/src/extension/deferred-turn-coordinator.ts +171 -0
- package/src/extension/deferred-turn.ts +166 -0
- package/src/extension/index.ts +438 -90
- package/src/extension/session-events.ts +2 -2
- package/src/extension/step-message.ts +1 -0
- package/src/extension/widget.ts +24 -5
- package/src/herdr/setup.ts +4 -4
- package/src/render/graph-render.ts +1 -2
- package/src/viewer/render.ts +7 -6
- package/src/workflows/catalog.ts +7 -2
- package/src/workflows/command-batch.ts +254 -0
- package/src/workflows/composition.ts +9 -0
- package/src/workflows/decision-presentation.ts +56 -43
- package/src/workflows/engine.ts +25 -20
- package/src/workflows/errors.ts +24 -0
- package/src/workflows/human-decision.ts +218 -101
- package/src/workflows/index.ts +20 -11
- package/src/workflows/progress.ts +18 -3
- package/src/workflows/schema.ts +19 -1
- package/src/workflows/shell.ts +10 -0
- package/src/workflows/store.ts +8 -1
- package/src/workflows/types.ts +43 -59
- 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/docs/workflows.md
CHANGED
|
@@ -16,7 +16,7 @@ Files are discovered by suffix (`.workflow.ts`, `.workflow.js`, `.workflow.mts`,
|
|
|
16
16
|
3. Workflows built into Pi Workflows
|
|
17
17
|
|
|
18
18
|
Pi Workflows includes built-in `autoplan`, `autodoc`, `autoimplement`,
|
|
19
|
-
`plan-approval`, and `monitor` workflows. `autoplan` is the current name for the
|
|
19
|
+
`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
|
|
@@ -161,11 +161,13 @@ then fails the step. If an agent node times out or the workflow is cancelled,
|
|
|
161
161
|
the extension also aborts its active Pi turn. The model cannot continue to use
|
|
162
162
|
tools after the engine has closed that attempt.
|
|
163
163
|
|
|
164
|
-
`timeoutMs` can be a finite positive number or a function of the normal
|
|
165
|
-
context
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
164
|
+
`timeoutMs` can be a finite positive number, `null`, or a function of the normal
|
|
165
|
+
node context that returns either value. Omit it to use the 15-minute engine
|
|
166
|
+
default. Set it to `null` to disable only the wall-clock deadline; cancellation,
|
|
167
|
+
parking, claim loss, shutdown, and the node's abort signal still work. A timeout
|
|
168
|
+
function can use prepared outputs to select a policy for this run. It has 30
|
|
169
|
+
seconds to return. Computed timeout functions are runtime code, so definition
|
|
170
|
+
snapshots omit them. Snapshots keep fixed numbers and fixed `null` values.
|
|
169
171
|
|
|
170
172
|
### compute
|
|
171
173
|
|
|
@@ -289,6 +291,10 @@ const choices = defineHumanChoices({
|
|
|
289
291
|
humanDecision({
|
|
290
292
|
audience: "operator",
|
|
291
293
|
choices,
|
|
294
|
+
onTimeout: {
|
|
295
|
+
afterMs: 10 * 60_000,
|
|
296
|
+
response: { choice: "continue" },
|
|
297
|
+
},
|
|
292
298
|
request: ({ outputs }) => ({
|
|
293
299
|
title: "Approve plan",
|
|
294
300
|
subject: outputs.plan,
|
|
@@ -301,7 +307,7 @@ humanDecision({
|
|
|
301
307
|
});
|
|
302
308
|
```
|
|
303
309
|
|
|
304
|
-
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
|
|
310
|
+
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.
|
|
305
311
|
|
|
306
312
|
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.
|
|
307
313
|
|
|
@@ -415,14 +421,64 @@ runs.
|
|
|
415
421
|
|
|
416
422
|
The built-in `autoplan` workflow selects a practical in-scope solution and writes a detailed plan. 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`.
|
|
417
423
|
|
|
418
|
-
The built-in `plan-approval` workflow offers
|
|
424
|
+
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.
|
|
425
|
+
|
|
426
|
+
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.
|
|
427
|
+
|
|
428
|
+
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.
|
|
429
|
+
|
|
430
|
+
Autoimplement gives `implement` an eight-hour deadline. When a supported
|
|
431
|
+
long-running agent node times out, one shared read-only fallback inspects the
|
|
432
|
+
current repository, accepted workflow outputs, and relevant pull-request state.
|
|
433
|
+
It then retries the timed-out stage or routes to verification, review, CI,
|
|
434
|
+
delivery, the existing redesign workflow, or blocked. The fallback can run at
|
|
435
|
+
most three times in one Autoimplement run. Its own failure or timeout is
|
|
436
|
+
terminal. Cancellation remains immediate and never enters fallback. A repeated
|
|
437
|
+
effect step first checks what already exists and performs only missing work.
|
|
438
|
+
This graph fallback starts after the timed-out turn ends and is separate from
|
|
439
|
+
successor-turn delivery.
|
|
440
|
+
|
|
441
|
+
Autoimplement uses batches for pi-reviewer, pending CI watches, and local verification commands from independent repositories. It keeps model turns, fixes, pushes, comment changes, merges, and releases in their existing order. Reviewer commands are tied to the repository, base branch, pushed head, and relevant dependency fingerprint. A later review round includes only repositories whose head or dependency fingerprint changed. P0 or P1 work still requires another review. P2-only work can be addressed and verified without another reviewer run only because of that P2 work.
|
|
442
|
+
|
|
443
|
+
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.
|
|
419
444
|
|
|
420
|
-
|
|
445
|
+
The action abort signal stops active command process groups and prevents queued commands from starting. Accepted outputs use the existing trace and artifacts. 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.
|
|
421
446
|
|
|
422
447
|
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.
|
|
423
448
|
|
|
424
449
|
Autoimplement can run the blocker challenge at most three times in one run. Each later challenge receives the earlier challenge results. Reaching the limit stops with the normal workflow safety-limit reason. Explicit human stops, cancellation, exhausted workflow or replan limits, protected authorization gaps, and an independent blocked result from redesign remain direct stops. These hard boundaries do not enter the blocker challenge.
|
|
425
450
|
|
|
451
|
+
### Built-in sanity check
|
|
452
|
+
|
|
453
|
+
The built-in `sanity-check` workflow reviews a pull request or local contribution before implementation, approval, or merge. It checks whether the change is needed, duplicates existing code, should use a simpler design, adds unnecessary data models or public plugin and SDK APIs, or has scope and test problems.
|
|
454
|
+
|
|
455
|
+
```json
|
|
456
|
+
{
|
|
457
|
+
"mode": "serial",
|
|
458
|
+
"baseRef": "origin/main"
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
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.
|
|
463
|
+
|
|
464
|
+
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`.
|
|
465
|
+
|
|
466
|
+
Sanity Check revision 3 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.
|
|
467
|
+
|
|
468
|
+
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.
|
|
469
|
+
|
|
470
|
+
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.
|
|
471
|
+
|
|
472
|
+
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.
|
|
473
|
+
|
|
474
|
+
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.
|
|
475
|
+
|
|
476
|
+
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.
|
|
477
|
+
|
|
478
|
+
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.
|
|
479
|
+
|
|
480
|
+
Serial mode still uses two sessions, and parallel mode still uses five. Prompts, review areas, strict result validation, verdicts, and final notification stay unchanged. The workflow sends the final report through a final notification with `triggerTurn: false`, so the origin model does not produce another response. 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.
|
|
481
|
+
|
|
426
482
|
### Built-in monitor
|
|
427
483
|
|
|
428
484
|
The built-in `monitor` workflow turns a plain request for repeated checks into
|
|
@@ -439,7 +495,7 @@ one looping workflow run. Its input is:
|
|
|
439
495
|
}
|
|
440
496
|
```
|
|
441
497
|
|
|
442
|
-
The first check runs immediately. Omit `repair` for observation-only monitoring. An authorized repair routes through
|
|
498
|
+
The first check runs immediately. Omit `repair` for observation-only monitoring. An authorized repair routes through the shared plan-change workflow, Autoimplement, and a fresh check. A repeated issue with unchanged target evidence stops as blocked. Omit `repair.approval` for the 10-minute autonomous default. Use `approval.mode: "required"` to wait for an explicit answer or `approval.mode: "skip"` to continue without asking.
|
|
443
499
|
|
|
444
500
|
`everyMinutes` defaults to 30. Each accepted check must provide one concise report and choose `continue`, `repair` when authorized, or `stop`. The
|
|
445
501
|
runtime queues that report as a workflow notification with `triggerTurn:
|
|
@@ -496,9 +552,10 @@ use the same card and keep the active attempt id.
|
|
|
496
552
|
|
|
497
553
|
Headless RPC execution receives the same complete prompt without TUI metadata.
|
|
498
554
|
Workflow notifications use a separate message type with `triggerTurn: false`,
|
|
499
|
-
so a notification does not start an assistant response.
|
|
500
|
-
|
|
501
|
-
|
|
555
|
+
so a notification does not start an assistant response. Deferred successor turns
|
|
556
|
+
use an internal turn-intent contract instead of the notification outbox. See
|
|
557
|
+
[WORKFLOW_STEP_MESSAGES.md](WORKFLOW_STEP_MESSAGES.md) for the step-message contract
|
|
558
|
+
and [Deferred workflow turns](DEFERRED_TURNS.md) for the successor-turn contract.
|
|
502
559
|
|
|
503
560
|
## Result presentation
|
|
504
561
|
|
|
@@ -521,9 +578,11 @@ After the final run state has been persisted, the Pi extension sends the
|
|
|
521
578
|
presentation instructions and bounded final result to the model as a hidden
|
|
522
579
|
follow-up message. The next visible message is a normal assistant response.
|
|
523
580
|
Returning `undefined`, returning an empty string, or omitting
|
|
524
|
-
`presentationPrompt` produces no
|
|
525
|
-
runs are never presented
|
|
526
|
-
|
|
581
|
+
`presentationPrompt` produces no presentation. Failed, timed-out, and cancelled
|
|
582
|
+
runs are never presented. When one of those outcomes would otherwise strand an
|
|
583
|
+
agent after a workflow-caused turn abort or asynchronous crash, the extension
|
|
584
|
+
uses the deferred-turn contract to send one factual fallback after settlement.
|
|
585
|
+
Async prompt builders have 30 seconds to finish and receive an
|
|
527
586
|
`AbortSignal` that fires on timeout, session shutdown, or when a new workflow
|
|
528
587
|
or normal user turn starts; stale presentations are discarded. Once a presentation message has
|
|
529
588
|
been queued, another workflow cannot start until that assistant response
|
|
@@ -561,13 +620,17 @@ possible. Defaults worth knowing:
|
|
|
561
620
|
and `running`. `workflow status` and `workflow cancel` accept the run ID before a run bundle
|
|
562
621
|
exists.
|
|
563
622
|
- If deferred activation fails, the queue stores a bounded safe error, releases the session
|
|
564
|
-
reservation, and
|
|
565
|
-
|
|
566
|
-
-
|
|
567
|
-
|
|
568
|
-
|
|
623
|
+
reservation, and creates one deferred-turn intent for the initiating session. A workflow that
|
|
624
|
+
reports `started` and then crashes before its first prompt follows the same path. The model gets
|
|
625
|
+
one factual follow-up after settlement and can make a new explicit start call. Pi Workflows does
|
|
626
|
+
not retry blindly.
|
|
627
|
+
- An agent-issued `workflow cancel` aborts the current node and the current Pi turn, then creates
|
|
628
|
+
one deferred-turn intent. The next natural workflow message resolves it when possible; otherwise
|
|
629
|
+
one factual fallback starts after settlement. Direct `/workflow cancel` remains quiet because it
|
|
630
|
+
is explicit user control. When no run is live but the widget still shows a parked or finished run,
|
|
631
|
+
the command clears the widget.
|
|
569
632
|
- One workflow runs per session at a time.
|
|
570
|
-
- After the workflow tool accepts an agent-step submission, the extension removes any assistant tail text from the rest of that agent run. The next workflow message
|
|
633
|
+
- After the workflow tool accepts an agent-step submission, the extension removes any assistant tail text from the rest of that agent run. The next workflow message is the visible continuation. A deferred intent makes a workflow prompt, presentation, and factual fallback compete to provide one successor turn, so an abort cannot produce two continuation turns.
|
|
571
634
|
- Agent nudges: if the model ends its turn without submitting the pending
|
|
572
635
|
step, it gets a reminder, twice by default, then the step fails.
|
|
573
636
|
|
|
@@ -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,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
action,
|
|
3
|
+
compute,
|
|
4
|
+
defineWorkflow,
|
|
5
|
+
runCommandBatch,
|
|
6
|
+
type CommandBatchRequest,
|
|
7
|
+
} from "@osolmaz/pi-workflows";
|
|
8
|
+
|
|
9
|
+
type Input = {
|
|
10
|
+
cwd: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default defineWorkflow({
|
|
14
|
+
name: "command-batch",
|
|
15
|
+
input: (value): Input => value as Input,
|
|
16
|
+
startAt: "prepare",
|
|
17
|
+
nodes: {
|
|
18
|
+
prepare: compute({
|
|
19
|
+
run: ({ input }) =>
|
|
20
|
+
({
|
|
21
|
+
maxConcurrency: 2,
|
|
22
|
+
items: [
|
|
23
|
+
{
|
|
24
|
+
id: "first",
|
|
25
|
+
command: "printf",
|
|
26
|
+
args: ["%s", "first"],
|
|
27
|
+
cwd: (input as Input).cwd,
|
|
28
|
+
timeoutMs: 10_000,
|
|
29
|
+
maxOutputChars: 10_000,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "second",
|
|
33
|
+
command: "printf",
|
|
34
|
+
args: ["%s", "second"],
|
|
35
|
+
cwd: (input as Input).cwd,
|
|
36
|
+
timeoutMs: 10_000,
|
|
37
|
+
maxOutputChars: 10_000,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
}) satisfies CommandBatchRequest,
|
|
41
|
+
}),
|
|
42
|
+
run: action({
|
|
43
|
+
run: async (context) =>
|
|
44
|
+
await runCommandBatch(context.outputs.prepare as CommandBatchRequest, {
|
|
45
|
+
signal: context.signal,
|
|
46
|
+
}),
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
49
|
+
edges: [{ from: "prepare", to: "run" }],
|
|
50
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sanityCheckWorkflow as default } from "@osolmaz/pi-workflows/builtins";
|
package/herdr-plugin.toml
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
id = "osolmaz.pi-workflows"
|
|
2
|
-
name = "
|
|
3
|
-
version = "0.
|
|
2
|
+
name = "pi-workflows"
|
|
3
|
+
version = "0.12.1"
|
|
4
4
|
min_herdr_version = "0.7.0"
|
|
5
|
-
description = "Open the active
|
|
5
|
+
description = "Open the active pi-workflows run in piw from a managed Herdr pane."
|
|
6
6
|
platforms = ["linux", "macos"]
|
|
7
7
|
|
|
8
8
|
[[panes]]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osolmaz/pi-workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
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": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/decision-presentation-v1.schema.json",
|
|
4
|
-
"title": "
|
|
4
|
+
"title": "pi-workflows decision presentation v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": ["schema", "summary", "blocks"],
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/human-decision-accepted-v1.schema.json",
|
|
4
|
-
"title": "
|
|
4
|
+
"title": "pi-workflows accepted human decision v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": [
|
|
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
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/human-decision-answer-attempt-v1.schema.json",
|
|
4
|
-
"title": "
|
|
4
|
+
"title": "pi-workflows human decision answer attempt v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/human-decision-cancellation-v1.schema.json",
|
|
4
|
-
"title": "
|
|
4
|
+
"title": "pi-workflows human decision cancellation v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": ["schema", "decisionId", "requestDigest", "cancelledAt", "reason"],
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/human-decision-continuation-v1.schema.json",
|
|
4
|
-
"title": "
|
|
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" }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/human-decision-delivery-v1.schema.json",
|
|
4
|
-
"title": "
|
|
4
|
+
"title": "pi-workflows human decision delivery v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": [
|
|
@@ -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
|
}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/human-decision-receipt-v1.schema.json",
|
|
4
|
-
"title": "
|
|
4
|
+
"title": "pi-workflows redacted human decision receipt v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": [
|
|
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
|
}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/osolmaz/pi-workflows/schemas/human-decision-request-v1.schema.json",
|
|
4
|
-
"title": "
|
|
4
|
+
"title": "pi-workflows human decision request v1",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": [
|
|
8
8
|
"schema",
|
|
9
9
|
"decisionId",
|
|
10
10
|
"requestDigest",
|
|
11
|
+
"subjectDigest",
|
|
12
|
+
"presentationDigest",
|
|
11
13
|
"runId",
|
|
12
14
|
"workflowName",
|
|
13
15
|
"nodeId",
|
|
14
16
|
"attemptId",
|
|
15
17
|
"audience",
|
|
16
18
|
"title",
|
|
17
|
-
"
|
|
19
|
+
"subject",
|
|
20
|
+
"presentation",
|
|
21
|
+
"revision",
|
|
18
22
|
"choices",
|
|
19
23
|
"createdAt"
|
|
20
24
|
],
|
|
@@ -22,13 +26,19 @@
|
|
|
22
26
|
"schema": { "const": "pi-workflows.human-decision-request.v1" },
|
|
23
27
|
"decisionId": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$" },
|
|
24
28
|
"requestDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
29
|
+
"subjectDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
30
|
+
"presentationDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
25
31
|
"runId": { "type": "string" },
|
|
26
32
|
"workflowName": { "type": "string" },
|
|
27
33
|
"nodeId": { "type": "string" },
|
|
28
34
|
"attemptId": { "type": "string" },
|
|
29
35
|
"audience": { "type": "string" },
|
|
30
36
|
"title": { "type": "string", "minLength": 1 },
|
|
31
|
-
"
|
|
37
|
+
"subject": true,
|
|
38
|
+
"presentation": {
|
|
39
|
+
"$ref": "decision-presentation-v1.schema.json"
|
|
40
|
+
},
|
|
41
|
+
"revision": { "type": "integer", "minimum": 1 },
|
|
32
42
|
"choices": {
|
|
33
43
|
"type": "object",
|
|
34
44
|
"minProperties": 1,
|
|
@@ -54,6 +64,16 @@
|
|
|
54
64
|
}
|
|
55
65
|
},
|
|
56
66
|
"createdAt": { "type": "string", "format": "date-time" },
|
|
57
|
-
"expiresAt": { "type": "string", "format": "date-time" }
|
|
58
|
-
|
|
67
|
+
"expiresAt": { "type": "string", "format": "date-time" },
|
|
68
|
+
"defaultResponse": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"additionalProperties": false,
|
|
71
|
+
"required": ["choice"],
|
|
72
|
+
"properties": {
|
|
73
|
+
"choice": { "type": "string" },
|
|
74
|
+
"input": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"dependentRequired": { "defaultResponse": ["expiresAt"] }
|
|
59
79
|
}
|