@osolmaz/pi-workflows 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +15 -6
  2. package/dist/builtins/autoimplement-command-batches.d.ts +52 -0
  3. package/dist/builtins/autoimplement-command-batches.js +258 -0
  4. package/dist/builtins/autoimplement-command-batches.js.map +1 -0
  5. package/dist/builtins/autoimplement.workflow.d.ts +29 -3
  6. package/dist/builtins/autoimplement.workflow.js +876 -231
  7. package/dist/builtins/autoimplement.workflow.js.map +1 -1
  8. package/dist/builtins/catalog.js +3 -1
  9. package/dist/builtins/catalog.js.map +1 -1
  10. package/dist/builtins/index.d.ts +2 -0
  11. package/dist/builtins/index.js +1 -0
  12. package/dist/builtins/index.js.map +1 -1
  13. package/dist/builtins/sanity-check-session.d.ts +17 -0
  14. package/dist/builtins/sanity-check-session.js +168 -0
  15. package/dist/builtins/sanity-check-session.js.map +1 -0
  16. package/dist/builtins/sanity-check.workflow.d.ts +83 -0
  17. package/dist/builtins/sanity-check.workflow.js +398 -0
  18. package/dist/builtins/sanity-check.workflow.js.map +1 -0
  19. package/dist/controllers/sqlite.d.ts +141 -5
  20. package/dist/controllers/sqlite.js +568 -46
  21. package/dist/controllers/sqlite.js.map +1 -1
  22. package/dist/extension/decision-channels.js +7 -7
  23. package/dist/extension/deferred-turn-coordinator.d.ts +32 -0
  24. package/dist/extension/deferred-turn-coordinator.js +143 -0
  25. package/dist/extension/deferred-turn-coordinator.js.map +1 -0
  26. package/dist/extension/deferred-turn.d.ts +44 -0
  27. package/dist/extension/deferred-turn.js +110 -0
  28. package/dist/extension/deferred-turn.js.map +1 -0
  29. package/dist/extension/index.js +515 -84
  30. package/dist/extension/index.js.map +1 -1
  31. package/dist/extension/step-message.d.ts +1 -0
  32. package/dist/extension/step-message.js.map +1 -1
  33. package/dist/herdr/setup.js +4 -4
  34. package/dist/host/runner.js +3 -0
  35. package/dist/host/runner.js.map +1 -1
  36. package/dist/workflows/command-batch.d.ts +38 -0
  37. package/dist/workflows/command-batch.js +176 -0
  38. package/dist/workflows/command-batch.js.map +1 -0
  39. package/dist/workflows/engine.js +8 -4
  40. package/dist/workflows/engine.js.map +1 -1
  41. package/dist/workflows/index.d.ts +1 -0
  42. package/dist/workflows/index.js +1 -0
  43. package/dist/workflows/index.js.map +1 -1
  44. package/dist/workflows/migrate-sources.d.ts +1 -1
  45. package/dist/workflows/migrate-sources.js.map +1 -1
  46. package/dist/workflows/schema.js +2 -1
  47. package/dist/workflows/schema.js.map +1 -1
  48. package/dist/workflows/shell.d.ts +4 -0
  49. package/dist/workflows/shell.js +6 -0
  50. package/dist/workflows/shell.js.map +1 -1
  51. package/dist/workflows/store.js +3 -1
  52. package/dist/workflows/store.js.map +1 -1
  53. package/dist/workflows/tool-input.d.ts +1 -0
  54. package/dist/workflows/tool-input.js +2 -2
  55. package/dist/workflows/tool-input.js.map +1 -1
  56. package/dist/workflows/types.d.ts +4 -3
  57. package/docs/2026-08-18-herdr-piw-plan.md +1 -1
  58. package/docs/2026-08-20-durable-workflow-launch-plan.md +445 -0
  59. package/docs/CONTROLLERS.md +2 -2
  60. package/docs/DEFERRED_TURNS.md +298 -0
  61. package/docs/DESIGN_PHILOSOPHY.md +1 -1
  62. package/docs/HUMAN_DECISIONS.md +7 -7
  63. package/docs/HUMAN_DECISION_PRESENTATIONS.md +3 -3
  64. package/docs/MONITOR.md +2 -2
  65. package/docs/WORKFLOW_COMPOSITION.md +2 -2
  66. package/docs/WORKFLOW_STEP_MESSAGES.md +5 -5
  67. package/docs/WORKFLOW_UPDATES.md +28 -5
  68. package/docs/plans/2026-08-04-controller-runtime-plan.md +1 -1
  69. package/docs/plans/2026-08-05-always-on-workflows-plan.md +1 -1
  70. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +9 -9
  71. package/docs/plans/2026-08-13-built-in-workflow-catalog-plan.md +1 -1
  72. package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
  73. package/docs/plans/2026-08-16-workflow-updates-plan.md +3 -3
  74. package/docs/plans/2026-08-17-bundled-skills-plan.md +6 -6
  75. package/docs/plans/2026-08-19-human-decision-gates-plan.md +5 -5
  76. package/docs/plans/2026-08-19-human-decision-presentations-plan.md +1 -1
  77. package/docs/plans/2026-08-19-provider-compatible-workflow-tool-schema-plan.md +1 -1
  78. package/docs/plans/2026-08-19-workflow-composition-plan.md +6 -6
  79. package/docs/plans/2026-08-20-autoimplement-blocker-challenge-plan.md +3 -3
  80. package/docs/plans/2026-08-20-bounded-command-batches-plan.md +206 -0
  81. package/docs/plans/2026-08-20-herdr-plugin-sync-plan.md +9 -9
  82. package/docs/plans/2026-08-21-autoimplement-timeout-fallback-plan.md +242 -0
  83. package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +324 -0
  84. package/docs/plans/2026-08-21-sanity-check-plan.md +175 -0
  85. package/docs/run-bundles.md +3 -1
  86. package/docs/workflows.md +67 -17
  87. package/examples/workflows/command-batch.workflow.ts +50 -0
  88. package/examples/workflows/sanity-check.workflow.ts +1 -0
  89. package/herdr-plugin.toml +3 -3
  90. package/package.json +1 -1
  91. package/schemas/decision-presentation-v1.schema.json +1 -1
  92. package/schemas/human-decision-accepted-v1.schema.json +1 -1
  93. package/schemas/human-decision-accepted-v2.schema.json +1 -1
  94. package/schemas/human-decision-answer-attempt-v1.schema.json +1 -1
  95. package/schemas/human-decision-cancellation-v1.schema.json +1 -1
  96. package/schemas/human-decision-continuation-v1.schema.json +1 -1
  97. package/schemas/human-decision-delivery-v1.schema.json +1 -1
  98. package/schemas/human-decision-delivery-v2.schema.json +1 -1
  99. package/schemas/human-decision-receipt-v1.schema.json +1 -1
  100. package/schemas/human-decision-receipt-v2.schema.json +1 -1
  101. package/schemas/human-decision-request-v1.schema.json +1 -1
  102. package/schemas/human-decision-request-v2.schema.json +1 -1
  103. package/schemas/human-decision-resolution-v1.schema.json +1 -1
  104. package/schemas/human-decision-resolution-v2.schema.json +1 -1
  105. package/schemas/human-decision-settlement-v1.schema.json +1 -1
  106. package/skills/autodoc/SKILL.md +33 -2
  107. package/skills/autoimplement/SKILL.md +66 -12
  108. package/skills/autoplan/SKILL.md +26 -2
  109. package/skills/monitor/SKILL.md +35 -21
  110. package/skills/pi-workflows/SKILL.md +19 -5
  111. package/src/builtins/autoimplement-command-batches.ts +364 -0
  112. package/src/builtins/autoimplement.workflow.ts +1065 -261
  113. package/src/builtins/catalog.ts +3 -1
  114. package/src/builtins/index.ts +13 -0
  115. package/src/builtins/sanity-check-session.ts +205 -0
  116. package/src/builtins/sanity-check.workflow.ts +624 -0
  117. package/src/controllers/sqlite.ts +878 -51
  118. package/src/extension/decision-channels.ts +7 -7
  119. package/src/extension/deferred-turn-coordinator.ts +171 -0
  120. package/src/extension/deferred-turn.ts +166 -0
  121. package/src/extension/index.ts +646 -91
  122. package/src/extension/step-message.ts +1 -0
  123. package/src/herdr/setup.ts +4 -4
  124. package/src/host/runner.ts +3 -0
  125. package/src/workflows/command-batch.ts +254 -0
  126. package/src/workflows/engine.ts +8 -5
  127. package/src/workflows/index.ts +15 -0
  128. package/src/workflows/migrate-sources.ts +5 -1
  129. package/src/workflows/schema.ts +2 -1
  130. package/src/workflows/shell.ts +10 -0
  131. package/src/workflows/store.ts +3 -1
  132. package/src/workflows/tool-input.ts +5 -2
  133. package/src/workflows/types.ts +4 -3
@@ -0,0 +1,445 @@
1
+ ---
2
+ title: Make deferred workflow launches durable
3
+ author: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
4
+ date: 2026-08-20
5
+ ---
6
+
7
+ # Make deferred workflow launches durable
8
+
9
+ The launch queue and activation contract in this plan remain current. [Deferred workflow turns](DEFERRED_TURNS.md) replaces the launch-specific failure-notification mechanism with the general successor-turn intent contract.
10
+
11
+ ## Goal
12
+
13
+ A successful `workflow start` call must create a real queued workflow before it returns. The model
14
+ must receive the final run ID, and pi-workflows must start that run only after the current agent turn
15
+ settles.
16
+
17
+ If startup then fails, pi-workflows must save the failure and start one new model turn with an
18
+ actionable error. The model can correct the request and call `workflow start` again. A failed launch
19
+ must release the session reservation so the corrected run can start.
20
+
21
+ This change stays inside pi-workflows. It uses the existing project-scoped SQLite controller store
22
+ and documented Pi extension APIs. It does not change Pi, add a service, or add another database.
23
+
24
+ ## Current failure
25
+
26
+ The current tool path stores a pending launch only in `pendingToolLaunch`. It returns:
27
+
28
+ ```text
29
+ Workflow <name> will start after this turn finishes.
30
+ ```
31
+
32
+ After the agent turn settles, the `agent_settled` handler clears `pendingToolLaunch` and calls
33
+ `startRun`. If `startRun` fails, the handler sends only a TUI notification. No run ID was returned,
34
+ `workflow status` has no durable launch to inspect, and the model receives no new turn.
35
+
36
+ This happened twice while starting `autoimplement`. The tool reported a queued launch, but no run
37
+ became active. The initiating model could not see the startup error and incorrectly reported that
38
+ the workflow had started.
39
+
40
+ ## Decision
41
+
42
+ Use a durable prepared run and one model-visible failure follow-up.
43
+
44
+ During the `workflow start` tool call, pi-workflows will:
45
+
46
+ 1. Resolve and validate the workflow and all available start conditions.
47
+ 2. Allocate the final run ID.
48
+ 3. Save a queued record in the existing SQLite workflow queue.
49
+ 4. Reserve the initiating Pi session.
50
+ 5. Return the run ID and say that the workflow is queued.
51
+
52
+ After the current agent turn settles, pi-workflows will:
53
+
54
+ 1. Claim the queued record.
55
+ 2. Change it to `starting`.
56
+ 3. Build the engine and executor without running a node.
57
+ 4. Change the record to `running`.
58
+ 5. Release the engine to run the first node.
59
+
60
+ If startup fails, pi-workflows will:
61
+
62
+ 1. Change the record to `failed`.
63
+ 2. Save a bounded safe error.
64
+ 3. Release the session reservation.
65
+ 4. Create one eligible deferred-turn intent for the owning Pi session.
66
+ 5. Resolve that intent with one factual follow-up after settlement.
67
+
68
+ The new model turn will contain the failed run ID and an actionable error. The model can fix the
69
+ workflow reference, input, source, or local condition and call `workflow start` again. Each retry is
70
+ an explicit model action with a new run ID. pi-workflows does not perform a blind automatic retry.
71
+
72
+ ## Alpha compatibility contract
73
+
74
+ pi-workflows is in alpha. Change the current storage and tool contracts in place.
75
+
76
+ - Keep `pi-workflows.controller-store.v1`.
77
+ - Keep existing run-bundle schema identifiers.
78
+ - Do not add a v2 schema.
79
+ - Do not add a compatibility reader, data migration, dual path, alias, feature flag, or fallback to
80
+ `pendingToolLaunch`.
81
+ - Change the SQLite table definitions and TypeScript types directly.
82
+ - Remove the superseded status values and launch path in the same change.
83
+
84
+ An existing controller store with the old alpha table layout is incompatible. On open, pi-workflows
85
+ must verify the required table columns and status contract. If the layout is old, it must stop with a
86
+ clear instruction to preserve any needed run evidence and reset the project-scoped controller store.
87
+ It must not silently reinterpret or delete old state.
88
+
89
+ Run bundles remain separate evidence. Resetting an incompatible controller queue must not delete run
90
+ bundle directories.
91
+
92
+ ## Public behavior
93
+
94
+ ### Start
95
+
96
+ A successful tool result becomes:
97
+
98
+ ```text
99
+ Workflow autoimplement queued (run autoimplement-...).
100
+ ```
101
+
102
+ The structured result contains:
103
+
104
+ ```json
105
+ {
106
+ "action": "start",
107
+ "workflow": "autoimplement",
108
+ "runId": "autoimplement-...",
109
+ "queued": true
110
+ }
111
+ ```
112
+
113
+ Queued means that the durable reservation exists. It does not mean that the engine is running.
114
+
115
+ Every check that can run before acknowledgement must run before the queue record is committed. This
116
+ includes:
117
+
118
+ - Workflow resolution and definition validation.
119
+ - Declared input validation.
120
+ - Parent checkpoint and source checks for continuations.
121
+ - Controller-store access.
122
+ - Existing active or queued session reservation.
123
+ - Pending final presentation conflicts.
124
+
125
+ A preflight error returns through the original tool call. The model can correct it in the same turn.
126
+ No queued record remains after a failed preflight.
127
+
128
+ ### Activation
129
+
130
+ Interactive activation starts only from a safe idle boundary:
131
+
132
+ - `agent_settled` after the initiating turn.
133
+ - `session_start` recovery when no agent turn is active.
134
+ - The next `agent_settled` event when recovery starts during an active turn.
135
+
136
+ Repeated lifecycle events must not start the same run twice. Claims use compare-and-set updates, a
137
+ claim token, a bounded lease, and a final fence before the engine starts its first node.
138
+
139
+ No compute node, shell action, function action, agent node, or presentation starts while the
140
+ initiating agent turn is active.
141
+
142
+ ### Failure and model iteration
143
+
144
+ A deferred startup failure becomes a terminal queued-run state. The safe follow-up message is:
145
+
146
+ ```text
147
+ Workflow autoimplement failed to start (run autoimplement-...): <safe reason>.
148
+ Inspect the error and call workflow start again only after you correct the cause.
149
+ ```
150
+
151
+ The message does not contain raw workflow input, prompt text, credentials, request headers, or a
152
+ stack trace.
153
+
154
+ The turn intent has a deterministic ID derived from the session, run, and launch event. Pi Workflows records it in `workflow_turn_intents`. Before a delivery retry, it checks the Pi session branch for the intent ID. This prevents a duplicate after a crash between session append and intent resolution.
155
+
156
+ A failed launch releases the one-workflow session reservation before it sends the follow-up. The
157
+ model can therefore call `workflow start` during the new turn. If that launch also fails, the same
158
+ process repeats with a new run ID. The regular Pi loop and user control remain the bounds; Pi
159
+ Workflows does not create an internal retry loop.
160
+
161
+ ### Status
162
+
163
+ `workflow status` with a run ID reads the queued-run record before a run bundle exists. After the
164
+ engine starts, it also reads the normal run bundle.
165
+
166
+ Status reports these launch states:
167
+
168
+ ```text
169
+ queued
170
+ starting
171
+ running
172
+ failed
173
+ cancelled
174
+ parked
175
+ done
176
+ ```
177
+
178
+ A failed status includes only the bounded safe error. Status without a run ID shows the current
179
+ session reservation or the displayed run.
180
+
181
+ ### Cancellation
182
+
183
+ `workflow cancel` accepts the queued run ID. Cancellation changes `queued` or `starting` to
184
+ `cancelled` atomically and invalidates the activation fence. A race cannot release the executor after
185
+ cancellation wins.
186
+
187
+ A cancelled launch releases the session reservation and sends no failure follow-up. A later start
188
+ can create a new run.
189
+
190
+ ## Storage contract
191
+
192
+ Use the existing `workflow_run_queue` table as the source of truth for launch state.
193
+
194
+ Change its alpha v1 layout in place to store:
195
+
196
+ - Final run ID.
197
+ - Workflow name and immutable source identity.
198
+ - Definition digest.
199
+ - Private workflow input while activation needs it.
200
+ - Launch state.
201
+ - Owning Pi session.
202
+ - Claim token and lease expiry.
203
+ - Safe failure code and message.
204
+ - Created, updated, started, and finished times.
205
+
206
+ Replace the current `claimed`, `parked`, and `done` launch-state contract with:
207
+
208
+ ```text
209
+ queued | starting | running | parked | done | failed | cancelled
210
+ ```
211
+
212
+ Keep `parked` and `done` for current resume and terminal queue behavior. Remove `claimed`; `starting`
213
+ and `running` state its meaning directly.
214
+
215
+ Clear private queue input when the launch becomes `running`, `failed`, or `cancelled`. The normal run
216
+ bundle owns input after the engine starts.
217
+
218
+ Keep `workflow_notifications` limited to passive `progress` and `final` reports. A launch failure creates an eligible row in `workflow_turn_intents`; it does not add a run-level notification kind.
219
+
220
+ The project-scoped controller store remains private local state. Tests must verify restrictive file
221
+ and directory permissions.
222
+
223
+ ## State transitions
224
+
225
+ Only these launch transitions are valid:
226
+
227
+ ```text
228
+ queued -> starting
229
+ queued -> cancelled
230
+ starting -> running
231
+ starting -> failed
232
+ starting -> cancelled
233
+ starting -> queued # expired lease with no run bundle
234
+ running -> parked
235
+ running -> done
236
+ running -> failed
237
+ running -> cancelled
238
+ parked -> starting # explicit resume
239
+ parked -> cancelled
240
+ ```
241
+
242
+ Every transition uses an expected current state and claim token when applicable. A stale handler gets
243
+ no ownership and performs no side effect.
244
+
245
+ When recovery finds `starting` after a lease expires:
246
+
247
+ - No run bundle: return to `queued`.
248
+ - Valid running bundle: reconcile to `running` and use existing run recovery.
249
+ - Waiting bundle: reconcile to `parked`.
250
+ - Terminal bundle: reconcile to `done`, `failed`, or `cancelled`.
251
+ - Changed workflow source or unreadable bundle: record `failed` and notify the owning session.
252
+
253
+ ## Error contract
254
+
255
+ Classify startup failures into a small set of stable codes, such as:
256
+
257
+ ```text
258
+ workflow_not_found
259
+ workflow_invalid
260
+ input_invalid
261
+ source_changed
262
+ store_unavailable
263
+ activation_failed
264
+ cancelled
265
+ ```
266
+
267
+ Persist a plain safe message with a strict byte limit. Keep the original error only in transient
268
+ process memory for local debug logging. Never persist or send the stack, causes, raw input, prompt,
269
+ credential, or unbounded provider text.
270
+
271
+ A failure must remain useful. The safe message should name the check that failed and the action that
272
+ can correct it without including secret values.
273
+
274
+ ## Implementation plan
275
+
276
+ ### 1. Replace the alpha controller-store layout
277
+
278
+ Update `src/controllers/sqlite.ts` and its exported queue and notification types.
279
+
280
+ - Keep `CONTROLLER_STORE_SCHEMA` at `pi-workflows.controller-store.v1`.
281
+ - Change `SCHEMA_SQL` directly.
282
+ - Remove old alpha `ALTER TABLE` compatibility logic for the workflow queue.
283
+ - Add exact-layout validation after table creation.
284
+ - Add the launch states and safe failure fields.
285
+ - Generalize workflow notifications for run-level failure notices.
286
+ - Add a partial unique index for one `queued`, `starting`, or `running` interactive reservation per
287
+ origin session.
288
+
289
+ For an incompatible existing table, return a clear alpha reset error. Do not mutate it.
290
+
291
+ ### 2. Add atomic launch operations
292
+
293
+ Add focused SQLite methods:
294
+
295
+ - `reservePreparedRun`
296
+ - `claimPreparedRun`
297
+ - `markPreparedRunRunning`
298
+ - `failPreparedRun`
299
+ - `cancelPreparedRun`
300
+ - `parkRunningRun`
301
+ - `finishRunningRun`
302
+ - `findSessionReservation`
303
+ - `listRecoverableRuns`
304
+ - `recoverExpiredStartingRun`
305
+
306
+ Use `BEGIN IMMEDIATE`, expected states, claim tokens, and lease checks.
307
+
308
+ ### 3. Split preparation from activation
309
+
310
+ Refactor `src/extension/index.ts`.
311
+
312
+ Create a small `src/extension/launch-coordinator.ts` if it keeps state transitions and recovery out of
313
+ the extension entry point.
314
+
315
+ Preparation owns resolution, validation, run ID allocation, immutable source identity, definition
316
+ digest, and reservation. Activation owns claims, engine construction, recorder setup, `activeRun`,
317
+ running state, and executor release.
318
+
319
+ Controller child workflows remain on their controller scheduler path. Share pure workflow-resolution
320
+ helpers where useful, but do not make controller children wait for an interactive agent boundary.
321
+
322
+ ### 4. Change the start tool
323
+
324
+ Update `src/extension/workflow-tool.ts` and the extension start handler.
325
+
326
+ Return the queued run ID only after the SQLite transaction commits. Remove the old “will start”
327
+ result and every success message that says the workflow already started.
328
+
329
+ ### 5. Add the failure follow-up
330
+
331
+ Create a versioned custom message for launch results. Store only:
332
+
333
+ - Notification schema.
334
+ - Notification ID.
335
+ - Run ID.
336
+ - Workflow name.
337
+ - `failed` state.
338
+ - Safe error code and message.
339
+
340
+ Deliver it through public `pi.sendMessage` after settlement with `triggerTurn: true` and
341
+ `deliverAs: "followUp"`.
342
+
343
+ The notification asks the model to inspect and correct the cause. It does not automatically call
344
+ `workflow start`.
345
+
346
+ ### 6. Update status, cancellation, and recovery
347
+
348
+ Status must read the queue before a run bundle exists. Cancellation must target queued and starting
349
+ runs by ID. Session startup and agent settlement must ask the launch coordinator for recoverable work
350
+ owned by that session.
351
+
352
+ Delete `pendingToolLaunch` and all status, cancel, shutdown, and `agent_settled` branches that depend
353
+ on it.
354
+
355
+ ### 7. Keep rendering secondary
356
+
357
+ Render queued, starting, failed, and cancelled launch state in the TUI from durable storage. A TUI
358
+ notification can announce failure, but it is not the source of truth and is not the only delivery
359
+ surface.
360
+
361
+ ### 8. Update documentation
362
+
363
+ Update `docs/workflows.md` with the queued start contract, run ID, status, cancellation, failure
364
+ follow-up, and model retry behavior. Update controller-store documentation with the alpha reset rule.
365
+ Do not document a v2 schema or migration path.
366
+
367
+ ## Tests
368
+
369
+ Add or update these tests:
370
+
371
+ 1. Clean alpha v1 store creation with the new exact layout.
372
+ 2. Old alpha v1 layout rejection with a clear reset instruction.
373
+ 3. No automatic table migration or silent deletion.
374
+ 4. One-session reservation and different-session independence.
375
+ 5. Durable run ID before the start tool returns.
376
+ 6. Synchronous preflight failure with no queue record.
377
+ 7. Zero engine activity before `agent_settled`.
378
+ 8. Duplicate `agent_settled` and `session_start` events with one activation.
379
+ 9. Lease expiry and recovery at every activation boundary.
380
+ 10. Cancellation before claim, during `starting`, and before executor release.
381
+ 11. Source change between preparation and activation.
382
+ 12. Safe error redaction and byte bounds.
383
+ 13. One durable launch-failure turn intent.
384
+ 14. Crash before session append, after append, and before intent resolution.
385
+ 15. Failed reservation release followed by a corrected model start.
386
+ 16. Repeated model correction attempts with one active reservation at a time.
387
+ 17. Status for every launch and run state.
388
+ 18. Current child workflow, continuation, parking, resume, recorder, widget, and presentation
389
+ behavior.
390
+
391
+ Add a real Pi end-to-end test in `test/e2e/workflow.e2e.test.ts` with the existing mock provider:
392
+
393
+ 1. The model calls `workflow start` for a valid file workflow.
394
+ 2. The tool returns a durable queued run ID.
395
+ 3. The test changes or removes the workflow source before the initiating turn settles.
396
+ 4. Activation records `failed`.
397
+ 5. Pi sends one follow-up model turn with the safe error.
398
+ 6. The model corrects the request and calls `workflow start` again.
399
+ 7. The new run starts and reaches its first workflow step.
400
+ 8. The first failed run remains inspectable by ID.
401
+
402
+ The test must use the packaged extension and real Pi lifecycle events. It must not call a real model
403
+ or external service.
404
+
405
+ ## Acceptance criteria
406
+
407
+ - The start tool never reports success without a committed queued record and final run ID.
408
+ - The model can correct synchronous start errors in the same turn.
409
+ - A deferred startup failure always becomes durable before notification.
410
+ - One launch-failure intent starts one new model turn.
411
+ - The model can correct the cause and start a new run.
412
+ - Failed and cancelled launches release the session reservation.
413
+ - No two runs activate for one reservation.
414
+ - Reload, restart, compaction, and repeated settlement do not lose or duplicate a launch.
415
+ - Status and cancellation work before a run bundle exists.
416
+ - Private input and error details do not leak.
417
+ - No Pi change, new service, new database, v2 schema, compatibility path, or migration exists.
418
+ - The old `pendingToolLaunch` path is gone.
419
+
420
+ ## Verification
421
+
422
+ Run the canonical repository gates:
423
+
424
+ ```bash
425
+ npm run check
426
+ npm run test:e2e
427
+ npx slophammer-ts@latest dry .
428
+ npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
429
+ git diff --check
430
+ ```
431
+
432
+ Run pi-reviewer against the base branch and fix all valid P0 and P1 findings before release work.
433
+
434
+ Package publication and OnurPi adoption are separate tasks. Do not edit an installed `node_modules`
435
+ copy as the implementation source.
436
+
437
+ ## Non-goals
438
+
439
+ - Do not change Pi or propose a new Pi API.
440
+ - Do not add a service, daemon, remote queue, telemetry endpoint, or second database.
441
+ - Do not preserve old alpha controller-store layouts.
442
+ - Do not add a migration or v2 schema.
443
+ - Do not add blind automatic workflow retries.
444
+ - Do not change built-in workflow behavior except for test fixtures needed to verify startup.
445
+ - Do not publish or adopt a package as part of this documentation change.
@@ -1,10 +1,10 @@
1
1
  # Controller runtime specification
2
2
 
3
- Pi Workflows runs finite TypeScript graphs. A graph starts with an input, follows explicit edges, and ends with a result or checkpoint. This works well for one bounded task.
3
+ pi-workflows runs finite TypeScript graphs. A graph starts with an input, follows explicit edges, and ends with a result or checkpoint. This works well for one bounded task.
4
4
 
5
5
  Long-running automation has a different job. It must keep comparing a requested state with the current state of another system. Events can arrive more than once, processes can stop between an external request and its local receipt, and the external state can change while work is running.
6
6
 
7
- This specification adds a Kubernetes-style controller runtime to Pi Workflows. The controller runtime sits beside the graph engine. Controllers manage durable resources, while workflows remain finite jobs that a controller can start and observe.
7
+ This specification adds a Kubernetes-style controller runtime to pi-workflows. The controller runtime sits beside the graph engine. Controllers manage durable resources, while workflows remain finite jobs that a controller can start and observe.
8
8
 
9
9
  The design follows the Kubernetes [controller pattern](https://kubernetes.io/docs/concepts/architecture/controller/), its [`spec` and `status` split](https://kubernetes.io/docs/concepts/overview/working-with-objects/), and the [idempotent reconciliation guidance](https://book.kubebuilder.io/reference/good-practices).
10
10