@osolmaz/pi-workflows 0.12.0 → 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 +4 -3
- package/dist/builtins/autoimplement.workflow.d.ts +485 -126
- package/dist/builtins/autoimplement.workflow.js +17 -105
- package/dist/builtins/autoimplement.workflow.js.map +1 -1
- package/dist/builtins/catalog.js +4 -4
- package/dist/builtins/index.d.ts +2 -1
- package/dist/builtins/index.js +2 -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 +5 -3
- package/dist/builtins/sanity-check.workflow.js +105 -21
- package/dist/builtins/sanity-check.workflow.js.map +1 -1
- package/dist/extension/decision-channels.d.ts +2 -2
- package/dist/extension/decision-channels.js +22 -28
- package/dist/extension/decision-channels.js.map +1 -1
- package/dist/extension/index.js +62 -33
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/session-events.d.ts +2 -2
- package/dist/extension/widget.js +23 -3
- package/dist/extension/widget.js.map +1 -1
- 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/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 +14 -13
- 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 +2 -2
- package/dist/workflows/index.js +1 -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 +10 -0
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/store.js +5 -0
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +33 -45
- package/docs/HUMAN_DECISIONS.md +25 -35
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +14 -24
- package/docs/MONITOR.md +5 -11
- package/docs/WORKFLOW_COMPOSITION.md +8 -7
- package/docs/plans/2026-08-21-plan-change-approval-policy-plan.md +322 -0
- package/docs/plans/2026-08-21-sanity-check-plan.md +202 -94
- package/docs/run-bundles.md +6 -6
- package/docs/workflows.md +26 -6
- package/examples/workflows/approved-plan.workflow.ts +19 -46
- package/herdr-plugin.toml +1 -1
- package/package.json +7 -7
- 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/monitor/SKILL.md +31 -3
- package/skills/pi-workflows/SKILL.md +2 -1
- package/skills/sanity-check/SKILL.md +44 -0
- package/src/builtins/autoimplement.workflow.ts +19 -118
- package/src/builtins/catalog.ts +4 -4
- package/src/builtins/index.ts +11 -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 +186 -41
- package/src/extension/decision-channels.ts +29 -59
- package/src/extension/index.ts +79 -41
- package/src/extension/session-events.ts +2 -2
- package/src/extension/widget.ts +24 -5
- 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/composition.ts +9 -0
- package/src/workflows/decision-presentation.ts +56 -43
- package/src/workflows/engine.ts +17 -15
- package/src/workflows/errors.ts +24 -0
- package/src/workflows/human-decision.ts +218 -101
- package/src/workflows/index.ts +5 -11
- package/src/workflows/progress.ts +18 -3
- package/src/workflows/schema.ts +17 -0
- package/src/workflows/store.ts +5 -0
- package/src/workflows/types.ts +39 -56
- 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/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/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
|
|
|
@@ -268,9 +272,9 @@ Decision records live next to workflow run bundles under the pi-workflows state
|
|
|
268
272
|
- channel settlement results; and
|
|
269
273
|
- the continuation request and result.
|
|
270
274
|
|
|
271
|
-
The resolution record uses a no-replace create.
|
|
275
|
+
The resolution record uses a no-replace create. A valid human answer or eligible timeout response claims the same immutable resolution. The saved result includes `human` or `timeout` provenance. A timeout result has no human actor or channel identity. Cancellation writes a terminal tombstone that takes precedence over automatic continuation. A retry adopts the existing matching result. A conflicting or late answer receives an `already decided` result.
|
|
272
276
|
|
|
273
|
-
The continuation run ID is derived from the
|
|
277
|
+
The continuation run ID is derived from the decision ID. Recovery adopts an existing matching continuation or creates it once. A crash after resolution cannot run the next workflow step twice. 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 stay only in the private decision records and never enter the run bundle or model context.
|
|
274
278
|
|
|
275
279
|
SQLite may index pending decisions and channel leases, but immutable decision files remain the source of truth. The index is disposable and rebuildable.
|
|
276
280
|
|
|
@@ -286,33 +290,19 @@ pi-workflows keeps solution choice, documentation, and implementation in separat
|
|
|
286
290
|
|
|
287
291
|
`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
292
|
|
|
289
|
-
If later implementation, verification, review, comments, or CI evidence invalidates the plan,
|
|
293
|
+
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
294
|
|
|
291
295
|
## Reusable plan approval workflow
|
|
292
296
|
|
|
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:
|
|
297
|
+
pi-workflows ships a typed `plan-approval` workflow built on `humanDecision()`. Its policy has three modes:
|
|
300
298
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
input: ({ outputs }) => ({
|
|
305
|
-
plan: outputs.devise.plan,
|
|
306
|
-
planDigest: outputs.devise.planDigest,
|
|
307
|
-
audience: "operator",
|
|
308
|
-
}),
|
|
309
|
-
}),
|
|
310
|
-
},
|
|
311
|
-
```
|
|
299
|
+
- `auto` asks the configured audience and continues after the configured deadline. It defaults to audience `operator` and 10 minutes.
|
|
300
|
+
- `required` waits for an explicit human answer.
|
|
301
|
+
- `skip` creates no human decision and continues immediately.
|
|
312
302
|
|
|
313
|
-
|
|
303
|
+
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
304
|
|
|
315
|
-
|
|
305
|
+
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
306
|
|
|
317
307
|
## Recovery and cancellation
|
|
318
308
|
|
|
@@ -325,27 +315,27 @@ Recovery follows these rules:
|
|
|
325
315
|
- ambiguous Telegram sends are not retried automatically;
|
|
326
316
|
- duplicate channel updates are harmless;
|
|
327
317
|
- stale responses are rejected;
|
|
328
|
-
- one
|
|
329
|
-
- the winning
|
|
318
|
+
- one human or timeout response creates one continuation;
|
|
319
|
+
- the winning human answer or timeout policy dismisses any pending Pi dialog;
|
|
330
320
|
- confirmed channel settlement is adopted without another remote call;
|
|
331
321
|
- failed channel settlement has a bounded retry count and cannot create an unbounded record loop; and
|
|
332
322
|
- 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
323
|
|
|
334
|
-
A decision with no available channel remains waiting and reports the configuration problem.
|
|
324
|
+
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
325
|
|
|
336
326
|
## Compatibility
|
|
337
327
|
|
|
338
|
-
|
|
328
|
+
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
329
|
|
|
340
330
|
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
331
|
|
|
342
332
|
## Contract impact
|
|
343
333
|
|
|
344
334
|
- **Session state:** Pi records normal workflow messages and interactive decision results.
|
|
345
|
-
- **Other persistent data:**
|
|
335
|
+
- **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
336
|
- **Pi internals:** none.
|
|
347
337
|
- **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
|
|
338
|
+
- **Public pi-workflows API:** typed human choices, `humanDecision().onTimeout`, `humanDecisionEdge()`, the channel interface, the plan approval policy, and the shared plan-change workflow.
|
|
349
339
|
|
|
350
340
|
## Verification requirements
|
|
351
341
|
|
|
@@ -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
|
|
package/docs/MONITOR.md
CHANGED
|
@@ -38,7 +38,7 @@ The monitor checks a target, sends one status notification after every accepted
|
|
|
38
38
|
|
|
39
39
|
`repair` must set `authorized: true`. It can constrain scope, repository, base branch, merge behavior, and other implementation constraints. Omitted `merge` means the repair can prepare but cannot merge a pull request; merging requires explicit `merge: true`. Without this object the monitor is observation-only. Repair authority does not permit a protected model, benchmark, credential, hardware, spending, or scope change.
|
|
40
40
|
|
|
41
|
-
`repair.approval`
|
|
41
|
+
`repair.approval` uses `auto`, `required`, or `skip` mode. When omitted, Monitor uses `auto` with audience `operator`, a 10-minute timeout, and three allowed replans. Auto mode asks and then continues with the exact plan if no answer is accepted by the deadline. Required mode waits for an explicit human answer. Skip mode asks nothing. Continue starts implementation, stop ends the repair truthfully, and replan preserves exact operator text before the shared plan-change workflow runs again. The model-facing workflow tool cannot approve the gate.
|
|
42
42
|
|
|
43
43
|
`reportWhen` is removed. The monitor always reports after every accepted check.
|
|
44
44
|
|
|
@@ -102,17 +102,11 @@ prepare
|
|
|
102
102
|
├─ continue → schedule → sleep → check
|
|
103
103
|
└─ repair → repairGuard
|
|
104
104
|
├─ blocked → repairBlocked → repairReport → finish
|
|
105
|
-
└─
|
|
105
|
+
└─ planChange
|
|
106
106
|
├─ blocked → repairBlocked
|
|
107
|
-
└─
|
|
107
|
+
└─ ready → implementation: autoimplement
|
|
108
108
|
├─ blocked → repairBlocked
|
|
109
|
-
|
|
110
|
-
└─ approval: plan-approval
|
|
111
|
-
├─ stop → repairBlocked
|
|
112
|
-
├─ replan → initialDesign
|
|
113
|
-
└─ continue → implementation: autoimplement
|
|
114
|
-
├─ blocked → repairBlocked
|
|
115
|
-
└─ completed → check
|
|
109
|
+
└─ completed → check
|
|
116
110
|
```
|
|
117
111
|
|
|
118
112
|
- `prepare` is a `compute` node that validates and applies input defaults.
|
|
@@ -122,7 +116,7 @@ prepare
|
|
|
122
116
|
- `report` is a `notify` node that queues exactly one report.
|
|
123
117
|
- `decide` is a `compute` node that applies the route and check safety limit.
|
|
124
118
|
- `repairGuard` stops a repeated issue when a completed repair did not change its fingerprint or observed target state.
|
|
125
|
-
- `
|
|
119
|
+
- `planChange` and `implementation` are included workflows. Plan change owns Autoplan, Autodoc, approval policy, and exact-text replanning. Autoimplement receives the selected plan without another decision and enters its own plan-change mount only when later evidence requires a changed plan.
|
|
126
120
|
- `repairBlocked` and `repairReport` preserve a truthful blocked result and user notification.
|
|
127
121
|
- `schedule` is a function `action` that publishes the next-check time.
|
|
128
122
|
- `sleep` is the existing runtime-owned shell wait.
|
|
@@ -265,7 +265,7 @@ monitor
|
|
|
265
265
|
|
|
266
266
|
`autoimplement` requires a clear existing plan, but the structured `plan` input is optional because the plan can already be in conversation context or canonical documentation. It blocks when it cannot find a clear plan. It skips autodoc when documentation is current and includes autodoc when documentation is missing or stale. The absence of `input.plan` never routes to initial autoplan.
|
|
267
267
|
|
|
268
|
-
Autoimplement includes
|
|
268
|
+
Autoimplement includes the shared plan-change workflow only as evidence-driven `redesign`. When implementation, verification, review, comments, or CI proves that the approach is wrong, the shared workflow runs Autoplan, Autodoc, the configured plan decision, and bounded replanning before implementation resumes. Local bugs go to a fix step instead. Existing supplied or discovered plans bypass the decision.
|
|
269
269
|
|
|
270
270
|
Review rounds record findings at every severity from P0 through P2. P0 or P1 findings require another implementation and review round. A P2-only round can be addressed, but the workflow does not run the reviewer again solely because P2 work changed files.
|
|
271
271
|
|
|
@@ -281,16 +281,17 @@ Monitor remains observation-only unless its input explicitly authorizes mutation
|
|
|
281
281
|
|
|
282
282
|
```text
|
|
283
283
|
check
|
|
284
|
-
->
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
->
|
|
284
|
+
-> planChange
|
|
285
|
+
-> autoplan
|
|
286
|
+
-> autodoc
|
|
287
|
+
-> plan-approval
|
|
288
|
+
-> replan: autoplan
|
|
288
289
|
-> implementation: autoimplement
|
|
289
|
-
-> redesign:
|
|
290
|
+
-> redesign: planChange when needed
|
|
290
291
|
-> check
|
|
291
292
|
```
|
|
292
293
|
|
|
293
|
-
The
|
|
294
|
+
The shared plan-change workflow creates, records, and gates each repair plan. Its default policy asks the `operator` audience and continues after 10 minutes without an answer. Required mode waits for an explicit answer. Skip mode creates no decision. Monitor passes the selected plan into Autoimplement, so Autoimplement does not ask about that digest again. A later Autoimplement redesign uses the same shared workflow for the changed digest. The monitor checks the target again after implementation and does not trust a repair claim by itself.
|
|
294
295
|
|
|
295
296
|
A protected change to model choice, benchmark method, credentials, hardware, spending authority, or another user decision exits as blocked. The workflow never changes the protected part of the task silently.
|
|
296
297
|
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Plan Change Approval Policy Plan
|
|
3
|
+
author: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
|
|
4
|
+
date: 2026-08-21
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Plan change approval policy plan
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Autoimplement and Monitor must use one shared workflow whenever they create or revise a plan. The shared workflow plans, records the plan in canonical documentation, asks for the configured human decision, and handles bounded replanning.
|
|
12
|
+
|
|
13
|
+
The default policy is autonomous. It asks the `operator` audience to continue, stop, or replan. If no valid answer is accepted within 10 minutes, it continues with the exact presented plan. A required policy waits for an explicit answer. A skip policy continues immediately without creating a human decision.
|
|
14
|
+
|
|
15
|
+
The timeout default belongs to the general `humanDecision()` contract. It must be durable, deterministic, bound to the exact request and plan digest, and separate from a human answer. Autoimplement and Monitor must not contain their own decision timers or copies of approval and replan logic.
|
|
16
|
+
|
|
17
|
+
## Goals
|
|
18
|
+
|
|
19
|
+
The change must provide these results:
|
|
20
|
+
|
|
21
|
+
- Every plan newly created or changed by Autoimplement or Monitor passes through one shared plan-change workflow.
|
|
22
|
+
- Existing supplied or discovered plans do not receive a new decision.
|
|
23
|
+
- The default policy asks for a decision and continues after 10 minutes when there is no answer.
|
|
24
|
+
- Operators can require an explicit answer or skip the decision.
|
|
25
|
+
- Pi and Telegram show and settle the same durable decision.
|
|
26
|
+
- A human answer, timeout default, and cancellation cannot create more than one continuation.
|
|
27
|
+
- Cancellation remains immediate and terminal.
|
|
28
|
+
- Repeated entry with the same plan digest does not create another decision.
|
|
29
|
+
- Monitor does not cause Autoimplement to ask again for the plan that Monitor already selected.
|
|
30
|
+
|
|
31
|
+
## Approval policy
|
|
32
|
+
|
|
33
|
+
Autoimplement and Monitor use the same policy shape:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
type PlanApprovalPolicy = {
|
|
37
|
+
mode: "auto" | "required" | "skip";
|
|
38
|
+
audience?: string;
|
|
39
|
+
timeoutMinutes?: number;
|
|
40
|
+
maxReplans?: number;
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The workflow input field remains `approval`. When it is absent, parsing supplies this policy:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mode": "auto",
|
|
49
|
+
"audience": "operator",
|
|
50
|
+
"timeoutMinutes": 10,
|
|
51
|
+
"maxReplans": 3
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The modes have these meanings:
|
|
56
|
+
|
|
57
|
+
- `auto` creates a human decision. It continues with the presented plan when no valid answer is accepted before the deadline.
|
|
58
|
+
- `required` creates a human decision with no automatic response. It waits for `continue`, `stop`, or `replan`.
|
|
59
|
+
- `skip` creates no human decision and continues immediately.
|
|
60
|
+
|
|
61
|
+
`audience` defaults to `operator`. `timeoutMinutes` applies only to `auto` and defaults to 10. `maxReplans` defaults to 3 and bounds the exact-instructions replan loop. Parsers reject unknown fields, unsupported combinations, non-positive timeouts, and invalid replan limits.
|
|
62
|
+
|
|
63
|
+
The skills must map common requests as follows:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"approval": {
|
|
68
|
+
"mode": "required"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use this for requests such as “block on plan changes.”
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"approval": {
|
|
78
|
+
"mode": "skip"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Use this for requests such as “do not block on plan changes.” Omitting `approval` uses the 10-minute autonomous default.
|
|
84
|
+
|
|
85
|
+
## Shared plan-change workflow
|
|
86
|
+
|
|
87
|
+
Add one internal finite workflow that owns this sequence:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
autoplan
|
|
91
|
+
-> autodoc
|
|
92
|
+
-> plan-approval
|
|
93
|
+
-> continue -> ready
|
|
94
|
+
-> stop -> blocked
|
|
95
|
+
-> replan -> autoplan
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The workflow receives the planning problem, scope, constraints, repository and document context, previous plan, new evidence, and approval policy. It returns either:
|
|
99
|
+
|
|
100
|
+
- `ready`, with the selected plan, plan digest, canonical documents, revision, and decision provenance; or
|
|
101
|
+
- `blocked`, with the reason and evidence.
|
|
102
|
+
|
|
103
|
+
The workflow owns the replan count and passes exact operator instructions back to Autoplan. Each changed plan gets a new positive revision. The plan digest binds the plan, documentation result, approval request, and final output.
|
|
104
|
+
|
|
105
|
+
The workflow bypasses the human-decision node in `skip` mode but still records `skipped` as the plan selection provenance. It does not create a synthetic human receipt.
|
|
106
|
+
|
|
107
|
+
Promote the existing approved-plan composition pattern into this internal built-in workflow. Keep `plan-approval` as the low-level reusable decision workflow. Do not add a standalone `plan-approval` skill.
|
|
108
|
+
|
|
109
|
+
## Human-decision timeout default
|
|
110
|
+
|
|
111
|
+
Extend the public `humanDecision()` definition with a general optional timeout response:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
humanDecision({
|
|
115
|
+
audience: "operator",
|
|
116
|
+
choices,
|
|
117
|
+
request,
|
|
118
|
+
onTimeout: {
|
|
119
|
+
afterMs: 10 * 60_000,
|
|
120
|
+
response: { choice: "continue" },
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The policy may also be derived from the node context so the shared plan-change workflow can use its parsed input. `afterMs` must be a positive finite duration. The response must satisfy the same typed choice and input contract as a human response. An absent `onTimeout` keeps the current indefinite wait.
|
|
126
|
+
|
|
127
|
+
When the engine creates the request, it computes and persists:
|
|
128
|
+
|
|
129
|
+
- the absolute expiry time;
|
|
130
|
+
- the validated default response;
|
|
131
|
+
- the request and presentation digests;
|
|
132
|
+
- the exact node and attempt identity; and
|
|
133
|
+
- the plan digest and revision already present in the decision subject.
|
|
134
|
+
|
|
135
|
+
The request digest includes the deadline policy and default response. A changed deadline, response, plan, or revision therefore creates a different request identity.
|
|
136
|
+
|
|
137
|
+
## Resolution and provenance
|
|
138
|
+
|
|
139
|
+
A timeout default is an automatic workflow-policy resolution. It is not a human answer and must not use a human actor or channel identity.
|
|
140
|
+
|
|
141
|
+
The existing resolution record gains a distinct timeout-default outcome and provenance in place. Human acceptance, timeout default, and cancellation all compete for the same immutable resolution record. The first valid resolution wins. The accepted workflow output states whether the result came from:
|
|
142
|
+
|
|
143
|
+
- `human`;
|
|
144
|
+
- `timeout`;
|
|
145
|
+
- `skipped`; or
|
|
146
|
+
- `cancelled`, where a terminal record is exposed.
|
|
147
|
+
|
|
148
|
+
A human answer is valid only before the deadline and while no terminal resolution exists. A late answer cannot replace a timeout default. A timeout resolver must re-read an existing resolution and adopt it rather than create another result.
|
|
149
|
+
|
|
150
|
+
The plan-approval continue result carries the plan digest, decision revision, response, and resolution provenance. A timeout result carries no human actor. A skipped result carries no human-decision receipt.
|
|
151
|
+
|
|
152
|
+
## Recovery and ownership
|
|
153
|
+
|
|
154
|
+
Use the existing one-second human-decision recovery loop. Do not add a service, daemon, controller, or second timer system.
|
|
155
|
+
|
|
156
|
+
For an unresolved request with an eligible timeout default, the current owner must:
|
|
157
|
+
|
|
158
|
+
1. confirm that the parent run is still waiting at the same request;
|
|
159
|
+
2. confirm that the request deadline has passed;
|
|
160
|
+
3. confirm that the run and decision are not cancelled;
|
|
161
|
+
4. atomically write or adopt the timeout-default resolution;
|
|
162
|
+
5. create or adopt the deterministic continuation record;
|
|
163
|
+
6. start the continuation only when the owning process can claim it; and
|
|
164
|
+
7. settle every open Pi and Telegram view.
|
|
165
|
+
|
|
166
|
+
If no owner is active at the deadline, the request becomes eligible at that time. The next active owner resolves it and starts or adopts the continuation. The saved absolute deadline means a restart does not restart the 10-minute period.
|
|
167
|
+
|
|
168
|
+
Auto mode must continue after the deadline even when no decision channel is configured. Required mode remains waiting and reports the missing channel configuration. Skip mode does not use a channel.
|
|
169
|
+
|
|
170
|
+
## Cancellation and races
|
|
171
|
+
|
|
172
|
+
Explicit workflow cancellation remains terminal. It must cancel the waiting decision, close channel views, and prevent a timeout continuation.
|
|
173
|
+
|
|
174
|
+
The cancellation path and timeout resolver must check the durable run cancellation state before and after claiming the decision resolution and before starting a continuation. If cancellation races with an automatic resolution, the cancelled run and its deterministic continuation must not execute more workflow nodes. A later recovery pass must not revive either run.
|
|
175
|
+
|
|
176
|
+
A human answer and timeout default use the immutable resolution as their race boundary. Tests must cover both winners at the deadline boundary and prove that only one continuation can exist.
|
|
177
|
+
|
|
178
|
+
## Autoimplement integration
|
|
179
|
+
|
|
180
|
+
Autoimplement must use the shared plan-change workflow only for a changed plan produced by its internal redesign route.
|
|
181
|
+
|
|
182
|
+
These plans bypass the gate:
|
|
183
|
+
|
|
184
|
+
- an explicit plan supplied in the Autoimplement input;
|
|
185
|
+
- a current plan found by plan discovery; and
|
|
186
|
+
- a plan passed by Monitor after Monitor completed the shared plan-change workflow.
|
|
187
|
+
|
|
188
|
+
When new evidence routes Autoimplement to redesign, the shared workflow receives the current plan as `previousPlan` and the new issue as evidence. A changed ready plan returns to implementation. A stopped or exhausted plan change returns blocked. The same digest must not create another decision after resume or route re-entry.
|
|
189
|
+
|
|
190
|
+
Remove Autoimplement’s duplicate approval route, approval input mapping, and replan guard. Keep only policy parsing and the mapping into the shared workflow.
|
|
191
|
+
|
|
192
|
+
## Monitor integration
|
|
193
|
+
|
|
194
|
+
Each Monitor repair that requires a new plan enters the shared plan-change workflow. This includes every exact-instructions replan requested by the operator.
|
|
195
|
+
|
|
196
|
+
A ready plan is passed to Autoimplement with its plan digest and canonical documentation state. Autoimplement treats it as selected and does not ask about it again. If Autoimplement later produces a changed plan because of implementation, review, or CI evidence, Autoimplement uses the shared workflow for that new digest.
|
|
197
|
+
|
|
198
|
+
Remove Monitor’s duplicate approval route, plan-approval input mapping, and replan guard. Keep the monitor repair authorization, no-progress protection, and post-repair observation unchanged.
|
|
199
|
+
|
|
200
|
+
## Skills and examples
|
|
201
|
+
|
|
202
|
+
Update the Autoimplement and Monitor skills with complete one-shot calls for:
|
|
203
|
+
|
|
204
|
+
- omitted approval, which uses the 10-minute autonomous default;
|
|
205
|
+
- `approval.mode: "required"`; and
|
|
206
|
+
- `approval.mode: "skip"`.
|
|
207
|
+
|
|
208
|
+
The examples must retain the required task, scope, constraints, repository, base branch, merge authority, and other workflow-specific input. They must not show a model calling the answer action for a protected human decision.
|
|
209
|
+
|
|
210
|
+
Update the workflow authoring skill and examples to explain `humanDecision().onTimeout`, timeout provenance, and the rule that only a policy-defined response can run automatically.
|
|
211
|
+
|
|
212
|
+
## Public contracts and persisted data
|
|
213
|
+
|
|
214
|
+
Change the current alpha contracts in place:
|
|
215
|
+
|
|
216
|
+
- add `onTimeout` to the public typed human-decision definition;
|
|
217
|
+
- add the persisted deadline and default response to the current human-decision request contract;
|
|
218
|
+
- add timeout-default provenance to the current accepted result, receipt, resolution, continuation, and channel settlement handling where it applies;
|
|
219
|
+
- add the shared `PlanApprovalPolicy` and plan-change input and output types;
|
|
220
|
+
- change Autoimplement and Monitor approval inputs to the shared policy; and
|
|
221
|
+
- keep existing camelCase JSON fields and current schema and contract identifiers.
|
|
222
|
+
|
|
223
|
+
Persisted request and resolution JSON remains under the current human-decision state root. Run bundles remain under the current run store. Add no migration reader, dual read, dual write, alias, feature flag, or new schema generation.
|
|
224
|
+
|
|
225
|
+
Increment the affected built-in revisions as one hard alpha cutover:
|
|
226
|
+
|
|
227
|
+
- Autoimplement revision 6 to 7;
|
|
228
|
+
- Monitor revision 7 to 8; and
|
|
229
|
+
- plan-approval revision 2 to 3.
|
|
230
|
+
|
|
231
|
+
Older active runs refuse resume through the existing source-change behavior. The new internal plan-change workflow does not need to be a user-facing catalog entry or skill.
|
|
232
|
+
|
|
233
|
+
## Documentation
|
|
234
|
+
|
|
235
|
+
When implementation ships, update:
|
|
236
|
+
|
|
237
|
+
- `docs/HUMAN_DECISIONS.md` for timeout responses, provenance, recovery, races, and channel behavior;
|
|
238
|
+
- `docs/WORKFLOW_COMPOSITION.md` for the shared plan-change workflow;
|
|
239
|
+
- `docs/workflows.md` for the public API and Autoimplement behavior;
|
|
240
|
+
- `docs/MONITOR.md` for repair-plan decisions;
|
|
241
|
+
- `docs/run-bundles.md` for request, resolution, continuation, and snapshot fields;
|
|
242
|
+
- Autoimplement and Monitor skill text and examples; and
|
|
243
|
+
- package examples and generated layout fixtures affected by the graph change.
|
|
244
|
+
|
|
245
|
+
Keep the previous human-decision and composition plans unchanged as historical records.
|
|
246
|
+
|
|
247
|
+
## Implementation steps
|
|
248
|
+
|
|
249
|
+
1. Add and validate the typed `humanDecision().onTimeout` contract. Bind the validated default response and absolute deadline into request identity and persisted request data.
|
|
250
|
+
2. Extend the human-decision store with one atomic timeout-default resolution operation. Preserve one immutable resolution and one deterministic continuation.
|
|
251
|
+
3. Update extension decision recovery to resolve eligible defaults, recover after restart, settle channels, and start only the owned continuation. Keep cancellation checks around resolution and continuation claims.
|
|
252
|
+
4. Update Pi and Telegram decision presentation and settlement so the deadline and automatic action are clear and a completed timeout closes pending views.
|
|
253
|
+
5. Extend plan-approval with the shared policy and explicit human, timeout, and skipped provenance.
|
|
254
|
+
6. Add the internal shared plan-change workflow with Autoplan, Autodoc, plan approval, and bounded exact-instructions replanning.
|
|
255
|
+
7. Replace the duplicate Autoimplement planning approval path with the shared workflow and gate only changed internal redesign results.
|
|
256
|
+
8. Replace the duplicate Monitor repair-plan approval path with the shared workflow and pass its selected plan to Autoimplement without another decision.
|
|
257
|
+
9. Update public exports, current schemas, built-in revisions, skills, examples, documentation, and generated fixtures.
|
|
258
|
+
10. Run all unit, integration, real-Pi, documentation, formatting, dependency-boundary, and package-resource checks.
|
|
259
|
+
|
|
260
|
+
## Tests
|
|
261
|
+
|
|
262
|
+
Use fake clocks, temporary directories, and fake channels. Tests must not call a real model, use a real Telegram credential, or mutate a real remote.
|
|
263
|
+
|
|
264
|
+
Cover:
|
|
265
|
+
|
|
266
|
+
- `onTimeout` type and runtime validation;
|
|
267
|
+
- absent timeout behavior;
|
|
268
|
+
- the default 10-minute deadline;
|
|
269
|
+
- custom positive timeout values;
|
|
270
|
+
- invalid timeout and response combinations;
|
|
271
|
+
- auto, required, and skip policy parsing;
|
|
272
|
+
- human continue, stop, and exact-text replan;
|
|
273
|
+
- human-answer and timeout-default races with each winner;
|
|
274
|
+
- timeout provenance without a human actor;
|
|
275
|
+
- late answer rejection;
|
|
276
|
+
- immediate terminal cancellation before and during timeout resolution;
|
|
277
|
+
- one continuation after concurrent or repeated recovery;
|
|
278
|
+
- restart recovery before and after the deadline;
|
|
279
|
+
- auto mode with no configured channel;
|
|
280
|
+
- required mode with no configured channel;
|
|
281
|
+
- Pi and Telegram delivery, expiry text, and settlement;
|
|
282
|
+
- plan digest and positive revision binding;
|
|
283
|
+
- no duplicate decision for the same digest;
|
|
284
|
+
- bounded replans;
|
|
285
|
+
- Autoimplement changed-plan routing;
|
|
286
|
+
- Autoimplement supplied and discovered plan bypass;
|
|
287
|
+
- Monitor repair-plan routing;
|
|
288
|
+
- no second decision when Monitor passes its selected plan to Autoimplement;
|
|
289
|
+
- later Autoimplement redesign after Monitor selection;
|
|
290
|
+
- built-in revision refusal for old active runs;
|
|
291
|
+
- package skill and workflow discovery; and
|
|
292
|
+
- real-Pi continuation with a short fake-clock deadline and no real model.
|
|
293
|
+
|
|
294
|
+
## Verification
|
|
295
|
+
|
|
296
|
+
Run:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
npm run check
|
|
300
|
+
npm run test:e2e
|
|
301
|
+
npx slophammer-ts@latest dry .
|
|
302
|
+
npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
|
|
303
|
+
npx -y @simpledoc/simpledoc check
|
|
304
|
+
git diff --check
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Inspect the complete public diff before each commit, push, or pull-request update. Verify GitHub CI and Pi Reviewer before delivery.
|
|
308
|
+
|
|
309
|
+
## Boundaries
|
|
310
|
+
|
|
311
|
+
This work changes only the pi-workflows repository. It may change the workflow engine, extension decision recovery, built-in workflow composition, skills, tests, examples, fixtures, and documentation needed for this policy.
|
|
312
|
+
|
|
313
|
+
It must not:
|
|
314
|
+
|
|
315
|
+
- change Pi core or use undocumented Pi APIs;
|
|
316
|
+
- add a service, daemon, controller, scheduler, or persistence location;
|
|
317
|
+
- change external services, credentials, Telegram configuration, CI policy, or unrelated repositories;
|
|
318
|
+
- add a standalone plan-approval skill;
|
|
319
|
+
- queue, revive, or extend deferred successor turns;
|
|
320
|
+
- add compatibility readers, migrations, dual paths, new schema generations, aliases, or feature flags;
|
|
321
|
+
- merge the implementation pull request; or
|
|
322
|
+
- publish a package or release.
|