@osolmaz/pi-workflows 0.13.4 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +136 -118
  2. package/dist/controllers/index.d.ts +1 -1
  3. package/dist/controllers/index.js.map +1 -1
  4. package/dist/controllers/sqlite.d.ts +34 -31
  5. package/dist/controllers/sqlite.js +116 -77
  6. package/dist/controllers/sqlite.js.map +1 -1
  7. package/dist/extension/index.js +721 -202
  8. package/dist/extension/index.js.map +1 -1
  9. package/dist/extension/restart-policy.d.ts +38 -0
  10. package/dist/extension/restart-policy.js +116 -0
  11. package/dist/extension/restart-policy.js.map +1 -0
  12. package/dist/extension/terminal-decision.d.ts +51 -0
  13. package/dist/extension/terminal-decision.js +110 -0
  14. package/dist/extension/terminal-decision.js.map +1 -0
  15. package/dist/state/prune.js +36 -10
  16. package/dist/state/prune.js.map +1 -1
  17. package/dist/workflows/tool-input.d.ts +4 -0
  18. package/dist/workflows/tool-input.js +6 -1
  19. package/dist/workflows/tool-input.js.map +1 -1
  20. package/docs/2026-08-25-workflow-follow-ups.md +8 -6
  21. package/docs/DEFERRED_TURNS.md +39 -26
  22. package/docs/HUMAN_DECISIONS.md +12 -4
  23. package/docs/SQLITE_STATE.md +24 -0
  24. package/docs/plans/2026-08-19-human-decision-gates-plan.md +34 -8
  25. package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +357 -0
  26. package/docs/workflows.md +85 -29
  27. package/herdr-plugin.toml +1 -1
  28. package/package.json +1 -1
  29. package/skills/autodoc/SKILL.md +1 -1
  30. package/skills/autoimplement/SKILL.md +1 -1
  31. package/skills/autoplan/SKILL.md +1 -1
  32. package/skills/pi-workflows/SKILL.md +2 -0
  33. package/src/controllers/index.ts +3 -0
  34. package/src/controllers/sqlite.ts +226 -155
  35. package/src/extension/index.ts +881 -220
  36. package/src/extension/restart-policy.ts +163 -0
  37. package/src/extension/terminal-decision.ts +172 -0
  38. package/src/state/prune.ts +35 -9
  39. package/src/workflows/tool-input.ts +9 -1
package/docs/workflows.md CHANGED
@@ -430,6 +430,7 @@ The model sees one `workflow` tool. Its `action` field supports:
430
430
 
431
431
  - `list` for discovered workflow names and sources.
432
432
  - `start` with a workflow name or path and structured input.
433
+ - `restart` with a terminal run ID. It creates a new run from the exact stored workflow reference and input.
433
434
  - `status` for the active run or a supplied run ID.
434
435
  - `pause`, `resume`, and `cancel` for the active run.
435
436
  - `answer` with ordinary checkpoint input and an optional run ID. Protected `humanDecision()` gates reject this model-facing action.
@@ -439,8 +440,47 @@ The model sees one `workflow` tool. Its `action` field supports:
439
440
  - `update` for a non-completing update from the current agent attempt.
440
441
  - `submit` for the current workflow step contract.
441
442
 
442
- A model-started run is queued until the model's current turn settles. The first
443
- workflow prompt then starts a new turn. This keeps the requesting turn outside
443
+ A direct user request to continue or resume the active workflow maps to the
444
+ `resume` action immediately. The model does not call `status` instead of
445
+ `resume`, and it does not use `status` as a prerequisite.
446
+
447
+ `resume` is idempotent while a run is active. A held, pausing, or paused run is
448
+ released and reports `resumed: true`. An active run that is already executing
449
+ returns normal success with `resumed: false` and `alreadyRunning: true`. It does
450
+ not change the run state. With no active run, `resume` still returns a warning.
451
+
452
+ Model-facing `status` keeps `status` as the durable workflow lifecycle state.
453
+ It also reports the host action fields `paused`, `workState`, and `resumable`.
454
+ For the current active run, `paused` is true when the host has requested or
455
+ applied a hold, or when the durable run state has `paused: true`. `workState`
456
+ is `running`, `pausing`, or `paused` for that active host run and `inactive`
457
+ when no current host run can act on the durable state. `resumable` is true only
458
+ when `resume` can release the current active run. Queue-only status uses its
459
+ launch state, such as `queued` or `starting`, as `workState`; queue-only and
460
+ no-run results report `paused: false` and `resumable: false`. Thus, a durable
461
+ `status: "running"` can correctly appear with `workState: "pausing"` or
462
+ `workState: "paused"`, and the status message names that actionable state
463
+ instead of saying only that the workflow is running.
464
+
465
+ Restart uses this contract:
466
+
467
+ ```json
468
+ {
469
+ "action": "restart",
470
+ "runId": "terminal-run-id"
471
+ }
472
+ ```
473
+
474
+ The terminal run must belong to the current Pi session and must not be active,
475
+ waiting, or explicitly cancelled. Its source and revision must still resolve
476
+ exactly. Restart creates a new immutable run and leaves the terminal run
477
+ unchanged. It copies the stored input and safe launch settings; it does not
478
+ reconstruct input from conversation history.
479
+
480
+ A model-started run is queued until the model's current turn settles. A terminal
481
+ decision turn can reserve one restart, Monitor run, or other workflow start.
482
+ A second workflow launch from that turn fails. The first workflow prompt then
483
+ starts a new turn. This keeps the requesting turn outside
444
484
  the workflow's first attempt and prevents an early missing-submission reminder.
445
485
  The normal extension offers all actions. The headless RPC bridge offers only
446
486
  `update` and `submit`, so a workflow child cannot recursively control other
@@ -665,19 +705,30 @@ export default defineWorkflow({
665
705
  });
666
706
  ```
667
707
 
668
- After the final run state has been persisted, the Pi extension sends the
669
- presentation instructions and bounded final result to the model as a hidden
670
- follow-up message. The next visible message is a normal assistant response.
671
- Returning `undefined`, returning an empty string, or omitting
672
- `presentationPrompt` produces no presentation. Failed, timed-out, and cancelled
673
- runs are never presented. When one of those outcomes would otherwise strand an
674
- agent after a workflow-caused turn abort or asynchronous crash, the extension
675
- uses the deferred-turn contract to send one factual fallback after settlement.
676
- Async prompt builders have 30 seconds to finish and receive an
677
- `AbortSignal` that fires on timeout, session shutdown, or when a new workflow
678
- or normal user turn starts; stale presentations are discarded. Once a presentation message has
679
- been queued, another workflow cannot start until that assistant response
680
- settles, so results cannot interleave.
708
+ After a top-level interactive run becomes terminal, the Pi extension gives the
709
+ model one normal terminal decision turn. The message contains the workflow name
710
+ and revision, terminal run ID, exact stored input, bounded result, terminal
711
+ state and reason, restart count, and earlier terminal outcomes in the restart
712
+ chain. A completed state does not prove that the user's larger task is complete.
713
+ The model uses the current Pi conversation to stop, restart safely, start
714
+ Monitor for an authorized external wait, ask for a decision or authority, or
715
+ take another safe authorized action.
716
+
717
+ `presentationPrompt` adds workflow-specific presentation instructions to this
718
+ shared terminal decision message for completed runs. Returning `undefined`,
719
+ returning an empty string, omitting `presentationPrompt`, or ending in failure,
720
+ timeout, or cancellation uses the factual terminal fallback instead. Normal
721
+ presentation and fallback claim the same terminal turn intent, so races,
722
+ reload, crash recovery, and compaction cannot create a second decision turn.
723
+ Async prompt builders have 30 seconds to finish and receive an `AbortSignal`
724
+ that fires on timeout, session shutdown, or when a new workflow or normal user
725
+ turn starts; stale presentations are discarded.
726
+
727
+ Waiting checkpoints are not terminal and do not create a terminal decision
728
+ turn. Controller child runs and internally owned runs report to their owner and
729
+ do not create competing turns. Explicit cancellation produces terminal facts,
730
+ but its decision instruction defaults to stopping and the `restart` shortcut
731
+ rejects it.
681
732
 
682
733
  An agent with `expectedOutput: assistantMessage()` is different. Its visible
683
734
  assistant response is the node output, can appear before later nodes, and also
@@ -685,12 +736,11 @@ works inside an included workflow. A root `presentationPrompt` would add a
685
736
  second response, so workflows that end with assistant-message output normally
686
737
  omit it.
687
738
 
688
- Presentation is outside the workflow graph: it cannot route to another node,
689
- change the run status, or alter the SQLite run state. If prompt generation or message
690
- delivery fails, the extension reports a warning and leaves the finished run
691
- unchanged. Opting in adds one hidden custom message and one assistant response
692
- to the normal Pi session; it adds no other persistent data and uses no Pi
693
- internals.
739
+ Presentation and terminal decisions are outside the workflow graph: they cannot
740
+ route to another node, change the terminal run, or alter its result. A selected
741
+ restart always creates a new run. Workflow definitions need no opt-in,
742
+ continuation node, or restart prompt. Pi owns conversation history. Pi Workflows
743
+ does not identify, hash, copy, or store an original user message.
694
744
 
695
745
  ## Runtime behavior
696
746
 
@@ -712,20 +762,26 @@ possible. Defaults worth knowing:
712
762
  held without nudges and the engine pauses at the next boundary. Node
713
763
  timeouts keep ticking while held, so a long-abandoned step still times out.
714
764
  `/workflow resume` re-delivers the pending step prompt.
765
+ - Resuming an active run that is already running succeeds without changing the
766
+ engine, executor, widget, or durable workflow state. This makes duplicate
767
+ `resume` calls safe.
715
768
  - A model-started workflow is persisted as `queued` with its final run ID before the start tool
716
769
  returns. Activation waits for the initiating agent turn to settle, then moves through `starting`
717
770
  and `running`. `workflow status` and `workflow cancel` accept the run ID before a SQLite run state
718
771
  exists.
719
772
  - If deferred activation fails, the queue stores a bounded safe error, releases the session
720
- reservation, and creates one deferred-turn intent for the initiating session. A workflow that
773
+ reservation, and creates one terminal turn intent for the initiating session. A workflow that
721
774
  reports `started` and then crashes before its first prompt follows the same path. The model gets
722
- one factual follow-up after settlement and can make a new explicit start call. Pi Workflows does
723
- not retry blindly.
724
- - An agent-issued `workflow cancel` aborts the current node and the current Pi turn, then creates
725
- one deferred-turn intent. The next natural workflow message resolves it when possible; otherwise
726
- one factual fallback starts after settlement. Direct `/workflow cancel` remains quiet because it
727
- is explicit user control. When no run is live but the widget still shows a parked or finished run,
728
- the command clears the widget.
775
+ one factual decision turn after settlement. Pi Workflows does not retry automatically.
776
+ - Agent-issued and direct `workflow cancel` actions that cancel an active or queued run create or
777
+ settle one terminal turn intent. The resulting decision defaults to stopping, and `restart`
778
+ rejects the cancelled run. When no run is live but the widget still shows a parked or finished
779
+ run, the command clears the widget.
780
+ - A restart chain allows at most three restart actions after the original run. The terminal
781
+ fingerprint excludes timestamps and run IDs. If the same workflow revision, exact input, state,
782
+ result or error, and reason occur again in that chain, another restart fails immediately. A
783
+ changed outcome can remain restartable until the chain limit. Starting Monitor does not consume
784
+ a restart.
729
785
  - One workflow runs per session at a time.
730
786
  - After the workflow tool accepts an agent-step submission, any assistant text that follows remains visible. The next workflow message continues the graph. 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.
731
787
  - Agent nudges: if the model ends its turn without submitting the pending
package/herdr-plugin.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  id = "osolmaz.pi-workflows"
2
2
  name = "pi-workflows"
3
- version = "0.13.4"
3
+ version = "0.14.0"
4
4
  min_herdr_version = "0.7.0"
5
5
  description = "Open the active pi-workflows run in piw from a managed Herdr pane."
6
6
  platforms = ["linux", "macos"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osolmaz/pi-workflows",
3
- "version": "0.13.4",
3
+ "version": "0.14.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"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: autodoc
3
- description: Use when an existing selected solution or clear implementation plan must be recorded or updated in canonical documentation before implementation, including choosing the right repository and applying SimpleDoc conventions.
3
+ description: Records or updates an existing selected plan in canonical documentation without implementing it. Use only when the user explicitly asks to run autodoc.
4
4
  compatibility: Requires pi-workflows and the built-in autodoc workflow.
5
5
  ---
6
6
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: autoimplement
3
- description: Use when the user asks to implement a plan end-to-end, test it, run pi-reviewer against the base branch in a loop until no P0/P1 issues remain, and make sure CI/CD is green before finishing.
3
+ description: Implements an existing plan end to end, tests it, runs pi-reviewer until no P0/P1 issues remain, and verifies CI/CD. Use only when the user explicitly asks to run autoimplement.
4
4
  compatibility: Requires Pi Workflows and the built-in autoimplement workflow.
5
5
  ---
6
6
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: autoplan
3
- description: Use when the user asks to devise, choose, or plan the most Long term elegant and production ready solution, compare it with the Holy grail, and produce the best practical in-scope implementation plan without asking the user to resolve the gap.
3
+ description: Compares practical solutions with the ideal end state, selects the best in-scope option, and produces an implementation plan. Use only when the user explicitly asks to run autoplan.
4
4
  compatibility: Requires pi-workflows and the built-in autoplan workflow.
5
5
  ---
6
6
 
@@ -22,6 +22,8 @@ Use the smallest applicable action:
22
22
  - `update` publishes a non-completing durable update for the active step attempt.
23
23
  - `submit` completes an active submitted agent step with its required output. An assistant-message step completes through its normal visible reply instead.
24
24
 
25
+ When the user asks to continue or resume the active workflow, call `workflow` with `action: "resume"` immediately. Do not use `workflow status` as a substitute or prerequisite.
26
+
25
27
  Use `start` only once for one requested run. Before starting, load the matching workflow skill when one exists and build its complete input. Include scope, authority, constraints, identifiers, and finish criteria required by that skill. Do not start with placeholders that still need user or model repair.
26
28
 
27
29
  For a workflow without a specialized skill, inspect its input contract and make one complete call. For example:
@@ -24,7 +24,10 @@ export {
24
24
  SqliteControllerStore,
25
25
  type RunEventRecord,
26
26
  type WorkflowNotificationRecord,
27
+ type WorkflowRunClaimOptions,
28
+ type WorkflowRunPreparationResult,
27
29
  type WorkflowRunQueueRecord,
30
+ type WorkflowRunReservationOptions,
28
31
  } from "./sqlite.js";
29
32
  export {
30
33
  type ControllerStore,