@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/CONTROLLERS.md
CHANGED
|
@@ -159,11 +159,11 @@ Mutation policy stays in deterministic effect drivers. Agent workflows return fi
|
|
|
159
159
|
|
|
160
160
|
## Child workflows
|
|
161
161
|
|
|
162
|
-
`ctx.workflows.ensure()` creates or finds a workflow run by a stable request key and input fingerprint. Repeated reconciliations find the same active or completed request. A changed input must use a new key. The controller
|
|
162
|
+
`ctx.workflows.ensure()` creates or finds a workflow run by a stable request key and input fingerprint. Repeated reconciliations find the same active or completed request. A changed input must use a new key. An asynchronous child completion validates the reserved request and run IDs through a separate scheduler-completion command; it never reuses the controller claim that launched the child. The controller transaction reserves and saves each attempt's run ID before the scheduler starts it, so recovery can find the run row.
|
|
163
163
|
|
|
164
|
-
A child run is one immutable attempt. Its existing run
|
|
164
|
+
A child run is one immutable attempt. Its existing SQLite run state remains the execution record. The parent resource points to the current run, and workflow completion enqueues the parent key. A host restart can record an abandoned attempt and create another attempt for the same stable request.
|
|
165
165
|
|
|
166
|
-
The workflow scheduler records an abandoned running
|
|
166
|
+
The workflow scheduler records an abandoned running run as `failed` with a final `run_interrupted` event. The controller store treats that child attempt as `interrupted`, so the next reconciliation starts another immutable attempt. Compute work can run again, while consequential external actions belong in the effect API so recovery observes them before retrying.
|
|
167
167
|
|
|
168
168
|
## Deletion and cleanup
|
|
169
169
|
|
|
@@ -183,7 +183,7 @@ The Pi extension starts local workers during `session_start` and closes them dur
|
|
|
183
183
|
|
|
184
184
|
Every reconciliation emits structured records with the controller name, resource key, generation, reconcile ID, outcome and duration, plus the requeue reason. Effect state changes and child workflow links are also recorded. Logs and viewer projections remain secondary to the resource and effect stores.
|
|
185
185
|
|
|
186
|
-
`pi-workflows controllers` lists resources and their current readiness condition. `pi-workflows controller <controller> <key>` prints one resource together with its effects, child workflows, and recent events.
|
|
186
|
+
`pi-workflows controllers` lists resources and their current readiness condition. `pi-workflows controller <controller> <key>` prints one resource together with its effects, child workflows, and recent events. Run views read the same database through query-only connections.
|
|
187
187
|
|
|
188
188
|
## Safety rules
|
|
189
189
|
|
|
@@ -196,7 +196,7 @@ A production controller must follow these rules:
|
|
|
196
196
|
- Reconcile again after each consequential external effect.
|
|
197
197
|
- Keep model output separate from mutation authority.
|
|
198
198
|
- Bound worker counts and retry rates. Also bound timeouts and stored payload sizes.
|
|
199
|
-
- Redact credentials and private provider responses from logs and
|
|
199
|
+
- Redact credentials and private provider responses from logs and SQLite runs.
|
|
200
200
|
|
|
201
201
|
## Package and Pi integration
|
|
202
202
|
|
|
@@ -204,11 +204,13 @@ The controller API is exported from `@osolmaz/pi-workflows/controllers`. Control
|
|
|
204
204
|
|
|
205
205
|
The implementation uses documented Pi extension APIs only. Commands and tools use `registerCommand` and `registerTool`. Session lifecycle uses `session_start` and `session_shutdown`. Workflow prompts use `sendUserMessage`, while status uses `setWidget` and `setStatus`.
|
|
206
206
|
|
|
207
|
-
The `/controller` command lists and inspects resources, applies specs, requests reconciliation or deletion, and starts or stops local workers. Stopping workers records an active child as interrupted, so
|
|
207
|
+
The `/controller` command lists and inspects resources, applies specs, requests reconciliation or deletion, and starts or stops local workers. Stopping workers records an active child as interrupted, so a later worker can create another attempt.
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
Controller resources use the canonical [SQLite state](SQLITE_STATE.md) database. `projects` separates repository-local resources by canonical project path. Controller claims use the shared lease generation, token, expiry, and expected resource revision. Effects and child workflows use the shared transactional outbox and deterministic receipts.
|
|
210
210
|
|
|
211
|
-
|
|
211
|
+
The same database backs the standalone host (`pi-workflows host`). The host reconciles controllers without a Pi session and claims parked interactive runs from `run_queue`. Conversation children execute in headless `pi --mode rpc` sessions. A Pi session and the host can share the database safely because SQLite transactions and durable leases arbitrate ownership, but only one owner can mutate a resource at a time.
|
|
212
|
+
|
|
213
|
+
Normal workflow prompts, tool calls, and replies remain part of the Pi session. No Pi internal type, private API, or persistent Pi schema changes.
|
|
212
214
|
|
|
213
215
|
## Exclusions
|
|
214
216
|
|
package/docs/DEFERRED_TURNS.md
CHANGED
|
@@ -246,7 +246,7 @@ Store leases prevent concurrent processes from sending the same resolution. Bran
|
|
|
246
246
|
|
|
247
247
|
## Claim transfer
|
|
248
248
|
|
|
249
|
-
Claim loss stops the old runner's work and all fenced
|
|
249
|
+
Claim loss stops the old runner's work and all fenced SQLite writes. The intent stays pending and fallback-ineligible while another runner can resume the run.
|
|
250
250
|
|
|
251
251
|
The new runner's next workflow prompt can resolve the intent. If durable state later proves a terminal outcome with no natural successor, terminal handling makes the intent eligible for fallback to its target session.
|
|
252
252
|
|
|
@@ -281,7 +281,7 @@ This is an alpha hard cutover.
|
|
|
281
281
|
- Add `workflow_turn_intents` to the existing database.
|
|
282
282
|
- Remove the launch-trigger runtime path.
|
|
283
283
|
- Add no v2 schema, compatibility reader, dual write, alias, or feature flag.
|
|
284
|
-
- Keep historical terminal
|
|
284
|
+
- Keep historical terminal SQLite runs readable because their contract does not change.
|
|
285
285
|
|
|
286
286
|
## Conformance
|
|
287
287
|
|
|
@@ -16,7 +16,7 @@ Shared behavior should usually start as a data format or pure helper used by a w
|
|
|
16
16
|
|
|
17
17
|
## Explicit behavior
|
|
18
18
|
|
|
19
|
-
The graph should show what runs and where it can go.
|
|
19
|
+
The graph should show what runs and where it can go. Use structured, validated agent results when the graph must inspect fields or choose a route. Use a declared assistant-message result when exact visible text belongs inside the graph. Commands and other side effects should be declared by the workflow author.
|
|
20
20
|
|
|
21
21
|
Avoid hidden polling, implicit retries, automatic command generation, and state changes that the graph cannot explain.
|
|
22
22
|
|
|
@@ -30,7 +30,9 @@ A notification should not start a model turn unless the workflow explicitly requ
|
|
|
30
30
|
|
|
31
31
|
Runs should survive interruption and remain safe to resume. Save the run input and every accepted output. Save attempts and events along with enough evidence of side effects for replay and diagnosis.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Immutable SQLite events are the record of what happened. Domain rows are current projections written in the same transaction. Viewers derive their answers from those facts instead of creating another source of truth.
|
|
34
|
+
|
|
35
|
+
Reading shared state never gives mutation authority. Every durable write checks its actor, expected resource revision, and current lease generation when ownership is required. Follow-up work uses deterministic effects and idempotent receipts so partial failure can converge safely.
|
|
34
36
|
|
|
35
37
|
## Boundaries
|
|
36
38
|
|
package/docs/HUMAN_DECISIONS.md
CHANGED
|
@@ -60,6 +60,10 @@ export default defineWorkflow({
|
|
|
60
60
|
approve: humanDecision({
|
|
61
61
|
audience: "operator",
|
|
62
62
|
choices: planChoices,
|
|
63
|
+
onTimeout: {
|
|
64
|
+
afterMs: 10 * 60_000,
|
|
65
|
+
response: { choice: "continue" },
|
|
66
|
+
},
|
|
63
67
|
request: ({ outputs }) => ({
|
|
64
68
|
title: "Approve the implementation plan",
|
|
65
69
|
subject: outputs.propose,
|
|
@@ -106,6 +110,8 @@ type PlanDecision =
|
|
|
106
110
|
|
|
107
111
|
`humanDecisionEdge()` requires one destination for every choice. A missing or extra case is a TypeScript error. Runtime validation applies the same choice and input contract before an answer can win.
|
|
108
112
|
|
|
113
|
+
`onTimeout` is optional. It supplies a positive duration and a response that satisfies the same choice contract. The request stores the resulting absolute deadline and validated response. When no human answer wins before the deadline, the decision recovery owner applies that response with `timeout` provenance. Omitting `onTimeout` keeps an indefinite wait. A request cannot combine `onTimeout` with a separate `expiresAt` value.
|
|
114
|
+
|
|
109
115
|
## Checkpoint behavior
|
|
110
116
|
|
|
111
117
|
A human decision still has `nodeType: "checkpoint"`. The helper adds a human decision contract to that checkpoint.
|
|
@@ -118,9 +124,7 @@ When the engine reaches the node, it:
|
|
|
118
124
|
4. asks the configured channels to deliver it; and
|
|
119
125
|
5. parks the run in `waiting` state.
|
|
120
126
|
|
|
121
|
-
When a valid answer is accepted, the continuation keeps the workflow's original input. The human answer becomes the checkpoint node's output in the continuation.
|
|
122
|
-
|
|
123
|
-
This distinction preserves old workflow definitions and run bundles.
|
|
127
|
+
When a valid answer is accepted, the continuation keeps the workflow's original input. The human answer becomes the checkpoint node's output in the continuation. Ordinary checkpoints keep their current behavior, where `/workflow answer` supplies the continuation input.
|
|
124
128
|
|
|
125
129
|
## Request and response contracts
|
|
126
130
|
|
|
@@ -136,12 +140,12 @@ A new decision request contains:
|
|
|
136
140
|
- the logical audience;
|
|
137
141
|
- the complete choice contract;
|
|
138
142
|
- the canonical request digest;
|
|
139
|
-
- an optional
|
|
143
|
+
- an optional absolute deadline and automatic response; and
|
|
140
144
|
- the creation time.
|
|
141
145
|
|
|
142
|
-
The presentation is an explicit display allowlist. A channel does not receive the subject and cannot infer operator text from it. The request digest binds the subject, visible presentation, title, revision, choices, and
|
|
146
|
+
The presentation is an explicit display allowlist. A channel does not receive the subject and cannot infer operator text from it. The request digest binds the subject, visible presentation, title, revision, choices, input prompts, deadline, and automatic response. Each choice has a stable ID and may have no input or one validated text input contract.
|
|
143
147
|
|
|
144
|
-
|
|
148
|
+
Human decisions use only `pi-workflows.human-decision-request.v1`. The former `body` request and all human-decision `v2` records are invalid. This is an alpha hard cutover: old waiting runs and decision state must be reset rather than migrated or reinterpreted.
|
|
145
149
|
|
|
146
150
|
A submitted response contains:
|
|
147
151
|
|
|
@@ -210,7 +214,7 @@ pi-workflows keeps credential references in a separate private file. A Telegram
|
|
|
210
214
|
}
|
|
211
215
|
```
|
|
212
216
|
|
|
213
|
-
Run `/workflow-channel setup` in Pi TUI to verify and install a profile, `/workflow-channel status` to inspect whether profiles are active, and `/workflow-channel reload` after a private configuration change. Setup asks for the token file path, not the token. It updates mode-`0600` private files and does not copy the token. Token values never enter source files, workflow inputs,
|
|
217
|
+
Run `/workflow-channel setup` in Pi TUI to verify and install a profile, `/workflow-channel status` to inspect whether profiles are active, and `/workflow-channel reload` after a private configuration change. Setup asks for the token file path, not the token. It updates mode-`0600` private files and does not copy the token. Token values never enter source files, workflow inputs, SQLite runs, logs, child environments, or model-visible tool results.
|
|
214
218
|
|
|
215
219
|
The same Unix account can read a local credential file. This design prevents accidental propagation, not a hostile same-account process. A separately owned connector can implement the same channel interface later if stronger isolation becomes necessary.
|
|
216
220
|
|
|
@@ -250,29 +254,28 @@ A choice without input submits from its button. A text choice such as `replan` w
|
|
|
250
254
|
4. the channel verifies the numeric user ID, chat ID, reply message ID, decision ID, and request digest; and
|
|
251
255
|
5. the exact received text becomes `input.instructions`.
|
|
252
256
|
|
|
253
|
-
The adapter does not infer a choice from ordinary chat text. Callback payloads contain short opaque IDs because Telegram limits callback data.
|
|
257
|
+
The adapter does not infer a choice from ordinary chat text. Callback payloads contain short opaque IDs because Telegram limits callback data. Private local SQLite rows map each opaque ID to the validated decision presentation. Credentials remain outside the database.
|
|
254
258
|
|
|
255
|
-
Telegram permits one long-polling consumer for a bot profile. Active Pi processes use
|
|
259
|
+
Telegram permits one long-polling consumer for a bot profile. Active Pi processes use the shared SQLite lease so one process owns polling and the others observe the same channel state. The lease owner can accept a verified reply, but only the Pi session that owns the waiting run creates its continuation. Active sessions inspect the durable accepted-answer fence and recover their own continuation. If no Pi process is running, Telegram delivery and reply collection resume when Pi starts again. Running an always-on service is outside this design.
|
|
256
260
|
|
|
257
261
|
The Bot API does not provide an idempotency key for `sendMessage`. pi-workflows therefore writes a delivery intent before sending and never blindly retries an ambiguous send. A timed-out send is recorded as `unknown`; Pi remains available and an operator can request another delivery. This avoids automatic duplicate messages while keeping decision acceptance exactly once.
|
|
258
262
|
|
|
259
263
|
## Durable decision records
|
|
260
264
|
|
|
261
|
-
|
|
265
|
+
Human decisions use the canonical [SQLite state](SQLITE_STATE.md) database:
|
|
262
266
|
|
|
263
|
-
-
|
|
264
|
-
-
|
|
265
|
-
-
|
|
266
|
-
- the
|
|
267
|
-
-
|
|
268
|
-
- channel
|
|
269
|
-
- the continuation request and result.
|
|
267
|
+
- `human_decisions` stores each immutable request;
|
|
268
|
+
- `human_decision_submissions` records human, policy, channel, and control candidates;
|
|
269
|
+
- `human_decision_resolutions` stores the one accepted-or-cancelled winner;
|
|
270
|
+
- `continuations` links the parent and continuation runs;
|
|
271
|
+
- `effects` records parent settlement, continuation, and presentation settlement work; and
|
|
272
|
+
- channel tables store delivery and settlement receipts.
|
|
270
273
|
|
|
271
|
-
|
|
274
|
+
A valid human answer, eligible timeout policy, explicit cancellation, or no-default expiry competes for the same resolution primary key. The winning transaction records the immutable resolution, audit event, and required effects together. A retry adopts the existing matching result. A conflicting or late answer receives the durable winner.
|
|
272
275
|
|
|
273
|
-
|
|
276
|
+
A deadline with a validated default response is timeout-policy acceptance. It cannot become expiry cancellation. No-default expiry can cancel. Automatic policy and continuation creation require the current run owner's token and lease generation. A verified channel can submit a human candidate without gaining run ownership.
|
|
274
277
|
|
|
275
|
-
|
|
278
|
+
The continuation run ID is derived from the decision ID. The owner adopts an existing matching continuation or creates it once. The continuation record and redacted receipt carry the resolution provenance, decision ID, request digest, gate node ID, choice, acceptance time, and answer digest. Human actor, channel, event, and idempotency details remain private and do not enter model-visible status output.
|
|
276
279
|
|
|
277
280
|
## Planning workflow composition
|
|
278
281
|
|
|
@@ -286,33 +289,19 @@ pi-workflows keeps solution choice, documentation, and implementation in separat
|
|
|
286
289
|
|
|
287
290
|
`autoimplement` first finds the clear existing plan in its input, the conversation, or referenced canonical documents. It blocks when no clear plan exists. A caller can bypass discovery and autodoc only by supplying both the explicit plan and a `documentation` receipt whose plan digest matches it. A plan without that current-document evidence enters autodoc so the canonical documents are inspected and adopted or updated. The absence of a structured `plan` input never authorizes `autoplan`.
|
|
288
291
|
|
|
289
|
-
If later implementation, verification, review, comments, or CI evidence invalidates the plan,
|
|
292
|
+
If later implementation, verification, review, comments, or CI evidence invalidates the plan, Autoimplement enters the shared plan-change workflow. That workflow runs Autoplan, Autodoc, plan approval, and bounded exact-text replanning. Monitor uses the same workflow for each new repair plan and passes the selected plan into Autoimplement without a second decision.
|
|
290
293
|
|
|
291
294
|
## Reusable plan approval workflow
|
|
292
295
|
|
|
293
|
-
pi-workflows ships a typed `plan-approval` workflow built on `humanDecision()`. Its
|
|
294
|
-
|
|
295
|
-
- `continue`, with the approval receipt;
|
|
296
|
-
- `stop`, with the stop receipt; and
|
|
297
|
-
- `replan`, with the exact instructions and receipt.
|
|
298
|
-
|
|
299
|
-
A parent can include it without copying prompts or channel handling:
|
|
296
|
+
pi-workflows ships a typed `plan-approval` workflow built on `humanDecision()`. Its policy has three modes:
|
|
300
297
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
input: ({ outputs }) => ({
|
|
305
|
-
plan: outputs.devise.plan,
|
|
306
|
-
planDigest: outputs.devise.planDigest,
|
|
307
|
-
audience: "operator",
|
|
308
|
-
}),
|
|
309
|
-
}),
|
|
310
|
-
},
|
|
311
|
-
```
|
|
298
|
+
- `auto` asks the configured audience and continues after the configured deadline. It defaults to audience `operator` and 10 minutes.
|
|
299
|
+
- `required` waits for an explicit human answer.
|
|
300
|
+
- `skip` creates no human decision and continues immediately.
|
|
312
301
|
|
|
313
|
-
|
|
302
|
+
The workflow has `continue`, `stop`, and exact-text `replan` exits. Continue reports `human`, `timeout`, or `skipped` provenance. Stop and replan always require a human answer.
|
|
314
303
|
|
|
315
|
-
|
|
304
|
+
The internal plan-change workflow composes Autoplan, Autodoc, and plan approval once. It owns the replan count, plan digest, and positive revision. Autoimplement and Monitor include this workflow instead of copying approval routes. A plan supplied by the caller or already selected by Monitor bypasses another decision. Only a changed plan digest enters the gate.
|
|
316
305
|
|
|
317
306
|
## Recovery and cancellation
|
|
318
307
|
|
|
@@ -325,27 +314,27 @@ Recovery follows these rules:
|
|
|
325
314
|
- ambiguous Telegram sends are not retried automatically;
|
|
326
315
|
- duplicate channel updates are harmless;
|
|
327
316
|
- stale responses are rejected;
|
|
328
|
-
- one
|
|
329
|
-
- the winning
|
|
317
|
+
- one human or timeout response creates one continuation;
|
|
318
|
+
- the winning human answer or timeout policy dismisses any pending Pi dialog;
|
|
330
319
|
- confirmed channel settlement is adopted without another remote call;
|
|
331
320
|
- failed channel settlement has a bounded retry count and cannot create an unbounded record loop; and
|
|
332
321
|
- cancellation resolves the owned waiting decision from durable state, even after restart, closes pending views, and prevents a later answer from continuing the run.
|
|
333
322
|
|
|
334
|
-
A decision with no available channel remains waiting and reports the configuration problem.
|
|
323
|
+
A required decision with no available channel remains waiting and reports the configuration problem. An automatic decision does not need a channel to apply its saved response after the deadline. A skipped plan policy creates no decision.
|
|
335
324
|
|
|
336
325
|
## Compatibility
|
|
337
326
|
|
|
338
|
-
|
|
327
|
+
This alpha change updates the current request, accepted-result, receipt, resolution, continuation, and snapshot contracts in place. Old active runs refuse resume through normal source and definition identity checks. There is no compatibility reader, migration, dual path, or new schema generation. Updated viewers label a human decision as a checkpoint, show its deadline and automatic action when present, and keep the canonical subject separate. Private channel configuration and transport identifiers remain hidden.
|
|
339
328
|
|
|
340
329
|
The engine remains independent from Pi and Telegram. Core code owns decision contracts, validation, durable acceptance, and continuation. The Pi extension owns UI and channel lifecycle. The Telegram adapter owns Bot API translation. Workflow definitions own only the question, choices, audience, and routes.
|
|
341
330
|
|
|
342
331
|
## Contract impact
|
|
343
332
|
|
|
344
333
|
- **Session state:** Pi records normal workflow messages and interactive decision results.
|
|
345
|
-
- **Other persistent data:**
|
|
334
|
+
- **Other persistent data:** decision requests and resolutions can carry a deadline, automatic response, and resolution provenance in the existing decision store. The private channel index remains rebuildable.
|
|
346
335
|
- **Pi internals:** none.
|
|
347
336
|
- **Public Pi API:** documented extension lifecycle and UI methods only.
|
|
348
|
-
- **Public pi-workflows API:** typed human choices, `humanDecision()`, `humanDecisionEdge()`, the channel interface, and the
|
|
337
|
+
- **Public pi-workflows API:** typed human choices, `humanDecision().onTimeout`, `humanDecisionEdge()`, the channel interface, the plan approval policy, and the shared plan-change workflow.
|
|
349
338
|
|
|
350
339
|
## Verification requirements
|
|
351
340
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Human decision presentations
|
|
2
2
|
|
|
3
|
-
This contract is implemented.
|
|
4
|
-
subject from the complete readable message shown to an operator.
|
|
5
|
-
|
|
3
|
+
This contract is implemented. Human decision requests separate their canonical
|
|
4
|
+
subject from the complete readable message shown to an operator. Human decisions use
|
|
5
|
+
one v1 contract with no legacy body form or parallel schema version.
|
|
6
6
|
The implementation plan is in
|
|
7
7
|
[the human decision presentations plan](plans/2026-08-19-human-decision-presentations-plan.md).
|
|
8
8
|
|
|
@@ -52,7 +52,7 @@ not see `subject` unless the workflow explicitly copies selected text into
|
|
|
52
52
|
|
|
53
53
|
## Request contract
|
|
54
54
|
|
|
55
|
-
A
|
|
55
|
+
A request uses `pi-workflows.human-decision-request.v1`. It contains:
|
|
56
56
|
|
|
57
57
|
| Field | Required | Meaning |
|
|
58
58
|
| -------------------- | -------- | ----------------------------------------------- |
|
|
@@ -255,25 +255,15 @@ It omits absent sections. It never serializes the plan object. `plan-approval`,
|
|
|
255
255
|
`monitor`, `autoplan`, `autodoc`, and `autoimplement` reuse this presenter where
|
|
256
256
|
they ask a person to approve a plan.
|
|
257
257
|
|
|
258
|
-
##
|
|
258
|
+
## Alpha cutover
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
The human-decision request, accepted result, receipt, delivery, and resolution use one
|
|
261
|
+
v1 schema family. The current structured subject and explicit presentation contract
|
|
262
|
+
replaced the former body request and parallel v2 records in place.
|
|
261
263
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
- An oversized v1 body remains answerable. The formatter keeps a bounded readable
|
|
266
|
-
prefix and adds an explicit omission notice with the full body digest and size.
|
|
267
|
-
It never hides omitted content behind an ellipsis.
|
|
268
|
-
- The compatibility formatter reads only the historical `body`, which was
|
|
269
|
-
already the display field. It never reads a new structured subject.
|
|
270
|
-
- V1 request bytes and digests do not change.
|
|
271
|
-
- Pending and accepted v1 decisions continue to use v1 validation and digest
|
|
272
|
-
rules.
|
|
273
|
-
- New preferred authoring emits v2. The existing body form remains a deprecated
|
|
274
|
-
compatibility overload until a separate removal is approved.
|
|
275
|
-
|
|
276
|
-
No migration rewrites run bundles or decision records.
|
|
264
|
+
Old waiting runs and human-decision state are incompatible. The runtime fails with a
|
|
265
|
+
reset instruction instead of reading, migrating, or silently reinterpreting them.
|
|
266
|
+
There is no compatibility reader, dual path, alias, or migration.
|
|
277
267
|
|
|
278
268
|
## Privacy and security
|
|
279
269
|
|
|
@@ -311,10 +301,10 @@ npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
|
|
|
311
301
|
npx -y @simpledoc/simpledoc check
|
|
312
302
|
```
|
|
313
303
|
|
|
314
|
-
Tests must cover schema validation, canonical digests,
|
|
304
|
+
Tests must cover schema validation, canonical digests, structured-value formatting,
|
|
315
305
|
plan rendering, Pi and Telegram content parity, unsafe text, Unicode, multipart
|
|
316
|
-
delivery, ambiguous sends, recovery, stale answers, viewer output,
|
|
317
|
-
that no channel serializes a subject as JSON.
|
|
306
|
+
delivery, ambiguous sends, recovery, stale answers, viewer output, incompatible-state
|
|
307
|
+
failure, and proof that no channel serializes a subject as JSON.
|
|
318
308
|
|
|
319
309
|
## Boundaries
|
|
320
310
|
|