@osolmaz/pi-workflows 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/README.md +56 -31
  2. package/dist/builtins/autodoc.workflow.d.ts +4 -4
  3. package/dist/builtins/autoimplement.workflow.d.ts +797 -142
  4. package/dist/builtins/autoimplement.workflow.js +17 -105
  5. package/dist/builtins/autoimplement.workflow.js.map +1 -1
  6. package/dist/builtins/autoplan.workflow.d.ts +126 -13
  7. package/dist/builtins/autoplan.workflow.js +200 -29
  8. package/dist/builtins/autoplan.workflow.js.map +1 -1
  9. package/dist/builtins/catalog.js +7 -5
  10. package/dist/builtins/catalog.js.map +1 -1
  11. package/dist/builtins/index.d.ts +4 -2
  12. package/dist/builtins/index.js +3 -1
  13. package/dist/builtins/index.js.map +1 -1
  14. package/dist/builtins/monitor.workflow.d.ts +56 -23
  15. package/dist/builtins/monitor.workflow.js +508 -329
  16. package/dist/builtins/monitor.workflow.js.map +1 -1
  17. package/dist/builtins/pi-agent-group.d.ts +72 -0
  18. package/dist/builtins/pi-agent-group.js +1087 -0
  19. package/dist/builtins/pi-agent-group.js.map +1 -0
  20. package/dist/builtins/plain-summary.workflow.d.ts +32 -0
  21. package/dist/builtins/plain-summary.workflow.js +134 -0
  22. package/dist/builtins/plain-summary.workflow.js.map +1 -0
  23. package/dist/builtins/plan-approval.workflow.d.ts +39 -5
  24. package/dist/builtins/plan-approval.workflow.js +92 -14
  25. package/dist/builtins/plan-approval.workflow.js.map +1 -1
  26. package/dist/builtins/plan-change.workflow.d.ts +449 -0
  27. package/dist/builtins/plan-change.workflow.js +256 -0
  28. package/dist/builtins/plan-change.workflow.js.map +1 -0
  29. package/dist/builtins/plan-presentation.js +2 -2
  30. package/dist/builtins/plan-presentation.js.map +1 -1
  31. package/dist/builtins/sanity-check.workflow.d.ts +50 -6
  32. package/dist/builtins/sanity-check.workflow.js +150 -28
  33. package/dist/builtins/sanity-check.workflow.js.map +1 -1
  34. package/dist/controllers/effects.d.ts +3 -2
  35. package/dist/controllers/effects.js +8 -1
  36. package/dist/controllers/effects.js.map +1 -1
  37. package/dist/controllers/index.d.ts +1 -1
  38. package/dist/controllers/index.js +1 -1
  39. package/dist/controllers/index.js.map +1 -1
  40. package/dist/controllers/manager.d.ts +1 -0
  41. package/dist/controllers/manager.js +41 -17
  42. package/dist/controllers/manager.js.map +1 -1
  43. package/dist/controllers/sqlite.d.ts +107 -85
  44. package/dist/controllers/sqlite.js +1611 -1486
  45. package/dist/controllers/sqlite.js.map +1 -1
  46. package/dist/controllers/store.d.ts +9 -8
  47. package/dist/controllers/store.js +1 -31
  48. package/dist/controllers/store.js.map +1 -1
  49. package/dist/controllers/types.d.ts +3 -0
  50. package/dist/controllers/workflow-engine-scheduler.d.ts +1 -1
  51. package/dist/controllers/workflow-engine-scheduler.js +3 -5
  52. package/dist/controllers/workflow-engine-scheduler.js.map +1 -1
  53. package/dist/controllers/workflows.d.ts +2 -2
  54. package/dist/controllers/workflows.js +11 -10
  55. package/dist/controllers/workflows.js.map +1 -1
  56. package/dist/extension/controller-host.js +2 -2
  57. package/dist/extension/controller-host.js.map +1 -1
  58. package/dist/extension/decision-channels.d.ts +4 -2
  59. package/dist/extension/decision-channels.js +333 -146
  60. package/dist/extension/decision-channels.js.map +1 -1
  61. package/dist/extension/executor.d.ts +9 -2
  62. package/dist/extension/executor.js +89 -2
  63. package/dist/extension/executor.js.map +1 -1
  64. package/dist/extension/herdr-viewer.d.ts +0 -1
  65. package/dist/extension/herdr-viewer.js +0 -4
  66. package/dist/extension/herdr-viewer.js.map +1 -1
  67. package/dist/extension/index.js +209 -127
  68. package/dist/extension/index.js.map +1 -1
  69. package/dist/extension/recorder.d.ts +3 -10
  70. package/dist/extension/recorder.js +13 -22
  71. package/dist/extension/recorder.js.map +1 -1
  72. package/dist/extension/session-events.d.ts +2 -2
  73. package/dist/extension/step-message.d.ts +7 -2
  74. package/dist/extension/step-message.js +94 -2
  75. package/dist/extension/step-message.js.map +1 -1
  76. package/dist/extension/widget.js +29 -3
  77. package/dist/extension/widget.js.map +1 -1
  78. package/dist/host/rpc-executor.d.ts +3 -0
  79. package/dist/host/rpc-executor.js +2 -0
  80. package/dist/host/rpc-executor.js.map +1 -1
  81. package/dist/host/runner.d.ts +3 -6
  82. package/dist/host/runner.js +83 -32
  83. package/dist/host/runner.js.map +1 -1
  84. package/dist/render/graph-render.js +15 -10
  85. package/dist/render/graph-render.js.map +1 -1
  86. package/dist/state/database.d.ts +35 -0
  87. package/dist/state/database.js +287 -0
  88. package/dist/state/database.js.map +1 -0
  89. package/dist/state/index.d.ts +4 -0
  90. package/dist/state/index.js +5 -0
  91. package/dist/state/index.js.map +1 -0
  92. package/dist/state/json.d.ts +6 -0
  93. package/dist/state/json.js +38 -0
  94. package/dist/state/json.js.map +1 -0
  95. package/dist/state/mutation.d.ts +57 -0
  96. package/dist/state/mutation.js +255 -0
  97. package/dist/state/mutation.js.map +1 -0
  98. package/dist/state/schema.d.ts +6 -0
  99. package/dist/state/schema.js +473 -0
  100. package/dist/state/schema.js.map +1 -0
  101. package/dist/viewer/cli.d.ts +2 -2
  102. package/dist/viewer/cli.js +142 -122
  103. package/dist/viewer/cli.js.map +1 -1
  104. package/dist/viewer/render.d.ts +4 -4
  105. package/dist/viewer/render.js +9 -23
  106. package/dist/viewer/render.js.map +1 -1
  107. package/dist/viewer/session-reducer.d.ts +1 -1
  108. package/dist/viewer/session-reducer.js +1 -1
  109. package/dist/viewer/tui.d.ts +3 -3
  110. package/dist/viewer/tui.js +15 -13
  111. package/dist/viewer/tui.js.map +1 -1
  112. package/dist/viewer/watch.d.ts +2 -5
  113. package/dist/viewer/watch.js +13 -13
  114. package/dist/viewer/watch.js.map +1 -1
  115. package/dist/workflows/catalog.js +7 -2
  116. package/dist/workflows/catalog.js.map +1 -1
  117. package/dist/workflows/composition.js +20 -2
  118. package/dist/workflows/composition.js.map +1 -1
  119. package/dist/workflows/decision-presentation.d.ts +1 -1
  120. package/dist/workflows/decision-presentation.js +51 -38
  121. package/dist/workflows/decision-presentation.js.map +1 -1
  122. package/dist/workflows/definition.d.ts +6 -2
  123. package/dist/workflows/definition.js +17 -0
  124. package/dist/workflows/definition.js.map +1 -1
  125. package/dist/workflows/engine.d.ts +7 -7
  126. package/dist/workflows/engine.js +196 -115
  127. package/dist/workflows/engine.js.map +1 -1
  128. package/dist/workflows/errors.d.ts +16 -3
  129. package/dist/workflows/errors.js +18 -3
  130. package/dist/workflows/errors.js.map +1 -1
  131. package/dist/workflows/human-decision.d.ts +45 -8
  132. package/dist/workflows/human-decision.js +641 -274
  133. package/dist/workflows/human-decision.js.map +1 -1
  134. package/dist/workflows/index.d.ts +5 -6
  135. package/dist/workflows/index.js +4 -5
  136. package/dist/workflows/index.js.map +1 -1
  137. package/dist/workflows/progress.d.ts +1 -0
  138. package/dist/workflows/progress.js +15 -3
  139. package/dist/workflows/progress.js.map +1 -1
  140. package/dist/workflows/schema.js +27 -1
  141. package/dist/workflows/schema.js.map +1 -1
  142. package/dist/workflows/store.d.ts +83 -103
  143. package/dist/workflows/store.js +907 -951
  144. package/dist/workflows/store.js.map +1 -1
  145. package/dist/workflows/types.d.ts +88 -126
  146. package/docs/CONTROLLERS.md +10 -8
  147. package/docs/DEFERRED_TURNS.md +2 -2
  148. package/docs/DESIGN_PHILOSOPHY.md +4 -2
  149. package/docs/HUMAN_DECISIONS.md +36 -47
  150. package/docs/HUMAN_DECISION_PRESENTATIONS.md +14 -24
  151. package/docs/MONITOR.md +179 -237
  152. package/docs/SQLITE_STATE.md +219 -0
  153. package/docs/WORKFLOW_COMPOSITION.md +27 -26
  154. package/docs/WORKFLOW_STEP_MESSAGES.md +20 -18
  155. package/docs/WORKFLOW_UPDATES.md +10 -9
  156. package/docs/development.md +9 -9
  157. package/docs/live-replay-protocol.md +28 -37
  158. package/docs/plans/2026-08-16-workflow-updates-plan.md +1 -1
  159. package/docs/plans/2026-08-19-human-decision-gates-plan.md +1 -1
  160. package/docs/plans/2026-08-21-autoimplement-timeout-fallback-plan.md +1 -1
  161. package/docs/plans/2026-08-21-plan-change-approval-policy-plan.md +322 -0
  162. package/docs/plans/2026-08-21-sanity-check-plan.md +217 -95
  163. package/docs/plans/2026-08-22-goal-finishing-monitor-plan.md +200 -0
  164. package/docs/plans/2026-08-23-assistant-agent-completion-plan.md +701 -0
  165. package/docs/plans/2026-08-23-sqlite-state-plan.md +970 -0
  166. package/docs/plans/replayable-run-bundles-implementation-plan.md +2 -2
  167. package/docs/plans/session-event-replay-implementation-plan.md +1 -1
  168. package/docs/plans/tui-viewer-implementation-plan.md +1 -1
  169. package/docs/session-event-journal.md +63 -434
  170. package/docs/tui-viewer.md +13 -15
  171. package/docs/workflows.md +127 -53
  172. package/examples/workflows/approved-plan.workflow.ts +19 -46
  173. package/examples/workflows/plain-summary.workflow.ts +1 -0
  174. package/herdr-plugin.toml +1 -1
  175. package/package.json +7 -7
  176. package/plugins/herdr/viewer.mjs +1 -11
  177. package/schemas/human-decision-accepted-v1.schema.json +15 -3
  178. package/schemas/human-decision-continuation-v1.schema.json +10 -1
  179. package/schemas/human-decision-delivery-v1.schema.json +8 -0
  180. package/schemas/human-decision-receipt-v1.schema.json +8 -0
  181. package/schemas/human-decision-request-v1.schema.json +24 -4
  182. package/skills/autoimplement/SKILL.md +27 -0
  183. package/skills/autoplan/SKILL.md +5 -4
  184. package/skills/monitor/SKILL.md +91 -135
  185. package/skills/pi-workflows/SKILL.md +9 -8
  186. package/skills/sanity-check/SKILL.md +44 -0
  187. package/src/builtins/autoimplement.workflow.ts +19 -118
  188. package/src/builtins/autoplan.workflow.ts +290 -40
  189. package/src/builtins/catalog.ts +7 -5
  190. package/src/builtins/index.ts +18 -1
  191. package/src/builtins/monitor.workflow.ts +673 -382
  192. package/src/builtins/pi-agent-group.ts +1407 -0
  193. package/src/builtins/plain-summary.workflow.ts +185 -0
  194. package/src/builtins/plan-approval.workflow.ts +157 -24
  195. package/src/builtins/plan-change.workflow.ts +321 -0
  196. package/src/builtins/plan-presentation.ts +2 -2
  197. package/src/builtins/sanity-check.workflow.ts +248 -48
  198. package/src/controllers/effects.ts +7 -0
  199. package/src/controllers/index.ts +0 -6
  200. package/src/controllers/manager.ts +72 -32
  201. package/src/controllers/sqlite.ts +2420 -1948
  202. package/src/controllers/store.ts +17 -38
  203. package/src/controllers/types.ts +3 -0
  204. package/src/controllers/workflow-engine-scheduler.ts +4 -8
  205. package/src/controllers/workflows.ts +45 -21
  206. package/src/extension/controller-host.ts +1 -2
  207. package/src/extension/decision-channels.ts +456 -203
  208. package/src/extension/executor.ts +105 -2
  209. package/src/extension/herdr-viewer.ts +0 -5
  210. package/src/extension/index.ts +251 -151
  211. package/src/extension/recorder.ts +13 -22
  212. package/src/extension/session-events.ts +2 -2
  213. package/src/extension/step-message.ts +106 -4
  214. package/src/extension/widget.ts +32 -5
  215. package/src/host/rpc-executor.ts +4 -0
  216. package/src/host/runner.ts +93 -41
  217. package/src/render/graph-render.ts +12 -6
  218. package/src/state/database.ts +375 -0
  219. package/src/state/index.ts +29 -0
  220. package/src/state/json.ts +42 -0
  221. package/src/state/mutation.ts +435 -0
  222. package/src/state/schema.ts +475 -0
  223. package/src/viewer/cli.ts +151 -144
  224. package/src/viewer/render.ts +19 -30
  225. package/src/viewer/session-reducer.ts +1 -1
  226. package/src/viewer/tui.ts +18 -17
  227. package/src/viewer/watch.ts +13 -17
  228. package/src/workflows/catalog.ts +7 -2
  229. package/src/workflows/composition.ts +21 -3
  230. package/src/workflows/decision-presentation.ts +56 -43
  231. package/src/workflows/definition.ts +36 -3
  232. package/src/workflows/engine.ts +228 -130
  233. package/src/workflows/errors.ts +27 -3
  234. package/src/workflows/human-decision.ts +921 -349
  235. package/src/workflows/index.ts +20 -30
  236. package/src/workflows/progress.ts +18 -3
  237. package/src/workflows/schema.ts +36 -1
  238. package/src/workflows/store.ts +1300 -1163
  239. package/src/workflows/types.ts +100 -137
  240. package/dist/builtins/sanity-check-session.d.ts +0 -17
  241. package/dist/builtins/sanity-check-session.js +0 -168
  242. package/dist/builtins/sanity-check-session.js.map +0 -1
  243. package/dist/workflows/artifacts.d.ts +0 -40
  244. package/dist/workflows/artifacts.js +0 -155
  245. package/dist/workflows/artifacts.js.map +0 -1
  246. package/dist/workflows/migrate-sources.d.ts +0 -42
  247. package/dist/workflows/migrate-sources.js +0 -133
  248. package/dist/workflows/migrate-sources.js.map +0 -1
  249. package/docs/run-bundles.md +0 -481
  250. package/schemas/human-decision-accepted-v2.schema.json +0 -50
  251. package/schemas/human-decision-delivery-v2.schema.json +0 -36
  252. package/schemas/human-decision-receipt-v2.schema.json +0 -39
  253. package/schemas/human-decision-request-v2.schema.json +0 -69
  254. package/schemas/human-decision-resolution-v2.schema.json +0 -27
  255. package/src/builtins/sanity-check-session.ts +0 -205
  256. package/src/workflows/artifacts.ts +0 -188
  257. package/src/workflows/migrate-sources.ts +0 -178
@@ -1,18 +1,18 @@
1
1
  # Live replay protocol
2
2
 
3
- The Rust viewer (`tui/`) can watch runs in two ways: by reading run bundles
3
+ The Rust viewer (`tui/`) can watch runs in two ways: by reading SQLite runs
4
4
  directly from the filesystem (the default, in-process) or by connecting to a
5
5
  `piw serve` WebSocket server. Both paths produce the same semantic state; the
6
6
  protocol below is the network form of that state. Protocol id:
7
7
  `pi-workflows.replay.v1`.
8
8
 
9
- The server is a reader like any other: it only consumes run bundles (see
10
- [run-bundles.md](run-bundles.md)) and never writes them. The protocol has no
9
+ The server is a reader like any other: it only consumes SQLite runs (see
10
+ [SQLITE_STATE.md](SQLITE_STATE.md)) and never writes them. The protocol has no
11
11
  authentication, so the server only accepts loopback bind addresses and refuses
12
- to start on anything else; bundles contain private data, and remote viewing
12
+ to start on anything else; workflow state contains private data, and remote viewing
13
13
  goes through an SSH tunnel. Handshakes that
14
14
  carry an `Origin` header are rejected: browsers always send one, and a web
15
- page must not be able to read bundles by opening a WebSocket to localhost.
15
+ page must not be able to read workflow state by opening a WebSocket to localhost.
16
16
 
17
17
  ## Transport and framing
18
18
 
@@ -49,18 +49,15 @@ run:
49
49
  }
50
50
  ```
51
51
 
52
- - `manifest`, `workflow`, `state`, `events`, and every `session` field are the
53
- bundle documents verbatim. `workflow` is the definition snapshot,
54
- top-level `events` are parsed workflow trace lines, `session.entries` are
55
- settled Pi entries, `session.events` are normalized temporal events, and
56
- `session.capture` is capture integrity. `session.eventsMalformed` and
57
- `session.eventsTornTail` are derived transport diagnostics from the live
58
- tailer, not bundle documents. `session` is `null` until a binding exists.
59
- - `live` is true while the run status is non-terminal and the bundle is still
60
- growing. `possiblyInterrupted` is true when the status is `running` but the
61
- bundle has not changed for 60 seconds.
62
- - Artifact references inside the view stay references; contents are fetched
63
- on demand.
52
+ - `manifest`, `workflow`, `state`, `events`, and every `session` field are
53
+ semantic projections from SQLite. `workflow` is the definition snapshot,
54
+ top-level `events` are workflow events, `session.entries` are settled Pi
55
+ entries, `session.events` are normalized temporal events, and
56
+ `session.capture` is capture integrity. `session` is `null` until a binding
57
+ exists.
58
+ - `live` is true while the run status is non-terminal. `possiblyInterrupted`
59
+ is a reader-side diagnostic based on current ownership and update time.
60
+ - Values are resolved from content-addressed SQLite blobs.
64
61
 
65
62
  Because the full trace and session history are part of the view, replay
66
63
  scrubbing is a pure client-side operation; rewinding never requires the
@@ -106,7 +103,7 @@ Client to server:
106
103
  | `watch_runs` | — | subscribe to the run listing |
107
104
  | `watch_run` | `runId` | subscribe to one run's view |
108
105
  | `unwatch_run` | `runId` | end a run subscription |
109
- | `fetch_artifact` | `runId`, `path` | request artifact contents |
106
+ | `fetch_artifact` | `runId`, `path` | unsupported; returns `error` |
110
107
 
111
108
  Server to client:
112
109
 
@@ -116,13 +113,11 @@ Server to client:
116
113
  | `runs` | `runs` | full run listing (summaries), re-sent on change |
117
114
  | `run_snapshot` | `runId`, `revision`, `view` | full view after subscribe |
118
115
  | `run_patch` | `runId`, `revision`, `patch` | incremental view update |
119
- | `artifact` | `runId`, `path`, `content` | artifact contents (UTF-8) |
116
+ | `artifact` | `runId`, `path`, `content` | reserved; not sent by SQLite-backed servers |
120
117
  | `error` | `message`, `runId?` | request failed |
121
118
 
122
- Artifact requests are answered only from files below the artifact directory
123
- declared by `manifest.paths.artifacts`. Paths outside that directory and
124
- symlinks whose canonical targets leave it are refused. Responses are capped at
125
- 4 MiB of actual file size; anything else produces an `error`.
119
+ SQLite-backed views contain resolved values. A `fetch_artifact` request returns
120
+ an `error` because there is no artifact directory.
126
121
 
127
122
  Run listing summaries are the manifest plus `live` and
128
123
  `possiblyInterrupted`:
@@ -136,20 +131,16 @@ run views use patches.
136
131
 
137
132
  ## Reconnection
138
133
 
139
- The native client treats the run listing, selected run, and pending artifact
140
- reads as desired state rather than one-shot commands. After a connection closes,
134
+ The native client treats the run listing and selected run as desired state rather
135
+ than one-shot commands. After a connection closes,
141
136
  it keeps the cached run visible with a stale/reconnecting label, retries with
142
137
  bounded backoff, sends `watch_runs` after the next valid `hello`, and restores
143
138
  the current `watch_run`. A reconnect receives a fresh snapshot before later
144
- patches. Pending artifact reads are resubmitted once per connection.
145
-
146
- ## Filesystem semantics behind the protocol
147
-
148
- The server watches the runs directory (inotify with polling fallback) and
149
- tails `trace.ndjson`, `session/entries.ndjson`, and `session/events.ndjson`
150
- incrementally. Torn final NDJSON lines are buffered until complete. The server
151
- also re-reads atomic `session/capture.json` changes. `state.json` and
152
- `manifest.json` are
153
- re-read on change; a `state.json` whose `traceSeq` is older than the last
154
- tailed trace event is stale and is replaced when the writer catches up. After
155
- a terminal status, watching stops.
139
+ patches.
140
+
141
+ ## SQLite semantics behind the protocol
142
+
143
+ The server polls `state.sqlite` through a query-only connection. Each refresh
144
+ reads a committed run projection, immutable events, session rows, and blob
145
+ values. A transaction is either fully visible or not visible, so a client never
146
+ observes half of a state transition.
@@ -355,7 +355,7 @@ Update:
355
355
 
356
356
  - `README.md`
357
357
  - `docs/workflows.md`
358
- - `docs/run-bundles.md`
358
+ - `docs/SQLITE_STATE.md`
359
359
  - `docs/development.md`
360
360
  - `docs/WORKFLOW_UPDATES.md`
361
361
  - `docs/WORKFLOW_STEP_MESSAGES.md`
@@ -68,7 +68,7 @@ Pi and Telegram implement one channel interface. Workflows address a named audie
68
68
  ### Documentation and display
69
69
 
70
70
  - Add the authoring API to `docs/workflows.md`.
71
- - Add human decision state to `docs/run-bundles.md`.
71
+ - Add human decision state to `docs/SQLITE_STATE.md`.
72
72
  - Add channel setup and recovery instructions.
73
73
  - Add a custom gate example and a composed plan approval example.
74
74
  - Show pending and accepted choices in TypeScript and Rust viewers.
@@ -153,7 +153,7 @@ A repeated node performs only missing work. It must not create a duplicate commi
153
153
  7. Route supported `timed_out` outcomes to the fallback. Preserve success, failure, and cancellation behavior.
154
154
  8. Update consequential-node prompts so repeated attempts inspect state and perform only missing work.
155
155
  9. Increment the built-in Autoimplement revision from 5 to 6 in `src/builtins/catalog.ts`.
156
- 10. Update `docs/workflows.md` and `docs/run-bundles.md` when implementation ships so public documentation matches the code.
156
+ 10. Update `docs/workflows.md` and `docs/SQLITE_STATE.md` when implementation ships so public documentation matches the code.
157
157
 
158
158
  ## Alpha cutover
159
159
 
@@ -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/SQLITE_STATE.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.