@osolmaz/pi-workflows 0.11.2 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -10
- package/dist/builtins/autoimplement-command-batches.d.ts +52 -0
- package/dist/builtins/autoimplement-command-batches.js +258 -0
- package/dist/builtins/autoimplement-command-batches.js.map +1 -0
- package/dist/builtins/autoimplement.workflow.d.ts +509 -124
- package/dist/builtins/autoimplement.workflow.js +884 -327
- package/dist/builtins/autoimplement.workflow.js.map +1 -1
- package/dist/builtins/catalog.js +5 -3
- package/dist/builtins/catalog.js.map +1 -1
- package/dist/builtins/index.d.ts +4 -1
- package/dist/builtins/index.js +3 -1
- package/dist/builtins/index.js.map +1 -1
- package/dist/builtins/monitor.workflow.d.ts +2 -4
- package/dist/builtins/monitor.workflow.js +26 -128
- package/dist/builtins/monitor.workflow.js.map +1 -1
- package/dist/builtins/pi-agent-group.d.ts +72 -0
- package/dist/builtins/pi-agent-group.js +1087 -0
- package/dist/builtins/pi-agent-group.js.map +1 -0
- package/dist/builtins/plan-approval.workflow.d.ts +39 -5
- package/dist/builtins/plan-approval.workflow.js +92 -14
- package/dist/builtins/plan-approval.workflow.js.map +1 -1
- package/dist/builtins/plan-change.workflow.d.ts +301 -0
- package/dist/builtins/plan-change.workflow.js +256 -0
- package/dist/builtins/plan-change.workflow.js.map +1 -0
- package/dist/builtins/plan-presentation.js +2 -2
- package/dist/builtins/plan-presentation.js.map +1 -1
- package/dist/builtins/sanity-check.workflow.d.ts +85 -0
- package/dist/builtins/sanity-check.workflow.js +482 -0
- package/dist/builtins/sanity-check.workflow.js.map +1 -0
- package/dist/controllers/sqlite.d.ts +90 -2
- package/dist/controllers/sqlite.js +380 -5
- package/dist/controllers/sqlite.js.map +1 -1
- package/dist/extension/decision-channels.d.ts +2 -2
- package/dist/extension/decision-channels.js +29 -35
- package/dist/extension/decision-channels.js.map +1 -1
- package/dist/extension/deferred-turn-coordinator.d.ts +32 -0
- package/dist/extension/deferred-turn-coordinator.js +143 -0
- package/dist/extension/deferred-turn-coordinator.js.map +1 -0
- package/dist/extension/deferred-turn.d.ts +44 -0
- package/dist/extension/deferred-turn.js +110 -0
- package/dist/extension/deferred-turn.js.map +1 -0
- package/dist/extension/index.js +348 -80
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/session-events.d.ts +2 -2
- package/dist/extension/step-message.d.ts +1 -0
- package/dist/extension/step-message.js.map +1 -1
- package/dist/extension/widget.js +23 -3
- package/dist/extension/widget.js.map +1 -1
- package/dist/herdr/setup.js +4 -4
- package/dist/render/graph-render.js +1 -2
- package/dist/render/graph-render.js.map +1 -1
- package/dist/viewer/render.js +7 -6
- package/dist/viewer/render.js.map +1 -1
- package/dist/workflows/catalog.js +7 -2
- package/dist/workflows/catalog.js.map +1 -1
- package/dist/workflows/command-batch.d.ts +38 -0
- package/dist/workflows/command-batch.js +176 -0
- package/dist/workflows/command-batch.js.map +1 -0
- package/dist/workflows/composition.js +8 -0
- package/dist/workflows/composition.js.map +1 -1
- package/dist/workflows/decision-presentation.d.ts +1 -1
- package/dist/workflows/decision-presentation.js +51 -38
- package/dist/workflows/decision-presentation.js.map +1 -1
- package/dist/workflows/engine.d.ts +2 -2
- package/dist/workflows/engine.js +22 -17
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/errors.d.ts +13 -0
- package/dist/workflows/errors.js +15 -0
- package/dist/workflows/errors.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +16 -4
- package/dist/workflows/human-decision.js +175 -72
- package/dist/workflows/human-decision.js.map +1 -1
- package/dist/workflows/index.d.ts +3 -2
- package/dist/workflows/index.js +2 -1
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/progress.d.ts +1 -0
- package/dist/workflows/progress.js +15 -3
- package/dist/workflows/progress.js.map +1 -1
- package/dist/workflows/schema.js +12 -1
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/shell.d.ts +4 -0
- package/dist/workflows/shell.js +6 -0
- package/dist/workflows/shell.js.map +1 -1
- package/dist/workflows/store.js +8 -1
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +37 -48
- package/docs/2026-08-18-herdr-piw-plan.md +1 -1
- package/docs/2026-08-20-durable-workflow-launch-plan.md +19 -23
- package/docs/CONTROLLERS.md +2 -2
- package/docs/DEFERRED_TURNS.md +298 -0
- package/docs/DESIGN_PHILOSOPHY.md +1 -1
- package/docs/HUMAN_DECISIONS.md +30 -40
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +17 -27
- package/docs/MONITOR.md +7 -13
- package/docs/WORKFLOW_COMPOSITION.md +10 -9
- package/docs/WORKFLOW_STEP_MESSAGES.md +5 -5
- package/docs/WORKFLOW_UPDATES.md +28 -5
- package/docs/plans/2026-08-04-controller-runtime-plan.md +1 -1
- package/docs/plans/2026-08-05-always-on-workflows-plan.md +1 -1
- package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +9 -9
- package/docs/plans/2026-08-13-built-in-workflow-catalog-plan.md +1 -1
- package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
- package/docs/plans/2026-08-16-workflow-updates-plan.md +3 -3
- package/docs/plans/2026-08-17-bundled-skills-plan.md +6 -6
- package/docs/plans/2026-08-19-human-decision-gates-plan.md +5 -5
- package/docs/plans/2026-08-19-human-decision-presentations-plan.md +1 -1
- package/docs/plans/2026-08-19-provider-compatible-workflow-tool-schema-plan.md +1 -1
- package/docs/plans/2026-08-19-workflow-composition-plan.md +6 -6
- package/docs/plans/2026-08-20-autoimplement-blocker-challenge-plan.md +3 -3
- package/docs/plans/2026-08-20-bounded-command-batches-plan.md +206 -0
- package/docs/plans/2026-08-20-herdr-plugin-sync-plan.md +9 -9
- package/docs/plans/2026-08-21-autoimplement-timeout-fallback-plan.md +242 -0
- package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +324 -0
- package/docs/plans/2026-08-21-plan-change-approval-policy-plan.md +322 -0
- package/docs/plans/2026-08-21-sanity-check-plan.md +283 -0
- package/docs/run-bundles.md +8 -6
- package/docs/workflows.md +85 -22
- package/examples/workflows/approved-plan.workflow.ts +19 -46
- package/examples/workflows/command-batch.workflow.ts +50 -0
- package/examples/workflows/sanity-check.workflow.ts +1 -0
- package/herdr-plugin.toml +3 -3
- package/package.json +7 -7
- package/schemas/decision-presentation-v1.schema.json +1 -1
- package/schemas/human-decision-accepted-v1.schema.json +16 -4
- package/schemas/human-decision-answer-attempt-v1.schema.json +1 -1
- package/schemas/human-decision-cancellation-v1.schema.json +1 -1
- package/schemas/human-decision-continuation-v1.schema.json +11 -2
- package/schemas/human-decision-delivery-v1.schema.json +9 -1
- package/schemas/human-decision-receipt-v1.schema.json +9 -1
- package/schemas/human-decision-request-v1.schema.json +25 -5
- package/schemas/human-decision-resolution-v1.schema.json +1 -1
- package/schemas/human-decision-settlement-v1.schema.json +1 -1
- package/skills/autodoc/SKILL.md +33 -2
- package/skills/autoimplement/SKILL.md +93 -12
- package/skills/autoplan/SKILL.md +26 -2
- package/skills/monitor/SKILL.md +66 -24
- package/skills/pi-workflows/SKILL.md +21 -6
- package/skills/sanity-check/SKILL.md +44 -0
- package/src/builtins/autoimplement-command-batches.ts +364 -0
- package/src/builtins/autoimplement.workflow.ts +1075 -370
- package/src/builtins/catalog.ts +5 -3
- package/src/builtins/index.ts +24 -0
- package/src/builtins/monitor.workflow.ts +27 -150
- package/src/builtins/pi-agent-group.ts +1407 -0
- package/src/builtins/plan-approval.workflow.ts +157 -24
- package/src/builtins/plan-change.workflow.ts +321 -0
- package/src/builtins/plan-presentation.ts +2 -2
- package/src/builtins/sanity-check.workflow.ts +769 -0
- package/src/controllers/sqlite.ts +580 -7
- package/src/extension/decision-channels.ts +36 -66
- package/src/extension/deferred-turn-coordinator.ts +171 -0
- package/src/extension/deferred-turn.ts +166 -0
- package/src/extension/index.ts +438 -90
- package/src/extension/session-events.ts +2 -2
- package/src/extension/step-message.ts +1 -0
- package/src/extension/widget.ts +24 -5
- package/src/herdr/setup.ts +4 -4
- package/src/render/graph-render.ts +1 -2
- package/src/viewer/render.ts +7 -6
- package/src/workflows/catalog.ts +7 -2
- package/src/workflows/command-batch.ts +254 -0
- package/src/workflows/composition.ts +9 -0
- package/src/workflows/decision-presentation.ts +56 -43
- package/src/workflows/engine.ts +25 -20
- package/src/workflows/errors.ts +24 -0
- package/src/workflows/human-decision.ts +218 -101
- package/src/workflows/index.ts +20 -11
- package/src/workflows/progress.ts +18 -3
- package/src/workflows/schema.ts +19 -1
- package/src/workflows/shell.ts +10 -0
- package/src/workflows/store.ts +8 -1
- package/src/workflows/types.ts +43 -59
- package/schemas/human-decision-accepted-v2.schema.json +0 -50
- package/schemas/human-decision-delivery-v2.schema.json +0 -36
- package/schemas/human-decision-receipt-v2.schema.json +0 -39
- package/schemas/human-decision-request-v2.schema.json +0 -69
- package/schemas/human-decision-resolution-v2.schema.json +0 -27
|
@@ -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.
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Run Sanity Check with Provider Extensions
|
|
3
|
+
author: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
|
|
4
|
+
date: 2026-08-21
|
|
5
|
+
updated: 2026-08-22
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Run Sanity Check with Provider Extensions
|
|
9
|
+
|
|
10
|
+
## Goal
|
|
11
|
+
|
|
12
|
+
Use direct Pi SDK sessions for the built-in `sanity-check` workflow. Each reviewer gets an independent in-memory context. Each child can load the extension that owns its exact configured model provider, while only the parent workflow action can control workflow state.
|
|
13
|
+
|
|
14
|
+
The child must use the configured provider, model, thinking level, and provider-owned authentication. It must fail before prompting if that exact dispatch is not available. It must never silently use OpenRouter, Kimi, a local model, or another fallback.
|
|
15
|
+
|
|
16
|
+
The workflow keeps only the final bounded answer and safe operational facts. It does not keep child prompts, reasoning, message history, tool arguments, tool results, repository content, credentials, or extension-private state.
|
|
17
|
+
|
|
18
|
+
## Scope
|
|
19
|
+
|
|
20
|
+
The change is limited to Pi Workflows. It changes the private SDK agent-group runner, Sanity Check composition, extension admission, model runtime construction, tests, and canonical documentation.
|
|
21
|
+
|
|
22
|
+
The workflow continues to use existing `action`, `compute`, and `notify` nodes. `src/workflows` and `WorkflowActionContext` remain Pi-independent. The change does not add a workflow primitive, public agent-group export, persisted schema, child workflow run, service, queue, store, transport, Pi core change, or private Pi API.
|
|
23
|
+
|
|
24
|
+
Sanity Check keeps its existing input, review areas, prompts, evidence rules, session counts, strict result validation, verdicts, final notification, and progress schema.
|
|
25
|
+
|
|
26
|
+
## Child session contract
|
|
27
|
+
|
|
28
|
+
Each child session:
|
|
29
|
+
|
|
30
|
+
- has independent in-memory context and history;
|
|
31
|
+
- uses `SessionManager.inMemory` and creates no Pi session file;
|
|
32
|
+
- owns a separate `ModelRuntime`, provider instance, extension runtime, resource loader, and `AgentSession`;
|
|
33
|
+
- can use only the verified built-in `read`, `grep`, `find`, and `ls` tools;
|
|
34
|
+
- may load the extension that registers the exact configured provider;
|
|
35
|
+
- may load another behavior extension only through an explicit private allowlist;
|
|
36
|
+
- loads no skills, prompt templates, themes, or context files;
|
|
37
|
+
- does not receive the workflow tool, workflow commands, parent run id, node id, attempt id, update channel, or workflow callback;
|
|
38
|
+
- returns only bounded final assistant text and bounded safe lifecycle facts;
|
|
39
|
+
- shares the parent Node process and does not provide OS process isolation.
|
|
40
|
+
|
|
41
|
+
Pi extensions are trusted in-process code. The runner prevents normal model, tool, command, and callback access to workflow state. It does not sandbox an extension that directly uses the filesystem or network.
|
|
42
|
+
|
|
43
|
+
## Input and review modes
|
|
44
|
+
|
|
45
|
+
The workflow input stays unchanged. Serial mode remains the default.
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mode": "serial",
|
|
50
|
+
"baseRef": "origin/main"
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`mode` is `serial` or `parallel`. The current repository and checked-out branch are the contribution under review. When `baseRef` is omitted, the workflow tries the remote default branch, the current branch upstream, and the first parent, then uses `HEAD` for a working-tree-only review.
|
|
55
|
+
|
|
56
|
+
Serial mode creates one review session for all four review areas, then one verification session. It uses two model sessions.
|
|
57
|
+
|
|
58
|
+
Parallel mode creates four focused review sessions at the same time, then one verification session. It uses five model sessions.
|
|
59
|
+
|
|
60
|
+
The agent-group runner enforces maximum concurrency and returns results in request order. A material failure stops queued work, aborts active siblings, waits for every started child to settle, and keeps the first failure as the primary cause.
|
|
61
|
+
|
|
62
|
+
## Evidence and results
|
|
63
|
+
|
|
64
|
+
The first node collects facts without model judgment. It uses fixed, non-mutating commands to collect:
|
|
65
|
+
|
|
66
|
+
- pull request intent and linked issue context when available;
|
|
67
|
+
- stated acceptance criteria;
|
|
68
|
+
- base and head revisions;
|
|
69
|
+
- changed files;
|
|
70
|
+
- the diff and diff statistics;
|
|
71
|
+
- relevant new exports, schemas, persisted fields, and nearby existing code.
|
|
72
|
+
|
|
73
|
+
Pull request and repository text is untrusted evidence, not instructions. Evidence and review inputs stay bounded before they enter a model prompt or run bundle.
|
|
74
|
+
|
|
75
|
+
The verification session receives the evidence and review results. It must remove unsupported claims, require exact file and symbol references, separate facts from assumptions, resolve supported conflicts, and place unresolved questions in `unknowns` or contributor questions. It returns `keep`, `simplify`, `refactor`, `drop`, or `needs_evidence`.
|
|
76
|
+
|
|
77
|
+
The existing strict result parsers stay unchanged. They continue to enforce all review areas, evidence, acceptance case, verdict, string, and item limits.
|
|
78
|
+
|
|
79
|
+
## Provider-first extension profile
|
|
80
|
+
|
|
81
|
+
The runner resolves one immutable child profile before it starts the group.
|
|
82
|
+
|
|
83
|
+
### Resolve candidate paths
|
|
84
|
+
|
|
85
|
+
Use `SettingsManager` and `DefaultPackageManager.resolve()` to find enabled extension paths without executing extension factories. Canonicalize and deduplicate the paths.
|
|
86
|
+
|
|
87
|
+
The default candidate set contains enabled user-scope extensions. Project extensions are excluded unless the private policy admits them explicitly. Direct and wrapper paths for Pi Workflows are excluded before any extension factory runs.
|
|
88
|
+
|
|
89
|
+
### Preflight provider ownership
|
|
90
|
+
|
|
91
|
+
Load candidate extensions in a no-session `DefaultResourceLoader` preflight. Pass the paths through `additionalExtensionPaths` and set `noExtensions: true` so the loader does not perform a second discovery pass.
|
|
92
|
+
|
|
93
|
+
Inspect documented pending native and legacy provider registrations. Admit the one extension path that registers the exact configured provider. Permit other behavior extensions only through an explicit private allowlist.
|
|
94
|
+
|
|
95
|
+
Fail before session creation when:
|
|
96
|
+
|
|
97
|
+
- no extension registers the configured provider;
|
|
98
|
+
- more than one extension claims the configured provider;
|
|
99
|
+
- an extension fails to load;
|
|
100
|
+
- an admitted extension registers a reserved workflow tool or command;
|
|
101
|
+
- an extension replaces `read`, `grep`, `find`, or `ls`;
|
|
102
|
+
- a loaded path is outside the frozen candidate snapshot.
|
|
103
|
+
|
|
104
|
+
Before invalidation, dispatch `session_shutdown` through a temporary public `ExtensionRunner` so factory-owned setup can clean up. Preflight does not create a session or dispatch `session_start`. Always invalidate the preflight extension runtime in `finally`.
|
|
105
|
+
|
|
106
|
+
Extension factories run before their registrations can be inspected. Pi documents that factories must not start background resources. Pi Workflows relies on that contract and does not claim to contain a factory that violates it.
|
|
107
|
+
|
|
108
|
+
## Exact model dispatch
|
|
109
|
+
|
|
110
|
+
Resolve one immutable `{ provider, modelId, thinkingLevel }` value for the group. A complete explicit override wins. Otherwise, use the configured `SettingsManager` defaults. Reject partial overrides, missing defaults, unsupported thinking values, and prompts that start with an extension slash command.
|
|
111
|
+
|
|
112
|
+
Read and strictly validate the configured cached model catalog once. Keep it as an in-memory group snapshot. Create a deep-cloned in-memory model store for each child. Do the same for ordinary Pi credentials read from `auth.json`. Pi Workflows never writes these snapshots back.
|
|
113
|
+
|
|
114
|
+
Provider extensions use their existing provider-owned credential store in place. Pi Workflows does not copy, inspect, print, migrate, or persist those credentials.
|
|
115
|
+
|
|
116
|
+
For each child:
|
|
117
|
+
|
|
118
|
+
1. Create a fresh non-networked `ModelRuntime` from cloned snapshots.
|
|
119
|
+
2. Create a fresh resource loader with only the frozen admitted extension paths.
|
|
120
|
+
3. Disable secondary extension discovery, skills, prompt templates, themes, and context files.
|
|
121
|
+
4. Load a fresh extension and provider instance.
|
|
122
|
+
5. Find the exact cached model and pass it to `createAgentSession`.
|
|
123
|
+
6. Pass the exact configured thinking level.
|
|
124
|
+
7. Verify the session's actual provider, model, thinking level, authentication, extension state, active tools, and built-in tool sources.
|
|
125
|
+
8. Start the prompt only after all checks pass.
|
|
126
|
+
|
|
127
|
+
Any mismatch is terminal. The runner does not select another provider, model, or thinking level.
|
|
128
|
+
|
|
129
|
+
A transient model selected only in the parent TUI is not inherited. The runner enforces the configured process default unless the private request gives a complete explicit dispatch.
|
|
130
|
+
|
|
131
|
+
## Workflow authority boundary
|
|
132
|
+
|
|
133
|
+
The parent Sanity Check action is the only workflow owner.
|
|
134
|
+
|
|
135
|
+
Children receive only the built-in read-only tool instances requested by Sanity Check. Extension tools can register but remain inactive. The runner rejects same-name replacements for the built-in tools.
|
|
136
|
+
|
|
137
|
+
Children receive no:
|
|
138
|
+
|
|
139
|
+
- `workflow` tool;
|
|
140
|
+
- `/workflow`, `/piw`, `/controller`, or workflow-channel command;
|
|
141
|
+
- run, node, or attempt identifier;
|
|
142
|
+
- workflow update, answer, submit, pause, resume, or cancel callback;
|
|
143
|
+
- child workflow run or parent workflow handle.
|
|
144
|
+
|
|
145
|
+
The runner rejects prompts that would invoke extension slash commands. These controls prevent the normal child model and admitted extension bindings from inspecting or changing workflow state.
|
|
146
|
+
|
|
147
|
+
## Lifecycle and privacy
|
|
148
|
+
|
|
149
|
+
One owner controls each child from creation through cleanup.
|
|
150
|
+
|
|
151
|
+
The owner:
|
|
152
|
+
|
|
153
|
+
1. Creates the child runtime and session.
|
|
154
|
+
2. Subscribes before prompting.
|
|
155
|
+
3. Emits only bounded safe lifecycle phases.
|
|
156
|
+
4. Waits for prompt settlement.
|
|
157
|
+
5. Extracts only the latest final assistant text.
|
|
158
|
+
6. Bounds the returned text before validation.
|
|
159
|
+
7. Calls and awaits `abort()` on timeout or cancellation.
|
|
160
|
+
8. Waits for prompt settlement after abort.
|
|
161
|
+
9. Unsubscribes.
|
|
162
|
+
10. Disposes the session so extension shutdown runs.
|
|
163
|
+
11. Invalidates remaining extension runtime state.
|
|
164
|
+
12. Releases provider resources.
|
|
165
|
+
|
|
166
|
+
Cleanup runs for success, creation failure, authentication failure, provider failure, malformed output, timeout, parent cancellation, sibling failure, and disposal failure. A cleanup failure remains a bounded secondary diagnostic and does not replace an earlier primary error.
|
|
167
|
+
|
|
168
|
+
The workflow never copies extension events or extension-private state into progress or run bundles.
|
|
169
|
+
|
|
170
|
+
## Progress and visibility
|
|
171
|
+
|
|
172
|
+
Sanity Check keeps the existing `pi-workflows.progress.v1` records and keys:
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
agents/review
|
|
176
|
+
agents/review/necessity
|
|
177
|
+
agents/review/duplication
|
|
178
|
+
agents/review/contracts
|
|
179
|
+
agents/review/scope_tests
|
|
180
|
+
agents/verification
|
|
181
|
+
agents/verification/verification
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Aggregate tracks report completed and total sessions. Child tracks report a bounded role label, the verified actual model when known, and a safe phase such as `starting`, `thinking`, `tool: read`, `finalizing`, or a terminal phase.
|
|
185
|
+
|
|
186
|
+
Updates are deduplicated, throttled, and observational. They cannot change agent execution.
|
|
187
|
+
|
|
188
|
+
The Pi widget shows the aggregate plus failed and active children within its ten-line limit. `piw` shows all durable child tracks and samples. Both views use existing progress records. No new persisted field or schema is added.
|
|
189
|
+
|
|
190
|
+
## Implementation plan
|
|
191
|
+
|
|
192
|
+
1. Update the Pi SDK development baseline to one compatible 0.84.x release. Keep the Pi coding-agent, Pi AI, and Pi TUI packages aligned and set an honest peer compatibility floor. Do not add Pi Factory or a provider extension as a dependency.
|
|
193
|
+
2. Add the private dispatch and child extension profile contracts under `src/builtins`. Do not export them from package entry points.
|
|
194
|
+
3. Resolve enabled extension paths without execution. Canonicalize paths, exclude project extensions by default, and exclude direct and wrapper Pi Workflows paths.
|
|
195
|
+
4. Add the no-session extension preflight. Identify the exact native or legacy provider owner and reject reserved workflow capabilities, provider conflicts, load errors, and built-in tool overrides.
|
|
196
|
+
5. Keep the model-catalog snapshot work, but change it to one validated group snapshot and one clone per child. Add the same ownership for ordinary Pi credentials. Remove the previous empty-catalog behavior.
|
|
197
|
+
6. Replace the shared group `ModelRuntime` with one complete runtime per child.
|
|
198
|
+
7. Verify exact provider, model, thinking, authentication, admitted extensions, active tools, and tool sources before every prompt.
|
|
199
|
+
8. Complete provider, extension, and session cleanup on every exit path.
|
|
200
|
+
9. Pass the private profile and exact dispatch through Sanity Check without changing its review behavior or progress schema. Remove any `--no-extensions` launch guidance.
|
|
201
|
+
10. Change the built-in Sanity Check revision from 2 to 3.
|
|
202
|
+
11. Add temporary fixture extensions and full unit, integration, interactive Pi, and standalone host coverage.
|
|
203
|
+
12. Update this plan and `docs/workflows.md` to match the shipped behavior.
|
|
204
|
+
13. Run the complete repository gate and inspect the full public diff.
|
|
205
|
+
14. After mock-provider verification, run one bounded real acceptance on OpenClaw pull request 126028 with `openai-codex/gpt-5.6-sol` and high thinking. Abort immediately if any child reports another provider or model. Do not modify OpenClaw.
|
|
206
|
+
|
|
207
|
+
## Revision and compatibility
|
|
208
|
+
|
|
209
|
+
Sanity Check moves from built-in revision 2 to revision 3.
|
|
210
|
+
|
|
211
|
+
This is an alpha hard cutover. Do not retain the revision-2 child runtime, fallback, compatibility runner, migration, alias, dual path, or feature flag. An unfinished revision-2 run must fail with clear cancel-and-restart guidance. Terminal revision-2 bundles remain readable historical evidence because the persisted schema does not change.
|
|
212
|
+
|
|
213
|
+
## Tests
|
|
214
|
+
|
|
215
|
+
Unit and integration tests must cover:
|
|
216
|
+
|
|
217
|
+
- dispatch parsing and exact provider, model, and thinking enforcement;
|
|
218
|
+
- missing authentication and no fallback;
|
|
219
|
+
- extension path resolution, canonicalization, scope filtering, disabled paths, and explicit behavior paths;
|
|
220
|
+
- direct and wrapper Pi Workflows exclusion;
|
|
221
|
+
- native and legacy provider-owner discovery;
|
|
222
|
+
- reserved workflow command and tool rejection;
|
|
223
|
+
- inactive extension tools and built-in tool override rejection;
|
|
224
|
+
- per-child runtime, provider, extension, loader, and history isolation under parallel execution;
|
|
225
|
+
- validated model and credential snapshots, deep clones, cancellation, malformed input, and no writes;
|
|
226
|
+
- provider-owned mock authentication without credential exposure;
|
|
227
|
+
- success, provider error, empty output, malformed output, oversized output, timeout, cancellation, fail-fast, and cleanup-error precedence;
|
|
228
|
+
- final-only retention and absence of private child content in results, errors, updates, and bundles;
|
|
229
|
+
- serial two-session and parallel five-session behavior;
|
|
230
|
+
- existing progress keys, model labels, throttling, and rendering;
|
|
231
|
+
- interactive Pi with normal extensions enabled and the local mock provider;
|
|
232
|
+
- standalone `WorkflowHost` through the same private runtime path;
|
|
233
|
+
- no child session files or child workflow runs;
|
|
234
|
+
- built-in revision 3 and historical terminal bundle reading;
|
|
235
|
+
- final notification without another model turn.
|
|
236
|
+
|
|
237
|
+
Tests use mock providers and temporary directories. They do not call real models or write outside temporary directories.
|
|
238
|
+
|
|
239
|
+
Before completion, run:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
npm run check
|
|
243
|
+
npm run test:e2e
|
|
244
|
+
npx slophammer-ts@latest dry .
|
|
245
|
+
npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
After these checks and Pi Reviewer pass, perform the one explicitly authorized bounded GPT-5.6 Sol acceptance run.
|
|
249
|
+
|
|
250
|
+
## Acceptance criteria
|
|
251
|
+
|
|
252
|
+
The implementation is complete when:
|
|
253
|
+
|
|
254
|
+
- `/workflow sanity-check` discovers built-in revision 3;
|
|
255
|
+
- the parent Pi process runs with its normal configured extensions;
|
|
256
|
+
- serial mode uses two independent in-memory SDK sessions;
|
|
257
|
+
- parallel mode uses five independent in-memory SDK sessions, with four reviews running concurrently;
|
|
258
|
+
- every child loads the extension that owns the exact configured provider;
|
|
259
|
+
- every child reports the exact required provider, model, and thinking level before prompting;
|
|
260
|
+
- no child silently falls back to OpenRouter, Kimi, a local model, or another dispatch;
|
|
261
|
+
- children use only verified built-in read-only tools and create no session files;
|
|
262
|
+
- children cannot use normal workflow tools, commands, identifiers, or callbacks;
|
|
263
|
+
- the workflow keeps only bounded final answers and safe operational facts;
|
|
264
|
+
- child prompts, reasoning, tool payloads, histories, credentials, and extension state do not enter run bundles or progress updates;
|
|
265
|
+
- provider, extension, and session cleanup completes on every exit path;
|
|
266
|
+
- Sanity Check review behavior, strict validation, verdicts, progress, and final notification remain unchanged;
|
|
267
|
+
- interactive and headless runs use the same private SDK path;
|
|
268
|
+
- all required checks pass with coverage margin;
|
|
269
|
+
- the bounded acceptance run on OpenClaw pull request 126028 reports GPT-5.6 Sol for every child and completes with a strict verdict without modifying OpenClaw.
|
|
270
|
+
|
|
271
|
+
## Contract impact
|
|
272
|
+
|
|
273
|
+
- **Origin session:** The normal workflow start record and one final workflow notification.
|
|
274
|
+
- **Parent extensions:** The parent Pi process loads its normal configured extensions.
|
|
275
|
+
- **Child extensions:** Only the exact provider owner and explicit private behavior paths are admitted.
|
|
276
|
+
- **Child sessions:** Independent in-memory contexts and complete per-child runtimes in the same Node process. No child session file or child workflow run.
|
|
277
|
+
- **Model dispatch:** Exact provider, model, and thinking are required. Fallback is forbidden.
|
|
278
|
+
- **Credentials:** Pi Workflows does not copy or persist credentials. Provider extensions use their existing stores in place.
|
|
279
|
+
- **Other persistent data:** The normal workflow run bundle and existing progress updates only.
|
|
280
|
+
- **Private content:** Prompts, reasoning, intermediate messages, tool payloads, histories, credentials, and extension-private state are not persisted by Pi Workflows.
|
|
281
|
+
- **Pi public API:** Documented package manager, resource loader, extension and provider registration, model runtime, session, event, abort, and disposal APIs only.
|
|
282
|
+
- **Pi Workflows public API:** No change.
|
|
283
|
+
- **Isolation:** Workflow capability is withheld from normal child bindings. Arbitrary trusted in-process extension code is not sandboxed.
|
package/docs/run-bundles.md
CHANGED
|
@@ -40,18 +40,18 @@ Human decision records use a separate additive directory next to `runs/` so a wa
|
|
|
40
40
|
request.json
|
|
41
41
|
deliveries/<channel>/<attempt-id>.json
|
|
42
42
|
answers/<attempt-id>.json
|
|
43
|
-
resolution.json # atomic
|
|
44
|
-
accepted.json
|
|
45
|
-
cancelled.json #
|
|
43
|
+
resolution.json # atomic resolved-or-cancelled fence
|
|
44
|
+
accepted.json # human or timeout response with explicit provenance
|
|
45
|
+
cancelled.json # terminal cancellation tombstone
|
|
46
46
|
settlements/<channel>/<attempt-id>.json
|
|
47
47
|
continuation.json
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
The request links to the waiting run, node, attempt, workflow source, and canonical request digest.
|
|
50
|
+
The request links to the waiting run, node, attempt, workflow source, and canonical request digest. The single v1 request stores the canonical subject and a separate normalized operator presentation. Its subject, presentation, revision, choices, input prompts, optional deadline, and optional automatic response are bound to the request digest. Accepted records and redacted continuation receipts preserve the subject and presentation digests and state `human` or `timeout` provenance. A timeout record has no human source. Final records use no-replace creation and adopt only identical retries. `resolution.json` is the first resolved-or-cancelled fence. It materializes either `accepted.json` or `cancelled.json`; a crash can rebuild that detail from the resolution. A cancellation tombstone prevents later automatic continuation. `continuation.json` binds one resolved response and its provenance to one deterministic continuation run. Delivery and settlement records cannot change the result. Older human-decision record shapes are incompatible alpha state and require reset; there is no migration reader.
|
|
51
51
|
|
|
52
52
|
Telegram multipart delivery uses additive v2 delivery records for the overall intent, each part, and completion. Part records contain only recipient indexes, part indexes, counts, and content digests. Telegram chat and message IDs remain in the private disposable channel projection and never enter run or decision bundles. An ambiguous part remains unknown and is not retried blindly.
|
|
53
53
|
|
|
54
|
-
A human-decision continuation preserves the parent's original workflow input and replaces the carried checkpoint output with the
|
|
54
|
+
A human-decision continuation preserves the parent's original workflow input and replaces the carried checkpoint output with the resolved typed response for routing. Its `humanDecision` state is a redacted receipt with `human` or `timeout` provenance. A v2 receipt includes the subject digest, presentation digest, and revision, but not the subject itself. Verified human actor, channel, event, and idempotency details remain in the private sibling decision records and are not copied into the run bundle. Ordinary checkpoint continuations keep using the answer as the continuation input. This alpha contract changes current v1 and v2 field sets in place; old active definitions refuse resume instead of using a compatibility path.
|
|
55
55
|
|
|
56
56
|
Run ids are `<UTC timestamp>-<workflow slug>-<8 hex chars>`, so lexical order
|
|
57
57
|
is chronological order.
|
|
@@ -183,7 +183,9 @@ A serializable snapshot of the graph taken at run start
|
|
|
183
183
|
(`pi-workflows.definition-snapshot.v1`). Functions such as prompts and
|
|
184
184
|
validators are not serialized. Each node keeps only its metadata (`nodeType`,
|
|
185
185
|
`timeoutMs`, `statusDetail`, `expectedOutput`, `summary`, `actionExecution`),
|
|
186
|
-
and edges are copied verbatim.
|
|
186
|
+
and edges are copied verbatim. A fixed `timeoutMs: null` is preserved and means
|
|
187
|
+
that the node has no wall-clock deadline. Timeout callbacks remain omitted.
|
|
188
|
+
A human-decision snapshot records fixed `onTimeout` duration and response values. A dynamic timeout callback is omitted and marked as dynamic. Included nodes also record `mountPath`, `localNodeId`, and internal entry or exit status. The top-level `composition.mounts` list records every mount, entry, named exit, and child step limit. The snapshot is what lets viewers draw all nodes, including ones that have not run yet. It is immutable after run start.
|
|
187
189
|
|
|
188
190
|
## Resume and repair
|
|
189
191
|
|