@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
@@ -0,0 +1,475 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ export const STATE_APPLICATION_ID = 0x50495746;
4
+ export const STATE_SCHEMA_NAME = "pi-workflows-state";
5
+ export const STATE_SCHEMA_VERSION = 1;
6
+ export const STATE_APP_VERSION = "0.12.1";
7
+
8
+ export const STATE_SCHEMA_SQL = String.raw`
9
+ CREATE TABLE schema_meta (
10
+ id INTEGER PRIMARY KEY CHECK (id = 1),
11
+ schema_name TEXT NOT NULL CHECK (schema_name = 'pi-workflows-state'),
12
+ schema_version INTEGER NOT NULL CHECK (schema_version = 1),
13
+ schema_digest BLOB NOT NULL CHECK (length(schema_digest) = 32),
14
+ app_version TEXT NOT NULL,
15
+ created_at INTEGER NOT NULL,
16
+ updated_at INTEGER NOT NULL
17
+ ) STRICT;
18
+
19
+ CREATE TABLE projects (
20
+ project_id TEXT PRIMARY KEY,
21
+ canonical_path TEXT NOT NULL UNIQUE,
22
+ created_at INTEGER NOT NULL
23
+ ) STRICT;
24
+
25
+ CREATE TABLE blobs (
26
+ blob_hash BLOB PRIMARY KEY CHECK (length(blob_hash) = 32),
27
+ media_type TEXT NOT NULL,
28
+ byte_length INTEGER NOT NULL CHECK (byte_length >= 0),
29
+ content BLOB NOT NULL,
30
+ created_at INTEGER NOT NULL,
31
+ CHECK (byte_length = length(content))
32
+ ) STRICT;
33
+
34
+ CREATE TABLE resources (
35
+ resource_id TEXT PRIMARY KEY,
36
+ resource_type TEXT NOT NULL CHECK (resource_type IN (
37
+ 'run', 'session', 'decision', 'controller', 'effect', 'channel', 'notification', 'turn_intent'
38
+ )),
39
+ aggregate_key TEXT NOT NULL,
40
+ revision INTEGER NOT NULL DEFAULT 0 CHECK (revision >= 0),
41
+ created_at INTEGER NOT NULL,
42
+ updated_at INTEGER NOT NULL,
43
+ UNIQUE (resource_type, aggregate_key)
44
+ ) STRICT;
45
+
46
+ CREATE TABLE leases (
47
+ resource_id TEXT PRIMARY KEY REFERENCES resources(resource_id) ON DELETE CASCADE,
48
+ generation INTEGER NOT NULL DEFAULT 0 CHECK (generation >= 0),
49
+ owner_type TEXT CHECK (owner_type IN ('session', 'host', 'controller', 'channel', 'system')),
50
+ owner_id TEXT,
51
+ token_hash BLOB CHECK (token_hash IS NULL OR length(token_hash) = 32),
52
+ acquired_at INTEGER,
53
+ heartbeat_at INTEGER,
54
+ expires_at INTEGER,
55
+ CHECK (
56
+ (owner_type IS NULL AND owner_id IS NULL AND token_hash IS NULL AND acquired_at IS NULL AND heartbeat_at IS NULL AND expires_at IS NULL)
57
+ OR
58
+ (owner_type IS NOT NULL AND owner_id IS NOT NULL AND token_hash IS NOT NULL AND acquired_at IS NOT NULL AND heartbeat_at IS NOT NULL AND expires_at IS NOT NULL)
59
+ )
60
+ ) STRICT;
61
+
62
+ CREATE INDEX leases_expires_idx ON leases(expires_at) WHERE expires_at IS NOT NULL;
63
+ CREATE INDEX leases_owner_idx ON leases(owner_type, owner_id) WHERE owner_type IS NOT NULL;
64
+
65
+ CREATE TABLE events (
66
+ event_seq INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ event_id TEXT NOT NULL UNIQUE,
68
+ resource_id TEXT NOT NULL REFERENCES resources(resource_id),
69
+ resource_revision INTEGER NOT NULL CHECK (resource_revision > 0),
70
+ event_type TEXT NOT NULL,
71
+ actor_type TEXT NOT NULL CHECK (actor_type IN (
72
+ 'session', 'host', 'controller', 'channel', 'human', 'policy', 'control', 'system'
73
+ )),
74
+ actor_id TEXT,
75
+ lease_generation INTEGER CHECK (lease_generation IS NULL OR lease_generation > 0),
76
+ payload_hash BLOB REFERENCES blobs(blob_hash),
77
+ recorded_at INTEGER NOT NULL,
78
+ UNIQUE (resource_id, resource_revision)
79
+ ) STRICT;
80
+
81
+ CREATE INDEX events_resource_idx ON events(resource_id, event_seq);
82
+
83
+ CREATE TABLE workflow_definitions (
84
+ definition_digest BLOB PRIMARY KEY CHECK (length(definition_digest) = 32),
85
+ workflow_name TEXT NOT NULL,
86
+ definition_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
87
+ created_at INTEGER NOT NULL
88
+ ) STRICT;
89
+
90
+ CREATE TABLE runs (
91
+ run_id TEXT PRIMARY KEY,
92
+ resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id) ON DELETE CASCADE,
93
+ project_id TEXT REFERENCES projects(project_id),
94
+ parent_run_id TEXT REFERENCES runs(run_id),
95
+ definition_digest BLOB NOT NULL REFERENCES workflow_definitions(definition_digest),
96
+ workflow_ref TEXT NOT NULL,
97
+ workflow_source_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
98
+ launch_options_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
99
+ source_type TEXT NOT NULL CHECK (source_type IN ('builtin', 'file')),
100
+ source_ref TEXT NOT NULL,
101
+ source_revision TEXT NOT NULL,
102
+ title TEXT,
103
+ status TEXT NOT NULL CHECK (status IN (
104
+ 'queued', 'running', 'waiting', 'completed', 'failed', 'timed_out', 'cancelled'
105
+ )),
106
+ paused INTEGER NOT NULL DEFAULT 0 CHECK (paused IN (0, 1)),
107
+ status_detail TEXT,
108
+ input_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
109
+ output_hash BLOB REFERENCES blobs(blob_hash),
110
+ error_hash BLOB REFERENCES blobs(blob_hash),
111
+ created_at INTEGER NOT NULL,
112
+ updated_at INTEGER NOT NULL,
113
+ finished_at INTEGER,
114
+ CHECK ((status IN ('waiting', 'completed', 'failed', 'timed_out', 'cancelled')) = (finished_at IS NOT NULL))
115
+ ) STRICT;
116
+
117
+ CREATE INDEX runs_project_idx ON runs(project_id, created_at DESC);
118
+ CREATE INDEX runs_status_idx ON runs(status, updated_at DESC);
119
+ CREATE INDEX runs_parent_idx ON runs(parent_run_id);
120
+
121
+ CREATE TABLE run_bindings (
122
+ run_id TEXT PRIMARY KEY REFERENCES runs(run_id) ON DELETE CASCADE,
123
+ origin_session_id TEXT NOT NULL,
124
+ execution_mode TEXT NOT NULL CHECK (execution_mode IN ('interactive', 'headless')),
125
+ created_at INTEGER NOT NULL
126
+ ) STRICT;
127
+
128
+ CREATE INDEX run_bindings_session_idx ON run_bindings(origin_session_id, created_at DESC);
129
+
130
+ CREATE TABLE run_queue (
131
+ run_id TEXT PRIMARY KEY REFERENCES runs(run_id) ON DELETE CASCADE,
132
+ status TEXT NOT NULL CHECK (status IN (
133
+ 'queued', 'starting', 'running', 'parked', 'done', 'failed', 'cancelled'
134
+ )),
135
+ available_at INTEGER NOT NULL,
136
+ affinity_runner_id TEXT,
137
+ origin_session_id TEXT NOT NULL,
138
+ consecutive_errors INTEGER NOT NULL DEFAULT 0 CHECK (consecutive_errors >= 0),
139
+ error_code TEXT,
140
+ error_hash BLOB REFERENCES blobs(blob_hash),
141
+ created_at INTEGER NOT NULL,
142
+ updated_at INTEGER NOT NULL,
143
+ started_at INTEGER,
144
+ finished_at INTEGER
145
+ ) STRICT;
146
+
147
+ CREATE INDEX run_queue_claim_idx ON run_queue(status, available_at, created_at);
148
+ CREATE UNIQUE INDEX run_queue_active_session_idx ON run_queue(origin_session_id)
149
+ WHERE status IN ('queued', 'starting', 'running');
150
+
151
+ CREATE TABLE node_attempts (
152
+ attempt_id TEXT PRIMARY KEY,
153
+ run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
154
+ node_id TEXT NOT NULL,
155
+ attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
156
+ node_type TEXT NOT NULL,
157
+ status TEXT NOT NULL CHECK (status IN (
158
+ 'pending', 'running', 'waiting', 'completed', 'failed', 'timed_out', 'cancelled'
159
+ )),
160
+ input_hash BLOB REFERENCES blobs(blob_hash),
161
+ contract_hash BLOB REFERENCES blobs(blob_hash),
162
+ presentation_hash BLOB REFERENCES blobs(blob_hash),
163
+ output_hash BLOB REFERENCES blobs(blob_hash),
164
+ result_hash BLOB REFERENCES blobs(blob_hash),
165
+ error_hash BLOB REFERENCES blobs(blob_hash),
166
+ started_at INTEGER,
167
+ deadline_at INTEGER,
168
+ finished_at INTEGER,
169
+ created_at INTEGER NOT NULL,
170
+ updated_at INTEGER NOT NULL,
171
+ UNIQUE (run_id, node_id, attempt_number)
172
+ ) STRICT;
173
+
174
+ CREATE UNIQUE INDEX node_attempts_active_idx ON node_attempts(run_id)
175
+ WHERE status IN ('pending', 'running', 'waiting');
176
+ CREATE INDEX node_attempts_run_idx ON node_attempts(run_id, created_at);
177
+
178
+ CREATE TABLE workflow_updates (
179
+ update_id TEXT PRIMARY KEY,
180
+ attempt_id TEXT NOT NULL REFERENCES node_attempts(attempt_id) ON DELETE CASCADE,
181
+ update_seq INTEGER NOT NULL CHECK (update_seq > 0),
182
+ update_type TEXT NOT NULL,
183
+ update_key TEXT NOT NULL,
184
+ data_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
185
+ recorded_at INTEGER NOT NULL,
186
+ UNIQUE (attempt_id, update_seq)
187
+ ) STRICT;
188
+
189
+ CREATE INDEX workflow_updates_key_idx ON workflow_updates(attempt_id, update_type, update_key, update_seq DESC);
190
+
191
+ CREATE TABLE session_segments (
192
+ segment_id TEXT PRIMARY KEY,
193
+ run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
194
+ attempt_id TEXT REFERENCES node_attempts(attempt_id),
195
+ capture_key TEXT,
196
+ session_id TEXT NOT NULL,
197
+ resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id),
198
+ binding_hash BLOB REFERENCES blobs(blob_hash),
199
+ status TEXT NOT NULL CHECK (status IN ('recording', 'complete', 'failed')),
200
+ entry_count INTEGER NOT NULL DEFAULT 0 CHECK (entry_count >= 0),
201
+ event_count INTEGER NOT NULL DEFAULT 0 CHECK (event_count >= 0),
202
+ failure_hash BLOB REFERENCES blobs(blob_hash),
203
+ created_at INTEGER NOT NULL,
204
+ finished_at INTEGER
205
+ ) STRICT;
206
+
207
+ CREATE INDEX session_segments_run_idx ON session_segments(run_id, created_at);
208
+
209
+ CREATE TABLE session_entries (
210
+ segment_id TEXT NOT NULL REFERENCES session_segments(segment_id) ON DELETE CASCADE,
211
+ entry_seq INTEGER NOT NULL CHECK (entry_seq > 0),
212
+ entry_id TEXT NOT NULL,
213
+ entry_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
214
+ recorded_at INTEGER NOT NULL,
215
+ PRIMARY KEY (segment_id, entry_seq),
216
+ UNIQUE (segment_id, entry_id)
217
+ ) STRICT;
218
+
219
+ CREATE TABLE session_events (
220
+ segment_id TEXT NOT NULL REFERENCES session_segments(segment_id) ON DELETE CASCADE,
221
+ event_seq INTEGER NOT NULL CHECK (event_seq > 0),
222
+ event_type TEXT NOT NULL,
223
+ node_id TEXT,
224
+ attempt_id TEXT,
225
+ turn_id TEXT,
226
+ message_id TEXT,
227
+ tool_call_id TEXT,
228
+ payload_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
229
+ recorded_at INTEGER NOT NULL,
230
+ PRIMARY KEY (segment_id, event_seq)
231
+ ) STRICT;
232
+
233
+ CREATE TABLE human_decisions (
234
+ decision_id TEXT PRIMARY KEY,
235
+ resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id),
236
+ run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
237
+ attempt_id TEXT NOT NULL REFERENCES node_attempts(attempt_id),
238
+ audience TEXT NOT NULL,
239
+ title TEXT NOT NULL,
240
+ subject_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
241
+ presentation_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
242
+ choices_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
243
+ request_digest BLOB NOT NULL UNIQUE CHECK (length(request_digest) = 32),
244
+ presentation_revision INTEGER NOT NULL CHECK (presentation_revision > 0),
245
+ deadline_at INTEGER,
246
+ default_response_hash BLOB REFERENCES blobs(blob_hash),
247
+ request_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
248
+ created_at INTEGER NOT NULL
249
+ ) STRICT;
250
+
251
+ CREATE INDEX human_decisions_run_idx ON human_decisions(run_id, created_at);
252
+ CREATE INDEX human_decisions_deadline_idx ON human_decisions(deadline_at) WHERE deadline_at IS NOT NULL;
253
+
254
+ CREATE TABLE human_decision_resolutions (
255
+ decision_id TEXT PRIMARY KEY REFERENCES human_decisions(decision_id) ON DELETE CASCADE,
256
+ outcome TEXT NOT NULL CHECK (outcome IN ('accepted', 'cancelled')),
257
+ provenance TEXT NOT NULL CHECK (provenance IN (
258
+ 'human', 'timeout_policy', 'explicit_cancel', 'expired_no_default'
259
+ )),
260
+ response_hash BLOB REFERENCES blobs(blob_hash),
261
+ reason TEXT,
262
+ channel TEXT,
263
+ actor_id TEXT,
264
+ request_digest BLOB NOT NULL CHECK (length(request_digest) = 32),
265
+ resolved_at INTEGER NOT NULL,
266
+ CHECK (
267
+ (outcome = 'accepted' AND response_hash IS NOT NULL AND reason IS NULL)
268
+ OR
269
+ (outcome = 'cancelled' AND response_hash IS NULL AND reason IS NOT NULL)
270
+ )
271
+ ) STRICT;
272
+
273
+ CREATE TABLE human_decision_submissions (
274
+ decision_id TEXT NOT NULL REFERENCES human_decisions(decision_id) ON DELETE CASCADE,
275
+ attempt_id TEXT NOT NULL,
276
+ source TEXT NOT NULL CHECK (source IN ('human', 'policy', 'control', 'channel')),
277
+ actor_id TEXT,
278
+ channel TEXT,
279
+ candidate_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
280
+ outcome TEXT NOT NULL CHECK (outcome IN ('won', 'adopted', 'already_resolved', 'rejected')),
281
+ result_hash BLOB REFERENCES blobs(blob_hash),
282
+ submitted_at INTEGER NOT NULL,
283
+ PRIMARY KEY (decision_id, attempt_id)
284
+ ) STRICT;
285
+
286
+ CREATE TABLE continuations (
287
+ decision_id TEXT PRIMARY KEY REFERENCES human_decisions(decision_id) ON DELETE CASCADE,
288
+ parent_run_id TEXT NOT NULL UNIQUE REFERENCES runs(run_id),
289
+ continuation_run_id TEXT NOT NULL UNIQUE REFERENCES runs(run_id),
290
+ response_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
291
+ created_at INTEGER NOT NULL
292
+ ) STRICT;
293
+
294
+ CREATE TABLE controller_resources (
295
+ controller_resource_id TEXT PRIMARY KEY,
296
+ resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id) ON DELETE CASCADE,
297
+ project_id TEXT REFERENCES projects(project_id),
298
+ controller_name TEXT NOT NULL,
299
+ resource_key TEXT NOT NULL,
300
+ uid TEXT NOT NULL UNIQUE,
301
+ generation INTEGER NOT NULL CHECK (generation > 0),
302
+ spec_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
303
+ status_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
304
+ deletion_requested_at INTEGER,
305
+ created_at INTEGER NOT NULL,
306
+ updated_at INTEGER NOT NULL,
307
+ UNIQUE (project_id, controller_name, resource_key)
308
+ ) STRICT;
309
+
310
+ CREATE INDEX controller_resources_name_idx ON controller_resources(controller_name, resource_key);
311
+
312
+ CREATE TABLE controller_finalizers (
313
+ controller_resource_id TEXT NOT NULL REFERENCES controller_resources(controller_resource_id) ON DELETE CASCADE,
314
+ finalizer TEXT NOT NULL,
315
+ position INTEGER NOT NULL CHECK (position >= 0),
316
+ PRIMARY KEY (controller_resource_id, finalizer),
317
+ UNIQUE (controller_resource_id, position)
318
+ ) STRICT;
319
+
320
+ CREATE TABLE controller_queue (
321
+ controller_resource_id TEXT PRIMARY KEY REFERENCES controller_resources(controller_resource_id) ON DELETE CASCADE,
322
+ available_at INTEGER NOT NULL,
323
+ queue_version INTEGER NOT NULL DEFAULT 1 CHECK (queue_version > 0),
324
+ consecutive_errors INTEGER NOT NULL DEFAULT 0 CHECK (consecutive_errors >= 0),
325
+ last_error_hash BLOB REFERENCES blobs(blob_hash),
326
+ created_at INTEGER NOT NULL,
327
+ updated_at INTEGER NOT NULL
328
+ ) STRICT;
329
+
330
+ CREATE INDEX controller_queue_claim_idx ON controller_queue(available_at, created_at);
331
+
332
+ CREATE TABLE controller_workflows (
333
+ request_id TEXT PRIMARY KEY,
334
+ controller_resource_id TEXT NOT NULL REFERENCES controller_resources(controller_resource_id) ON DELETE CASCADE,
335
+ request_key TEXT NOT NULL,
336
+ workflow_name TEXT NOT NULL,
337
+ input_fingerprint BLOB NOT NULL CHECK (length(input_fingerprint) = 32),
338
+ reserved_run_id TEXT,
339
+ run_id TEXT REFERENCES runs(run_id),
340
+ status TEXT NOT NULL CHECK (status IN (
341
+ 'pending', 'running', 'waiting', 'succeeded', 'failed', 'interrupted'
342
+ )),
343
+ attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
344
+ error_hash BLOB REFERENCES blobs(blob_hash),
345
+ created_at INTEGER NOT NULL,
346
+ updated_at INTEGER NOT NULL,
347
+ UNIQUE (controller_resource_id, request_key)
348
+ ) STRICT;
349
+
350
+ CREATE TABLE effects (
351
+ effect_id TEXT PRIMARY KEY,
352
+ resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id),
353
+ source_resource_id TEXT NOT NULL REFERENCES resources(resource_id),
354
+ source_revision INTEGER NOT NULL CHECK (source_revision > 0),
355
+ effect_type TEXT NOT NULL,
356
+ idempotency_key TEXT NOT NULL,
357
+ payload_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
358
+ owner_scope TEXT NOT NULL CHECK (owner_scope IN ('run', 'controller', 'channel', 'system')),
359
+ status TEXT NOT NULL CHECK (status IN (
360
+ 'pending', 'applying', 'applied', 'rejected', 'ambiguous', 'cancelled'
361
+ )),
362
+ attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
363
+ next_attempt_at INTEGER,
364
+ result_hash BLOB REFERENCES blobs(blob_hash),
365
+ external_ref TEXT,
366
+ error_hash BLOB REFERENCES blobs(blob_hash),
367
+ created_at INTEGER NOT NULL,
368
+ updated_at INTEGER NOT NULL,
369
+ settled_at INTEGER,
370
+ UNIQUE (source_resource_id, effect_type, idempotency_key)
371
+ ) STRICT;
372
+
373
+ CREATE INDEX effects_pending_idx ON effects(status, next_attempt_at, created_at);
374
+
375
+ CREATE TABLE effect_attempts (
376
+ effect_id TEXT NOT NULL REFERENCES effects(effect_id) ON DELETE CASCADE,
377
+ attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
378
+ owner_id TEXT NOT NULL,
379
+ lease_generation INTEGER NOT NULL CHECK (lease_generation > 0),
380
+ started_at INTEGER NOT NULL,
381
+ finished_at INTEGER,
382
+ outcome TEXT CHECK (outcome IN ('applied', 'rejected', 'ambiguous', 'interrupted')),
383
+ result_hash BLOB REFERENCES blobs(blob_hash),
384
+ error_hash BLOB REFERENCES blobs(blob_hash),
385
+ PRIMARY KEY (effect_id, attempt_number)
386
+ ) STRICT;
387
+
388
+ CREATE TABLE notifications (
389
+ notification_id TEXT PRIMARY KEY,
390
+ effect_id TEXT NOT NULL UNIQUE REFERENCES effects(effect_id),
391
+ run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
392
+ attempt_id TEXT NOT NULL REFERENCES node_attempts(attempt_id),
393
+ notification_index INTEGER NOT NULL CHECK (notification_index >= 0),
394
+ target_session_id TEXT NOT NULL,
395
+ notification_type TEXT NOT NULL CHECK (notification_type IN ('progress', 'final')),
396
+ content_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
397
+ created_at INTEGER NOT NULL,
398
+ UNIQUE (run_id, attempt_id, notification_index)
399
+ ) STRICT;
400
+
401
+ CREATE TABLE turn_intents (
402
+ turn_intent_id TEXT PRIMARY KEY,
403
+ resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id),
404
+ effect_id TEXT NOT NULL UNIQUE REFERENCES effects(effect_id),
405
+ source_event_id TEXT NOT NULL UNIQUE,
406
+ run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
407
+ workflow_ref TEXT NOT NULL,
408
+ target_session_id TEXT NOT NULL,
409
+ cause TEXT NOT NULL,
410
+ node_id TEXT,
411
+ attempt_id TEXT,
412
+ resolution_type TEXT,
413
+ resolution_message_id TEXT,
414
+ facts_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
415
+ requested_at INTEGER NOT NULL,
416
+ eligible_at INTEGER,
417
+ resolved_at INTEGER,
418
+ created_at INTEGER NOT NULL
419
+ ) STRICT;
420
+
421
+ CREATE TABLE channels (
422
+ channel_id TEXT PRIMARY KEY,
423
+ resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id),
424
+ adapter_type TEXT NOT NULL,
425
+ profile_key TEXT NOT NULL,
426
+ created_at INTEGER NOT NULL,
427
+ UNIQUE (adapter_type, profile_key)
428
+ ) STRICT;
429
+
430
+ CREATE TABLE channel_cursors (
431
+ channel_id TEXT NOT NULL REFERENCES channels(channel_id) ON DELETE CASCADE,
432
+ cursor_key TEXT NOT NULL,
433
+ cursor_value TEXT NOT NULL,
434
+ updated_at INTEGER NOT NULL,
435
+ PRIMARY KEY (channel_id, cursor_key)
436
+ ) STRICT;
437
+
438
+ CREATE TABLE channel_inbox (
439
+ channel_id TEXT NOT NULL REFERENCES channels(channel_id) ON DELETE CASCADE,
440
+ external_event_id TEXT NOT NULL,
441
+ event_type TEXT NOT NULL CHECK (event_type IN ('callback', 'reply')),
442
+ payload_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
443
+ received_at INTEGER NOT NULL,
444
+ processed_at INTEGER,
445
+ result_hash BLOB REFERENCES blobs(blob_hash),
446
+ PRIMARY KEY (channel_id, external_event_id)
447
+ ) STRICT;
448
+
449
+ CREATE TABLE channel_messages (
450
+ message_id TEXT PRIMARY KEY,
451
+ channel_id TEXT NOT NULL REFERENCES channels(channel_id) ON DELETE CASCADE,
452
+ decision_id TEXT REFERENCES human_decisions(decision_id),
453
+ purpose TEXT NOT NULL CHECK (purpose IN ('delivery', 'settlement')),
454
+ content_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
455
+ external_conversation_ref TEXT,
456
+ external_message_ref TEXT,
457
+ status TEXT NOT NULL CHECK (status IN ('pending', 'confirmed', 'failed', 'ambiguous')),
458
+ created_at INTEGER NOT NULL,
459
+ updated_at INTEGER NOT NULL
460
+ ) STRICT;
461
+
462
+ CREATE INDEX channel_messages_decision_idx ON channel_messages(decision_id, purpose, created_at);
463
+
464
+ CREATE TABLE channel_message_parts (
465
+ message_id TEXT NOT NULL REFERENCES channel_messages(message_id) ON DELETE CASCADE,
466
+ recipient_index INTEGER NOT NULL CHECK (recipient_index >= 0),
467
+ part_index INTEGER NOT NULL CHECK (part_index >= 0),
468
+ content_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
469
+ external_conversation_ref TEXT NOT NULL,
470
+ external_message_ref TEXT NOT NULL,
471
+ PRIMARY KEY (message_id, recipient_index, part_index)
472
+ ) STRICT;
473
+ `;
474
+
475
+ export const STATE_SCHEMA_DIGEST = createHash("sha256").update(STATE_SCHEMA_SQL).digest();